Rename any instance of scene layer or render layer in code with view layer
[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_lamp_types.h"
43 #include "DNA_material_types.h"
44 #include "DNA_node_types.h"
45 #include "DNA_scene_types.h"
46 #include "DNA_world_types.h"
47 #include "DNA_brush_types.h"
48 #include "DNA_linestyle_types.h"
49
50 #include "BKE_context.h"
51 #include "BKE_action.h"
52 #include "BKE_layer.h"
53 #include "BKE_material.h"
54 #include "BKE_modifier.h"
55 #include "BKE_paint.h"
56 #include "BKE_particle.h"
57 #include "BKE_screen.h"
58 #include "BKE_texture.h"
59 #include "BKE_linestyle.h"
60 #include "BKE_workspace.h"
61
62 #include "RNA_access.h"
63
64 #include "ED_buttons.h"
65 #include "ED_armature.h"
66 #include "ED_screen.h"
67 #include "ED_physics.h"
68
69 #include "UI_interface.h"
70 #include "UI_resources.h"
71
72 #include "buttons_intern.h" // own include
73
74 static int set_pointer_type(ButsContextPath *path, bContextDataResult *result, StructRNA *type)
75 {
76         PointerRNA *ptr;
77         int a;
78
79         for (a = 0; a < path->len; a++) {
80                 ptr = &path->ptr[a];
81
82                 if (RNA_struct_is_a(ptr->type, type)) {
83                         CTX_data_pointer_set(result, ptr->id.data, ptr->type, ptr->data);
84                         return 1;
85                 }
86         }
87
88         return 0;
89 }
90
91 static PointerRNA *get_pointer_type(ButsContextPath *path, StructRNA *type)
92 {
93         PointerRNA *ptr;
94         int a;
95
96         for (a = 0; a < path->len; a++) {
97                 ptr = &path->ptr[a];
98
99                 if (RNA_struct_is_a(ptr->type, type))
100                         return ptr;
101         }
102
103         return NULL;
104 }
105
106 /************************* Creating the Path ************************/
107
108 static int buttons_context_path_scene(ButsContextPath *path)
109 {
110         PointerRNA *ptr = &path->ptr[path->len - 1];
111
112         /* this one just verifies */
113         return RNA_struct_is_a(ptr->type, &RNA_Scene);
114 }
115
116 /* note: this function can return 1 without adding a world to the path
117  * so the buttons stay visible, but be sure to check the ID type if a ID_WO */
118 static int buttons_context_path_world(ButsContextPath *path)
119 {
120         Scene *scene;
121         World *world;
122         PointerRNA *ptr = &path->ptr[path->len - 1];
123
124         /* if we already have a (pinned) world, we're done */
125         if (RNA_struct_is_a(ptr->type, &RNA_World)) {
126                 return 1;
127         }
128         /* if we have a scene, use the scene's world */
129         else if (buttons_context_path_scene(path)) {
130                 scene = path->ptr[path->len - 1].data;
131                 world = scene->world;
132                 
133                 if (world) {
134                         RNA_id_pointer_create(&scene->world->id, &path->ptr[path->len]);
135                         path->len++;
136                         return 1;
137                 }
138                 else {
139                         return 1;
140                 }
141         }
142
143         /* no path to a world possible */
144         return 0;
145 }
146
147 static int buttons_context_path_linestyle(ButsContextPath *path)
148 {
149         Scene *scene;
150         FreestyleLineStyle *linestyle;
151         PointerRNA *ptr = &path->ptr[path->len - 1];
152
153         /* if we already have a (pinned) linestyle, we're done */
154         if (RNA_struct_is_a(ptr->type, &RNA_FreestyleLineStyle)) {
155                 return 1;
156         }
157         /* if we have a scene, use the lineset's linestyle */
158         else if (buttons_context_path_scene(path)) {
159                 scene = path->ptr[path->len - 1].data;
160                 linestyle = BKE_linestyle_active_from_scene(scene);
161                 if (linestyle) {
162                         RNA_id_pointer_create(&linestyle->id, &path->ptr[path->len]);
163                         path->len++;
164                         return 1;
165                 }
166         }
167
168         /* no path to a linestyle possible */
169         return 0;
170 }
171
172 static int buttons_context_path_workspace(ButsContextPath *path)
173 {
174         PointerRNA *ptr = &path->ptr[path->len - 1];
175
176         /* This one just verifies. */
177         return RNA_struct_is_a(ptr->type, &RNA_WorkSpace);
178 }
179
180 static int buttons_context_path_collection(ButsContextPath *path)
181 {
182         PointerRNA *ptr = &path->ptr[path->len - 1];
183
184         /* if we already have a (pinned) Collection, we're done */
185         if (RNA_struct_is_a(ptr->type, &RNA_LayerCollection)) {
186                 return 1;
187         }
188
189         ViewLayer *sl = ptr->data;
190         LayerCollection *sc = BKE_layer_collection_get_active(sl);
191
192         if (sc) {
193                 RNA_pointer_create(NULL, &RNA_LayerCollection, sc, &path->ptr[path->len]);
194                 path->len++;
195                 return 1;
196         }
197
198         /* no path to a collection possible */
199         return 0;
200 }
201
202 static int buttons_context_path_object(ButsContextPath *path)
203 {
204         PointerRNA *ptr = &path->ptr[path->len - 1];
205
206         /* if we already have a (pinned) object, we're done */
207         if (RNA_struct_is_a(ptr->type, &RNA_Object)) {
208                 return 1;
209         }
210
211         ViewLayer *sl = ptr->data;
212         Object *ob = (sl->basact) ? sl->basact->object : NULL;
213
214         if (ob) {
215                 RNA_id_pointer_create(&ob->id, &path->ptr[path->len]);
216                 path->len++;
217
218                 return 1;
219         }
220
221         /* no path to a object possible */
222         return 0;
223 }
224
225 static int buttons_context_path_data(ButsContextPath *path, int type)
226 {
227         Object *ob;
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) && (type == -1 || type == OB_MESH)) return 1;
232         else if (RNA_struct_is_a(ptr->type, &RNA_Curve) && (type == -1 || ELEM(type, OB_CURVE, OB_SURF, OB_FONT))) return 1;
233         else if (RNA_struct_is_a(ptr->type, &RNA_Armature) && (type == -1 || type == OB_ARMATURE)) return 1;
234         else if (RNA_struct_is_a(ptr->type, &RNA_MetaBall) && (type == -1 || type == OB_MBALL)) return 1;
235         else if (RNA_struct_is_a(ptr->type, &RNA_Lattice) && (type == -1 || type == OB_LATTICE)) return 1;
236         else if (RNA_struct_is_a(ptr->type, &RNA_Camera) && (type == -1 || type == OB_CAMERA)) return 1;
237         else if (RNA_struct_is_a(ptr->type, &RNA_Lamp) && (type == -1 || type == OB_LAMP)) return 1;
238         else if (RNA_struct_is_a(ptr->type, &RNA_Speaker) && (type == -1 || type == OB_SPEAKER)) return 1;
239         else if (RNA_struct_is_a(ptr->type, &RNA_LightProbe) && (type == -1 || type == OB_LIGHTPROBE)) 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))
264                         return 1;
265         }
266
267         return 0;
268 }
269
270 static int buttons_context_path_material(ButsContextPath *path, bool for_texture, bool new_shading)
271 {
272         Object *ob;
273         PointerRNA *ptr = &path->ptr[path->len - 1];
274         Material *ma;
275
276         /* if we already have a (pinned) material, we're done */
277         if (RNA_struct_is_a(ptr->type, &RNA_Material)) {
278                 return 1;
279         }
280         /* if we have an object, use the object material slot */
281         else if (buttons_context_path_object(path)) {
282                 ob = path->ptr[path->len - 1].data;
283
284                 if (ob && OB_TYPE_SUPPORT_MATERIAL(ob->type)) {
285                         ma = give_current_material(ob, ob->actcol);
286                         RNA_id_pointer_create(&ma->id, &path->ptr[path->len]);
287                         path->len++;
288
289                         if (for_texture && give_current_material_texture_node(ma))
290                                 return 1;
291
292                         if (!new_shading) {
293                                 /* Only try to get mat from node in case of old shading system (see T40331). */
294                                 ma = give_node_material(ma);
295                                 if (ma) {
296                                         RNA_id_pointer_create(&ma->id, &path->ptr[path->len]);
297                                         path->len++;
298                                 }
299                         }
300                         return 1;
301                 }
302         }
303
304         /* no path to a material possible */
305         return 0;
306 }
307
308 static int buttons_context_path_bone(ButsContextPath *path)
309 {
310         bArmature *arm;
311         EditBone *edbo;
312
313         /* if we have an armature, get the active bone */
314         if (buttons_context_path_data(path, OB_ARMATURE)) {
315                 arm = path->ptr[path->len - 1].data;
316
317                 if (arm->edbo) {
318                         if (arm->act_edbone) {
319                                 edbo = arm->act_edbone;
320                                 RNA_pointer_create(&arm->id, &RNA_EditBone, edbo, &path->ptr[path->len]);
321                                 path->len++;
322                                 return 1;
323                         }
324                 }
325                 else {
326                         if (arm->act_bone) {
327                                 RNA_pointer_create(&arm->id, &RNA_Bone, arm->act_bone, &path->ptr[path->len]);
328                                 path->len++;
329                                 return 1;
330                         }
331                 }
332         }
333
334         /* no path to a bone possible */
335         return 0;
336 }
337
338 static int buttons_context_path_pose_bone(ButsContextPath *path)
339 {
340         PointerRNA *ptr = &path->ptr[path->len - 1];
341
342         /* if we already have a (pinned) PoseBone, we're done */
343         if (RNA_struct_is_a(ptr->type, &RNA_PoseBone)) {
344                 return 1;
345         }
346
347         /* if we have an armature, get the active bone */
348         if (buttons_context_path_object(path)) {
349                 Object *ob = path->ptr[path->len - 1].data;
350                 bArmature *arm = ob->data; /* path->ptr[path->len-1].data - works too */
351
352                 if (ob->type != OB_ARMATURE || arm->edbo) {
353                         return 0;
354                 }
355                 else {
356                         if (arm->act_bone) {
357                                 bPoseChannel *pchan = BKE_pose_channel_find_name(ob->pose, arm->act_bone->name);
358                                 if (pchan) {
359                                         RNA_pointer_create(&ob->id, &RNA_PoseBone, pchan, &path->ptr[path->len]);
360                                         path->len++;
361                                         return 1;
362                                 }
363                         }
364                 }
365         }
366
367         /* no path to a bone possible */
368         return 0;
369 }
370
371
372 static int buttons_context_path_particle(ButsContextPath *path)
373 {
374         Object *ob;
375         ParticleSystem *psys;
376         PointerRNA *ptr = &path->ptr[path->len - 1];
377
378         /* if we already have (pinned) particle settings, we're done */
379         if (RNA_struct_is_a(ptr->type, &RNA_ParticleSettings)) {
380                 return 1;
381         }
382         /* if we have an object, get the active particle system */
383         if (buttons_context_path_object(path)) {
384                 ob = path->ptr[path->len - 1].data;
385
386                 if (ob && ob->type == OB_MESH) {
387                         psys = psys_get_current(ob);
388
389                         RNA_pointer_create(&ob->id, &RNA_ParticleSystem, psys, &path->ptr[path->len]);
390                         path->len++;
391                         return 1;
392                 }
393         }
394
395         /* no path to a particle system possible */
396         return 0;
397 }
398
399 static int buttons_context_path_brush(const bContext *C, ButsContextPath *path)
400 {
401         Scene *scene;
402         Brush *br = NULL;
403         PointerRNA *ptr = &path->ptr[path->len - 1];
404
405         /* if we already have a (pinned) brush, we're done */
406         if (RNA_struct_is_a(ptr->type, &RNA_Brush)) {
407                 return 1;
408         }
409         /* if we have a scene, use the toolsettings brushes */
410         else if (buttons_context_path_scene(path)) {
411                 scene = path->ptr[path->len - 1].data;
412
413                 if (scene) {
414                         ViewLayer *sl = CTX_data_view_layer(C);
415                         br = BKE_paint_brush(BKE_paint_get_active(scene, sl));
416                 }
417
418                 if (br) {
419                         RNA_id_pointer_create((ID *)br, &path->ptr[path->len]);
420                         path->len++;
421
422                         return 1;
423                 }
424         }
425
426         /* no path to a brush possible */
427         return 0;
428 }
429
430 static int buttons_context_path_texture(const bContext *C, ButsContextPath *path, ButsContextTexture *ct)
431 {
432         if (ct) {
433                 /* new shading system */
434                 PointerRNA *ptr = &path->ptr[path->len - 1];
435                 ID *id;
436
437                 /* if we already have a (pinned) texture, we're done */
438                 if (RNA_struct_is_a(ptr->type, &RNA_Texture))
439                         return 1;
440
441                 if (!ct->user)
442                         return 0;
443                 
444                 id = ct->user->id;
445
446                 if (id) {
447                         if (GS(id->name) == ID_BR)
448                                 buttons_context_path_brush(C, path);
449                         else if (GS(id->name) == ID_MA)
450                                 buttons_context_path_material(path, false, true);
451                         else if (GS(id->name) == ID_WO)
452                                 buttons_context_path_world(path);
453                         else if (GS(id->name) == ID_LA)
454                                 buttons_context_path_data(path, OB_LAMP);
455                         else if (GS(id->name) == ID_PA)
456                                 buttons_context_path_particle(path);
457                         else if (GS(id->name) == ID_OB)
458                                 buttons_context_path_object(path);
459                         else if (GS(id->name) == ID_LS)
460                                 buttons_context_path_linestyle(path);
461                 }
462
463                 if (ct->texture) {
464                         RNA_id_pointer_create(&ct->texture->id, &path->ptr[path->len]);
465                         path->len++;
466                 }
467
468                 return 1;
469         }
470         else {
471                 /* old shading system */
472                 Material *ma;
473                 Lamp *la;
474                 World *wo;
475                 ParticleSystem *psys;
476                 FreestyleLineStyle *ls;
477                 Tex *tex;
478                 PointerRNA *ptr = &path->ptr[path->len - 1];
479
480                 /* if we already have a (pinned) texture, we're done */
481                 if (RNA_struct_is_a(ptr->type, &RNA_Texture)) {
482                         return 1;
483                 }
484                 /* try world */
485                 else if ((path->tex_ctx == SB_TEXC_WORLD) && buttons_context_path_world(path)) {
486                         wo = path->ptr[path->len - 1].data;
487
488                         if (wo && GS(wo->id.name) == ID_WO) {
489                                 tex = give_current_world_texture(wo);
490
491                                 RNA_id_pointer_create(&tex->id, &path->ptr[path->len]);
492                                 path->len++;
493                                 return 1;
494                         }
495                 }
496                 /* try particles */
497                 else if ((path->tex_ctx == SB_TEXC_PARTICLES) && buttons_context_path_particle(path)) {
498                         if (path->ptr[path->len - 1].type == &RNA_ParticleSettings) {
499                                 ParticleSettings *part = path->ptr[path->len - 1].data;
500
501                                 tex = give_current_particle_texture(part);
502                                 RNA_id_pointer_create(&tex->id, &path->ptr[path->len]);
503                                 path->len++;
504                                 return 1;
505                         }
506                         else {
507                                 psys = path->ptr[path->len - 1].data;
508
509                                 if (psys && psys->part && GS(psys->part->id.name) == ID_PA) {
510                                         tex = give_current_particle_texture(psys->part);
511
512                                         RNA_id_pointer_create(&tex->id, &path->ptr[path->len]);
513                                         path->len++;
514                                         return 1;
515                                 }
516                         }
517                 }
518                 /* try material */
519                 else if ((path->tex_ctx == SB_TEXC_MATERIAL) && buttons_context_path_material(path, true, false)) {
520                         ma = path->ptr[path->len - 1].data;
521
522                         if (ma) {
523                                 tex = give_current_material_texture(ma);
524
525                                 RNA_id_pointer_create(&tex->id, &path->ptr[path->len]);
526                                 path->len++;
527                                 return 1;
528                         }
529                 }
530                 /* try lamp */
531                 else if ((path->tex_ctx == SB_TEXC_LAMP) && buttons_context_path_data(path, OB_LAMP)) {
532                         la = path->ptr[path->len - 1].data;
533
534                         if (la) {
535                                 tex = give_current_lamp_texture(la);
536
537                                 RNA_id_pointer_create(&tex->id, &path->ptr[path->len]);
538                                 path->len++;
539                                 return 1;
540                         }
541                 }
542                 /* try linestyle */
543                 else if ((path->tex_ctx == SB_TEXC_LINESTYLE) && buttons_context_path_linestyle(path)) {
544                         ls = path->ptr[path->len - 1].data;
545
546                         if (ls) {
547                                 tex = give_current_linestyle_texture(ls);
548
549                                 RNA_id_pointer_create(&tex->id, &path->ptr[path->len]);
550                                 path->len++;
551                                 return 1;
552                         }
553                 }
554         }
555
556         /* no path to a texture possible */
557         return 0;
558 }
559
560 #ifdef WITH_FREESTYLE
561 static bool buttons_context_linestyle_pinnable(const bContext *C)
562 {
563         Scene *scene = CTX_data_scene(C);
564         ViewLayer *active_view_layer;
565         FreestyleConfig *config;
566         SpaceButs *sbuts;
567
568         /* if Freestyle is disabled in the scene */
569         if ((scene->r.mode & R_EDGE_FRS) == 0) {
570                 return false;
571         }
572         /* if Freestyle is not in the Parameter Editor mode */
573         active_view_layer = BLI_findlink(&scene->view_layers, scene->active_view_layer);
574         config = &active_view_layer->freestyle_config;
575         if (config->mode != FREESTYLE_CONTROL_EDITOR_MODE) {
576                 return false;
577         }
578         /* if the scene has already been pinned */
579         sbuts = CTX_wm_space_buts(C);
580         if (sbuts->pinid && sbuts->pinid == &scene->id) {
581                 return false;
582         }
583         return true;
584 }
585 #endif
586
587 static int buttons_context_path(const bContext *C, ButsContextPath *path, int mainb, int flag)
588 {
589         SpaceButs *sbuts = CTX_wm_space_buts(C);
590         Scene *scene = CTX_data_scene(C);
591         WorkSpace *workspace = CTX_wm_workspace(C);
592         ID *id;
593         int found;
594
595         memset(path, 0, sizeof(*path));
596         path->flag = flag;
597         path->tex_ctx = sbuts->texture_context;
598
599         const bool use_scene_settings = BKE_workspace_use_scene_settings_get(workspace);
600
601         /* If some ID datablock is pinned, set the root pointer. */
602         if (sbuts->pinid) {
603                 id = sbuts->pinid;
604
605                 RNA_id_pointer_create(id, &path->ptr[0]);
606                 path->len++;
607         }
608         /* No pinned root, use scene or workspace as initial root. */
609         else {
610                 if ((mainb != BCONTEXT_WORKSPACE) && (use_scene_settings ||
611                     ELEM(mainb, BCONTEXT_SCENE, BCONTEXT_RENDER, BCONTEXT_VIEW_LAYER, BCONTEXT_WORLD)))
612                 {
613                         RNA_id_pointer_create(&scene->id, &path->ptr[0]);
614                         path->len++;
615                 }
616                 else {
617                         RNA_id_pointer_create(&workspace->id, &path->ptr[0]);
618                         path->len++;
619                 }
620         }
621
622         if (!ELEM(mainb, BCONTEXT_WORKSPACE, BCONTEXT_SCENE, BCONTEXT_RENDER, BCONTEXT_VIEW_LAYER, BCONTEXT_WORLD)) {
623                 ViewLayer *view_layer = BKE_view_layer_from_workspace_get(scene, workspace);
624                 RNA_pointer_create(NULL, &RNA_ViewLayer, view_layer, &path->ptr[path->len]);
625                 path->len++;
626         }
627
628         /* now for each buttons context type, we try to construct a path,
629          * tracing back recursively */
630         switch (mainb) {
631                 case BCONTEXT_SCENE:
632                 case BCONTEXT_RENDER:
633                         found = buttons_context_path_scene(path);
634                         break;
635                 case BCONTEXT_VIEW_LAYER:
636 #ifdef WITH_FREESTYLE
637                         if (buttons_context_linestyle_pinnable(C)) {
638                                 found = buttons_context_path_linestyle(path);
639                                 if (found) {
640                                         break;
641                                 }
642                         }
643 #endif
644                         found = buttons_context_path_scene(path);
645                         break;
646                 case BCONTEXT_WORLD:
647                         found = buttons_context_path_world(path);
648                         break;
649                 case BCONTEXT_WORKSPACE:
650                         found = buttons_context_path_workspace(path);
651                         break;
652                 case BCONTEXT_COLLECTION:
653                         found = buttons_context_path_collection(path);
654                         break;
655                 case BCONTEXT_OBJECT:
656                 case BCONTEXT_PHYSICS:
657                 case BCONTEXT_CONSTRAINT:
658                         found = buttons_context_path_object(path);
659                         break;
660                 case BCONTEXT_MODIFIER:
661                         found = buttons_context_path_modifier(path);
662                         break;
663                 case BCONTEXT_DATA:
664                         found = buttons_context_path_data(path, -1);
665                         break;
666                 case BCONTEXT_PARTICLE:
667                         found = buttons_context_path_particle(path);
668                         break;
669                 case BCONTEXT_MATERIAL:
670                         found = buttons_context_path_material(path, false, (sbuts->texuser != NULL));
671                         break;
672                 case BCONTEXT_TEXTURE:
673                         found = buttons_context_path_texture(C, path, sbuts->texuser);
674                         break;
675                 case BCONTEXT_BONE:
676                         found = buttons_context_path_bone(path);
677                         if (!found)
678                                 found = buttons_context_path_data(path, OB_ARMATURE);
679                         break;
680                 case BCONTEXT_BONE_CONSTRAINT:
681                         found = buttons_context_path_pose_bone(path);
682                         break;
683                 default:
684                         found = 0;
685                         break;
686         }
687
688         return found;
689 }
690
691 static int buttons_shading_context(const bContext *C, int mainb)
692 {
693         Object *ob = CTX_data_active_object(C);
694
695         if (ELEM(mainb, BCONTEXT_MATERIAL, BCONTEXT_WORLD, BCONTEXT_TEXTURE))
696                 return 1;
697         if (mainb == BCONTEXT_DATA && ob && ELEM(ob->type, OB_LAMP, OB_CAMERA))
698                 return 1;
699         
700         return 0;
701 }
702
703 static int buttons_shading_new_context(const bContext *C, int flag)
704 {
705         Object *ob = CTX_data_active_object(C);
706
707         if (flag & (1 << BCONTEXT_MATERIAL))
708                 return BCONTEXT_MATERIAL;
709         else if (ob && ELEM(ob->type, OB_LAMP, OB_CAMERA) && (flag & (1 << BCONTEXT_DATA)))
710                 return BCONTEXT_DATA;
711         else if (flag & (1 << BCONTEXT_WORLD))
712                 return BCONTEXT_WORLD;
713         
714         return BCONTEXT_RENDER;
715 }
716
717 void buttons_context_compute(const bContext *C, SpaceButs *sbuts)
718 {
719         ButsContextPath *path;
720         PointerRNA *ptr;
721         int a, pflag = 0, flag = 0;
722
723         if (!sbuts->path)
724                 sbuts->path = MEM_callocN(sizeof(ButsContextPath), "ButsContextPath");
725
726         path = sbuts->path;
727
728         /* We need to set Scene path now! Else, buttons_texture_context_compute() might not get a valid scene. */
729         buttons_context_path(C, path, BCONTEXT_SCENE, pflag);
730
731         buttons_texture_context_compute(C, sbuts);
732
733         /* for each context, see if we can compute a valid path to it, if
734          * this is the case, we know we have to display the button */
735         for (a = 0; a < BCONTEXT_TOT; a++) {
736                 if (buttons_context_path(C, path, a, pflag)) {
737                         flag |= (1 << a);
738
739                         /* setting icon for data context */
740                         if (a == BCONTEXT_DATA) {
741                                 ptr = &path->ptr[path->len - 1];
742
743                                 if (ptr->type)
744                                         sbuts->dataicon = RNA_struct_ui_icon(ptr->type);
745                                 else
746                                         sbuts->dataicon = ICON_EMPTY_DATA;
747                         }
748                 }
749         }
750
751         /* always try to use the tab that was explicitly
752          * set to the user, so that once that context comes
753          * back, the tab is activated again */
754         sbuts->mainb = sbuts->mainbuser;
755
756         /* in case something becomes invalid, change */
757         if ((flag & (1 << sbuts->mainb)) == 0) {
758                 if (sbuts->flag & SB_SHADING_CONTEXT) {
759                         /* try to keep showing shading related buttons */
760                         sbuts->mainb = buttons_shading_new_context(C, flag);
761                 }
762                 else if (flag & BCONTEXT_OBJECT) {
763                         sbuts->mainb = BCONTEXT_OBJECT;
764                 }
765                 else {
766                         for (a = 0; a < BCONTEXT_TOT; a++) {
767                                 if (flag & (1 << a)) {
768                                         sbuts->mainb = a;
769                                         break;
770                                 }
771                         }
772                 }
773         }
774
775         buttons_context_path(C, path, sbuts->mainb, pflag);
776
777         if (!(flag & (1 << sbuts->mainb))) {
778                 if (flag & (1 << BCONTEXT_OBJECT))
779                         sbuts->mainb = BCONTEXT_OBJECT;
780                 else
781                         sbuts->mainb = BCONTEXT_SCENE;
782         }
783
784         if (buttons_shading_context(C, sbuts->mainb))
785                 sbuts->flag |= SB_SHADING_CONTEXT;
786         else
787                 sbuts->flag &= ~SB_SHADING_CONTEXT;
788
789         sbuts->pathflag = flag;
790 }
791
792 /************************* Context Callback ************************/
793
794 const char *buttons_context_dir[] = {
795         "texture_slot", "scene", "world", "object", "mesh", "armature", "lattice", "curve",
796         "meta_ball", "lamp", "speaker", "lightprobe", "camera", "material", "material_slot",
797         "texture", "texture_user", "texture_user_property", "bone", "edit_bone",
798         "pose_bone", "particle_system", "particle_system_editable", "particle_settings",
799         "cloth", "soft_body", "fluid", "smoke", "collision", "brush", "dynamic_paint",
800         "line_style", "collection", "workspace", NULL
801 };
802
803 int buttons_context(const bContext *C, const char *member, bContextDataResult *result)
804 {
805         SpaceButs *sbuts = CTX_wm_space_buts(C);
806         ButsContextPath *path = sbuts ? sbuts->path : NULL;
807
808         if (!path)
809                 return 0;
810
811         /* here we handle context, getting data from precomputed path */
812         if (CTX_data_dir(member)) {
813                 /* in case of new shading system we skip texture_slot, complex python
814                  * UI script logic depends on checking if this is available */
815                 if (sbuts->texuser)
816                         CTX_data_dir_set(result, buttons_context_dir + 1);
817                 else
818                         CTX_data_dir_set(result, buttons_context_dir);
819                 return 1;
820         }
821         else if (CTX_data_equals(member, "scene")) {
822                 /* Do not return one here if scene not found in path, in this case we want to get default context scene! */
823                 return set_pointer_type(path, result, &RNA_Scene);
824         }
825         else if (CTX_data_equals(member, "world")) {
826                 set_pointer_type(path, result, &RNA_World);
827                 return 1;
828         }
829         else if (CTX_data_equals(member, "workspace")) {
830                 /* Do not return one here if scene not found in path, in this case we want to get default context scene! */
831                 return set_pointer_type(path, result, &RNA_WorkSpace);
832         }
833         else if (CTX_data_equals(member, "object")) {
834                 set_pointer_type(path, result, &RNA_Object);
835                 return 1;
836         }
837         else if (CTX_data_equals(member, "mesh")) {
838                 set_pointer_type(path, result, &RNA_Mesh);
839                 return 1;
840         }
841         else if (CTX_data_equals(member, "armature")) {
842                 set_pointer_type(path, result, &RNA_Armature);
843                 return 1;
844         }
845         else if (CTX_data_equals(member, "lattice")) {
846                 set_pointer_type(path, result, &RNA_Lattice);
847                 return 1;
848         }
849         else if (CTX_data_equals(member, "curve")) {
850                 set_pointer_type(path, result, &RNA_Curve);
851                 return 1;
852         }
853         else if (CTX_data_equals(member, "meta_ball")) {
854                 set_pointer_type(path, result, &RNA_MetaBall);
855                 return 1;
856         }
857         else if (CTX_data_equals(member, "lamp")) {
858                 set_pointer_type(path, result, &RNA_Lamp);
859                 return 1;
860         }
861         else if (CTX_data_equals(member, "camera")) {
862                 set_pointer_type(path, result, &RNA_Camera);
863                 return 1;
864         }
865         else if (CTX_data_equals(member, "speaker")) {
866                 set_pointer_type(path, result, &RNA_Speaker);
867                 return 1;
868         }
869         else if (CTX_data_equals(member, "lightprobe")) {
870                 set_pointer_type(path, result, &RNA_LightProbe);
871                 return 1;
872         }
873         else if (CTX_data_equals(member, "material")) {
874                 set_pointer_type(path, result, &RNA_Material);
875                 return 1;
876         }
877         else if (CTX_data_equals(member, "texture")) {
878                 ButsContextTexture *ct = sbuts->texuser;
879
880                 if (ct) {
881                         /* new shading system */
882                         CTX_data_pointer_set(result, &ct->texture->id, &RNA_Texture, ct->texture);
883                 }
884                 else {
885                         /* old shading system */
886                         set_pointer_type(path, result, &RNA_Texture);
887                 }
888
889                 return 1;
890         }
891         else if (CTX_data_equals(member, "material_slot")) {
892                 PointerRNA *ptr = get_pointer_type(path, &RNA_Object);
893
894                 if (ptr) {
895                         Object *ob = ptr->data;
896
897                         if (ob && OB_TYPE_SUPPORT_MATERIAL(ob->type) && ob->totcol) {
898                                 /* a valid actcol isn't ensured [#27526] */
899                                 int matnr = ob->actcol - 1;
900                                 if (matnr < 0) matnr = 0;
901                                 CTX_data_pointer_set(result, &ob->id, &RNA_MaterialSlot, &ob->mat[matnr]);
902                         }
903                 }
904
905                 return 1;
906         }
907         else if (CTX_data_equals(member, "texture_user")) {
908                 ButsContextTexture *ct = sbuts->texuser;
909
910                 if (!ct)
911                         return -1;  /* old shading system (found but not available) */
912
913                 if (ct->user && ct->user->ptr.data) {
914                         ButsTextureUser *user = ct->user;
915                         CTX_data_pointer_set(result, user->ptr.id.data, user->ptr.type, user->ptr.data);
916                 }
917
918                 return 1;
919         }
920         else if (CTX_data_equals(member, "texture_user_property")) {
921                 ButsContextTexture *ct = sbuts->texuser;
922
923                 if (!ct)
924                         return -1;  /* old shading system (found but not available) */
925
926                 if (ct->user && ct->user->ptr.data) {
927                         ButsTextureUser *user = ct->user;
928                         CTX_data_pointer_set(result, NULL, &RNA_Property, user->prop);
929                 }
930
931                 return 1;
932         }
933         else if (CTX_data_equals(member, "texture_node")) {
934                 ButsContextTexture *ct = sbuts->texuser;
935
936                 if (ct) {
937                         /* new shading system */
938                         if (ct->user && ct->user->node) {
939                                 CTX_data_pointer_set(result, &ct->user->ntree->id, &RNA_Node, ct->user->node);
940                         }
941
942                         return 1;
943                 }
944                 else {
945                         /* old shading system */
946                         PointerRNA *ptr;
947
948                         if ((ptr = get_pointer_type(path, &RNA_Material))) {
949                                 Material *ma = ptr->data;
950
951                                 if (ma) {
952                                         bNode *node = give_current_material_texture_node(ma);
953                                         CTX_data_pointer_set(result, &ma->nodetree->id, &RNA_Node, node);
954                                 }
955                         }
956
957                         return 1;
958                 }
959         }
960         else if (CTX_data_equals(member, "texture_slot")) {
961                 ButsContextTexture *ct = sbuts->texuser;
962                 PointerRNA *ptr;
963
964                 /* Particles slots are used in both old and new textures handling. */
965                 if ((ptr = get_pointer_type(path, &RNA_ParticleSystem))) {
966                         ParticleSettings *part = ((ParticleSystem *)ptr->data)->part;
967
968                         if (part)
969                                 CTX_data_pointer_set(result, &part->id, &RNA_ParticleSettingsTextureSlot, part->mtex[(int)part->texact]);
970                 }
971                 else if (ct) {
972                         return 0;  /* new shading system */
973                 }
974                 else if ((ptr = get_pointer_type(path, &RNA_Material))) {
975                         Material *ma = ptr->data;
976
977                         /* if we have a node material, get slot from material in material node */
978                         if (ma && ma->use_nodes && ma->nodetree) {
979                                 /* if there's an active texture node in the node tree,
980                                  * then that texture is in context directly, without a texture slot */
981                                 if (give_current_material_texture_node(ma))
982                                         return 0;
983
984                                 ma = give_node_material(ma);
985                                 if (ma)
986                                         CTX_data_pointer_set(result, &ma->id, &RNA_MaterialTextureSlot, ma->mtex[(int)ma->texact]);
987                                 else
988                                         return 0;
989                         }
990                         else if (ma) {
991                                 CTX_data_pointer_set(result, &ma->id, &RNA_MaterialTextureSlot, ma->mtex[(int)ma->texact]);
992                         }
993                 }
994                 else if ((ptr = get_pointer_type(path, &RNA_Lamp))) {
995                         Lamp *la = ptr->data;
996
997                         if (la)
998                                 CTX_data_pointer_set(result, &la->id, &RNA_LampTextureSlot, la->mtex[(int)la->texact]);
999                 }
1000                 else if ((ptr = get_pointer_type(path, &RNA_World))) {
1001                         World *wo = ptr->data;
1002
1003                         if (wo)
1004                                 CTX_data_pointer_set(result, &wo->id, &RNA_WorldTextureSlot, wo->mtex[(int)wo->texact]);
1005                 }
1006                 else if ((ptr = get_pointer_type(path, &RNA_FreestyleLineStyle))) {
1007                         FreestyleLineStyle *ls = ptr->data;
1008
1009                         if (ls)
1010                                 CTX_data_pointer_set(result, &ls->id, &RNA_LineStyleTextureSlot, ls->mtex[(int)ls->texact]);
1011                 }
1012
1013                 return 1;
1014         }
1015         else if (CTX_data_equals(member, "bone")) {
1016                 set_pointer_type(path, result, &RNA_Bone);
1017                 return 1;
1018         }
1019         else if (CTX_data_equals(member, "edit_bone")) {
1020                 set_pointer_type(path, result, &RNA_EditBone);
1021                 return 1;
1022         }
1023         else if (CTX_data_equals(member, "pose_bone")) {
1024                 set_pointer_type(path, result, &RNA_PoseBone);
1025                 return 1;
1026         }
1027         else if (CTX_data_equals(member, "particle_system")) {
1028                 set_pointer_type(path, result, &RNA_ParticleSystem);
1029                 return 1;
1030         }
1031         else if (CTX_data_equals(member, "particle_system_editable")) {
1032                 if (PE_poll((bContext *)C))
1033                         set_pointer_type(path, result, &RNA_ParticleSystem);
1034                 else
1035                         CTX_data_pointer_set(result, NULL, &RNA_ParticleSystem, NULL);
1036                 return 1;
1037         }
1038         else if (CTX_data_equals(member, "particle_settings")) {
1039                 /* only available when pinned */
1040                 PointerRNA *ptr = get_pointer_type(path, &RNA_ParticleSettings);
1041                 
1042                 if (ptr && ptr->data) {
1043                         CTX_data_pointer_set(result, ptr->id.data, &RNA_ParticleSettings, ptr->data);
1044                         return 1;
1045                 }
1046                 else {
1047                         /* get settings from active particle system instead */
1048                         ptr = get_pointer_type(path, &RNA_ParticleSystem);
1049                         
1050                         if (ptr && ptr->data) {
1051                                 ParticleSettings *part = ((ParticleSystem *)ptr->data)->part;
1052                                 CTX_data_pointer_set(result, ptr->id.data, &RNA_ParticleSettings, part);
1053                                 return 1;
1054                         }
1055                 }
1056                 set_pointer_type(path, result, &RNA_ParticleSettings);
1057                 return 1;
1058         }
1059         else if (CTX_data_equals(member, "cloth")) {
1060                 PointerRNA *ptr = get_pointer_type(path, &RNA_Object);
1061
1062                 if (ptr && ptr->data) {
1063                         Object *ob = ptr->data;
1064                         ModifierData *md = modifiers_findByType(ob, eModifierType_Cloth);
1065                         CTX_data_pointer_set(result, &ob->id, &RNA_ClothModifier, md);
1066                         return 1;
1067                 }
1068         }
1069         else if (CTX_data_equals(member, "soft_body")) {
1070                 PointerRNA *ptr = get_pointer_type(path, &RNA_Object);
1071
1072                 if (ptr && ptr->data) {
1073                         Object *ob = ptr->data;
1074                         ModifierData *md = modifiers_findByType(ob, eModifierType_Softbody);
1075                         CTX_data_pointer_set(result, &ob->id, &RNA_SoftBodyModifier, md);
1076                         return 1;
1077                 }
1078         }
1079         else if (CTX_data_equals(member, "fluid")) {
1080                 PointerRNA *ptr = get_pointer_type(path, &RNA_Object);
1081
1082                 if (ptr && ptr->data) {
1083                         Object *ob = ptr->data;
1084                         ModifierData *md = modifiers_findByType(ob, eModifierType_Fluidsim);
1085                         CTX_data_pointer_set(result, &ob->id, &RNA_FluidSimulationModifier, md);
1086                         return 1;
1087                 }
1088         }
1089         
1090         else if (CTX_data_equals(member, "smoke")) {
1091                 PointerRNA *ptr = get_pointer_type(path, &RNA_Object);
1092
1093                 if (ptr && ptr->data) {
1094                         Object *ob = ptr->data;
1095                         ModifierData *md = modifiers_findByType(ob, eModifierType_Smoke);
1096                         CTX_data_pointer_set(result, &ob->id, &RNA_SmokeModifier, md);
1097                         return 1;
1098                 }
1099         }
1100         else if (CTX_data_equals(member, "collision")) {
1101                 PointerRNA *ptr = get_pointer_type(path, &RNA_Object);
1102
1103                 if (ptr && ptr->data) {
1104                         Object *ob = ptr->data;
1105                         ModifierData *md = modifiers_findByType(ob, eModifierType_Collision);
1106                         CTX_data_pointer_set(result, &ob->id, &RNA_CollisionModifier, md);
1107                         return 1;
1108                 }
1109         }
1110         else if (CTX_data_equals(member, "brush")) {
1111                 set_pointer_type(path, result, &RNA_Brush);
1112                 return 1;
1113         }
1114         else if (CTX_data_equals(member, "dynamic_paint")) {
1115                 PointerRNA *ptr = get_pointer_type(path, &RNA_Object);
1116
1117                 if (ptr && ptr->data) {
1118                         Object *ob = ptr->data;
1119                         ModifierData *md = modifiers_findByType(ob, eModifierType_DynamicPaint);
1120                         CTX_data_pointer_set(result, &ob->id, &RNA_DynamicPaintModifier, md);
1121                         return 1;
1122                 }
1123         }
1124         else if (CTX_data_equals(member, "line_style")) {
1125                 set_pointer_type(path, result, &RNA_FreestyleLineStyle);
1126                 return 1;
1127         }
1128         else if (CTX_data_equals(member, "collection")) {
1129                 set_pointer_type(path, result, &RNA_LayerCollection);
1130                 return 1;
1131         }
1132         else {
1133                 return 0; /* not found */
1134         }
1135
1136         return -1; /* found but not available */
1137 }
1138
1139 /************************* Drawing the Path ************************/
1140
1141 static void pin_cb(bContext *C, void *UNUSED(arg1), void *UNUSED(arg2))
1142 {
1143         SpaceButs *sbuts = CTX_wm_space_buts(C);
1144
1145         if (sbuts->flag & SB_PIN_CONTEXT) {
1146                 sbuts->pinid = buttons_context_id_path(C);
1147         }
1148         else
1149                 sbuts->pinid = NULL;
1150         
1151         ED_area_tag_redraw(CTX_wm_area(C));
1152 }
1153
1154 void buttons_context_draw(const bContext *C, uiLayout *layout)
1155 {
1156         SpaceButs *sbuts = CTX_wm_space_buts(C);
1157         ButsContextPath *path = sbuts->path;
1158         uiLayout *row;
1159         uiBlock *block;
1160         uiBut *but;
1161         PointerRNA *ptr;
1162         char namebuf[128], *name;
1163         int a, icon;
1164
1165         if (!path)
1166                 return;
1167
1168         row = uiLayoutRow(layout, true);
1169         uiLayoutSetAlignment(row, UI_LAYOUT_ALIGN_LEFT);
1170
1171         block = uiLayoutGetBlock(row);
1172         UI_block_emboss_set(block, UI_EMBOSS_NONE);
1173         but = uiDefIconButBitC(block, UI_BTYPE_ICON_TOGGLE, SB_PIN_CONTEXT, 0, ICON_UNPINNED, 0, 0, UI_UNIT_X, UI_UNIT_Y, &sbuts->flag,
1174                                0, 0, 0, 0, TIP_("Follow context or keep fixed data-block displayed"));
1175         UI_but_flag_disable(but, UI_BUT_UNDO); /* skip undo on screen buttons */
1176         UI_but_func_set(but, pin_cb, NULL, NULL);
1177
1178         for (a = 0; a < path->len; a++) {
1179                 ptr = &path->ptr[a];
1180
1181                 if (a != 0)
1182                         uiItemL(row, "", VICO_SMALL_TRI_RIGHT_VEC);
1183
1184                 if (ptr->data) {
1185                         icon = RNA_struct_ui_icon(ptr->type);
1186                         name = RNA_struct_name_get_alloc(ptr, namebuf, sizeof(namebuf), NULL);
1187
1188                         if (name) {
1189                                 if ((!ELEM(sbuts->mainb, BCONTEXT_RENDER, BCONTEXT_SCENE, BCONTEXT_VIEW_LAYER) && ptr->type == &RNA_Scene) ||
1190                                     (!ELEM(sbuts->mainb, BCONTEXT_WORKSPACE) && ptr->type == &RNA_WorkSpace))
1191                                 {
1192                                         uiItemLDrag(row, ptr, "", icon);  /* save some space */
1193                                 }
1194                                 else {
1195                                         uiItemLDrag(row, ptr, name, icon);
1196                                 }
1197
1198                                 if (name != namebuf)
1199                                         MEM_freeN(name);
1200                         }
1201                         else
1202                                 uiItemL(row, "", icon);
1203                 }
1204         }
1205 }
1206
1207 static void buttons_panel_context(const bContext *C, Panel *pa)
1208 {
1209         buttons_context_draw(C, pa->layout);
1210 }
1211
1212 void buttons_context_register(ARegionType *art)
1213 {
1214         PanelType *pt;
1215
1216         pt = MEM_callocN(sizeof(PanelType), "spacetype buttons panel context");
1217         strcpy(pt->idname, "BUTTONS_PT_context");
1218         strcpy(pt->label, N_("Context"));  /* XXX C panels are not available through RNA (bpy.types)! */
1219         strcpy(pt->translation_context, BLT_I18NCONTEXT_DEFAULT_BPYRNA);
1220         pt->draw = buttons_panel_context;
1221         pt->flag = PNL_NO_HEADER;
1222         BLI_addtail(&art->paneltypes, pt);
1223 }
1224
1225 ID *buttons_context_id_path(const bContext *C)
1226 {
1227         SpaceButs *sbuts = CTX_wm_space_buts(C);
1228         ButsContextPath *path = sbuts->path;
1229         PointerRNA *ptr;
1230         int a;
1231
1232         if (path->len) {
1233                 for (a = path->len - 1; a >= 0; a--) {
1234                         ptr = &path->ptr[a];
1235
1236                         /* pin particle settings instead of system, since only settings are an idblock*/
1237                         if (sbuts->mainb == BCONTEXT_PARTICLE && sbuts->flag & SB_PIN_CONTEXT) {
1238                                 if (ptr->type == &RNA_ParticleSystem && ptr->data) {
1239                                         ParticleSystem *psys = (ParticleSystem *)ptr->data;
1240                                         return &psys->part->id;
1241                                 }
1242                         }
1243
1244                         if (ptr->id.data) {
1245                                 return ptr->id.data;
1246                         }
1247                 }
1248         }
1249
1250         return NULL;
1251 }