Blender V4.3
wm_toolsystem.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 "CLG_log.h"
14
15#include "MEM_guardedalloc.h"
16
17#include "BLI_listbase.h"
18#include "BLI_string.h"
19#include "BLI_utildefines.h"
20
21#include "DNA_ID.h"
22#include "DNA_brush_types.h"
23#include "DNA_object_types.h"
24#include "DNA_scene_types.h"
25#include "DNA_space_types.h"
27#include "DNA_workspace_types.h"
28
29#include "BKE_asset_edit.hh"
30#include "BKE_brush.hh"
31#include "BKE_context.hh"
32#include "BKE_idprop.hh"
33#include "BKE_layer.hh"
34#include "BKE_lib_id.hh"
35#include "BKE_main.hh"
36#include "BKE_paint.hh"
37#include "BKE_workspace.hh"
38
39#include "RNA_access.hh"
40#include "RNA_enum_types.hh"
41
42#include "WM_api.hh"
43#include "WM_message.hh"
44#include "WM_toolsystem.hh" /* Own include. */
45#include "WM_types.hh"
46
47static void toolsystem_reinit_with_toolref(bContext *C, WorkSpace * /*workspace*/, bToolRef *tref);
49 WorkSpace *workspace,
50 const bToolKey *tkey,
51 const char *default_tool);
53 WorkSpace *workspace,
54 bToolRef *tref);
55static void toolsystem_ref_set_by_brush_type(bContext *C, const char *brush_type);
56
57/* -------------------------------------------------------------------- */
62{
63 WorkSpace *workspace = CTX_wm_workspace(C);
64 if (workspace == nullptr) {
65 return nullptr;
66 }
67 const Scene *scene = CTX_data_scene(C);
68 ViewLayer *view_layer = CTX_data_view_layer(C);
69 ScrArea *area = CTX_wm_area(C);
70 if ((area == nullptr) || ((1 << area->spacetype) & WM_TOOLSYSTEM_SPACE_MASK) == 0) {
71 return nullptr;
72 }
73 bToolKey tkey{};
74 tkey.space_type = area->spacetype;
75 tkey.mode = WM_toolsystem_mode_from_spacetype(scene, view_layer, area, area->spacetype);
76 bToolRef *tref = WM_toolsystem_ref_find(workspace, &tkey);
77 /* We could return 'area->runtime.tool' in this case. */
78 if (area->runtime.is_tool_set) {
79 BLI_assert(tref == area->runtime.tool);
80 }
81 return tref;
82}
83
85{
87 return tref ? tref->runtime : nullptr;
88}
89
91{
93 LISTBASE_FOREACH (bToolRef *, tref, &workspace->tools) {
94 if ((tref->space_type == tkey->space_type) && (tref->mode == tkey->mode)) {
95 return tref;
96 }
97 }
98 return nullptr;
99}
100
102{
103 bToolRef *tref = WM_toolsystem_ref_find(workspace, tkey);
104 return tref ? tref->runtime : nullptr;
105}
106
107bool WM_toolsystem_ref_ensure(WorkSpace *workspace, const bToolKey *tkey, bToolRef **r_tref)
108{
109 bToolRef *tref = WM_toolsystem_ref_find(workspace, tkey);
110 if (tref) {
111 *r_tref = tref;
112 return false;
113 }
114 tref = static_cast<bToolRef *>(MEM_callocN(sizeof(*tref), __func__));
115 BLI_addhead(&workspace->tools, tref);
116 tref->space_type = tkey->space_type;
117 tref->mode = tkey->mode;
118 *r_tref = tref;
119 return true;
120}
121
126 ViewLayer *view_layer,
127 ScrArea *area)
128{
129 bToolKey tkey{};
130
131 if (area && ((1 << area->spacetype) & WM_TOOLSYSTEM_SPACE_MASK)) {
132 tkey.space_type = area->spacetype;
133 tkey.mode = WM_toolsystem_mode_from_spacetype(scene, view_layer, area, area->spacetype);
134 return tkey;
135 }
136
137 /* Otherwise: Fallback to getting the active tool for 3D views. */
138 tkey.space_type = SPACE_VIEW3D;
139 tkey.mode = WM_toolsystem_mode_from_spacetype(scene, view_layer, nullptr, SPACE_VIEW3D);
140 return tkey;
141}
142
151{
152 /* Current space & mode has its own active tool, use that. */
153 const ScrArea *area = CTX_wm_area(C);
154 if (area && ((1 << area->spacetype) & WM_TOOLSYSTEM_SPACE_MASK)) {
156 }
157
158 /* Otherwise: Fallback to getting the active tool for 3D views. */
159 WorkSpace *workspace = CTX_wm_workspace(C);
160 if (workspace == nullptr) {
161 return nullptr;
162 }
163 const Scene *scene = CTX_data_scene(C);
164 ViewLayer *view_layer = CTX_data_view_layer(C);
165 bToolKey tkey{};
167 tkey.mode = WM_toolsystem_mode_from_spacetype(scene, view_layer, nullptr, SPACE_VIEW3D);
168 return WM_toolsystem_ref_find(workspace, &tkey);
169}
170
173static void toolsystem_unlink_ref(bContext *C, WorkSpace * /*workspace*/, bToolRef *tref)
174{
175 bToolRef_Runtime *tref_rt = tref->runtime;
176
177 if (tref_rt->gizmo_group[0]) {
178 wmGizmoGroupType *gzgt = WM_gizmogrouptype_find(tref_rt->gizmo_group, false);
179 if (gzgt != nullptr) {
180 Main *bmain = CTX_data_main(C);
181 WM_gizmo_group_remove_by_tool(C, bmain, gzgt, tref);
182 }
183 }
184}
185void WM_toolsystem_unlink(bContext *C, WorkSpace *workspace, const bToolKey *tkey)
186{
187 bToolRef *tref = WM_toolsystem_ref_find(workspace, tkey);
188 if (tref && tref->runtime) {
189 toolsystem_unlink_ref(C, workspace, tref);
190 }
191}
192
193/* -------------------------------------------------------------------- */
197static const char *brush_type_identifier_get(const int brush_type, const PaintMode paint_mode)
198{
199 const EnumPropertyItem *type_enum = BKE_paint_get_tool_enum_from_paintmode(paint_mode);
200 const int item_idx = RNA_enum_from_value(type_enum, brush_type);
201 if (item_idx == -1) {
202 return "";
203 }
204 return type_enum[item_idx].identifier;
205}
206
207static bool brush_type_matches_active_tool(bContext *C, const int brush_type)
208{
210
211 if (!(active_tool->runtime->flag & TOOLREF_FLAG_USE_BRUSHES)) {
212 return false;
213 }
214
216 return active_tool->runtime->brush_type == brush_type;
217}
218
220 const char *brush_type_name)
221{
222 return static_cast<NamedBrushAssetReference *>(
224 brush_type_name,
226}
227
232{
235
236 if (paint->brush != nullptr) {
237 if (std::optional<AssetWeakReference> brush_asset_reference =
239 {
240 paint->tool_brush_bindings.main_brush_asset_reference = MEM_new<AssetWeakReference>(
241 __func__, *brush_asset_reference);
242 }
243 }
244}
245
247 const PaintMode paint_mode,
248 const int brush_type)
249{
250 if (paint->brush == nullptr) {
251 return;
252 }
253 const char *brush_type_name = brush_type_identifier_get(brush_type, paint_mode);
254 if (!brush_type_name || !brush_type_name[0]) {
255 return;
256 }
257
258 /* Update existing reference. */
260 paint, brush_type_name))
261 {
262 MEM_delete(existing_brush_ref->brush_asset_reference);
263 existing_brush_ref->brush_asset_reference = MEM_new<AssetWeakReference>(
264 __func__, *paint->brush_asset_reference);
265 }
266 /* Add new reference. */
267 else {
268 NamedBrushAssetReference *new_brush_ref = MEM_cnew<NamedBrushAssetReference>(__func__);
269
270 new_brush_ref->name = BLI_strdup(brush_type_name);
271 new_brush_ref->brush_asset_reference = MEM_new<AssetWeakReference>(
272 __func__, *paint->brush_asset_reference);
274 }
275}
276
278{
281
282 if (!BKE_paint_brush_poll(paint, brush)) {
283 /* Avoid switching tool when brush isn't valid for this mode anyway. */
284 return false;
285 }
286
287 /* If necessary, find a compatible tool to switch to. */
288 {
289 std::optional<int> brush_type = BKE_paint_get_brush_type_from_paintmode(brush, paint_mode);
290 if (!brush_type) {
292 WM_toolsystem_ref_set_by_id(C, "builtin.brush");
293 }
294 else if (!brush_type_matches_active_tool(C, *brush_type)) {
295 const char *brush_type_name = brush_type_identifier_get(*brush_type, paint_mode);
296 /* Calls into .py to query available tools. */
297 toolsystem_ref_set_by_brush_type(C, brush_type_name);
298 }
299 }
300
301 /* Do after switching tool, since switching tool will attempt to restore the last used brush of
302 * that tool (in #toolsystem_brush_activate_from_toolref_for_object_paint()). */
303 if (!BKE_paint_brush_set(paint, brush)) {
304 return false;
305 }
306
307 if (active_tool->runtime->brush_type == -1) {
308 /* Only update the main brush binding to reference the newly active brush. */
310 }
311 else {
312 toolsystem_brush_type_binding_update(paint, paint_mode, active_tool->runtime->brush_type);
313 }
314
315 return true;
316}
317
319 const WorkSpace *workspace,
320 const bToolRef *tref)
321{
322 const Main *bmain = CTX_data_main(C);
323 const bToolRef_Runtime *tref_rt = tref->runtime;
324
325 if (!tref_rt->data_block[0]) {
326 return;
327 }
328
330 const int i = RNA_enum_from_identifier(items, tref_rt->data_block);
331 if (i == -1) {
332 return;
333 }
334
335 const wmWindowManager *wm = static_cast<wmWindowManager *>(bmain->wm.first);
336 LISTBASE_FOREACH (wmWindow *, win, &wm->windows) {
337 if (workspace == WM_window_get_active_workspace(win)) {
338 Scene *scene = WM_window_get_active_scene(win);
339 ToolSettings *ts = scene->toolsettings;
340 ts->particle.brushtype = items[i].value;
341 }
342 }
343}
344
346 const WorkSpace *workspace,
347 const bToolRef *tref)
348{
349 Main *bmain = CTX_data_main(C);
350 bToolRef_Runtime *tref_rt = tref->runtime;
351
352 const PaintMode paint_mode = BKE_paintmode_get_from_tool(tref);
353 BLI_assert(paint_mode != PaintMode::Invalid);
354
355 wmWindowManager *wm = static_cast<wmWindowManager *>(bmain->wm.first);
356 LISTBASE_FOREACH (wmWindow *, win, &wm->windows) {
357 if (workspace != WM_window_get_active_workspace(win)) {
358 continue;
359 }
360 Scene *scene = WM_window_get_active_scene(win);
361 BKE_paint_ensure_from_paintmode(scene, paint_mode);
362 Paint *paint = BKE_paint_get_active_from_paintmode(scene, paint_mode);
363
364 /* Attempt to re-activate a brush remembered for this brush type, as stored in a brush
365 * binding. */
366 if (tref_rt->brush_type != -1) {
367 std::optional<AssetWeakReference> brush_asset_reference =
368 [&]() -> std::optional<AssetWeakReference> {
369 const char *brush_type_name = brush_type_identifier_get(tref_rt->brush_type, paint_mode);
371 paint, brush_type_name);
372
373 if (brush_ref && brush_ref->brush_asset_reference) {
374 return *brush_ref->brush_asset_reference;
375 }
376 /* No remembered brush found for this type, use a default for the type. */
378 tref_rt->brush_type);
379 }();
380
381 if (brush_asset_reference) {
382 BKE_paint_brush_set(bmain, paint, &*brush_asset_reference);
383 }
384 }
385 /* Re-activate the main brush, regardless of the brush type. */
386 else {
390 }
391 else {
392 std::optional<AssetWeakReference> main_brush_asset_reference =
393 [&]() -> std::optional<AssetWeakReference> {
396 }
398 std::nullopt);
399 }();
400
401 if (main_brush_asset_reference) {
402 BKE_paint_brush_set(bmain, paint, &*main_brush_asset_reference);
404 }
405 }
406 }
407 }
408}
409
414 const WorkSpace *workspace,
415 const bToolRef *tref)
416{
418
419 if (tref->space_type == SPACE_VIEW3D) {
420 if (tref->mode == CTX_MODE_PARTICLE) {
422 }
423 else {
425 }
426 }
427}
428
431static void toolsystem_ref_link(const bContext *C, WorkSpace *workspace, bToolRef *tref)
432{
433 bToolRef_Runtime *tref_rt = tref->runtime;
434 if (tref_rt->gizmo_group[0]) {
435 const char *idname = tref_rt->gizmo_group;
436 wmGizmoGroupType *gzgt = WM_gizmogrouptype_find(idname, false);
437 if (gzgt != nullptr) {
438 if ((gzgt->flag & WM_GIZMOGROUPTYPE_TOOL_INIT) == 0) {
440 /* Even if the group-type was has been linked, it's possible the space types
441 * were not previously using it. (happens with multiple windows). */
444 }
445 }
446 }
447 else {
448 CLOG_WARN(WM_LOG_TOOLS, "'%s' widget not found", idname);
449 }
450 }
451
452 if (tref_rt->flag & TOOLREF_FLAG_USE_BRUSHES) {
453 toolsystem_brush_activate_from_toolref(C, workspace, tref);
454 }
455}
456
457static void toolsystem_refresh_ref(const bContext *C, WorkSpace *workspace, bToolRef *tref)
458{
459 if (tref->runtime == nullptr) {
460 return;
461 }
462 /* Currently same operation. */
463 toolsystem_ref_link(C, workspace, tref);
464}
465void WM_toolsystem_refresh(const bContext *C, WorkSpace *workspace, const bToolKey *tkey)
466{
467 bToolRef *tref = WM_toolsystem_ref_find(workspace, tkey);
468 if (tref) {
469 toolsystem_refresh_ref(C, workspace, tref);
470 }
471}
472
473static void toolsystem_reinit_ref(bContext *C, WorkSpace *workspace, bToolRef *tref)
474{
475 toolsystem_reinit_with_toolref(C, workspace, tref);
476}
477void WM_toolsystem_reinit(bContext *C, WorkSpace *workspace, const bToolKey *tkey)
478{
479 bToolRef *tref = WM_toolsystem_ref_find(workspace, tkey);
480 if (tref) {
481 toolsystem_reinit_ref(C, workspace, tref);
482 }
483}
484
486{
487 LISTBASE_FOREACH (bToolRef *, tref, &workspace->tools) {
488 tref->tag = 0;
489 }
490
491 LISTBASE_FOREACH (bToolRef *, tref, &workspace->tools) {
492 if (tref->runtime) {
493 if (tref->tag == 0) {
494 toolsystem_unlink_ref(C, workspace, tref);
495 tref->tag = 1;
496 }
497 }
498 }
499}
500
502{
503 BLI_assert(0);
504 LISTBASE_FOREACH (bToolRef *, tref, &workspace->tools) {
505 toolsystem_refresh_ref(C, workspace, tref);
506 }
507}
509{
511 const Scene *scene = WM_window_get_active_scene(win);
513 LISTBASE_FOREACH (ScrArea *, area, &screen->areabase) {
514 if (((1 << area->spacetype) & WM_TOOLSYSTEM_SPACE_MASK) == 0) {
515 continue;
516 }
517
519 bToolKey tkey{};
520 tkey.space_type = area->spacetype;
521 tkey.mode = WM_toolsystem_mode_from_spacetype(scene, view_layer, area, area->spacetype);
522 bToolRef *tref = WM_toolsystem_ref_find(workspace, &tkey);
523 if (tref) {
524 if (tref->tag == 0) {
525 toolsystem_reinit_ref(C, workspace, tref);
526 tref->tag = 1;
527 }
528 }
529 }
530}
531
533 WorkSpace *workspace,
534 bToolRef *tref,
535 const bToolRef_Runtime *tref_rt,
536 const char *idname)
537{
538 Main *bmain = CTX_data_main(C);
539
540 if (tref->runtime) {
541 toolsystem_unlink_ref(C, workspace, tref);
542 }
543
544 STRNCPY(tref->idname, idname);
545
546 if (tref->runtime == nullptr) {
547 tref->runtime = static_cast<bToolRef_Runtime *>(MEM_callocN(sizeof(*tref->runtime), __func__));
548 }
549
550 if (tref_rt != tref->runtime) {
551 *tref->runtime = *tref_rt;
552 }
553
554 /* Ideally Python could check this gizmo group flag and not
555 * pass in the argument to begin with. */
556 bool use_fallback_keymap = false;
557
558 if (tref->idname_fallback[0] || tref->runtime->keymap_fallback[0]) {
559 if (tref_rt->flag & TOOLREF_FLAG_FALLBACK_KEYMAP) {
560 use_fallback_keymap = true;
561 }
562 else if (tref_rt->gizmo_group[0]) {
563 wmGizmoGroupType *gzgt = WM_gizmogrouptype_find(tref_rt->gizmo_group, false);
564 if (gzgt) {
566 use_fallback_keymap = true;
567 }
568 }
569 }
570 }
571 if (use_fallback_keymap == false) {
572 tref->idname_fallback[0] = '\0';
573 tref->runtime->keymap_fallback[0] = '\0';
574 }
575
576 toolsystem_ref_link(C, workspace, tref);
577
578 toolsystem_refresh_screen_from_active_tool(bmain, workspace, tref);
579
580 /* Set the cursor if possible, if not - it's fine as entering the region will refresh it. */
581 {
582 wmWindow *win = CTX_wm_window(C);
583 if (win != nullptr) {
584 win->addmousemove = true;
585 win->tag_cursor_refresh = true;
586 }
587 }
588
589 {
590 wmMsgBus *mbus = CTX_wm_message_bus(C);
591 WM_msg_publish_rna_prop(mbus, &workspace->id, workspace, WorkSpace, tools);
592 }
593}
594
596{
597 bToolRef_Runtime *tref_rt = tref->runtime;
598 if ((tref_rt == nullptr) || (tref_rt->data_block[0] == '\0')) {
599 return;
600 }
601 wmWindowManager *wm = static_cast<wmWindowManager *>(bmain->wm.first);
602 LISTBASE_FOREACH (wmWindow *, win, &wm->windows) {
603 if (workspace != WM_window_get_active_workspace(win)) {
604 continue;
605 }
606
607 Scene *scene = WM_window_get_active_scene(win);
608 ToolSettings *ts = scene->toolsettings;
610 BKE_view_layer_synced_ensure(scene, view_layer);
611 const Object *ob = BKE_view_layer_active_object_get(view_layer);
612 if (ob == nullptr) {
613 /* Pass. */
614 }
615 if ((tref->space_type == SPACE_VIEW3D) && (tref->mode == CTX_MODE_PARTICLE)) {
616 if (ob->mode & OB_MODE_PARTICLE_EDIT) {
618 const int i = RNA_enum_from_value(items, ts->particle.brushtype);
619 const EnumPropertyItem *item = &items[i];
620 if (!STREQ(tref_rt->data_block, item->identifier)) {
621 STRNCPY(tref_rt->data_block, item->identifier);
622 SNPRINTF(tref->idname, "builtin_brush.%s", item->name);
623 }
624 }
625 }
626 }
627}
628
630{
631 Main *bmain = CTX_data_main(C);
632
633 BLI_assert(CTX_wm_window(C) == nullptr);
634
635 LISTBASE_FOREACH (WorkSpace *, workspace, &bmain->workspaces) {
636 LISTBASE_FOREACH (bToolRef *, tref, &workspace->tools) {
637 MEM_SAFE_FREE(tref->runtime);
638 }
639 }
640
641 /* Rely on screen initialization for gizmos. */
642}
643
644static bool toolsystem_key_ensure_check(const bToolKey *tkey)
645{
646 switch (tkey->space_type) {
647 case SPACE_VIEW3D:
648 return true;
649 case SPACE_IMAGE:
650 if (ELEM(tkey->mode, SI_MODE_PAINT, SI_MODE_UV)) {
651 return true;
652 }
653 break;
654 case SPACE_NODE:
655 return true;
656 case SPACE_SEQ:
657 return true;
658 }
659 return false;
660}
661
663 ViewLayer *view_layer,
664 ScrArea *area,
665 int space_type)
666{
667 int mode = -1;
668 switch (space_type) {
669 case SPACE_VIEW3D: {
670 /* 'area' may be nullptr in this case. */
671 BKE_view_layer_synced_ensure(scene, view_layer);
672 Object *obact = BKE_view_layer_active_object_get(view_layer);
673 if (obact != nullptr) {
674 Object *obedit = OBEDIT_FROM_OBACT(obact);
675 mode = CTX_data_mode_enum_ex(obedit, obact, eObjectMode(obact->mode));
676 }
677 else {
678 mode = CTX_MODE_OBJECT;
679 }
680 break;
681 }
682 case SPACE_IMAGE: {
683 SpaceImage *sima = static_cast<SpaceImage *>(area->spacedata.first);
684 mode = sima->mode;
685 break;
686 }
687 case SPACE_NODE: {
688 mode = 0;
689 break;
690 }
691 case SPACE_SEQ: {
692 SpaceSeq *sseq = static_cast<SpaceSeq *>(area->spacedata.first);
693 mode = sseq->view;
694 break;
695 }
696 }
697 return mode;
698}
699
701 ViewLayer *view_layer,
702 ScrArea *area,
703 bToolKey *tkey)
704{
705 int space_type = SPACE_EMPTY;
706 int mode = -1;
707
708 if (area != nullptr) {
709 space_type = area->spacetype;
710 mode = WM_toolsystem_mode_from_spacetype(scene, view_layer, area, space_type);
711 }
712
713 if (mode != -1) {
714 tkey->space_type = space_type;
715 tkey->mode = mode;
716 return true;
717 }
718 return false;
719}
720
722{
723 Main *bmain = CTX_data_main(C);
724
725 struct {
726 wmWindow *win;
727 ScrArea *area;
728 ARegion *region;
729 bool is_set;
730 } context_prev = {nullptr};
731
732 for (wmWindowManager *wm = static_cast<wmWindowManager *>(bmain->wm.first); wm;
733 wm = static_cast<wmWindowManager *>(wm->id.next))
734 {
735 LISTBASE_FOREACH (wmWindow *, win, &wm->windows) {
738 const Scene *scene = WM_window_get_active_scene(win);
740 /* Could skip loop for modes that don't depend on space type. */
741 int space_type_mask_handled = 0;
742 LISTBASE_FOREACH (ScrArea *, area, &screen->areabase) {
743 /* Don't change the space type of the active tool, only update its mode. */
744 const int space_type_mask = (1 << area->spacetype);
745 if ((space_type_mask & WM_TOOLSYSTEM_SPACE_MASK) &&
746 ((space_type_mask_handled & space_type_mask) == 0))
747 {
748 space_type_mask_handled |= space_type_mask;
749 bToolKey tkey{};
750 tkey.space_type = area->spacetype;
751 tkey.mode = WM_toolsystem_mode_from_spacetype(scene, view_layer, area, area->spacetype);
752 bToolRef *tref = WM_toolsystem_ref_find(workspace, &tkey);
753 if (tref != area->runtime.tool) {
754 if (context_prev.is_set == false) {
755 context_prev.win = CTX_wm_window(C);
756 context_prev.area = CTX_wm_area(C);
757 context_prev.region = CTX_wm_region(C);
758 context_prev.is_set = true;
759 }
760
761 CTX_wm_window_set(C, win);
762 CTX_wm_area_set(C, area);
763
764 toolsystem_reinit_ensure_toolref(C, workspace, &tkey, nullptr);
765 }
766 }
767 }
768 }
769 }
770
771 if (context_prev.is_set) {
772 CTX_wm_window_set(C, context_prev.win);
773 CTX_wm_area_set(C, context_prev.area);
774 CTX_wm_region_set(C, context_prev.region);
775 }
776
778
779 LISTBASE_FOREACH (WorkSpace *, workspace, &bmain->workspaces) {
780 if (workspace->id.tag & ID_TAG_DOIT) {
781 workspace->id.tag &= ~ID_TAG_DOIT;
782 /* Refresh to ensure data is initialized.
783 * This is needed because undo can load a state which no longer has the underlying DNA data
784 * needed for the tool (un-initialized paint-slots for eg), see: #64339. */
785 LISTBASE_FOREACH (bToolRef *, tref, &workspace->tools) {
786 toolsystem_refresh_ref(C, workspace, tref);
787 }
788 }
789 }
790}
791
793 const Scene *scene,
794 ViewLayer *view_layer,
795 ScrArea *area)
796{
797 const bool is_tool_set_prev = area->runtime.is_tool_set;
798 const bToolRef *tref_prev = area->runtime.tool;
799
800 area->runtime.tool = nullptr;
801 area->runtime.is_tool_set = true;
802 const int mode = WM_toolsystem_mode_from_spacetype(scene, view_layer, area, area->spacetype);
803 LISTBASE_FOREACH (bToolRef *, tref, &workspace->tools) {
804 if (tref->space_type == area->spacetype) {
805 if (tref->mode == mode) {
806 area->runtime.tool = tref;
807 break;
808 }
809 }
810 }
811 return !(is_tool_set_prev && (tref_prev == area->runtime.tool));
812}
813
815{
817 bool space_type_has_tools[SPACE_TYPE_NUM] = {false};
818 LISTBASE_FOREACH (bToolRef *, tref, &workspace->tools) {
819 space_type_has_tools[tref->space_type] = true;
820 }
822 const Scene *scene = WM_window_get_active_scene(win);
824 LISTBASE_FOREACH (ScrArea *, area, &screen->areabase) {
825 area->runtime.tool = nullptr;
826 area->runtime.is_tool_set = true;
827 if (space_type_has_tools[area->spacetype]) {
828 WM_toolsystem_refresh_screen_area(workspace, scene, view_layer, area);
829 }
830 }
831}
832
834{
835 /* Update all ScrArea's tools. */
836 for (wmWindowManager *wm = static_cast<wmWindowManager *>(bmain->wm.first); wm;
837 wm = static_cast<wmWindowManager *>(wm->id.next))
838 {
839 LISTBASE_FOREACH (wmWindow *, win, &wm->windows) {
841 }
842 }
843}
844
846 WorkSpace *workspace,
847 bToolRef *tref)
848{
849 /* Update all ScrArea's tools. */
850 for (wmWindowManager *wm = static_cast<wmWindowManager *>(bmain->wm.first); wm;
851 wm = static_cast<wmWindowManager *>(wm->id.next))
852 {
853 LISTBASE_FOREACH (wmWindow *, win, &wm->windows) {
854 if (workspace == WM_window_get_active_workspace(win)) {
856 const Scene *scene = WM_window_get_active_scene(win);
858 LISTBASE_FOREACH (ScrArea *, area, &screen->areabase) {
859 if (area->spacetype == tref->space_type) {
860 int mode = WM_toolsystem_mode_from_spacetype(scene, view_layer, area, area->spacetype);
861 if (mode == tref->mode) {
862 area->runtime.tool = tref;
863 area->runtime.is_tool_set = true;
864 }
865 }
866 }
867 }
868 }
869 }
870}
871
873 bContext *C, WorkSpace *workspace, const bToolKey *tkey, const char *name, bool cycle)
874{
875 wmOperatorType *ot = WM_operatortype_find("WM_OT_tool_set_by_id", false);
876 /* On startup, Python operators are not yet loaded. */
877 if (ot == nullptr) {
878 return nullptr;
879 }
880
881/* Some contexts use the current space type (image editor for e.g.),
882 * ensure this is set correctly or there is no area. */
883#ifndef NDEBUG
884 /* Exclude this check for some space types where the space type isn't used. */
886 ScrArea *area = CTX_wm_area(C);
887 BLI_assert(area == nullptr || area->spacetype == tkey->space_type);
888 }
889#endif
890
891 PointerRNA op_props;
893 RNA_string_set(&op_props, "name", name);
894
896
897 RNA_enum_set(&op_props, "space_type", tkey->space_type);
898 RNA_boolean_set(&op_props, "cycle", cycle);
899
900 WM_operator_name_call_ptr(C, ot, WM_OP_EXEC_DEFAULT, &op_props, nullptr);
902
903 bToolRef *tref = WM_toolsystem_ref_find(workspace, tkey);
904
905 if (tref) {
906 Main *bmain = CTX_data_main(C);
907 toolsystem_refresh_screen_from_active_tool(bmain, workspace, tref);
908 }
909
910 return (tref && STREQ(tref->idname, name)) ? tref : nullptr;
911}
912
914{
915 const Scene *scene = CTX_data_scene(C);
916 ViewLayer *view_layer = CTX_data_view_layer(C);
917 ScrArea *area = CTX_wm_area(C);
918 bToolKey tkey;
919 if (WM_toolsystem_key_from_context(scene, view_layer, area, &tkey)) {
920 WorkSpace *workspace = CTX_wm_workspace(C);
921 return WM_toolsystem_ref_set_by_id_ex(C, workspace, &tkey, name, false);
922 }
923 return nullptr;
924}
925
926static void toolsystem_ref_set_by_brush_type(bContext *C, const char *brush_type)
927{
928 const Scene *scene = CTX_data_scene(C);
929 ViewLayer *view_layer = CTX_data_view_layer(C);
930 ScrArea *area = CTX_wm_area(C);
931 const bToolKey tkey = toolsystem_key_from_context_or_view3d(scene, view_layer, area);
932 WorkSpace *workspace = CTX_wm_workspace(C);
933
934 wmOperatorType *ot = WM_operatortype_find("WM_OT_tool_set_by_brush_type", false);
935 /* On startup, Python operators are not yet loaded. */
936 if (ot == nullptr) {
937 return;
938 }
939
940/* Some contexts use the current space type (image editor for e.g.),
941 * ensure this is set correctly or there is no area. */
942#ifndef NDEBUG
943 /* Exclude this check for some space types where the space type isn't used. */
945 ScrArea *area = CTX_wm_area(C);
946 BLI_assert(area == nullptr || area->spacetype == tkey.space_type);
947 }
948#endif
949
950 PointerRNA op_props;
952 RNA_string_set(&op_props, "brush_type", brush_type);
953
955
956 RNA_enum_set(&op_props, "space_type", tkey.space_type);
957
958 WM_operator_name_call_ptr(C, ot, WM_OP_EXEC_DEFAULT, &op_props, nullptr);
960
961 bToolRef *tref = WM_toolsystem_ref_find(workspace, &tkey);
962
963 if (tref) {
964 Main *bmain = CTX_data_main(C);
965 toolsystem_refresh_screen_from_active_tool(bmain, workspace, tref);
966 }
967}
968
970{
971 bToolKey tkey{};
972 tkey.space_type = tref->space_type;
973 tkey.mode = tref->mode;
974 WM_toolsystem_ref_set_by_id_ex(C, workspace, &tkey, tref->idname, false);
975}
976
977static const char *toolsystem_default_tool(const bToolKey *tkey)
978{
979 switch (tkey->space_type) {
980 case SPACE_VIEW3D:
981 switch (tkey->mode) {
982 case CTX_MODE_SCULPT:
995 return "builtin.brush";
997 return "builtin_brush.Comb";
999 return "builtin.select_text";
1000 }
1001 break;
1002 case SPACE_IMAGE:
1003 switch (tkey->mode) {
1004 case SI_MODE_PAINT:
1005 return "builtin.brush";
1006 }
1007 break;
1008 case SPACE_NODE: {
1009 return "builtin.select_box";
1010 }
1011 case SPACE_SEQ: {
1012 return "builtin.select_box";
1013 }
1014 }
1015
1016 return "builtin.select_box";
1017}
1018
1023 WorkSpace *workspace,
1024 const bToolKey *tkey,
1025 const char *default_tool)
1026{
1027 bToolRef *tref;
1028 if (WM_toolsystem_ref_ensure(workspace, tkey, &tref)) {
1029 if (default_tool == nullptr) {
1030 default_tool = toolsystem_default_tool(tkey);
1031 }
1032 STRNCPY(tref->idname, default_tool);
1033 }
1034 toolsystem_reinit_with_toolref(C, workspace, tref);
1035 return tref;
1036}
1037
1039{
1040 const Scene *scene = CTX_data_scene(C);
1041 ViewLayer *view_layer = CTX_data_view_layer(C);
1042 int space_type = SPACE_VIEW3D;
1043 bToolKey tkey{};
1044 tkey.space_type = space_type;
1045 tkey.mode = WM_toolsystem_mode_from_spacetype(scene, view_layer, nullptr, space_type);
1046 toolsystem_reinit_ensure_toolref(C, workspace, &tkey, nullptr);
1047}
1048
1050{
1051 WorkSpace *workspace = CTX_wm_workspace(C);
1052 if (workspace) {
1054 }
1055
1056 /* Multi window support. */
1057 Main *bmain = CTX_data_main(C);
1058 wmWindowManager *wm = static_cast<wmWindowManager *>(bmain->wm.first);
1059 if (!BLI_listbase_is_single(&wm->windows)) {
1060 wmWindow *win_prev = CTX_wm_window(C);
1061 ScrArea *area_prev = CTX_wm_area(C);
1062 ARegion *region_prev = CTX_wm_region(C);
1063
1064 LISTBASE_FOREACH (wmWindow *, win, &wm->windows) {
1065 if (win != win_prev) {
1066 WorkSpace *workspace_iter = WM_window_get_active_workspace(win);
1067 if (workspace_iter != workspace) {
1068
1069 CTX_wm_window_set(C, win);
1070
1072
1073 CTX_wm_window_set(C, win_prev);
1074 CTX_wm_area_set(C, area_prev);
1075 CTX_wm_region_set(C, region_prev);
1076 }
1077 }
1078 }
1079 }
1080}
1081
1083 bContext *C, WorkSpace *workspace, const Scene *scene, ViewLayer *view_layer, ScrArea *area)
1084{
1085 bToolKey tkey{};
1086 tkey.space_type = area->spacetype;
1087 tkey.mode = WM_toolsystem_mode_from_spacetype(scene, view_layer, area, area->spacetype);
1088 if (toolsystem_key_ensure_check(&tkey)) {
1089 toolsystem_reinit_ensure_toolref(C, workspace, &tkey, nullptr);
1090 }
1091}
1092
1094{
1096 return tref_rt && (tref_rt->flag & TOOLREF_FLAG_USE_BRUSHES);
1097}
1098
1100{
1102 return tref_rt && (tref_rt->cursor != WM_CURSOR_DEFAULT);
1103}
1104
1106 wmMsgSubscribeKey * /*msg_key*/,
1107 wmMsgSubscribeValue *msg_val)
1108{
1109 ScrArea *area = static_cast<ScrArea *>(msg_val->user_data);
1110 Main *bmain = CTX_data_main(C);
1111 wmWindow *win = static_cast<wmWindow *>(((wmWindowManager *)bmain->wm.first)->windows.first);
1112 if (win->next != nullptr) {
1113 do {
1114 bScreen *screen = WM_window_get_active_screen(win);
1115 if (BLI_findindex(&screen->areabase, area) != -1) {
1116 break;
1117 }
1118 } while ((win = win->next));
1119 }
1120
1121 WorkSpace *workspace = WM_window_get_active_workspace(win);
1122 const Scene *scene = WM_window_get_active_scene(win);
1123 ViewLayer *view_layer = WM_window_get_active_view_layer(win);
1124
1125 bToolKey tkey{};
1126 tkey.space_type = area->spacetype;
1127 tkey.mode = WM_toolsystem_mode_from_spacetype(scene, view_layer, area, area->spacetype);
1128 WM_toolsystem_refresh(C, workspace, &tkey);
1129 WM_toolsystem_refresh_screen_area(workspace, scene, view_layer, area);
1130}
1131
1132static IDProperty *idprops_ensure_named_group(IDProperty *group, const char *idname)
1133{
1134 IDProperty *prop = IDP_GetPropertyFromGroup(group, idname);
1135 if ((prop == nullptr) || (prop->type != IDP_GROUP)) {
1136 prop = blender::bke::idprop::create_group(__func__).release();
1137 STRNCPY(prop->name, idname);
1138 IDP_ReplaceInGroup_ex(group, prop, nullptr);
1139 }
1140 return prop;
1141}
1142
1144{
1145 IDProperty *group = tref->properties;
1146 if (group == nullptr) {
1147 return nullptr;
1148 }
1149 return IDP_GetPropertyFromGroup(group, tref->idname);
1150}
1151
1153{
1154 if (tref->properties == nullptr) {
1155 tref->properties = blender::bke::idprop::create_group(__func__).release();
1156 }
1157 return idprops_ensure_named_group(tref->properties, tref->idname);
1158}
1159
1161 const char *idname,
1162 StructRNA *type,
1163 PointerRNA *r_ptr)
1164{
1166 IDProperty *prop = group ? IDP_GetPropertyFromGroup(group, idname) : nullptr;
1167 *r_ptr = RNA_pointer_create(nullptr, type, prop);
1168 return (prop != nullptr);
1169}
1170
1172 const char *idname,
1173 StructRNA *type,
1174 PointerRNA *r_ptr)
1175{
1177 IDProperty *prop = idprops_ensure_named_group(group, idname);
1178 *r_ptr = RNA_pointer_create(nullptr, type, prop);
1179}
1180
1182 PointerRNA *dst_ptr,
1183 PointerRNA *src_ptr,
1185{
1186 *dst_ptr = *src_ptr;
1187 if (dst_ptr->data) {
1188 dst_ptr->data = IDP_CopyProperty(static_cast<const IDProperty *>(dst_ptr->data));
1189 }
1190 else {
1191 dst_ptr->data = blender::bke::idprop::create_group("wmOpItemProp").release();
1192 }
1194 if (group != nullptr) {
1196 if (prop) {
1197 /* Important key-map items properties don't get overwritten by the tools.
1198 * - When a key-map item doesn't set a property, the tool-systems is used.
1199 * - When it does, it overrides the tool-system.
1200 *
1201 * This way the default action can be to follow the top-bar tool-settings &
1202 * modifier keys can be used to perform different actions that aren't clobbered here.
1203 */
1204 IDP_MergeGroup(static_cast<IDProperty *>(dst_ptr->data), prop, false);
1205 }
1206 }
1207}
WorkSpace * CTX_wm_workspace(const bContext *C)
@ CTX_MODE_VERTEX_GPENCIL_LEGACY
@ CTX_MODE_WEIGHT_GPENCIL_LEGACY
@ CTX_MODE_SCULPT_GPENCIL_LEGACY
@ CTX_MODE_PAINT_GREASE_PENCIL
@ CTX_MODE_PAINT_GPENCIL_LEGACY
@ CTX_MODE_PAINT_TEXTURE
@ CTX_MODE_SCULPT_GREASE_PENCIL
@ CTX_MODE_PARTICLE
@ CTX_MODE_SCULPT
@ CTX_MODE_OBJECT
@ CTX_MODE_SCULPT_CURVES
@ CTX_MODE_EDIT_TEXT
@ CTX_MODE_WEIGHT_GREASE_PENCIL
@ CTX_MODE_VERTEX_GREASE_PENCIL
@ CTX_MODE_PAINT_VERTEX
@ CTX_MODE_PAINT_WEIGHT
ScrArea * CTX_wm_area(const bContext *C)
wmWindow * CTX_wm_window(const bContext *C)
Scene * CTX_data_scene(const bContext *C)
enum eContextObjectMode CTX_data_mode_enum_ex(const Object *obedit, const Object *ob, eObjectMode object_mode)
void CTX_wm_window_set(bContext *C, wmWindow *win)
Main * CTX_data_main(const bContext *C)
void CTX_wm_area_set(bContext *C, ScrArea *area)
void CTX_wm_region_set(bContext *C, ARegion *region)
ARegion * CTX_wm_region(const bContext *C)
wmMsgBus * CTX_wm_message_bus(const bContext *C)
ViewLayer * CTX_data_view_layer(const bContext *C)
IDProperty * IDP_GetPropertyFromGroup(const IDProperty *prop, const char *name) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
Definition idprop.cc:763
void IDP_ReplaceInGroup_ex(IDProperty *group, IDProperty *prop, IDProperty *prop_exist)
Definition idprop.cc:654
IDProperty * IDP_CopyProperty(const IDProperty *prop) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
Definition idprop.cc:861
void IDP_MergeGroup(IDProperty *dest, const IDProperty *src, bool do_overwrite) ATTR_NONNULL()
Definition idprop.cc:717
void BKE_view_layer_synced_ensure(const Scene *scene, ViewLayer *view_layer)
Object * BKE_view_layer_active_object_get(const ViewLayer *view_layer)
PaintMode
Definition BKE_paint.hh:99
bool BKE_paint_brush_set(Paint *paint, Brush *brush)
Definition paint.cc:714
Paint * BKE_paint_get_active_from_paintmode(Scene *sce, PaintMode mode)
Definition paint.cc:371
const EnumPropertyItem * BKE_paint_get_tool_enum_from_paintmode(PaintMode mode)
Definition paint.cc:408
std::optional< AssetWeakReference > BKE_paint_brush_type_default_reference(eObjectMode ob_mode, std::optional< int > brush_type)
Definition paint.cc:1030
std::optional< int > BKE_paint_get_brush_type_from_paintmode(const Brush *brush, const PaintMode mode)
Definition paint.cc:1308
PaintMode BKE_paintmode_get_active_from_context(const bContext *C)
Definition paint.cc:506
bool BKE_paint_brush_poll(const Paint *paint, const Brush *brush)
Definition paint.cc:659
PaintMode BKE_paintmode_get_from_tool(const bToolRef *tref)
Definition paint.cc:565
bool BKE_paint_ensure_from_paintmode(Scene *sce, PaintMode mode)
Definition paint.cc:320
void BKE_workspace_id_tag_all_visible(Main *bmain, int tag) ATTR_NONNULL()
Definition workspace.cc:546
#define BLI_assert_unreachable()
Definition BLI_assert.h:97
#define BLI_assert(a)
Definition BLI_assert.h:50
void BLI_addhead(struct ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition listbase.cc:90
#define LISTBASE_FOREACH(type, var, list)
void void BLI_INLINE bool BLI_listbase_is_single(const struct ListBase *lb)
int BLI_findindex(const struct ListBase *listbase, const void *vlink) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
void * BLI_findstring_ptr(const struct ListBase *listbase, const char *id, int offset) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
char * BLI_strdup(const char *str) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1) ATTR_MALLOC
Definition string.c:40
#define STRNCPY(dst, src)
Definition BLI_string.h:593
#define SNPRINTF(dst, format,...)
Definition BLI_string.h:597
#define ELEM(...)
#define STREQ(a, b)
#define CLOG_WARN(clg_ref,...)
Definition CLG_log.h:181
ID and Library types, which are fundamental for SDNA.
@ ID_TAG_DOIT
Definition DNA_ID.h:1003
@ IDP_GROUP
eObjectMode
@ OB_MODE_PARTICLE_EDIT
Object is a sort of wrapper for general info.
#define OBEDIT_FROM_OBACT(ob)
@ SPACE_NODE
@ SPACE_SEQ
@ SPACE_EMPTY
@ SPACE_IMAGE
@ SPACE_VIEW3D
#define SPACE_TYPE_NUM
@ SI_MODE_PAINT
@ SI_MODE_UV
@ TOOLREF_FLAG_FALLBACK_KEYMAP
@ TOOLREF_FLAG_USE_BRUSHES
Read Guarded memory(de)allocation.
#define MEM_SAFE_FREE(v)
@ WM_GIZMOGROUPTYPE_TOOL_INIT
@ WM_GIZMOGROUPTYPE_TOOL_FALLBACK_KEYMAP
#define WM_TOOLSYSTEM_SPACE_MASK
#define WM_TOOLSYSTEM_SPACE_MASK_MODE_FROM_SPACE
CLG_LogRef * WM_LOG_TOOLS
@ WM_OP_EXEC_DEFAULT
Definition WM_types.hh:225
#define offsetof(t, d)
void *(* MEM_callocN)(size_t len, const char *str)
Definition mallocn.cc:42
std::unique_ptr< IDProperty, IDPropertyDeleter > create_group(StringRefNull prop_name, eIDPropertyFlag flags={})
Allocate a new IDProperty of type IDP_GROUP.
std::optional< AssetWeakReference > asset_edit_weak_reference_from_id(const ID &id)
void RNA_string_set(PointerRNA *ptr, const char *name, const char *value)
void RNA_boolean_set(PointerRNA *ptr, const char *name, bool value)
int RNA_enum_from_identifier(const EnumPropertyItem *item, const char *identifier)
int RNA_enum_from_value(const EnumPropertyItem *item, const int value)
void RNA_enum_set(PointerRNA *ptr, const char *name, int value)
PointerRNA RNA_pointer_create(ID *id, StructRNA *type, void *data)
const EnumPropertyItem rna_enum_particle_edit_hair_brush_items[]
const char * identifier
Definition RNA_types.hh:506
const char * name
Definition RNA_types.hh:510
char name[64]
Definition DNA_ID.h:163
char type
Definition DNA_ID.h:154
void * first
ListBase wm
Definition BKE_main.hh:239
ListBase workspaces
Definition BKE_main.hh:246
struct AssetWeakReference * brush_asset_reference
unsigned short ob_mode
struct Paint_Runtime runtime
struct AssetWeakReference * brush_asset_reference
struct Brush * brush
ToolSystemBrushBindings tool_brush_bindings
void * data
Definition RNA_types.hh:42
struct ParticleEditSettings particle
struct AssetWeakReference * main_brush_asset_reference
IDProperty * properties
bToolRef_Runtime * runtime
char idname_fallback[64]
wmGizmoMapType_Params gzmap_params
eWM_GizmoFlagGroupTypeFlag flag
const char * idname
Definition WM_types.hh:992
struct wmWindow * next
@ WM_CURSOR_DEFAULT
Definition wm_cursors.hh:15
int WM_operator_name_call_ptr(bContext *C, wmOperatorType *ot, wmOperatorCallContext context, PointerRNA *properties, const wmEvent *event)
wmOperatorType * ot
Definition wm_files.cc:4125
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)
void WM_gizmoconfig_update_tag_group_type_init(wmGizmoMapType *gzmap_type, wmGizmoGroupType *gzgt)
wmGizmoMapType * WM_gizmomaptype_ensure(const wmGizmoMapType_Params *gzmap_params)
#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)
void WM_operator_properties_free(PointerRNA *ptr)
static void toolsystem_brush_activate_from_toolref_for_object_paint(const bContext *C, const WorkSpace *workspace, const bToolRef *tref)
void WM_toolsystem_reinit(bContext *C, WorkSpace *workspace, const bToolKey *tkey)
void WM_toolsystem_update_from_context(bContext *C, WorkSpace *workspace, const Scene *scene, ViewLayer *view_layer, ScrArea *area)
bToolRef * WM_toolsystem_ref_find(WorkSpace *workspace, const bToolKey *tkey)
bool WM_toolsystem_key_from_context(const Scene *scene, ViewLayer *view_layer, ScrArea *area, bToolKey *tkey)
void WM_toolsystem_init(const 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)
bToolRef_Runtime * WM_toolsystem_runtime_find(WorkSpace *workspace, const bToolKey *tkey)
void WM_toolsystem_refresh_all(const bContext *C, WorkSpace *workspace)
static const bToolRef * toolsystem_active_tool_from_context_or_view3d(const bContext *C)
static void toolsystem_refresh_screen_from_active_tool(Main *bmain, WorkSpace *workspace, bToolRef *tref)
IDProperty * WM_toolsystem_ref_properties_ensure_idprops(bToolRef *tref)
static void toolsystem_ref_set_by_brush_type(bContext *C, const char *brush_type)
static void toolsystem_brush_activate_from_toolref_for_object_particle(const bContext *C, const WorkSpace *workspace, const bToolRef *tref)
void WM_toolsystem_unlink(bContext *C, WorkSpace *workspace, const bToolKey *tkey)
void WM_toolsystem_reinit_all(bContext *C, wmWindow *win)
int WM_toolsystem_mode_from_spacetype(const Scene *scene, ViewLayer *view_layer, ScrArea *area, int space_type)
bool WM_toolsystem_active_tool_is_brush(const bContext *C)
void WM_toolsystem_refresh_screen_all(Main *bmain)
static bool toolsystem_key_ensure_check(const bToolKey *tkey)
static void toolsystem_refresh_ref(const bContext *C, WorkSpace *workspace, bToolRef *tref)
static void toolsystem_unlink_ref(bContext *C, WorkSpace *, bToolRef *tref)
void WM_toolsystem_refresh(const bContext *C, WorkSpace *workspace, const bToolKey *tkey)
void WM_toolsystem_ref_properties_init_for_keymap(bToolRef *tref, PointerRNA *dst_ptr, PointerRNA *src_ptr, wmOperatorType *ot)
static void toolsystem_brush_type_binding_update(Paint *paint, const PaintMode paint_mode, const int brush_type)
static const char * brush_type_identifier_get(const int brush_type, const PaintMode paint_mode)
static void toolsystem_ref_link(const bContext *C, WorkSpace *workspace, bToolRef *tref)
bToolRef * WM_toolsystem_ref_set_by_id(bContext *C, const char *name)
static void toolsystem_main_brush_binding_update_from_active(Paint *paint)
static NamedBrushAssetReference * toolsystem_brush_type_binding_lookup(const Paint *paint, const char *brush_type_name)
IDProperty * WM_toolsystem_ref_properties_get_idprops(bToolRef *tref)
bToolRef * WM_toolsystem_ref_set_by_id_ex(bContext *C, WorkSpace *workspace, const bToolKey *tkey, const char *name, bool cycle)
static void toolsystem_reinit_with_toolref(bContext *C, WorkSpace *, bToolRef *tref)
void WM_toolsystem_do_msg_notify_tag_refresh(bContext *C, wmMsgSubscribeKey *, wmMsgSubscribeValue *msg_val)
bool WM_toolsystem_activate_brush_and_tool(bContext *C, Paint *paint, Brush *brush)
bToolRef_Runtime * WM_toolsystem_runtime_from_context(const bContext *C)
bool WM_toolsystem_refresh_screen_area(WorkSpace *workspace, const Scene *scene, ViewLayer *view_layer, ScrArea *area)
bool WM_toolsystem_active_tool_has_custom_cursor(const bContext *C)
void WM_toolsystem_ref_set_from_runtime(bContext *C, WorkSpace *workspace, bToolRef *tref, const bToolRef_Runtime *tref_rt, const char *idname)
void WM_toolsystem_refresh_screen_window(wmWindow *win)
static void toolsystem_reinit_ref(bContext *C, WorkSpace *workspace, bToolRef *tref)
void WM_toolsystem_update_from_context_view3d(bContext *C)
void WM_toolsystem_refresh_active(bContext *C)
void WM_toolsystem_unlink_all(bContext *C, WorkSpace *workspace)
static bToolRef * toolsystem_reinit_ensure_toolref(bContext *C, WorkSpace *workspace, const bToolKey *tkey, const char *default_tool)
static bToolKey toolsystem_key_from_context_or_view3d(const Scene *scene, ViewLayer *view_layer, ScrArea *area)
static const char * toolsystem_default_tool(const bToolKey *tkey)
bool WM_toolsystem_ref_ensure(WorkSpace *workspace, const bToolKey *tkey, bToolRef **r_tref)
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)
static void toolsystem_brush_activate_from_toolref(const bContext *C, const WorkSpace *workspace, const bToolRef *tref)
bToolRef * WM_toolsystem_ref_from_context(const bContext *C)
static IDProperty * idprops_ensure_named_group(IDProperty *group, const char *idname)
static bool brush_type_matches_active_tool(bContext *C, const int brush_type)
ViewLayer * WM_window_get_active_view_layer(const wmWindow *win)
Scene * WM_window_get_active_scene(const wmWindow *win)
WorkSpace * WM_window_get_active_workspace(const wmWindow *win)
bScreen * WM_window_get_active_screen(const wmWindow *win)