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