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