Blender V4.5
buttons_context.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2009 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
8
9#include <algorithm>
10#include <cstdlib>
11#include <cstring>
12
13#include "MEM_guardedalloc.h"
14
15#include "BLI_listbase.h"
16#include "BLI_string.h"
17#include "BLI_utildefines.h"
18
19#include "BLT_translation.hh"
20
21#include "DNA_armature_types.h"
23#include "DNA_linestyle_types.h"
24#include "DNA_material_types.h"
25#include "DNA_node_types.h"
26#include "DNA_scene_types.h"
28#include "DNA_world_types.h"
29
30#include "BKE_action.hh"
31#include "BKE_context.hh"
32#include "BKE_layer.hh"
33#include "BKE_linestyle.h"
34#include "BKE_material.hh"
35#include "BKE_modifier.hh"
36#include "BKE_object.hh"
37#include "BKE_paint.hh"
38#include "BKE_particle.h"
39#include "BKE_screen.hh"
40
41#include "RNA_access.hh"
42#include "RNA_prototypes.hh"
43
44#include "ED_buttons.hh"
45#include "ED_physics.hh"
46#include "ED_screen.hh"
47
48#include "UI_interface.hh"
49#include "UI_resources.hh"
50
51#include "WM_api.hh"
52
53#include "buttons_intern.hh" /* own include */
54
56{
57 for (int i = 0; i < path->len; i++) {
58 PointerRNA *ptr = &path->ptr[i];
59
60 if (RNA_struct_is_a(ptr->type, type)) {
62 return CTX_RESULT_OK;
63 }
64 }
65
67}
68
70{
71 for (int i = 0; i < path->len; i++) {
72 PointerRNA *ptr = &path->ptr[i];
73
74 if (RNA_struct_is_a(ptr->type, type)) {
75 return ptr;
76 }
77 }
78
79 return nullptr;
80}
81
82/************************* Creating the Path ************************/
83
85{
86 PointerRNA *ptr = &path->ptr[path->len - 1];
87
88 /* this one just verifies */
89 return RNA_struct_is_a(ptr->type, &RNA_Scene);
90}
91
93{
94 PointerRNA *ptr = &path->ptr[path->len - 1];
95
96 /* View Layer may have already been resolved in a previous call
97 * (e.g. in buttons_context_path_linestyle). */
98 if (RNA_struct_is_a(ptr->type, &RNA_ViewLayer)) {
99 return true;
100 }
101
102 if (buttons_context_path_scene(path)) {
103 Scene *scene = static_cast<Scene *>(path->ptr[path->len - 1].data);
104 ViewLayer *view_layer = (win->scene == scene) ? WM_window_get_active_view_layer(win) :
106
107 path->ptr[path->len] = RNA_pointer_create_discrete(&scene->id, &RNA_ViewLayer, view_layer);
108 path->len++;
109 return true;
110 }
111
112 return false;
113}
114
115/* NOTE: this function can return true without adding a world to the path
116 * so the buttons stay visible, but be sure to check the ID type if a ID_WO */
118{
119 PointerRNA *ptr = &path->ptr[path->len - 1];
120
121 /* if we already have a (pinned) world, we're done */
122 if (RNA_struct_is_a(ptr->type, &RNA_World)) {
123 return true;
124 }
125 /* if we have a scene, use the scene's world */
126 if (buttons_context_path_scene(path)) {
127 Scene *scene = static_cast<Scene *>(path->ptr[path->len - 1].data);
128 World *world = scene->world;
129
130 if (world) {
131 path->ptr[path->len] = RNA_id_pointer_create(&scene->world->id);
132 path->len++;
133 return true;
134 }
135
136 return true;
137 }
138
139 /* no path to a world possible */
140 return false;
141}
142
144 ButsContextPath *path,
145 wmWindow *window)
146{
147 PointerRNA *ptr = &path->ptr[path->len - 1];
148
149 /* if we already have a (pinned) collection, we're done */
150 if (RNA_struct_is_a(ptr->type, &RNA_Collection)) {
151 return true;
152 }
153
154 Scene *scene = CTX_data_scene(C);
155
156 /* if we have a view layer, use the view layer's active collection */
157 if (buttons_context_path_view_layer(path, window)) {
158 ViewLayer *view_layer = static_cast<ViewLayer *>(path->ptr[path->len - 1].data);
159 BKE_view_layer_synced_ensure(scene, view_layer);
161
162 /* Do not show collection tab for master collection. */
163 if (c == scene->master_collection) {
164 return false;
165 }
166
167 if (c) {
168 path->ptr[path->len] = RNA_id_pointer_create(&c->id);
169 path->len++;
170 return true;
171 }
172 }
173
174 /* no path to a collection possible */
175 return false;
176}
177
179{
180 PointerRNA *ptr = &path->ptr[path->len - 1];
181
182 /* if we already have a (pinned) linestyle, we're done */
183 if (RNA_struct_is_a(ptr->type, &RNA_FreestyleLineStyle)) {
184 return true;
185 }
186 /* if we have a view layer, use the lineset's linestyle */
187 if (buttons_context_path_view_layer(path, window)) {
188 ViewLayer *view_layer = static_cast<ViewLayer *>(path->ptr[path->len - 1].data);
190 if (linestyle) {
191 path->ptr[path->len] = RNA_id_pointer_create(&linestyle->id);
192 path->len++;
193 return true;
194 }
195 }
196
197 /* no path to a linestyle possible */
198 return false;
199}
200
202{
203 PointerRNA *ptr = &path->ptr[path->len - 1];
204
205 /* if we already have a (pinned) object, we're done */
206 if (RNA_struct_is_a(ptr->type, &RNA_Object)) {
207 return true;
208 }
209 if (!RNA_struct_is_a(ptr->type, &RNA_ViewLayer)) {
210 return false;
211 }
212
213 ViewLayer *view_layer = static_cast<ViewLayer *>(ptr->data);
215
216 if (ob) {
217 path->ptr[path->len] = RNA_id_pointer_create(&ob->id);
218 path->len++;
219
220 return true;
221 }
222
223 /* no path to a object possible */
224 return false;
225}
226
227static bool buttons_context_path_data(ButsContextPath *path, int type)
228{
229 PointerRNA *ptr = &path->ptr[path->len - 1];
230
231 /* if we already have a data, we're done */
232 if (RNA_struct_is_a(ptr->type, &RNA_Mesh) && ELEM(type, -1, OB_MESH)) {
233 return true;
234 }
235 if (RNA_struct_is_a(ptr->type, &RNA_Curve) &&
236 (type == -1 || ELEM(type, OB_CURVES_LEGACY, OB_SURF, OB_FONT)))
237 {
238 return true;
239 }
240 if (RNA_struct_is_a(ptr->type, &RNA_Armature) && ELEM(type, -1, OB_ARMATURE)) {
241 return true;
242 }
243 if (RNA_struct_is_a(ptr->type, &RNA_MetaBall) && ELEM(type, -1, OB_MBALL)) {
244 return true;
245 }
246 if (RNA_struct_is_a(ptr->type, &RNA_Lattice) && ELEM(type, -1, OB_LATTICE)) {
247 return true;
248 }
249 if (RNA_struct_is_a(ptr->type, &RNA_Camera) && ELEM(type, -1, OB_CAMERA)) {
250 return true;
251 }
252 if (RNA_struct_is_a(ptr->type, &RNA_Light) && ELEM(type, -1, OB_LAMP)) {
253 return true;
254 }
255 if (RNA_struct_is_a(ptr->type, &RNA_Speaker) && ELEM(type, -1, OB_SPEAKER)) {
256 return true;
257 }
258 if (RNA_struct_is_a(ptr->type, &RNA_LightProbe) && ELEM(type, -1, OB_LIGHTPROBE)) {
259 return true;
260 }
261 if (RNA_struct_is_a(ptr->type, &RNA_GreasePencilv3) && ELEM(type, -1, OB_GREASE_PENCIL)) {
262 return true;
263 }
264 if (RNA_struct_is_a(ptr->type, &RNA_Curves) && ELEM(type, -1, OB_CURVES)) {
265 return true;
266 }
267 if (RNA_struct_is_a(ptr->type, &RNA_PointCloud) && ELEM(type, -1, OB_POINTCLOUD)) {
268 return true;
269 }
270 if (RNA_struct_is_a(ptr->type, &RNA_Volume) && ELEM(type, -1, OB_VOLUME)) {
271 return true;
272 }
273 /* try to get an object in the path, no pinning supported here */
274 if (buttons_context_path_object(path)) {
275 Object *ob = static_cast<Object *>(path->ptr[path->len - 1].data);
276
277 if (ob && ELEM(type, -1, ob->type)) {
278 path->ptr[path->len] = RNA_id_pointer_create(static_cast<ID *>(ob->data));
279 path->len++;
280
281 return true;
282 }
283 }
284
285 /* no path to data possible */
286 return false;
287}
288
290{
291 if (buttons_context_path_object(path)) {
292 Object *ob = static_cast<Object *>(path->ptr[path->len - 1].data);
293
294 if (ELEM(ob->type,
295 OB_MESH,
297 OB_FONT,
298 OB_SURF,
301 OB_CURVES,
303 OB_VOLUME))
304 {
306 if (md != nullptr) {
307 path->ptr[path->len] = RNA_pointer_create_discrete(&ob->id, &RNA_Modifier, md);
308 path->len++;
309 }
310
311 return true;
312 }
313 }
314
315 return false;
316}
317
319{
320 if (buttons_context_path_object(path)) {
321 Object *ob = static_cast<Object *>(path->ptr[path->len - 1].data);
322
323 if (ob && ob->type == OB_GREASE_PENCIL) {
324 return true;
325 }
326 }
327
328 return false;
329}
330
332{
333 PointerRNA *ptr = &path->ptr[path->len - 1];
334
335 /* if we already have a (pinned) material, we're done */
336 if (RNA_struct_is_a(ptr->type, &RNA_Material)) {
337 return true;
338 }
339 /* if we have an object, use the object material slot */
340 if (buttons_context_path_object(path)) {
341 Object *ob = static_cast<Object *>(path->ptr[path->len - 1].data);
342
343 if (ob && OB_TYPE_SUPPORT_MATERIAL(ob->type)) {
345
346 const int slot = blender::math::max(ob->actcol - 1, 0);
347 if (ob->matbits && ob->matbits[slot] == 0) {
348 /* When material from active slot is stored in object data, include it in context path, see
349 * !134968. */
351 }
352 if (ma != nullptr) {
353 path->ptr[path->len] = RNA_id_pointer_create(&ma->id);
354 path->len++;
355 }
356 return true;
357 }
358 }
359
360 /* no path to a material possible */
361 return false;
362}
363
365{
366 /* if we have an armature, get the active bone */
368 bArmature *arm = static_cast<bArmature *>(path->ptr[path->len - 1].data);
369
370 if (arm->edbo) {
371 if (arm->act_edbone) {
372 EditBone *edbo = arm->act_edbone;
373 path->ptr[path->len] = RNA_pointer_create_discrete(&arm->id, &RNA_EditBone, edbo);
374 path->len++;
375 return true;
376 }
377 }
378 else {
379 if (arm->act_bone) {
380 path->ptr[path->len] = RNA_pointer_create_discrete(&arm->id, &RNA_Bone, arm->act_bone);
381 path->len++;
382 return true;
383 }
384 }
385 }
386
387 /* no path to a bone possible */
388 return false;
389}
390
392{
393 PointerRNA *ptr = &path->ptr[path->len - 1];
394
395 /* if we already have a (pinned) PoseBone, we're done */
396 if (RNA_struct_is_a(ptr->type, &RNA_PoseBone)) {
397 return true;
398 }
399
400 /* if we have an armature, get the active bone */
401 if (buttons_context_path_object(path)) {
402 Object *ob = static_cast<Object *>(path->ptr[path->len - 1].data);
403 bArmature *arm = static_cast<bArmature *>(
404 ob->data); /* path->ptr[path->len-1].data - works too */
405
406 if (ob->type != OB_ARMATURE || arm->edbo) {
407 return false;
408 }
409
410 if (arm->act_bone) {
412 if (pchan) {
413 path->ptr[path->len] = RNA_pointer_create_discrete(&ob->id, &RNA_PoseBone, pchan);
414 path->len++;
415 return true;
416 }
417 }
418 }
419
420 /* no path to a bone possible */
421 return false;
422}
423
425{
426 PointerRNA *ptr = &path->ptr[path->len - 1];
427
428 /* if we already have (pinned) particle settings, we're done */
429 if (RNA_struct_is_a(ptr->type, &RNA_ParticleSettings)) {
430 return true;
431 }
432 /* if we have an object, get the active particle system */
433 if (buttons_context_path_object(path)) {
434 Object *ob = static_cast<Object *>(path->ptr[path->len - 1].data);
435
436 if (ob && ob->type == OB_MESH) {
438 if (psys != nullptr) {
439 path->ptr[path->len] = RNA_pointer_create_discrete(&ob->id, &RNA_ParticleSystem, psys);
440 path->len++;
441 }
442 return true;
443 }
444 }
445
446 /* no path to a particle system possible */
447 return false;
448}
449
451{
452 PointerRNA *ptr = &path->ptr[path->len - 1];
453
454 /* if we already have a (pinned) brush, we're done */
455 if (RNA_struct_is_a(ptr->type, &RNA_Brush)) {
456 return true;
457 }
458 /* If we have a scene, use the tool-settings brushes. */
459 if (buttons_context_path_scene(path)) {
460 Scene *scene = static_cast<Scene *>(path->ptr[path->len - 1].data);
461
462 Brush *br = nullptr;
463 if (scene) {
464 wmWindow *window = CTX_wm_window(C);
465 ViewLayer *view_layer = WM_window_get_active_view_layer(window);
466 br = BKE_paint_brush(BKE_paint_get_active(scene, view_layer));
467 }
468
469 if (br) {
470 path->ptr[path->len] = RNA_id_pointer_create((ID *)br);
471 path->len++;
472
473 return true;
474 }
475 }
476
477 /* no path to a brush possible */
478 return false;
479}
480
482 ButsContextPath *path,
484{
485 PointerRNA *ptr = &path->ptr[path->len - 1];
486
487 if (!ct) {
488 return false;
489 }
490
491 /* if we already have a (pinned) texture, we're done */
492 if (RNA_struct_is_a(ptr->type, &RNA_Texture)) {
493 return true;
494 }
495
496 if (!ct->user) {
497 return false;
498 }
499
500 ID *id = ct->user->id;
501
502 if (id) {
503 if (GS(id->name) == ID_BR) {
505 }
506 else if (GS(id->name) == ID_PA) {
508 }
509 else if (GS(id->name) == ID_OB) {
511 }
512 else if (GS(id->name) == ID_LS) {
514 }
515 }
516
517 if (ct->texture) {
518 path->ptr[path->len] = RNA_id_pointer_create(&ct->texture->id);
519 path->len++;
520 }
521
522 return true;
523}
524
525#ifdef WITH_FREESTYLE
526static bool buttons_context_linestyle_pinnable(const bContext *C, ViewLayer *view_layer)
527{
528 wmWindow *window = CTX_wm_window(C);
529 Scene *scene = WM_window_get_active_scene(window);
530
531 /* if Freestyle is disabled in the scene */
532 if ((scene->r.mode & R_EDGE_FRS) == 0) {
533 return false;
534 }
535 /* if Freestyle is not in the Parameter Editor mode */
536 FreestyleConfig *config = &view_layer->freestyle_config;
537 if (config->mode != FREESTYLE_CONTROL_EDITOR_MODE) {
538 return false;
539 }
540 /* if the scene has already been pinned */
542 if (sbuts->pinid && sbuts->pinid == &scene->id) {
543 return false;
544 }
545 return true;
546}
547#endif
548
550 const bContext *C, SpaceProperties *sbuts, ButsContextPath *path, int mainb, int flag)
551{
552 /* Note we don't use CTX_data here, instead we get it from the window.
553 * Otherwise there is a loop reading the context that we are setting. */
554 wmWindow *window = CTX_wm_window(C);
555 Scene *scene = WM_window_get_active_scene(window);
556 ViewLayer *view_layer = WM_window_get_active_view_layer(window);
557
558 *path = {};
559 path->flag = flag;
560
561 /* If some ID datablock is pinned, set the root pointer. */
562 if (sbuts->pinid) {
563 ID *id = sbuts->pinid;
564
565 path->ptr[0] = RNA_id_pointer_create(id);
566 path->len++;
567 }
568 /* No pinned root, use scene as initial root. */
569 else if (mainb != BCONTEXT_TOOL) {
570 path->ptr[0] = RNA_id_pointer_create(&scene->id);
571 path->len++;
572
573 if (!ELEM(mainb,
579 {
580 path->ptr[path->len] = RNA_pointer_create_discrete(nullptr, &RNA_ViewLayer, view_layer);
581 path->len++;
582 }
583 }
584
585 /* now for each buttons context type, we try to construct a path,
586 * tracing back recursively */
587 bool found;
588 switch (mainb) {
589 case BCONTEXT_SCENE:
590 case BCONTEXT_RENDER:
591 case BCONTEXT_OUTPUT:
592 found = buttons_context_path_scene(path);
593 break;
595#ifdef WITH_FREESTYLE
596 if (buttons_context_linestyle_pinnable(C, view_layer)) {
597 found = buttons_context_path_linestyle(path, window);
598 if (found) {
599 break;
600 }
601 }
602#endif
603 found = buttons_context_path_view_layer(path, window);
604 break;
605 case BCONTEXT_WORLD:
606 found = buttons_context_path_world(path);
607 break;
608 case BCONTEXT_COLLECTION: /* This is for Line Art collection flags */
609 found = buttons_context_path_collection(C, path, window);
610 break;
611 case BCONTEXT_TOOL:
612 found = true;
613 break;
614 case BCONTEXT_OBJECT:
615 case BCONTEXT_PHYSICS:
617 found = buttons_context_path_object(path);
618 break;
620 found = buttons_context_path_modifier(path);
621 break;
623 found = buttons_context_path_shaderfx(path);
624 break;
625 case BCONTEXT_DATA:
626 found = buttons_context_path_data(path, -1);
627 break;
629 found = buttons_context_path_particle(path);
630 break;
632 found = buttons_context_path_material(path);
633 break;
634 case BCONTEXT_TEXTURE:
636 C, path, static_cast<ButsContextTexture *>(sbuts->texuser));
637 break;
638 case BCONTEXT_BONE:
639 found = buttons_context_path_bone(path);
640 if (!found) {
642 }
643 break;
645 found = buttons_context_path_pose_bone(path);
646 break;
647 default:
648 found = false;
649 break;
650 }
651
652 return found;
653}
654
655static bool buttons_shading_context(const bContext *C, int mainb)
656{
657 wmWindow *window = CTX_wm_window(C);
658 const Scene *scene = WM_window_get_active_scene(window);
659 ViewLayer *view_layer = WM_window_get_active_view_layer(window);
660 BKE_view_layer_synced_ensure(scene, view_layer);
662
664 return true;
665 }
666 if (mainb == BCONTEXT_DATA && ob && ELEM(ob->type, OB_LAMP, OB_CAMERA)) {
667 return true;
668 }
669
670 return false;
671}
672
674{
675 wmWindow *window = CTX_wm_window(C);
676 const Scene *scene = WM_window_get_active_scene(window);
677 ViewLayer *view_layer = WM_window_get_active_view_layer(window);
678 BKE_view_layer_synced_ensure(scene, view_layer);
680
681 if (flag & (1 << BCONTEXT_MATERIAL)) {
682 return BCONTEXT_MATERIAL;
683 }
684 if (ob && ELEM(ob->type, OB_LAMP, OB_CAMERA) && (flag & (1 << BCONTEXT_DATA))) {
685 return BCONTEXT_DATA;
686 }
687 if (flag & (1 << BCONTEXT_WORLD)) {
688 return BCONTEXT_WORLD;
689 }
690
691 return BCONTEXT_RENDER;
692}
693
695{
696 if (!sbuts->path) {
697 sbuts->path = MEM_new<ButsContextPath>("ButsContextPath");
698 }
699
700 ButsContextPath *path = static_cast<ButsContextPath *>(sbuts->path);
701
702 int pflag = 0;
703 int flag = 0;
704
705 /* Set scene path. */
706 buttons_context_path(C, sbuts, path, BCONTEXT_SCENE, pflag);
707
709
710 /* for each context, see if we can compute a valid path to it, if
711 * this is the case, we know we have to display the button */
712 for (int i = 0; i < BCONTEXT_TOT; i++) {
713 if (buttons_context_path(C, sbuts, path, i, pflag)) {
714 flag |= (1 << i);
715
716 /* setting icon for data context */
717 if (i == BCONTEXT_DATA) {
718 PointerRNA *ptr = &path->ptr[path->len - 1];
719
720 if (ptr->type) {
721 if (RNA_struct_is_a(ptr->type, &RNA_Light)) {
722 sbuts->dataicon = ICON_OUTLINER_DATA_LIGHT;
723 }
724 else {
725 sbuts->dataicon = RNA_struct_ui_icon(ptr->type);
726 }
727 }
728 else {
729 sbuts->dataicon = ICON_EMPTY_DATA;
730 }
731 }
732 }
733 }
734
735 /* always try to use the tab that was explicitly
736 * set to the user, so that once that context comes
737 * back, the tab is activated again */
738 sbuts->mainb = sbuts->mainbuser;
739
740 /* in case something becomes invalid, change */
741 if ((flag & (1 << sbuts->mainb)) == 0) {
742 if (sbuts->flag & SB_SHADING_CONTEXT) {
743 /* try to keep showing shading related buttons */
745 }
746 else if (flag & BCONTEXT_OBJECT) {
747 sbuts->mainb = BCONTEXT_OBJECT;
748 }
749 else {
750 for (int i = 0; i < BCONTEXT_TOT; i++) {
751 if (flag & (1 << i)) {
752 sbuts->mainb = i;
753 break;
754 }
755 }
756 }
757 }
758
759 buttons_context_path(C, sbuts, path, sbuts->mainb, pflag);
760
761 if (!(flag & (1 << sbuts->mainb))) {
762 if (flag & (1 << BCONTEXT_OBJECT)) {
763 sbuts->mainb = BCONTEXT_OBJECT;
764 }
765 else {
766 sbuts->mainb = BCONTEXT_SCENE;
767 }
768 }
769
770 if (buttons_shading_context(C, sbuts->mainb)) {
771 sbuts->flag |= SB_SHADING_CONTEXT;
772 }
773 else {
774 sbuts->flag &= ~SB_SHADING_CONTEXT;
775 }
776
777 sbuts->pathflag = flag;
778}
779
781{
782 for (int i = 0; i < path->len; ++i) {
783 if (ptr->owner_id == path->ptr[i].owner_id) {
784 return true;
785 }
786 }
787 return false;
788}
789
791 const SpaceProperties *sbuts,
792 ScrArea *area)
793{
794 ScrArea *active_area = CTX_wm_area(C);
795 const bool auto_sync = ED_area_has_shared_border(active_area, area) &&
797 return auto_sync || sbuts->outliner_sync == PROPERTIES_SYNC_ALWAYS;
798}
799
801 SpaceProperties *sbuts,
803 const int context)
804{
805 ButsContextPath path;
806 if (buttons_context_path(C, sbuts, &path, context, 0) && is_pointer_in_path(&path, ptr)) {
807 sbuts->mainbuser = context;
808 sbuts->mainb = sbuts->mainbuser;
809 }
810}
811
812/************************* Context Callback ************************/
813
814const char *buttons_context_dir[] = {
815 "texture_slot",
816 "scene",
817 "world",
818 "object",
819 "mesh",
820 "armature",
821 "lattice",
822 "curve",
823 "meta_ball",
824 "light",
825 "speaker",
826 "lightprobe",
827 "camera",
828 "material",
829 "material_slot",
830 "texture",
831 "texture_user",
832 "texture_user_property",
833 "texture_node",
834 "bone",
835 "edit_bone",
836 "pose_bone",
837 "particle_system",
838 "particle_system_editable",
839 "particle_settings",
840 "cloth",
841 "soft_body",
842 "fluid",
843 "collision",
844 "brush",
845 "dynamic_paint",
846 "line_style",
847 "collection",
848 "gpencil",
849 "grease_pencil",
850 "curves",
851 "pointcloud",
852 "volume",
853 nullptr,
854};
855
856int /*eContextResult*/ buttons_context(const bContext *C,
857 const char *member,
859{
861 if (sbuts && sbuts->path == nullptr) {
862 /* path is cleared for #SCREEN_OT_redo_last, when global undo does a file-read which clears the
863 * path (see lib_link_workspace_layout_restore). */
865 }
866 ButsContextPath *path = static_cast<ButsContextPath *>(sbuts ? sbuts->path : nullptr);
867
868 if (!path) {
870 }
871
872 if (sbuts->mainb == BCONTEXT_TOOL) {
874 }
875
876 /* here we handle context, getting data from precomputed path */
877 if (CTX_data_dir(member)) {
878 /* in case of new shading system we skip texture_slot, complex python
879 * UI script logic depends on checking if this is available */
880 if (sbuts->texuser) {
882 }
883 else {
885 }
886 return CTX_RESULT_OK;
887 }
888 if (CTX_data_equals(member, "scene")) {
889 /* Do not return one here if scene is not found in path,
890 * in this case we want to get default context scene! */
891 return set_pointer_type(path, result, &RNA_Scene);
892 }
893 if (CTX_data_equals(member, "world")) {
894 set_pointer_type(path, result, &RNA_World);
895 return CTX_RESULT_OK;
896 }
897 if (CTX_data_equals(member, "collection")) {
898 /* Do not return one here if collection is not found in path,
899 * in this case we want to get default context collection! */
900 return set_pointer_type(path, result, &RNA_Collection);
901 }
902 if (CTX_data_equals(member, "object")) {
903 set_pointer_type(path, result, &RNA_Object);
904 return CTX_RESULT_OK;
905 }
906 if (CTX_data_equals(member, "mesh")) {
907 set_pointer_type(path, result, &RNA_Mesh);
908 return CTX_RESULT_OK;
909 }
910 if (CTX_data_equals(member, "armature")) {
911 set_pointer_type(path, result, &RNA_Armature);
912 return CTX_RESULT_OK;
913 }
914 if (CTX_data_equals(member, "lattice")) {
915 set_pointer_type(path, result, &RNA_Lattice);
916 return CTX_RESULT_OK;
917 }
918 if (CTX_data_equals(member, "curve")) {
919 set_pointer_type(path, result, &RNA_Curve);
920 return CTX_RESULT_OK;
921 }
922 if (CTX_data_equals(member, "meta_ball")) {
923 set_pointer_type(path, result, &RNA_MetaBall);
924 return CTX_RESULT_OK;
925 }
926 if (CTX_data_equals(member, "light")) {
927 set_pointer_type(path, result, &RNA_Light);
928 return CTX_RESULT_OK;
929 }
930 if (CTX_data_equals(member, "camera")) {
931 set_pointer_type(path, result, &RNA_Camera);
932 return CTX_RESULT_OK;
933 }
934 if (CTX_data_equals(member, "speaker")) {
935 set_pointer_type(path, result, &RNA_Speaker);
936 return CTX_RESULT_OK;
937 }
938 if (CTX_data_equals(member, "lightprobe")) {
939 set_pointer_type(path, result, &RNA_LightProbe);
940 return CTX_RESULT_OK;
941 }
942 if (CTX_data_equals(member, "curves")) {
943 set_pointer_type(path, result, &RNA_Curves);
944 return CTX_RESULT_OK;
945 }
946 if (CTX_data_equals(member, "pointcloud")) {
947 set_pointer_type(path, result, &RNA_PointCloud);
948 return CTX_RESULT_OK;
949 }
950 if (CTX_data_equals(member, "volume")) {
951 set_pointer_type(path, result, &RNA_Volume);
952 return CTX_RESULT_OK;
953 }
954 if (CTX_data_equals(member, "material")) {
955 set_pointer_type(path, result, &RNA_Material);
956 return CTX_RESULT_OK;
957 }
958 if (CTX_data_equals(member, "texture")) {
959 ButsContextTexture *ct = static_cast<ButsContextTexture *>(sbuts->texuser);
960
961 if (ct) {
962 if (ct->texture == nullptr) {
963 return CTX_RESULT_NO_DATA;
964 }
965
966 CTX_data_pointer_set(result, &ct->texture->id, &RNA_Texture, ct->texture);
967 }
968
969 return CTX_RESULT_OK;
970 }
971 if (CTX_data_equals(member, "material_slot")) {
972 PointerRNA *ptr = get_pointer_type(path, &RNA_Object);
973
974 if (ptr) {
975 Object *ob = static_cast<Object *>(ptr->data);
976
977 if (ob && OB_TYPE_SUPPORT_MATERIAL(ob->type) && ob->totcol) {
978 /* a valid actcol isn't ensured #27526. */
979 int matnr = ob->actcol - 1;
980 matnr = std::max(matnr, 0);
981 /* Keep aligned with rna_Object_material_slots_get. */
983 result, &ob->id, &RNA_MaterialSlot, (void *)(matnr + uintptr_t(&ob->id)));
984 }
985 }
986
987 return CTX_RESULT_OK;
988 }
989 if (CTX_data_equals(member, "texture_user")) {
990 ButsContextTexture *ct = static_cast<ButsContextTexture *>(sbuts->texuser);
991
992 if (!ct) {
993 return CTX_RESULT_NO_DATA;
994 }
995
996 if (ct->user && ct->user->ptr.data) {
997 ButsTextureUser *user = ct->user;
999 }
1000
1001 return CTX_RESULT_OK;
1002 }
1003 if (CTX_data_equals(member, "texture_user_property")) {
1004 ButsContextTexture *ct = static_cast<ButsContextTexture *>(sbuts->texuser);
1005
1006 if (!ct) {
1007 return CTX_RESULT_NO_DATA;
1008 }
1009
1010 if (ct->user && ct->user->ptr.data) {
1011 ButsTextureUser *user = ct->user;
1012 CTX_data_pointer_set(result, nullptr, &RNA_Property, user->prop);
1013 }
1014
1015 return CTX_RESULT_OK;
1016 }
1017 if (CTX_data_equals(member, "texture_node")) {
1018 ButsContextTexture *ct = static_cast<ButsContextTexture *>(sbuts->texuser);
1019
1020 if (ct) {
1021 /* new shading system */
1022 if (ct->user && ct->user->node) {
1023 CTX_data_pointer_set(result, &ct->user->ntree->id, &RNA_Node, ct->user->node);
1024 }
1025
1026 return CTX_RESULT_OK;
1027 }
1028 return CTX_RESULT_NO_DATA;
1029 }
1030 if (CTX_data_equals(member, "texture_slot")) {
1031 ButsContextTexture *ct = static_cast<ButsContextTexture *>(sbuts->texuser);
1032 PointerRNA *ptr;
1033
1034 /* Particles slots are used in both old and new textures handling. */
1035 if ((ptr = get_pointer_type(path, &RNA_ParticleSystem))) {
1036 ParticleSettings *part = ((ParticleSystem *)ptr->data)->part;
1037
1038 if (part) {
1040 result, &part->id, &RNA_ParticleSettingsTextureSlot, part->mtex[int(part->texact)]);
1041 }
1042 }
1043 else if (ct) {
1044 return CTX_RESULT_MEMBER_NOT_FOUND; /* new shading system */
1045 }
1046 else if ((ptr = get_pointer_type(path, &RNA_FreestyleLineStyle))) {
1047 FreestyleLineStyle *ls = static_cast<FreestyleLineStyle *>(ptr->data);
1048
1049 if (ls) {
1051 result, &ls->id, &RNA_LineStyleTextureSlot, ls->mtex[int(ls->texact)]);
1052 }
1053 }
1054
1055 return CTX_RESULT_OK;
1056 }
1057 if (CTX_data_equals(member, "bone")) {
1058 set_pointer_type(path, result, &RNA_Bone);
1059 return CTX_RESULT_OK;
1060 }
1061 if (CTX_data_equals(member, "edit_bone")) {
1062 set_pointer_type(path, result, &RNA_EditBone);
1063 return CTX_RESULT_OK;
1064 }
1065 if (CTX_data_equals(member, "pose_bone")) {
1066 set_pointer_type(path, result, &RNA_PoseBone);
1067 return CTX_RESULT_OK;
1068 }
1069 if (CTX_data_equals(member, "particle_system")) {
1070 set_pointer_type(path, result, &RNA_ParticleSystem);
1071 return CTX_RESULT_OK;
1072 }
1073 if (CTX_data_equals(member, "particle_system_editable")) {
1074 if (PE_poll((bContext *)C)) {
1075 set_pointer_type(path, result, &RNA_ParticleSystem);
1076 }
1077 else {
1078 CTX_data_pointer_set(result, nullptr, &RNA_ParticleSystem, nullptr);
1079 }
1080 return CTX_RESULT_OK;
1081 }
1082 if (CTX_data_equals(member, "particle_settings")) {
1083 /* only available when pinned */
1084 PointerRNA *ptr = get_pointer_type(path, &RNA_ParticleSettings);
1085
1086 if (ptr && ptr->data) {
1088 return CTX_RESULT_OK;
1089 }
1090
1091 /* get settings from active particle system instead */
1092 ptr = get_pointer_type(path, &RNA_ParticleSystem);
1093
1094 if (ptr && ptr->data) {
1095 ParticleSettings *part = ((ParticleSystem *)ptr->data)->part;
1096 CTX_data_pointer_set(result, ptr->owner_id, &RNA_ParticleSettings, part);
1097 return CTX_RESULT_OK;
1098 }
1099
1100 set_pointer_type(path, result, &RNA_ParticleSettings);
1101 return CTX_RESULT_OK;
1102 }
1103 if (CTX_data_equals(member, "cloth")) {
1104 PointerRNA *ptr = get_pointer_type(path, &RNA_Object);
1105
1106 if (ptr && ptr->data) {
1107 Object *ob = static_cast<Object *>(ptr->data);
1109 CTX_data_pointer_set(result, &ob->id, &RNA_ClothModifier, md);
1110 return CTX_RESULT_OK;
1111 }
1112 return CTX_RESULT_NO_DATA;
1113 }
1114 if (CTX_data_equals(member, "soft_body")) {
1115 PointerRNA *ptr = get_pointer_type(path, &RNA_Object);
1116
1117 if (ptr && ptr->data) {
1118 Object *ob = static_cast<Object *>(ptr->data);
1120 CTX_data_pointer_set(result, &ob->id, &RNA_SoftBodyModifier, md);
1121 return CTX_RESULT_OK;
1122 }
1123 return CTX_RESULT_NO_DATA;
1124 }
1125
1126 if (CTX_data_equals(member, "fluid")) {
1127 PointerRNA *ptr = get_pointer_type(path, &RNA_Object);
1128
1129 if (ptr && ptr->data) {
1130 Object *ob = static_cast<Object *>(ptr->data);
1132 CTX_data_pointer_set(result, &ob->id, &RNA_FluidModifier, md);
1133 return CTX_RESULT_OK;
1134 }
1135 return CTX_RESULT_NO_DATA;
1136 }
1137 if (CTX_data_equals(member, "collision")) {
1138 PointerRNA *ptr = get_pointer_type(path, &RNA_Object);
1139
1140 if (ptr && ptr->data) {
1141 Object *ob = static_cast<Object *>(ptr->data);
1143 CTX_data_pointer_set(result, &ob->id, &RNA_CollisionModifier, md);
1144 return CTX_RESULT_OK;
1145 }
1146 return CTX_RESULT_NO_DATA;
1147 }
1148 if (CTX_data_equals(member, "brush")) {
1149 set_pointer_type(path, result, &RNA_Brush);
1150 return CTX_RESULT_OK;
1151 }
1152 if (CTX_data_equals(member, "dynamic_paint")) {
1153 PointerRNA *ptr = get_pointer_type(path, &RNA_Object);
1154
1155 if (ptr && ptr->data) {
1156 Object *ob = static_cast<Object *>(ptr->data);
1158 CTX_data_pointer_set(result, &ob->id, &RNA_DynamicPaintModifier, md);
1159 return CTX_RESULT_OK;
1160 }
1161 return CTX_RESULT_NO_DATA;
1162 }
1163 if (CTX_data_equals(member, "line_style")) {
1164 set_pointer_type(path, result, &RNA_FreestyleLineStyle);
1165 return CTX_RESULT_OK;
1166 }
1167 if (CTX_data_equals(member, "gpencil")) {
1168 set_pointer_type(path, result, &RNA_GreasePencil);
1169 return CTX_RESULT_OK;
1170 }
1171 if (CTX_data_equals(member, "grease_pencil")) {
1172 set_pointer_type(path, result, &RNA_GreasePencilv3);
1173 return CTX_RESULT_OK;
1174 }
1176}
1177
1178/************************* Drawing the Path ************************/
1179
1180static bool buttons_panel_context_poll(const bContext *C, PanelType * /*pt*/)
1181{
1183 return sbuts->mainb != BCONTEXT_TOOL;
1184}
1185
1186static void buttons_panel_context_draw(const bContext *C, Panel *panel)
1187{
1189 ButsContextPath *path = static_cast<ButsContextPath *>(sbuts->path);
1190
1191 if (!path) {
1192 return;
1193 }
1194
1195 uiLayout *row = &panel->layout->row(true);
1197
1198 bool first = true;
1199 for (int i = 0; i < path->len; i++) {
1200 PointerRNA *ptr = &path->ptr[i];
1201
1202 /* Skip scene and view layer to save space. */
1203 if (!ELEM(sbuts->mainb,
1208 BCONTEXT_WORLD) &&
1209 ptr->type == &RNA_Scene)
1210 {
1211 continue;
1212 }
1213 if (!ELEM(sbuts->mainb,
1218 BCONTEXT_WORLD) &&
1219 ptr->type == &RNA_ViewLayer)
1220 {
1221 continue;
1222 }
1223
1224 if (ptr->data == nullptr) {
1225 continue;
1226 }
1227
1228 /* Add > triangle. */
1229 if (!first) {
1230 row->label("", ICON_RIGHTARROW);
1231 }
1232
1233 /* Add icon and name. */
1234 int icon = RNA_struct_ui_icon(ptr->type);
1235 char namebuf[128];
1236 char *name = RNA_struct_name_get_alloc(ptr, namebuf, sizeof(namebuf), nullptr);
1237
1238 if (name) {
1239 uiItemLDrag(row, ptr, name, icon);
1240
1241 if (name != namebuf) {
1242 MEM_freeN(name);
1243 }
1244 }
1245 else {
1246 row->label("", icon);
1247 }
1248
1249 first = false;
1250 }
1251
1252 uiLayout *pin_row = &row->row(false);
1254 uiItemSpacer(pin_row);
1256 pin_row->op(
1257 "BUTTONS_OT_toggle_pin", "", (sbuts->flag & SB_PIN_CONTEXT) ? ICON_PINNED : ICON_UNPINNED);
1258}
1259
1261{
1262 PanelType *pt = MEM_callocN<PanelType>("spacetype buttons panel context");
1263 STRNCPY(pt->idname, "PROPERTIES_PT_context");
1264 STRNCPY(pt->label, N_("Context")); /* XXX C panels unavailable through RNA bpy.types! */
1269 BLI_addtail(&art->paneltypes, pt);
1270}
1271
1273{
1275 ButsContextPath *path = static_cast<ButsContextPath *>(sbuts->path);
1276
1277 if (path->len == 0) {
1278 return nullptr;
1279 }
1280
1281 for (int i = path->len - 1; i >= 0; i--) {
1282 PointerRNA *ptr = &path->ptr[i];
1283
1284 /* Pin particle settings instead of system, since only settings are an ID-block. */
1285 if (sbuts->mainb == BCONTEXT_PARTICLE && sbuts->flag & SB_PIN_CONTEXT) {
1286 if (ptr->type == &RNA_ParticleSystem && ptr->data) {
1287 ParticleSystem *psys = static_cast<ParticleSystem *>(ptr->data);
1288 return &psys->part->id;
1289 }
1290 }
1291
1292 /* There is no valid image ID panel, Image Empty objects need this workaround. */
1293 if (sbuts->mainb == BCONTEXT_DATA && sbuts->flag & SB_PIN_CONTEXT) {
1294 if (ptr->type == &RNA_Image && ptr->data) {
1295 continue;
1296 }
1297 }
1298
1299 if (ptr->owner_id) {
1300 return ptr->owner_id;
1301 }
1302 }
1303
1304 return nullptr;
1305}
Blender kernel action and pose functionality.
bPoseChannel * BKE_pose_channel_find_name(const bPose *pose, const char *name)
void CTX_data_dir_set(bContextDataResult *result, const char **dir)
bool CTX_data_equals(const char *member, const char *str)
void CTX_data_pointer_set(bContextDataResult *result, ID *id, StructRNA *type, void *data)
bool CTX_data_dir(const char *member)
SpaceProperties * CTX_wm_space_properties(const bContext *C)
ScrArea * CTX_wm_area(const bContext *C)
wmWindow * CTX_wm_window(const bContext *C)
@ CTX_RESULT_MEMBER_NOT_FOUND
@ CTX_RESULT_OK
@ CTX_RESULT_NO_DATA
Scene * CTX_data_scene(const bContext *C)
void CTX_data_pointer_set_ptr(bContextDataResult *result, const PointerRNA *ptr)
void BKE_view_layer_synced_ensure(const Scene *scene, ViewLayer *view_layer)
LayerCollection * BKE_view_layer_active_collection_get(ViewLayer *view_layer)
ViewLayer * BKE_view_layer_default_view(const Scene *scene)
Object * BKE_view_layer_active_object_get(const ViewLayer *view_layer)
Blender kernel freestyle line style functionality.
FreestyleLineStyle * BKE_linestyle_active_from_view_layer(struct ViewLayer *view_layer)
Definition linestyle.cc:704
General operations, lookup, etc. for materials.
Material * BKE_object_material_get(Object *ob, short act)
ModifierData * BKE_modifiers_findby_type(const Object *ob, ModifierType type)
General operations, lookup, etc. for blender objects.
ModifierData * BKE_object_active_modifier(const Object *ob)
Paint * BKE_paint_get_active(Scene *sce, ViewLayer *view_layer)
Definition paint.cc:428
Brush * BKE_paint_brush(Paint *paint)
Definition paint.cc:636
struct ParticleSystem * psys_get_current(struct Object *ob)
Definition particle.cc:537
@ PANEL_TYPE_NO_HEADER
@ PANEL_TYPE_NO_SEARCH
void BLI_addtail(ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition listbase.cc:111
char * STRNCPY(char(&dst)[N], const char *src)
Definition BLI_string.h:688
#define ELEM(...)
#define BLT_I18NCONTEXT_DEFAULT_BPYRNA
@ ID_LS
@ ID_BR
@ ID_OB
@ ID_PA
Object groups, one object can be in many groups at once.
@ FREESTYLE_CONTROL_EDITOR_MODE
@ eModifierType_Cloth
@ eModifierType_Fluid
@ eModifierType_Collision
@ eModifierType_DynamicPaint
@ eModifierType_Softbody
@ OB_SPEAKER
@ OB_LATTICE
@ OB_MBALL
@ OB_SURF
@ OB_CAMERA
@ OB_FONT
@ OB_GREASE_PENCIL
@ OB_ARMATURE
@ OB_LAMP
@ OB_MESH
@ OB_POINTCLOUD
@ OB_VOLUME
@ OB_CURVES_LEGACY
@ OB_CURVES
@ OB_LIGHTPROBE
#define OB_TYPE_SUPPORT_MATERIAL(_type)
@ R_EDGE_FRS
@ SB_SHADING_CONTEXT
@ SB_PIN_CONTEXT
@ PROPERTIES_SYNC_ALWAYS
@ PROPERTIES_SYNC_AUTO
@ 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
bool PE_poll(bContext *C)
bool ED_area_has_shared_border(ScrArea *a, ScrArea *b)
Definition area.cc:2089
Read Guarded memory(de)allocation.
#define C
Definition RandGen.cpp:29
@ UI_LAYOUT_ALIGN_LEFT
@ UI_LAYOUT_ALIGN_RIGHT
void uiLayoutSetAlignment(uiLayout *layout, char alignment)
void uiItemSpacer(uiLayout *layout)
void uiItemLDrag(uiLayout *layout, PointerRNA *ptr, blender::StringRef name, int icon)
void uiLayoutSetEmboss(uiLayout *layout, blender::ui::EmbossType emboss)
static bool buttons_context_path(const bContext *C, SpaceProperties *sbuts, ButsContextPath *path, int mainb, int flag)
static bool buttons_context_path_shaderfx(ButsContextPath *path)
static bool buttons_context_path_bone(ButsContextPath *path)
static bool buttons_context_path_scene(ButsContextPath *path)
static int set_pointer_type(ButsContextPath *path, bContextDataResult *result, StructRNA *type)
static bool buttons_context_path_data(ButsContextPath *path, int type)
const char * buttons_context_dir[]
int buttons_context(const bContext *C, const char *member, bContextDataResult *result)
void ED_buttons_set_context(const bContext *C, SpaceProperties *sbuts, PointerRNA *ptr, const int context)
static PointerRNA * get_pointer_type(ButsContextPath *path, StructRNA *type)
void buttons_context_compute(const bContext *C, SpaceProperties *sbuts)
void buttons_context_register(ARegionType *art)
static bool buttons_context_path_material(ButsContextPath *path)
static bool buttons_context_path_texture(const bContext *C, ButsContextPath *path, ButsContextTexture *ct)
static bool buttons_context_path_pose_bone(ButsContextPath *path)
static bool buttons_context_path_object(ButsContextPath *path)
static int buttons_shading_new_context(const bContext *C, int flag)
static bool buttons_context_path_particle(ButsContextPath *path)
bool ED_buttons_should_sync_with_outliner(const bContext *C, const SpaceProperties *sbuts, ScrArea *area)
static bool buttons_context_path_view_layer(ButsContextPath *path, wmWindow *win)
static bool buttons_context_path_linestyle(ButsContextPath *path, wmWindow *window)
static bool buttons_shading_context(const bContext *C, int mainb)
static bool is_pointer_in_path(ButsContextPath *path, PointerRNA *ptr)
static bool buttons_context_path_brush(const bContext *C, ButsContextPath *path)
static bool buttons_context_path_collection(const bContext *C, ButsContextPath *path, wmWindow *window)
static bool buttons_context_path_world(ButsContextPath *path)
ID * buttons_context_id_path(const bContext *C)
static void buttons_panel_context_draw(const bContext *C, Panel *panel)
static bool buttons_context_path_modifier(ButsContextPath *path)
static bool buttons_panel_context_poll(const bContext *C, PanelType *)
void buttons_texture_context_compute(const bContext *C, SpaceProperties *sbuts)
#define GS(a)
void * MEM_callocN(size_t len, const char *str)
Definition mallocn.cc:118
void MEM_freeN(void *vmemh)
Definition mallocn.cc:113
T max(const T &a, const T &b)
bool RNA_struct_is_a(const StructRNA *type, const StructRNA *srna)
char * RNA_struct_name_get_alloc(PointerRNA *ptr, char *fixedbuf, int fixedlen, int *r_len)
int RNA_struct_ui_icon(const StructRNA *type)
PointerRNA RNA_pointer_create_discrete(ID *id, StructRNA *type, void *data)
PointerRNA RNA_id_pointer_create(ID *id)
ListBase paneltypes
char name[64]
PointerRNA ptr[8]
struct ButsTextureUser * user
bNodeTree * ntree
PropertyRNA * prop
struct MTex * mtex[18]
Definition DNA_ID.h:404
char name[66]
Definition DNA_ID.h:415
struct Collection * collection
struct bPose * pose
char * matbits
void(* draw)(const bContext *C, Panel *panel)
char idname[BKE_ST_MAXNAME]
bool(* poll)(const bContext *C, PanelType *pt)
char translation_context[BKE_ST_MAXNAME]
char label[BKE_ST_MAXNAME]
struct uiLayout * layout
struct MTex * mtex[18]
ParticleSettings * part
ID * owner_id
Definition RNA_types.hh:51
void * data
Definition RNA_types.hh:53
struct Collection * master_collection
struct RenderData r
struct World * world
struct FreestyleConfig freestyle_config
struct EditBone * act_edbone
ListBase * edbo
PointerRNA op(wmOperatorType *ot, std::optional< blender::StringRef > name, int icon, wmOperatorCallContext context, eUI_Item_Flag flag)
void label(blender::StringRef name, int icon)
uiLayout & row(bool align)
struct Scene * scene
i
Definition text_draw.cc:230
#define N_(msgid)
PointerRNA * ptr
Definition wm_files.cc:4227
ViewLayer * WM_window_get_active_view_layer(const wmWindow *win)
Scene * WM_window_get_active_scene(const wmWindow *win)
uint8_t flag
Definition wm_window.cc:139