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