Blender V4.5
space_buttons.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2008 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
8
9#include <cstring>
10
11#include "MEM_guardedalloc.h"
12
13#include "DNA_scene_types.h"
14#include "DNA_space_types.h"
15#include "DNA_view2d_types.h"
16
17#include "BLI_bitmap.h"
18#include "BLI_listbase.h"
19#include "BLI_span.hh"
20#include "BLI_string.h"
21#include "BLI_string_ref.hh"
22#include "BLI_utildefines.h"
23
24#include "BKE_context.hh"
25#include "BKE_lib_query.hh"
26#include "BKE_lib_remap.hh"
27#include "BKE_modifier.hh"
28#include "BKE_screen.hh"
29#include "BKE_shader_fx.h"
30
31#include "BLT_translation.hh"
32
33#include "ED_buttons.hh"
34#include "ED_screen.hh"
35#include "ED_space_api.hh"
36#include "ED_view3d.hh" /* To draw toolbar UI. */
37
38#include "WM_api.hh"
39#include "WM_message.hh"
40#include "WM_types.hh"
41
42#include "RNA_access.hh"
43#include "RNA_prototypes.hh"
44
45#include "UI_interface.hh"
46#include "UI_interface_c.hh"
47#include "UI_view2d.hh"
48
49#include "BLO_read_write.hh"
50
51#include "buttons_intern.hh" /* own include */
52
53/* -------------------------------------------------------------------- */
56
57static SpaceLink *buttons_create(const ScrArea * /*area*/, const Scene * /*scene*/)
58{
59 ARegion *region;
60 SpaceProperties *sbuts;
61
62 sbuts = MEM_callocN<SpaceProperties>("initbuts");
64 sbuts->mainb = sbuts->mainbuser = BCONTEXT_OBJECT;
65 sbuts->visible_tabs = uint(-1); /* 0xFFFFFFFF - All tabs visible by default. */
66
67 /* header */
68 region = BKE_area_region_new();
69
70 BLI_addtail(&sbuts->regionbase, region);
73
74 /* navigation bar */
75 region = BKE_area_region_new();
76
77 BLI_addtail(&sbuts->regionbase, region);
79 region->alignment = RGN_ALIGN_LEFT;
80
81#if 0
82 /* context region */
83 region = BKE_area_region_new();
84 BLI_addtail(&sbuts->regionbase, region);
86 region->alignment = RGN_ALIGN_TOP;
87#endif
88
89 /* main region */
90 region = BKE_area_region_new();
91
92 BLI_addtail(&sbuts->regionbase, region);
94
95 return (SpaceLink *)sbuts;
96}
97
98/* Doesn't free the space-link itself. */
99static void buttons_free(SpaceLink *sl)
100{
101 SpaceProperties *sbuts = (SpaceProperties *)sl;
102
103 if (sbuts->path) {
104 MEM_delete(static_cast<ButsContextPath *>(sbuts->path));
105 }
106
107 if (sbuts->texuser) {
108 ButsContextTexture *ct = static_cast<ButsContextTexture *>(sbuts->texuser);
110 MEM_delete(user);
111 }
113 MEM_freeN(ct);
114 }
115
116 if (sbuts->runtime != nullptr) {
118 MEM_freeN(sbuts->runtime);
119 }
120}
121
122/* spacetype; init callback */
123static void buttons_init(wmWindowManager * /*wm*/, ScrArea *area)
124{
126
127 if (sbuts->runtime == nullptr) {
129 sbuts->runtime->search_string[0] = '\0';
130 sbuts->runtime->tab_search_results = BLI_BITMAP_NEW(BCONTEXT_TOT * 2, __func__);
131 }
132}
133
135{
136 SpaceProperties *sfile_old = (SpaceProperties *)sl;
137 SpaceProperties *sbutsn = static_cast<SpaceProperties *>(MEM_dupallocN(sl));
138
139 /* clear or remove stuff from old */
140 sbutsn->path = nullptr;
141 sbutsn->texuser = nullptr;
142 if (sfile_old->runtime != nullptr) {
143 sbutsn->runtime = static_cast<SpaceProperties_Runtime *>(MEM_dupallocN(sfile_old->runtime));
144 sbutsn->runtime->search_string[0] = '\0';
146 }
147
148 return (SpaceLink *)sbutsn;
149}
150
151/* add handlers, stuff you only do once or on area/region changes */
153{
154 wmKeyMap *keymap;
155
156 ED_region_panels_init(wm, region);
157
158 keymap = WM_keymap_ensure(wm->defaultconf, "Property Editor", SPACE_PROPERTIES, RGN_TYPE_WINDOW);
159 WM_event_add_keymap_handler(&region->runtime->handlers, keymap);
160}
161
163
164/* -------------------------------------------------------------------- */
167
168void ED_buttons_visible_tabs_menu(bContext *C, uiLayout *layout, void * /*arg*/)
169{
171 reinterpret_cast<ID *>(CTX_wm_screen(C)), &RNA_SpaceProperties, CTX_wm_space_properties(C));
172
173 /* These can be reordered freely. */
174 constexpr std::array<blender::StringRefNull, BCONTEXT_TOT> filter_items = {
175 "show_properties_tool",
176 "show_properties_render",
177 "show_properties_output",
178 "show_properties_view_layer",
179 "show_properties_scene",
180 "show_properties_world",
181 "show_properties_collection",
182 "show_properties_object",
183 "show_properties_modifiers",
184 "show_properties_effects",
185 "show_properties_particles",
186 "show_properties_physics",
187 "show_properties_constraints",
188 "show_properties_data",
189 "show_properties_bone",
190 "show_properties_bone_constraints",
191 "show_properties_material",
192 "show_properties_texture",
193 };
194
195 for (blender::StringRefNull item : filter_items) {
196 layout->prop(&ptr, item, UI_ITEM_R_TOGGLE, std::nullopt, ICON_NONE);
197 }
198}
199
200void ED_buttons_navbar_menu(bContext *C, uiLayout *layout, void * /*arg*/)
201{
202 ED_screens_region_flip_menu_create(C, layout, nullptr);
204 layout->op("SCREEN_OT_region_toggle", IFACE_("Hide"), ICON_NONE);
205}
206
208 bool apply_filter)
209{
211 const int filter = sbuts->visible_tabs;
212
213 auto add_spacer = [&]() {
214 if (!tabs.is_empty() && tabs.last() != BCONTEXT_SEPARATOR) {
216 }
217 };
218
219 auto add_tab = [&](eSpaceButtons_Context tab) {
220 if (sbuts->pathflag & (1 << tab) && (!apply_filter || filter & (1 << tab))) {
221 tabs.append(tab);
222 }
223 };
224
225 add_tab(BCONTEXT_TOOL);
226
227 add_spacer();
228
229 add_tab(BCONTEXT_RENDER);
230 add_tab(BCONTEXT_OUTPUT);
231 add_tab(BCONTEXT_VIEW_LAYER);
232 add_tab(BCONTEXT_SCENE);
233 add_tab(BCONTEXT_WORLD);
234
235 add_spacer();
236
237 add_tab(BCONTEXT_COLLECTION);
238
239 add_spacer();
240
241 add_tab(BCONTEXT_OBJECT);
242 add_tab(BCONTEXT_MODIFIER);
243 add_tab(BCONTEXT_SHADERFX);
244 add_tab(BCONTEXT_PARTICLE);
245 add_tab(BCONTEXT_PHYSICS);
246 add_tab(BCONTEXT_CONSTRAINT);
247 add_tab(BCONTEXT_DATA);
248 add_tab(BCONTEXT_BONE);
250 add_tab(BCONTEXT_MATERIAL);
251
252 add_spacer();
253
254 add_tab(BCONTEXT_TEXTURE);
255
256 return tabs;
257}
258
259static const char *buttons_main_region_context_string(const short mainb)
260{
261 switch (mainb) {
262 case BCONTEXT_SCENE:
263 return "scene";
264 case BCONTEXT_RENDER:
265 return "render";
266 case BCONTEXT_OUTPUT:
267 return "output";
269 return "view_layer";
270 case BCONTEXT_WORLD:
271 return "world";
273 return "collection";
274 case BCONTEXT_OBJECT:
275 return "object";
276 case BCONTEXT_DATA:
277 return "data";
279 return "material";
280 case BCONTEXT_TEXTURE:
281 return "texture";
283 return "particle";
284 case BCONTEXT_PHYSICS:
285 return "physics";
286 case BCONTEXT_BONE:
287 return "bone";
289 return "modifier";
291 return "shaderfx";
293 return "constraint";
295 return "bone_constraint";
296 case BCONTEXT_TOOL:
297 return "tool";
298 }
299
300 /* All the cases should be handled. */
301 BLI_assert(false);
302 return "";
303}
304
306 SpaceProperties *sbuts,
307 ARegion *region)
308{
310
311 const char *contexts[2] = {buttons_main_region_context_string(sbuts->mainb), nullptr};
312
314 C, region, &region->runtime->type->paneltypes, WM_OP_INVOKE_REGION_WIN, contexts, nullptr);
315}
316
318
319/* -------------------------------------------------------------------- */
322
324{
325 return (sbuts->runtime) ? sbuts->runtime->search_string : "";
326}
327
329{
330 return (sbuts->runtime) ? STRNLEN(sbuts->runtime->search_string) : 0;
331}
332
333void ED_buttons_search_string_set(SpaceProperties *sbuts, const char *value)
334{
335 if (sbuts->runtime) {
336 STRNCPY(sbuts->runtime->search_string, value);
337 }
338}
339
341{
342 if (!sbuts->runtime) {
343 return false;
344 }
345 return BLI_BITMAP_TEST(sbuts->runtime->tab_search_results, index);
346}
347
349
350/* -------------------------------------------------------------------- */
353
355{
356 const char *contexts[2] = {buttons_main_region_context_string(sbuts->mainb), nullptr};
357
358 if (sbuts->mainb == BCONTEXT_TOOL) {
359 return false;
360 }
361
364 C, region, &region->runtime->type->paneltypes, contexts, nullptr);
365}
366
368 SpaceProperties *sbuts, blender::Span<eSpaceButtons_Context> context_tabs_array)
369{
370 /* As long as all-tab search in the tool is disabled in the tool context, don't move from it. */
371 if (sbuts->mainb == BCONTEXT_TOOL) {
372 return;
373 }
374
375 int current_tab_index = 0;
376 for (int i = 0; i < context_tabs_array.size(); i++) {
377 if (sbuts->mainb == context_tabs_array[i]) {
378 current_tab_index = i;
379 break;
380 }
381 }
382
383 /* Try the tabs after the current tab. */
384 for (int i = current_tab_index; i < context_tabs_array.size(); i++) {
386 sbuts->mainbuser = context_tabs_array[i];
387 return;
388 }
389 }
390
391 /* Try the tabs before the current tab. */
392 for (int i = 0; i < current_tab_index; i++) {
394 sbuts->mainbuser = context_tabs_array[i];
395 return;
396 }
397 }
398}
399
401 SpaceProperties *sbuts,
402 ARegion *region_original,
403 blender::Span<eSpaceButtons_Context> context_tabs_array)
404{
405 /* Use local copies of the area and duplicate the region as a mainly-paranoid protection
406 * against changing any of the space / region data while running the search. */
407 ScrArea *area_original = CTX_wm_area(C);
408 ScrArea area_copy = blender::dna::shallow_copy(*area_original);
409 ARegion *region_copy = BKE_area_region_copy(area_copy.type, region_original);
410 /* Set the region visible field. Otherwise some layout code thinks we're drawing in a popup.
411 * This likely isn't necessary, but it's nice to emulate a "real" region where possible. */
412 region_copy->runtime->visible = true;
413 CTX_wm_area_set((bContext *)C, &area_copy);
414 CTX_wm_region_set((bContext *)C, region_copy);
415
416 SpaceProperties sbuts_copy = blender::dna::shallow_copy(*sbuts);
417 sbuts_copy.path = nullptr;
418 sbuts_copy.texuser = nullptr;
419 sbuts_copy.runtime = static_cast<SpaceProperties_Runtime *>(MEM_dupallocN(sbuts->runtime));
420 sbuts_copy.runtime->tab_search_results = nullptr;
421 BLI_listbase_clear(&area_copy.spacedata);
422 BLI_addtail(&area_copy.spacedata, &sbuts_copy);
423
424 /* Loop through the tabs added to the properties editor. */
425 for (int i = 0; i < context_tabs_array.size(); i++) {
426 /* -1 corresponds to a spacer. */
427 if (context_tabs_array[i] == -1) {
428 continue;
429 }
430
431 /* Handle search for the current tab in the normal layout pass. */
432 if (context_tabs_array[i] == sbuts->mainb) {
433 continue;
434 }
435
436 sbuts_copy.mainb = sbuts_copy.mainbo = sbuts_copy.mainbuser = context_tabs_array[i];
437
438 /* Actually do the search and store the result in the bitmap. */
440 i,
441 property_search_for_context(C, region_copy, &sbuts_copy));
442
443 UI_blocklist_free(C, region_copy);
444 }
445
446 BKE_area_region_free(area_copy.type, region_copy);
447 MEM_freeN(region_copy);
448 buttons_free((SpaceLink *)&sbuts_copy);
449
450 CTX_wm_area_set((bContext *)C, area_original);
451 CTX_wm_region_set((bContext *)C, region_original);
452}
453
459 SpaceProperties *sbuts,
460 ARegion *region)
461{
462 /* Theoretical maximum of every context shown with a spacer between every tab. */
463 const blender::Vector<eSpaceButtons_Context> context_tabs_array = ED_buttons_tabs_list(sbuts);
464
465 property_search_all_tabs(C, sbuts, region, context_tabs_array);
466
467 /* Check whether the current tab has a search match. */
468 bool current_tab_has_search_match = false;
469 LISTBASE_FOREACH (Panel *, panel, &region->panels) {
471 current_tab_has_search_match = true;
472 }
473 }
474
475 /* Find which index in the list the current tab corresponds to. */
476 int current_tab_index = -1;
477 for (const int i : context_tabs_array.index_range()) {
478 if (context_tabs_array[i] == sbuts->mainb) {
479 current_tab_index = i;
480 }
481 }
482 BLI_assert(current_tab_index != -1);
483
484 /* Update the tab search match flag for the current tab. */
486 sbuts->runtime->tab_search_results, current_tab_index, current_tab_has_search_match);
487
488 /* Move to the next tab with a result */
489 if (!current_tab_has_search_match) {
490 if (region->flag & RGN_FLAG_SEARCH_FILTER_UPDATE) {
491 property_search_move_to_next_tab_with_results(sbuts, context_tabs_array);
492 }
493 }
494}
495
497
498/* -------------------------------------------------------------------- */
501
503{
504 using namespace blender;
505 const Vector<eSpaceButtons_Context> tabs_array_no_filter = ED_buttons_tabs_list(sbuts, false);
506 const Vector<eSpaceButtons_Context> tabs_array = ED_buttons_tabs_list(sbuts);
507
508 const int old_index = tabs_array_no_filter.first_index_of(eSpaceButtons_Context(sbuts->mainb));
509
510 /* Try to find next tab to switch to. */
512 for (int i = old_index; i < tabs_array_no_filter.size(); i += iter_step) {
513 const eSpaceButtons_Context candidate_tab = tabs_array_no_filter[i];
514
515 if (candidate_tab == BCONTEXT_SEPARATOR) {
516 continue;
517 }
518
519 const int found_tab_index = tabs_array.first_index_of_try(candidate_tab);
520
521 if (found_tab_index != -1) {
522 new_tab = tabs_array[found_tab_index];
523 break;
524 }
525 }
526
527 return new_tab;
528}
529
530/* Change active tab, if it was hidden. */
532{
533 const bool tab_was_hidden = ((1 << sbuts->mainb) & sbuts->visible_tabs) == 0;
534 if (!tab_was_hidden) {
535 return;
536 }
537
539
540 /* Try to find previous tab to switch to. */
541 if (int(new_tab) == -1) {
542 new_tab = find_new_properties_tab(sbuts, -1);
543 }
544
545 if (int(new_tab) == -1) {
546 new_tab = eSpaceButtons_Context(1 << BCONTEXT_TOOL);
548 }
549
550 sbuts->mainb = new_tab;
551 sbuts->mainbuser = new_tab;
552}
553
554static void buttons_main_region_layout(const bContext *C, ARegion *region)
555{
556 /* draw entirely, view changes should be handled here */
558
559 /* Needed for RNA to get the good values! */
561
562 if (ED_buttons_tabs_list(sbuts).is_empty()) {
565 return;
566 }
567
569
570 if (sbuts->mainb == BCONTEXT_TOOL) {
571 ED_view3d_buttons_region_layout_ex(C, region, "Tool");
572 }
573 else {
575 }
576
577 if (region->flag & RGN_FLAG_SEARCH_FILTER_ACTIVE) {
579 }
580
581 sbuts->mainbo = sbuts->mainb;
582}
583
585{
586 ARegion *region = params->region;
587 const wmNotifier *wmn = params->notifier;
588
589 /* context changes */
590 switch (wmn->category) {
591 case NC_SCREEN:
592 if (ELEM(wmn->data, ND_LAYER)) {
593 ED_region_tag_redraw(region);
594 }
595 break;
596 }
597}
598
608
609static void buttons_keymap(wmKeyConfig *keyconf)
610{
611 WM_keymap_ensure(keyconf, "Property Editor", SPACE_PROPERTIES, RGN_TYPE_WINDOW);
612}
613
615
616/* -------------------------------------------------------------------- */
619
620/* add handlers, stuff you only do once or on area/region changes */
622{
623 ED_region_header_init(region);
624}
625
626static void buttons_header_region_draw(const bContext *C, ARegion *region)
627{
629
630 /* Needed for RNA to get the good values! */
632
633 ED_region_header(C, region);
634}
635
637{
638 wmMsgBus *mbus = params->message_bus;
639 ScrArea *area = params->area;
640 ARegion *region = params->region;
641 SpaceProperties *sbuts = static_cast<SpaceProperties *>(area->spacedata.first);
642
643 wmMsgSubscribeValue msg_sub_value_region_tag_redraw{};
644 msg_sub_value_region_tag_redraw.owner = region;
645 msg_sub_value_region_tag_redraw.user_data = region;
646 msg_sub_value_region_tag_redraw.notify = ED_region_do_msg_notify_tag_redraw;
647
648 /* Don't check for SpaceProperties.mainb here, we may toggle between view-layers
649 * where one has no active object, so that available contexts changes. */
650 WM_msg_subscribe_rna_anon_prop(mbus, Window, view_layer, &msg_sub_value_region_tag_redraw);
651
653 WM_msg_subscribe_rna_anon_prop(mbus, ViewLayer, name, &msg_sub_value_region_tag_redraw);
654 }
655
656 if (sbuts->mainb == BCONTEXT_TOOL) {
657 WM_msg_subscribe_rna_anon_prop(mbus, WorkSpace, tools, &msg_sub_value_region_tag_redraw);
658 }
659}
660
662
663/* -------------------------------------------------------------------- */
666
674
676{
679
680 LISTBASE_FOREACH (PanelType *, pt, &region->runtime->type->paneltypes) {
681 pt->flag |= PANEL_TYPE_LAYOUT_VERT_BAR;
682 }
683
684 ED_region_panels_layout(C, region);
685 /* #ED_region_panels_layout adds vertical scroll-bars, we don't want them. */
687 ED_region_panels_draw(C, region);
688}
689
692{
693 wmMsgBus *mbus = params->message_bus;
694 ARegion *region = params->region;
695
696 wmMsgSubscribeValue msg_sub_value_region_tag_redraw{};
697 msg_sub_value_region_tag_redraw.owner = region;
698 msg_sub_value_region_tag_redraw.user_data = region;
699 msg_sub_value_region_tag_redraw.notify = ED_region_do_msg_notify_tag_redraw;
700
701 WM_msg_subscribe_rna_anon_prop(mbus, Window, view_layer, &msg_sub_value_region_tag_redraw);
702 /* Redraw when image editor mode changes, texture tab needs to be added when switching to "Paint"
703 * mode. */
705 mbus, SpaceImageEditor, ui_mode, &msg_sub_value_region_tag_redraw);
706}
707
708/* draw a certain button set only if properties area is currently
709 * showing that button set, to reduce unnecessary drawing. */
710static void buttons_area_redraw(ScrArea *area, short buttons)
711{
712 SpaceProperties *sbuts = static_cast<SpaceProperties *>(area->spacedata.first);
713
714 /* if the area's current button set is equal to the one to redraw */
715 if (sbuts->mainb == buttons) {
716 ED_area_tag_redraw(area);
717 }
718}
719
721
722/* -------------------------------------------------------------------- */
725
726/* reused! */
728{
729 ScrArea *area = params->area;
730 const wmNotifier *wmn = params->notifier;
731 SpaceProperties *sbuts = static_cast<SpaceProperties *>(area->spacedata.first);
732
733 /* context changes */
734 switch (wmn->category) {
735 case NC_SCENE:
736 switch (wmn->data) {
741 break;
742 case ND_WORLD:
744 sbuts->preview = 1;
745 break;
746 case ND_FRAME:
747 /* any buttons area can have animated properties so redraw all */
748 ED_area_tag_redraw(area);
749 sbuts->preview = 1;
750 break;
751 case ND_OB_ACTIVE:
752 ED_area_tag_redraw(area);
753 sbuts->preview = 1;
754 break;
755 case ND_KEYINGSET:
757 break;
758 case ND_RENDER_RESULT:
759 break;
760 case ND_MODE:
761 case ND_LAYER:
762 default:
763 ED_area_tag_redraw(area);
764 break;
765 }
766 break;
767 case NC_OBJECT:
768 switch (wmn->data) {
769 case ND_TRANSFORM:
771 buttons_area_redraw(area, BCONTEXT_DATA); /* Auto-texture-space flag. */
772 break;
773 case ND_POSE:
774 case ND_BONE_ACTIVE:
775 case ND_BONE_SELECT:
780 break;
781 case ND_MODIFIER:
782 if (wmn->action == NA_RENAME) {
783 ED_area_tag_redraw(area);
784 }
785 else {
787 }
789 break;
790 case ND_CONSTRAINT:
793 break;
794 case ND_SHADERFX:
796 break;
797 case ND_PARTICLE:
798 if (wmn->action == NA_EDITED) {
800 }
801 sbuts->preview = 1;
802 break;
803 case ND_DRAW:
807 /* Needed to refresh context path when changing active particle system index. */
810 break;
811 case ND_DRAW_ANIMVIZ:
813 break;
814 default:
815 /* Not all object RNA props have a ND_ notifier (yet) */
816 ED_area_tag_redraw(area);
817 break;
818 }
819 break;
820 case NC_GEOM:
821 switch (wmn->data) {
822 case ND_SELECT:
823 case ND_DATA:
824 case ND_VERTEX_GROUP:
825 ED_area_tag_redraw(area);
826 break;
827 }
828 break;
829 case NC_MATERIAL:
830 ED_area_tag_redraw(area);
831 switch (wmn->data) {
832 case ND_SHADING:
833 case ND_SHADING_DRAW:
834 case ND_SHADING_LINKS:
836 case ND_NODES:
837 /* currently works by redraws... if preview is set, it (re)starts job */
838 sbuts->preview = 1;
839 break;
840 }
841 break;
842 case NC_WORLD:
844 sbuts->preview = 1;
845 break;
846 case NC_LAMP:
848 sbuts->preview = 1;
849 break;
850 case NC_GROUP:
852 break;
853 case NC_BRUSH:
856 sbuts->preview = 1;
857 break;
858 case NC_TEXTURE:
859 case NC_IMAGE:
860 if (wmn->action != NA_PAINTING) {
861 ED_area_tag_redraw(area);
862 sbuts->preview = 1;
863 }
864 break;
865 case NC_WORKSPACE:
867 break;
868 case NC_SPACE:
869 if (wmn->data == ND_SPACE_PROPERTIES) {
870 ED_area_tag_redraw(area);
871 }
872 else if (wmn->data == ND_SPACE_CHANGED) {
873 ED_area_tag_redraw(area);
874 sbuts->preview = 1;
875 }
876 break;
877 case NC_ID:
878 if (ELEM(wmn->action, NA_RENAME, NA_EDITED)) {
879 ED_area_tag_redraw(area);
880 }
881 break;
882 case NC_ANIMATION:
883 switch (wmn->data) {
884 case ND_KEYFRAME_PROP:
885 case ND_NLA_ACTCHANGE:
886 ED_area_tag_redraw(area);
887 break;
888 case ND_KEYFRAME:
889 if (ELEM(wmn->action, NA_EDITED, NA_ADDED, NA_REMOVED)) {
890 ED_area_tag_redraw(area);
891 }
892 break;
893 }
894 break;
895 case NC_GPENCIL:
896 if (wmn->data == ND_DATA) {
898 ED_area_tag_redraw(area);
899 }
900 }
901 else if (wmn->action == NA_EDITED) {
902 ED_area_tag_redraw(area);
903 }
904 break;
905 case NC_NODE:
906 if (wmn->action == NA_SELECTED) {
907 ED_area_tag_redraw(area);
908 /* new active node, update texture preview */
909 if (sbuts->mainb == BCONTEXT_TEXTURE) {
910 sbuts->preview = 1;
911 }
912 }
913 break;
914 /* Listener for preview render, when doing an global undo. */
915 case NC_WM:
916 if (wmn->data == ND_UNDO) {
917 ED_area_tag_redraw(area);
918 sbuts->preview = 1;
919 }
920 break;
921 case NC_SCREEN:
922 if (wmn->data == ND_LAYOUTSET) {
923 ED_area_tag_redraw(area);
924 sbuts->preview = 1;
925 }
926 break;
927#ifdef WITH_FREESTYLE
928 case NC_LINESTYLE:
929 ED_area_tag_redraw(area);
930 sbuts->preview = 1;
931 break;
932#endif
933 }
934
935 if (wmn->data == ND_KEYS) {
936 ED_area_tag_redraw(area);
937 }
938}
939
940static void buttons_id_remap(ScrArea * /*area*/,
941 SpaceLink *slink,
942 const blender::bke::id::IDRemapper &mappings)
943{
944 SpaceProperties *sbuts = (SpaceProperties *)slink;
945
947 sbuts->flag &= ~SB_PIN_CONTEXT;
948 }
949
950 if (sbuts->path) {
951 ButsContextPath *path = static_cast<ButsContextPath *>(sbuts->path);
952 for (int i = 0; i < path->len; i++) {
953 switch (mappings.apply(&path->ptr[i].owner_id, ID_REMAP_APPLY_DEFAULT)) {
955 path->len = i;
956 if (i != 0) {
957 /* If the first item in the path is cleared, the whole path is cleared, so no need to
958 * clear further items here, see also at the end of this block. */
959 for (int j = i; j < path->len; j++) {
960 path->ptr[j] = {};
961 }
962 }
963 break;
964 }
966 path->ptr[i] = RNA_id_pointer_create(path->ptr[i].owner_id);
967 /* There is no easy way to check/make path downwards valid, just nullify it.
968 * Next redraw will rebuild this anyway. */
969 i++;
970 for (int j = i; j < path->len; j++) {
971 path->ptr[j] = {};
972 }
973 path->len = i;
974 break;
975 }
976
979 /* Nothing to do. */
980 break;
981 }
982 }
983 }
984 if (path->len == 0 && sbuts->path) {
985 MEM_delete(static_cast<ButsContextPath *>(sbuts->path));
986 sbuts->path = nullptr;
987 }
988 }
989
990 if (sbuts->texuser) {
991 ButsContextTexture *ct = static_cast<ButsContextTexture *>(sbuts->texuser);
992 mappings.apply(reinterpret_cast<ID **>(&ct->texture), ID_REMAP_APPLY_DEFAULT);
994 MEM_delete(user);
995 }
997 ct->user = nullptr;
998 }
999}
1000
1002{
1003 SpaceProperties *sbuts = reinterpret_cast<SpaceProperties *>(space_link);
1004 const int data_flags = BKE_lib_query_foreachid_process_flags_get(data);
1005 const bool is_readonly = (data_flags & IDWALK_READONLY) != 0;
1006
1008 if (!is_readonly) {
1009 if (sbuts->pinid == nullptr) {
1010 sbuts->flag &= ~SB_PIN_CONTEXT;
1011 }
1012 /* NOTE: Restoring path pointers is complicated, if not impossible, because this contains
1013 * data pointers too, not just ID ones. See #40046. */
1014 if (sbuts->path) {
1015 MEM_delete(static_cast<ButsContextPath *>(sbuts->path));
1016 sbuts->path = nullptr;
1017 }
1018 }
1019
1020 if (sbuts->texuser) {
1021 ButsContextTexture *ct = static_cast<ButsContextTexture *>(sbuts->texuser);
1023
1024 if (!is_readonly) {
1026 MEM_delete(user);
1027 }
1029 ct->user = nullptr;
1030 }
1031 }
1032}
1033
1035{
1036 SpaceProperties *sbuts = (SpaceProperties *)sl;
1037
1038 sbuts->path = nullptr;
1039 sbuts->texuser = nullptr;
1040 sbuts->mainbo = sbuts->mainb;
1041 sbuts->mainbuser = sbuts->mainb;
1042 sbuts->runtime = nullptr;
1043}
1044
1046 ID * /*parent_id*/,
1047 SpaceLink *sl)
1048{
1049 SpaceProperties *sbuts = reinterpret_cast<SpaceProperties *>(sl);
1050
1051 if (sbuts->pinid == nullptr) {
1052 sbuts->flag &= ~SB_PIN_CONTEXT;
1053 }
1054}
1055
1057{
1058 BLO_write_struct(writer, SpaceProperties, sl);
1059}
1060
1062
1063/* -------------------------------------------------------------------- */
1066
1068{
1069 std::unique_ptr<SpaceType> st = std::make_unique<SpaceType>();
1070 ARegionType *art;
1071
1072 st->spaceid = SPACE_PROPERTIES;
1073 STRNCPY(st->name, "Buttons");
1074
1075 st->create = buttons_create;
1076 st->free = buttons_free;
1077 st->init = buttons_init;
1078 st->duplicate = buttons_duplicate;
1079 st->operatortypes = buttons_operatortypes;
1080 st->keymap = buttons_keymap;
1081 st->listener = buttons_area_listener;
1082 st->context = buttons_context;
1083 st->id_remap = buttons_id_remap;
1084 st->foreach_id = buttons_foreach_id;
1085 st->blend_read_data = buttons_space_blend_read_data;
1086 st->blend_read_after_liblink = buttons_space_blend_read_after_liblink;
1087 st->blend_write = buttons_space_blend_write;
1088
1089 /* regions: main window */
1090 art = MEM_callocN<ARegionType>("spacetype buttons region");
1099 BLI_addhead(&st->regiontypes, art);
1100
1101 /* Register the panel types from modifiers. The actual panels are built per modifier rather
1102 * than per modifier type. */
1103 for (int i = 0; i < NUM_MODIFIER_TYPES; i++) {
1105 if (mti != nullptr && mti->panel_register != nullptr) {
1106 mti->panel_register(art);
1107 }
1108 }
1109 for (int i = 0; i < NUM_SHADER_FX_TYPES; i++) {
1111 continue;
1112 }
1114 if (fxti != nullptr && fxti->panel_register != nullptr) {
1115 fxti->panel_register(art);
1116 }
1117 }
1118
1119 /* regions: header */
1120 art = MEM_callocN<ARegionType>("spacetype buttons region");
1122 art->prefsizey = HEADERY;
1124
1128 BLI_addhead(&st->regiontypes, art);
1129
1130 /* regions: navigation bar */
1131 art = MEM_callocN<ARegionType>("spacetype nav buttons region");
1133 art->prefsizex = AREAMINX;
1138 BLI_addhead(&st->regiontypes, art);
1139
1140 BKE_spacetype_register(std::move(st));
1141}
1142
bScreen * CTX_wm_screen(const bContext *C)
SpaceProperties * CTX_wm_space_properties(const bContext *C)
ScrArea * CTX_wm_area(const bContext *C)
void CTX_wm_area_set(bContext *C, ScrArea *area)
void CTX_wm_region_set(bContext *C, ARegion *region)
#define BKE_LIB_FOREACHID_PROCESS_IDSUPER(data_, id_super_, cb_flag_)
@ IDWALK_CB_DIRECT_WEAK_LINK
#define BKE_LIB_FOREACHID_PROCESS_ID(data_, id_, cb_flag_)
LibraryForeachIDFlag BKE_lib_query_foreachid_process_flags_get(const LibraryForeachIDData *data)
Definition lib_query.cc:129
@ IDWALK_READONLY
@ ID_REMAP_RESULT_SOURCE_REMAPPED
@ ID_REMAP_RESULT_SOURCE_UNASSIGNED
@ ID_REMAP_RESULT_SOURCE_NOT_MAPPABLE
@ ID_REMAP_RESULT_SOURCE_UNAVAILABLE
@ ID_REMAP_APPLY_DEFAULT
const ModifierTypeInfo * BKE_modifier_get_info(ModifierType type)
void BKE_spacetype_register(std::unique_ptr< SpaceType > st)
Definition screen.cc:276
ARegion * BKE_area_region_new()
Definition screen.cc:381
void BKE_area_region_free(SpaceType *st, ARegion *region)
Definition screen.cc:591
@ PANEL_TYPE_LAYOUT_VERT_BAR
ARegion * BKE_area_region_copy(const SpaceType *st, const ARegion *region)
Definition screen.cc:344
@ REGION_DRAW_LOCK_ALL
const ShaderFxTypeInfo * BKE_shaderfx_get_info(ShaderFxType type)
Definition shader_fx.cc:131
#define BLI_assert_unreachable()
Definition BLI_assert.h:93
#define BLI_assert(a)
Definition BLI_assert.h:46
#define BLI_BITMAP_NEW(_num, _alloc_string)
Definition BLI_bitmap.h:37
#define BLI_BITMAP_TEST(_bitmap, _index)
Definition BLI_bitmap.h:61
#define BLI_BITMAP_SET(_bitmap, _index, _set)
Definition BLI_bitmap.h:99
#define LISTBASE_FOREACH(type, var, list)
BLI_INLINE void BLI_listbase_clear(ListBase *lb)
#define LISTBASE_FOREACH_MUTABLE(type, var, list)
void BLI_addtail(ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition listbase.cc:111
void BLI_addhead(ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition listbase.cc:91
#define STRNLEN(str)
Definition BLI_string.h:608
char * STRNCPY(char(&dst)[N], const char *src)
Definition BLI_string.h:688
unsigned int uint
#define ELEM(...)
#define BLO_write_struct(writer, struct_name, data_ptr)
#define IFACE_(msgid)
float[3] Vector
@ NUM_MODIFIER_TYPES
#define HEADERY
#define AREAMINX
@ RGN_TYPE_CHANNELS
@ RGN_TYPE_WINDOW
@ RGN_TYPE_NAV_BAR
@ RGN_TYPE_HEADER
@ RGN_FLAG_SEARCH_FILTER_UPDATE
@ RGN_FLAG_NO_USER_RESIZE
@ RGN_FLAG_SEARCH_FILTER_ACTIVE
@ RGN_ALIGN_BOTTOM
@ RGN_ALIGN_LEFT
@ RGN_ALIGN_TOP
@ eShaderFxType_Light_deprecated
@ NUM_SHADER_FX_TYPES
@ SPACE_PROPERTIES
@ SB_PIN_CONTEXT
eSpaceButtons_Context
@ BCONTEXT_CONSTRAINT
@ BCONTEXT_COLLECTION
@ BCONTEXT_OUTPUT
@ BCONTEXT_VIEW_LAYER
@ BCONTEXT_MATERIAL
@ BCONTEXT_TOT
@ BCONTEXT_SHADERFX
@ BCONTEXT_MODIFIER
@ BCONTEXT_BONE
@ BCONTEXT_DATA
@ BCONTEXT_OBJECT
@ BCONTEXT_BONE_CONSTRAINT
@ BCONTEXT_PHYSICS
@ BCONTEXT_SCENE
@ BCONTEXT_WORLD
@ BCONTEXT_RENDER
@ BCONTEXT_TEXTURE
@ BCONTEXT_TOOL
@ BCONTEXT_PARTICLE
@ BCONTEXT_SEPARATOR
@ USER_HEADER_BOTTOM
@ V2D_SCROLL_VERTICAL
@ V2D_LOCKZOOM_X
@ V2D_LOCKZOOM_Y
void ED_area_tag_redraw(ScrArea *area)
Definition area.cc:714
bool ED_region_property_search(const bContext *C, ARegion *region, ListBase *paneltypes, const char *contexts[], const char *category_override)
Definition area.cc:3559
@ ED_KEYMAP_NAVBAR
Definition ED_screen.hh:749
@ ED_KEYMAP_UI
Definition ED_screen.hh:740
@ ED_KEYMAP_HEADER
Definition ED_screen.hh:746
@ ED_KEYMAP_VIEW2D
Definition ED_screen.hh:743
@ ED_KEYMAP_FRAMES
Definition ED_screen.hh:745
void ED_region_header(const bContext *C, ARegion *region)
Definition area.cc:3754
void ED_region_header_init(ARegion *region)
Definition area.cc:3769
void ED_region_panels_layout_ex(const bContext *C, ARegion *region, ListBase *paneltypes, wmOperatorCallContext op_context, const char *contexts[], const char *category_override)
Definition area.cc:3219
void ED_region_panels_layout(const bContext *C, ARegion *region)
Definition area.cc:3403
void ED_region_panels_init(wmWindowManager *wm, ARegion *region)
Definition area.cc:3473
void ED_region_tag_redraw(ARegion *region)
Definition area.cc:639
void ED_screens_region_flip_menu_create(bContext *C, uiLayout *layout, void *arg)
void ED_region_do_msg_notify_tag_redraw(bContext *C, wmMsgSubscribeKey *msg_key, wmMsgSubscribeValue *msg_val)
Definition area.cc:384
void ED_region_panels_draw(const bContext *C, ARegion *region)
Definition area.cc:3409
void ED_view3d_buttons_region_layout_ex(const bContext *C, ARegion *region, const char *category_override)
#define Window
Read Guarded memory(de)allocation.
#define C
Definition RandGen.cpp:29
void UI_blocklist_free(const bContext *C, ARegion *region)
bool UI_panel_matches_search_filter(const Panel *panel)
bool UI_panel_is_active(const Panel *panel)
@ UI_ITEM_R_TOGGLE
void uiLayoutSetOperatorContext(uiLayout *layout, wmOperatorCallContext opcontext)
View2D * UI_view2d_fromcontext(const bContext *C)
Definition view2d.cc:1854
#define NC_WORLD
Definition WM_types.hh:384
#define ND_SHADING
Definition WM_types.hh:474
#define ND_WORLD
Definition WM_types.hh:449
#define NC_ID
Definition WM_types.hh:392
#define NC_NODE
Definition WM_types.hh:391
#define NC_GEOM
Definition WM_types.hh:390
#define ND_NLA_ACTCHANGE
Definition WM_types.hh:495
#define ND_SPACE_CHANGED
Definition WM_types.hh:535
#define ND_DRAW
Definition WM_types.hh:458
#define NC_BRUSH
Definition WM_types.hh:382
#define ND_OB_ACTIVE
Definition WM_types.hh:437
#define ND_RENDER_RESULT
Definition WM_types.hh:443
#define NC_WM
Definition WM_types.hh:371
#define ND_DATA
Definition WM_types.hh:506
#define NC_LINESTYLE
Definition WM_types.hh:397
#define ND_RENDER_OPTIONS
Definition WM_types.hh:432
#define NC_ANIMATION
Definition WM_types.hh:385
#define ND_SHADING_PREVIEW
Definition WM_types.hh:477
#define ND_VERTEX_GROUP
Definition WM_types.hh:507
#define NC_SCREEN
Definition WM_types.hh:374
#define ND_MODE
Definition WM_types.hh:442
#define ND_SPACE_PROPERTIES
Definition WM_types.hh:526
#define ND_KEYINGSET
Definition WM_types.hh:445
#define NC_SCENE
Definition WM_types.hh:375
#define NA_ADDED
Definition WM_types.hh:583
#define NC_GROUP
Definition WM_types.hh:380
#define ND_NODES
Definition WM_types.hh:433
#define ND_MODIFIER
Definition WM_types.hh:459
#define ND_POSE
Definition WM_types.hh:455
#define NA_EDITED
Definition WM_types.hh:581
#define ND_PARTICLE
Definition WM_types.hh:462
#define ND_KEYFRAME_PROP
Definition WM_types.hh:492
#define NC_MATERIAL
Definition WM_types.hh:377
#define NC_LAMP
Definition WM_types.hh:379
#define NC_IMAGE
Definition WM_types.hh:381
#define ND_CONSTRAINT
Definition WM_types.hh:461
#define NC_WORKSPACE
Definition WM_types.hh:373
#define ND_UNDO
Definition WM_types.hh:414
#define ND_FRAME
Definition WM_types.hh:431
#define NA_REMOVED
Definition WM_types.hh:584
#define ND_SELECT
Definition WM_types.hh:505
#define NC_GPENCIL
Definition WM_types.hh:396
#define NC_TEXTURE
Definition WM_types.hh:378
#define ND_BONE_ACTIVE
Definition WM_types.hh:456
#define ND_TRANSFORM
Definition WM_types.hh:453
#define ND_LAYER
Definition WM_types.hh:447
@ WM_OP_INVOKE_REGION_WIN
Definition WM_types.hh:239
@ WM_OP_INVOKE_DEFAULT
Definition WM_types.hh:238
#define ND_BONE_COLLECTION
Definition WM_types.hh:471
#define ND_KEYS
Definition WM_types.hh:460
#define NA_RENAME
Definition WM_types.hh:585
#define ND_SHADERFX
Definition WM_types.hh:468
#define NA_PAINTING
Definition WM_types.hh:588
#define ND_DRAW_ANIMVIZ
Definition WM_types.hh:470
#define ND_BONE_SELECT
Definition WM_types.hh:457
#define ND_KEYFRAME
Definition WM_types.hh:491
#define ND_LAYOUTSET
Definition WM_types.hh:423
#define NC_OBJECT
Definition WM_types.hh:376
#define ND_SHADING_LINKS
Definition WM_types.hh:476
#define ND_SHADING_DRAW
Definition WM_types.hh:475
#define NC_SPACE
Definition WM_types.hh:389
#define NA_SELECTED
Definition WM_types.hh:586
#define U
BMesh const char void * data
int buttons_context(const bContext *C, const char *member, bContextDataResult *result)
void buttons_context_compute(const bContext *C, SpaceProperties *sbuts)
void buttons_context_register(ARegionType *art)
void BUTTONS_OT_toggle_pin(wmOperatorType *ot)
void BUTTONS_OT_context_menu(wmOperatorType *ot)
void BUTTONS_OT_directory_browse(wmOperatorType *ot)
void BUTTONS_OT_clear_filter(wmOperatorType *ot)
void BUTTONS_OT_file_browse(wmOperatorType *ot)
void BUTTONS_OT_start_filter(wmOperatorType *ot)
int64_t size() const
int64_t first_index_of(const T &value) const
int64_t first_index_of_try(const T &value) const
constexpr int64_t size() const
Definition BLI_span.hh:252
void append(const T &value)
const T & last(const int64_t n=0) const
bool is_empty() const
IndexRange index_range() const
IDRemapperApplyResult apply(ID **r_id_ptr, IDRemapperApplyOptions options, ID *id_self=nullptr) const
#define filter
#define MEM_SAFE_FREE(v)
uiWidgetBaseParameters params[MAX_WIDGET_BASE_BATCH]
void * MEM_mallocN(size_t len, const char *str)
Definition mallocn.cc:128
void * MEM_callocN(size_t len, const char *str)
Definition mallocn.cc:118
void * MEM_dupallocN(const void *vmemh)
Definition mallocn.cc:143
void MEM_freeN(void *vmemh)
Definition mallocn.cc:113
PointerRNA RNA_pointer_create_discrete(ID *id, StructRNA *type, void *data)
PointerRNA RNA_id_pointer_create(ID *id)
static void buttons_main_region_layout(const bContext *C, ARegion *region)
int ED_buttons_search_string_length(SpaceProperties *sbuts)
void ED_buttons_navbar_menu(bContext *C, uiLayout *layout, void *)
void ED_buttons_search_string_set(SpaceProperties *sbuts, const char *value)
static void buttons_space_blend_write(BlendWriter *writer, SpaceLink *sl)
static bool property_search_for_context(const bContext *C, ARegion *region, SpaceProperties *sbuts)
static void buttons_header_region_draw(const bContext *C, ARegion *region)
void ED_buttons_visible_tabs_menu(bContext *C, uiLayout *layout, void *)
static void buttons_main_region_property_search(const bContext *C, SpaceProperties *sbuts, ARegion *region)
const char * ED_buttons_search_string_get(SpaceProperties *sbuts)
static void buttons_navigation_bar_region_message_subscribe(const wmRegionMessageSubscribeParams *params)
static const char * buttons_main_region_context_string(const short mainb)
static void buttons_foreach_id(SpaceLink *space_link, LibraryForeachIDData *data)
blender::Vector< eSpaceButtons_Context > ED_buttons_tabs_list(const SpaceProperties *sbuts, bool apply_filter)
static void buttons_navigation_bar_region_draw(const bContext *C, ARegion *region)
static void buttons_init(wmWindowManager *, ScrArea *area)
static void buttons_main_region_init(wmWindowManager *wm, ARegion *region)
static void buttons_id_remap(ScrArea *, SpaceLink *slink, const blender::bke::id::IDRemapper &mappings)
static eSpaceButtons_Context find_new_properties_tab(const SpaceProperties *sbuts, int iter_step)
void ED_spacetype_buttons()
static void property_search_move_to_next_tab_with_results(SpaceProperties *sbuts, blender::Span< eSpaceButtons_Context > context_tabs_array)
static void buttons_navigation_bar_region_init(wmWindowManager *wm, ARegion *region)
static void buttons_main_region_listener(const wmRegionListenerParams *params)
static void property_search_all_tabs(const bContext *C, SpaceProperties *sbuts, ARegion *region_original, blender::Span< eSpaceButtons_Context > context_tabs_array)
static SpaceLink * buttons_create(const ScrArea *, const Scene *)
static void buttons_header_region_message_subscribe(const wmRegionMessageSubscribeParams *params)
static void buttons_main_region_layout_properties(const bContext *C, SpaceProperties *sbuts, ARegion *region)
static void buttons_area_redraw(ScrArea *area, short buttons)
static void buttons_space_blend_read_after_liblink(BlendLibReader *, ID *, SpaceLink *sl)
static void buttons_apply_filter(SpaceProperties *sbuts)
static void buttons_operatortypes()
static void buttons_header_region_init(wmWindowManager *, ARegion *region)
static void buttons_space_blend_read_data(BlendDataReader *, SpaceLink *sl)
bool ED_buttons_tab_has_search_result(SpaceProperties *sbuts, const int index)
static void buttons_free(SpaceLink *sl)
static SpaceLink * buttons_duplicate(SpaceLink *sl)
static void buttons_keymap(wmKeyConfig *keyconf)
static void buttons_area_listener(const wmSpaceTypeListenerParams *params)
void(* message_subscribe)(const wmRegionMessageSubscribeParams *params)
void(* listener)(const wmRegionListenerParams *params)
void(* draw)(const bContext *C, ARegion *region)
void(* layout)(const bContext *C, ARegion *region)
void(* init)(wmWindowManager *wm, ARegion *region)
ARegionRuntimeHandle * runtime
ListBase panels
PointerRNA ptr[8]
struct ButsTextureUser * user
Definition DNA_ID.h:404
void * first
void(* panel_register)(ARegionType *region_type)
ID * owner_id
Definition RNA_types.hh:51
ListBase spacedata
struct SpaceType * type
void(* panel_register)(struct ARegionType *region_type)
BLI_bitmap * tab_search_results
char search_string[UI_MAX_NAME_STR]
struct SpaceProperties_Runtime * runtime
short keepzoom
PointerRNA op(wmOperatorType *ot, std::optional< blender::StringRef > name, int icon, wmOperatorCallContext context, eUI_Item_Flag flag)
void prop(PointerRNA *ptr, PropertyRNA *prop, int index, int value, eUI_Item_Flag flag, std::optional< blender::StringRef > name_opt, int icon, std::optional< blender::StringRef > placeholder=std::nullopt)
unsigned int data
Definition WM_types.hh:355
unsigned int action
Definition WM_types.hh:355
unsigned int category
Definition WM_types.hh:355
struct wmKeyConfig * defaultconf
i
Definition text_draw.cc:230
wmEventHandler_Keymap * WM_event_add_keymap_handler(ListBase *handlers, wmKeyMap *keymap)
PointerRNA * ptr
Definition wm_files.cc:4227
wmKeyMap * WM_keymap_ensure(wmKeyConfig *keyconf, const char *idname, int spaceid, int regionid)
Definition wm_keymap.cc:893
#define WM_msg_subscribe_rna_anon_prop(mbus, type_, prop_, value)
void WM_operatortype_append(void(*opfunc)(wmOperatorType *))