Cleanup: add trailing commas
[blender.git] / source / blender / editors / space_buttons / buttons_context.c
1 /*
2  * ***** BEGIN GPL LICENSE BLOCK *****
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software Foundation,
16  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17  *
18  * The Original Code is Copyright (C) 2009 Blender Foundation.
19  * All rights reserved.
20  *
21  * Contributor(s): Blender Foundation
22  *
23  * ***** END GPL LICENSE BLOCK *****
24  */
25
26 /** \file blender/editors/space_buttons/buttons_context.c
27  *  \ingroup spbuttons
28  */
29
30
31 #include <stdlib.h>
32 #include <string.h>
33
34 #include "MEM_guardedalloc.h"
35
36 #include "BLI_listbase.h"
37 #include "BLI_utildefines.h"
38
39 #include "BLT_translation.h"
40
41 #include "DNA_armature_types.h"
42 #include "DNA_collection_types.h"
43 #include "DNA_lamp_types.h"
44 #include "DNA_material_types.h"
45 #include "DNA_node_types.h"
46 #include "DNA_scene_types.h"
47 #include "DNA_world_types.h"
48 #include "DNA_brush_types.h"
49 #include "DNA_linestyle_types.h"
50 #include "DNA_windowmanager_types.h"
51
52 #include "BKE_context.h"
53 #include "BKE_action.h"
54 #include "BKE_layer.h"
55 #include "BKE_material.h"
56 #include "BKE_modifier.h"
57 #include "BKE_paint.h"
58 #include "BKE_particle.h"
59 #include "BKE_screen.h"
60 #include "BKE_texture.h"
61 #include "BKE_linestyle.h"
62
63 #include "RNA_access.h"
64
65 #include "ED_buttons.h"
66 #include "ED_armature.h"
67 #include "ED_screen.h"
68 #include "ED_physics.h"
69
70 #include "UI_interface.h"
71 #include "UI_resources.h"
72
73 #include "WM_api.h"
74
75 #include "buttons_intern.h" // own include
76
77 static int set_pointer_type(ButsContextPath *path, bContextDataResult *result, StructRNA *type)
78 {
79         PointerRNA *ptr;
80         int a;
81
82         for (a = 0; a < path->len; a++) {
83                 ptr = &path->ptr[a];
84
85                 if (RNA_struct_is_a(ptr->type, type)) {
86                         CTX_data_pointer_set(result, ptr->id.data, ptr->type, ptr->data);
87                         return 1;
88                 }
89         }
90
91         return 0;
92 }
93
94 static PointerRNA *get_pointer_type(ButsContextPath *path, StructRNA *type)
95 {
96         PointerRNA *ptr;
97         int a;
98
99         for (a = 0; a < path->len; a++) {
100                 ptr = &path->ptr[a];
101
102                 if (RNA_struct_is_a(ptr->type, type))
103                         return ptr;
104         }
105
106         return NULL;
107 }
108
109 /************************* Creating the Path ************************/
110
111 static int buttons_context_path_scene(ButsContextPath *path)
112 {
113         PointerRNA *ptr = &path->ptr[path->len - 1];
114
115         /* this one just verifies */
116         return RNA_struct_is_a(ptr->type, &RNA_Scene);
117 }
118
119 static int buttons_context_path_view_layer(ButsContextPath *path, wmWindow *win)
120 {
121         PointerRNA *ptr = &path->ptr[path->len - 1];
122
123         /* View Layer may have already been resolved in a previous call
124          * (e.g. in buttons_context_path_linestyle). */
125         if (RNA_struct_is_a(ptr->type, &RNA_ViewLayer)) {
126                 return 1;
127         }
128
129         if (buttons_context_path_scene(path)) {
130                 Scene *scene = path->ptr[path->len - 1].data;
131                 ViewLayer *view_layer = (win->scene == scene) ?
132                         WM_window_get_active_view_layer(win) :
133                         BKE_view_layer_default_view(scene);
134
135                 RNA_pointer_create(&scene->id, &RNA_ViewLayer, view_layer, &path->ptr[path->len]);
136                 path->len++;
137                 return 1;
138         }
139
140         return 0;
141 }
142
143 /* note: this function can return 1 without adding a world to the path
144  * so the buttons stay visible, but be sure to check the ID type if a ID_WO */
145 static int buttons_context_path_world(ButsContextPath *path)
146 {
147         Scene *scene;
148         World *world;
149         PointerRNA *ptr = &path->ptr[path->len - 1];
150
151         /* if we already have a (pinned) world, we're done */
152         if (RNA_struct_is_a(ptr->type, &RNA_World)) {
153                 return 1;
154         }
155         /* if we have a scene, use the scene's world */
156         else if (buttons_context_path_scene(path)) {
157                 scene = path->ptr[path->len - 1].data;
158                 world = scene->world;
159
160                 if (world) {
161                         RNA_id_pointer_create(&scene->world->id, &path->ptr[path->len]);
162                         path->len++;
163                         return 1;
164                 }
165                 else {
166                         return 1;
167                 }
168         }
169
170         /* no path to a world possible */
171         return 0;
172 }
173
174 static int buttons_context_path_linestyle(ButsContextPath *path, wmWindow *window)
175 {
176         FreestyleLineStyle *linestyle;
177         PointerRNA *ptr = &path->ptr[path->len - 1];
178
179         /* if we already have a (pinned) linestyle, we're done */
180         if (RNA_struct_is_a(ptr->type, &RNA_FreestyleLineStyle)) {
181                 return 1;
182         }
183         /* if we have a view layer, use the lineset's linestyle */
184         else if (buttons_context_path_view_layer(path, window)) {
185                 ViewLayer *view_layer = path->ptr[path->len - 1].data;
186                 linestyle = BKE_linestyle_active_from_view_layer(view_layer);
187                 if (linestyle) {
188                         RNA_id_pointer_create(&linestyle->id, &path->ptr[path->len]);
189                         path->len++;
190                         return 1;
191                 }
192         }
193
194         /* no path to a linestyle possible */
195         return 0;
196 }
197
198 static int buttons_context_path_object(ButsContextPath *path)
199 {
200         PointerRNA *ptr = &path->ptr[path->len - 1];
201
202         /* if we already have a (pinned) object, we're done */
203         if (RNA_struct_is_a(ptr->type, &RNA_Object)) {
204                 return 1;
205         }
206         if (!RNA_struct_is_a(ptr->type, &RNA_ViewLayer)) {
207                 return 0;
208         }
209
210         ViewLayer *view_layer = ptr->data;
211         Object *ob = (view_layer->basact) ? view_layer->basact->object : NULL;
212
213         if (ob) {
214                 RNA_id_pointer_create(&ob->id, &path->ptr[path->len]);
215                 path->len++;
216
217                 return 1;
218         }
219
220         /* no path to a object possible */
221         return 0;
222 }
223
224 static int buttons_context_path_data(ButsContextPath *path, int type)
225 {
226         Object *ob;
227         PointerRNA *ptr = &path->ptr[path->len - 1];
228
229         /* if we already have a data, we're done */
230         if (RNA_struct_is_a(ptr->type, &RNA_Mesh) && (type == -1 || type == OB_MESH)) return 1;
231         else if (RNA_struct_is_a(ptr->type, &RNA_Curve) && (type == -1 || ELEM(type, OB_CURVE, OB_SURF, OB_FONT))) return 1;
232         else if (RNA_struct_is_a(ptr->type, &RNA_Armature) && (type == -1 || type == OB_ARMATURE)) return 1;
233         else if (RNA_struct_is_a(ptr->type, &RNA_MetaBall) && (type == -1 || type == OB_MBALL)) return 1;
234         else if (RNA_struct_is_a(ptr->type, &RNA_Lattice) && (type == -1 || type == OB_LATTICE)) return 1;
235         else if (RNA_struct_is_a(ptr->type, &RNA_Camera) && (type == -1 || type == OB_CAMERA)) return 1;
236         else if (RNA_struct_is_a(ptr->type, &RNA_Light) && (type == -1 || type == OB_LAMP)) return 1;
237         else if (RNA_struct_is_a(ptr->type, &RNA_Speaker) && (type == -1 || type == OB_SPEAKER)) return 1;
238         else if (RNA_struct_is_a(ptr->type, &RNA_LightProbe) && (type == -1 || type == OB_LIGHTPROBE)) return 1;
239         else if (RNA_struct_is_a(ptr->type, &RNA_GreasePencil) && (type == -1 || type == OB_GPENCIL)) return 1;
240         /* try to get an object in the path, no pinning supported here */
241         else if (buttons_context_path_object(path)) {
242                 ob = path->ptr[path->len - 1].data;
243
244                 if (ob && (type == -1 || type == ob->type)) {
245                         RNA_id_pointer_create(ob->data, &path->ptr[path->len]);
246                         path->len++;
247
248                         return 1;
249                 }
250         }
251
252         /* no path to data possible */
253         return 0;
254 }
255
256 static int buttons_context_path_modifier(ButsContextPath *path)
257 {
258         Object *ob;
259
260         if (buttons_context_path_object(path)) {
261                 ob = path->ptr[path->len - 1].data;
262
263                 if (ob && ELEM(ob->type, OB_MESH, OB_CURVE, OB_FONT, OB_SURF, OB_LATTICE, OB_GPENCIL))
264                         return 1;
265         }
266
267         return 0;
268 }
269
270 static int buttons_context_path_shaderfx(ButsContextPath *path)
271 {
272         Object *ob;
273
274         if (buttons_context_path_object(path)) {
275                 ob = path->ptr[path->len - 1].data;
276
277                 if (ob && ELEM(ob->type, OB_GPENCIL))
278                         return 1;
279         }
280
281         return 0;
282 }
283
284 static int buttons_context_path_material(ButsContextPath *path)
285 {
286         Object *ob;
287         PointerRNA *ptr = &path->ptr[path->len - 1];
288         Material *ma;
289
290         /* if we already have a (pinned) material, we're done */
291         if (RNA_struct_is_a(ptr->type, &RNA_Material)) {
292                 return 1;
293         }
294         /* if we have an object, use the object material slot */
295         else if (buttons_context_path_object(path)) {
296                 ob = path->ptr[path->len - 1].data;
297
298                 if (ob && OB_TYPE_SUPPORT_MATERIAL(ob->type)) {
299                         ma = give_current_material(ob, ob->actcol);
300                         RNA_id_pointer_create(&ma->id, &path->ptr[path->len]);
301                         path->len++;
302                         return 1;
303                 }
304         }
305
306         /* no path to a material possible */
307         return 0;
308 }
309
310 static int buttons_context_path_bone(ButsContextPath *path)
311 {
312         bArmature *arm;
313         EditBone *edbo;
314
315         /* if we have an armature, get the active bone */
316         if (buttons_context_path_data(path, OB_ARMATURE)) {
317                 arm = path->ptr[path->len - 1].data;
318
319                 if (arm->edbo) {
320                         if (arm->act_edbone) {
321                                 edbo = arm->act_edbone;
322                                 RNA_pointer_create(&arm->id, &RNA_EditBone, edbo, &path->ptr[path->len]);
323                                 path->len++;
324                                 return 1;
325                         }
326                 }
327                 else {
328                         if (arm->act_bone) {
329                                 RNA_pointer_create(&arm->id, &RNA_Bone, arm->act_bone, &path->ptr[path->len]);
330                                 path->len++;
331                                 return 1;
332                         }
333                 }
334         }
335
336         /* no path to a bone possible */
337         return 0;
338 }
339
340 static int buttons_context_path_pose_bone(ButsContextPath *path)
341 {
342         PointerRNA *ptr = &path->ptr[path->len - 1];
343
344         /* if we already have a (pinned) PoseBone, we're done */
345         if (RNA_struct_is_a(ptr->type, &RNA_PoseBone)) {
346                 return 1;
347         }
348
349         /* if we have an armature, get the active bone */
350         if (buttons_context_path_object(path)) {
351                 Object *ob = path->ptr[path->len - 1].data;
352                 bArmature *arm = ob->data; /* path->ptr[path->len-1].data - works too */
353
354                 if (ob->type != OB_ARMATURE || arm->edbo) {
355                         return 0;
356                 }
357                 else {
358                         if (arm->act_bone) {
359                                 bPoseChannel *pchan = BKE_pose_channel_find_name(ob->pose, arm->act_bone->name);
360                                 if (pchan) {
361                                         RNA_pointer_create(&ob->id, &RNA_PoseBone, pchan, &path->ptr[path->len]);
362                                         path->len++;
363                                         return 1;
364                                 }
365                         }
366                 }
367         }
368
369         /* no path to a bone possible */
370         return 0;
371 }
372
373
374 static int buttons_context_path_particle(ButsContextPath *path)
375 {
376         Object *ob;
377         ParticleSystem *psys;
378         PointerRNA *ptr = &path->ptr[path->len - 1];
379
380         /* if we already have (pinned) particle settings, we're done */
381         if (RNA_struct_is_a(ptr->type, &RNA_ParticleSettings)) {
382                 return 1;
383         }
384         /* if we have an object, get the active particle system */
385         if (buttons_context_path_object(path)) {
386                 ob = path->ptr[path->len - 1].data;
387
388                 if (ob && ob->type == OB_MESH) {
389                         psys = psys_get_current(ob);
390
391                         RNA_pointer_create(&ob->id, &RNA_ParticleSystem, psys, &path->ptr[path->len]);
392                         path->len++;
393                         return 1;
394                 }
395         }
396
397         /* no path to a particle system possible */
398         return 0;
399 }
400
401 static int buttons_context_path_brush(const bContext *C, ButsContextPath *path)
402 {
403         Scene *scene;
404         Brush *br = NULL;
405         PointerRNA *ptr = &path->ptr[path->len - 1];
406
407         /* if we already have a (pinned) brush, we're done */
408         if (RNA_struct_is_a(ptr->type, &RNA_Brush)) {
409                 return 1;
410         }
411         /* if we have a scene, use the toolsettings brushes */
412         else if (buttons_context_path_scene(path)) {
413                 scene = path->ptr[path->len - 1].data;
414
415                 if (scene) {
416                         wmWindow *window = CTX_wm_window(C);
417                         ViewLayer *view_layer = WM_window_get_active_view_layer(window);
418                         br = BKE_paint_brush(BKE_paint_get_active(scene, view_layer));
419                 }
420
421                 if (br) {
422                         RNA_id_pointer_create((ID *)br, &path->ptr[path->len]);
423                         path->len++;
424
425                         return 1;
426                 }
427         }
428
429         /* no path to a brush possible */
430         return 0;
431 }
432
433 static int buttons_context_path_texture(const bContext *C, ButsContextPath *path, ButsContextTexture *ct)
434 {
435         PointerRNA *ptr = &path->ptr[path->len - 1];
436         ID *id;
437
438         if (!ct)
439                 return 0;
440
441         /* if we already have a (pinned) texture, we're done */
442         if (RNA_struct_is_a(ptr->type, &RNA_Texture))
443                 return 1;
444
445         if (!ct->user)
446                 return 0;
447
448         id = ct->user->id;
449
450         if (id) {
451                 if (GS(id->name) == ID_BR)
452                         buttons_context_path_brush(C, path);
453                 else if (GS(id->name) == ID_PA)
454                         buttons_context_path_particle(path);
455                 else if (GS(id->name) == ID_OB)
456                         buttons_context_path_object(path);
457                 else if (GS(id->name) == ID_LS)
458                         buttons_context_path_linestyle(path, CTX_wm_window(C));
459         }
460
461         if (ct->texture) {
462                 RNA_id_pointer_create(&ct->texture->id, &path->ptr[path->len]);
463                 path->len++;
464         }
465
466         return 1;
467 }
468
469 #ifdef WITH_FREESTYLE
470 static bool buttons_context_linestyle_pinnable(const bContext *C, ViewLayer *view_layer)
471 {
472         wmWindow *window = CTX_wm_window(C);
473         Scene *scene = WM_window_get_active_scene(window);
474         FreestyleConfig *config;
475         SpaceButs *sbuts;
476
477         /* if Freestyle is disabled in the scene */
478         if ((scene->r.mode & R_EDGE_FRS) == 0) {
479                 return false;
480         }
481         /* if Freestyle is not in the Parameter Editor mode */
482         config = &view_layer->freestyle_config;
483         if (config->mode != FREESTYLE_CONTROL_EDITOR_MODE) {
484                 return false;
485         }
486         /* if the scene has already been pinned */
487         sbuts = CTX_wm_space_buts(C);
488         if (sbuts->pinid && sbuts->pinid == &scene->id) {
489                 return false;
490         }
491         return true;
492 }
493 #endif
494
495 static int buttons_context_path(const bContext *C, ButsContextPath *path, int mainb, int flag)
496 {
497         /* Note we don't use CTX_data here, instead we get it from the window.
498          * Otherwise there is a loop reading the context that we are setting. */
499         SpaceButs *sbuts = CTX_wm_space_buts(C);
500         wmWindow *window = CTX_wm_window(C);
501         Scene *scene = WM_window_get_active_scene(window);
502         ViewLayer *view_layer = WM_window_get_active_view_layer(window);
503         Object *ob = OBACT(view_layer);
504         ID *id;
505         int found;
506
507         memset(path, 0, sizeof(*path));
508         path->flag = flag;
509
510         /* If some ID datablock is pinned, set the root pointer. */
511         if (sbuts->pinid) {
512                 id = sbuts->pinid;
513
514                 RNA_id_pointer_create(id, &path->ptr[0]);
515                 path->len++;
516         }
517         /* No pinned root, use scene as initial root. */
518         else if (mainb != BCONTEXT_TOOL) {
519                 RNA_id_pointer_create(&scene->id, &path->ptr[0]);
520                 path->len++;
521
522                 if (!ELEM(mainb, BCONTEXT_SCENE, BCONTEXT_RENDER, BCONTEXT_OUTPUT, BCONTEXT_VIEW_LAYER, BCONTEXT_WORLD)) {
523                         RNA_pointer_create(NULL, &RNA_ViewLayer, view_layer, &path->ptr[path->len]);
524                         path->len++;
525                 }
526         }
527
528         /* now for each buttons context type, we try to construct a path,
529          * tracing back recursively */
530         switch (mainb) {
531                 case BCONTEXT_SCENE:
532                 case BCONTEXT_RENDER:
533                 case BCONTEXT_OUTPUT:
534                         found = buttons_context_path_scene(path);
535                         break;
536                 case BCONTEXT_VIEW_LAYER:
537 #ifdef WITH_FREESTYLE
538                         if (buttons_context_linestyle_pinnable(C, view_layer)) {
539                                 found = buttons_context_path_linestyle(path, window);
540                                 if (found) {
541                                         break;
542                                 }
543                         }
544 #endif
545                         found = buttons_context_path_view_layer(path, window);
546                         break;
547                 case BCONTEXT_WORLD:
548                         found = buttons_context_path_world(path);
549                         break;
550                 case BCONTEXT_TOOL:
551                         found = true;
552                         break;
553                 case BCONTEXT_OBJECT:
554                 case BCONTEXT_PHYSICS:
555                 case BCONTEXT_CONSTRAINT:
556                         found = buttons_context_path_object(path);
557                         break;
558                 case BCONTEXT_MODIFIER:
559                         found = buttons_context_path_modifier(path);
560                         break;
561                 case BCONTEXT_SHADERFX:
562                         found = buttons_context_path_shaderfx(path);
563                         break;
564                 case BCONTEXT_DATA:
565                         found = buttons_context_path_data(path, -1);
566                         break;
567                 case BCONTEXT_PARTICLE:
568                         found = buttons_context_path_particle(path);
569                         break;
570                 case BCONTEXT_MATERIAL:
571                         /* NOTE: Grease Pencil materials use different panels... */
572                         if (ob && ob->type == OB_GPENCIL) {
573                                 /* XXX: Why path_data? */
574                                 found = buttons_context_path_data(path, -1);
575                         }
576                         else {
577                                 found = buttons_context_path_material(path);
578                         }
579                         break;
580                 case BCONTEXT_TEXTURE:
581                         found = buttons_context_path_texture(C, path, sbuts->texuser);
582                         break;
583                 case BCONTEXT_BONE:
584                         found = buttons_context_path_bone(path);
585                         if (!found)
586                                 found = buttons_context_path_data(path, OB_ARMATURE);
587                         break;
588                 case BCONTEXT_BONE_CONSTRAINT:
589                         found = buttons_context_path_pose_bone(path);
590                         break;
591                 default:
592                         found = 0;
593                         break;
594         }
595
596         return found;
597 }
598
599 static int buttons_shading_context(const bContext *C, int mainb)
600 {
601         wmWindow *window = CTX_wm_window(C);
602         ViewLayer *view_layer = WM_window_get_active_view_layer(window);
603         Object *ob = OBACT(view_layer);
604
605         if (ELEM(mainb, BCONTEXT_MATERIAL, BCONTEXT_WORLD, BCONTEXT_TEXTURE))
606                 return 1;
607         if (mainb == BCONTEXT_DATA && ob && ELEM(ob->type, OB_LAMP, OB_CAMERA))
608                 return 1;
609
610         return 0;
611 }
612
613 static int buttons_shading_new_context(const bContext *C, int flag)
614 {
615         wmWindow *window = CTX_wm_window(C);
616         ViewLayer *view_layer = WM_window_get_active_view_layer(window);
617         Object *ob = OBACT(view_layer);
618
619         if (flag & (1 << BCONTEXT_MATERIAL))
620                 return BCONTEXT_MATERIAL;
621         else if (ob && ELEM(ob->type, OB_LAMP, OB_CAMERA) && (flag & (1 << BCONTEXT_DATA)))
622                 return BCONTEXT_DATA;
623         else if (flag & (1 << BCONTEXT_WORLD))
624                 return BCONTEXT_WORLD;
625
626         return BCONTEXT_RENDER;
627 }
628
629 void buttons_context_compute(const bContext *C, SpaceButs *sbuts)
630 {
631         ButsContextPath *path;
632         PointerRNA *ptr;
633         int a, pflag = 0, flag = 0;
634
635         if (!sbuts->path)
636                 sbuts->path = MEM_callocN(sizeof(ButsContextPath), "ButsContextPath");
637
638         path = sbuts->path;
639
640         /* Set scene path. */
641         buttons_context_path(C, path, BCONTEXT_SCENE, pflag);
642
643         buttons_texture_context_compute(C, sbuts);
644
645         /* for each context, see if we can compute a valid path to it, if
646          * this is the case, we know we have to display the button */
647         for (a = 0; a < BCONTEXT_TOT; a++) {
648                 if (buttons_context_path(C, path, a, pflag)) {
649                         flag |= (1 << a);
650
651                         /* setting icon for data context */
652                         if (a == BCONTEXT_DATA) {
653                                 ptr = &path->ptr[path->len - 1];
654
655                                 if (ptr->type) {
656                                         sbuts->dataicon = RNA_struct_ui_icon(ptr->type);
657                                 }
658                                 else {
659                                         sbuts->dataicon = ICON_EMPTY_DATA;
660                                 }
661                         }
662                 }
663         }
664
665         /* always try to use the tab that was explicitly
666          * set to the user, so that once that context comes
667          * back, the tab is activated again */
668         sbuts->mainb = sbuts->mainbuser;
669
670         /* in case something becomes invalid, change */
671         if ((flag & (1 << sbuts->mainb)) == 0) {
672                 if (sbuts->flag & SB_SHADING_CONTEXT) {
673                         /* try to keep showing shading related buttons */
674                         sbuts->mainb = buttons_shading_new_context(C, flag);
675                 }
676                 else if (flag & BCONTEXT_OBJECT) {
677                         sbuts->mainb = BCONTEXT_OBJECT;
678                 }
679                 else {
680                         for (a = 0; a < BCONTEXT_TOT; a++) {
681                                 if (flag & (1 << a)) {
682                                         sbuts->mainb = a;
683                                         break;
684                                 }
685                         }
686                 }
687         }
688
689         buttons_context_path(C, path, sbuts->mainb, pflag);
690
691         if (!(flag & (1 << sbuts->mainb))) {
692                 if (flag & (1 << BCONTEXT_OBJECT))
693                         sbuts->mainb = BCONTEXT_OBJECT;
694                 else
695                         sbuts->mainb = BCONTEXT_SCENE;
696         }
697
698         if (buttons_shading_context(C, sbuts->mainb))
699                 sbuts->flag |= SB_SHADING_CONTEXT;
700         else
701                 sbuts->flag &= ~SB_SHADING_CONTEXT;
702
703         sbuts->pathflag = flag;
704 }
705
706 /************************* Context Callback ************************/
707
708 const char *buttons_context_dir[] = {
709         "texture_slot", "scene", "world", "object", "mesh", "armature", "lattice", "curve",
710         "meta_ball", "light", "speaker", "lightprobe", "camera", "material", "material_slot",
711         "texture", "texture_user", "texture_user_property", "bone", "edit_bone",
712         "pose_bone", "particle_system", "particle_system_editable", "particle_settings",
713         "cloth", "soft_body", "fluid", "smoke", "collision", "brush", "dynamic_paint",
714         "line_style", "collection", NULL,
715 };
716
717 int buttons_context(const bContext *C, const char *member, bContextDataResult *result)
718 {
719         SpaceButs *sbuts = CTX_wm_space_buts(C);
720         ButsContextPath *path = sbuts ? sbuts->path : NULL;
721
722         if (!path)
723                 return 0;
724
725         /* here we handle context, getting data from precomputed path */
726         if (CTX_data_dir(member)) {
727                 /* in case of new shading system we skip texture_slot, complex python
728                  * UI script logic depends on checking if this is available */
729                 if (sbuts->texuser)
730                         CTX_data_dir_set(result, buttons_context_dir + 1);
731                 else
732                         CTX_data_dir_set(result, buttons_context_dir);
733                 return 1;
734         }
735         else if (CTX_data_equals(member, "scene")) {
736                 /* Do not return one here if scene not found in path,
737                  * in this case we want to get default context scene! */
738                 return set_pointer_type(path, result, &RNA_Scene);
739         }
740         else if (CTX_data_equals(member, "world")) {
741                 set_pointer_type(path, result, &RNA_World);
742                 return 1;
743         }
744         else if (CTX_data_equals(member, "object")) {
745                 set_pointer_type(path, result, &RNA_Object);
746                 return 1;
747         }
748         else if (CTX_data_equals(member, "mesh")) {
749                 set_pointer_type(path, result, &RNA_Mesh);
750                 return 1;
751         }
752         else if (CTX_data_equals(member, "armature")) {
753                 set_pointer_type(path, result, &RNA_Armature);
754                 return 1;
755         }
756         else if (CTX_data_equals(member, "lattice")) {
757                 set_pointer_type(path, result, &RNA_Lattice);
758                 return 1;
759         }
760         else if (CTX_data_equals(member, "curve")) {
761                 set_pointer_type(path, result, &RNA_Curve);
762                 return 1;
763         }
764         else if (CTX_data_equals(member, "meta_ball")) {
765                 set_pointer_type(path, result, &RNA_MetaBall);
766                 return 1;
767         }
768         else if (CTX_data_equals(member, "light")) {
769                 set_pointer_type(path, result, &RNA_Light);
770                 return 1;
771         }
772         else if (CTX_data_equals(member, "camera")) {
773                 set_pointer_type(path, result, &RNA_Camera);
774                 return 1;
775         }
776         else if (CTX_data_equals(member, "speaker")) {
777                 set_pointer_type(path, result, &RNA_Speaker);
778                 return 1;
779         }
780         else if (CTX_data_equals(member, "lightprobe")) {
781                 set_pointer_type(path, result, &RNA_LightProbe);
782                 return 1;
783         }
784         else if (CTX_data_equals(member, "material")) {
785                 set_pointer_type(path, result, &RNA_Material);
786                 return 1;
787         }
788         else if (CTX_data_equals(member, "texture")) {
789                 ButsContextTexture *ct = sbuts->texuser;
790
791                 if (ct) {
792                         CTX_data_pointer_set(result, &ct->texture->id, &RNA_Texture, ct->texture);
793                 }
794
795                 return 1;
796         }
797         else if (CTX_data_equals(member, "material_slot")) {
798                 PointerRNA *ptr = get_pointer_type(path, &RNA_Object);
799
800                 if (ptr) {
801                         Object *ob = ptr->data;
802
803                         if (ob && OB_TYPE_SUPPORT_MATERIAL(ob->type) && ob->totcol) {
804                                 /* a valid actcol isn't ensured [#27526] */
805                                 int matnr = ob->actcol - 1;
806                                 if (matnr < 0) matnr = 0;
807                                 CTX_data_pointer_set(result, &ob->id, &RNA_MaterialSlot, &ob->mat[matnr]);
808                         }
809                 }
810
811                 return 1;
812         }
813         else if (CTX_data_equals(member, "texture_user")) {
814                 ButsContextTexture *ct = sbuts->texuser;
815
816                 if (!ct)
817                         return -1;
818
819                 if (ct->user && ct->user->ptr.data) {
820                         ButsTextureUser *user = ct->user;
821                         CTX_data_pointer_set(result, user->ptr.id.data, user->ptr.type, user->ptr.data);
822                 }
823
824                 return 1;
825         }
826         else if (CTX_data_equals(member, "texture_user_property")) {
827                 ButsContextTexture *ct = sbuts->texuser;
828
829                 if (!ct)
830                         return -1;
831
832                 if (ct->user && ct->user->ptr.data) {
833                         ButsTextureUser *user = ct->user;
834                         CTX_data_pointer_set(result, NULL, &RNA_Property, user->prop);
835                 }
836
837                 return 1;
838         }
839         else if (CTX_data_equals(member, "texture_node")) {
840                 ButsContextTexture *ct = sbuts->texuser;
841
842                 if (ct) {
843                         /* new shading system */
844                         if (ct->user && ct->user->node) {
845                                 CTX_data_pointer_set(result, &ct->user->ntree->id, &RNA_Node, ct->user->node);
846                         }
847
848                         return 1;
849                 }
850         }
851         else if (CTX_data_equals(member, "texture_slot")) {
852                 ButsContextTexture *ct = sbuts->texuser;
853                 PointerRNA *ptr;
854
855                 /* Particles slots are used in both old and new textures handling. */
856                 if ((ptr = get_pointer_type(path, &RNA_ParticleSystem))) {
857                         ParticleSettings *part = ((ParticleSystem *)ptr->data)->part;
858
859                         if (part)
860                                 CTX_data_pointer_set(result, &part->id, &RNA_ParticleSettingsTextureSlot, part->mtex[(int)part->texact]);
861                 }
862                 else if (ct) {
863                         return 0;  /* new shading system */
864                 }
865                 else if ((ptr = get_pointer_type(path, &RNA_FreestyleLineStyle))) {
866                         FreestyleLineStyle *ls = ptr->data;
867
868                         if (ls)
869                                 CTX_data_pointer_set(result, &ls->id, &RNA_LineStyleTextureSlot, ls->mtex[(int)ls->texact]);
870                 }
871
872                 return 1;
873         }
874         else if (CTX_data_equals(member, "bone")) {
875                 set_pointer_type(path, result, &RNA_Bone);
876                 return 1;
877         }
878         else if (CTX_data_equals(member, "edit_bone")) {
879                 set_pointer_type(path, result, &RNA_EditBone);
880                 return 1;
881         }
882         else if (CTX_data_equals(member, "pose_bone")) {
883                 set_pointer_type(path, result, &RNA_PoseBone);
884                 return 1;
885         }
886         else if (CTX_data_equals(member, "particle_system")) {
887                 set_pointer_type(path, result, &RNA_ParticleSystem);
888                 return 1;
889         }
890         else if (CTX_data_equals(member, "particle_system_editable")) {
891                 if (PE_poll((bContext *)C))
892                         set_pointer_type(path, result, &RNA_ParticleSystem);
893                 else
894                         CTX_data_pointer_set(result, NULL, &RNA_ParticleSystem, NULL);
895                 return 1;
896         }
897         else if (CTX_data_equals(member, "particle_settings")) {
898                 /* only available when pinned */
899                 PointerRNA *ptr = get_pointer_type(path, &RNA_ParticleSettings);
900
901                 if (ptr && ptr->data) {
902                         CTX_data_pointer_set(result, ptr->id.data, &RNA_ParticleSettings, ptr->data);
903                         return 1;
904                 }
905                 else {
906                         /* get settings from active particle system instead */
907                         ptr = get_pointer_type(path, &RNA_ParticleSystem);
908
909                         if (ptr && ptr->data) {
910                                 ParticleSettings *part = ((ParticleSystem *)ptr->data)->part;
911                                 CTX_data_pointer_set(result, ptr->id.data, &RNA_ParticleSettings, part);
912                                 return 1;
913                         }
914                 }
915                 set_pointer_type(path, result, &RNA_ParticleSettings);
916                 return 1;
917         }
918         else if (CTX_data_equals(member, "cloth")) {
919                 PointerRNA *ptr = get_pointer_type(path, &RNA_Object);
920
921                 if (ptr && ptr->data) {
922                         Object *ob = ptr->data;
923                         ModifierData *md = modifiers_findByType(ob, eModifierType_Cloth);
924                         CTX_data_pointer_set(result, &ob->id, &RNA_ClothModifier, md);
925                         return 1;
926                 }
927         }
928         else if (CTX_data_equals(member, "soft_body")) {
929                 PointerRNA *ptr = get_pointer_type(path, &RNA_Object);
930
931                 if (ptr && ptr->data) {
932                         Object *ob = ptr->data;
933                         ModifierData *md = modifiers_findByType(ob, eModifierType_Softbody);
934                         CTX_data_pointer_set(result, &ob->id, &RNA_SoftBodyModifier, md);
935                         return 1;
936                 }
937         }
938         else if (CTX_data_equals(member, "fluid")) {
939                 PointerRNA *ptr = get_pointer_type(path, &RNA_Object);
940
941                 if (ptr && ptr->data) {
942                         Object *ob = ptr->data;
943                         ModifierData *md = modifiers_findByType(ob, eModifierType_Fluidsim);
944                         CTX_data_pointer_set(result, &ob->id, &RNA_FluidSimulationModifier, md);
945                         return 1;
946                 }
947         }
948
949         else if (CTX_data_equals(member, "smoke")) {
950                 PointerRNA *ptr = get_pointer_type(path, &RNA_Object);
951
952                 if (ptr && ptr->data) {
953                         Object *ob = ptr->data;
954                         ModifierData *md = modifiers_findByType(ob, eModifierType_Smoke);
955                         CTX_data_pointer_set(result, &ob->id, &RNA_SmokeModifier, md);
956                         return 1;
957                 }
958         }
959         else if (CTX_data_equals(member, "collision")) {
960                 PointerRNA *ptr = get_pointer_type(path, &RNA_Object);
961
962                 if (ptr && ptr->data) {
963                         Object *ob = ptr->data;
964                         ModifierData *md = modifiers_findByType(ob, eModifierType_Collision);
965                         CTX_data_pointer_set(result, &ob->id, &RNA_CollisionModifier, md);
966                         return 1;
967                 }
968         }
969         else if (CTX_data_equals(member, "brush")) {
970                 set_pointer_type(path, result, &RNA_Brush);
971                 return 1;
972         }
973         else if (CTX_data_equals(member, "dynamic_paint")) {
974                 PointerRNA *ptr = get_pointer_type(path, &RNA_Object);
975
976                 if (ptr && ptr->data) {
977                         Object *ob = ptr->data;
978                         ModifierData *md = modifiers_findByType(ob, eModifierType_DynamicPaint);
979                         CTX_data_pointer_set(result, &ob->id, &RNA_DynamicPaintModifier, md);
980                         return 1;
981                 }
982         }
983         else if (CTX_data_equals(member, "line_style")) {
984                 set_pointer_type(path, result, &RNA_FreestyleLineStyle);
985                 return 1;
986         }
987         else {
988                 return 0; /* not found */
989         }
990
991         return -1; /* found but not available */
992 }
993
994 /************************* Drawing the Path ************************/
995
996 static void pin_cb(bContext *C, void *UNUSED(arg1), void *UNUSED(arg2))
997 {
998         SpaceButs *sbuts = CTX_wm_space_buts(C);
999
1000         if (sbuts->flag & SB_PIN_CONTEXT) {
1001                 sbuts->pinid = buttons_context_id_path(C);
1002         }
1003         else
1004                 sbuts->pinid = NULL;
1005
1006         ED_area_tag_redraw(CTX_wm_area(C));
1007 }
1008
1009 void buttons_context_draw(const bContext *C, uiLayout *layout)
1010 {
1011         SpaceButs *sbuts = CTX_wm_space_buts(C);
1012         ButsContextPath *path = sbuts->path;
1013         uiLayout *row;
1014         uiBlock *block;
1015         uiBut *but;
1016         PointerRNA *ptr;
1017         char namebuf[128], *name;
1018         int a, icon;
1019         bool first = true;
1020
1021         if (!path)
1022                 return;
1023
1024         row = uiLayoutRow(layout, true);
1025         uiLayoutSetAlignment(row, UI_LAYOUT_ALIGN_LEFT);
1026
1027         for (a = 0; a < path->len; a++) {
1028                 ptr = &path->ptr[a];
1029
1030                 /* Skip scene and view layer to save space. */
1031                 if ((!ELEM(sbuts->mainb, BCONTEXT_RENDER, BCONTEXT_OUTPUT, BCONTEXT_SCENE, BCONTEXT_VIEW_LAYER, BCONTEXT_WORLD) && ptr->type == &RNA_Scene)) {
1032                         continue;
1033                 }
1034                 else if ((!ELEM(sbuts->mainb, BCONTEXT_RENDER, BCONTEXT_OUTPUT, BCONTEXT_SCENE, BCONTEXT_VIEW_LAYER, BCONTEXT_WORLD) && ptr->type == &RNA_ViewLayer)) {
1035                         continue;
1036                 }
1037
1038                 /* Add > triangle. */
1039                 if (!first) {
1040                         uiItemL(row, "", ICON_SMALL_TRI_RIGHT_VEC);
1041                 }
1042                 else {
1043                         first = false;
1044                 }
1045
1046                 /* Add icon + name .*/
1047                 if (ptr->data) {
1048                         icon = RNA_struct_ui_icon(ptr->type);
1049                         name = RNA_struct_name_get_alloc(ptr, namebuf, sizeof(namebuf), NULL);
1050
1051                         if (name) {
1052                                 uiItemLDrag(row, ptr, name, icon);
1053
1054                                 if (name != namebuf)
1055                                         MEM_freeN(name);
1056                         }
1057                         else {
1058                                 uiItemL(row, "", icon);
1059                         }
1060                 }
1061         }
1062
1063         uiItemSpacer(row);
1064
1065         block = uiLayoutGetBlock(row);
1066         UI_block_emboss_set(block, UI_EMBOSS_NONE);
1067         but = uiDefIconButBitC(block, UI_BTYPE_ICON_TOGGLE, SB_PIN_CONTEXT, 0, ICON_UNPINNED, 0, 0, UI_UNIT_X, UI_UNIT_Y, &sbuts->flag,
1068                                0, 0, 0, 0, TIP_("Follow context or keep fixed data-block displayed"));
1069         UI_but_flag_disable(but, UI_BUT_UNDO); /* skip undo on screen buttons */
1070         UI_but_func_set(but, pin_cb, NULL, NULL);
1071 }
1072
1073 #ifdef USE_HEADER_CONTEXT_PATH
1074 static bool buttons_header_context_poll(const bContext *C, HeaderType *UNUSED(ht))
1075 #else
1076 static bool buttons_panel_context_poll(const bContext *C, PanelType *UNUSED(pt))
1077 #endif
1078 {
1079         SpaceButs *sbuts = CTX_wm_space_buts(C);
1080         return (sbuts->mainb != BCONTEXT_TOOL);
1081 }
1082
1083 #ifdef USE_HEADER_CONTEXT_PATH
1084 static void buttons_header_context_draw(const bContext *C, Header *ptr)
1085 #else
1086 static void buttons_panel_context_draw(const bContext *C, Panel *ptr)
1087 #endif
1088 {
1089         buttons_context_draw(C, ptr->layout);
1090 }
1091
1092 void buttons_context_register(ARegionType *art)
1093 {
1094 #ifdef USE_HEADER_CONTEXT_PATH
1095         HeaderType *ht;
1096
1097         ht = MEM_callocN(sizeof(HeaderType), "spacetype buttons context header");
1098         strcpy(ht->idname, "BUTTONS_HT_context");
1099         ht->space_type = SPACE_BUTS;
1100         ht->region_type = art->regionid;
1101         ht->poll = buttons_header_context_poll;
1102         ht->draw = buttons_header_context_draw;
1103         BLI_addtail(&art->headertypes, ht);
1104 #else
1105         PanelType *pt;
1106
1107         pt = MEM_callocN(sizeof(PanelType), "spacetype buttons panel context");
1108         strcpy(pt->idname, "BUTTONS_PT_context");
1109         strcpy(pt->label, N_("Context"));  /* XXX C panels unavailable through RNA bpy.types! */
1110         strcpy(pt->translation_context, BLT_I18NCONTEXT_DEFAULT_BPYRNA);
1111         pt->poll = buttons_panel_context_poll;
1112         pt->draw = buttons_panel_context_draw;
1113         pt->flag = PNL_NO_HEADER;
1114         BLI_addtail(&art->paneltypes, pt);
1115 #endif
1116 }
1117
1118 ID *buttons_context_id_path(const bContext *C)
1119 {
1120         SpaceButs *sbuts = CTX_wm_space_buts(C);
1121         ButsContextPath *path = sbuts->path;
1122         PointerRNA *ptr;
1123         int a;
1124
1125         if (path->len) {
1126                 for (a = path->len - 1; a >= 0; a--) {
1127                         ptr = &path->ptr[a];
1128
1129                         /* pin particle settings instead of system, since only settings are an idblock*/
1130                         if (sbuts->mainb == BCONTEXT_PARTICLE && sbuts->flag & SB_PIN_CONTEXT) {
1131                                 if (ptr->type == &RNA_ParticleSystem && ptr->data) {
1132                                         ParticleSystem *psys = (ParticleSystem *)ptr->data;
1133                                         return &psys->part->id;
1134                                 }
1135                         }
1136
1137                         if (ptr->id.data) {
1138                                 return ptr->id.data;
1139                         }
1140                 }
1141         }
1142
1143         return NULL;
1144 }