├── .gitignore
├── CHANGELOG.md
├── README.md
└── __init__.py
/.gitignore:
--------------------------------------------------------------------------------
1 | __pycache__
2 | *.py[cod]
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | # changelog
2 |
3 | 1.3.0 - 2021-10-30:
4 |
5 | - fix: bad mode in for snap selection to cursor / cursor to selected for Grease Pencil
6 | - code: converted to multifile addons and added Changelog
7 | - code: transfered 2.79 version to another repo
8 |
9 | 1.2.1 - 2020-12-20:
10 |
11 | - fix: keymap unregister
12 |
13 | 1.2.0 - 2020-12-16:
14 |
15 | - new shortcut: jump prev/next marker with `shift+alt+mouse4/5` (in every editor)
16 |
17 | 1.1.1 - 2020-11-28:
18 |
19 | - feat: added cursor to selected and selection to cursor for grease pencil
20 | - fix: Bug in keymap register that could affect other addon's keymap
21 | - better UI for infos in addon prefs
22 | - readme: changelog formating updated
23 |
24 | 1.0.0 - 13-09-2019:
25 |
26 | - invert preference work only on the focus/view all shortcut
27 | - fixed bug with keyframe jumping
28 | - new shortcut : move origin point
29 |
30 | 0.0.9 - 02-06-2019:
31 |
32 | - full change of keymap setting:
33 | - inverting default shortchut to a more logical setup (prev = going back, next = going to).
34 | - suppressing all preferences that overcomplicated the addon, letting only the possibility to invert everything (maybe delete even this one later).
35 |
36 | 0.0.8 - 19-02-2019:
37 |
38 | - 2.8 version
39 |
40 | 0.0.7 - 05-06-2018:
41 |
42 | - Added Alt combo to jump keyframe
43 |
44 | 0.0.5 - 22-04-2018:
45 |
46 | - Fix bad keymap unregister
47 | - Added modifiers functions:
48 | - Shift combo : cursor to selection and selection to cursor
49 | - Ctrl combo : access alternative view tweak
50 |
51 | 0.0.3 - 14-04-2018:
52 |
53 | - By default shortcuts are now completely consistent (view_selected and view all everywhere)
54 | - added addon preferences to invert buttons and customize shortcut in 3D view.
55 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # MyKeyMouse
2 | Blender keymapper addon - Map shortcuts on mouse button 4 and 5 for mouse with additional buttons.
3 |
4 | **[Download latest](https://github.com/Pullusb/MyKeyMouse/archive/refs/heads/master.zip)** (right click, save Target as)
5 |
6 | For older blender 2.7 version go [here](https://github.com/Pullusb/SB_blender_addons_old_2_7)
7 |
8 | If you want to support me, you can buy things on my [gumroad](https://pullusb.gumroad.com) or [blender market](https://blendermarket.com/creators/pullup) pages (other mean to support [here](http://www.samuelbernou.fr/donate)).
9 |
10 | --------
11 |
12 | ### Description
13 |
14 | Add '*view selection*' and '*view all*' shortcuts on mouse.
15 |
16 | Keymapp a list of shortcut for almost all editor where:
17 | - *mouse button 4* (often used as 'previous' action) is used to "get back", fit all elements in view. (like *home* button)
18 | - *mouse button 5* (often used as 'next' action) is used to "go to", focus on selected items. (like *numpad period* button)
19 |
20 | In the addons preferences you can choose to invert (button 4 to focus and button 5 to view all) :
21 |
22 | It does NOT affect any original shortcut on keyboard.
23 |
24 | Usual location of button 4 and 5 on a mouse with basic extra buttons (this may vary a lot on different device)
25 |
26 | 
27 |
28 |
29 | ### Why ?
30 | The location of *home* key and *numpad period* are far from both hands and force you to quit temporarily your rest positions, tending to break the workflow fluidity.
31 |
32 |
33 | ### Other added keymaps
34 |
35 | - *Ctrl + mouse button 5* Toggle isolate selection (*numpad slash* button)
36 |
37 |
38 | - *Shift + mouse button 4* Snap 3D cursor to selection
39 | - *Shift + mouse button 5* Snap selection to 3D cursor
40 |
41 |
42 | - *Alt + mouse button 4* Jump to previous keyframe
43 | - *Alt + mouse button 5* Jump to next keyframe
44 |
45 |
46 | - *Alt + Shift + mouse button 4* Jump to previous Marker
47 | - *Alt + Shift + mouse button 5* Jump to next Marker
48 |
49 |
50 | - *Ctrl + Shift + alt + mouse mouse button 4* Origin to geometry
51 | - *Ctrl + Shift + alt + mouse mouse button 5* Origin to cursor
52 |
53 |
54 |
58 |
59 | Thanks to [Vincent Lamy for the base idea](https://www.nothing-is-3d.com/article22/blender-utiliser-les-boutons-lateraux-de-la-souris)
60 |
--------------------------------------------------------------------------------
/__init__.py:
--------------------------------------------------------------------------------
1 | bl_info = {
2 | "name": "MyKeyMouse",
3 | "description": "Add 'view selected' and 'view all' actions to mouse buttons 4 and 5",
4 | "author": "Samuel Bernou",
5 | "version": (1, 3, 0),
6 | "blender": (2, 80, 0),
7 | "location": "Mouse button 4 (usually 'previous') and 5 (usually 'next') on almost all editors",
8 | "warning": "",
9 | "doc_url": "https://github.com/Pullusb/MyKeyMouse",
10 | "category": "Object" }
11 |
12 | import bpy
13 | import os
14 |
15 | #keymap focus view selected (numpad_period) to mouse button 4 on all related editors
16 | #keymap view all (home key) to mouse button 5 on all related editors
17 |
18 | #customisation
19 | #3D view only :
20 | # Button 4 can view center pick on mouse instead (really a mouse related shortcut)
21 | # Button 5 can do local view instead (already have shit+C accessible for view all)
22 |
23 |
24 | addon_keymaps = []
25 | def register_keymaps():
26 | preferences = bpy.context.preferences
27 | addon_prefs = preferences.addons[__name__].preferences
28 |
29 | #mouse 4 and 5 often correspond to previous and next on mouse device
30 | key_prev = "BUTTON4MOUSE"#prev
31 | key_next = "BUTTON5MOUSE"#next
32 |
33 | if addon_prefs.mkmouse_invert_focus == True:
34 | key_focus = "BUTTON4MOUSE"
35 | key_home = "BUTTON5MOUSE"
36 | else:#default
37 | key_focus = "BUTTON5MOUSE"
38 | key_home = "BUTTON4MOUSE"
39 |
40 | shortcuts_items = [
41 |
42 | ##button 4 - focus selection
43 | ["3D View", "VIEW_3D", "view3d.view_selected", key_focus],
44 | ["Graph Editor", "GRAPH_EDITOR", "graph.view_selected", key_focus],
45 | ["Dopesheet", 'DOPESHEET_EDITOR', "action.view_selected", key_focus],
46 | ["Sequencer", 'SEQUENCE_EDITOR', "sequencer.view_selected", key_focus],
47 | ["Node Editor", "NODE_EDITOR", "node.view_selected", key_focus],
48 | ["NLA Editor", "NLA_EDITOR", "nla.view_selected", key_focus],
49 | ["Clip Editor", "CLIP_EDITOR", "clip.view_selected", key_focus],
50 | ["Image", "IMAGE_EDITOR", "image.view_selected", key_focus],
51 | ["Outliner", "OUTLINER", "outliner.show_active", key_focus],
52 |
53 | ##button 5 - view all
54 | ["3D View", "VIEW_3D", "view3d.view_all", key_home],
55 | ["Graph Editor", "GRAPH_EDITOR", "graph.view_all", key_home],
56 | ["Image", "IMAGE_EDITOR", "image.view_all", key_home],
57 | ["Node Editor", "NODE_EDITOR", "node.view_all", key_home],
58 | ["Dopesheet", "DOPESHEET_EDITOR", "action.view_all", key_home],
59 | ["NLA Editor", "NLA_EDITOR", "nla.view_all", key_home],
60 | ["Sequencer", "SEQUENCE_EDITOR", "sequencer.view_all", key_home],
61 | ["SequencerPreview", "SEQUENCE_EDITOR", "sequencer.view_all_preview", key_home],
62 | ["Clip Editor", "CLIP_EDITOR", "clip.view_all", key_home],
63 | ["Clip Graph Editor", "CLIP_EDITOR", "clip.graph_view_all", key_home],
64 | ["Clip Dopesheet Editor", "CLIP_EDITOR", "clip.dopesheet_view_all", key_home],
65 |
66 | #not exists anymore in 2.8
67 | # ["Timeline", "TIMELINE", "time.view_all", key_home],
68 | #["Logic Editor", "LOGIC_EDITOR", "logic.view_all", key_home],
69 |
70 | ]
71 |
72 | shortcuts_items.append(["3D View", "VIEW_3D", "view3d.localview", key_next, True, False, False])
73 |
74 | # Snapping utility with shift (cursor to selection and selection to selected)
75 | shortcuts_items.append(["3D View", "VIEW_3D", "view3d.snap_cursor_to_selected", key_prev, False, True, False])
76 | shortcuts_items.append(["3D View", "VIEW_3D", "view3d.snap_selected_to_cursor", key_next, False, True, False])
77 |
78 | # Same with GPencil (that have a different operator)
79 | shortcuts_items.append(["Grease Pencil Stroke Edit Mode", "EMPTY", "gpencil.snap_cursor_to_selected", key_prev, False, True, False])
80 | shortcuts_items.append(["Grease Pencil Stroke Edit Mode", "EMPTY", "gpencil.snap_to_cursor", key_next, False, True, False])
81 |
82 |
83 | ## 2.79 : 3D view > keymap view center pick on mouse (Alt+F) Changed to 'alt + MMB' to match early 2.8 settings
84 | #if LooseVersion(str(bpy.app.version)) < LooseVersion('(2, 80, 0)'):#only set for 2.79
85 | # shortcuts_items.append(["3D View", "VIEW_3D", "view3d.view_center_pick", "MIDDLEMOUSE", False, False, True])
86 |
87 | ## appending all keymap from above list
88 | addon = bpy.context.window_manager.keyconfigs.addon
89 | for item in shortcuts_items:
90 | #print(item)# printing items for debug
91 | km = addon.keymaps.new(name = item[0], space_type = item[1])
92 | if len(item) > 4:#contain modifiers keys
93 | kmi = km.keymap_items.new(item[2], type = item[3], value = "PRESS", ctrl=item[4], shift=item[5],alt=item[6])
94 | else:
95 | kmi = km.keymap_items.new(item[2], type = item[3], value = "PRESS")
96 |
97 | # print(item[2],'-->', kmi)
98 | addon_keymaps.append((km, kmi))
99 |
100 | # Moving origin point utility, cursor/geometry. (hold properties)
101 | km = addon.keymaps.new(name = "3D View", space_type = "VIEW_3D")
102 | kmi = km.keymap_items.new("object.origin_set", type = key_next, value = "PRESS", ctrl = True, shift = True, alt = True)
103 | kmi.properties.type = 'ORIGIN_CURSOR'
104 | addon_keymaps.append((km, kmi))
105 |
106 | kmi = km.keymap_items.new("object.origin_set", type = key_prev, value = "PRESS", ctrl = True, shift = True, alt = True)
107 | kmi.properties.type = 'ORIGIN_GEOMETRY'
108 | addon_keymaps.append((km, kmi))
109 |
110 | # Combo keyframe jump with alt special case (hold properties). Button BUTTON6MOUSE et 7 not working with logitech software...
111 | km = addon.keymaps.new(name = "Window", space_type = "EMPTY")
112 | kmi = km.keymap_items.new("screen.keyframe_jump", type = key_prev, value = "PRESS", alt = True)
113 | kmi.properties.next = False
114 | addon_keymaps.append((km, kmi))
115 |
116 | kmi = km.keymap_items.new("screen.keyframe_jump", type = key_next, value = "PRESS", alt = True)
117 | kmi.properties.next = True
118 | addon_keymaps.append((km, kmi))
119 |
120 | ## jump to marker
121 | kmi = km.keymap_items.new("screen.marker_jump", type = key_prev, value = "PRESS", alt = True, shift = True)
122 | kmi.properties.next = False
123 | addon_keymaps.append((km, kmi))
124 |
125 | kmi = km.keymap_items.new("screen.marker_jump", type = key_next, value = "PRESS", alt = True, shift = True)
126 | kmi.properties.next = True
127 | addon_keymaps.append((km, kmi))
128 |
129 | ###---user pref
130 |
131 | class My_key_mouse_addon_pref(bpy.types.AddonPreferences):
132 | bl_idname = __name__
133 |
134 | mkmouse_invert_focus : bpy.props.BoolProperty(
135 | name="Invert (prev button = view selected, next button = view all. (Save prefs and restart Blender to apply changes)",
136 | default=False,
137 | )
138 | '''
139 | mkmouse_viewport_local_view : bpy.props.BoolProperty(
140 | name="Use local view (instead of view all)",
141 | default=False,
142 | )#"Use local view (like numpad slash) instead of view all (else combine ctrl)"
143 | mkmouse_viewport_center_on_mouse : bpy.props.BoolProperty(
144 | name="Use centering view on mouse (instead of view selected)",
145 | default=False,
146 | )#"Use centering view on mouse (like Alt+F) instead of view selected (else combine ctrl)"
147 | '''
148 |
149 | def draw(self, context):
150 | layout = self.layout
151 | box = layout.box()
152 |
153 | box.label(
154 | text="Focus control (all editor) :")
155 | box.label(
156 | text="mouse Prev button = view all")
157 | box.label(
158 | text="mouse Next button = view selected")
159 | # box.label(text="Customization ")
160 | box.prop(self, "mkmouse_invert_focus")
161 |
162 |
163 | box = layout.box()
164 | box.label(text="Only in 3D viewport:")
165 | box.label(text="Ctrl + mouse Next button = Use local view (like numpad slash)")
166 | #box.label(text="Ctrl + mouse Prev button = Unnassigned")
167 | # layout.separator()
168 | box.label(text="Cursor Snapping:")
169 | box.label(text="Shift + mouse Prev button = 3D cursor to selection")
170 | box.label(text="Shift + mouse Next button = selection to 3D cursor")
171 | # layout.separator()
172 | box.label(text="Origin change:")
173 | box.label(text="Ctrl + Shift + alt + mouse Prev button = Origin to geometry")
174 | box.label(text="Ctrl + Shift + alt + mouse Next button = Origin to cursor")
175 |
176 | # layout.label(text="Alt + middle mouse button = centering view on mouse (default shortcut in 2.8) as with Alt+F ")
177 |
178 | box = layout.box()
179 | box.label(text="Timeline related (all editor):")
180 | box.label(text="Alt + mouse Prev button = jump to prev keyframe")
181 | box.label(text="Alt + mouse Next button = jump to next keyframe")
182 |
183 | box.label(text="Alt + Shift + mouse Prev button = jump to prev marker")
184 | box.label(text="Alt + Shift + mouse Next button = jump to next marker")
185 |
186 | '''
187 | layout.label(
188 | text="Options to swap calls in 3D viewport (accessible with 'ctrl' modifier):")
189 | layout.prop(self, "mkmouse_viewport_center_on_mouse")
190 | layout.prop(self, "mkmouse_viewport_local_view")
191 | '''
192 |
193 | def unregister_keymaps():
194 | # wm = bpy.context.window_manager
195 | for km, kmi in addon_keymaps:
196 | km.keymap_items.remove(kmi)
197 | addon_keymaps.clear()
198 |
199 |
200 | ## note : register via bpy.utils.register_module(__name__) Fails !
201 | ## addons prefs isn't loaded when keymap_register try to access it.
202 |
203 | def register():
204 | if bpy.app.background:
205 | return
206 | bpy.utils.register_class(My_key_mouse_addon_pref)
207 | register_keymaps()
208 |
209 | def unregister():
210 | if bpy.app.background:
211 | return
212 | unregister_keymaps()
213 | bpy.utils.unregister_class(My_key_mouse_addon_pref)
214 |
215 | if __name__ == "__main__":
216 | register()
217 |
--------------------------------------------------------------------------------