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