572176a256abfec13955601b070269f0f4b6670b
[blender-staging.git] / source / blender / editors / space_buttons / buttons_context.c
1 /**
2  * $Id:
3  *
4  * ***** BEGIN GPL LICENSE BLOCK *****
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; either version 2
9  * of the License, or (at your option) any later version. 
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software Foundation,
18  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19  *
20  * The Original Code is Copyright (C) 2009 Blender Foundation.
21  * All rights reserved.
22  *
23  * Contributor(s): Blender Foundation
24  *
25  * ***** END GPL LICENSE BLOCK *****
26  */
27
28 #include <stdlib.h>
29 #include <string.h>
30
31 #include "MEM_guardedalloc.h"
32
33 #include "DNA_armature_types.h"
34 #include "DNA_brush_types.h"
35 #include "DNA_lamp_types.h"
36 #include "DNA_material_types.h"
37 #include "DNA_modifier_types.h"
38 #include "DNA_node_types.h"
39 #include "DNA_object_types.h"
40 #include "DNA_scene_types.h"
41 #include "DNA_screen_types.h"
42 #include "DNA_space_types.h"
43 #include "DNA_particle_types.h"
44 #include "DNA_texture_types.h"
45 #include "DNA_world_types.h"
46
47 #include "BLI_listbase.h"
48
49 #include "BKE_context.h"
50 #include "BKE_global.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 #include "BKE_utildefines.h"
59 #include "BKE_world.h"
60
61 #include "RNA_access.h"
62
63 #include "ED_armature.h"
64 #include "ED_screen.h"
65 #include "ED_physics.h"
66
67 #include "UI_interface.h"
68 #include "UI_resources.h"
69
70 #include "buttons_intern.h"     // own include
71
72 typedef struct ButsContextPath {
73         PointerRNA ptr[8];
74         int len;
75         int flag;
76 } ButsContextPath;
77
78 static int set_pointer_type(ButsContextPath *path, bContextDataResult *result, StructRNA *type)
79 {
80         PointerRNA *ptr;
81         int a;
82
83         for(a=0; a<path->len; a++) {
84                 ptr= &path->ptr[a];
85
86                 if(RNA_struct_is_a(ptr->type, type)) {
87                         CTX_data_pointer_set(result, ptr->id.data, ptr->type, ptr->data);
88                         return 1;
89                 }
90         }
91
92         return 0;
93 }
94
95 static PointerRNA *get_pointer_type(ButsContextPath *path, StructRNA *type)
96 {
97         PointerRNA *ptr;
98         int a;
99
100         for(a=0; a<path->len; a++) {
101                 ptr= &path->ptr[a];
102
103                 if(RNA_struct_is_a(ptr->type, type))
104                         return ptr;
105         }
106
107         return NULL;
108 }
109
110 /************************* Creating the Path ************************/
111
112 static int buttons_context_path_scene(ButsContextPath *path)
113 {
114         PointerRNA *ptr= &path->ptr[path->len-1];
115
116         /* this one just verifies */
117         return RNA_struct_is_a(ptr->type, &RNA_Scene);
118 }
119
120 /* note: this function can return 1 without adding a world to the path
121  * so the buttons stay visible, but be sure to check the ID type if a ID_WO */
122 static int buttons_context_path_world(ButsContextPath *path)
123 {
124         Scene *scene;
125         World *world;
126         PointerRNA *ptr= &path->ptr[path->len-1];
127
128         /* if we already have a (pinned) world, we're done */
129         if(RNA_struct_is_a(ptr->type, &RNA_World)) {
130                 return 1;
131         }
132         /* if we have a scene, use the scene's world */
133         else if(buttons_context_path_scene(path)) {
134                 scene= path->ptr[path->len-1].data;
135                 world= scene->world;
136                 
137                 if(world) {
138                         RNA_id_pointer_create(&scene->world->id, &path->ptr[path->len]);
139                         path->len++;
140                         return 1;
141                 }
142                 else {
143                         return 1;
144                 }
145         }
146
147         /* no path to a world possible */
148         return 0;
149 }
150
151
152 static int buttons_context_path_object(ButsContextPath *path)
153 {
154         Scene *scene;
155         Object *ob;
156         PointerRNA *ptr= &path->ptr[path->len-1];
157
158         /* if we already have a (pinned) object, we're done */
159         if(RNA_struct_is_a(ptr->type, &RNA_Object)) {
160                 return 1;
161         }
162         /* if we have a scene, use the scene's active object */
163         else if(buttons_context_path_scene(path)) {
164                 scene= path->ptr[path->len-1].data;
165                 ob= (scene->basact)? scene->basact->object: NULL;
166
167                 if(ob) {
168                         RNA_id_pointer_create(&ob->id, &path->ptr[path->len]);
169                         path->len++;
170
171                         return 1;
172                 }
173         }
174
175         /* no path to a object possible */
176         return 0;
177 }
178
179 static int buttons_context_path_data(ButsContextPath *path, int type)
180 {
181         Object *ob;
182         PointerRNA *ptr= &path->ptr[path->len-1];
183
184         /* if we already have a data, we're done */
185         if(RNA_struct_is_a(ptr->type, &RNA_Mesh) && (type == -1 || type == OB_MESH)) return 1;
186         else if(RNA_struct_is_a(ptr->type, &RNA_Curve) && (type == -1 || ELEM3(type, OB_CURVE, OB_SURF, OB_FONT))) return 1;
187         else if(RNA_struct_is_a(ptr->type, &RNA_Armature) && (type == -1 || type == OB_ARMATURE)) return 1;
188         else if(RNA_struct_is_a(ptr->type, &RNA_MetaBall) && (type == -1 || type == OB_MBALL)) return 1;
189         else if(RNA_struct_is_a(ptr->type, &RNA_Lattice) && (type == -1 || type == OB_LATTICE)) return 1;
190         else if(RNA_struct_is_a(ptr->type, &RNA_Camera) && (type == -1 || type == OB_CAMERA)) return 1;
191         else if(RNA_struct_is_a(ptr->type, &RNA_Lamp) && (type == -1 || type == OB_LAMP)) return 1;
192         /* try to get an object in the path, no pinning supported here */
193         else if(buttons_context_path_object(path)) {
194                 ob= path->ptr[path->len-1].data;
195
196                 if(ob && (type == -1 || type == ob->type)) {
197                         RNA_id_pointer_create(ob->data, &path->ptr[path->len]);
198                         path->len++;
199
200                         return 1;
201                 }
202         }
203
204         /* no path to data possible */
205         return 0;
206 }
207
208 static int buttons_context_path_modifier(ButsContextPath *path)
209 {
210         Object *ob;
211
212         if(buttons_context_path_object(path)) {
213                 ob= path->ptr[path->len-1].data;
214
215                 if(ob && ELEM5(ob->type, OB_MESH, OB_CURVE, OB_FONT, OB_SURF, OB_LATTICE))
216                         return 1;
217         }
218
219         return 0;
220 }
221
222 static int buttons_context_path_material(ButsContextPath *path)
223 {
224         Object *ob;
225         PointerRNA *ptr= &path->ptr[path->len-1];
226         Material *ma;
227
228         /* if we already have a (pinned) material, we're done */
229         if(RNA_struct_is_a(ptr->type, &RNA_Material)) {
230                 return 1;
231         }
232         /* if we have an object, use the object material slot */
233         else if(buttons_context_path_object(path)) {
234                 ob= path->ptr[path->len-1].data;
235
236                 if(ob && ob->type && (ob->type<OB_LAMP)) {
237                         ma= give_current_material(ob, ob->actcol);
238                         RNA_id_pointer_create(&ma->id, &path->ptr[path->len]);
239                         path->len++;
240                         return 1;
241                 }
242         }
243
244         /* no path to a material possible */
245         return 0;
246 }
247
248 static int buttons_context_path_bone(ButsContextPath *path)
249 {
250         bArmature *arm;
251         EditBone *edbo;
252
253         /* if we have an armature, get the active bone */
254         if(buttons_context_path_data(path, OB_ARMATURE)) {
255                 arm= path->ptr[path->len-1].data;
256
257                 if(arm->edbo) {
258                         if(arm->act_edbone) {
259                                 edbo= arm->act_edbone;
260                                 RNA_pointer_create(&arm->id, &RNA_EditBone, edbo, &path->ptr[path->len]);
261                                 path->len++;
262                                 return 1;
263                         }
264                 }
265                 else {
266                         if(arm->act_bone) {
267                                 RNA_pointer_create(&arm->id, &RNA_Bone, arm->act_bone, &path->ptr[path->len]);
268                                 path->len++;
269                                 return 1;
270                         }
271                 }
272         }
273
274         /* no path to a bone possible */
275         return 0;
276 }
277
278 static int buttons_context_path_pose_bone(ButsContextPath *path)
279 {
280         PointerRNA *ptr= &path->ptr[path->len-1];
281
282         /* if we already have a (pinned) PoseBone, we're done */
283         if(RNA_struct_is_a(ptr->type, &RNA_PoseBone)) {
284                 return 1;
285         }
286
287         /* if we have an armature, get the active bone */
288         if(buttons_context_path_object(path)) {
289                 Object *ob= path->ptr[path->len-1].data;
290                 bArmature *arm= ob->data; /* path->ptr[path->len-1].data - works too */
291
292                 if(ob->type != OB_ARMATURE || arm->edbo) {
293                         return 0;
294                 }
295                 else {
296                         if(arm->act_bone) {
297                                 bPoseChannel *pchan= get_pose_channel(ob->pose, arm->act_bone->name);
298                                 if(pchan) {
299                                         RNA_pointer_create(&ob->id, &RNA_PoseBone, pchan, &path->ptr[path->len]);
300                                         path->len++;
301                                         return 1;
302                                 }
303                         }
304                 }
305         }
306
307         /* no path to a bone possible */
308         return 0;
309 }
310
311
312 static int buttons_context_path_particle(ButsContextPath *path)
313 {
314         Object *ob;
315         ParticleSystem *psys;
316
317         /* if we have an object, get the active particle system */
318         if(buttons_context_path_object(path)) {
319                 ob= path->ptr[path->len-1].data;
320
321                 if(ob && ob->type == OB_MESH) {
322                         psys= psys_get_current(ob);
323
324                         RNA_pointer_create(&ob->id, &RNA_ParticleSystem, psys, &path->ptr[path->len]);
325                         path->len++;
326                         return 1;
327                 }
328         }
329
330         /* no path to a particle system possible */
331         return 0;
332 }
333
334 static int buttons_context_path_brush(const bContext *C, ButsContextPath *path)
335 {
336         Scene *scene;
337         Brush *br= NULL;
338         PointerRNA *ptr= &path->ptr[path->len-1];
339
340         /* if we already have a (pinned) brush, we're done */
341         if(RNA_struct_is_a(ptr->type, &RNA_Brush)) {
342                 return 1;
343         }
344         /* if we have a scene, use the toolsettings brushes */
345         else if(buttons_context_path_scene(path)) {
346                 scene= path->ptr[path->len-1].data;
347
348                 if(scene)
349                         br= paint_brush(paint_get_active(scene));
350
351                 if(br) {
352                         RNA_id_pointer_create(&br->id, &path->ptr[path->len]);
353                         path->len++;
354
355                         return 1;
356                 }
357         }
358
359         /* no path to a brush possible */
360         return 0;
361 }
362
363 static int buttons_context_path_texture(const bContext *C, ButsContextPath *path)
364 {
365         Material *ma;
366         Lamp *la;
367         Brush *br;
368         World *wo;
369         Tex *tex;
370         PointerRNA *ptr= &path->ptr[path->len-1];
371         int orig_len = path->len;
372
373         /* if we already have a (pinned) texture, we're done */
374         if(RNA_struct_is_a(ptr->type, &RNA_Texture)) {
375                 return 1;
376         }
377         /* try brush */
378         if((path->flag & SB_BRUSH_TEX) && buttons_context_path_brush(C, path)) {
379                 br= path->ptr[path->len-1].data;
380                 
381                 if(br) {
382                         tex= give_current_brush_texture(br);
383
384                         RNA_id_pointer_create(&tex->id, &path->ptr[path->len]);
385                         path->len++;
386                         return 1;
387                 }
388         }
389         /* try world */
390         if((path->flag & SB_WORLD_TEX) && buttons_context_path_world(path)) {
391                 wo= path->ptr[path->len-1].data;
392
393                 if(wo && GS(wo->id.name)==ID_WO) {
394                         tex= give_current_world_texture(wo);
395
396                         RNA_id_pointer_create(&tex->id, &path->ptr[path->len]);
397                         path->len++;
398                         return 1;
399                 }
400         }
401         /* try material */
402         if(buttons_context_path_material(path)) {
403                 ma= path->ptr[path->len-1].data;
404
405                 if(ma) {
406                         tex= give_current_material_texture(ma);
407
408                         RNA_id_pointer_create(&tex->id, &path->ptr[path->len]);
409                         path->len++;
410                         return 1;
411                 }
412         }
413         /* try lamp */
414         if(buttons_context_path_data(path, OB_LAMP)) {
415                 la= path->ptr[path->len-1].data;
416
417                 if(la) {
418                         tex= give_current_lamp_texture(la);
419
420                         RNA_id_pointer_create(&tex->id, &path->ptr[path->len]);
421                         path->len++;
422                         return 1;
423                 }
424         }
425         /* try brushes again in case of no material, lamp, etc */
426         path->len = orig_len;
427         if(buttons_context_path_brush(C, path)) {
428                 br= path->ptr[path->len-1].data;
429                 
430                 if(br) {
431                         tex= give_current_brush_texture(br);
432                         
433                         RNA_id_pointer_create(&tex->id, &path->ptr[path->len]);
434                         path->len++;
435                         return 1;
436                 }
437         }
438
439         /* no path to a texture possible */
440         return 0;
441 }
442
443
444 static int buttons_context_path(const bContext *C, ButsContextPath *path, int mainb, int flag)
445 {
446         SpaceButs *sbuts= CTX_wm_space_buts(C);
447         ID *id;
448         int found;
449
450         memset(path, 0, sizeof(*path));
451         path->flag= flag;
452
453         /* if some ID datablock is pinned, set the root pointer */
454         if(sbuts->pinid) {
455                 id= sbuts->pinid;
456
457                 RNA_id_pointer_create(id, &path->ptr[0]);
458                 path->len++;
459         }
460
461         /* no pinned root, use scene as root */
462         if(path->len == 0) {
463                 id= (ID*)CTX_data_scene(C);
464                 RNA_id_pointer_create(id, &path->ptr[0]);
465                 path->len++;
466         }
467
468         /* now for each buttons context type, we try to construct a path,
469          * tracing back recursively */
470         switch(mainb) {
471                 case BCONTEXT_SCENE:
472                 case BCONTEXT_RENDER:
473                         found= buttons_context_path_scene(path);
474                         break;
475                 case BCONTEXT_WORLD:
476                         found= buttons_context_path_world(path);
477                         break;
478                 case BCONTEXT_OBJECT:
479                 case BCONTEXT_PHYSICS:
480                 case BCONTEXT_CONSTRAINT:
481                         found= buttons_context_path_object(path);
482                         break;
483                 case BCONTEXT_MODIFIER:
484                         found= buttons_context_path_modifier(path);
485                         break;
486                 case BCONTEXT_DATA:
487                         found= buttons_context_path_data(path, -1);
488                         break;
489                 case BCONTEXT_PARTICLE:
490                         found= buttons_context_path_particle(path);
491                         break;
492                 case BCONTEXT_MATERIAL:
493                         found= buttons_context_path_material(path);
494                         break;
495                 case BCONTEXT_TEXTURE:
496                         found= buttons_context_path_texture(C, path);
497                         break;
498                 case BCONTEXT_BONE:
499                         found= buttons_context_path_bone(path);
500                         if(!found)
501                                 found= buttons_context_path_data(path, OB_ARMATURE);
502                         break;
503                 case BCONTEXT_BONE_CONSTRAINT:
504                         found= buttons_context_path_pose_bone(path);
505                         break;
506                 default:
507                         found= 0;
508                         break;
509         }
510
511         return found;
512 }
513
514 static int buttons_shading_context(const bContext *C, int mainb)
515 {
516         Object *ob= CTX_data_active_object(C);
517
518         if(ELEM3(mainb, BCONTEXT_MATERIAL, BCONTEXT_WORLD, BCONTEXT_TEXTURE))
519                 return 1;
520         if(mainb == BCONTEXT_DATA && ob && ELEM(ob->type, OB_LAMP, OB_CAMERA))
521                 return 1;
522         
523         return 0;
524 }
525
526 static int buttons_shading_new_context(const bContext *C, int flag, int mainb)
527 {
528         Object *ob= CTX_data_active_object(C);
529
530         if(flag & (1 << BCONTEXT_MATERIAL))
531                 return BCONTEXT_MATERIAL;
532         else if(ob && ELEM(ob->type, OB_LAMP, OB_CAMERA) && (flag & (1 << BCONTEXT_DATA)))
533                 return BCONTEXT_DATA;
534         else if(flag & (1 << BCONTEXT_WORLD))
535                 return BCONTEXT_WORLD;
536         
537         return BCONTEXT_RENDER;
538 }
539
540 void buttons_context_compute(const bContext *C, SpaceButs *sbuts)
541 {
542         ButsContextPath *path;
543         PointerRNA *ptr;
544         int a, pflag, flag= 0;
545
546         if(!sbuts->path)
547                 sbuts->path= MEM_callocN(sizeof(ButsContextPath), "ButsContextPath");
548         
549         path= sbuts->path;
550         pflag= (sbuts->flag & (SB_WORLD_TEX|SB_BRUSH_TEX));
551         
552         /* for each context, see if we can compute a valid path to it, if
553          * this is the case, we know we have to display the button */
554         for(a=0; a<BCONTEXT_TOT; a++) {
555                 if(buttons_context_path(C, path, a, pflag)) {
556                         flag |= (1<<a);
557
558                         /* setting icon for data context */
559                         if(a == BCONTEXT_DATA) {
560                                 ptr= &path->ptr[path->len-1];
561
562                                 if(ptr->type)
563                                         sbuts->dataicon= RNA_struct_ui_icon(ptr->type);
564                                 else
565                                         sbuts->dataicon= ICON_EMPTY_DATA;
566                         }
567                 }
568         }
569
570         /* always try to use the tab that was explicitly
571          * set to the user, so that once that context comes
572          * back, the tab is activated again */
573         sbuts->mainb= sbuts->mainbuser;
574
575         /* in case something becomes invalid, change */
576         if((flag & (1 << sbuts->mainb)) == 0) {
577                 if(sbuts->flag & SB_SHADING_CONTEXT) {
578                         /* try to keep showing shading related buttons */
579                         sbuts->mainb= buttons_shading_new_context(C, flag, sbuts->mainb);
580                 }
581                 else if(flag & BCONTEXT_OBJECT) {
582                         sbuts->mainb= BCONTEXT_OBJECT;
583                 }
584                 else {
585                         for(a=0; a<BCONTEXT_TOT; a++) {
586                                 if(flag & (1 << a)) {
587                                         sbuts->mainb= a;
588                                         break;
589                                 }
590                         }
591                 }
592         }
593
594         buttons_context_path(C, path, sbuts->mainb, pflag);
595
596         if(!(flag & (1 << sbuts->mainb))) {
597                 if(flag & (1 << BCONTEXT_OBJECT))
598                         sbuts->mainb= BCONTEXT_OBJECT;
599                 else
600                         sbuts->mainb= BCONTEXT_SCENE;
601         }
602
603         if(buttons_shading_context(C, sbuts->mainb))
604                 sbuts->flag |= SB_SHADING_CONTEXT;
605         else
606                 sbuts->flag &= ~SB_SHADING_CONTEXT;
607
608         sbuts->pathflag= flag;
609 }
610
611 /************************* Context Callback ************************/
612
613 int buttons_context(const bContext *C, const char *member, bContextDataResult *result)
614 {
615         SpaceButs *sbuts= CTX_wm_space_buts(C);
616         ButsContextPath *path= sbuts?sbuts->path:NULL;
617
618         if(!path)
619                 return 0;
620
621         /* here we handle context, getting data from precomputed path */
622         if(CTX_data_dir(member)) {
623                 static const char *dir[] = {
624                         "world", "object", "mesh", "armature", "lattice", "curve",
625                         "meta_ball", "lamp", "camera", "material", "material_slot",
626                         "texture", "texture_slot", "bone", "edit_bone", "pose_bone", "particle_system", "particle_system_editable",
627                         "cloth", "soft_body", "fluid", "smoke", "collision", "brush", NULL};
628
629                 CTX_data_dir_set(result, dir);
630                 return 1;
631         }
632         else if(CTX_data_equals(member, "world")) {
633                 set_pointer_type(path, result, &RNA_World);
634                 return 1;
635         }
636         else if(CTX_data_equals(member, "object")) {
637                 set_pointer_type(path, result, &RNA_Object);
638                 return 1;
639         }
640         else if(CTX_data_equals(member, "mesh")) {
641                 set_pointer_type(path, result, &RNA_Mesh);
642                 return 1;
643         }
644         else if(CTX_data_equals(member, "armature")) {
645                 set_pointer_type(path, result, &RNA_Armature);
646                 return 1;
647         }
648         else if(CTX_data_equals(member, "lattice")) {
649                 set_pointer_type(path, result, &RNA_Lattice);
650                 return 1;
651         }
652         else if(CTX_data_equals(member, "curve")) {
653                 set_pointer_type(path, result, &RNA_Curve);
654                 return 1;
655         }
656         else if(CTX_data_equals(member, "meta_ball")) {
657                 set_pointer_type(path, result, &RNA_MetaBall);
658                 return 1;
659         }
660         else if(CTX_data_equals(member, "lamp")) {
661                 set_pointer_type(path, result, &RNA_Lamp);
662                 return 1;
663         }
664         else if(CTX_data_equals(member, "camera")) {
665                 set_pointer_type(path, result, &RNA_Camera);
666                 return 1;
667         }
668         else if(CTX_data_equals(member, "material")) {
669                 set_pointer_type(path, result, &RNA_Material);
670                 return 1;
671         }
672         else if(CTX_data_equals(member, "texture")) {
673                 set_pointer_type(path, result, &RNA_Texture);
674                 return 1;
675         }
676         else if(CTX_data_equals(member, "material_slot")) {
677                 PointerRNA *ptr= get_pointer_type(path, &RNA_Object);
678
679                 if(ptr) {
680                         Object *ob= ptr->data;
681
682                         if(ob && ob->type && (ob->type<OB_LAMP) && ob->totcol)
683                                 CTX_data_pointer_set(result, &ob->id, &RNA_MaterialSlot, ob->mat+ob->actcol-1);
684                 }
685
686                 return 1;
687         }
688         else if(CTX_data_equals(member, "texture_node")) {
689                 PointerRNA *ptr;
690
691                 if((ptr=get_pointer_type(path, &RNA_Material))) {
692                         Material *ma= ptr->data;
693
694                         if(ma) {
695                                 bNode *node= give_current_material_texture_node(ma);
696                                 CTX_data_pointer_set(result, &ma->id, &RNA_Node, node);
697                         }
698                 }
699
700                 return 1;
701         }
702         else if(CTX_data_equals(member, "texture_slot")) {
703                 PointerRNA *ptr;
704
705                 if((ptr=get_pointer_type(path, &RNA_Material))) {
706                         Material *ma= ptr->data;
707
708                         /* if we have a node material, get slot from material in material node */
709                         if(ma && ma->use_nodes && ma->nodetree)
710                                 ma= give_node_material(ma);
711
712                         if(ma)
713                                 CTX_data_pointer_set(result, &ma->id, &RNA_MaterialTextureSlot, ma->mtex[(int)ma->texact]);
714                 }
715                 else if((ptr=get_pointer_type(path, &RNA_Lamp))) {
716                         Lamp *la= ptr->data;
717
718                         if(la)
719                                 CTX_data_pointer_set(result, &la->id, &RNA_LampTextureSlot, la->mtex[(int)la->texact]);
720                 }
721                 else if((ptr=get_pointer_type(path, &RNA_World))) {
722                         World *wo= ptr->data;
723
724                         if(wo)
725                                 CTX_data_pointer_set(result, &wo->id, &RNA_WorldTextureSlot, wo->mtex[(int)wo->texact]);
726                 }
727                 else if((ptr=get_pointer_type(path, &RNA_Brush))) { /* how to get this into context? */
728                         Brush *br= ptr->data;
729
730                         if(br)
731                                 CTX_data_pointer_set(result, &br->id, &RNA_BrushTextureSlot, &br->mtex);
732                 }
733
734                 return 1;
735         }
736         else if(CTX_data_equals(member, "bone")) {
737                 set_pointer_type(path, result, &RNA_Bone);
738                 return 1;
739         }
740         else if(CTX_data_equals(member, "edit_bone")) {
741                 set_pointer_type(path, result, &RNA_EditBone);
742                 return 1;
743         }
744         else if(CTX_data_equals(member, "pose_bone")) {
745                 set_pointer_type(path, result, &RNA_PoseBone);
746                 return 1;
747         }
748         else if(CTX_data_equals(member, "particle_system")) {
749                 set_pointer_type(path, result, &RNA_ParticleSystem);
750                 return 1;
751         }
752         else if(CTX_data_equals(member, "particle_system_editable")) {
753                 if(PE_poll((bContext*)C))
754                         set_pointer_type(path, result, &RNA_ParticleSystem);
755                 else
756                         CTX_data_pointer_set(result, NULL, &RNA_ParticleSystem, NULL);
757                 return 1;
758         }       
759         else if(CTX_data_equals(member, "cloth")) {
760                 PointerRNA *ptr= get_pointer_type(path, &RNA_Object);
761
762                 if(ptr && ptr->data) {
763                         Object *ob= ptr->data;
764                         ModifierData *md= modifiers_findByType(ob, eModifierType_Cloth);
765                         CTX_data_pointer_set(result, &ob->id, &RNA_ClothModifier, md);
766                         return 1;
767                 }
768         }
769         else if(CTX_data_equals(member, "soft_body")) {
770                 PointerRNA *ptr= get_pointer_type(path, &RNA_Object);
771
772                 if(ptr && ptr->data) {
773                         Object *ob= ptr->data;
774                         ModifierData *md= modifiers_findByType(ob, eModifierType_Softbody);
775                         CTX_data_pointer_set(result, &ob->id, &RNA_SoftBodyModifier, md);
776                         return 1;
777                 }
778         }
779         else if(CTX_data_equals(member, "fluid")) {
780                 PointerRNA *ptr= get_pointer_type(path, &RNA_Object);
781
782                 if(ptr && ptr->data) {
783                         Object *ob= ptr->data;
784                         ModifierData *md= modifiers_findByType(ob, eModifierType_Fluidsim);
785                         CTX_data_pointer_set(result, &ob->id, &RNA_FluidSimulationModifier, md);
786                         return 1;
787                 }
788         }
789         
790         else if(CTX_data_equals(member, "smoke")) {
791                 PointerRNA *ptr= get_pointer_type(path, &RNA_Object);
792
793                 if(ptr && ptr->data) {
794                         Object *ob= ptr->data;
795                         ModifierData *md= modifiers_findByType(ob, eModifierType_Smoke);
796                         CTX_data_pointer_set(result, &ob->id, &RNA_SmokeModifier, md);
797                         return 1;
798                 }
799         }
800         else if(CTX_data_equals(member, "collision")) {
801                 PointerRNA *ptr= get_pointer_type(path, &RNA_Object);
802
803                 if(ptr && ptr->data) {
804                         Object *ob= ptr->data;
805                         ModifierData *md= modifiers_findByType(ob, eModifierType_Collision);
806                         CTX_data_pointer_set(result, &ob->id, &RNA_CollisionModifier, md);
807                         return 1;
808                 }
809         }
810         else if(CTX_data_equals(member, "brush")) {
811                 set_pointer_type(path, result, &RNA_Brush);
812                 return 1;
813         }
814         else {
815                 return 0; /* not found */
816         }
817
818         return -1; /* found but not available */
819 }
820
821 /************************* Drawing the Path ************************/
822
823 static void pin_cb(bContext *C, void *arg1, void *arg2)
824 {
825         SpaceButs *sbuts= CTX_wm_space_buts(C);
826         ButsContextPath *path= sbuts->path;
827         PointerRNA *ptr;
828         int a;
829
830         if(sbuts->flag & SB_PIN_CONTEXT) {
831                 if(path->len) {
832                         for(a=path->len-1; a>=0; a--) {
833                                 ptr= &path->ptr[a];
834
835                                 if(ptr->id.data) {
836                                         sbuts->pinid= ptr->id.data;
837                                         break;
838                                 }
839                         }
840                 }
841         }
842         else
843                 sbuts->pinid= NULL;
844         
845         ED_area_tag_redraw(CTX_wm_area(C));
846 }
847
848 void buttons_context_draw(const bContext *C, uiLayout *layout)
849 {
850         SpaceButs *sbuts= CTX_wm_space_buts(C);
851         ButsContextPath *path= sbuts->path;
852         uiLayout *row;
853         uiBlock *block;
854         uiBut *but;
855         PointerRNA *ptr;
856         char namebuf[128], *name;
857         int a, icon;
858
859         if(!path)
860                 return;
861
862         row= uiLayoutRow(layout, 1);
863         uiLayoutSetAlignment(row, UI_LAYOUT_ALIGN_LEFT);
864
865         block= uiLayoutGetBlock(row);
866         uiBlockSetEmboss(block, UI_EMBOSSN);
867         but= uiDefIconButBitC(block, ICONTOG, SB_PIN_CONTEXT, 0, ICON_UNPINNED, 0, 0, UI_UNIT_X, UI_UNIT_Y, &sbuts->flag, 0, 0, 0, 0, "Follow context or keep fixed datablock displayed");
868         uiButSetFunc(but, pin_cb, NULL, NULL);
869
870         for(a=0; a<path->len; a++) {
871                 ptr= &path->ptr[a];
872
873                 if(a != 0)
874                         uiItemL(row, "", VICO_SMALL_TRI_RIGHT_VEC);
875
876                 if(ptr->data) {
877                         icon= RNA_struct_ui_icon(ptr->type);
878                         name= RNA_struct_name_get_alloc(ptr, namebuf, sizeof(namebuf));
879
880                         if(name) {
881                                 if(!ELEM(sbuts->mainb, BCONTEXT_RENDER, BCONTEXT_SCENE) && ptr->type == &RNA_Scene)
882                                         uiItemLDrag(row, ptr, "", icon); /* save some space */
883                                 else
884                                         uiItemLDrag(row, ptr, name, icon);
885                                                                  
886                                 if(name != namebuf)
887                                         MEM_freeN(name);
888                         }
889                         else
890                                 uiItemL(row, "", icon);
891                 }
892         }
893 }
894
895 static void buttons_panel_context(const bContext *C, Panel *pa)
896 {
897         buttons_context_draw(C, pa->layout);
898 }
899
900 void buttons_context_register(ARegionType *art)
901 {
902         PanelType *pt;
903
904         pt= MEM_callocN(sizeof(PanelType), "spacetype buttons panel context");
905         strcpy(pt->idname, "BUTTONS_PT_context");
906         strcpy(pt->label, "Context");
907         pt->draw= buttons_panel_context;
908         pt->flag= PNL_NO_HEADER;
909         BLI_addtail(&art->paneltypes, pt);
910 }