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