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