Blender V5.0
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
18
19#include <cstring>
20
21#include "CLG_log.h"
22
23#include "MEM_guardedalloc.h"
24
25#include "BLI_listbase.h"
26#include "BLI_string.h"
27#include "BLI_string_utf8.h"
28#include "BLI_utildefines.h"
29
30#include "DNA_ID.h"
31#include "DNA_brush_types.h"
32#include "DNA_object_types.h"
33#include "DNA_scene_types.h"
34#include "DNA_space_types.h"
36#include "DNA_workspace_types.h"
37
38#include "BKE_asset_edit.hh"
39#include "BKE_brush.hh"
40#include "BKE_context.hh"
41#include "BKE_global.hh"
42#include "BKE_idprop.hh"
43#include "BKE_layer.hh"
44#include "BKE_lib_id.hh"
45#include "BKE_main.hh"
46#include "BKE_paint.hh"
47#include "BKE_paint_types.hh"
48#include "BKE_workspace.hh"
49
50#include "RNA_access.hh"
51#include "RNA_enum_types.hh"
52
53#include "WM_api.hh"
54#include "WM_message.hh"
55#include "WM_toolsystem.hh" /* Own include. */
56#include "WM_types.hh"
57
58static void toolsystem_reinit_with_toolref(bContext *C, WorkSpace * /*workspace*/, bToolRef *tref);
60 WorkSpace *workspace,
61 const bToolKey *tkey,
62 const char *default_tool);
64 WorkSpace *workspace,
65 bToolRef *tref);
66static void toolsystem_ref_set_by_brush_type(bContext *C, const char *brush_type);
67
68static void toolsystem_ref_set_by_id_pending(Main *bmain,
69 bToolRef *tref,
70 const char *idname_pending);
71
72/* -------------------------------------------------------------------- */
75
77{
78 WorkSpace *workspace = CTX_wm_workspace(C);
79 if (workspace == nullptr) {
80 return nullptr;
81 }
82 const Scene *scene = CTX_data_scene(C);
83 ViewLayer *view_layer = CTX_data_view_layer(C);
84 ScrArea *area = CTX_wm_area(C);
85 if ((area == nullptr) || ((1 << area->spacetype) & WM_TOOLSYSTEM_SPACE_MASK) == 0) {
86 return nullptr;
87 }
88 bToolKey tkey{};
89 tkey.space_type = area->spacetype;
90 tkey.mode = WM_toolsystem_mode_from_spacetype(scene, view_layer, area, area->spacetype);
91 bToolRef *tref = WM_toolsystem_ref_find(workspace, &tkey);
92 /* We could return 'area->runtime.tool' in this case. */
93 if (area->runtime.is_tool_set) {
94 BLI_assert(tref == area->runtime.tool);
95 }
96 return tref;
97}
98
100{
102 return tref ? tref->runtime : nullptr;
103}
104
106{
108 LISTBASE_FOREACH (bToolRef *, tref, &workspace->tools) {
109 if ((tref->space_type == tkey->space_type) && (tref->mode == tkey->mode)) {
110 return tref;
111 }
112 }
113 return nullptr;
114}
115
117{
118 bToolRef *tref = WM_toolsystem_ref_find(workspace, tkey);
119 return tref ? tref->runtime : nullptr;
120}
121
122bool WM_toolsystem_ref_ensure(WorkSpace *workspace, const bToolKey *tkey, bToolRef **r_tref)
123{
124 bToolRef *tref = WM_toolsystem_ref_find(workspace, tkey);
125 if (tref) {
126 *r_tref = tref;
127 return false;
128 }
129 tref = MEM_callocN<bToolRef>(__func__);
130 BLI_addhead(&workspace->tools, tref);
131 tref->space_type = tkey->space_type;
132 tref->mode = tkey->mode;
133 *r_tref = tref;
134 return true;
135}
136
141 ViewLayer *view_layer,
142 ScrArea *area)
143{
144 bToolKey tkey{};
145
146 if (area && ((1 << area->spacetype) & WM_TOOLSYSTEM_SPACE_MASK)) {
147 tkey.space_type = area->spacetype;
148 tkey.mode = WM_toolsystem_mode_from_spacetype(scene, view_layer, area, area->spacetype);
149 return tkey;
150 }
151
152 /* Otherwise: Fallback to getting the active tool for 3D views. */
154 tkey.mode = WM_toolsystem_mode_from_spacetype(scene, view_layer, nullptr, SPACE_VIEW3D);
155 return tkey;
156}
157
166{
167 /* Current space & mode has its own active tool, use that. */
168 const ScrArea *area = CTX_wm_area(C);
169 if (area && ((1 << area->spacetype) & WM_TOOLSYSTEM_SPACE_MASK)) {
171 }
172
173 /* Otherwise: Fallback to getting the active tool for 3D views. */
174 WorkSpace *workspace = CTX_wm_workspace(C);
175 if (workspace == nullptr) {
176 return nullptr;
177 }
178 const Scene *scene = CTX_data_scene(C);
179 ViewLayer *view_layer = CTX_data_view_layer(C);
180 bToolKey tkey{};
182 tkey.mode = WM_toolsystem_mode_from_spacetype(scene, view_layer, nullptr, SPACE_VIEW3D);
183 return WM_toolsystem_ref_find(workspace, &tkey);
184}
185
187
188static void toolsystem_unlink_ref(bContext *C, WorkSpace * /*workspace*/, bToolRef *tref)
189{
190 bToolRef_Runtime *tref_rt = tref->runtime;
191
192 if (tref_rt->gizmo_group[0]) {
193 wmGizmoGroupType *gzgt = WM_gizmogrouptype_find(tref_rt->gizmo_group, false);
194 if (gzgt != nullptr) {
195 Main *bmain = CTX_data_main(C);
196 WM_gizmo_group_remove_by_tool(C, bmain, gzgt, tref);
197 }
198 }
199}
200void WM_toolsystem_unlink(bContext *C, WorkSpace *workspace, const bToolKey *tkey)
201{
202 bToolRef *tref = WM_toolsystem_ref_find(workspace, tkey);
203 if (tref && tref->runtime) {
204 toolsystem_unlink_ref(C, workspace, tref);
205 }
206}
207
208/* -------------------------------------------------------------------- */
211
212static const char *brush_type_identifier_get(const int brush_type, const PaintMode paint_mode)
213{
214 const EnumPropertyItem *type_enum = BKE_paint_get_tool_enum_from_paintmode(paint_mode);
215 const int item_idx = RNA_enum_from_value(type_enum, brush_type);
216 if (item_idx == -1) {
217 return "";
218 }
219 return type_enum[item_idx].identifier;
220}
221
222static bool brush_type_matches_active_tool(bContext *C, const int brush_type)
223{
225
226 if (active_tool->runtime == nullptr) {
227 /* Should only ever be null in background mode. */
228 BLI_assert(G.background);
229 return false;
230 }
231
232 if (!(active_tool->runtime->flag & TOOLREF_FLAG_USE_BRUSHES)) {
233 return false;
234 }
235
237 return active_tool->runtime->brush_type == brush_type;
238}
239
241 const char *brush_type_name)
242{
243 return static_cast<NamedBrushAssetReference *>(
245 brush_type_name,
247}
248
253{
256
257 if (paint->brush != nullptr) {
258 if (std::optional<AssetWeakReference> brush_asset_reference =
260 {
261 paint->tool_brush_bindings.main_brush_asset_reference = MEM_new<AssetWeakReference>(
262 __func__, *brush_asset_reference);
263 }
264 }
265}
266
268 const PaintMode paint_mode,
269 const int brush_type)
270{
271 if (paint->brush == nullptr) {
272 return;
273 }
274 const char *brush_type_name = brush_type_identifier_get(brush_type, paint_mode);
275 if (!brush_type_name || !brush_type_name[0]) {
276 return;
277 }
278
279 /* Update existing reference. */
281 paint, brush_type_name))
282 {
283 MEM_delete(existing_brush_ref->brush_asset_reference);
284 existing_brush_ref->brush_asset_reference = MEM_new<AssetWeakReference>(
285 __func__, *paint->brush_asset_reference);
286 }
287 /* Add new reference. */
288 else {
290
291 new_brush_ref->name = BLI_strdup(brush_type_name);
292 new_brush_ref->brush_asset_reference = MEM_new<AssetWeakReference>(
293 __func__, *paint->brush_asset_reference);
295 }
296}
297
299{
302
303 if (!BKE_paint_can_use_brush(paint, brush)) {
304 /* Avoid switching tool when brush isn't valid for this mode anyway. */
305 return false;
306 }
307
308 /* If necessary, find a compatible tool to switch to. */
309 {
310 std::optional<int> brush_type = BKE_paint_get_brush_type_from_paintmode(brush, paint_mode);
311 if (!brush_type) {
313 WM_toolsystem_ref_set_by_id(C, "builtin.brush");
314 }
315 else if (!brush_type_matches_active_tool(C, *brush_type)) {
316 const char *brush_type_name = brush_type_identifier_get(*brush_type, paint_mode);
317 /* Calls into .py to query available tools. */
318 toolsystem_ref_set_by_brush_type(C, brush_type_name);
319 }
320 }
321
322 /* Do after switching tool, since switching tool will attempt to restore the last used brush of
323 * that tool (in #toolsystem_brush_activate_from_toolref_for_object_paint()). */
324 if (!BKE_paint_brush_set(paint, brush)) {
325 return false;
326 }
327
328 if (active_tool->runtime->brush_type == -1) {
329 /* Only update the main brush binding to reference the newly active brush. */
331 }
332 else {
333 toolsystem_brush_type_binding_update(paint, paint_mode, active_tool->runtime->brush_type);
334 }
335
336 return true;
337}
338
340 const WorkSpace *workspace,
341 const bToolRef *tref)
342{
343 const bToolRef_Runtime *tref_rt = tref->runtime;
344
345 if (!tref_rt->data_block[0]) {
346 return;
347 }
348
350 const int i = RNA_enum_from_identifier(items, tref_rt->data_block);
351 if (i == -1) {
352 return;
353 }
354
355 const 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 Scene *scene = WM_window_get_active_scene(win);
359 ToolSettings *ts = scene->toolsettings;
360 ts->particle.brushtype = items[i].value;
361 }
362 }
363}
364
366 const WorkSpace *workspace,
367 const bToolRef *tref)
368{
369 bToolRef_Runtime *tref_rt = tref->runtime;
370
371 const PaintMode paint_mode = BKE_paintmode_get_from_tool(tref);
372 BLI_assert(paint_mode != PaintMode::Invalid);
373
374 wmWindowManager *wm = static_cast<wmWindowManager *>(bmain->wm.first);
375 LISTBASE_FOREACH (wmWindow *, win, &wm->windows) {
376 if (workspace != WM_window_get_active_workspace(win)) {
377 continue;
378 }
379 Scene *scene = WM_window_get_active_scene(win);
380 BKE_paint_ensure_from_paintmode(scene, paint_mode);
381 Paint *paint = BKE_paint_get_active_from_paintmode(scene, paint_mode);
382
383 /* Attempt to re-activate a brush remembered for this brush type, as stored in a brush
384 * binding. */
385 if (tref_rt->brush_type != -1) {
386 std::optional<AssetWeakReference> brush_asset_reference =
387 [&]() -> std::optional<AssetWeakReference> {
388 const char *brush_type_name = brush_type_identifier_get(tref_rt->brush_type, paint_mode);
390 paint, brush_type_name);
391
392 if (brush_ref && brush_ref->brush_asset_reference) {
393 return *brush_ref->brush_asset_reference;
394 }
395 /* No remembered brush found for this type, use a default for the type. */
396 return BKE_paint_brush_type_default_reference(paint->runtime->paint_mode,
397 tref_rt->brush_type);
398 }();
399
400 if (brush_asset_reference) {
401 BKE_paint_brush_set(bmain, paint, *brush_asset_reference);
402 }
403 }
404 /* Re-activate the main brush, regardless of the brush type. */
405 else {
409 }
410 else {
411 std::optional<AssetWeakReference> main_brush_asset_reference =
412 [&]() -> std::optional<AssetWeakReference> {
415 }
416 return BKE_paint_brush_type_default_reference(paint->runtime->paint_mode, std::nullopt);
417 }();
418
419 if (main_brush_asset_reference) {
420 BKE_paint_brush_set(bmain, paint, *main_brush_asset_reference);
422 }
423 }
424 }
425 }
426}
427
432 const WorkSpace *workspace,
433 const bToolRef *tref)
434{
436
437 if (tref->space_type == SPACE_VIEW3D) {
438 if (tref->mode == CTX_MODE_PARTICLE) {
440 }
441 else {
443 }
444 }
445 else if (tref->space_type == SPACE_IMAGE) {
446 if (tref->mode == SI_MODE_PAINT) {
448 }
449 }
450}
451
458 WorkSpace *workspace,
459 bToolRef *tref)
460{
461 if (tref->space_type == SPACE_VIEW3D) {
462 if (tref->mode == CTX_MODE_PAINT_TEXTURE) {
463 bToolKey tkey{};
464 tkey.space_type = SPACE_IMAGE;
465 tkey.mode = SI_MODE_PAINT;
466 bToolRef *tref_other = WM_toolsystem_ref_find(workspace, &tkey);
467 if (tref_other) {
468 toolsystem_ref_set_by_id_pending(bmain, tref_other, tref->idname);
469 }
470 }
471 }
472 else if (tref->space_type == SPACE_IMAGE) {
473 if (tref->mode == SI_MODE_PAINT) {
474 bToolKey tkey{};
477 bToolRef *tref_other = WM_toolsystem_ref_find(workspace, &tkey);
478 if (tref_other) {
479 toolsystem_ref_set_by_id_pending(bmain, tref_other, tref->idname);
480 }
481 }
482 }
483}
485 WorkSpace *workspace,
486 bToolRef *tref)
487{
488 const PaintMode paint_mode = BKE_paintmode_get_from_tool(tref);
489
490 wmWindowManager *wm = static_cast<wmWindowManager *>(bmain->wm.first);
491 LISTBASE_FOREACH (wmWindow *, win, &wm->windows) {
492 if (workspace != WM_window_get_active_workspace(win)) {
493 continue;
494 }
495 Scene *scene = WM_window_get_active_scene(win);
496 if (Paint *paint = BKE_paint_get_active_from_paintmode(scene, paint_mode)) {
498 }
499 }
500}
501
503
504static void toolsystem_ref_link(Main *bmain, WorkSpace *workspace, bToolRef *tref)
505{
506 bToolRef_Runtime *tref_rt = tref->runtime;
507 if (tref_rt->gizmo_group[0]) {
508 const char *idname = tref_rt->gizmo_group;
509 wmGizmoGroupType *gzgt = WM_gizmogrouptype_find(idname, false);
510 if (gzgt != nullptr) {
511 if ((gzgt->flag & WM_GIZMOGROUPTYPE_TOOL_INIT) == 0) {
513 /* Even if the group-type has been linked, it's possible the space types
514 * were not previously using it. (happens with multiple windows). */
517 }
518 }
519 }
520 else {
521 CLOG_WARN(WM_LOG_TOOL_GIZMO, "'%s' widget not found", idname);
522 }
523 }
524
525 if (tref_rt->flag & TOOLREF_FLAG_USE_BRUSHES) {
526 toolsystem_brush_activate_from_toolref(bmain, workspace, tref);
527 toolsystem_brush_sync_for_texture_paint(bmain, workspace, tref);
528 }
529 else {
530 toolsystem_brush_clear_paint_reference(bmain, workspace, tref);
531 }
532}
533
534static void toolsystem_refresh_ref(const bContext *C, WorkSpace *workspace, bToolRef *tref)
535{
536 if (tref->runtime == nullptr) {
537 return;
538 }
539 /* Currently same operation. */
540 toolsystem_ref_link(CTX_data_main(C), workspace, tref);
541}
542void WM_toolsystem_refresh(const bContext *C, WorkSpace *workspace, const bToolKey *tkey)
543{
544 bToolRef *tref = WM_toolsystem_ref_find(workspace, tkey);
545 if (tref) {
546 toolsystem_refresh_ref(C, workspace, tref);
547 }
548}
549
550static void toolsystem_reinit_ref(bContext *C, WorkSpace *workspace, bToolRef *tref)
551{
552 toolsystem_reinit_with_toolref(C, workspace, tref);
553}
554void WM_toolsystem_reinit(bContext *C, WorkSpace *workspace, const bToolKey *tkey)
555{
556 bToolRef *tref = WM_toolsystem_ref_find(workspace, tkey);
557 if (tref) {
558 toolsystem_reinit_ref(C, workspace, tref);
559 }
560}
561
563{
564 LISTBASE_FOREACH (bToolRef *, tref, &workspace->tools) {
565 tref->tag = 0;
566 }
567
568 LISTBASE_FOREACH (bToolRef *, tref, &workspace->tools) {
569 if (tref->runtime) {
570 if (tref->tag == 0) {
571 toolsystem_unlink_ref(C, workspace, tref);
572 tref->tag = 1;
573 }
574 }
575 }
576}
577
579{
580 BLI_assert(0);
581 LISTBASE_FOREACH (bToolRef *, tref, &workspace->tools) {
582 toolsystem_refresh_ref(C, workspace, tref);
583 }
584}
586{
588 const Scene *scene = WM_window_get_active_scene(win);
590 LISTBASE_FOREACH (ScrArea *, area, &screen->areabase) {
591 if (((1 << area->spacetype) & WM_TOOLSYSTEM_SPACE_MASK) == 0) {
592 continue;
593 }
594
596 bToolKey tkey{};
597 tkey.space_type = area->spacetype;
598 tkey.mode = WM_toolsystem_mode_from_spacetype(scene, view_layer, area, area->spacetype);
599 bToolRef *tref = WM_toolsystem_ref_find(workspace, &tkey);
600 if (tref) {
601 if (tref->tag == 0) {
602 toolsystem_reinit_ref(C, workspace, tref);
603 tref->tag = 1;
604 }
605 }
606 }
607}
608
610 WorkSpace *workspace,
611 bToolRef *tref,
612 const bToolRef_Runtime *tref_rt,
613 const char *idname)
614{
615 Main *bmain = CTX_data_main(C);
616
617 if (tref->runtime) {
618 toolsystem_unlink_ref(C, workspace, tref);
619 }
620
621 STRNCPY_UTF8(tref->idname, idname);
622
623 /* This immediate request supersedes any unhandled pending requests. */
624 tref->idname_pending[0] = '\0';
625
626 if (tref->runtime == nullptr) {
627 tref->runtime = MEM_callocN<bToolRef_Runtime>(__func__);
628 }
629
630 if (tref_rt != tref->runtime) {
631 *tref->runtime = *tref_rt;
632 }
633
634 /* Ideally Python could check this gizmo group flag and not
635 * pass in the argument to begin with. */
636 bool use_fallback_keymap = false;
637
638 if (tref->idname_fallback[0] || tref->runtime->keymap_fallback[0]) {
639 if (tref_rt->flag & TOOLREF_FLAG_FALLBACK_KEYMAP) {
640 use_fallback_keymap = true;
641 }
642 else if (tref_rt->gizmo_group[0]) {
643 wmGizmoGroupType *gzgt = WM_gizmogrouptype_find(tref_rt->gizmo_group, false);
644 if (gzgt) {
646 use_fallback_keymap = true;
647 }
648 }
649 }
650 }
651 if (use_fallback_keymap == false) {
652 tref->idname_fallback[0] = '\0';
653 tref->runtime->keymap_fallback[0] = '\0';
654 }
655
656 toolsystem_ref_link(bmain, workspace, tref);
657
658 toolsystem_refresh_screen_from_active_tool(bmain, workspace, tref);
659
660 /* Set the cursor if possible, if not - it's fine as entering the region will refresh it. */
661 {
662 wmWindow *win = CTX_wm_window(C);
663 if (win != nullptr) {
664 win->addmousemove = true;
665 win->tag_cursor_refresh = true;
666 }
667 }
668
669 {
671 WM_msg_publish_rna_prop(mbus, &workspace->id, workspace, WorkSpace, tools);
672 }
673}
674
676{
677 bToolRef_Runtime *tref_rt = tref->runtime;
678 if ((tref_rt == nullptr) || (tref_rt->data_block[0] == '\0')) {
679 return;
680 }
681 wmWindowManager *wm = static_cast<wmWindowManager *>(bmain->wm.first);
682 LISTBASE_FOREACH (wmWindow *, win, &wm->windows) {
683 if (workspace != WM_window_get_active_workspace(win)) {
684 continue;
685 }
686
687 Scene *scene = WM_window_get_active_scene(win);
688 ToolSettings *ts = scene->toolsettings;
690 BKE_view_layer_synced_ensure(scene, view_layer);
691 const Object *ob = BKE_view_layer_active_object_get(view_layer);
692 if (ob == nullptr) {
693 /* Pass. */
694 }
695 if ((tref->space_type == SPACE_VIEW3D) && (tref->mode == CTX_MODE_PARTICLE)) {
696 if (ob->mode & OB_MODE_PARTICLE_EDIT) {
698 const int i = RNA_enum_from_value(items, ts->particle.brushtype);
699 const EnumPropertyItem *item = &items[i];
700 if (!STREQ(tref_rt->data_block, item->identifier)) {
701 STRNCPY_UTF8(tref_rt->data_block, item->identifier);
702 SNPRINTF_UTF8(tref->idname, "builtin_brush.%s", item->name);
703 }
704 }
705 }
706 }
707}
708
710{
711 Main *bmain = CTX_data_main(C);
712
713 BLI_assert(CTX_wm_window(C) == nullptr);
714
715 LISTBASE_FOREACH (WorkSpace *, workspace, &bmain->workspaces) {
716 LISTBASE_FOREACH (bToolRef *, tref, &workspace->tools) {
717 MEM_SAFE_FREE(tref->runtime);
718 }
719 }
720
721 /* Rely on screen initialization for gizmos. */
722}
723
724static bool toolsystem_key_ensure_check(const bToolKey *tkey)
725{
726 switch (tkey->space_type) {
727 case SPACE_VIEW3D:
728 return true;
729 case SPACE_IMAGE:
731 return true;
732 }
733 break;
734 case SPACE_NODE:
735 return true;
736 case SPACE_SEQ:
737 return true;
738 }
739 return false;
740}
741
743 ViewLayer *view_layer,
744 ScrArea *area,
745 int space_type)
746{
747 int mode = -1;
748 switch (space_type) {
749 case SPACE_VIEW3D: {
750 /* 'area' may be nullptr in this case. */
751 BKE_view_layer_synced_ensure(scene, view_layer);
752 Object *obact = BKE_view_layer_active_object_get(view_layer);
753 if (obact != nullptr) {
754 Object *obedit = OBEDIT_FROM_OBACT(obact);
755 mode = CTX_data_mode_enum_ex(obedit, obact, eObjectMode(obact->mode));
756 }
757 else {
758 mode = CTX_MODE_OBJECT;
759 }
760 break;
761 }
762 case SPACE_IMAGE: {
763 SpaceImage *sima = static_cast<SpaceImage *>(area->spacedata.first);
764 mode = sima->mode;
765 break;
766 }
767 case SPACE_NODE: {
768 mode = 0;
769 break;
770 }
771 case SPACE_SEQ: {
772 SpaceSeq *sseq = static_cast<SpaceSeq *>(area->spacedata.first);
773 mode = sseq->view;
774 break;
775 }
776 }
777 return mode;
778}
779
781 ViewLayer *view_layer,
782 ScrArea *area,
783 bToolKey *tkey)
784{
785 int space_type = SPACE_EMPTY;
786 int mode = -1;
787
788 if (area != nullptr) {
789 space_type = area->spacetype;
790 mode = WM_toolsystem_mode_from_spacetype(scene, view_layer, area, space_type);
791 }
792
793 if (mode != -1) {
794 tkey->space_type = space_type;
795 tkey->mode = mode;
796 return true;
797 }
798 return false;
799}
800
802{
803 Main *bmain = CTX_data_main(C);
804
805 struct {
806 wmWindow *win;
807 ScrArea *area;
808 ARegion *region;
809 bool is_set;
810 } context_prev = {nullptr};
811
812 for (wmWindowManager *wm = static_cast<wmWindowManager *>(bmain->wm.first); wm;
813 wm = static_cast<wmWindowManager *>(wm->id.next))
814 {
815 LISTBASE_FOREACH (wmWindow *, win, &wm->windows) {
818 const Scene *scene = WM_window_get_active_scene(win);
820 /* Could skip loop for modes that don't depend on space type. */
821 int space_type_mask_handled = 0;
822 LISTBASE_FOREACH (ScrArea *, area, &screen->areabase) {
823 /* Don't change the space type of the active tool, only update its mode. */
824 const int space_type_mask = (1 << area->spacetype);
825 if ((space_type_mask & WM_TOOLSYSTEM_SPACE_MASK) &&
826 ((space_type_mask_handled & space_type_mask) == 0))
827 {
828 space_type_mask_handled |= space_type_mask;
829 bToolKey tkey{};
830 tkey.space_type = area->spacetype;
831 tkey.mode = WM_toolsystem_mode_from_spacetype(scene, view_layer, area, area->spacetype);
832 bToolRef *tref = WM_toolsystem_ref_find(workspace, &tkey);
833 if (tref != area->runtime.tool) {
834 if (context_prev.is_set == false) {
835 context_prev.win = CTX_wm_window(C);
836 context_prev.area = CTX_wm_area(C);
837 context_prev.region = CTX_wm_region(C);
838 context_prev.is_set = true;
839 }
840
841 CTX_wm_window_set(C, win);
842 CTX_wm_area_set(C, area);
843
844 toolsystem_reinit_ensure_toolref(C, workspace, &tkey, nullptr);
845 }
846 }
847 }
848 }
849 }
850
851 if (context_prev.is_set) {
852 CTX_wm_window_set(C, context_prev.win);
853 CTX_wm_area_set(C, context_prev.area);
854 CTX_wm_region_set(C, context_prev.region);
855 }
856
858
859 LISTBASE_FOREACH (WorkSpace *, workspace, &bmain->workspaces) {
860 if (workspace->id.tag & ID_TAG_DOIT) {
861 workspace->id.tag &= ~ID_TAG_DOIT;
862 /* Refresh to ensure data is initialized.
863 * This is needed because undo can load a state which no longer has the underlying DNA data
864 * needed for the tool (un-initialized paint-slots for eg), see: #64339. */
865 LISTBASE_FOREACH (bToolRef *, tref, &workspace->tools) {
866 toolsystem_refresh_ref(C, workspace, tref);
867 }
868 }
869 }
870}
871
873 const Scene *scene,
874 ViewLayer *view_layer,
875 ScrArea *area)
876{
877 const bool is_tool_set_prev = area->runtime.is_tool_set;
878 const bToolRef *tref_prev = area->runtime.tool;
879
880 area->runtime.tool = nullptr;
881 area->runtime.is_tool_set = true;
882 const int mode = WM_toolsystem_mode_from_spacetype(scene, view_layer, area, area->spacetype);
883 LISTBASE_FOREACH (bToolRef *, tref, &workspace->tools) {
884 if (tref->space_type == area->spacetype) {
885 if (tref->mode == mode) {
886 area->runtime.tool = tref;
887 break;
888 }
889 }
890 }
891 return !(is_tool_set_prev && (tref_prev == area->runtime.tool));
892}
893
895{
897 bool space_type_has_tools[SPACE_TYPE_NUM] = {false};
898 LISTBASE_FOREACH (bToolRef *, tref, &workspace->tools) {
899 space_type_has_tools[tref->space_type] = true;
900 }
902 const Scene *scene = WM_window_get_active_scene(win);
904 LISTBASE_FOREACH (ScrArea *, area, &screen->areabase) {
905 area->runtime.tool = nullptr;
906 area->runtime.is_tool_set = true;
907 if (space_type_has_tools[area->spacetype]) {
908 WM_toolsystem_refresh_screen_area(workspace, scene, view_layer, area);
909 }
910 }
911}
912
914{
915 /* Update all ScrArea's tools. */
916 for (wmWindowManager *wm = static_cast<wmWindowManager *>(bmain->wm.first); wm;
917 wm = static_cast<wmWindowManager *>(wm->id.next))
918 {
919 LISTBASE_FOREACH (wmWindow *, win, &wm->windows) {
921 }
922 }
923}
924
926 WorkSpace *workspace,
927 bToolRef *tref)
928{
929 /* Update all ScrArea's tools. */
930 for (wmWindowManager *wm = static_cast<wmWindowManager *>(bmain->wm.first); wm;
931 wm = static_cast<wmWindowManager *>(wm->id.next))
932 {
933 LISTBASE_FOREACH (wmWindow *, win, &wm->windows) {
934 if (workspace == WM_window_get_active_workspace(win)) {
936 const Scene *scene = WM_window_get_active_scene(win);
938 LISTBASE_FOREACH (ScrArea *, area, &screen->areabase) {
939 if (area->spacetype == tref->space_type) {
940 int mode = WM_toolsystem_mode_from_spacetype(scene, view_layer, area, area->spacetype);
941 if (mode == tref->mode) {
942 area->runtime.tool = tref;
943 area->runtime.is_tool_set = true;
944 }
945 }
946 }
947 }
948 }
949 }
950}
951
953 bContext *C, WorkSpace *workspace, const bToolKey *tkey, const char *name, bool cycle)
954{
955 wmOperatorType *ot = WM_operatortype_find("WM_OT_tool_set_by_id", false);
956 /* On startup, Python operators are not yet loaded. */
957 if (ot == nullptr) {
958 return nullptr;
959 }
960
961/* Some contexts use the current space type (e.g. image editor),
962 * ensure this is set correctly or there is no area. */
963#ifndef NDEBUG
964 /* Exclude this check for some space types where the space type isn't used. */
966 ScrArea *area = CTX_wm_area(C);
967 BLI_assert(area == nullptr || area->spacetype == tkey->space_type);
968 }
969#endif
970
971 PointerRNA op_props;
973 RNA_string_set(&op_props, "name", name);
974
976
977 RNA_enum_set(&op_props, "space_type", tkey->space_type);
978 RNA_boolean_set(&op_props, "cycle", cycle);
979
982
983 bToolRef *tref = WM_toolsystem_ref_find(workspace, tkey);
984
985 if (tref) {
986 Main *bmain = CTX_data_main(C);
987 toolsystem_refresh_screen_from_active_tool(bmain, workspace, tref);
988 }
989
990 return (tref && STREQ(tref->idname, name)) ? tref : nullptr;
991}
992
994{
995 const Scene *scene = CTX_data_scene(C);
996 ViewLayer *view_layer = CTX_data_view_layer(C);
997 ScrArea *area = CTX_wm_area(C);
998 bToolKey tkey;
999 if (WM_toolsystem_key_from_context(scene, view_layer, area, &tkey)) {
1000 WorkSpace *workspace = CTX_wm_workspace(C);
1001 return WM_toolsystem_ref_set_by_id_ex(C, workspace, &tkey, name, false);
1002 }
1003 return nullptr;
1004}
1005
1006static void toolsystem_ref_set_by_brush_type(bContext *C, const char *brush_type)
1007{
1008 const Scene *scene = CTX_data_scene(C);
1009 ViewLayer *view_layer = CTX_data_view_layer(C);
1010 ScrArea *area = CTX_wm_area(C);
1011 const bToolKey tkey = toolsystem_key_from_context_or_view3d(scene, view_layer, area);
1012 WorkSpace *workspace = CTX_wm_workspace(C);
1013
1014 wmOperatorType *ot = WM_operatortype_find("WM_OT_tool_set_by_brush_type", false);
1015 /* On startup, Python operators are not yet loaded. */
1016 if (ot == nullptr) {
1017 return;
1018 }
1019
1020/* Some contexts use the current space type (e.g. image editor),
1021 * ensure this is set correctly or there is no area. */
1022#ifndef NDEBUG
1023 /* Exclude this check for some space types where the space type isn't used. */
1025 ScrArea *area = CTX_wm_area(C);
1026 BLI_assert(area == nullptr || area->spacetype == tkey.space_type);
1027 }
1028#endif
1029
1030 PointerRNA op_props;
1032 RNA_string_set(&op_props, "brush_type", brush_type);
1033
1035
1036 RNA_enum_set(&op_props, "space_type", tkey.space_type);
1037
1039 WM_operator_properties_free(&op_props);
1040
1041 bToolRef *tref = WM_toolsystem_ref_find(workspace, &tkey);
1042
1043 if (tref) {
1044 Main *bmain = CTX_data_main(C);
1045 toolsystem_refresh_screen_from_active_tool(bmain, workspace, tref);
1046 }
1047}
1048
1057 bToolRef *tref,
1058 const char *idname_pending)
1059{
1060 BLI_assert(idname_pending[0]);
1061
1062 /* Check if the pending or current tool is already set to the requested value. */
1063 const bool this_match = STREQ(idname_pending, tref->idname);
1064 if (tref->idname_pending[0]) {
1065 const bool next_match = STREQ(idname_pending, tref->idname_pending);
1066 if (next_match) {
1067 return;
1068 }
1069 /* Highly unlikely but possible the current active tool matches the name.
1070 * In this case clear pending as there is nothing to do. */
1071 if (this_match) {
1072 tref->idname_pending[0] = '\0';
1073 return;
1074 }
1075 }
1076 else {
1077 if (this_match) {
1078 return;
1079 }
1080 }
1081
1082 STRNCPY_UTF8(tref->idname_pending, idname_pending);
1083
1084 /* If there would be a convenient way to know which screens used which work-spaces,
1085 * that could be used here. */
1086 LISTBASE_FOREACH (bScreen *, screen, &bmain->screens) {
1087 LISTBASE_FOREACH (ScrArea *, area, &screen->areabase) {
1088 if (area->runtime.tool == tref) {
1089 area->runtime.tool = nullptr;
1090 area->runtime.is_tool_set = false;
1091 area->flag |= AREA_FLAG_ACTIVE_TOOL_UPDATE;
1092 }
1093 }
1094 }
1095}
1096
1098{
1099 bToolKey tkey{};
1100 tkey.space_type = tref->space_type;
1101 tkey.mode = tref->mode;
1102
1103 const char *idname = tref->idname_pending[0] ? tref->idname_pending : tref->idname;
1104
1105 WM_toolsystem_ref_set_by_id_ex(C, workspace, &tkey, idname, false);
1106
1107 /* Never attempt the pending name again, if it's not found, no need to keep trying. */
1108 tref->idname_pending[0] = '\0';
1109}
1110
1111static const char *toolsystem_default_tool(const bToolKey *tkey)
1112{
1113 switch (tkey->space_type) {
1114 case SPACE_VIEW3D:
1115 switch (tkey->mode) {
1116 case CTX_MODE_SCULPT:
1129 return "builtin.brush";
1130 case CTX_MODE_PARTICLE:
1131 return "builtin_brush.Comb";
1132 case CTX_MODE_EDIT_TEXT:
1133 return "builtin.select_text";
1134 }
1135 break;
1136 case SPACE_IMAGE:
1137 switch (tkey->mode) {
1138 case SI_MODE_PAINT:
1139 return "builtin.brush";
1140 case SI_MODE_VIEW:
1141 return "builtin.sample";
1142 case SI_MODE_MASK:
1143 return "builtin.select_box";
1144 }
1145 break;
1146 case SPACE_NODE: {
1147 return "builtin.select_box";
1148 }
1149 case SPACE_SEQ: {
1150 return "builtin.select_box";
1151 }
1152 }
1153
1154 return "builtin.select_box";
1155}
1156
1161 WorkSpace *workspace,
1162 const bToolKey *tkey,
1163 const char *default_tool)
1164{
1165 bToolRef *tref;
1166 if (WM_toolsystem_ref_ensure(workspace, tkey, &tref)) {
1167 if (default_tool == nullptr) {
1168 default_tool = toolsystem_default_tool(tkey);
1169 }
1170 STRNCPY_UTF8(tref->idname, default_tool);
1171 }
1172 toolsystem_reinit_with_toolref(C, workspace, tref);
1173 return tref;
1174}
1175
1177{
1178 const Scene *scene = CTX_data_scene(C);
1179 ViewLayer *view_layer = CTX_data_view_layer(C);
1180 int space_type = SPACE_VIEW3D;
1181 bToolKey tkey{};
1182 tkey.space_type = space_type;
1183 tkey.mode = WM_toolsystem_mode_from_spacetype(scene, view_layer, nullptr, space_type);
1184 toolsystem_reinit_ensure_toolref(C, workspace, &tkey, nullptr);
1185}
1186
1188{
1189 WorkSpace *workspace = CTX_wm_workspace(C);
1190 if (workspace) {
1192 }
1193
1194 /* Multi window support. */
1195 Main *bmain = CTX_data_main(C);
1196 wmWindowManager *wm = static_cast<wmWindowManager *>(bmain->wm.first);
1197 if (!BLI_listbase_is_single(&wm->windows)) {
1198 wmWindow *win_prev = CTX_wm_window(C);
1199 ScrArea *area_prev = CTX_wm_area(C);
1200 ARegion *region_prev = CTX_wm_region(C);
1201
1202 LISTBASE_FOREACH (wmWindow *, win, &wm->windows) {
1203 if (win != win_prev) {
1204 WorkSpace *workspace_iter = WM_window_get_active_workspace(win);
1205 if (workspace_iter != workspace) {
1206
1207 CTX_wm_window_set(C, win);
1208
1210
1211 CTX_wm_window_set(C, win_prev);
1212 CTX_wm_area_set(C, area_prev);
1213 CTX_wm_region_set(C, region_prev);
1214 }
1215 }
1216 }
1217 }
1218}
1219
1221 bContext *C, WorkSpace *workspace, const Scene *scene, ViewLayer *view_layer, ScrArea *area)
1222{
1223 bToolKey tkey{};
1224 tkey.space_type = area->spacetype;
1225 tkey.mode = WM_toolsystem_mode_from_spacetype(scene, view_layer, area, area->spacetype);
1226 if (toolsystem_key_ensure_check(&tkey)) {
1227 toolsystem_reinit_ensure_toolref(C, workspace, &tkey, nullptr);
1228 }
1229}
1230
1232{
1234 return tref_rt && (tref_rt->flag & TOOLREF_FLAG_USE_BRUSHES);
1235}
1236
1238{
1240 return tref_rt && (tref_rt->cursor != WM_CURSOR_DEFAULT);
1241}
1242
1244 wmMsgSubscribeKey * /*msg_key*/,
1245 wmMsgSubscribeValue *msg_val)
1246{
1247 ScrArea *area = static_cast<ScrArea *>(msg_val->user_data);
1248 Main *bmain = CTX_data_main(C);
1249 wmWindow *win = static_cast<wmWindow *>(((wmWindowManager *)bmain->wm.first)->windows.first);
1250 if (win->next != nullptr) {
1251 do {
1252 bScreen *screen = WM_window_get_active_screen(win);
1253 if (BLI_findindex(&screen->areabase, area) != -1) {
1254 break;
1255 }
1256 } while ((win = win->next));
1257 }
1258
1259 WorkSpace *workspace = WM_window_get_active_workspace(win);
1260 const Scene *scene = WM_window_get_active_scene(win);
1261 ViewLayer *view_layer = WM_window_get_active_view_layer(win);
1262
1263 bToolKey tkey{};
1264 tkey.space_type = area->spacetype;
1265 tkey.mode = WM_toolsystem_mode_from_spacetype(scene, view_layer, area, area->spacetype);
1266 WM_toolsystem_refresh(C, workspace, &tkey);
1267 WM_toolsystem_refresh_screen_area(workspace, scene, view_layer, area);
1268}
1269
1270static IDProperty *idprops_ensure_named_group(IDProperty *group, const char *idname)
1271{
1272 IDProperty *prop = IDP_GetPropertyFromGroup(group, idname);
1273 if ((prop == nullptr) || (prop->type != IDP_GROUP)) {
1274 prop = blender::bke::idprop::create_group(__func__).release();
1275 STRNCPY_UTF8(prop->name, idname);
1276 IDP_ReplaceInGroup_ex(group, prop, nullptr, 0);
1277 }
1278 return prop;
1279}
1280
1282{
1283 IDProperty *group = tref->properties;
1284 if (group == nullptr) {
1285 return nullptr;
1286 }
1287 return IDP_GetPropertyFromGroup(group, tref->idname);
1288}
1289
1291{
1292 if (tref->properties == nullptr) {
1293 tref->properties = blender::bke::idprop::create_group(__func__).release();
1294 }
1295 return idprops_ensure_named_group(tref->properties, tref->idname);
1296}
1297
1299 const char *idname,
1300 StructRNA *type,
1301 PointerRNA *r_ptr)
1302{
1304 IDProperty *prop = group ? IDP_GetPropertyFromGroup(group, idname) : nullptr;
1305 *r_ptr = RNA_pointer_create_discrete(nullptr, type, prop);
1306 return (prop != nullptr);
1307}
1308
1310 const char *idname,
1311 StructRNA *type,
1312 PointerRNA *r_ptr)
1313{
1315 IDProperty *prop = idprops_ensure_named_group(group, idname);
1316 *r_ptr = RNA_pointer_create_discrete(nullptr, type, prop);
1317}
1318
1320 PointerRNA *dst_ptr,
1321 PointerRNA *src_ptr,
1323{
1324 *dst_ptr = *src_ptr;
1325 if (dst_ptr->data) {
1326 dst_ptr->data = IDP_CopyProperty(static_cast<const IDProperty *>(dst_ptr->data));
1327 }
1328 else {
1329 dst_ptr->data = blender::bke::idprop::create_group("wmOpItemProp").release();
1330 }
1332 if (group != nullptr) {
1333 IDProperty *prop = IDP_GetPropertyFromGroup(group, ot->idname);
1334 if (prop) {
1335 /* Important key-map items properties don't get overwritten by the tools.
1336 * - When a key-map item doesn't set a property, the tool-systems is used.
1337 * - When it does, it overrides the tool-system.
1338 *
1339 * This way the default action can be to follow the top-bar tool-settings &
1340 * modifier keys can be used to perform different actions that aren't clobbered here.
1341 */
1342 IDP_MergeGroup(static_cast<IDProperty *>(dst_ptr->data), prop, false);
1343 }
1344 }
1345}
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, blender::StringRef name) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
Definition idprop.cc:747
void IDP_ReplaceInGroup_ex(IDProperty *group, IDProperty *prop, IDProperty *prop_exist, int flag)
Definition idprop.cc:645
IDProperty * IDP_CopyProperty(const IDProperty *prop) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
Definition idprop.cc:863
void IDP_MergeGroup(IDProperty *dest, const IDProperty *src, bool do_overwrite) ATTR_NONNULL()
Definition idprop.cc:712
void BKE_view_layer_synced_ensure(const Scene *scene, ViewLayer *view_layer)
Object * BKE_view_layer_active_object_get(const ViewLayer *view_layer)
std::optional< AssetWeakReference > BKE_paint_brush_type_default_reference(PaintMode paint_mode, std::optional< int > brush_type)
Definition paint.cc:1033
bool BKE_paint_brush_set(Paint *paint, Brush *brush)
Definition paint.cc:710
Paint * BKE_paint_get_active_from_paintmode(Scene *sce, PaintMode mode)
Definition paint.cc:374
const EnumPropertyItem * BKE_paint_get_tool_enum_from_paintmode(PaintMode mode)
Definition paint.cc:409
void BKE_paint_previous_asset_reference_clear(Paint *paint)
Definition paint.cc:1120
bool BKE_paint_can_use_brush(const Paint *paint, const Brush *brush)
Definition paint.cc:655
PaintMode BKE_paintmode_get_active_from_context(const bContext *C)
Definition paint.cc:505
PaintMode BKE_paintmode_get_from_tool(const bToolRef *tref)
Definition paint.cc:561
std::optional< int > BKE_paint_get_brush_type_from_paintmode(const Brush *brush, PaintMode mode)
Definition paint.cc:1340
bool BKE_paint_ensure_from_paintmode(Scene *sce, PaintMode mode)
Definition paint.cc:326
PaintMode
void BKE_workspace_id_tag_all_visible(Main *bmain, int tag) ATTR_NONNULL()
Definition workspace.cc:547
#define BLI_assert_unreachable()
Definition BLI_assert.h:93
#define BLI_assert(a)
Definition BLI_assert.h:46
int BLI_findindex(const ListBase *listbase, const void *vlink) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
Definition listbase.cc:586
#define LISTBASE_FOREACH(type, var, list)
void BLI_addhead(ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition listbase.cc:91
void * BLI_findstring_ptr(const ListBase *listbase, const char *id, int offset) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
Definition listbase.cc:651
void void BLI_INLINE bool BLI_listbase_is_single(const ListBase *lb)
char * BLI_strdup(const char *str) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1) ATTR_MALLOC
Definition string.cc:41
#define SNPRINTF_UTF8(dst, format,...)
#define STRNCPY_UTF8(dst, src)
#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.
@ ID_TAG_DOIT
Definition DNA_ID.h:1036
@ IDP_GROUP
eObjectMode
@ OB_MODE_PARTICLE_EDIT
Object is a sort of wrapper for general info.
#define OBEDIT_FROM_OBACT(ob)
@ AREA_FLAG_ACTIVE_TOOL_UPDATE
@ SPACE_NODE
@ SPACE_SEQ
@ SPACE_EMPTY
@ SPACE_IMAGE
@ SPACE_VIEW3D
#define SPACE_TYPE_NUM
@ SI_MODE_PAINT
@ SI_MODE_VIEW
@ SI_MODE_MASK
@ SI_MODE_UV
@ TOOLREF_FLAG_FALLBACK_KEYMAP
@ TOOLREF_FLAG_USE_BRUSHES
Read Guarded memory(de)allocation.
#define MEM_SAFE_FREE(v)
#define C
Definition RandGen.cpp:29
@ 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_TOOL_GIZMO
#define offsetof(t, d)
void * MEM_callocN(size_t len, const char *str)
Definition mallocn.cc:118
#define G(x, y, z)
std::unique_ptr< IDProperty, IDPropertyDeleter > create_group(StringRef prop_name, eIDPropertyFlag flags={})
Allocate a new IDProperty of type IDP_GROUP.
std::optional< AssetWeakReference > asset_edit_weak_reference_from_id(const ID &id)
const char * name
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_discrete(ID *id, StructRNA *type, void *data)
const EnumPropertyItem rna_enum_particle_edit_hair_brush_items[]
const char * identifier
Definition RNA_types.hh:657
const char * name
Definition RNA_types.hh:661
char name[64]
Definition DNA_ID.h:164
char type
Definition DNA_ID.h:156
void * first
ListBase wm
Definition BKE_main.hh:307
ListBase screens
Definition BKE_main.hh:292
ListBase workspaces
Definition BKE_main.hh:315
struct AssetWeakReference * brush_asset_reference
struct AssetWeakReference * brush_asset_reference
struct Brush * brush
ToolSystemBrushBindings tool_brush_bindings
PaintRuntimeHandle * runtime
void * data
Definition RNA_types.hh:53
struct ToolSettings * toolsettings
struct bToolRef * tool
ListBase spacedata
ScrArea_Runtime runtime
struct ParticleEditSettings particle
struct AssetWeakReference * main_brush_asset_reference
ListBase areabase
IDProperty * properties
bToolRef_Runtime * runtime
char idname_fallback[64]
char idname_pending[64]
wmGizmoMapType_Params gzmap_params
eWM_GizmoFlagGroupTypeFlag flag
struct wmWindow * next
i
Definition text_draw.cc:230
@ WM_CURSOR_DEFAULT
Definition wm_cursors.hh:15
wmOperatorStatus WM_operator_name_call_ptr(bContext *C, wmOperatorType *ot, blender::wm::OpCallContext context, PointerRNA *properties, const wmEvent *event)
wmOperatorType * ot
Definition wm_files.cc:4237
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 StringRef 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_particle(const Main *bmain, 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 toolsystem_ref_link(Main *bmain, WorkSpace *workspace, bToolRef *tref)
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)
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)
static void toolsystem_brush_sync_for_texture_paint(Main *bmain, WorkSpace *workspace, bToolRef *tref)
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)
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)
static void toolsystem_brush_clear_paint_reference(Main *bmain, WorkSpace *workspace, bToolRef *tref)
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)
static void toolsystem_brush_activate_from_toolref(Main *bmain, const WorkSpace *workspace, const bToolRef *tref)
void WM_toolsystem_refresh_screen_window(wmWindow *win)
static void toolsystem_reinit_ref(bContext *C, WorkSpace *workspace, bToolRef *tref)
static void toolsystem_ref_set_by_id_pending(Main *bmain, bToolRef *tref, const char *idname_pending)
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 void toolsystem_brush_activate_from_toolref_for_object_paint(Main *bmain, const WorkSpace *workspace, const bToolRef *tref)
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)
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)