diff --git a/scripts/presets/keyconfig/keymap_data/blender_default.py b/scripts/presets/keyconfig/keymap_data/blender_default.py index 8382f686c5b..c6537818f8e 100644 --- a/scripts/presets/keyconfig/keymap_data/blender_default.py +++ b/scripts/presets/keyconfig/keymap_data/blender_default.py @@ -5482,220 +5482,228 @@ def km_lattice(params): op_menu("VIEW3D_MT_hook", {"type": 'H', "value": 'PRESS', "ctrl": True}), *_template_items_proportional_editing( params, connected=False, toggle_data_path='tool_settings.use_proportional_edit'), *_template_items_context_menu("VIEW3D_MT_edit_lattice_context_menu", params.context_menu_event), ]) return keymap # Particle edit mode. def km_particle(params): items = [] keymap = ( "Particle", {"space_type": 'EMPTY', "region_type": 'WINDOW'}, {"items": items}, ) items.extend([ *_template_items_select_actions(params, "particle.select_all"), ("particle.select_more", {"type": 'NUMPAD_PLUS', "value": 'PRESS', "ctrl": True, "repeat": True}, None), ("particle.select_less", {"type": 'NUMPAD_MINUS', "value": 'PRESS', "ctrl": True, "repeat": True}, None), ("particle.select_linked_pick", {"type": 'L', "value": 'PRESS'}, {"properties": [("deselect", False)]}), ("particle.select_linked_pick", {"type": 'L', "value": 'PRESS', "shift": True}, {"properties": [("deselect", True)]}), ("particle.select_linked", {"type": 'L', "value": 'PRESS', "ctrl": True}, None), ("particle.delete", {"type": 'X', "value": 'PRESS'}, None), ("particle.delete", {"type": 'DEL', "value": 'PRESS'}, None), *_template_items_hide_reveal_actions("particle.hide", "particle.reveal"), ("particle.brush_edit", {"type": 'LEFTMOUSE', "value": 'PRESS'}, None), ("particle.brush_edit", {"type": 'LEFTMOUSE', "value": 'PRESS', "shift": True}, None), ("wm.radial_control", {"type": 'F', "value": 'PRESS'}, {"properties": [("data_path_primary", 'tool_settings.particle_edit.brush.size')]}), ("wm.radial_control", {"type": 'F', "value": 'PRESS', "shift": True}, {"properties": [("data_path_primary", 'tool_settings.particle_edit.brush.strength')]}), ("particle.weight_set", {"type": 'K', "value": 'PRESS', "shift": True}, None), *( (("wm.context_set_enum", {"type": NUMBERS_1[i], "value": 'PRESS'}, {"properties": [("data_path", "tool_settings.particle_edit.select_mode"), ("value", value)]}) for i, value in enumerate(('PATH', 'POINT', 'TIP')) ) ), *_template_items_proportional_editing( params, connected=False, toggle_data_path='tool_settings.use_proportional_edit'), *_template_items_context_menu("VIEW3D_MT_particle_context_menu", params.context_menu_event), ]) return keymap # Text edit mode. def km_font(params): items = [] keymap = ( "Font", {"space_type": 'EMPTY', "region_type": 'WINDOW'}, {"items": items}, ) items.extend([ ("font.style_toggle", {"type": 'B', "value": 'PRESS', "ctrl": True}, {"properties": [("style", 'BOLD')]}), ("font.style_toggle", {"type": 'I', "value": 'PRESS', "ctrl": True}, {"properties": [("style", 'ITALIC')]}), ("font.style_toggle", {"type": 'U', "value": 'PRESS', "ctrl": True}, {"properties": [("style", 'UNDERLINE')]}), ("font.style_toggle", {"type": 'P', "value": 'PRESS', "ctrl": True}, {"properties": [("style", 'SMALL_CAPS')]}), ("font.delete", {"type": 'DEL', "value": 'PRESS', "repeat": True}, {"properties": [("type", 'NEXT_OR_SELECTION')]}), ("font.delete", {"type": 'DEL', "value": 'PRESS', "ctrl": True, "repeat": True}, {"properties": [("type", 'NEXT_WORD')]}), ("font.delete", {"type": 'BACK_SPACE', "value": 'PRESS', "repeat": True}, {"properties": [("type", 'PREVIOUS_OR_SELECTION')]}), ("font.delete", {"type": 'BACK_SPACE', "value": 'PRESS', "shift": True, "repeat": True}, {"properties": [("type", 'PREVIOUS_OR_SELECTION')]}), ("font.delete", {"type": 'BACK_SPACE', "value": 'PRESS', "ctrl": True, "repeat": True}, {"properties": [("type", 'PREVIOUS_WORD')]}), ("font.move", {"type": 'HOME', "value": 'PRESS'}, {"properties": [("type", 'LINE_BEGIN')]}), ("font.move", {"type": 'END', "value": 'PRESS'}, {"properties": [("type", 'LINE_END')]}), ("font.move", {"type": 'LEFT_ARROW', "value": 'PRESS', "repeat": True}, {"properties": [("type", 'PREVIOUS_CHARACTER')]}), ("font.move", {"type": 'RIGHT_ARROW', "value": 'PRESS', "repeat": True}, {"properties": [("type", 'NEXT_CHARACTER')]}), ("font.move", {"type": 'LEFT_ARROW', "value": 'PRESS', "ctrl": True, "repeat": True}, {"properties": [("type", 'PREVIOUS_WORD')]}), ("font.move", {"type": 'RIGHT_ARROW', "value": 'PRESS', "ctrl": True, "repeat": True}, {"properties": [("type", 'NEXT_WORD')]}), ("font.move", {"type": 'UP_ARROW', "value": 'PRESS', "repeat": True}, {"properties": [("type", 'PREVIOUS_LINE')]}), ("font.move", {"type": 'DOWN_ARROW', "value": 'PRESS', "repeat": True}, {"properties": [("type", 'NEXT_LINE')]}), ("font.move", {"type": 'PAGE_UP', "value": 'PRESS', "repeat": True}, {"properties": [("type", 'PREVIOUS_PAGE')]}), ("font.move", {"type": 'PAGE_DOWN', "value": 'PRESS', "repeat": True}, {"properties": [("type", 'NEXT_PAGE')]}), + ("font.move", {"type": 'HOME', "value": 'PRESS', "ctrl": True, "repeat": True}, + {"properties": [("type", 'TEXT_BEGIN')]}), + ("font.move", {"type": 'END', "value": 'PRESS', "ctrl": True, "repeat": True}, + {"properties": [("type", 'TEXT_END')]}), ("font.move_select", {"type": 'HOME', "value": 'PRESS', "shift": True}, {"properties": [("type", 'LINE_BEGIN')]}), ("font.move_select", {"type": 'END', "value": 'PRESS', "shift": True}, {"properties": [("type", 'LINE_END')]}), ("font.move_select", {"type": 'LEFT_ARROW', "value": 'PRESS', "shift": True, "repeat": True}, {"properties": [("type", 'PREVIOUS_CHARACTER')]}), ("font.move_select", {"type": 'RIGHT_ARROW', "value": 'PRESS', "shift": True, "repeat": True}, {"properties": [("type", 'NEXT_CHARACTER')]}), ("font.move_select", {"type": 'LEFT_ARROW', "value": 'PRESS', "shift": True, "ctrl": True, "repeat": True}, {"properties": [("type", 'PREVIOUS_WORD')]}), ("font.move_select", {"type": 'RIGHT_ARROW', "value": 'PRESS', "shift": True, "ctrl": True, "repeat": True}, {"properties": [("type", 'NEXT_WORD')]}), ("font.move_select", {"type": 'UP_ARROW', "value": 'PRESS', "shift": True, "repeat": True}, {"properties": [("type", 'PREVIOUS_LINE')]}), ("font.move_select", {"type": 'DOWN_ARROW', "value": 'PRESS', "shift": True, "repeat": True}, {"properties": [("type", 'NEXT_LINE')]}), ("font.move_select", {"type": 'PAGE_UP', "value": 'PRESS', "shift": True, "repeat": True}, {"properties": [("type", 'PREVIOUS_PAGE')]}), ("font.move_select", {"type": 'PAGE_DOWN', "value": 'PRESS', "shift": True, "repeat": True}, {"properties": [("type", 'NEXT_PAGE')]}), + ("font.move_select", {"type": 'HOME', "value": 'PRESS', "shift": True, "ctrl": True, "repeat": True}, + {"properties": [("type", 'TEXT_BEGIN')]}), + ("font.move_select", {"type": 'END', "value": 'PRESS', "shift": True, "ctrl": True, "repeat": True}, + {"properties": [("type", 'TEXT_END')]}), ("font.change_spacing", {"type": 'LEFT_ARROW', "value": 'PRESS', "alt": True, "repeat": True}, {"properties": [("delta", -1)]}), ("font.change_spacing", {"type": 'RIGHT_ARROW', "value": 'PRESS', "alt": True, "repeat": True}, {"properties": [("delta", 1)]}), ("font.change_character", {"type": 'UP_ARROW', "value": 'PRESS', "alt": True, "repeat": True}, {"properties": [("delta", 1)]}), ("font.change_character", {"type": 'DOWN_ARROW', "value": 'PRESS', "alt": True, "repeat": True}, {"properties": [("delta", -1)]}), ("font.select_all", {"type": 'A', "value": 'PRESS', "ctrl": True}, None), ("font.text_copy", {"type": 'C', "value": 'PRESS', "ctrl": True}, None), ("font.text_cut", {"type": 'X', "value": 'PRESS', "ctrl": True}, None), ("font.text_paste", {"type": 'V', "value": 'PRESS', "ctrl": True, "repeat": True}, None), ("font.line_break", {"type": 'RET', "value": 'PRESS', "repeat": True}, None), ("font.text_insert", {"type": 'TEXTINPUT', "value": 'ANY', "any": True, "repeat": True}, None), ("font.text_insert", {"type": 'BACK_SPACE', "value": 'PRESS', "alt": True, "repeat": True}, {"properties": [("accent", True)]}), *_template_items_context_menu("VIEW3D_MT_edit_font_context_menu", params.context_menu_event), ]) return keymap # Curves edit mode. def km_curves(params): items = [] keymap = ( "Curves", {"space_type": 'EMPTY', "region_type": 'WINDOW'}, {"items": items}, ) items.extend([ ("curves.set_selection_domain", {"type": 'ONE', "value": 'PRESS'}, {"properties": [("domain", 'POINT')]}), ("curves.set_selection_domain", {"type": 'TWO', "value": 'PRESS'}, {"properties": [("domain", 'CURVE')]}), ("curves.disable_selection", {"type": 'ONE', "value": 'PRESS', "alt": True}, None), ("curves.disable_selection", {"type": 'TWO', "value": 'PRESS', "alt": True}, None), *_template_items_select_actions(params, "curves.select_all"), ("curves.select_linked", {"type": 'L', "value": 'PRESS', "ctrl": True}, None), ("curves.delete", {"type": 'X', "value": 'PRESS'}, None), ("curves.delete", {"type": 'DEL', "value": 'PRESS'}, None), ("curves.select_more", {"type": 'NUMPAD_PLUS', "value": 'PRESS', "ctrl": True, "repeat": True}, None), ("curves.select_less", {"type": 'NUMPAD_MINUS', "value": 'PRESS', "ctrl": True, "repeat": True}, None), *_template_items_proportional_editing( params, connected=True, toggle_data_path='tool_settings.use_proportional_edit'), ]) return keymap def km_sculpt_curves(params): items = [] keymap = ( "Sculpt Curves", {"space_type": 'EMPTY', "region_type": 'WINDOW'}, {"items": items}, ) items.extend([ ("sculpt_curves.brush_stroke", {"type": 'LEFTMOUSE', "value": 'PRESS'}, {"properties": [("mode", 'NORMAL')]}), ("sculpt_curves.brush_stroke", {"type": 'LEFTMOUSE', "value": 'PRESS', "ctrl": True}, {"properties": [("mode", 'INVERT')]}), ("sculpt_curves.brush_stroke", {"type": 'LEFTMOUSE', "value": 'PRESS', "shift": True}, {"properties": [("mode", 'SMOOTH')]}), ("curves.set_selection_domain", {"type": 'ONE', "value": 'PRESS'}, {"properties": [("domain", 'POINT')]}), ("curves.set_selection_domain", {"type": 'TWO', "value": 'PRESS'}, {"properties": [("domain", 'CURVE')]}), *_template_paint_radial_control("curves_sculpt"), *_template_items_select_actions(params, "curves.select_all"), ("sculpt_curves.min_distance_edit", {"type": 'R', "value": 'PRESS'}, {}), ("sculpt_curves.select_grow", {"type": 'A', "value": 'PRESS', "shift": True}, {}), ]) return keymap def km_object_non_modal(params): items = [] keymap = ( "Object Non-modal", {"space_type": 'EMPTY', "region_type": 'WINDOW'}, {"items": items}, ) if params.legacy: items.extend([ ("object.mode_set", {"type": 'TAB', "value": 'PRESS'}, {"properties": [("mode", 'EDIT'), ("toggle", True)]}), ("object.mode_set", {"type": 'TAB', "value": 'PRESS', "ctrl": True}, {"properties": [("mode", 'POSE'), ("toggle", True)]}), ("object.mode_set", {"type": 'V', "value": 'PRESS'}, {"properties": [("mode", 'VERTEX_PAINT'), ("toggle", True)]}), ("object.mode_set", {"type": 'TAB', "value": 'PRESS', "ctrl": True}, {"properties": [("mode", 'WEIGHT_PAINT'), ("toggle", True)]}), ("object.origin_set", {"type": 'C', "value": 'PRESS', "shift": True, "ctrl": True, "alt": True}, None), ]) else: items.extend([ # NOTE: this shortcut (while not temporary) is not ideal, see: #89757. ("object.transfer_mode", {"type": 'Q', "value": 'PRESS', "alt": True}, None), diff --git a/scripts/presets/keyconfig/keymap_data/industry_compatible_data.py b/scripts/presets/keyconfig/keymap_data/industry_compatible_data.py index f141566e7cc..e6fabb886a9 100644 --- a/scripts/presets/keyconfig/keymap_data/industry_compatible_data.py +++ b/scripts/presets/keyconfig/keymap_data/industry_compatible_data.py @@ -3678,220 +3678,228 @@ def km_lattice(params): op_tool_cycle("builtin.move", {"type": 'W', "value": 'PRESS'}), op_tool_cycle("builtin.rotate", {"type": 'E', "value": 'PRESS'}), op_tool_cycle("builtin.scale", {"type": 'R', "value": 'PRESS'}), op_tool_cycle("builtin.transform", {"type": 'T', "value": 'PRESS'}), op_tool_cycle("builtin.measure", {"type": 'M', "value": 'PRESS'}), ]) return keymap # Particle edit mode. def km_particle(params): items = [] keymap = ( "Particle", {"space_type": 'EMPTY', "region_type": 'WINDOW'}, {"items": items}, ) items.extend([ ("particle.select_all", {"type": 'A', "value": 'PRESS', "ctrl": True}, {"properties": [("action", 'SELECT')]}), ("particle.select_all", {"type": 'A', "value": 'PRESS', "ctrl": True, "shift": True}, {"properties": [("action", 'DESELECT')]}), ("particle.select_all", {"type": 'I', "value": 'PRESS', "ctrl": True}, {"properties": [("action", 'INVERT')]}), ("particle.select_more", {"type": 'UP_ARROW', "value": 'PRESS', "repeat": True}, None), ("particle.select_less", {"type": 'DOWN_ARROW', "value": 'PRESS', "repeat": True}, None), ("particle.select_linked_pick", {"type": 'RIGHT_BRACKET', "value": 'PRESS'}, {"properties": [("deselect", False)]}), ("particle.select_linked_pick", {"type": 'RIGHT_BRACKET', "value": 'PRESS', "shift": True}, {"properties": [("deselect", True)]}), ("particle.select_linked", {"type": 'RIGHT_BRACKET', "value": 'PRESS', "ctrl": True}, None), ("particle.delete", {"type": 'BACK_SPACE', "value": 'PRESS'}, None), ("particle.delete", {"type": 'DEL', "value": 'PRESS'}, None), ("particle.reveal", {"type": 'H', "value": 'PRESS', "alt": True}, None), ("particle.hide", {"type": 'H', "value": 'PRESS', "ctrl": True}, {"properties": [("unselected", False)]}), ("particle.hide", {"type": 'H', "value": 'PRESS', "shift": True}, {"properties": [("unselected", True)]}), ("particle.brush_edit", {"type": 'LEFTMOUSE', "value": 'PRESS'}, None), ("particle.brush_edit", {"type": 'LEFTMOUSE', "value": 'PRESS', "shift": True}, None), ("wm.radial_control", {"type": 'S', "value": 'PRESS'}, {"properties": [("data_path_primary", 'tool_settings.particle_edit.brush.size')]}), ("wm.radial_control", {"type": 'U', "value": 'PRESS', "shift": True}, {"properties": [("data_path_primary", 'tool_settings.particle_edit.brush.strength')]}), ("wm.context_toggle", {"type": 'B', "value": 'PRESS'}, {"properties": [("data_path", 'tool_settings.use_proportional_edit')]}), *_template_items_context_menu("VIEW3D_MT_particle_context_menu", {"type": 'RIGHTMOUSE', "value": 'PRESS'}), ]) return keymap # Text edit mode. def km_font(params): items = [] keymap = ( "Font", {"space_type": 'EMPTY', "region_type": 'WINDOW'}, {"items": items}, ) items.extend([ ("font.style_toggle", {"type": 'B', "value": 'PRESS', "ctrl": True}, {"properties": [("style", 'BOLD')]}), ("font.style_toggle", {"type": 'I', "value": 'PRESS', "ctrl": True}, {"properties": [("style", 'ITALIC')]}), ("font.style_toggle", {"type": 'U', "value": 'PRESS', "ctrl": True}, {"properties": [("style", 'UNDERLINE')]}), ("font.style_toggle", {"type": 'P', "value": 'PRESS', "ctrl": True}, {"properties": [("style", 'SMALL_CAPS')]}), ("font.delete", {"type": 'DEL', "value": 'PRESS', "repeat": True}, {"properties": [("type", 'NEXT_OR_SELECTION')]}), ("font.delete", {"type": 'DEL', "value": 'PRESS', "ctrl": True, "repeat": True}, {"properties": [("type", 'NEXT_WORD')]}), ("font.delete", {"type": 'BACK_SPACE', "value": 'PRESS', "repeat": True}, {"properties": [("type", 'PREVIOUS_OR_SELECTION')]}), ("font.delete", {"type": 'BACK_SPACE', "value": 'PRESS', "shift": True, "repeat": True}, {"properties": [("type", 'PREVIOUS_OR_SELECTION')]}), ("font.delete", {"type": 'BACK_SPACE', "value": 'PRESS', "ctrl": True, "repeat": True}, {"properties": [("type", 'PREVIOUS_WORD')]}), ("font.move", {"type": 'HOME', "value": 'PRESS'}, {"properties": [("type", 'LINE_BEGIN')]}), ("font.move", {"type": 'END', "value": 'PRESS'}, {"properties": [("type", 'LINE_END')]}), ("font.move", {"type": 'LEFT_ARROW', "value": 'PRESS', "repeat": True}, {"properties": [("type", 'PREVIOUS_CHARACTER')]}), ("font.move", {"type": 'RIGHT_ARROW', "value": 'PRESS', "repeat": True}, {"properties": [("type", 'NEXT_CHARACTER')]}), ("font.move", {"type": 'LEFT_ARROW', "value": 'PRESS', "ctrl": True, "repeat": True}, {"properties": [("type", 'PREVIOUS_WORD')]}), ("font.move", {"type": 'RIGHT_ARROW', "value": 'PRESS', "ctrl": True, "repeat": True}, {"properties": [("type", 'NEXT_WORD')]}), ("font.move", {"type": 'UP_ARROW', "value": 'PRESS', "repeat": True}, {"properties": [("type", 'PREVIOUS_LINE')]}), ("font.move", {"type": 'DOWN_ARROW', "value": 'PRESS', "repeat": True}, {"properties": [("type", 'NEXT_LINE')]}), ("font.move", {"type": 'PAGE_UP', "value": 'PRESS', "repeat": True}, {"properties": [("type", 'PREVIOUS_PAGE')]}), ("font.move", {"type": 'PAGE_DOWN', "value": 'PRESS', "repeat": True}, {"properties": [("type", 'NEXT_PAGE')]}), + ("font.move", {"type": 'HOME', "value": 'PRESS', "ctrl": True, "repeat": True}, + {"properties": [("type", 'TEXT_BEGIN')]}), + ("font.move", {"type": 'END', "value": 'PRESS', "ctrl": True, "repeat": True}, + {"properties": [("type", 'TEXT_END')]}), ("font.move_select", {"type": 'HOME', "value": 'PRESS', "shift": True}, {"properties": [("type", 'LINE_BEGIN')]}), ("font.move_select", {"type": 'END', "value": 'PRESS', "shift": True}, {"properties": [("type", 'LINE_END')]}), ("font.move_select", {"type": 'LEFT_ARROW', "value": 'PRESS', "shift": True, "repeat": True}, {"properties": [("type", 'PREVIOUS_CHARACTER')]}), ("font.move_select", {"type": 'RIGHT_ARROW', "value": 'PRESS', "shift": True, "repeat": True}, {"properties": [("type", 'NEXT_CHARACTER')]}), ("font.move_select", {"type": 'LEFT_ARROW', "value": 'PRESS', "shift": True, "ctrl": True, "repeat": True}, {"properties": [("type", 'PREVIOUS_WORD')]}), ("font.move_select", {"type": 'RIGHT_ARROW', "value": 'PRESS', "shift": True, "ctrl": True, "repeat": True}, {"properties": [("type", 'NEXT_WORD')]}), ("font.move_select", {"type": 'UP_ARROW', "value": 'PRESS', "shift": True, "repeat": True}, {"properties": [("type", 'PREVIOUS_LINE')]}), ("font.move_select", {"type": 'DOWN_ARROW', "value": 'PRESS', "shift": True, "repeat": True}, {"properties": [("type", 'NEXT_LINE')]}), ("font.move_select", {"type": 'PAGE_UP', "value": 'PRESS', "shift": True, "repeat": True}, {"properties": [("type", 'PREVIOUS_PAGE')]}), ("font.move_select", {"type": 'PAGE_DOWN', "value": 'PRESS', "shift": True, "repeat": True}, {"properties": [("type", 'NEXT_PAGE')]}), + ("font.move_select", {"type": 'HOME', "value": 'PRESS', "shift": True, "ctrl": True, "repeat": True}, + {"properties": [("type", 'TEXT_BEGIN')]}), + ("font.move_select", {"type": 'END', "value": 'PRESS', "shift": True, "ctrl": True, "repeat": True}, + {"properties": [("type", 'TEXT_END')]}), ("font.change_spacing", {"type": 'LEFT_ARROW', "value": 'PRESS', "alt": True, "repeat": True}, {"properties": [("delta", -1)]}), ("font.change_spacing", {"type": 'RIGHT_ARROW', "value": 'PRESS', "alt": True, "repeat": True}, {"properties": [("delta", 1)]}), ("font.change_character", {"type": 'UP_ARROW', "value": 'PRESS', "alt": True, "repeat": True}, {"properties": [("delta", 1)]}), ("font.change_character", {"type": 'DOWN_ARROW', "value": 'PRESS', "alt": True, "repeat": True}, {"properties": [("delta", -1)]}), ("font.select_all", {"type": 'A', "value": 'PRESS', "ctrl": True}, None), ("font.text_copy", {"type": 'C', "value": 'PRESS', "ctrl": True}, None), ("font.text_cut", {"type": 'X', "value": 'PRESS', "ctrl": True}, None), ("font.text_paste", {"type": 'V', "value": 'PRESS', "ctrl": True, "repeat": True}, None), ("font.line_break", {"type": 'RET', "value": 'PRESS'}, None), ("font.text_insert", {"type": 'TEXTINPUT', "value": 'ANY', "any": True}, None), ("font.text_insert", {"type": 'BACK_SPACE', "value": 'PRESS', "alt": True}, {"properties": [("accent", True)]}), *_template_items_context_menu("VIEW3D_MT_edit_font_context_menu", {"type": 'RIGHTMOUSE', "value": 'PRESS'}), ]) return keymap def km_object_non_modal(params): items = [] keymap = ( "Object Non-modal", {"space_type": 'EMPTY', "region_type": 'WINDOW'}, {"items": items}, ) items.extend([ ("object.mode_set", {"type": 'ONE', "value": 'PRESS'}, {"properties": [("mode", 'PAINT_GPENCIL')]}), ("object.mode_set", {"type": 'THREE', "value": 'PRESS'}, {"properties": [("mode", 'POSE')]}), ("object.mode_set_with_submode", {"type": 'ONE', "value": 'PRESS'}, {"properties": [("mode", 'EDIT'), ("mesh_select_mode", {'VERT'})]}), ("object.mode_set_with_submode", {"type": 'TWO', "value": 'PRESS'}, {"properties": [("mode", 'EDIT'), ("mesh_select_mode", {'EDGE'})]}), ("object.mode_set_with_submode", {"type": 'THREE', "value": 'PRESS'}, {"properties": [("mode", 'EDIT'), ("mesh_select_mode", {'FACE'})]}), ("object.mode_set", {"type": 'ONE', "value": 'PRESS'}, {"properties": [("mode", 'EDIT')]}), ("object.mode_set", {"type": 'FOUR', "value": 'PRESS'}, {"properties": [("mode", 'OBJECT')]}), ("object.mode_set", {"type": 'FIVE', "value": 'PRESS'}, {"properties": [("mode", 'SCULPT')]}), ("object.mode_set", {"type": 'SIX', "value": 'PRESS'}, {"properties": [("mode", 'VERTEX_PAINT')]}), ("object.mode_set", {"type": 'SEVEN', "value": 'PRESS'}, {"properties": [("mode", 'WEIGHT_PAINT')]}), ("object.mode_set", {"type": 'EIGHT', "value": 'PRESS'}, {"properties": [("mode", 'TEXTURE_PAINT')]}), ("object.mode_set", {"type": 'TWO', "value": 'PRESS'}, {"properties": [("mode", 'EDIT_GPENCIL')]}), ("object.mode_set", {"type": 'FIVE', "value": 'PRESS'}, {"properties": [("mode", 'SCULPT_GPENCIL')]}), ("object.mode_set", {"type": 'SIX', "value": 'PRESS'}, {"properties": [("mode", 'VERTEX_GPENCIL')]}), ("object.mode_set", {"type": 'SEVEN', "value": 'PRESS'}, {"properties": [("mode", 'WEIGHT_GPENCIL')]}), ]) return keymap # ------------------------------------------------------------------------------ # Modal Maps def km_knife_tool_modal_map(_params): items = [] keymap = ( "Knife Tool Modal Map", {"space_type": 'EMPTY', "region_type": 'WINDOW', "modal": True}, {"items": items}, ) items.extend([ ("CANCEL", {"type": 'ESC', "value": 'PRESS', "any": True}, None), ("PANNING", {"type": 'LEFTMOUSE', "value": 'PRESS', "alt": True}, None), ("CONFIRM", {"type": 'RET', "value": 'PRESS', "any": True}, None), ("CONFIRM", {"type": 'NUMPAD_ENTER', "value": 'PRESS', "any": True}, None), ("ADD_CUT_CLOSED", {"type": 'LEFTMOUSE', "value": 'DOUBLE_CLICK', "any": True}, None), ("ADD_CUT", {"type": 'LEFTMOUSE', "value": 'ANY', "any": True}, None), ("UNDO", {"type": 'Z', "value": 'PRESS', "ctrl": True}, None), ("NEW_CUT", {"type": 'RIGHTMOUSE', "value": 'PRESS'}, None), ("SNAP_MIDPOINTS_ON", {"type": 'LEFT_CTRL', "value": 'PRESS'}, None), ("SNAP_MIDPOINTS_OFF", {"type": 'LEFT_CTRL', "value": 'RELEASE'}, None), ("SNAP_MIDPOINTS_ON", {"type": 'RIGHT_CTRL', "value": 'PRESS'}, None), ("SNAP_MIDPOINTS_OFF", {"type": 'RIGHT_CTRL', "value": 'RELEASE'}, None), ("IGNORE_SNAP_ON", {"type": 'LEFT_SHIFT', "value": 'PRESS', "any": True}, None), ("IGNORE_SNAP_OFF", {"type": 'LEFT_SHIFT', "value": 'RELEASE', "any": True}, None), ("IGNORE_SNAP_ON", {"type": 'RIGHT_SHIFT', "value": 'PRESS', "any": True}, None), ("IGNORE_SNAP_OFF", {"type": 'RIGHT_SHIFT', "value": 'RELEASE', "any": True}, None), ("X_AXIS", {"type": 'X', "value": 'PRESS'}, None), ("Y_AXIS", {"type": 'Y', "value": 'PRESS'}, None), ("Z_AXIS", {"type": 'Z', "value": 'PRESS'}, None), ("ANGLE_SNAP_TOGGLE", {"type": 'A', "value": 'PRESS'}, None), diff --git a/scripts/startup/bl_ui/space_view3d.py b/scripts/startup/bl_ui/space_view3d.py index 461788215e3..37fdfd3123e 100644 --- a/scripts/startup/bl_ui/space_view3d.py +++ b/scripts/startup/bl_ui/space_view3d.py @@ -1707,200 +1707,205 @@ class VIEW3D_MT_select_edit_mesh(Menu): layout.menu("VIEW3D_MT_edit_mesh_select_by_trait") layout.separator() layout.menu("VIEW3D_MT_edit_mesh_select_more_less") layout.separator() layout.menu("VIEW3D_MT_edit_mesh_select_loops") layout.separator() layout.menu("VIEW3D_MT_edit_mesh_select_linked") layout.separator() layout.operator("mesh.select_axis", text="Side of Active") layout.operator("mesh.select_mirror") class VIEW3D_MT_select_edit_curve(Menu): bl_label = "Select" def draw(self, _context): layout = self.layout layout.operator("curve.select_all", text="All").action = 'SELECT' layout.operator("curve.select_all", text="None").action = 'DESELECT' layout.operator("curve.select_all", text="Invert").action = 'INVERT' layout.separator() layout.operator("view3d.select_box") layout.operator("view3d.select_circle") layout.operator_menu_enum("view3d.select_lasso", "mode") layout.separator() layout.operator("curve.select_random") layout.operator("curve.select_nth") layout.operator("curve.select_linked", text="Select Linked") layout.operator("curve.select_similar", text="Select Similar") layout.separator() layout.operator("curve.de_select_first") layout.operator("curve.de_select_last") layout.operator("curve.select_next") layout.operator("curve.select_previous") layout.separator() layout.operator("curve.select_more") layout.operator("curve.select_less") class VIEW3D_MT_select_edit_surface(Menu): bl_label = "Select" def draw(self, _context): layout = self.layout layout.operator("curve.select_all", text="All").action = 'SELECT' layout.operator("curve.select_all", text="None").action = 'DESELECT' layout.operator("curve.select_all", text="Invert").action = 'INVERT' layout.separator() layout.operator("view3d.select_box") layout.operator("view3d.select_circle") layout.operator_menu_enum("view3d.select_lasso", "mode") layout.separator() layout.operator("curve.select_random") layout.operator("curve.select_nth") layout.operator("curve.select_linked", text="Select Linked") layout.operator("curve.select_similar", text="Select Similar") layout.separator() layout.operator("curve.select_row") layout.separator() layout.operator("curve.select_more") layout.operator("curve.select_less") class VIEW3D_MT_select_edit_text(Menu): bl_label = "Select" def draw(self, _context): layout = self.layout layout.operator("font.select_all", text="All") layout.separator() + layout.operator("font.move_select", text="Top").type = 'TEXT_BEGIN' + layout.operator("font.move_select", text="Bottom").type = 'TEXT_END' + + layout.separator() + layout.operator("font.move_select", text="Previous Block").type = 'PREVIOUS_PAGE' layout.operator("font.move_select", text="Next Block").type = 'NEXT_PAGE' layout.separator() layout.operator("font.move_select", text="Line Begin").type = 'LINE_BEGIN' layout.operator("font.move_select", text="Line End").type = 'LINE_END' layout.separator() layout.operator("font.move_select", text="Previous Line").type = 'PREVIOUS_LINE' layout.operator("font.move_select", text="Next Line").type = 'NEXT_LINE' layout.separator() layout.operator("font.move_select", text="Previous Word").type = 'PREVIOUS_WORD' layout.operator("font.move_select", text="Next Word").type = 'NEXT_WORD' class VIEW3D_MT_select_edit_metaball(Menu): bl_label = "Select" def draw(self, _context): layout = self.layout layout.operator("mball.select_all", text="All").action = 'SELECT' layout.operator("mball.select_all", text="None").action = 'DESELECT' layout.operator("mball.select_all", text="Invert").action = 'INVERT' layout.separator() layout.operator("view3d.select_box") layout.operator("view3d.select_circle") layout.operator_menu_enum("view3d.select_lasso", "mode") layout.separator() layout.operator("mball.select_random_metaelems") layout.separator() layout.operator_menu_enum("mball.select_similar", "type", text="Similar") class VIEW3D_MT_edit_lattice_context_menu(Menu): bl_label = "Lattice Context Menu" def draw(self, _context): layout = self.layout layout = self.layout layout.menu("VIEW3D_MT_mirror") layout.operator_menu_enum("lattice.flip", "axis") layout.menu("VIEW3D_MT_snap") layout.separator() layout.operator("lattice.make_regular") class VIEW3D_MT_select_edit_lattice(Menu): bl_label = "Select" def draw(self, _context): layout = self.layout layout.operator("lattice.select_all", text="All").action = 'SELECT' layout.operator("lattice.select_all", text="None").action = 'DESELECT' layout.operator("lattice.select_all", text="Invert").action = 'INVERT' layout.separator() layout.operator("view3d.select_box") layout.operator("view3d.select_circle") layout.operator_menu_enum("view3d.select_lasso", "mode") layout.separator() layout.operator("lattice.select_mirror") layout.operator("lattice.select_random") layout.separator() layout.operator("lattice.select_more") layout.operator("lattice.select_less") layout.separator() layout.operator("lattice.select_ungrouped", text="Ungrouped Vertices") class VIEW3D_MT_select_edit_armature(Menu): bl_label = "Select" def draw(self, _context): layout = self.layout layout.operator("armature.select_all", text="All").action = 'SELECT' layout.operator("armature.select_all", text="None").action = 'DESELECT' diff --git a/source/blender/blenkernel/intern/vfont.c b/source/blender/blenkernel/intern/vfont.c index b6f9a23a3cd..f1b689bc695 100644 --- a/source/blender/blenkernel/intern/vfont.c +++ b/source/blender/blenkernel/intern/vfont.c @@ -1336,224 +1336,230 @@ static bool vfont_to_curve(Object *ob, if (maxx < ct->xof) { maxx = ct->xof; } } /* We put the x-coordinate exact at the curve, the y is rotated. */ /* length correction */ const float chartrans_size_x = maxx - minx; if (chartrans_size_x != 0.0f) { const CurveCache *cc = cu->textoncurve->runtime.curve_cache; const float totdist = BKE_anim_path_get_length(cc); distfac = (sizefac * totdist) / chartrans_size_x; distfac = (distfac > 1.0f) ? (1.0f / distfac) : 1.0f; } else { /* Happens when there are no characters, set this value to place the text cursor. */ distfac = 0.0f; } timeofs = 0.0f; if (distfac < 1.0f) { /* Path longer than text: space-mode is involved. */ if (cu->spacemode == CU_ALIGN_X_RIGHT) { timeofs = 1.0f - distfac; } else if (cu->spacemode == CU_ALIGN_X_MIDDLE) { timeofs = (1.0f - distfac) / 2.0f; } else if (cu->spacemode == CU_ALIGN_X_FLUSH) { distfac = 1.0f; } } if (chartrans_size_x != 0.0f) { distfac /= chartrans_size_x; } timeofs += distfac * cu->xof; /* not cyclic */ ct = chartransdata; for (i = 0; i <= slen; i++, ct++) { float ctime, dtime, vec[4], rotvec[3]; float si, co; /* Rotate around center character. */ info = &custrinfo[i]; ascii = mem[i]; if (info->flag & CU_CHINFO_SMALLCAPS_CHECK) { ascii = towupper(ascii); } che = find_vfont_char(vfd, ascii); twidth = char_width(cu, che, info); dtime = distfac * 0.5f * twidth; ctime = timeofs + distfac * (ct->xof - minx); CLAMP(ctime, 0.0f, 1.0f); /* Calculate the right loc AND the right rot separately. */ /* `vec` needs 4 items. */ BKE_where_on_path(cu->textoncurve, ctime, vec, NULL, NULL, NULL, NULL); BKE_where_on_path(cu->textoncurve, ctime + dtime, NULL, rotvec, NULL, NULL, NULL); mul_v3_fl(vec, sizefac); ct->rot = (float)M_PI - atan2f(rotvec[1], rotvec[0]); si = sinf(ct->rot); co = cosf(ct->rot); yof = ct->yof; ct->xof = vec[0] + si * yof; ct->yof = vec[1] + co * yof; if (selboxes && (i >= selstart) && (i <= selend)) { EditFontSelBox *sb; sb = &selboxes[i - selstart]; sb->rot = -ct->rot; } } } } if (selboxes) { ct = chartransdata; for (i = 0; i <= selend; i++, ct++) { if (i >= selstart) { selboxes[i - selstart].x = ct->xof * font_size; selboxes[i - selstart].y = (ct->yof - 0.25f) * font_size; selboxes[i - selstart].h = font_size; } } } - if (ELEM(mode, FO_CURSUP, FO_CURSDOWN, FO_PAGEUP, FO_PAGEDOWN) && + if (ELEM(mode, FO_CURSUP, FO_CURSDOWN, FO_PAGEUP, FO_PAGEDOWN, FO_TEXTBEGIN, FO_TEXTEND) && iter_data->status == VFONT_TO_CURVE_INIT) { ct = &chartransdata[ef->pos]; if (ELEM(mode, FO_CURSUP, FO_PAGEUP) && ct->linenr == 0) { /* pass */ } else if (ELEM(mode, FO_CURSDOWN, FO_PAGEDOWN) && ct->linenr == lnr) { /* pass */ } else { switch (mode) { case FO_CURSUP: lnr = ct->linenr - 1; break; case FO_CURSDOWN: lnr = ct->linenr + 1; break; case FO_PAGEUP: lnr = ct->linenr - 10; break; case FO_PAGEDOWN: lnr = ct->linenr + 10; break; + case FO_TEXTBEGIN: + lnr = 0; + break; + case FO_TEXTEND: + /* Pass. lnr is at the last line. */ + break; } cnr = ct->charnr; /* Seek for char with `lnr` & `cnr`. */ ef->pos = 0; ct = chartransdata; for (i = 0; i < slen; i++) { if (ct->linenr == lnr) { if ((ct->charnr == cnr) || ((ct + 1)->charnr == 0)) { break; } } else if (ct->linenr > lnr) { break; } ef->pos++; ct++; } } } /* Cursor first. */ if (ef) { float si, co; ct = &chartransdata[ef->pos]; si = sinf(ct->rot); co = cosf(ct->rot); f = ef->textcurs[0]; f[0] = font_size * (-0.02f * co + ct->xof); f[1] = font_size * (0.1f * si - (0.25f * co) + ct->yof); f[2] = font_size * (0.02f * co + ct->xof); f[3] = font_size * (-0.1f * si - (0.25f * co) + ct->yof); f[4] = font_size * (0.02f * co + 0.8f * si + ct->xof); f[5] = font_size * (-0.1f * si + 0.75f * co + ct->yof); f[6] = font_size * (-0.02f * co + 0.8f * si + ct->xof); f[7] = font_size * (0.1f * si + 0.75f * co + ct->yof); } if (mode == FO_SELCHANGE) { MEM_freeN(chartransdata); chartransdata = NULL; } else if (mode == FO_EDIT) { /* Make NURBS-data. */ BKE_nurbList_free(r_nubase); ct = chartransdata; for (i = 0; i < slen; i++) { uint cha = (uint)mem[i]; info = &(custrinfo[i]); if ((cu->overflow == CU_OVERFLOW_TRUNCATE) && (ob && ob->mode != OB_MODE_EDIT) && (info->flag & CU_CHINFO_OVERFLOW)) { break; } if (info->flag & CU_CHINFO_SMALLCAPS_CHECK) { cha = towupper(cha); } /* Only do that check in case we do have an object, otherwise all materials get erased every * time that code is called without an object. */ if (ob != NULL && (info->mat_nr > (ob->totcol))) { // CLOG_ERROR( // &LOG, "Illegal material index (%d) in text object, setting to 0", info->mat_nr); info->mat_nr = 0; } /* We don't want to see any character for '\n'. */ if (cha != '\n') { BKE_vfont_build_char(cu, r_nubase, cha, info, ct->xof, ct->yof, ct->rot, i, font_size); } if ((info->flag & CU_CHINFO_UNDERLINE) && (cha != '\n')) { float ulwidth, uloverlap = 0.0f; rctf rect; if ((i < (slen - 1)) && (mem[i + 1] != '\n') && ((mem[i + 1] != ' ') || (custrinfo[i + 1].flag & CU_CHINFO_UNDERLINE)) && ((custrinfo[i + 1].flag & CU_CHINFO_WRAP) == 0)) { uloverlap = xtrax + 0.1f; } /* Find the character, the characters has to be in the memory already * since character checking has been done earlier already. */ che = find_vfont_char(vfd, cha); twidth = char_width(cu, che, info); ulwidth = (twidth * (1.0f + (info->kern / 40.0f))) + uloverlap; rect.xmin = ct->xof; rect.xmax = rect.xmin + ulwidth; rect.ymin = ct->yof; rect.ymax = rect.ymin - cu->ulheight; build_underline( diff --git a/source/blender/editors/curve/curve_intern.h b/source/blender/editors/curve/curve_intern.h index 61a18dbd3e3..66404718bba 100644 --- a/source/blender/editors/curve/curve_intern.h +++ b/source/blender/editors/curve/curve_intern.h @@ -1,144 +1,146 @@ /* SPDX-License-Identifier: GPL-2.0-or-later * Copyright 2008 Blender Foundation */ /** \file * \ingroup edcurve */ #pragma once /* internal exports only */ struct EditNurb; struct GHash; struct ListBase; struct Object; struct ViewContext; struct wmOperatorType; #ifdef __cplusplus extern "C" { #endif /* editfont.c */ enum { DEL_NEXT_CHAR, DEL_PREV_CHAR, DEL_NEXT_WORD, DEL_PREV_WORD, DEL_SELECTION, DEL_NEXT_SEL, DEL_PREV_SEL }; enum { CASE_LOWER, CASE_UPPER }; enum { LINE_BEGIN, LINE_END, PREV_CHAR, NEXT_CHAR, PREV_WORD, NEXT_WORD, PREV_LINE, NEXT_LINE, PREV_PAGE, - NEXT_PAGE + NEXT_PAGE, + TEXT_BEGIN, + TEXT_END }; typedef enum eVisible_Types { HIDDEN = true, VISIBLE = false, } eVisible_Types; typedef enum eEndPoint_Types { FIRST = true, LAST = false, } eEndPoint_Types; typedef enum eCurveElem_Types { CURVE_VERTEX = 0, CURVE_SEGMENT, } eCurveElem_Types; /* internal select utils */ /** * Returns 1 in case (de)selection was successful. */ bool select_beztriple(BezTriple *bezt, bool selstatus, uint8_t flag, eVisible_Types hidden); /** * Returns 1 in case (de)selection was successful. */ bool select_bpoint(BPoint *bp, bool selstatus, uint8_t flag, bool hidden); void FONT_OT_text_insert(struct wmOperatorType *ot); void FONT_OT_line_break(struct wmOperatorType *ot); void FONT_OT_case_toggle(struct wmOperatorType *ot); void FONT_OT_case_set(struct wmOperatorType *ot); void FONT_OT_style_toggle(struct wmOperatorType *ot); void FONT_OT_style_set(struct wmOperatorType *ot); void FONT_OT_select_all(struct wmOperatorType *ot); void FONT_OT_text_copy(struct wmOperatorType *ot); void FONT_OT_text_cut(struct wmOperatorType *ot); void FONT_OT_text_paste(struct wmOperatorType *ot); void FONT_OT_text_paste_from_file(struct wmOperatorType *ot); void FONT_OT_move(struct wmOperatorType *ot); void FONT_OT_move_select(struct wmOperatorType *ot); void FONT_OT_delete(struct wmOperatorType *ot); void FONT_OT_change_character(struct wmOperatorType *ot); void FONT_OT_change_spacing(struct wmOperatorType *ot); void FONT_OT_open(struct wmOperatorType *ot); void FONT_OT_unlink(struct wmOperatorType *ot); void FONT_OT_textbox_add(struct wmOperatorType *ot); void FONT_OT_textbox_remove(struct wmOperatorType *ot); /* editcurve.c */ void CURVE_OT_hide(struct wmOperatorType *ot); void CURVE_OT_reveal(struct wmOperatorType *ot); void CURVE_OT_separate(struct wmOperatorType *ot); void CURVE_OT_split(struct wmOperatorType *ot); void CURVE_OT_duplicate(struct wmOperatorType *ot); void CURVE_OT_delete(struct wmOperatorType *ot); void CURVE_OT_dissolve_verts(struct wmOperatorType *ot); void CURVE_OT_spline_type_set(struct wmOperatorType *ot); void CURVE_OT_radius_set(struct wmOperatorType *ot); void CURVE_OT_spline_weight_set(struct wmOperatorType *ot); void CURVE_OT_handle_type_set(struct wmOperatorType *ot); void CURVE_OT_normals_make_consistent(struct wmOperatorType *ot); void CURVE_OT_decimate(struct wmOperatorType *ot); void CURVE_OT_shade_smooth(struct wmOperatorType *ot); void CURVE_OT_shade_flat(struct wmOperatorType *ot); void CURVE_OT_tilt_clear(struct wmOperatorType *ot); void CURVE_OT_smooth(struct wmOperatorType *ot); void CURVE_OT_smooth_weight(struct wmOperatorType *ot); void CURVE_OT_smooth_radius(struct wmOperatorType *ot); void CURVE_OT_smooth_tilt(struct wmOperatorType *ot); void CURVE_OT_switch_direction(struct wmOperatorType *ot); void CURVE_OT_subdivide(struct wmOperatorType *ot); void CURVE_OT_make_segment(struct wmOperatorType *ot); void CURVE_OT_spin(struct wmOperatorType *ot); void CURVE_OT_vertex_add(struct wmOperatorType *ot); void CURVE_OT_extrude(struct wmOperatorType *ot); void CURVE_OT_cyclic_toggle(struct wmOperatorType *ot); void CURVE_OT_match_texture_space(struct wmOperatorType *ot); /* exported for editcurve_undo.cc */ struct GHash *ED_curve_keyindex_hash_duplicate(struct GHash *keyindex); void ED_curve_keyindex_update_nurb(struct EditNurb *editnurb, struct Nurb *nu, struct Nurb *newnu); /* exported for editcurve_pen.c */ int ed_editcurve_addvert(Curve *cu, EditNurb *editnurb, View3D *v3d, const float location_init[3]); bool curve_toggle_cyclic(View3D *v3d, ListBase *editnurb, int direction); diff --git a/source/blender/editors/curve/editfont.c b/source/blender/editors/curve/editfont.c index f96bb85d53e..b09c20d4d09 100644 --- a/source/blender/editors/curve/editfont.c +++ b/source/blender/editors/curve/editfont.c @@ -1047,281 +1047,291 @@ static int paste_text_exec(bContext *C, wmOperator *op) /* Store both clipboards as utf8 for comparison, * Give priority to the internal 'vfont' clipboard with its 'CharInfo' text styles * as long as its synchronized with the systems clipboard. */ struct { char *buf; int len; } clipboard_system = {NULL}, clipboard_vfont = {NULL}; clipboard_system.buf = WM_clipboard_text_get(selection, &clipboard_system.len); if (clipboard_system.buf == NULL) { return OPERATOR_CANCELLED; } BKE_vfont_clipboard_get(&text_buf, NULL, &len_utf8, NULL); if (text_buf) { clipboard_vfont.buf = MEM_mallocN(len_utf8 + 1, __func__); if (clipboard_vfont.buf == NULL) { MEM_freeN(clipboard_system.buf); return OPERATOR_CANCELLED; } BLI_str_utf32_as_utf8(clipboard_vfont.buf, text_buf, len_utf8 + 1); } if (clipboard_vfont.buf && STREQ(clipboard_vfont.buf, clipboard_system.buf)) { retval = paste_selection(obedit, op->reports) ? OPERATOR_FINISHED : OPERATOR_CANCELLED; } else { if ((clipboard_system.len <= MAXTEXT) && font_paste_utf8(C, clipboard_system.buf, clipboard_system.len)) { text_update_edited(C, obedit, FO_EDIT); retval = OPERATOR_FINISHED; } else { BKE_report(op->reports, RPT_ERROR, "Clipboard too long"); retval = OPERATOR_CANCELLED; } /* free the existent clipboard buffer */ BKE_vfont_clipboard_free(); } if (retval != OPERATOR_CANCELLED) { text_update_edited(C, obedit, FO_EDIT); } /* cleanup */ if (clipboard_vfont.buf) { MEM_freeN(clipboard_vfont.buf); } MEM_freeN(clipboard_system.buf); return retval; } void FONT_OT_text_paste(wmOperatorType *ot) { /* identifiers */ ot->name = "Paste Text"; ot->description = "Paste text from clipboard"; ot->idname = "FONT_OT_text_paste"; /* api callbacks */ ot->exec = paste_text_exec; ot->poll = ED_operator_editfont; /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; /* properties */ PropertyRNA *prop; prop = RNA_def_boolean(ot->srna, "selection", 0, "Selection", "Paste text selected elsewhere rather than copied (X11/Wayland only)"); RNA_def_property_flag(prop, PROP_SKIP_SAVE); } /** \} */ /* -------------------------------------------------------------------- */ /** \name Move Operator * \{ */ static const EnumPropertyItem move_type_items[] = { {LINE_BEGIN, "LINE_BEGIN", 0, "Line Begin", ""}, {LINE_END, "LINE_END", 0, "Line End", ""}, {PREV_CHAR, "PREVIOUS_CHARACTER", 0, "Previous Character", ""}, {NEXT_CHAR, "NEXT_CHARACTER", 0, "Next Character", ""}, {PREV_WORD, "PREVIOUS_WORD", 0, "Previous Word", ""}, {NEXT_WORD, "NEXT_WORD", 0, "Next Word", ""}, {PREV_LINE, "PREVIOUS_LINE", 0, "Previous Line", ""}, {NEXT_LINE, "NEXT_LINE", 0, "Next Line", ""}, {PREV_PAGE, "PREVIOUS_PAGE", 0, "Previous Page", ""}, {NEXT_PAGE, "NEXT_PAGE", 0, "Next Page", ""}, + {TEXT_BEGIN, "TEXT_BEGIN", 0, "Text Top", ""}, + {TEXT_END, "TEXT_END", 0, "Text Bottom", ""}, {0, NULL, 0, NULL, NULL}, }; static int move_cursor(bContext *C, int type, const bool select) { Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C); Object *obedit = CTX_data_edit_object(C); Curve *cu = obedit->data; EditFont *ef = cu->editfont; int cursmove = -1; if ((select) && (ef->selstart == 0)) { ef->selstart = ef->selend = ef->pos + 1; } switch (type) { case LINE_BEGIN: while (ef->pos > 0) { if (ef->textbuf[ef->pos - 1] == '\n') { break; } if (ef->textbufinfo[ef->pos - 1].flag & CU_CHINFO_WRAP) { break; } ef->pos--; } cursmove = FO_CURS; break; case LINE_END: while (ef->pos < ef->len) { if (ef->textbuf[ef->pos] == 0) { break; } if (ef->textbuf[ef->pos] == '\n') { break; } if (ef->textbufinfo[ef->pos].flag & CU_CHINFO_WRAP) { break; } ef->pos++; } cursmove = FO_CURS; break; case PREV_WORD: { int pos = ef->pos; BLI_str_cursor_step_utf32( ef->textbuf, ef->len, &pos, STRCUR_DIR_PREV, STRCUR_JUMP_DELIM, true); ef->pos = pos; cursmove = FO_CURS; break; } case NEXT_WORD: { int pos = ef->pos; BLI_str_cursor_step_utf32( ef->textbuf, ef->len, &pos, STRCUR_DIR_NEXT, STRCUR_JUMP_DELIM, true); ef->pos = pos; cursmove = FO_CURS; break; } case PREV_CHAR: BLI_str_cursor_step_prev_utf32(ef->textbuf, ef->len, &ef->pos); cursmove = FO_CURS; break; case NEXT_CHAR: BLI_str_cursor_step_next_utf32(ef->textbuf, ef->len, &ef->pos); cursmove = FO_CURS; break; case PREV_LINE: cursmove = FO_CURSUP; break; case NEXT_LINE: cursmove = FO_CURSDOWN; break; + case TEXT_BEGIN: + cursmove = FO_TEXTBEGIN; + break; + + case TEXT_END: + cursmove = FO_TEXTEND; + break; + case PREV_PAGE: cursmove = FO_PAGEUP; break; case NEXT_PAGE: cursmove = FO_PAGEDOWN; break; } if (cursmove == -1) { return OPERATOR_CANCELLED; } if (ef->pos > ef->len) { ef->pos = ef->len; } else if (ef->pos >= MAXTEXT) { ef->pos = MAXTEXT; } else if (ef->pos < 0) { ef->pos = 0; } /* apply vertical cursor motion to position immediately * otherwise the selection will lag behind */ if (FO_CURS_IS_MOTION(cursmove)) { BKE_vfont_to_curve(DEG_get_evaluated_object(depsgraph, obedit), cursmove); cursmove = FO_CURS; } if (select == 0) { if (ef->selstart) { ef->selstart = ef->selend = 0; BKE_vfont_to_curve(DEG_get_evaluated_object(depsgraph, obedit), FO_SELCHANGE); } } if (select) { ef->selend = ef->pos; font_select_update_primary_clipboard(obedit); } text_update_edited(C, obedit, cursmove); return OPERATOR_FINISHED; } static int move_exec(bContext *C, wmOperator *op) { int type = RNA_enum_get(op->ptr, "type"); return move_cursor(C, type, false); } void FONT_OT_move(wmOperatorType *ot) { /* identifiers */ ot->name = "Move Cursor"; ot->description = "Move cursor to position type"; ot->idname = "FONT_OT_move"; /* api callbacks */ ot->exec = move_exec; ot->poll = ED_operator_editfont; /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; /* properties */ RNA_def_enum(ot->srna, "type", move_type_items, LINE_BEGIN, "Type", "Where to move cursor to"); } /** \} */ /* -------------------------------------------------------------------- */ /** \name Move Select Operator * \{ */ static int move_select_exec(bContext *C, wmOperator *op) { int type = RNA_enum_get(op->ptr, "type"); return move_cursor(C, type, true); } void FONT_OT_move_select(wmOperatorType *ot) { /* identifiers */ ot->name = "Move Select"; ot->description = "Move the cursor while selecting"; ot->idname = "FONT_OT_move_select"; /* api callbacks */ ot->exec = move_select_exec; ot->poll = ED_operator_editfont; /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; /* properties */ diff --git a/source/blender/makesdna/DNA_vfont_types.h b/source/blender/makesdna/DNA_vfont_types.h index 42be4dc63cc..7f7294c673a 100644 --- a/source/blender/makesdna/DNA_vfont_types.h +++ b/source/blender/makesdna/DNA_vfont_types.h @@ -1,53 +1,55 @@ /* SPDX-License-Identifier: GPL-2.0-or-later * Copyright 2001-2002 NaN Holding BV. All rights reserved. */ /** \file * \ingroup DNA * * Vector Fonts used for text in the 3D Viewport * (unrelated to text used to render the GUI). */ #pragma once #include "DNA_ID.h" #ifdef __cplusplus extern "C" { #endif struct PackedFile; struct VFontData; typedef struct VFont { ID id; /** 1024 = FILE_MAX. */ char filepath[1024]; struct VFontData *data; struct PackedFile *packedfile; /* runtime only, holds memory for freetype to read from * TODO: replace this with #blf_font_new() style loading. */ struct PackedFile *temp_pf; } VFont; /* *************** FONT ****************** */ #define FO_EDIT 0 #define FO_CURS 1 #define FO_CURSUP 2 #define FO_CURSDOWN 3 #define FO_DUPLI 4 #define FO_PAGEUP 8 #define FO_PAGEDOWN 9 -#define FO_SELCHANGE 10 +#define FO_TEXTBEGIN 10 +#define FO_TEXTEND 11 +#define FO_SELCHANGE 12 /* BKE_vfont_to_curve will move the cursor in these cases */ -#define FO_CURS_IS_MOTION(mode) (ELEM(mode, FO_CURSUP, FO_CURSDOWN, FO_PAGEUP, FO_PAGEDOWN)) +#define FO_CURS_IS_MOTION(mode) (ELEM(mode, FO_CURSUP, FO_CURSDOWN, FO_PAGEUP, FO_PAGEDOWN, FO_TEXTBEGIN, FO_TEXTEND)) #define FO_BUILTIN_NAME "" #ifdef __cplusplus } #endif