Blender V4.3
wm_keymap_utils.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2023 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
11#include <cstring>
12
13#include "DNA_object_types.h"
14#include "DNA_space_types.h"
15#include "DNA_userdef_types.h"
17
18#include "BLI_listbase.h"
19#include "BLI_utildefines.h"
20
21#include "BKE_context.hh"
22
23#include "RNA_access.hh"
24
25#include "WM_api.hh"
26#include "WM_types.hh"
27
28/* Menu wrapper for #WM_keymap_add_item. */
29
30/* -------------------------------------------------------------------- */
35 const char *idname,
37{
38 wmKeyMapItem *kmi = WM_keymap_add_item(keymap, "WM_OT_call_menu", params);
39 RNA_string_set(kmi->ptr, "name", idname);
40 return kmi;
41}
42
44 const char *idname,
46{
47 wmKeyMapItem *kmi = WM_keymap_add_item(keymap, "WM_OT_call_menu_pie", params);
48 RNA_string_set(kmi->ptr, "name", idname);
49 return kmi;
50}
51
53 const char *idname,
55{
56 wmKeyMapItem *kmi = WM_keymap_add_item(keymap, "WM_OT_call_panel", params);
57 RNA_string_set(kmi->ptr, "name", idname);
58 /* TODO: we might want to disable this. */
59 RNA_boolean_set(kmi->ptr, "keep_open", false);
60 return kmi;
61}
62
64 const char *idname,
66{
67 wmKeyMapItem *kmi = WM_keymap_add_item(keymap, "WM_OT_tool_set_by_id", params);
68 RNA_string_set(kmi->ptr, "name", idname);
69 return kmi;
70}
71
74/* -------------------------------------------------------------------- */
79{
80 eSpace_Type space_type = SPACE_EMPTY;
81 eRegion_Type region_type = RGN_TYPE_WINDOW;
83 const char *km_id = nullptr;
84 if (sl->spacetype == SPACE_VIEW3D) {
85 const enum eContextObjectMode mode = CTX_data_mode_enum(C);
86 switch (mode) {
88 km_id = "Mesh";
89 break;
91 km_id = "Curve";
92 break;
94 km_id = "Curves";
95 break;
97 km_id = "Curve";
98 break;
100 km_id = "Font";
101 break;
103 km_id = "Armature";
104 break;
106 km_id = "Metaball";
107 break;
109 km_id = "Lattice";
110 break;
112 km_id = "Grease Pencil Edit Mode";
113 break;
115 km_id = "Point Cloud Edit Mode";
116 break;
117 case CTX_MODE_POSE:
118 km_id = "Pose";
119 break;
120 case CTX_MODE_SCULPT:
121 km_id = "Sculpt";
122 break;
124 km_id = "Weight Paint";
125 break;
127 km_id = "Vertex Paint";
128 break;
130 km_id = "Image Paint";
131 break;
133 km_id = "Particle";
134 break;
135 case CTX_MODE_OBJECT:
136 km_id = "Object Mode";
137 break;
139 km_id = "Grease Pencil Stroke Paint Mode";
140 break;
142 km_id = "Grease Pencil Stroke Edit Mode";
143 break;
145 km_id = "Grease Pencil Stroke Sculpt Mode";
146 break;
148 km_id = "Grease Pencil Stroke Weight Mode";
149 break;
151 km_id = "Grease Pencil Stroke Vertex Mode";
152 break;
154 km_id = "Sculpt Curves";
155 break;
157 km_id = "Grease Pencil Paint Mode";
158 break;
160 km_id = "Grease Pencil Sculpt Mode";
161 break;
163 km_id = "Grease Pencil Weight Mode";
164 break;
166 km_id = "Grease Pencil Vertex Mode";
167 break;
168 }
169 }
170 else if (sl->spacetype == SPACE_IMAGE) {
171 const SpaceImage *sima = (SpaceImage *)sl;
172 const eSpaceImage_Mode mode = eSpaceImage_Mode(sima->mode);
173 switch (mode) {
174 case SI_MODE_VIEW:
175 km_id = "Image";
176 break;
177 case SI_MODE_PAINT:
178 km_id = "Image Paint";
179 break;
180 case SI_MODE_MASK:
181 km_id = "Mask Editing";
182 break;
183 case SI_MODE_UV:
184 km_id = "UV Editor";
185 break;
186 }
187 }
188 else if (sl->spacetype == SPACE_SEQ) {
189 const SpaceSeq *sseq = (SpaceSeq *)sl;
190 const enum eSpaceSeq_Displays view = eSpaceSeq_Displays(sseq->view);
191 space_type = SPACE_SEQ;
192 switch (view) {
194 km_id = "Sequencer";
195 break;
196 case SEQ_VIEW_PREVIEW:
197 km_id = "SequencerPreview";
198 break;
200 km_id = "SequencerCommon";
201 break;
202 }
203 }
204 else {
205 return nullptr;
206 }
207
208 wmKeyMap *km = WM_keymap_find_all(CTX_wm_manager(C), km_id, space_type, region_type);
209 BLI_assert(km);
210 return km;
211}
212
213wmKeyMap *WM_keymap_guess_opname(const bContext *C, const char *opname)
214{
215 /* Op types purposely skipped for now:
216 * BOID_OT
217 * BUTTONS_OT
218 * CONSTRAINT_OT
219 * ED_OT
220 * FLUID_OT
221 * TEXTURE_OT
222 * WORLD_OT
223 */
224
225 wmKeyMap *km = nullptr;
228
229 /* Window. */
230 if (STRPREFIX(opname, "WM_OT") || STRPREFIX(opname, "ED_OT_undo")) {
231 if (STREQ(opname, "WM_OT_tool_set_by_id") || STREQ(opname, "WM_OT_call_asset_shelf_popover")) {
233 }
234
235 if (km == nullptr) {
237 }
238 }
239 /* Screen & Render. */
240 else if (STRPREFIX(opname, "SCREEN_OT") || STRPREFIX(opname, "RENDER_OT") ||
241 STRPREFIX(opname, "SOUND_OT") || STRPREFIX(opname, "SCENE_OT"))
242 {
244 }
245 /* Grease Pencil. */
246 else if (STRPREFIX(opname, "GPENCIL_OT")) {
247 km = WM_keymap_find_all(wm, "Grease Pencil", SPACE_EMPTY, RGN_TYPE_WINDOW);
248 }
249 else if (STRPREFIX(opname, "GREASE_PENCIL_OT")) {
250 km = WM_keymap_find_all(wm, "Grease Pencil", SPACE_EMPTY, RGN_TYPE_WINDOW);
251 }
252 /* Markers. */
253 else if (STRPREFIX(opname, "MARKER_OT")) {
254 km = WM_keymap_find_all(wm, "Markers", SPACE_EMPTY, RGN_TYPE_WINDOW);
255 }
256 /* Import/Export. */
257 else if (STRPREFIX(opname, "IMPORT_") || STRPREFIX(opname, "EXPORT_")) {
259 }
260
261 /* 3D View. */
262 else if (STRPREFIX(opname, "VIEW3D_OT")) {
263 km = WM_keymap_find_all(wm, "3D View", sl->spacetype, RGN_TYPE_WINDOW);
264 }
265 else if (STRPREFIX(opname, "OBJECT_OT")) {
266 /* Exception, this needs to work outside object mode too. */
267 if (STRPREFIX(opname, "OBJECT_OT_mode_set")) {
268 km = WM_keymap_find_all(wm, "Object Non-modal", SPACE_EMPTY, RGN_TYPE_WINDOW);
269 }
270 else {
271 km = WM_keymap_find_all(wm, "Object Mode", SPACE_EMPTY, RGN_TYPE_WINDOW);
272 }
273 }
274 /* Object mode related. */
275 else if (STRPREFIX(opname, "GROUP_OT") || STRPREFIX(opname, "MATERIAL_OT") ||
276 STRPREFIX(opname, "PTCACHE_OT") || STRPREFIX(opname, "RIGIDBODY_OT"))
277 {
278 km = WM_keymap_find_all(wm, "Object Mode", SPACE_EMPTY, RGN_TYPE_WINDOW);
279 }
280
281 /* Editing Modes. */
282 else if (STRPREFIX(opname, "MESH_OT")) {
284
285 /* Some mesh operators are active in object mode too, like add-prim. */
286 if (km && !WM_keymap_poll((bContext *)C, km)) {
287 km = WM_keymap_find_all(wm, "Object Mode", SPACE_EMPTY, RGN_TYPE_WINDOW);
288 }
289 }
290 else if (STRPREFIX(opname, "CURVE_OT") || STRPREFIX(opname, "SURFACE_OT")) {
292
293 /* Some curve operators are active in object mode too, like add-prim. */
294 if (km && !WM_keymap_poll((bContext *)C, km)) {
295 km = WM_keymap_find_all(wm, "Object Mode", SPACE_EMPTY, RGN_TYPE_WINDOW);
296 }
297 }
298 else if (STRPREFIX(opname, "ARMATURE_OT") || STRPREFIX(opname, "SKETCH_OT")) {
299 km = WM_keymap_find_all(wm, "Armature", SPACE_EMPTY, RGN_TYPE_WINDOW);
300 }
301 else if (STRPREFIX(opname, "POSE_OT") || STRPREFIX(opname, "POSELIB_OT")) {
303 }
304 else if (STRPREFIX(opname, "SCULPT_OT")) {
305 switch (CTX_data_mode_enum(C)) {
306 case CTX_MODE_SCULPT:
308 break;
309 default:
310 break;
311 }
312 }
313 else if (STRPREFIX(opname, "CURVES_OT")) {
315 }
316 else if (STRPREFIX(opname, "SCULPT_CURVES_OT")) {
317 km = WM_keymap_find_all(wm, "Sculpt Curves", SPACE_EMPTY, RGN_TYPE_WINDOW);
318 }
319 else if (STRPREFIX(opname, "MBALL_OT")) {
320 km = WM_keymap_find_all(wm, "Metaball", SPACE_EMPTY, RGN_TYPE_WINDOW);
321
322 /* Some meta-ball operators are active in object mode too, like add-primitive. */
323 if (km && !WM_keymap_poll((bContext *)C, km)) {
324 km = WM_keymap_find_all(wm, "Object Mode", SPACE_EMPTY, RGN_TYPE_WINDOW);
325 }
326 }
327 else if (STRPREFIX(opname, "LATTICE_OT")) {
328 km = WM_keymap_find_all(wm, "Lattice", SPACE_EMPTY, RGN_TYPE_WINDOW);
329 }
330 else if (STRPREFIX(opname, "PARTICLE_OT")) {
331 km = WM_keymap_find_all(wm, "Particle", SPACE_EMPTY, RGN_TYPE_WINDOW);
332 }
333 else if (STRPREFIX(opname, "FONT_OT")) {
335 }
336 /* Paint Face Mask. */
337 else if (STRPREFIX(opname, "PAINT_OT_face_select")) {
339 wm, "Paint Face Mask (Weight, Vertex, Texture)", SPACE_EMPTY, RGN_TYPE_WINDOW);
340 }
341 else if (STRPREFIX(opname, "PAINT_OT") || STRPREFIX(opname, "BRUSH_OT")) {
342 /* Check for relevant mode. */
344 }
345 /* General 2D View, not bound to a specific spacetype. */
346 else if (STRPREFIX(opname, "VIEW2D_OT")) {
348 }
349 /* Image Editor. */
350 else if (STRPREFIX(opname, "IMAGE_OT")) {
351 km = WM_keymap_find_all(wm, "Image", sl->spacetype, RGN_TYPE_WINDOW);
352 }
353 /* Clip Editor. */
354 else if (STRPREFIX(opname, "CLIP_OT")) {
355 km = WM_keymap_find_all(wm, "Clip", sl->spacetype, RGN_TYPE_WINDOW);
356 }
357 else if (STRPREFIX(opname, "MASK_OT")) {
358 km = WM_keymap_find_all(wm, "Mask Editing", SPACE_EMPTY, RGN_TYPE_WINDOW);
359 }
360 /* UV Editor. */
361 else if (STRPREFIX(opname, "UV_OT")) {
362 /* Hack to allow using UV unwrapping ops from 3DView/editmode.
363 * Mesh keymap is probably not ideal, but best place I could find to put those. */
364 if (sl->spacetype == SPACE_VIEW3D) {
366 if (km && !WM_keymap_poll((bContext *)C, km)) {
367 km = nullptr;
368 }
369 }
370 if (!km) {
371 km = WM_keymap_find_all(wm, "UV Editor", SPACE_EMPTY, RGN_TYPE_WINDOW);
372 }
373 }
374 /* Node Editor. */
375 else if (STRPREFIX(opname, "NODE_OT")) {
376 km = WM_keymap_find_all(wm, "Node Editor", sl->spacetype, RGN_TYPE_WINDOW);
377 }
378 /* Animation Editor Channels. */
379 else if (STRPREFIX(opname, "ANIM_OT_channels")) {
380 km = WM_keymap_find_all(wm, "Animation Channels", SPACE_EMPTY, RGN_TYPE_WINDOW);
381 }
382 /* Animation Generic - after channels. */
383 else if (STRPREFIX(opname, "ANIM_OT")) {
384 if (sl->spacetype == SPACE_VIEW3D) {
385 switch (CTX_data_mode_enum(C)) {
386 case CTX_MODE_OBJECT:
387 km = WM_keymap_find_all(wm, "Object Mode", SPACE_EMPTY, RGN_TYPE_WINDOW);
388 break;
389 case CTX_MODE_POSE:
391 break;
392 default:
393 break;
394 }
395 if (km && !WM_keymap_poll((bContext *)C, km)) {
396 km = nullptr;
397 }
398 }
399
400 if (!km) {
401 km = WM_keymap_find_all(wm, "Animation", SPACE_EMPTY, RGN_TYPE_WINDOW);
402 }
403 }
404 /* Graph Editor. */
405 else if (STRPREFIX(opname, "GRAPH_OT")) {
406 km = WM_keymap_find_all(wm, "Graph Editor", sl->spacetype, RGN_TYPE_WINDOW);
407 }
408 /* Dopesheet Editor. */
409 else if (STRPREFIX(opname, "ACTION_OT")) {
410 km = WM_keymap_find_all(wm, "Dopesheet", sl->spacetype, RGN_TYPE_WINDOW);
411 }
412 /* NLA Editor. */
413 else if (STRPREFIX(opname, "NLA_OT")) {
414 km = WM_keymap_find_all(wm, "NLA Editor", sl->spacetype, RGN_TYPE_WINDOW);
415 }
416 /* Script. */
417 else if (STRPREFIX(opname, "SCRIPT_OT")) {
418 km = WM_keymap_find_all(wm, "Script", sl->spacetype, RGN_TYPE_WINDOW);
419 }
420 /* Text. */
421 else if (STRPREFIX(opname, "TEXT_OT")) {
422 km = WM_keymap_find_all(wm, "Text", sl->spacetype, RGN_TYPE_WINDOW);
423 }
424 /* Sequencer. */
425 else if (STRPREFIX(opname, "SEQUENCER_OT")) {
426 km = WM_keymap_find_all(wm, "Sequencer", sl->spacetype, RGN_TYPE_WINDOW);
427 }
428 /* Console. */
429 else if (STRPREFIX(opname, "CONSOLE_OT")) {
430 km = WM_keymap_find_all(wm, "Console", sl->spacetype, RGN_TYPE_WINDOW);
431 }
432 /* Console. */
433 else if (STRPREFIX(opname, "INFO_OT")) {
434 km = WM_keymap_find_all(wm, "Info", sl->spacetype, RGN_TYPE_WINDOW);
435 }
436 /* File browser. */
437 else if (STRPREFIX(opname, "FILE_OT")) {
438 km = WM_keymap_find_all(wm, "File Browser", sl->spacetype, RGN_TYPE_WINDOW);
439 }
440 /* Logic Editor. */
441 else if (STRPREFIX(opname, "LOGIC_OT")) {
442 km = WM_keymap_find_all(wm, "Logic Editor", sl->spacetype, RGN_TYPE_WINDOW);
443 }
444 /* Outliner. */
445 else if (STRPREFIX(opname, "OUTLINER_OT")) {
446 km = WM_keymap_find_all(wm, "Outliner", sl->spacetype, RGN_TYPE_WINDOW);
447 }
448 /* Transform. */
449 else if (STRPREFIX(opname, "TRANSFORM_OT")) {
450 /* Check for relevant editor. */
451 switch (sl->spacetype) {
452 case SPACE_VIEW3D:
453 km = WM_keymap_find_all(wm, "3D View", sl->spacetype, RGN_TYPE_WINDOW);
454 break;
455 case SPACE_GRAPH:
456 km = WM_keymap_find_all(wm, "Graph Editor", sl->spacetype, RGN_TYPE_WINDOW);
457 break;
458 case SPACE_ACTION:
459 km = WM_keymap_find_all(wm, "Dopesheet", sl->spacetype, RGN_TYPE_WINDOW);
460 break;
461 case SPACE_NLA:
462 km = WM_keymap_find_all(wm, "NLA Editor", sl->spacetype, RGN_TYPE_WINDOW);
463 break;
464 case SPACE_IMAGE:
465 km = WM_keymap_find_all(wm, "UV Editor", SPACE_EMPTY, RGN_TYPE_WINDOW);
466 break;
467 case SPACE_NODE:
468 km = WM_keymap_find_all(wm, "Node Editor", sl->spacetype, RGN_TYPE_WINDOW);
469 break;
470 case SPACE_SEQ:
471 km = WM_keymap_find_all(wm, "Sequencer", sl->spacetype, RGN_TYPE_WINDOW);
472 break;
473 }
474 }
475 /* User Interface. */
476 else if (STRPREFIX(opname, "UI_OT")) {
477 km = WM_keymap_find_all(wm, "User Interface", SPACE_EMPTY, RGN_TYPE_WINDOW);
478 }
479 /* Geometry. */
480 else if (STRPREFIX(opname, "GEOMETRY_OT")) {
481 switch (sl->spacetype) {
482 case SPACE_VIEW3D:
483 switch (CTX_data_mode_enum(C)) {
486 break;
489 break;
491 km = WM_keymap_find_all(wm, "Point Cloud Edit Mode", SPACE_EMPTY, RGN_TYPE_WINDOW);
492 break;
493 case CTX_MODE_SCULPT:
495 break;
497 km = WM_keymap_find_all(wm, "Sculpt Curves", SPACE_EMPTY, RGN_TYPE_WINDOW);
498 break;
499 default:
500 break;
501 }
502 break;
503 }
504 }
505
506 return km;
507}
508
509static bool wm_keymap_item_uses_modifier(const wmKeyMapItem *kmi, const int event_modifier)
510{
511 if (kmi->ctrl != KM_ANY) {
512 if ((kmi->ctrl == KM_NOTHING) != ((event_modifier & KM_CTRL) == 0)) {
513 return false;
514 }
515 }
516
517 if (kmi->alt != KM_ANY) {
518 if ((kmi->alt == KM_NOTHING) != ((event_modifier & KM_ALT) == 0)) {
519 return false;
520 }
521 }
522
523 if (kmi->shift != KM_ANY) {
524 if ((kmi->shift == KM_NOTHING) != ((event_modifier & KM_SHIFT) == 0)) {
525 return false;
526 }
527 }
528
529 if (kmi->oskey != KM_ANY) {
530 if ((kmi->oskey == KM_NOTHING) != ((event_modifier & KM_OSKEY) == 0)) {
531 return false;
532 }
533 }
534 return true;
535}
536
537bool WM_keymap_uses_event_modifier(const wmKeyMap *keymap, const int event_modifier)
538{
539 LISTBASE_FOREACH (const wmKeyMapItem *, kmi, &keymap->items) {
540 if ((kmi->flag & KMI_INACTIVE) == 0) {
541 if (wm_keymap_item_uses_modifier(kmi, event_modifier)) {
542 return true;
543 }
544 }
545 }
546 return false;
547}
548
550
eContextObjectMode
@ CTX_MODE_VERTEX_GPENCIL_LEGACY
@ CTX_MODE_WEIGHT_GPENCIL_LEGACY
@ CTX_MODE_EDIT_POINT_CLOUD
@ CTX_MODE_SCULPT_GPENCIL_LEGACY
@ CTX_MODE_PAINT_GREASE_PENCIL
@ CTX_MODE_PAINT_GPENCIL_LEGACY
@ CTX_MODE_EDIT_CURVE
@ CTX_MODE_PAINT_TEXTURE
@ CTX_MODE_EDIT_SURFACE
@ CTX_MODE_SCULPT_GREASE_PENCIL
@ CTX_MODE_PARTICLE
@ CTX_MODE_SCULPT
@ CTX_MODE_OBJECT
@ CTX_MODE_EDIT_MESH
@ CTX_MODE_EDIT_GREASE_PENCIL
@ CTX_MODE_SCULPT_CURVES
@ CTX_MODE_EDIT_TEXT
@ CTX_MODE_EDIT_CURVES
@ CTX_MODE_EDIT_ARMATURE
@ CTX_MODE_EDIT_LATTICE
@ CTX_MODE_WEIGHT_GREASE_PENCIL
@ CTX_MODE_VERTEX_GREASE_PENCIL
@ CTX_MODE_PAINT_VERTEX
@ CTX_MODE_EDIT_METABALL
@ CTX_MODE_PAINT_WEIGHT
@ CTX_MODE_EDIT_GPENCIL_LEGACY
@ CTX_MODE_POSE
SpaceLink * CTX_wm_space_data(const bContext *C)
wmWindowManager * CTX_wm_manager(const bContext *C)
enum eContextObjectMode CTX_data_mode_enum(const bContext *C)
#define BLI_assert(a)
Definition BLI_assert.h:50
#define LISTBASE_FOREACH(type, var, list)
#define STRPREFIX(a, b)
#define STREQ(a, b)
Object is a sort of wrapper for general info.
eRegion_Type
@ RGN_TYPE_WINDOW
eSpace_Type
@ SPACE_ACTION
@ SPACE_NODE
@ SPACE_NLA
@ SPACE_SEQ
@ SPACE_EMPTY
@ SPACE_IMAGE
@ SPACE_GRAPH
@ SPACE_VIEW3D
eSpaceSeq_Displays
@ SEQ_VIEW_SEQUENCE_PREVIEW
@ SEQ_VIEW_SEQUENCE
@ SEQ_VIEW_PREVIEW
eSpaceImage_Mode
@ SI_MODE_PAINT
@ SI_MODE_VIEW
@ SI_MODE_MASK
@ SI_MODE_UV
@ KM_NOTHING
Definition WM_types.hh:283
@ KM_ANY
Definition WM_types.hh:282
@ KM_CTRL
Definition WM_types.hh:256
@ KM_ALT
Definition WM_types.hh:257
@ KM_OSKEY
Definition WM_types.hh:259
@ KM_SHIFT
Definition WM_types.hh:255
uiWidgetBaseParameters params[MAX_WIDGET_BASE_BATCH]
void RNA_string_set(PointerRNA *ptr, const char *name, const char *value)
void RNA_boolean_set(PointerRNA *ptr, const char *name, bool value)
struct PointerRNA * ptr
wmKeyMap * WM_keymap_find_all(wmWindowManager *wm, const char *idname, int spaceid, int regionid)
Definition wm_keymap.cc:911
bool WM_keymap_poll(bContext *C, wmKeyMap *keymap)
Definition wm_keymap.cc:469
wmKeyMapItem * WM_keymap_add_item(wmKeyMap *keymap, const char *idname, const KeyMapItem_Params *params)
Definition wm_keymap.cc:546
wmKeyMapItem * WM_keymap_add_panel(wmKeyMap *keymap, const char *idname, const KeyMapItem_Params *params)
wmKeyMap * WM_keymap_guess_from_context(const bContext *C)
wmKeyMapItem * WM_keymap_add_menu(wmKeyMap *keymap, const char *idname, const KeyMapItem_Params *params)
wmKeyMapItem * WM_keymap_add_menu_pie(wmKeyMap *keymap, const char *idname, const KeyMapItem_Params *params)
bool WM_keymap_uses_event_modifier(const wmKeyMap *keymap, const int event_modifier)
void WM_keymap_fix_linking()
static bool wm_keymap_item_uses_modifier(const wmKeyMapItem *kmi, const int event_modifier)
wmKeyMap * WM_keymap_guess_opname(const bContext *C, const char *opname)
wmKeyMapItem * WM_keymap_add_tool(wmKeyMap *keymap, const char *idname, const KeyMapItem_Params *params)