Blender  V2.93
wm_toolsystem.c
Go to the documentation of this file.
1 /*
2  * This program is free software; you can redistribute it and/or
3  * modify it under the terms of the GNU General Public License
4  * as published by the Free Software Foundation; either version 2
5  * of the License, or (at your option) any later version.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * along with this program; if not, write to the Free Software Foundation,
14  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
15  */
16 
23 #include <string.h>
24 
25 #include "CLG_log.h"
26 
27 #include "MEM_guardedalloc.h"
28 
29 #include "BLI_listbase.h"
30 #include "BLI_string.h"
31 #include "BLI_utildefines.h"
32 
33 #include "DNA_ID.h"
34 #include "DNA_object_types.h"
35 #include "DNA_scene_types.h"
36 #include "DNA_space_types.h"
38 #include "DNA_workspace_types.h"
39 
40 #include "BKE_brush.h"
41 #include "BKE_context.h"
42 #include "BKE_idprop.h"
43 #include "BKE_lib_id.h"
44 #include "BKE_main.h"
45 #include "BKE_paint.h"
46 #include "BKE_workspace.h"
47 
48 #include "RNA_access.h"
49 #include "RNA_enum_types.h"
50 
51 #include "WM_api.h"
52 #include "WM_message.h"
53 #include "WM_toolsystem.h" /* own include */
54 #include "WM_types.h"
55 
57  WorkSpace *UNUSED(workspace),
58  bToolRef *tref);
60  WorkSpace *workspace,
61  const bToolKey *tkey,
62  const char *default_tool);
64  WorkSpace *workspace,
65  bToolRef *tref);
66 
67 /* -------------------------------------------------------------------- */
72 {
73  WorkSpace *workspace = CTX_wm_workspace(C);
74  ViewLayer *view_layer = CTX_data_view_layer(C);
76  if ((area == NULL) || ((1 << area->spacetype) & WM_TOOLSYSTEM_SPACE_MASK) == 0) {
77  return NULL;
78  }
79  const bToolKey tkey = {
80  .space_type = area->spacetype,
81  .mode = WM_toolsystem_mode_from_spacetype(view_layer, area, area->spacetype),
82  };
83  bToolRef *tref = WM_toolsystem_ref_find(workspace, &tkey);
84  /* We could return 'area->runtime.tool' in this case. */
85  if (area->runtime.is_tool_set) {
86  BLI_assert(tref == area->runtime.tool);
87  }
88  return tref;
89 }
90 
92 {
94  return tref ? tref->runtime : NULL;
95 }
96 
98 {
100  LISTBASE_FOREACH (bToolRef *, tref, &workspace->tools) {
101  if ((tref->space_type == tkey->space_type) && (tref->mode == tkey->mode)) {
102  return tref;
103  }
104  }
105  return NULL;
106 }
107 
109 {
110  bToolRef *tref = WM_toolsystem_ref_find(workspace, tkey);
111  return tref ? tref->runtime : NULL;
112 }
113 
114 bool WM_toolsystem_ref_ensure(struct WorkSpace *workspace, const bToolKey *tkey, bToolRef **r_tref)
115 {
116  bToolRef *tref = WM_toolsystem_ref_find(workspace, tkey);
117  if (tref) {
118  *r_tref = tref;
119  return false;
120  }
121  tref = MEM_callocN(sizeof(*tref), __func__);
122  BLI_addhead(&workspace->tools, tref);
123  tref->space_type = tkey->space_type;
124  tref->mode = tkey->mode;
125  *r_tref = tref;
126  return true;
127 }
128 
131 static void toolsystem_unlink_ref(bContext *C, WorkSpace *UNUSED(workspace), bToolRef *tref)
132 {
133  bToolRef_Runtime *tref_rt = tref->runtime;
134 
135  if (tref_rt->gizmo_group[0]) {
136  wmGizmoGroupType *gzgt = WM_gizmogrouptype_find(tref_rt->gizmo_group, false);
137  if (gzgt != NULL) {
138  Main *bmain = CTX_data_main(C);
139  WM_gizmo_group_remove_by_tool(C, bmain, gzgt, tref);
140  }
141  }
142 }
143 void WM_toolsystem_unlink(bContext *C, WorkSpace *workspace, const bToolKey *tkey)
144 {
145  bToolRef *tref = WM_toolsystem_ref_find(workspace, tkey);
146  if (tref && tref->runtime) {
147  toolsystem_unlink_ref(C, workspace, tref);
148  }
149 }
150 
151 static void toolsystem_ref_link(bContext *C, WorkSpace *workspace, bToolRef *tref)
152 {
153  bToolRef_Runtime *tref_rt = tref->runtime;
154  if (tref_rt->gizmo_group[0]) {
155  const char *idname = tref_rt->gizmo_group;
156  wmGizmoGroupType *gzgt = WM_gizmogrouptype_find(idname, false);
157  if (gzgt != NULL) {
158  if ((gzgt->flag & WM_GIZMOGROUPTYPE_TOOL_INIT) == 0) {
159  if (!WM_gizmo_group_type_ensure_ptr(gzgt)) {
160  /* Even if the group-type was has been linked, it's possible the space types
161  * were not previously using it. (happens with multiple windows.) */
162  wmGizmoMapType *gzmap_type = WM_gizmomaptype_ensure(&gzgt->gzmap_params);
164  }
165  }
166  }
167  else {
168  CLOG_WARN(WM_LOG_TOOLS, "'%s' widget not found", idname);
169  }
170  }
171 
172  if (tref_rt->data_block[0]) {
173  Main *bmain = CTX_data_main(C);
174 
175  if ((tref->space_type == SPACE_VIEW3D) && (tref->mode == CTX_MODE_PARTICLE)) {
177  const int i = RNA_enum_from_identifier(items, tref_rt->data_block);
178  if (i != -1) {
179  const int value = items[i].value;
180  wmWindowManager *wm = bmain->wm.first;
181  LISTBASE_FOREACH (wmWindow *, win, &wm->windows) {
182  if (workspace == WM_window_get_active_workspace(win)) {
185  ts->particle.brushtype = value;
186  }
187  }
188  }
189  }
190  else {
191  const ePaintMode paint_mode = BKE_paintmode_get_from_tool(tref);
192  BLI_assert(paint_mode != PAINT_MODE_INVALID);
193  const EnumPropertyItem *items = BKE_paint_get_tool_enum_from_paintmode(paint_mode);
194  BLI_assert(items != NULL);
195 
196  const int i = items ? RNA_enum_from_identifier(items, tref_rt->data_block) : -1;
197  if (i != -1) {
198  const int slot_index = items[i].value;
199  wmWindowManager *wm = bmain->wm.first;
200  LISTBASE_FOREACH (wmWindow *, win, &wm->windows) {
201  if (workspace == WM_window_get_active_workspace(win)) {
204  Paint *paint = BKE_paint_get_active_from_paintmode(scene, paint_mode);
205  struct Brush *brush = BKE_paint_toolslots_brush_get(paint, slot_index);
206  if (brush == NULL) {
207  /* Could make into a function. */
208  brush = (struct Brush *)BKE_libblock_find_name(bmain, ID_BR, items[i].name);
209  if (brush && slot_index == BKE_brush_tool_get(brush, paint)) {
210  /* pass */
211  }
212  else {
213  brush = BKE_brush_add(bmain, items[i].name, paint->runtime.ob_mode);
214  BKE_brush_tool_set(brush, paint, slot_index);
215  }
216  BKE_paint_brush_set(paint, brush);
217  }
218  BKE_paint_brush_set(paint, brush);
219  }
220  }
221  }
222  }
223  }
224 }
225 
226 static void toolsystem_refresh_ref(bContext *C, WorkSpace *workspace, bToolRef *tref)
227 {
228  if (tref->runtime == NULL) {
229  return;
230  }
231  /* currently same operation. */
232  toolsystem_ref_link(C, workspace, tref);
233 }
234 void WM_toolsystem_refresh(bContext *C, WorkSpace *workspace, const bToolKey *tkey)
235 {
236  bToolRef *tref = WM_toolsystem_ref_find(workspace, tkey);
237  if (tref) {
238  toolsystem_refresh_ref(C, workspace, tref);
239  }
240 }
241 
242 static void toolsystem_reinit_ref(bContext *C, WorkSpace *workspace, bToolRef *tref)
243 {
244  toolsystem_reinit_with_toolref(C, workspace, tref);
245 }
246 void WM_toolsystem_reinit(bContext *C, WorkSpace *workspace, const bToolKey *tkey)
247 {
248  bToolRef *tref = WM_toolsystem_ref_find(workspace, tkey);
249  if (tref) {
250  toolsystem_reinit_ref(C, workspace, tref);
251  }
252 }
253 
254 /* Operate on all active tools. */
255 void WM_toolsystem_unlink_all(struct bContext *C, struct WorkSpace *workspace)
256 {
257  LISTBASE_FOREACH (bToolRef *, tref, &workspace->tools) {
258  tref->tag = 0;
259  }
260 
261  LISTBASE_FOREACH (bToolRef *, tref, &workspace->tools) {
262  if (tref->runtime) {
263  if (tref->tag == 0) {
264  toolsystem_unlink_ref(C, workspace, tref);
265  tref->tag = 1;
266  }
267  }
268  }
269 }
270 
271 void WM_toolsystem_refresh_all(struct bContext *C, struct WorkSpace *workspace)
272 {
273  BLI_assert(0);
274  LISTBASE_FOREACH (bToolRef *, tref, &workspace->tools) {
275  toolsystem_refresh_ref(C, workspace, tref);
276  }
277 }
279 {
280  bScreen *screen = WM_window_get_active_screen(win);
281  ViewLayer *view_layer = WM_window_get_active_view_layer(win);
282  LISTBASE_FOREACH (ScrArea *, area, &screen->areabase) {
283  if (((1 << area->spacetype) & WM_TOOLSYSTEM_SPACE_MASK) == 0) {
284  continue;
285  }
286 
287  WorkSpace *workspace = WM_window_get_active_workspace(win);
288  const bToolKey tkey = {
289  .space_type = area->spacetype,
290  .mode = WM_toolsystem_mode_from_spacetype(view_layer, area, area->spacetype),
291  };
292  bToolRef *tref = WM_toolsystem_ref_find(workspace, &tkey);
293  if (tref) {
294  if (tref->tag == 0) {
295  toolsystem_reinit_ref(C, workspace, tref);
296  tref->tag = 1;
297  }
298  }
299  }
300 }
301 
303  struct WorkSpace *workspace,
304  bToolRef *tref,
305  const bToolRef_Runtime *tref_rt,
306  const char *idname)
307 {
308  Main *bmain = CTX_data_main(C);
309 
310  if (tref->runtime) {
311  toolsystem_unlink_ref(C, workspace, tref);
312  }
313 
314  STRNCPY(tref->idname, idname);
315 
316  if (tref->runtime == NULL) {
317  tref->runtime = MEM_callocN(sizeof(*tref->runtime), __func__);
318  }
319 
320  if (tref_rt != tref->runtime) {
321  *tref->runtime = *tref_rt;
322  }
323 
324  /* Ideally Python could check this gizmo group flag and not
325  * pass in the argument to begin with. */
326  bool use_fallback_keymap = false;
327 
328  if (tref->idname_fallback[0] || tref->runtime->keymap_fallback[0]) {
329  if (tref_rt->gizmo_group[0]) {
330  wmGizmoGroupType *gzgt = WM_gizmogrouptype_find(tref_rt->gizmo_group, false);
331  if (gzgt) {
333  use_fallback_keymap = true;
334  }
335  }
336  }
337  }
338  if (use_fallback_keymap == false) {
339  tref->idname_fallback[0] = '\0';
340  tref->runtime->keymap_fallback[0] = '\0';
341  }
342 
343  toolsystem_ref_link(C, workspace, tref);
344 
345  toolsystem_refresh_screen_from_active_tool(bmain, workspace, tref);
346 
347  /* Set the cursor if possible, if not - it's fine as entering the region will refresh it. */
348  {
349  wmWindow *win = CTX_wm_window(C);
350  if (win != NULL) {
351  win->addmousemove = true;
352  win->tag_cursor_refresh = true;
353  }
354  }
355 
356  {
357  struct wmMsgBus *mbus = CTX_wm_message_bus(C);
358  WM_msg_publish_rna_prop(mbus, &workspace->id, workspace, WorkSpace, tools);
359  }
360 }
361 
369 {
370  bToolRef_Runtime *tref_rt = tref->runtime;
371  if ((tref_rt == NULL) || (tref_rt->data_block[0] == '\0')) {
372  return;
373  }
374  wmWindowManager *wm = bmain->wm.first;
375  LISTBASE_FOREACH (wmWindow *, win, &wm->windows) {
376  if (workspace != WM_window_get_active_workspace(win)) {
377  continue;
378  }
379 
382  const ViewLayer *view_layer = WM_window_get_active_view_layer(win);
383  const Object *ob = OBACT(view_layer);
384  if (ob == NULL) {
385  /* pass */
386  }
387  if ((tref->space_type == SPACE_VIEW3D) && (tref->mode == CTX_MODE_PARTICLE)) {
388  if (ob->mode & OB_MODE_PARTICLE_EDIT) {
390  const int i = RNA_enum_from_value(items, ts->particle.brushtype);
391  const EnumPropertyItem *item = &items[i];
392  if (!STREQ(tref_rt->data_block, item->identifier)) {
393  STRNCPY(tref_rt->data_block, item->identifier);
394  SNPRINTF(tref->idname, "builtin_brush.%s", item->name);
395  }
396  }
397  }
398  else {
399  const ePaintMode paint_mode = BKE_paintmode_get_from_tool(tref);
400  Paint *paint = BKE_paint_get_active_from_paintmode(scene, paint_mode);
401  const EnumPropertyItem *items = BKE_paint_get_tool_enum_from_paintmode(paint_mode);
402  if (paint && paint->brush && items) {
403  const ID *brush = (ID *)paint->brush;
404  const char tool_type = BKE_brush_tool_get((struct Brush *)brush, paint);
405  const int i = RNA_enum_from_value(items, tool_type);
406  /* Possible when loading files from the future. */
407  if (i != -1) {
408  const char *name = items[i].name;
409  const char *identifier = items[i].identifier;
410  if (!STREQ(tref_rt->data_block, identifier)) {
411  STRNCPY(tref_rt->data_block, identifier);
412  SNPRINTF(tref->idname, "builtin_brush.%s", name);
413  }
414  }
415  }
416  }
417  }
418 }
419 
421 {
422  Main *bmain = CTX_data_main(C);
423 
425 
426  LISTBASE_FOREACH (WorkSpace *, workspace, &bmain->workspaces) {
427  LISTBASE_FOREACH (bToolRef *, tref, &workspace->tools) {
428  MEM_SAFE_FREE(tref->runtime);
429  }
430  }
431 
432  /* Rely on screen initialization for gizmos. */
433 }
434 
435 static bool toolsystem_key_ensure_check(const bToolKey *tkey)
436 {
437  switch (tkey->space_type) {
438  case SPACE_VIEW3D:
439  return true;
440  case SPACE_IMAGE:
441  if (ELEM(tkey->mode, SI_MODE_PAINT, SI_MODE_UV)) {
442  return true;
443  }
444  break;
445  case SPACE_NODE:
446  return true;
447  case SPACE_SEQ:
448  return true;
449  }
450  return false;
451 }
452 
453 int WM_toolsystem_mode_from_spacetype(ViewLayer *view_layer, ScrArea *area, int space_type)
454 {
455  int mode = -1;
456  switch (space_type) {
457  case SPACE_VIEW3D: {
458  /* 'area' may be NULL in this case. */
459  Object *obact = OBACT(view_layer);
460  if (obact != NULL) {
461  Object *obedit = OBEDIT_FROM_OBACT(obact);
462  mode = CTX_data_mode_enum_ex(obedit, obact, obact->mode);
463  }
464  else {
465  mode = CTX_MODE_OBJECT;
466  }
467  break;
468  }
469  case SPACE_IMAGE: {
470  SpaceImage *sima = area->spacedata.first;
471  mode = sima->mode;
472  break;
473  }
474  case SPACE_NODE: {
475  mode = 0;
476  break;
477  }
478  case SPACE_SEQ: {
479  SpaceSeq *sseq = area->spacedata.first;
480  mode = sseq->view;
481  break;
482  }
483  }
484  return mode;
485 }
486 
488 {
489  int space_type = SPACE_EMPTY;
490  int mode = -1;
491 
492  if (area != NULL) {
493  space_type = area->spacetype;
494  mode = WM_toolsystem_mode_from_spacetype(view_layer, area, space_type);
495  }
496 
497  if (mode != -1) {
498  tkey->space_type = space_type;
499  tkey->mode = mode;
500  return true;
501  }
502  return false;
503 }
504 
514 {
515  Main *bmain = CTX_data_main(C);
516  for (wmWindowManager *wm = bmain->wm.first; wm; wm = wm->id.next) {
517  LISTBASE_FOREACH (wmWindow *, win, &wm->windows) {
518  WorkSpace *workspace = WM_window_get_active_workspace(win);
519  bScreen *screen = WM_window_get_active_screen(win);
520  ViewLayer *view_layer = WM_window_get_active_view_layer(win);
521  /* Could skip loop for modes that don't depend on space type. */
522  int space_type_mask_handled = 0;
523  LISTBASE_FOREACH (ScrArea *, area, &screen->areabase) {
524  /* Don't change the space type of the active tool, only update its mode. */
525  const int space_type_mask = (1 << area->spacetype);
526  if ((space_type_mask & WM_TOOLSYSTEM_SPACE_MASK) &&
527  ((space_type_mask_handled & space_type_mask) == 0)) {
528  space_type_mask_handled |= space_type_mask;
529  const bToolKey tkey = {
530  .space_type = area->spacetype,
531  .mode = WM_toolsystem_mode_from_spacetype(view_layer, area, area->spacetype),
532  };
533  bToolRef *tref = WM_toolsystem_ref_find(workspace, &tkey);
534  if (tref != area->runtime.tool) {
535  toolsystem_reinit_ensure_toolref(C, workspace, &tkey, NULL);
536  }
537  }
538  }
539  }
540  }
541 
543 
544  LISTBASE_FOREACH (WorkSpace *, workspace, &bmain->workspaces) {
545  if (workspace->id.tag & LIB_TAG_DOIT) {
546  workspace->id.tag &= ~LIB_TAG_DOIT;
547  /* Refresh to ensure data is initialized.
548  * This is needed because undo can load a state which no longer has the underlying DNA data
549  * needed for the tool (un-initialized paint-slots for eg), see: T64339. */
550  LISTBASE_FOREACH (bToolRef *, tref, &workspace->tools) {
551  toolsystem_refresh_ref(C, workspace, tref);
552  }
553  }
554  }
555 }
556 
558 {
559  area->runtime.tool = NULL;
560  area->runtime.is_tool_set = true;
561  const int mode = WM_toolsystem_mode_from_spacetype(view_layer, area, area->spacetype);
562  LISTBASE_FOREACH (bToolRef *, tref, &workspace->tools) {
563  if (tref->space_type == area->spacetype) {
564  if (tref->mode == mode) {
565  area->runtime.tool = tref;
566  break;
567  }
568  }
569  }
570 }
571 
573 {
574  /* Update all ScrArea's tools */
575  for (wmWindowManager *wm = bmain->wm.first; wm; wm = wm->id.next) {
576  LISTBASE_FOREACH (wmWindow *, win, &wm->windows) {
577  WorkSpace *workspace = WM_window_get_active_workspace(win);
578  bool space_type_has_tools[SPACE_TYPE_LAST + 1] = {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  }
593 }
594 
596  WorkSpace *workspace,
597  bToolRef *tref)
598 {
599  /* Update all ScrArea's tools */
600  for (wmWindowManager *wm = bmain->wm.first; wm; wm = wm->id.next) {
601  LISTBASE_FOREACH (wmWindow *, win, &wm->windows) {
602  if (workspace == WM_window_get_active_workspace(win)) {
603  bScreen *screen = WM_window_get_active_screen(win);
604  ViewLayer *view_layer = WM_window_get_active_view_layer(win);
605  LISTBASE_FOREACH (ScrArea *, area, &screen->areabase) {
606  if (area->spacetype == tref->space_type) {
607  int mode = WM_toolsystem_mode_from_spacetype(view_layer, area, area->spacetype);
608  if (mode == tref->mode) {
609  area->runtime.tool = tref;
610  area->runtime.is_tool_set = true;
611  }
612  }
613  }
614  }
615  }
616  }
617 }
618 
620  bContext *C, WorkSpace *workspace, const bToolKey *tkey, const char *name, bool cycle)
621 {
622  wmOperatorType *ot = WM_operatortype_find("WM_OT_tool_set_by_id", false);
623  /* On startup, Python operators are not yet loaded. */
624  if (ot == NULL) {
625  return NULL;
626  }
627  PointerRNA op_props;
629  RNA_string_set(&op_props, "name", name);
630 
632 
633  RNA_enum_set(&op_props, "space_type", tkey->space_type);
634  RNA_boolean_set(&op_props, "cycle", cycle);
635 
637  WM_operator_properties_free(&op_props);
638 
639  bToolRef *tref = WM_toolsystem_ref_find(workspace, tkey);
640 
641  if (tref) {
642  Main *bmain = CTX_data_main(C);
643  toolsystem_refresh_screen_from_active_tool(bmain, workspace, tref);
644  }
645 
646  return (tref && STREQ(tref->idname, name)) ? tref : NULL;
647 }
648 
650 {
651  ViewLayer *view_layer = CTX_data_view_layer(C);
653  bToolKey tkey;
654  if (WM_toolsystem_key_from_context(view_layer, area, &tkey)) {
655  WorkSpace *workspace = CTX_wm_workspace(C);
656  return WM_toolsystem_ref_set_by_id_ex(C, workspace, &tkey, name, false);
657  }
658  return NULL;
659 }
660 
662 {
663  bToolKey tkey = {
664  .space_type = tref->space_type,
665  .mode = tref->mode,
666  };
667  WM_toolsystem_ref_set_by_id_ex(C, workspace, &tkey, tref->idname, false);
668 }
669 
670 static const char *toolsystem_default_tool(const bToolKey *tkey)
671 {
672  switch (tkey->space_type) {
673  case SPACE_VIEW3D:
674  switch (tkey->mode) {
675  /* Use the names of the enums for each brush tool. */
676  case CTX_MODE_SCULPT:
681  return "builtin_brush.Draw";
683  return "builtin_brush.Push";
685  return "builtin_brush.Weight";
687  return "builtin_brush.Draw";
688  /* end temporary hack. */
689 
690  case CTX_MODE_PARTICLE:
691  return "builtin_brush.Comb";
692  case CTX_MODE_EDIT_TEXT:
693  return "builtin.cursor";
694  }
695  break;
696  case SPACE_IMAGE:
697  switch (tkey->mode) {
698  case SI_MODE_PAINT:
699  return "builtin_brush.Draw";
700  }
701  break;
702  case SPACE_NODE: {
703  return "builtin.select_box";
704  }
705  case SPACE_SEQ: {
706  switch (tkey->mode) {
707  case SEQ_VIEW_SEQUENCE:
708  return "builtin.select";
709  case SEQ_VIEW_PREVIEW:
710  return "builtin.sample";
712  return "builtin.select";
713  }
714  return "builtin.select_box";
715  }
716  }
717 
718  return "builtin.select_box";
719 }
720 
725  WorkSpace *workspace,
726  const bToolKey *tkey,
727  const char *default_tool)
728 {
729  bToolRef *tref;
730  if (WM_toolsystem_ref_ensure(workspace, tkey, &tref)) {
731  if (default_tool == NULL) {
732  default_tool = toolsystem_default_tool(tkey);
733  }
734  STRNCPY(tref->idname, default_tool);
735  }
736  toolsystem_reinit_with_toolref(C, workspace, tref);
737  return tref;
738 }
739 
741 {
742  ViewLayer *view_layer = CTX_data_view_layer(C);
743  int space_type = SPACE_VIEW3D;
744  const bToolKey tkey = {
745  .space_type = space_type,
746  .mode = WM_toolsystem_mode_from_spacetype(view_layer, NULL, space_type),
747  };
748  toolsystem_reinit_ensure_toolref(C, workspace, &tkey, NULL);
749 }
750 
752 {
753  WorkSpace *workspace = CTX_wm_workspace(C);
755 
756  /* Multi window support. */
757  Main *bmain = CTX_data_main(C);
758  wmWindowManager *wm = bmain->wm.first;
759  if (!BLI_listbase_is_single(&wm->windows)) {
760  wmWindow *win_prev = CTX_wm_window(C);
761  ScrArea *area_prev = CTX_wm_area(C);
762  ARegion *region_prev = CTX_wm_region(C);
763 
764  LISTBASE_FOREACH (wmWindow *, win, &wm->windows) {
765  if (win != win_prev) {
766  WorkSpace *workspace_iter = WM_window_get_active_workspace(win);
767  if (workspace_iter != workspace) {
768 
769  CTX_wm_window_set(C, win);
770 
772 
773  CTX_wm_window_set(C, win_prev);
774  CTX_wm_area_set(C, area_prev);
775  CTX_wm_region_set(C, region_prev);
776  }
777  }
778  }
779  }
780 }
781 
783  WorkSpace *workspace,
784  ViewLayer *view_layer,
785  ScrArea *area)
786 {
787  const bToolKey tkey = {
788  .space_type = area->spacetype,
789  .mode = WM_toolsystem_mode_from_spacetype(view_layer, area, area->spacetype),
790  };
791  if (toolsystem_key_ensure_check(&tkey)) {
792  toolsystem_reinit_ensure_toolref(C, workspace, &tkey, NULL);
793  }
794 }
795 
800 {
802  return tref_rt && (tref_rt->data_block[0] != '\0');
803 }
804 
805 /* Follow wmMsgNotifyFn spec */
807  wmMsgSubscribeKey *UNUSED(msg_key),
808  wmMsgSubscribeValue *msg_val)
809 {
810  ScrArea *area = msg_val->user_data;
811  Main *bmain = CTX_data_main(C);
812  wmWindow *win = ((wmWindowManager *)bmain->wm.first)->windows.first;
813  if (win->next != NULL) {
814  do {
815  bScreen *screen = WM_window_get_active_screen(win);
816  if (BLI_findindex(&screen->areabase, area) != -1) {
817  break;
818  }
819  } while ((win = win->next));
820  }
821 
822  WorkSpace *workspace = WM_window_get_active_workspace(win);
823  ViewLayer *view_layer = WM_window_get_active_view_layer(win);
824 
825  const bToolKey tkey = {
826  .space_type = area->spacetype,
827  .mode = WM_toolsystem_mode_from_spacetype(view_layer, area, area->spacetype),
828  };
829  WM_toolsystem_refresh(C, workspace, &tkey);
830  WM_toolsystem_refresh_screen_area(workspace, view_layer, area);
831 }
832 
834 {
835  if (tref->properties == NULL) {
836  IDPropertyTemplate val = {0};
837  tref->properties = IDP_New(IDP_GROUP, &val, "wmOperatorProperties");
838  }
839  return tref->properties;
840 }
841 
843  const char *idname,
844  StructRNA *type,
845  PointerRNA *r_ptr)
846 {
847  IDProperty *group = tref->properties;
848  IDProperty *prop = group ? IDP_GetPropertyFromGroup(group, idname) : NULL;
849  RNA_pointer_create(NULL, type, prop, r_ptr);
850  return (prop != NULL);
851 }
852 
854  const char *idname,
855  StructRNA *type,
856  PointerRNA *r_ptr)
857 {
859  IDProperty *prop = IDP_GetPropertyFromGroup(group, idname);
860  if (prop == NULL) {
861  IDPropertyTemplate val = {0};
862  prop = IDP_New(IDP_GROUP, &val, "wmGenericProperties");
863  STRNCPY(prop->name, idname);
864  IDP_ReplaceInGroup_ex(group, prop, NULL);
865  }
866  else {
867  BLI_assert(prop->type == IDP_GROUP);
868  }
869 
870  RNA_pointer_create(NULL, type, prop, r_ptr);
871 }
872 
874  PointerRNA *dst_ptr,
875  PointerRNA *src_ptr,
877 {
878  *dst_ptr = *src_ptr;
879  if (dst_ptr->data) {
880  dst_ptr->data = IDP_CopyProperty(dst_ptr->data);
881  }
882  else {
883  IDPropertyTemplate val = {0};
884  dst_ptr->data = IDP_New(IDP_GROUP, &val, "wmOpItemProp");
885  }
886  if (tref->properties != NULL) {
888  if (prop) {
889  /* Important key-map items properties don't get overwritten by the tools.
890  * - When a key-map item doesn't set a property, the tool-systems is used.
891  * - When it does, it overrides the tool-system.
892  *
893  * This way the default action can be to follow the top-bar tool-settings &
894  * modifier keys can be used to perform different actions that aren't clobbered here.
895  */
896  IDP_MergeGroup(dst_ptr->data, prop, false);
897  }
898  }
899 }
#define BKE_brush_tool_set(brush, p, tool)
Definition: BKE_brush.h:144
#define BKE_brush_tool_get(brush, p)
Definition: BKE_brush.h:141
struct Brush * BKE_brush_add(struct Main *bmain, const char *name, const eObjectMode ob_mode)
Definition: brush.c:492
struct WorkSpace * CTX_wm_workspace(const bContext *C)
Definition: context.c:704
struct ScrArea * CTX_wm_area(const bContext *C)
Definition: context.c:714
void CTX_wm_region_set(bContext *C, struct ARegion *region)
Definition: context.c:985
@ CTX_MODE_PAINT_TEXTURE
Definition: BKE_context.h:126
@ CTX_MODE_WEIGHT_GPENCIL
Definition: BKE_context.h:132
@ CTX_MODE_PARTICLE
Definition: BKE_context.h:127
@ CTX_MODE_SCULPT
Definition: BKE_context.h:123
@ CTX_MODE_VERTEX_GPENCIL
Definition: BKE_context.h:133
@ CTX_MODE_OBJECT
Definition: BKE_context.h:128
@ CTX_MODE_EDIT_TEXT
Definition: BKE_context.h:118
@ CTX_MODE_SCULPT_GPENCIL
Definition: BKE_context.h:131
@ CTX_MODE_PAINT_GPENCIL
Definition: BKE_context.h:129
@ CTX_MODE_PAINT_VERTEX
Definition: BKE_context.h:125
@ CTX_MODE_PAINT_WEIGHT
Definition: BKE_context.h:124
struct ViewLayer * CTX_data_view_layer(const bContext *C)
Definition: context.c:1044
void CTX_wm_window_set(bContext *C, struct wmWindow *win)
Definition: context.c:942
enum eContextObjectMode CTX_data_mode_enum_ex(const struct Object *obedit, const struct Object *ob, const eObjectMode object_mode)
struct wmMsgBus * CTX_wm_message_bus(const bContext *C)
Definition: context.c:746
struct ARegion * CTX_wm_region(const bContext *C)
Definition: context.c:725
void CTX_wm_area_set(bContext *C, struct ScrArea *area)
Definition: context.c:973
struct Main * CTX_data_main(const bContext *C)
Definition: context.c:1018
struct wmWindow * CTX_wm_window(const bContext *C)
Definition: context.c:699
void IDP_ReplaceInGroup_ex(struct IDProperty *group, struct IDProperty *prop, struct IDProperty *prop_exist)
Definition: idprop.c:557
struct IDProperty * IDP_GetPropertyFromGroup(const struct IDProperty *prop, const char *name) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
void IDP_MergeGroup(struct IDProperty *dest, const struct IDProperty *src, const bool do_overwrite) ATTR_NONNULL()
struct IDProperty * IDP_New(const char type, const IDPropertyTemplate *val, const char *name) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
Definition: idprop.c:907
struct IDProperty * IDP_CopyProperty(const struct IDProperty *prop) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
struct ID * BKE_libblock_find_name(struct Main *bmain, const short type, const char *name) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
Definition: lib_id.c:1333
void BKE_paint_brush_set(struct Paint *paint, struct Brush *br)
Definition: paint.c:609
struct Paint * BKE_paint_get_active_from_paintmode(struct Scene *sce, ePaintMode mode)
Definition: paint.c:354
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:389
bool BKE_paint_ensure_from_paintmode(struct Scene *sce, ePaintMode mode)
Definition: paint.c:306
ePaintMode
Definition: BKE_paint.h:78
@ PAINT_MODE_INVALID
Definition: BKE_paint.h:95
ePaintMode BKE_paintmode_get_from_tool(const struct bToolRef *tref)
Definition: paint.c:570
void BKE_workspace_id_tag_all_visible(struct Main *bmain, int tag) ATTR_NONNULL()
Definition: workspace.c:519
#define BLI_assert(a)
Definition: BLI_assert.h:58
void BLI_addhead(struct ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition: listbase.c:87
#define LISTBASE_FOREACH(type, var, list)
Definition: BLI_listbase.h:172
void void BLI_INLINE bool BLI_listbase_is_single(const struct ListBase *lb)
Definition: BLI_listbase.h:120
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:163
#define SNPRINTF(dst, format,...)
Definition: BLI_string.h:165
#define UNUSED(x)
#define ELEM(...)
#define STREQ(a, b)
#define CLOG_WARN(clg_ref,...)
Definition: CLG_log.h:203
ID and Library types, which are fundamental for sdna.
@ LIB_TAG_DOIT
Definition: DNA_ID.h:554
@ IDP_GROUP
Definition: DNA_ID.h:101
@ ID_BR
Definition: DNA_ID_enums.h:81
@ 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_LAST
@ SI_MODE_PAINT
@ SI_MODE_UV
_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:39
@ WM_GIZMOGROUPTYPE_TOOL_INIT
@ WM_GIZMOGROUPTYPE_TOOL_FALLBACK_KEYMAP
#define WM_TOOLSYSTEM_SPACE_MASK
Definition: WM_toolsystem.h:43
struct CLG_LogRef * WM_LOG_TOOLS
@ WM_OP_EXEC_DEFAULT
Definition: WM_types.h:204
Scene scene
void *(* MEM_callocN)(size_t len, const char *str)
Definition: mallocn.c:45
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:146
void RNA_string_set(PointerRNA *ptr, const char *name, const char *value)
Definition: rna_access.c:6550
void RNA_boolean_set(PointerRNA *ptr, const char *name, bool value)
Definition: rna_access.c:6272
int RNA_enum_from_identifier(const EnumPropertyItem *item, const char *identifier)
Definition: rna_access.c:1876
int RNA_enum_from_value(const EnumPropertyItem *item, const int value)
Definition: rna_access.c:1902
void RNA_enum_set(PointerRNA *ptr, const char *name, int value)
Definition: rna_access.c:6413
const EnumPropertyItem rna_enum_particle_edit_hair_brush_items[]
const char * identifier
Definition: RNA_types.h:446
const char * name
Definition: RNA_types.h:450
char name[64]
Definition: DNA_ID.h:74
char type
Definition: DNA_ID.h:71
Definition: DNA_ID.h:273
void * first
Definition: DNA_listBase.h:47
Definition: BKE_main.h:116
ListBase wm
Definition: BKE_main.h:175
ListBase workspaces
Definition: BKE_main.h:181
unsigned short ob_mode
struct Paint_Runtime runtime
struct Brush * brush
void * data
Definition: RNA_types.h:52
struct ToolSettings * toolsettings
struct ParticleEditSettings particle
ListBase areabase
int space_type
Definition: WM_toolsystem.h:47
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:723
struct wmWindow * next
int WM_operator_name_call_ptr(bContext *C, wmOperatorType *ot, short context, PointerRNA *properties)
wmOperatorType * ot
Definition: wm_files.c:3156
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:584
void WM_operator_properties_free(PointerRNA *ptr)
Definition: wm_operators.c:711
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:91
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)
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:97
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)
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)
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:71
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:2372
ViewLayer * WM_window_get_active_view_layer(const wmWindow *win)
Definition: wm_window.c:2286
WorkSpace * WM_window_get_active_workspace(const wmWindow *win)
Definition: wm_window.c:2335
Scene * WM_window_get_active_scene(const wmWindow *win)
Definition: wm_window.c:2249