Blender  V3.3
wm_toolsystem.c
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-or-later */
2 
9 #include <string.h>
10 
11 #include "CLG_log.h"
12 
13 #include "MEM_guardedalloc.h"
14 
15 #include "BLI_listbase.h"
16 #include "BLI_string.h"
17 #include "BLI_utildefines.h"
18 
19 #include "DNA_ID.h"
20 #include "DNA_object_types.h"
21 #include "DNA_scene_types.h"
22 #include "DNA_space_types.h"
24 #include "DNA_workspace_types.h"
25 
26 #include "BKE_brush.h"
27 #include "BKE_context.h"
28 #include "BKE_idprop.h"
29 #include "BKE_lib_id.h"
30 #include "BKE_main.h"
31 #include "BKE_paint.h"
32 #include "BKE_workspace.h"
33 
34 #include "RNA_access.h"
35 #include "RNA_enum_types.h"
36 
37 #include "WM_api.h"
38 #include "WM_message.h"
39 #include "WM_toolsystem.h" /* own include */
40 #include "WM_types.h"
41 
43  WorkSpace *UNUSED(workspace),
44  bToolRef *tref);
46  WorkSpace *workspace,
47  const bToolKey *tkey,
48  const char *default_tool);
50  WorkSpace *workspace,
51  bToolRef *tref);
52 
53 /* -------------------------------------------------------------------- */
58 {
59  WorkSpace *workspace = CTX_wm_workspace(C);
60  ViewLayer *view_layer = CTX_data_view_layer(C);
62  if ((area == NULL) || ((1 << area->spacetype) & WM_TOOLSYSTEM_SPACE_MASK) == 0) {
63  return NULL;
64  }
65  const bToolKey tkey = {
66  .space_type = area->spacetype,
67  .mode = WM_toolsystem_mode_from_spacetype(view_layer, area, area->spacetype),
68  };
69  bToolRef *tref = WM_toolsystem_ref_find(workspace, &tkey);
70  /* We could return 'area->runtime.tool' in this case. */
71  if (area->runtime.is_tool_set) {
72  BLI_assert(tref == area->runtime.tool);
73  }
74  return tref;
75 }
76 
78 {
80  return tref ? tref->runtime : NULL;
81 }
82 
84 {
86  LISTBASE_FOREACH (bToolRef *, tref, &workspace->tools) {
87  if ((tref->space_type == tkey->space_type) && (tref->mode == tkey->mode)) {
88  return tref;
89  }
90  }
91  return NULL;
92 }
93 
95 {
96  bToolRef *tref = WM_toolsystem_ref_find(workspace, tkey);
97  return tref ? tref->runtime : NULL;
98 }
99 
100 bool WM_toolsystem_ref_ensure(struct WorkSpace *workspace, const bToolKey *tkey, bToolRef **r_tref)
101 {
102  bToolRef *tref = WM_toolsystem_ref_find(workspace, tkey);
103  if (tref) {
104  *r_tref = tref;
105  return false;
106  }
107  tref = MEM_callocN(sizeof(*tref), __func__);
108  BLI_addhead(&workspace->tools, tref);
109  tref->space_type = tkey->space_type;
110  tref->mode = tkey->mode;
111  *r_tref = tref;
112  return true;
113 }
114 
117 static void toolsystem_unlink_ref(bContext *C, WorkSpace *UNUSED(workspace), bToolRef *tref)
118 {
119  bToolRef_Runtime *tref_rt = tref->runtime;
120 
121  if (tref_rt->gizmo_group[0]) {
122  wmGizmoGroupType *gzgt = WM_gizmogrouptype_find(tref_rt->gizmo_group, false);
123  if (gzgt != NULL) {
124  Main *bmain = CTX_data_main(C);
125  WM_gizmo_group_remove_by_tool(C, bmain, gzgt, tref);
126  }
127  }
128 }
129 void WM_toolsystem_unlink(bContext *C, WorkSpace *workspace, const bToolKey *tkey)
130 {
131  bToolRef *tref = WM_toolsystem_ref_find(workspace, tkey);
132  if (tref && tref->runtime) {
133  toolsystem_unlink_ref(C, workspace, tref);
134  }
135 }
136 
137 static void toolsystem_ref_link(bContext *C, WorkSpace *workspace, bToolRef *tref)
138 {
139  bToolRef_Runtime *tref_rt = tref->runtime;
140  if (tref_rt->gizmo_group[0]) {
141  const char *idname = tref_rt->gizmo_group;
142  wmGizmoGroupType *gzgt = WM_gizmogrouptype_find(idname, false);
143  if (gzgt != NULL) {
144  if ((gzgt->flag & WM_GIZMOGROUPTYPE_TOOL_INIT) == 0) {
145  if (!WM_gizmo_group_type_ensure_ptr(gzgt)) {
146  /* Even if the group-type was has been linked, it's possible the space types
147  * were not previously using it. (happens with multiple windows.) */
148  wmGizmoMapType *gzmap_type = WM_gizmomaptype_ensure(&gzgt->gzmap_params);
150  }
151  }
152  }
153  else {
154  CLOG_WARN(WM_LOG_TOOLS, "'%s' widget not found", idname);
155  }
156  }
157 
158  if (tref_rt->data_block[0]) {
159  Main *bmain = CTX_data_main(C);
160 
161  if ((tref->space_type == SPACE_VIEW3D) && (tref->mode == CTX_MODE_PARTICLE)) {
163  const int i = RNA_enum_from_identifier(items, tref_rt->data_block);
164  if (i != -1) {
165  const int value = items[i].value;
166  wmWindowManager *wm = bmain->wm.first;
167  LISTBASE_FOREACH (wmWindow *, win, &wm->windows) {
168  if (workspace == WM_window_get_active_workspace(win)) {
171  ts->particle.brushtype = value;
172  }
173  }
174  }
175  }
176  else {
177  const ePaintMode paint_mode = BKE_paintmode_get_from_tool(tref);
178  BLI_assert(paint_mode != PAINT_MODE_INVALID);
179  const EnumPropertyItem *items = BKE_paint_get_tool_enum_from_paintmode(paint_mode);
180  BLI_assert(items != NULL);
181 
182  const int i = items ? RNA_enum_from_identifier(items, tref_rt->data_block) : -1;
183  if (i != -1) {
184  const int slot_index = items[i].value;
185  wmWindowManager *wm = bmain->wm.first;
186  LISTBASE_FOREACH (wmWindow *, win, &wm->windows) {
187  if (workspace == WM_window_get_active_workspace(win)) {
190  Paint *paint = BKE_paint_get_active_from_paintmode(scene, paint_mode);
191  struct Brush *brush = BKE_paint_toolslots_brush_get(paint, slot_index);
192  if (brush == NULL) {
193  /* Could make into a function. */
194  brush = (struct Brush *)BKE_libblock_find_name(bmain, ID_BR, items[i].name);
195  if (brush && slot_index == BKE_brush_tool_get(brush, paint)) {
196  /* pass */
197  }
198  else {
199  brush = BKE_brush_add(bmain, items[i].name, paint->runtime.ob_mode);
200 
201  BKE_brush_tool_set(brush, paint, slot_index);
202 
203  if (paint_mode == PAINT_MODE_SCULPT) {
204  BKE_brush_sculpt_reset(brush);
205  }
206  }
207  BKE_paint_brush_set(paint, brush);
208  }
209  BKE_paint_brush_set(paint, brush);
210  }
211  }
212  }
213  }
214  }
215 }
216 
217 static void toolsystem_refresh_ref(bContext *C, WorkSpace *workspace, bToolRef *tref)
218 {
219  if (tref->runtime == NULL) {
220  return;
221  }
222  /* currently same operation. */
223  toolsystem_ref_link(C, workspace, tref);
224 }
225 void WM_toolsystem_refresh(bContext *C, WorkSpace *workspace, const bToolKey *tkey)
226 {
227  bToolRef *tref = WM_toolsystem_ref_find(workspace, tkey);
228  if (tref) {
229  toolsystem_refresh_ref(C, workspace, tref);
230  }
231 }
232 
233 static void toolsystem_reinit_ref(bContext *C, WorkSpace *workspace, bToolRef *tref)
234 {
235  toolsystem_reinit_with_toolref(C, workspace, tref);
236 }
237 void WM_toolsystem_reinit(bContext *C, WorkSpace *workspace, const bToolKey *tkey)
238 {
239  bToolRef *tref = WM_toolsystem_ref_find(workspace, tkey);
240  if (tref) {
241  toolsystem_reinit_ref(C, workspace, tref);
242  }
243 }
244 
245 void WM_toolsystem_unlink_all(struct bContext *C, struct WorkSpace *workspace)
246 {
247  LISTBASE_FOREACH (bToolRef *, tref, &workspace->tools) {
248  tref->tag = 0;
249  }
250 
251  LISTBASE_FOREACH (bToolRef *, tref, &workspace->tools) {
252  if (tref->runtime) {
253  if (tref->tag == 0) {
254  toolsystem_unlink_ref(C, workspace, tref);
255  tref->tag = 1;
256  }
257  }
258  }
259 }
260 
261 void WM_toolsystem_refresh_all(struct bContext *C, struct WorkSpace *workspace)
262 {
263  BLI_assert(0);
264  LISTBASE_FOREACH (bToolRef *, tref, &workspace->tools) {
265  toolsystem_refresh_ref(C, workspace, tref);
266  }
267 }
269 {
270  bScreen *screen = WM_window_get_active_screen(win);
271  ViewLayer *view_layer = WM_window_get_active_view_layer(win);
272  LISTBASE_FOREACH (ScrArea *, area, &screen->areabase) {
273  if (((1 << area->spacetype) & WM_TOOLSYSTEM_SPACE_MASK) == 0) {
274  continue;
275  }
276 
277  WorkSpace *workspace = WM_window_get_active_workspace(win);
278  const bToolKey tkey = {
279  .space_type = area->spacetype,
280  .mode = WM_toolsystem_mode_from_spacetype(view_layer, area, area->spacetype),
281  };
282  bToolRef *tref = WM_toolsystem_ref_find(workspace, &tkey);
283  if (tref) {
284  if (tref->tag == 0) {
285  toolsystem_reinit_ref(C, workspace, tref);
286  tref->tag = 1;
287  }
288  }
289  }
290 }
291 
293  struct WorkSpace *workspace,
294  bToolRef *tref,
295  const bToolRef_Runtime *tref_rt,
296  const char *idname)
297 {
298  Main *bmain = CTX_data_main(C);
299 
300  if (tref->runtime) {
301  toolsystem_unlink_ref(C, workspace, tref);
302  }
303 
304  STRNCPY(tref->idname, idname);
305 
306  if (tref->runtime == NULL) {
307  tref->runtime = MEM_callocN(sizeof(*tref->runtime), __func__);
308  }
309 
310  if (tref_rt != tref->runtime) {
311  *tref->runtime = *tref_rt;
312  }
313 
314  /* Ideally Python could check this gizmo group flag and not
315  * pass in the argument to begin with. */
316  bool use_fallback_keymap = false;
317 
318  if (tref->idname_fallback[0] || tref->runtime->keymap_fallback[0]) {
319  if (tref_rt->flag & TOOLREF_FLAG_FALLBACK_KEYMAP) {
320  use_fallback_keymap = true;
321  }
322  else if (tref_rt->gizmo_group[0]) {
323  wmGizmoGroupType *gzgt = WM_gizmogrouptype_find(tref_rt->gizmo_group, false);
324  if (gzgt) {
326  use_fallback_keymap = true;
327  }
328  }
329  }
330  }
331  if (use_fallback_keymap == false) {
332  tref->idname_fallback[0] = '\0';
333  tref->runtime->keymap_fallback[0] = '\0';
334  }
335 
336  toolsystem_ref_link(C, workspace, tref);
337 
338  toolsystem_refresh_screen_from_active_tool(bmain, workspace, tref);
339 
340  /* Set the cursor if possible, if not - it's fine as entering the region will refresh it. */
341  {
342  wmWindow *win = CTX_wm_window(C);
343  if (win != NULL) {
344  win->addmousemove = true;
345  win->tag_cursor_refresh = true;
346  }
347  }
348 
349  {
350  struct wmMsgBus *mbus = CTX_wm_message_bus(C);
351  WM_msg_publish_rna_prop(mbus, &workspace->id, workspace, WorkSpace, tools);
352  }
353 }
354 
356 {
357  bToolRef_Runtime *tref_rt = tref->runtime;
358  if ((tref_rt == NULL) || (tref_rt->data_block[0] == '\0')) {
359  return;
360  }
361  wmWindowManager *wm = bmain->wm.first;
362  LISTBASE_FOREACH (wmWindow *, win, &wm->windows) {
363  if (workspace != WM_window_get_active_workspace(win)) {
364  continue;
365  }
366 
369  const ViewLayer *view_layer = WM_window_get_active_view_layer(win);
370  const Object *ob = OBACT(view_layer);
371  if (ob == NULL) {
372  /* pass */
373  }
374  if ((tref->space_type == SPACE_VIEW3D) && (tref->mode == CTX_MODE_PARTICLE)) {
375  if (ob->mode & OB_MODE_PARTICLE_EDIT) {
377  const int i = RNA_enum_from_value(items, ts->particle.brushtype);
378  const EnumPropertyItem *item = &items[i];
379  if (!STREQ(tref_rt->data_block, item->identifier)) {
380  STRNCPY(tref_rt->data_block, item->identifier);
381  SNPRINTF(tref->idname, "builtin_brush.%s", item->name);
382  }
383  }
384  }
385  else {
386  const ePaintMode paint_mode = BKE_paintmode_get_from_tool(tref);
387  Paint *paint = BKE_paint_get_active_from_paintmode(scene, paint_mode);
388  const EnumPropertyItem *items = BKE_paint_get_tool_enum_from_paintmode(paint_mode);
389  if (paint && paint->brush && items) {
390  const ID *brush = (ID *)paint->brush;
391  const char tool_type = BKE_brush_tool_get((struct Brush *)brush, paint);
392  const int i = RNA_enum_from_value(items, tool_type);
393  /* Possible when loading files from the future. */
394  if (i != -1) {
395  const char *name = items[i].name;
396  const char *identifier = items[i].identifier;
397  if (!STREQ(tref_rt->data_block, identifier)) {
398  STRNCPY(tref_rt->data_block, identifier);
399  SNPRINTF(tref->idname, "builtin_brush.%s", name);
400  }
401  }
402  }
403  }
404  }
405 }
406 
408 {
409  Main *bmain = CTX_data_main(C);
410 
412 
413  LISTBASE_FOREACH (WorkSpace *, workspace, &bmain->workspaces) {
414  LISTBASE_FOREACH (bToolRef *, tref, &workspace->tools) {
415  MEM_SAFE_FREE(tref->runtime);
416  }
417  }
418 
419  /* Rely on screen initialization for gizmos. */
420 }
421 
422 static bool toolsystem_key_ensure_check(const bToolKey *tkey)
423 {
424  switch (tkey->space_type) {
425  case SPACE_VIEW3D:
426  return true;
427  case SPACE_IMAGE:
428  if (ELEM(tkey->mode, SI_MODE_PAINT, SI_MODE_UV)) {
429  return true;
430  }
431  break;
432  case SPACE_NODE:
433  return true;
434  case SPACE_SEQ:
435  return true;
436  }
437  return false;
438 }
439 
440 int WM_toolsystem_mode_from_spacetype(ViewLayer *view_layer, ScrArea *area, int space_type)
441 {
442  int mode = -1;
443  switch (space_type) {
444  case SPACE_VIEW3D: {
445  /* 'area' may be NULL in this case. */
446  Object *obact = OBACT(view_layer);
447  if (obact != NULL) {
448  Object *obedit = OBEDIT_FROM_OBACT(obact);
449  mode = CTX_data_mode_enum_ex(obedit, obact, obact->mode);
450  }
451  else {
452  mode = CTX_MODE_OBJECT;
453  }
454  break;
455  }
456  case SPACE_IMAGE: {
457  SpaceImage *sima = area->spacedata.first;
458  mode = sima->mode;
459  break;
460  }
461  case SPACE_NODE: {
462  mode = 0;
463  break;
464  }
465  case SPACE_SEQ: {
466  SpaceSeq *sseq = area->spacedata.first;
467  mode = sseq->view;
468  break;
469  }
470  }
471  return mode;
472 }
473 
475 {
476  int space_type = SPACE_EMPTY;
477  int mode = -1;
478 
479  if (area != NULL) {
480  space_type = area->spacetype;
481  mode = WM_toolsystem_mode_from_spacetype(view_layer, area, space_type);
482  }
483 
484  if (mode != -1) {
485  tkey->space_type = space_type;
486  tkey->mode = mode;
487  return true;
488  }
489  return false;
490 }
491 
493 {
494  Main *bmain = CTX_data_main(C);
495 
496  struct {
497  wmWindow *win;
498  ScrArea *area;
499  ARegion *region;
500  bool is_set;
501  } context_prev = {0};
502 
503  for (wmWindowManager *wm = bmain->wm.first; wm; wm = wm->id.next) {
504  LISTBASE_FOREACH (wmWindow *, win, &wm->windows) {
505  WorkSpace *workspace = WM_window_get_active_workspace(win);
506  bScreen *screen = WM_window_get_active_screen(win);
507  ViewLayer *view_layer = WM_window_get_active_view_layer(win);
508  /* Could skip loop for modes that don't depend on space type. */
509  int space_type_mask_handled = 0;
510  LISTBASE_FOREACH (ScrArea *, area, &screen->areabase) {
511  /* Don't change the space type of the active tool, only update its mode. */
512  const int space_type_mask = (1 << area->spacetype);
513  if ((space_type_mask & WM_TOOLSYSTEM_SPACE_MASK) &&
514  ((space_type_mask_handled & space_type_mask) == 0)) {
515  space_type_mask_handled |= space_type_mask;
516  const bToolKey tkey = {
517  .space_type = area->spacetype,
518  .mode = WM_toolsystem_mode_from_spacetype(view_layer, area, area->spacetype),
519  };
520  bToolRef *tref = WM_toolsystem_ref_find(workspace, &tkey);
521  if (tref != area->runtime.tool) {
522  if (context_prev.is_set == false) {
523  context_prev.win = CTX_wm_window(C);
524  context_prev.area = CTX_wm_area(C);
525  context_prev.region = CTX_wm_region(C);
526  context_prev.is_set = true;
527  }
528 
529  CTX_wm_window_set(C, win);
531 
532  toolsystem_reinit_ensure_toolref(C, workspace, &tkey, NULL);
533  }
534  }
535  }
536  }
537  }
538 
539  if (context_prev.is_set) {
540  CTX_wm_window_set(C, context_prev.win);
541  CTX_wm_area_set(C, context_prev.area);
542  CTX_wm_region_set(C, context_prev.region);
543  }
544 
546 
547  LISTBASE_FOREACH (WorkSpace *, workspace, &bmain->workspaces) {
548  if (workspace->id.tag & LIB_TAG_DOIT) {
549  workspace->id.tag &= ~LIB_TAG_DOIT;
550  /* Refresh to ensure data is initialized.
551  * This is needed because undo can load a state which no longer has the underlying DNA data
552  * needed for the tool (un-initialized paint-slots for eg), see: T64339. */
553  LISTBASE_FOREACH (bToolRef *, tref, &workspace->tools) {
554  toolsystem_refresh_ref(C, workspace, tref);
555  }
556  }
557  }
558 }
559 
561 {
562  area->runtime.tool = NULL;
563  area->runtime.is_tool_set = true;
564  const int mode = WM_toolsystem_mode_from_spacetype(view_layer, area, area->spacetype);
565  LISTBASE_FOREACH (bToolRef *, tref, &workspace->tools) {
566  if (tref->space_type == area->spacetype) {
567  if (tref->mode == mode) {
568  area->runtime.tool = tref;
569  break;
570  }
571  }
572  }
573 }
574 
576 {
577  WorkSpace *workspace = WM_window_get_active_workspace(win);
578  bool space_type_has_tools[SPACE_TYPE_NUM] = {0};
579  LISTBASE_FOREACH (bToolRef *, tref, &workspace->tools) {
580  space_type_has_tools[tref->space_type] = true;
581  }
582  bScreen *screen = WM_window_get_active_screen(win);
583  ViewLayer *view_layer = WM_window_get_active_view_layer(win);
584  LISTBASE_FOREACH (ScrArea *, area, &screen->areabase) {
585  area->runtime.tool = NULL;
586  area->runtime.is_tool_set = true;
587  if (space_type_has_tools[area->spacetype]) {
588  WM_toolsystem_refresh_screen_area(workspace, view_layer, area);
589  }
590  }
591 }
592 
594 {
595  /* Update all ScrArea's tools */
596  for (wmWindowManager *wm = bmain->wm.first; wm; wm = wm->id.next) {
597  LISTBASE_FOREACH (wmWindow *, win, &wm->windows) {
599  }
600  }
601 }
602 
604  WorkSpace *workspace,
605  bToolRef *tref)
606 {
607  /* Update all ScrArea's tools */
608  for (wmWindowManager *wm = bmain->wm.first; wm; wm = wm->id.next) {
609  LISTBASE_FOREACH (wmWindow *, win, &wm->windows) {
610  if (workspace == WM_window_get_active_workspace(win)) {
611  bScreen *screen = WM_window_get_active_screen(win);
612  ViewLayer *view_layer = WM_window_get_active_view_layer(win);
613  LISTBASE_FOREACH (ScrArea *, area, &screen->areabase) {
614  if (area->spacetype == tref->space_type) {
615  int mode = WM_toolsystem_mode_from_spacetype(view_layer, area, area->spacetype);
616  if (mode == tref->mode) {
617  area->runtime.tool = tref;
618  area->runtime.is_tool_set = true;
619  }
620  }
621  }
622  }
623  }
624  }
625 }
626 
628  bContext *C, WorkSpace *workspace, const bToolKey *tkey, const char *name, bool cycle)
629 {
630  wmOperatorType *ot = WM_operatortype_find("WM_OT_tool_set_by_id", false);
631  /* On startup, Python operators are not yet loaded. */
632  if (ot == NULL) {
633  return NULL;
634  }
635 
636  /* Some contexts use the current space type (image editor for e.g.),
637  * ensure this is set correctly or there is no area. */
638 #ifndef NDEBUG
639  /* Exclude this check for some space types where the space type isn't used. */
642  BLI_assert(area == NULL || area->spacetype == tkey->space_type);
643  }
644 #endif
645 
646  PointerRNA op_props;
648  RNA_string_set(&op_props, "name", name);
649 
651 
652  RNA_enum_set(&op_props, "space_type", tkey->space_type);
653  RNA_boolean_set(&op_props, "cycle", cycle);
654 
656  WM_operator_properties_free(&op_props);
657 
658  bToolRef *tref = WM_toolsystem_ref_find(workspace, tkey);
659 
660  if (tref) {
661  Main *bmain = CTX_data_main(C);
662  toolsystem_refresh_screen_from_active_tool(bmain, workspace, tref);
663  }
664 
665  return (tref && STREQ(tref->idname, name)) ? tref : NULL;
666 }
667 
669 {
670  ViewLayer *view_layer = CTX_data_view_layer(C);
672  bToolKey tkey;
673  if (WM_toolsystem_key_from_context(view_layer, area, &tkey)) {
674  WorkSpace *workspace = CTX_wm_workspace(C);
675  return WM_toolsystem_ref_set_by_id_ex(C, workspace, &tkey, name, false);
676  }
677  return NULL;
678 }
679 
681 {
682  bToolKey tkey = {
683  .space_type = tref->space_type,
684  .mode = tref->mode,
685  };
686  WM_toolsystem_ref_set_by_id_ex(C, workspace, &tkey, tref->idname, false);
687 }
688 
689 static const char *toolsystem_default_tool(const bToolKey *tkey)
690 {
691  switch (tkey->space_type) {
692  case SPACE_VIEW3D:
693  switch (tkey->mode) {
694  /* Use the names of the enums for each brush tool. */
695  case CTX_MODE_SCULPT:
700  return "builtin_brush.Draw";
702  return "builtin_brush.Push";
704  return "builtin_brush.Weight";
706  return "builtin_brush.Draw";
708  return "builtin_brush.density";
709  /* end temporary hack. */
710 
711  case CTX_MODE_PARTICLE:
712  return "builtin_brush.Comb";
713  case CTX_MODE_EDIT_TEXT:
714  return "builtin.cursor";
715  }
716  break;
717  case SPACE_IMAGE:
718  switch (tkey->mode) {
719  case SI_MODE_PAINT:
720  return "builtin_brush.Draw";
721  }
722  break;
723  case SPACE_NODE: {
724  return "builtin.select_box";
725  }
726  case SPACE_SEQ: {
727  switch (tkey->mode) {
728  case SEQ_VIEW_SEQUENCE:
729  return "builtin.select";
730  case SEQ_VIEW_PREVIEW:
731  return "builtin.sample";
733  return "builtin.select";
734  }
735  return "builtin.select_box";
736  }
737  }
738 
739  return "builtin.select_box";
740 }
741 
746  WorkSpace *workspace,
747  const bToolKey *tkey,
748  const char *default_tool)
749 {
750  bToolRef *tref;
751  if (WM_toolsystem_ref_ensure(workspace, tkey, &tref)) {
752  if (default_tool == NULL) {
753  default_tool = toolsystem_default_tool(tkey);
754  }
755  STRNCPY(tref->idname, default_tool);
756  }
757  toolsystem_reinit_with_toolref(C, workspace, tref);
758  return tref;
759 }
760 
762 {
763  ViewLayer *view_layer = CTX_data_view_layer(C);
764  int space_type = SPACE_VIEW3D;
765  const bToolKey tkey = {
766  .space_type = space_type,
767  .mode = WM_toolsystem_mode_from_spacetype(view_layer, NULL, space_type),
768  };
769  toolsystem_reinit_ensure_toolref(C, workspace, &tkey, NULL);
770 }
771 
773 {
774  WorkSpace *workspace = CTX_wm_workspace(C);
776 
777  /* Multi window support. */
778  Main *bmain = CTX_data_main(C);
779  wmWindowManager *wm = bmain->wm.first;
780  if (!BLI_listbase_is_single(&wm->windows)) {
781  wmWindow *win_prev = CTX_wm_window(C);
782  ScrArea *area_prev = CTX_wm_area(C);
783  ARegion *region_prev = CTX_wm_region(C);
784 
785  LISTBASE_FOREACH (wmWindow *, win, &wm->windows) {
786  if (win != win_prev) {
787  WorkSpace *workspace_iter = WM_window_get_active_workspace(win);
788  if (workspace_iter != workspace) {
789 
790  CTX_wm_window_set(C, win);
791 
793 
794  CTX_wm_window_set(C, win_prev);
795  CTX_wm_area_set(C, area_prev);
796  CTX_wm_region_set(C, region_prev);
797  }
798  }
799  }
800  }
801 }
802 
804  WorkSpace *workspace,
805  ViewLayer *view_layer,
806  ScrArea *area)
807 {
808  const bToolKey tkey = {
809  .space_type = area->spacetype,
810  .mode = WM_toolsystem_mode_from_spacetype(view_layer, area, area->spacetype),
811  };
812  if (toolsystem_key_ensure_check(&tkey)) {
813  toolsystem_reinit_ensure_toolref(C, workspace, &tkey, NULL);
814  }
815 }
816 
818 {
820  return tref_rt && (tref_rt->data_block[0] != '\0');
821 }
822 
824  wmMsgSubscribeKey *UNUSED(msg_key),
825  wmMsgSubscribeValue *msg_val)
826 {
827  ScrArea *area = msg_val->user_data;
828  Main *bmain = CTX_data_main(C);
829  wmWindow *win = ((wmWindowManager *)bmain->wm.first)->windows.first;
830  if (win->next != NULL) {
831  do {
832  bScreen *screen = WM_window_get_active_screen(win);
833  if (BLI_findindex(&screen->areabase, area) != -1) {
834  break;
835  }
836  } while ((win = win->next));
837  }
838 
839  WorkSpace *workspace = WM_window_get_active_workspace(win);
840  ViewLayer *view_layer = WM_window_get_active_view_layer(win);
841 
842  const bToolKey tkey = {
843  .space_type = area->spacetype,
844  .mode = WM_toolsystem_mode_from_spacetype(view_layer, area, area->spacetype),
845  };
846  WM_toolsystem_refresh(C, workspace, &tkey);
847  WM_toolsystem_refresh_screen_area(workspace, view_layer, area);
848 }
849 
850 static IDProperty *idprops_ensure_named_group(IDProperty *group, const char *idname)
851 {
852  IDProperty *prop = IDP_GetPropertyFromGroup(group, idname);
853  if ((prop == NULL) || (prop->type != IDP_GROUP)) {
854  IDPropertyTemplate val = {0};
855  prop = IDP_New(IDP_GROUP, &val, __func__);
856  STRNCPY(prop->name, idname);
857  IDP_ReplaceInGroup_ex(group, prop, NULL);
858  }
859  return prop;
860 }
861 
863 {
864  IDProperty *group = tref->properties;
865  if (group == NULL) {
866  return NULL;
867  }
868  return IDP_GetPropertyFromGroup(group, tref->idname);
869 }
870 
872 {
873  if (tref->properties == NULL) {
874  IDPropertyTemplate val = {0};
875  tref->properties = IDP_New(IDP_GROUP, &val, __func__);
876  }
877  return idprops_ensure_named_group(tref->properties, tref->idname);
878 }
879 
881  const char *idname,
882  StructRNA *type,
883  PointerRNA *r_ptr)
884 {
886  IDProperty *prop = group ? IDP_GetPropertyFromGroup(group, idname) : NULL;
887  RNA_pointer_create(NULL, type, prop, r_ptr);
888  return (prop != NULL);
889 }
890 
892  const char *idname,
893  StructRNA *type,
894  PointerRNA *r_ptr)
895 {
897  IDProperty *prop = idprops_ensure_named_group(group, idname);
898  RNA_pointer_create(NULL, type, prop, r_ptr);
899 }
900 
902  PointerRNA *dst_ptr,
903  PointerRNA *src_ptr,
905 {
906  *dst_ptr = *src_ptr;
907  if (dst_ptr->data) {
908  dst_ptr->data = IDP_CopyProperty(dst_ptr->data);
909  }
910  else {
911  IDPropertyTemplate val = {0};
912  dst_ptr->data = IDP_New(IDP_GROUP, &val, "wmOpItemProp");
913  }
915  if (group != NULL) {
916  IDProperty *prop = IDP_GetPropertyFromGroup(group, ot->idname);
917  if (prop) {
918  /* Important key-map items properties don't get overwritten by the tools.
919  * - When a key-map item doesn't set a property, the tool-systems is used.
920  * - When it does, it overrides the tool-system.
921  *
922  * This way the default action can be to follow the top-bar tool-settings &
923  * modifier keys can be used to perform different actions that aren't clobbered here.
924  */
925  IDP_MergeGroup(dst_ptr->data, prop, false);
926  }
927  }
928 }
struct Brush * BKE_brush_add(struct Main *bmain, const char *name, eObjectMode ob_mode)
Definition: brush.cc:496
#define BKE_brush_tool_set(brush, p, tool)
Definition: BKE_brush.h:172
void BKE_brush_sculpt_reset(struct Brush *brush)
Definition: brush.cc:1683
#define BKE_brush_tool_get(brush, p)
Definition: BKE_brush.h:169
struct WorkSpace * CTX_wm_workspace(const bContext *C)
Definition: context.c:728
struct ScrArea * CTX_wm_area(const bContext *C)
Definition: context.c:738
void CTX_wm_region_set(bContext *C, struct ARegion *region)
Definition: context.c:1009
enum eContextObjectMode CTX_data_mode_enum_ex(const struct Object *obedit, const struct Object *ob, eObjectMode object_mode)
@ CTX_MODE_PAINT_TEXTURE
Definition: BKE_context.h:116
@ CTX_MODE_WEIGHT_GPENCIL
Definition: BKE_context.h:122
@ CTX_MODE_PARTICLE
Definition: BKE_context.h:117
@ CTX_MODE_SCULPT
Definition: BKE_context.h:113
@ CTX_MODE_VERTEX_GPENCIL
Definition: BKE_context.h:123
@ CTX_MODE_OBJECT
Definition: BKE_context.h:118
@ CTX_MODE_SCULPT_CURVES
Definition: BKE_context.h:124
@ CTX_MODE_EDIT_TEXT
Definition: BKE_context.h:107
@ CTX_MODE_SCULPT_GPENCIL
Definition: BKE_context.h:121
@ CTX_MODE_PAINT_GPENCIL
Definition: BKE_context.h:119
@ CTX_MODE_PAINT_VERTEX
Definition: BKE_context.h:115
@ CTX_MODE_PAINT_WEIGHT
Definition: BKE_context.h:114
struct ViewLayer * CTX_data_view_layer(const bContext *C)
Definition: context.c:1100
void CTX_wm_window_set(bContext *C, struct wmWindow *win)
Definition: context.c:966
struct wmMsgBus * CTX_wm_message_bus(const bContext *C)
Definition: context.c:770
struct ARegion * CTX_wm_region(const bContext *C)
Definition: context.c:749
void CTX_wm_area_set(bContext *C, struct ScrArea *area)
Definition: context.c:997
struct Main * CTX_data_main(const bContext *C)
Definition: context.c:1074
struct wmWindow * CTX_wm_window(const bContext *C)
Definition: context.c:723
struct IDProperty * IDP_New(char type, const IDPropertyTemplate *val, const char *name) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
Definition: idprop.c:887
void IDP_ReplaceInGroup_ex(struct IDProperty *group, struct IDProperty *prop, struct IDProperty *prop_exist)
Definition: idprop.c:563
void IDP_MergeGroup(struct IDProperty *dest, const struct IDProperty *src, bool do_overwrite) ATTR_NONNULL()
struct IDProperty * IDP_GetPropertyFromGroup(const struct IDProperty *prop, const char *name) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
struct IDProperty * IDP_CopyProperty(const struct IDProperty *prop) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
struct ID * BKE_libblock_find_name(struct Main *bmain, short type, const char *name) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
Definition: lib_id.c:1297
void BKE_paint_brush_set(struct Paint *paint, struct Brush *br)
Definition: paint.c:617
struct Paint * BKE_paint_get_active_from_paintmode(struct Scene *sce, ePaintMode mode)
Definition: paint.c:345
struct Brush * BKE_paint_toolslots_brush_get(struct Paint *paint, int slot_index)
const struct EnumPropertyItem * BKE_paint_get_tool_enum_from_paintmode(ePaintMode mode)
Definition: paint.c:382
bool BKE_paint_ensure_from_paintmode(struct Scene *sce, ePaintMode mode)
Definition: paint.c:294
ePaintMode
Definition: BKE_paint.h:67
@ PAINT_MODE_INVALID
Definition: BKE_paint.h:86
@ PAINT_MODE_SCULPT
Definition: BKE_paint.h:68
ePaintMode BKE_paintmode_get_from_tool(const struct bToolRef *tref)
Definition: paint.c:571
void BKE_workspace_id_tag_all_visible(struct Main *bmain, int tag) ATTR_NONNULL()
Definition: workspace.c:500
#define BLI_assert(a)
Definition: BLI_assert.h:46
void BLI_addhead(struct ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition: listbase.c:60
#define LISTBASE_FOREACH(type, var, list)
Definition: BLI_listbase.h:336
void void BLI_INLINE bool BLI_listbase_is_single(const struct ListBase *lb)
Definition: BLI_listbase.h:265
int BLI_findindex(const struct ListBase *listbase, const void *vlink) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
#define STRNCPY(dst, src)
Definition: BLI_string.h:483
#define SNPRINTF(dst, format,...)
Definition: BLI_string.h:485
#define UNUSED(x)
#define ELEM(...)
#define STREQ(a, b)
#define CLOG_WARN(clg_ref,...)
Definition: CLG_log.h:189
ID and Library types, which are fundamental for sdna.
@ IDP_GROUP
Definition: DNA_ID.h:141
@ LIB_TAG_DOIT
Definition: DNA_ID.h:707
@ ID_BR
Definition: DNA_ID_enums.h:69
@ OB_MODE_PARTICLE_EDIT
Object is a sort of wrapper for general info.
#define OBEDIT_FROM_OBACT(ob)
#define OBACT(_view_layer)
@ SPACE_NODE
@ SPACE_SEQ
@ SPACE_EMPTY
@ SPACE_IMAGE
@ SPACE_VIEW3D
@ SEQ_VIEW_SEQUENCE_PREVIEW
@ SEQ_VIEW_SEQUENCE
@ SEQ_VIEW_PREVIEW
#define SPACE_TYPE_NUM
@ SI_MODE_PAINT
@ SI_MODE_UV
@ TOOLREF_FLAG_FALLBACK_KEYMAP
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum type
Read Guarded memory(de)allocation.
#define MEM_SAFE_FREE(v)
#define C
Definition: RandGen.cpp:25
@ WM_GIZMOGROUPTYPE_TOOL_INIT
@ WM_GIZMOGROUPTYPE_TOOL_FALLBACK_KEYMAP
#define WM_TOOLSYSTEM_SPACE_MASK
Definition: WM_toolsystem.h:29
#define WM_TOOLSYSTEM_SPACE_MASK_MODE_FROM_SPACE
Definition: WM_toolsystem.h:34
struct CLG_LogRef * WM_LOG_TOOLS
@ WM_OP_EXEC_DEFAULT
Definition: WM_types.h:208
Scene scene
void *(* MEM_callocN)(size_t len, const char *str)
Definition: mallocn.c:31
static void area(int d1, int d2, int e1, int e2, float weights[2])
void RNA_pointer_create(ID *id, StructRNA *type, void *data, PointerRNA *r_ptr)
Definition: rna_access.c:136
void RNA_string_set(PointerRNA *ptr, const char *name, const char *value)
Definition: rna_access.c:5155
void RNA_boolean_set(PointerRNA *ptr, const char *name, bool value)
Definition: rna_access.c:4874
int RNA_enum_from_identifier(const EnumPropertyItem *item, const char *identifier)
Definition: rna_access.c:1714
int RNA_enum_from_value(const EnumPropertyItem *item, const int value)
Definition: rna_access.c:1736
void RNA_enum_set(PointerRNA *ptr, const char *name, int value)
Definition: rna_access.c:5015
const EnumPropertyItem rna_enum_particle_edit_hair_brush_items[]
const char * identifier
Definition: RNA_types.h:461
const char * name
Definition: RNA_types.h:465
char name[64]
Definition: DNA_ID.h:111
char type
Definition: DNA_ID.h:108
Definition: DNA_ID.h:368
void * first
Definition: DNA_listBase.h:31
Definition: BKE_main.h:121
ListBase wm
Definition: BKE_main.h:197
ListBase workspaces
Definition: BKE_main.h:203
unsigned short ob_mode
struct Paint_Runtime runtime
struct Brush * brush
void * data
Definition: RNA_types.h:38
struct ToolSettings * toolsettings
struct ParticleEditSettings particle
ListBase areabase
int space_type
Definition: WM_toolsystem.h:38
IDProperty * properties
char idname[64]
bToolRef_Runtime * runtime
char idname_fallback[64]
eWM_GizmoFlagGroupTypeFlag flag
struct wmGizmoMapType_Params gzmap_params
const char * idname
Definition: WM_types.h:890
struct wmWindow * next
int WM_operator_name_call_ptr(bContext *C, wmOperatorType *ot, wmOperatorCallContext context, PointerRNA *properties, const wmEvent *event)
wmOperatorType * ot
Definition: wm_files.c:3479
bool WM_gizmo_group_type_ensure_ptr(wmGizmoGroupType *gzgt)
void WM_gizmo_group_remove_by_tool(bContext *C, Main *bmain, const wmGizmoGroupType *gzgt, const bToolRef *tref)
wmGizmoGroupType * WM_gizmogrouptype_find(const char *idname, bool quiet)
wmGizmoMapType * WM_gizmomaptype_ensure(const struct wmGizmoMapType_Params *gzmap_params)
void WM_gizmoconfig_update_tag_group_type_init(wmGizmoMapType *gzmap_type, wmGizmoGroupType *gzgt)
#define WM_msg_publish_rna_prop(mbus, id_, data_, type_, prop_)
wmOperatorType * WM_operatortype_find(const char *idname, bool quiet)
void WM_operator_properties_create_ptr(PointerRNA *ptr, wmOperatorType *ot)
Definition: wm_operators.c:661
void WM_operator_properties_free(PointerRNA *ptr)
Definition: wm_operators.c:783
void WM_toolsystem_reinit_all(struct bContext *C, wmWindow *win)
void WM_toolsystem_reinit(bContext *C, WorkSpace *workspace, const bToolKey *tkey)
struct bToolRef_Runtime * WM_toolsystem_runtime_from_context(struct bContext *C)
Definition: wm_toolsystem.c:77
void WM_toolsystem_init(bContext *C)
bool WM_toolsystem_ref_properties_get_ex(bToolRef *tref, const char *idname, StructRNA *type, PointerRNA *r_ptr)
static void wm_toolsystem_update_from_context_view3d_impl(bContext *C, WorkSpace *workspace)
IDProperty * WM_toolsystem_ref_properties_ensure_idprops(bToolRef *tref)
static void toolsystem_refresh_screen_from_active_tool(Main *bmain, WorkSpace *workspace, bToolRef *tref)
bToolRef * WM_toolsystem_ref_set_by_id_ex(bContext *C, WorkSpace *workspace, const bToolKey *tkey, const char *name, bool cycle)
void WM_toolsystem_unlink(bContext *C, WorkSpace *workspace, const bToolKey *tkey)
bool WM_toolsystem_active_tool_is_brush(const bContext *C)
void WM_toolsystem_refresh_screen_all(Main *bmain)
bToolRef_Runtime * WM_toolsystem_runtime_find(WorkSpace *workspace, const bToolKey *tkey)
Definition: wm_toolsystem.c:94
static IDProperty * idprops_ensure_named_group(IDProperty *group, const char *idname)
bool WM_toolsystem_key_from_context(ViewLayer *view_layer, ScrArea *area, bToolKey *tkey)
static bool toolsystem_key_ensure_check(const bToolKey *tkey)
void WM_toolsystem_refresh_screen_area(WorkSpace *workspace, ViewLayer *view_layer, ScrArea *area)
void WM_toolsystem_ref_properties_init_for_keymap(bToolRef *tref, PointerRNA *dst_ptr, PointerRNA *src_ptr, wmOperatorType *ot)
static void toolsystem_reinit_with_toolref(bContext *C, WorkSpace *UNUSED(workspace), bToolRef *tref)
static void toolsystem_refresh_ref(bContext *C, WorkSpace *workspace, bToolRef *tref)
void WM_toolsystem_unlink_all(struct bContext *C, struct WorkSpace *workspace)
void WM_toolsystem_refresh_all(struct bContext *C, struct WorkSpace *workspace)
bToolRef * WM_toolsystem_ref_find(WorkSpace *workspace, const bToolKey *tkey)
Definition: wm_toolsystem.c:83
void WM_toolsystem_do_msg_notify_tag_refresh(bContext *C, wmMsgSubscribeKey *UNUSED(msg_key), wmMsgSubscribeValue *msg_val)
static void toolsystem_ref_link(bContext *C, WorkSpace *workspace, bToolRef *tref)
void WM_toolsystem_refresh_screen_window(wmWindow *win)
static void toolsystem_reinit_ref(bContext *C, WorkSpace *workspace, bToolRef *tref)
bToolRef * WM_toolsystem_ref_set_by_id(bContext *C, const char *name)
static void toolsystem_unlink_ref(bContext *C, WorkSpace *UNUSED(workspace), bToolRef *tref)
void WM_toolsystem_update_from_context_view3d(bContext *C)
IDProperty * WM_toolsystem_ref_properties_get_idprops(bToolRef *tref)
void WM_toolsystem_refresh_active(bContext *C)
static bToolRef * toolsystem_reinit_ensure_toolref(bContext *C, WorkSpace *workspace, const bToolKey *tkey, const char *default_tool)
bool WM_toolsystem_ref_ensure(struct WorkSpace *workspace, const bToolKey *tkey, bToolRef **r_tref)
int WM_toolsystem_mode_from_spacetype(ViewLayer *view_layer, ScrArea *area, int space_type)
struct bToolRef * WM_toolsystem_ref_from_context(struct bContext *C)
Definition: wm_toolsystem.c:57
static const char * toolsystem_default_tool(const bToolKey *tkey)
void WM_toolsystem_ref_properties_ensure_ex(bToolRef *tref, const char *idname, StructRNA *type, PointerRNA *r_ptr)
void WM_toolsystem_ref_sync_from_context(Main *bmain, WorkSpace *workspace, bToolRef *tref)
void WM_toolsystem_ref_set_from_runtime(struct bContext *C, struct WorkSpace *workspace, bToolRef *tref, const bToolRef_Runtime *tref_rt, const char *idname)
void WM_toolsystem_refresh(bContext *C, WorkSpace *workspace, const bToolKey *tkey)
void WM_toolsystem_update_from_context(bContext *C, WorkSpace *workspace, ViewLayer *view_layer, ScrArea *area)
bScreen * WM_window_get_active_screen(const wmWindow *win)
Definition: wm_window.c:2300
ViewLayer * WM_window_get_active_view_layer(const wmWindow *win)
Definition: wm_window.c:2217
WorkSpace * WM_window_get_active_workspace(const wmWindow *win)
Definition: wm_window.c:2266
Scene * WM_window_get_active_scene(const wmWindow *win)
Definition: wm_window.c:2183