Merge branch 'master' into temp_remove_particles
[blender.git] / source / blender / editors / space_buttons / buttons_context.c
1 /*
2  * ***** BEGIN GPL LICENSE BLOCK *****
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version. 
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software Foundation,
16  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17  *
18  * The Original Code is Copyright (C) 2009 Blender Foundation.
19  * All rights reserved.
20  *
21  * Contributor(s): Blender Foundation
22  *
23  * ***** END GPL LICENSE BLOCK *****
24  */
25
26 /** \file blender/editors/space_buttons/buttons_context.c
27  *  \ingroup spbuttons
28  */
29
30
31 #include <stdlib.h>
32 #include <string.h>
33
34 #include "MEM_guardedalloc.h"
35
36 #include "BLI_listbase.h"
37 #include "BLI_utildefines.h"
38
39 #include "BLT_translation.h"
40
41 #include "DNA_armature_types.h"
42 #include "DNA_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 #include "DNA_object_types.h"
50
51 #include "BKE_context.h"
52 #include "BKE_action.h"
53 #include "BKE_material.h"
54 #include "BKE_modifier.h"
55 #include "BKE_paint.h"
56 #include "BKE_screen.h"
57 #include "BKE_texture.h"
58 #include "BKE_linestyle.h"
59
60 #include "RNA_access.h"
61
62 #include "ED_buttons.h"
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 static int set_pointer_type(ButsContextPath *path, bContextDataResult *result, StructRNA *type)
73 {
74         PointerRNA *ptr;
75         int a;
76
77         for (a = 0; a < path->len; a++) {
78                 ptr = &path->ptr[a];
79
80                 if (RNA_struct_is_a(ptr->type, type)) {
81                         CTX_data_pointer_set(result, ptr->id.data, ptr->type, ptr->data);
82                         return 1;
83                 }
84         }
85
86         return 0;
87 }
88
89 static PointerRNA *get_pointer_type(ButsContextPath *path, StructRNA *type)
90 {
91         PointerRNA *ptr;
92         int a;
93
94         for (a = 0; a < path->len; a++) {
95                 ptr = &path->ptr[a];
96
97                 if (RNA_struct_is_a(ptr->type, type))
98                         return ptr;
99         }
100
101         return NULL;
102 }
103
104 /************************* Creating the Path ************************/
105
106 static int buttons_context_path_scene(ButsContextPath *path)
107 {
108         PointerRNA *ptr = &path->ptr[path->len - 1];
109
110         /* this one just verifies */
111         return RNA_struct_is_a(ptr->type, &RNA_Scene);
112 }
113
114 /* note: this function can return 1 without adding a world to the path
115  * so the buttons stay visible, but be sure to check the ID type if a ID_WO */
116 static int buttons_context_path_world(ButsContextPath *path)
117 {
118         Scene *scene;
119         World *world;
120         PointerRNA *ptr = &path->ptr[path->len - 1];
121
122         /* if we already have a (pinned) world, we're done */
123         if (RNA_struct_is_a(ptr->type, &RNA_World)) {
124                 return 1;
125         }
126         /* if we have a scene, use the scene's world */
127         else if (buttons_context_path_scene(path)) {
128                 scene = path->ptr[path->len - 1].data;
129                 world = scene->world;
130                 
131                 if (world) {
132                         RNA_id_pointer_create(&scene->world->id, &path->ptr[path->len]);
133                         path->len++;
134                         return 1;
135                 }
136                 else {
137                         return 1;
138                 }
139         }
140
141         /* no path to a world possible */
142         return 0;
143 }
144
145 static int buttons_context_path_linestyle(ButsContextPath *path)
146 {
147         Scene *scene;
148         FreestyleLineStyle *linestyle;
149         PointerRNA *ptr = &path->ptr[path->len - 1];
150
151         /* if we already have a (pinned) linestyle, we're done */
152         if (RNA_struct_is_a(ptr->type, &RNA_FreestyleLineStyle)) {
153                 return 1;
154         }
155         /* if we have a scene, use the lineset's linestyle */
156         else if (buttons_context_path_scene(path)) {
157                 scene = path->ptr[path->len - 1].data;
158                 linestyle = BKE_linestyle_active_from_scene(scene);
159                 if (linestyle) {
160                         RNA_id_pointer_create(&linestyle->id, &path->ptr[path->len]);
161                         path->len++;
162                         return 1;
163                 }
164         }
165
166         /* no path to a linestyle possible */
167         return 0;
168 }
169
170 static int buttons_context_path_object(ButsContextPath *path)
171 {
172         Scene *scene;
173         Object *ob;
174         PointerRNA *ptr = &path->ptr[path->len - 1];
175
176         /* if we already have a (pinned) object, we're done */
177         if (RNA_struct_is_a(ptr->type, &RNA_Object)) {
178                 return 1;
179         }
180         /* if we have a scene, use the scene's active object */
181         else if (buttons_context_path_scene(path)) {
182                 scene = path->ptr[path->len - 1].data;
183                 ob = (scene->basact) ? scene->basact->object : NULL;
184
185                 if (ob) {
186                         RNA_id_pointer_create(&ob->id, &path->ptr[path->len]);
187                         path->len++;
188
189                         return 1;
190                 }
191         }
192
193         /* no path to a object possible */
194         return 0;
195 }
196
197 static int buttons_context_path_data(ButsContextPath *path, int type)
198 {
199         Object *ob;
200         PointerRNA *ptr = &path->ptr[path->len - 1];
201
202         /* if we already have a data, we're done */
203         if (RNA_struct_is_a(ptr->type, &RNA_Mesh) && (type == -1 || type == OB_MESH)) return 1;
204         else if (RNA_struct_is_a(ptr->type, &RNA_Curve) && (type == -1 || ELEM(type, OB_CURVE, OB_SURF, OB_FONT))) return 1;
205         else if (RNA_struct_is_a(ptr->type, &RNA_Armature) && (type == -1 || type == OB_ARMATURE)) return 1;
206         else if (RNA_struct_is_a(ptr->type, &RNA_MetaBall) && (type == -1 || type == OB_MBALL)) return 1;
207         else if (RNA_struct_is_a(ptr->type, &RNA_Lattice) && (type == -1 || type == OB_LATTICE)) return 1;
208         else if (RNA_struct_is_a(ptr->type, &RNA_Camera) && (type == -1 || type == OB_CAMERA)) return 1;
209         else if (RNA_struct_is_a(ptr->type, &RNA_Lamp) && (type == -1 || type == OB_LAMP)) return 1;
210         else if (RNA_struct_is_a(ptr->type, &RNA_Speaker) && (type == -1 || type == OB_SPEAKER)) return 1;
211         /* try to get an object in the path, no pinning supported here */
212         else if (buttons_context_path_object(path)) {
213                 ob = path->ptr[path->len - 1].data;
214
215                 if (ob && (type == -1 || type == ob->type)) {
216                         RNA_id_pointer_create(ob->data, &path->ptr[path->len]);
217                         path->len++;
218
219                         return 1;
220                 }
221         }
222
223         /* no path to data possible */
224         return 0;
225 }
226
227 static int buttons_context_path_modifier(ButsContextPath *path)
228 {
229         Object *ob;
230
231         if (buttons_context_path_object(path)) {
232                 ob = path->ptr[path->len - 1].data;
233
234                 if (ob && ELEM(ob->type, OB_MESH, OB_CURVE, OB_FONT, OB_SURF, OB_LATTICE))
235                         return 1;
236         }
237
238         return 0;
239 }
240
241 static int buttons_context_path_material(ButsContextPath *path, bool for_texture, bool new_shading)
242 {
243         Object *ob;
244         PointerRNA *ptr = &path->ptr[path->len - 1];
245         Material *ma;
246
247         /* if we already have a (pinned) material, we're done */
248         if (RNA_struct_is_a(ptr->type, &RNA_Material)) {
249                 return 1;
250         }
251         /* if we have an object, use the object material slot */
252         else if (buttons_context_path_object(path)) {
253                 ob = path->ptr[path->len - 1].data;
254
255                 if (ob && OB_TYPE_SUPPORT_MATERIAL(ob->type)) {
256                         ma = give_current_material(ob, ob->actcol);
257                         RNA_id_pointer_create(&ma->id, &path->ptr[path->len]);
258                         path->len++;
259
260                         if (for_texture && give_current_material_texture_node(ma))
261                                 return 1;
262
263                         if (!new_shading) {
264                                 /* Only try to get mat from node in case of old shading system (see T40331). */
265                                 ma = give_node_material(ma);
266                                 if (ma) {
267                                         RNA_id_pointer_create(&ma->id, &path->ptr[path->len]);
268                                         path->len++;
269                                 }
270                         }
271                         return 1;
272                 }
273         }
274
275         /* no path to a material possible */
276         return 0;
277 }
278
279 static int buttons_context_path_bone(ButsContextPath *path)
280 {
281         bArmature *arm;
282         EditBone *edbo;
283
284         /* if we have an armature, get the active bone */
285         if (buttons_context_path_data(path, OB_ARMATURE)) {
286                 arm = path->ptr[path->len - 1].data;
287
288                 if (arm->edbo) {
289                         if (arm->act_edbone) {
290                                 edbo = arm->act_edbone;
291                                 RNA_pointer_create(&arm->id, &RNA_EditBone, edbo, &path->ptr[path->len]);
292                                 path->len++;
293                                 return 1;
294                         }
295                 }
296                 else {
297                         if (arm->act_bone) {
298                                 RNA_pointer_create(&arm->id, &RNA_Bone, arm->act_bone, &path->ptr[path->len]);
299                                 path->len++;
300                                 return 1;
301                         }
302                 }
303         }
304
305         /* no path to a bone possible */
306         return 0;
307 }
308
309 static int buttons_context_path_pose_bone(ButsContextPath *path)
310 {
311         PointerRNA *ptr = &path->ptr[path->len - 1];
312
313         /* if we already have a (pinned) PoseBone, we're done */
314         if (RNA_struct_is_a(ptr->type, &RNA_PoseBone)) {
315                 return 1;
316         }
317
318         /* if we have an armature, get the active bone */
319         if (buttons_context_path_object(path)) {
320                 Object *ob = path->ptr[path->len - 1].data;
321                 bArmature *arm = ob->data; /* path->ptr[path->len-1].data - works too */
322
323                 if (ob->type != OB_ARMATURE || arm->edbo) {
324                         return 0;
325                 }
326                 else {
327                         if (arm->act_bone) {
328                                 bPoseChannel *pchan = BKE_pose_channel_find_name(ob->pose, arm->act_bone->name);
329                                 if (pchan) {
330                                         RNA_pointer_create(&ob->id, &RNA_PoseBone, pchan, &path->ptr[path->len]);
331                                         path->len++;
332                                         return 1;
333                                 }
334                         }
335                 }
336         }
337
338         /* no path to a bone possible */
339         return 0;
340 }
341
342 static int buttons_context_path_brush(ButsContextPath *path)
343 {
344         Scene *scene;
345         Brush *br = NULL;
346         PointerRNA *ptr = &path->ptr[path->len - 1];
347
348         /* if we already have a (pinned) brush, we're done */
349         if (RNA_struct_is_a(ptr->type, &RNA_Brush)) {
350                 return 1;
351         }
352         /* if we have a scene, use the toolsettings brushes */
353         else if (buttons_context_path_scene(path)) {
354                 scene = path->ptr[path->len - 1].data;
355
356                 if (scene)
357                         br = BKE_paint_brush(BKE_paint_get_active(scene));
358
359                 if (br) {
360                         RNA_id_pointer_create((ID *)br, &path->ptr[path->len]);
361                         path->len++;
362
363                         return 1;
364                 }
365         }
366
367         /* no path to a brush possible */
368         return 0;
369 }
370
371 static int buttons_context_path_texture(ButsContextPath *path, ButsContextTexture *ct)
372 {
373         if (ct) {
374                 /* new shading system */
375                 PointerRNA *ptr = &path->ptr[path->len - 1];
376                 ID *id;
377
378                 /* if we already have a (pinned) texture, we're done */
379                 if (RNA_struct_is_a(ptr->type, &RNA_Texture))
380                         return 1;
381
382                 if (!ct->user)
383                         return 0;
384                 
385                 id = ct->user->id;
386
387                 if (id) {
388                         if (GS(id->name) == ID_BR)
389                                 buttons_context_path_brush(path);
390                         else if (GS(id->name) == ID_MA)
391                                 buttons_context_path_material(path, false, true);
392                         else if (GS(id->name) == ID_WO)
393                                 buttons_context_path_world(path);
394                         else if (GS(id->name) == ID_LA)
395                                 buttons_context_path_data(path, OB_LAMP);
396                         else if (GS(id->name) == ID_OB)
397                                 buttons_context_path_object(path);
398                         else if (GS(id->name) == ID_LS)
399                                 buttons_context_path_linestyle(path);
400                 }
401
402                 if (ct->texture) {
403                         RNA_id_pointer_create(&ct->texture->id, &path->ptr[path->len]);
404                         path->len++;
405                 }
406
407                 return 1;
408         }
409         else {
410                 /* old shading system */
411                 Material *ma;
412                 Lamp *la;
413                 World *wo;
414                 FreestyleLineStyle *ls;
415                 Tex *tex;
416                 PointerRNA *ptr = &path->ptr[path->len - 1];
417
418                 /* if we already have a (pinned) texture, we're done */
419                 if (RNA_struct_is_a(ptr->type, &RNA_Texture)) {
420                         return 1;
421                 }
422                 /* try world */
423                 else if ((path->tex_ctx == SB_TEXC_WORLD) && buttons_context_path_world(path)) {
424                         wo = path->ptr[path->len - 1].data;
425
426                         if (wo && GS(wo->id.name) == ID_WO) {
427                                 tex = give_current_world_texture(wo);
428
429                                 RNA_id_pointer_create(&tex->id, &path->ptr[path->len]);
430                                 path->len++;
431                                 return 1;
432                         }
433                 }
434                 /* try material */
435                 else if ((path->tex_ctx == SB_TEXC_MATERIAL) && buttons_context_path_material(path, true, false)) {
436                         ma = path->ptr[path->len - 1].data;
437
438                         if (ma) {
439                                 tex = give_current_material_texture(ma);
440
441                                 RNA_id_pointer_create(&tex->id, &path->ptr[path->len]);
442                                 path->len++;
443                                 return 1;
444                         }
445                 }
446                 /* try lamp */
447                 else if ((path->tex_ctx == SB_TEXC_LAMP) && buttons_context_path_data(path, OB_LAMP)) {
448                         la = path->ptr[path->len - 1].data;
449
450                         if (la) {
451                                 tex = give_current_lamp_texture(la);
452
453                                 RNA_id_pointer_create(&tex->id, &path->ptr[path->len]);
454                                 path->len++;
455                                 return 1;
456                         }
457                 }
458                 /* try linestyle */
459                 else if ((path->tex_ctx == SB_TEXC_LINESTYLE) && buttons_context_path_linestyle(path)) {
460                         ls = path->ptr[path->len - 1].data;
461
462                         if (ls) {
463                                 tex = give_current_linestyle_texture(ls);
464
465                                 RNA_id_pointer_create(&tex->id, &path->ptr[path->len]);
466                                 path->len++;
467                                 return 1;
468                         }
469                 }
470         }
471
472         /* no path to a texture possible */
473         return 0;
474 }
475
476 #ifdef WITH_FREESTYLE
477 static bool buttons_context_linestyle_pinnable(const bContext *C)
478 {
479         Scene *scene = CTX_data_scene(C);
480         SceneRenderLayer *actsrl;
481         FreestyleConfig *config;
482         SpaceButs *sbuts;
483
484         /* if Freestyle is disabled in the scene */
485         if ((scene->r.mode & R_EDGE_FRS) == 0) {
486                 return false;
487         }
488         /* if Freestyle is not in the Parameter Editor mode */
489         actsrl = BLI_findlink(&scene->r.layers, scene->r.actlay);
490         config = &actsrl->freestyleConfig;
491         if (config->mode != FREESTYLE_CONTROL_EDITOR_MODE) {
492                 return false;
493         }
494         /* if the scene has already been pinned */
495         sbuts = CTX_wm_space_buts(C);
496         if (sbuts->pinid && sbuts->pinid == &scene->id) {
497                 return false;
498         }
499         return true;
500 }
501 #endif
502
503 static int buttons_context_path(const bContext *C, ButsContextPath *path, int mainb, int flag)
504 {
505         SpaceButs *sbuts = CTX_wm_space_buts(C);
506         ID *id;
507         int found;
508
509         memset(path, 0, sizeof(*path));
510         path->flag = flag;
511         path->tex_ctx = sbuts->texture_context;
512
513         /* if some ID datablock is pinned, set the root pointer */
514         if (sbuts->pinid) {
515                 id = sbuts->pinid;
516
517                 RNA_id_pointer_create(id, &path->ptr[0]);
518                 path->len++;
519         }
520
521         /* no pinned root, use scene as root */
522         if (path->len == 0) {
523                 id = (ID *)CTX_data_scene(C);
524                 RNA_id_pointer_create(id, &path->ptr[0]);
525                 path->len++;
526         }
527
528         /* now for each buttons context type, we try to construct a path,
529          * tracing back recursively */
530         switch (mainb) {
531                 case BCONTEXT_SCENE:
532                 case BCONTEXT_RENDER:
533                         found = buttons_context_path_scene(path);
534                         break;
535                 case BCONTEXT_RENDER_LAYER:
536 #ifdef WITH_FREESTYLE
537                         if (buttons_context_linestyle_pinnable(C)) {
538                                 found = buttons_context_path_linestyle(path);
539                                 if (found) {
540                                         break;
541                                 }
542                         }
543 #endif
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_MATERIAL:
561                         found = buttons_context_path_material(path, false, (sbuts->texuser != NULL));
562                         break;
563                 case BCONTEXT_TEXTURE:
564                         found = buttons_context_path_texture(path, sbuts->texuser);
565                         break;
566                 case BCONTEXT_BONE:
567                         found = buttons_context_path_bone(path);
568                         if (!found)
569                                 found = buttons_context_path_data(path, OB_ARMATURE);
570                         break;
571                 case BCONTEXT_BONE_CONSTRAINT:
572                         found = buttons_context_path_pose_bone(path);
573                         break;
574                 default:
575                         found = 0;
576                         break;
577         }
578
579         return found;
580 }
581
582 static int buttons_shading_context(const bContext *C, int mainb)
583 {
584         Object *ob = CTX_data_active_object(C);
585
586         if (ELEM(mainb, BCONTEXT_MATERIAL, BCONTEXT_WORLD, BCONTEXT_TEXTURE))
587                 return 1;
588         if (mainb == BCONTEXT_DATA && ob && ELEM(ob->type, OB_LAMP, OB_CAMERA))
589                 return 1;
590         
591         return 0;
592 }
593
594 static int buttons_shading_new_context(const bContext *C, int flag)
595 {
596         Object *ob = CTX_data_active_object(C);
597
598         if (flag & (1 << BCONTEXT_MATERIAL))
599                 return BCONTEXT_MATERIAL;
600         else if (ob && ELEM(ob->type, OB_LAMP, OB_CAMERA) && (flag & (1 << BCONTEXT_DATA)))
601                 return BCONTEXT_DATA;
602         else if (flag & (1 << BCONTEXT_WORLD))
603                 return BCONTEXT_WORLD;
604         
605         return BCONTEXT_RENDER;
606 }
607
608 void buttons_context_compute(const bContext *C, SpaceButs *sbuts)
609 {
610         ButsContextPath *path;
611         PointerRNA *ptr;
612         int a, pflag = 0, flag = 0;
613
614         if (!sbuts->path)
615                 sbuts->path = MEM_callocN(sizeof(ButsContextPath), "ButsContextPath");
616
617         path = sbuts->path;
618
619         /* We need to set Scene path now! Else, buttons_texture_context_compute() might not get a valid scene. */
620         buttons_context_path(C, path, BCONTEXT_SCENE, pflag);
621
622         buttons_texture_context_compute(C, sbuts);
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", "scene", "world", "object", "mesh", "armature", "lattice", "curve",
687         "meta_ball", "lamp", "speaker", "camera", "material", "material_slot",
688         "texture", "texture_user", "texture_user_property", "bone", "edit_bone",
689         "pose_bone", "particle_system", "particle_system_editable", "particle_settings",
690         "cloth", "soft_body", "fluid", "smoke", "collision", "brush", "dynamic_paint",
691         "line_style", NULL
692 };
693
694 int buttons_context(const bContext *C, const char *member, bContextDataResult *result)
695 {
696         SpaceButs *sbuts = CTX_wm_space_buts(C);
697         ButsContextPath *path = sbuts ? sbuts->path : NULL;
698
699         if (!path)
700                 return 0;
701
702         /* here we handle context, getting data from precomputed path */
703         if (CTX_data_dir(member)) {
704                 /* in case of new shading system we skip texture_slot, complex python
705                  * UI script logic depends on checking if this is available */
706                 if (sbuts->texuser)
707                         CTX_data_dir_set(result, buttons_context_dir + 1);
708                 else
709                         CTX_data_dir_set(result, buttons_context_dir);
710                 return 1;
711         }
712         else if (CTX_data_equals(member, "scene")) {
713                 /* Do not return one here if scene not found in path, in this case we want to get default context scene! */
714                 return set_pointer_type(path, result, &RNA_Scene);
715         }
716         else if (CTX_data_equals(member, "world")) {
717                 set_pointer_type(path, result, &RNA_World);
718                 return 1;
719         }
720         else if (CTX_data_equals(member, "object")) {
721                 set_pointer_type(path, result, &RNA_Object);
722                 return 1;
723         }
724         else if (CTX_data_equals(member, "mesh")) {
725                 set_pointer_type(path, result, &RNA_Mesh);
726                 return 1;
727         }
728         else if (CTX_data_equals(member, "armature")) {
729                 set_pointer_type(path, result, &RNA_Armature);
730                 return 1;
731         }
732         else if (CTX_data_equals(member, "lattice")) {
733                 set_pointer_type(path, result, &RNA_Lattice);
734                 return 1;
735         }
736         else if (CTX_data_equals(member, "curve")) {
737                 set_pointer_type(path, result, &RNA_Curve);
738                 return 1;
739         }
740         else if (CTX_data_equals(member, "meta_ball")) {
741                 set_pointer_type(path, result, &RNA_MetaBall);
742                 return 1;
743         }
744         else if (CTX_data_equals(member, "lamp")) {
745                 set_pointer_type(path, result, &RNA_Lamp);
746                 return 1;
747         }
748         else if (CTX_data_equals(member, "camera")) {
749                 set_pointer_type(path, result, &RNA_Camera);
750                 return 1;
751         }
752         else if (CTX_data_equals(member, "speaker")) {
753                 set_pointer_type(path, result, &RNA_Speaker);
754                 return 1;
755         }
756         else if (CTX_data_equals(member, "material")) {
757                 set_pointer_type(path, result, &RNA_Material);
758                 return 1;
759         }
760         else if (CTX_data_equals(member, "texture")) {
761                 ButsContextTexture *ct = sbuts->texuser;
762
763                 if (ct) {
764                         /* new shading system */
765                         CTX_data_pointer_set(result, &ct->texture->id, &RNA_Texture, ct->texture);
766                 }
767                 else {
768                         /* old shading system */
769                         set_pointer_type(path, result, &RNA_Texture);
770                 }
771
772                 return 1;
773         }
774         else if (CTX_data_equals(member, "material_slot")) {
775                 PointerRNA *ptr = get_pointer_type(path, &RNA_Object);
776
777                 if (ptr) {
778                         Object *ob = ptr->data;
779
780                         if (ob && OB_TYPE_SUPPORT_MATERIAL(ob->type) && ob->totcol) {
781                                 /* a valid actcol isn't ensured [#27526] */
782                                 int matnr = ob->actcol - 1;
783                                 if (matnr < 0) matnr = 0;
784                                 CTX_data_pointer_set(result, &ob->id, &RNA_MaterialSlot, &ob->mat[matnr]);
785                         }
786                 }
787
788                 return 1;
789         }
790         else if (CTX_data_equals(member, "texture_user")) {
791                 ButsContextTexture *ct = sbuts->texuser;
792
793                 if (!ct)
794                         return -1;  /* old shading system (found but not available) */
795
796                 if (ct->user && ct->user->ptr.data) {
797                         ButsTextureUser *user = ct->user;
798                         CTX_data_pointer_set(result, user->ptr.id.data, user->ptr.type, user->ptr.data);
799                 }
800
801                 return 1;
802         }
803         else if (CTX_data_equals(member, "texture_user_property")) {
804                 ButsContextTexture *ct = sbuts->texuser;
805
806                 if (!ct)
807                         return -1;  /* old shading system (found but not available) */
808
809                 if (ct->user && ct->user->ptr.data) {
810                         ButsTextureUser *user = ct->user;
811                         CTX_data_pointer_set(result, NULL, &RNA_Property, user->prop);
812                 }
813
814                 return 1;
815         }
816         else if (CTX_data_equals(member, "texture_node")) {
817                 ButsContextTexture *ct = sbuts->texuser;
818
819                 if (ct) {
820                         /* new shading system */
821                         if (ct->user && ct->user->node) {
822                                 CTX_data_pointer_set(result, &ct->user->ntree->id, &RNA_Node, ct->user->node);
823                         }
824
825                         return 1;
826                 }
827                 else {
828                         /* old shading system */
829                         PointerRNA *ptr;
830
831                         if ((ptr = get_pointer_type(path, &RNA_Material))) {
832                                 Material *ma = ptr->data;
833
834                                 if (ma) {
835                                         bNode *node = give_current_material_texture_node(ma);
836                                         CTX_data_pointer_set(result, &ma->nodetree->id, &RNA_Node, node);
837                                 }
838                         }
839
840                         return 1;
841                 }
842         }
843         else if (CTX_data_equals(member, "texture_slot")) {
844                 ButsContextTexture *ct = sbuts->texuser;
845                 PointerRNA *ptr;
846
847                 if (ct) {
848                         return 0;  /* new shading system */
849                 }
850                 else if ((ptr = get_pointer_type(path, &RNA_Material))) {
851                         Material *ma = ptr->data;
852
853                         /* if we have a node material, get slot from material in material node */
854                         if (ma && ma->use_nodes && ma->nodetree) {
855                                 /* if there's an active texture node in the node tree,
856                                  * then that texture is in context directly, without a texture slot */
857                                 if (give_current_material_texture_node(ma))
858                                         return 0;
859
860                                 ma = give_node_material(ma);
861                                 if (ma)
862                                         CTX_data_pointer_set(result, &ma->id, &RNA_MaterialTextureSlot, ma->mtex[(int)ma->texact]);
863                                 else
864                                         return 0;
865                         }
866                         else if (ma) {
867                                 CTX_data_pointer_set(result, &ma->id, &RNA_MaterialTextureSlot, ma->mtex[(int)ma->texact]);
868                         }
869                 }
870                 else if ((ptr = get_pointer_type(path, &RNA_Lamp))) {
871                         Lamp *la = ptr->data;
872
873                         if (la)
874                                 CTX_data_pointer_set(result, &la->id, &RNA_LampTextureSlot, la->mtex[(int)la->texact]);
875                 }
876                 else if ((ptr = get_pointer_type(path, &RNA_World))) {
877                         World *wo = ptr->data;
878
879                         if (wo)
880                                 CTX_data_pointer_set(result, &wo->id, &RNA_WorldTextureSlot, wo->mtex[(int)wo->texact]);
881                 }
882                 else if ((ptr = get_pointer_type(path, &RNA_FreestyleLineStyle))) {
883                         FreestyleLineStyle *ls = ptr->data;
884
885                         if (ls)
886                                 CTX_data_pointer_set(result, &ls->id, &RNA_LineStyleTextureSlot, ls->mtex[(int)ls->texact]);
887                 }
888
889                 return 1;
890         }
891         else if (CTX_data_equals(member, "bone")) {
892                 set_pointer_type(path, result, &RNA_Bone);
893                 return 1;
894         }
895         else if (CTX_data_equals(member, "edit_bone")) {
896                 set_pointer_type(path, result, &RNA_EditBone);
897                 return 1;
898         }
899         else if (CTX_data_equals(member, "pose_bone")) {
900                 set_pointer_type(path, result, &RNA_PoseBone);
901                 return 1;
902         }
903         else if (CTX_data_equals(member, "cloth")) {
904                 PointerRNA *ptr = get_pointer_type(path, &RNA_Object);
905
906                 if (ptr && ptr->data) {
907                         Object *ob = ptr->data;
908                         ModifierData *md = modifiers_findByType(ob, eModifierType_Cloth);
909                         CTX_data_pointer_set(result, &ob->id, &RNA_ClothModifier, md);
910                         return 1;
911                 }
912         }
913         else if (CTX_data_equals(member, "soft_body")) {
914                 PointerRNA *ptr = get_pointer_type(path, &RNA_Object);
915
916                 if (ptr && ptr->data) {
917                         Object *ob = ptr->data;
918                         ModifierData *md = modifiers_findByType(ob, eModifierType_Softbody);
919                         CTX_data_pointer_set(result, &ob->id, &RNA_SoftBodyModifier, md);
920                         return 1;
921                 }
922         }
923         else if (CTX_data_equals(member, "fluid")) {
924                 PointerRNA *ptr = get_pointer_type(path, &RNA_Object);
925
926                 if (ptr && ptr->data) {
927                         Object *ob = ptr->data;
928                         ModifierData *md = modifiers_findByType(ob, eModifierType_Fluidsim);
929                         CTX_data_pointer_set(result, &ob->id, &RNA_FluidSimulationModifier, md);
930                         return 1;
931                 }
932         }
933         
934         else if (CTX_data_equals(member, "smoke")) {
935                 PointerRNA *ptr = get_pointer_type(path, &RNA_Object);
936
937                 if (ptr && ptr->data) {
938                         Object *ob = ptr->data;
939                         ModifierData *md = modifiers_findByType(ob, eModifierType_Smoke);
940                         CTX_data_pointer_set(result, &ob->id, &RNA_SmokeModifier, md);
941                         return 1;
942                 }
943         }
944         else if (CTX_data_equals(member, "collision")) {
945                 PointerRNA *ptr = get_pointer_type(path, &RNA_Object);
946
947                 if (ptr && ptr->data) {
948                         Object *ob = ptr->data;
949                         ModifierData *md = modifiers_findByType(ob, eModifierType_Collision);
950                         CTX_data_pointer_set(result, &ob->id, &RNA_CollisionModifier, md);
951                         return 1;
952                 }
953         }
954         else if (CTX_data_equals(member, "brush")) {
955                 set_pointer_type(path, result, &RNA_Brush);
956                 return 1;
957         }
958         else if (CTX_data_equals(member, "dynamic_paint")) {
959                 PointerRNA *ptr = get_pointer_type(path, &RNA_Object);
960
961                 if (ptr && ptr->data) {
962                         Object *ob = ptr->data;
963                         ModifierData *md = modifiers_findByType(ob, eModifierType_DynamicPaint);
964                         CTX_data_pointer_set(result, &ob->id, &RNA_DynamicPaintModifier, md);
965                         return 1;
966                 }
967         }
968         else if (CTX_data_equals(member, "line_style")) {
969                 set_pointer_type(path, result, &RNA_FreestyleLineStyle);
970                 return 1;
971         }
972         else {
973                 return 0; /* not found */
974         }
975
976         return -1; /* found but not available */
977 }
978
979 /************************* Drawing the Path ************************/
980
981 static void pin_cb(bContext *C, void *UNUSED(arg1), void *UNUSED(arg2))
982 {
983         SpaceButs *sbuts = CTX_wm_space_buts(C);
984
985         if (sbuts->flag & SB_PIN_CONTEXT) {
986                 sbuts->pinid = buttons_context_id_path(C);
987         }
988         else
989                 sbuts->pinid = NULL;
990         
991         ED_area_tag_redraw(CTX_wm_area(C));
992 }
993
994 void buttons_context_draw(const bContext *C, uiLayout *layout)
995 {
996         SpaceButs *sbuts = CTX_wm_space_buts(C);
997         ButsContextPath *path = sbuts->path;
998         uiLayout *row;
999         uiBlock *block;
1000         uiBut *but;
1001         PointerRNA *ptr;
1002         char namebuf[128], *name;
1003         int a, icon;
1004
1005         if (!path)
1006                 return;
1007
1008         row = uiLayoutRow(layout, true);
1009         uiLayoutSetAlignment(row, UI_LAYOUT_ALIGN_LEFT);
1010
1011         block = uiLayoutGetBlock(row);
1012         UI_block_emboss_set(block, UI_EMBOSS_NONE);
1013         but = uiDefIconButBitC(block, UI_BTYPE_ICON_TOGGLE, SB_PIN_CONTEXT, 0, ICON_UNPINNED, 0, 0, UI_UNIT_X, UI_UNIT_Y, &sbuts->flag,
1014                                0, 0, 0, 0, TIP_("Follow context or keep fixed datablock displayed"));
1015         UI_but_flag_disable(but, UI_BUT_UNDO); /* skip undo on screen buttons */
1016         UI_but_func_set(but, pin_cb, NULL, NULL);
1017
1018         for (a = 0; a < path->len; a++) {
1019                 ptr = &path->ptr[a];
1020
1021                 if (a != 0)
1022                         uiItemL(row, "", VICO_SMALL_TRI_RIGHT_VEC);
1023
1024                 if (ptr->data) {
1025                         icon = RNA_struct_ui_icon(ptr->type);
1026                         name = RNA_struct_name_get_alloc(ptr, namebuf, sizeof(namebuf), NULL);
1027
1028                         if (name) {
1029                                 if (!ELEM(sbuts->mainb, BCONTEXT_RENDER, BCONTEXT_SCENE, BCONTEXT_RENDER_LAYER) && ptr->type == &RNA_Scene)
1030                                         uiItemLDrag(row, ptr, "", icon);  /* save some space */
1031                                 else
1032                                         uiItemLDrag(row, ptr, name, icon);
1033
1034                                 if (name != namebuf)
1035                                         MEM_freeN(name);
1036                         }
1037                         else
1038                                 uiItemL(row, "", icon);
1039                 }
1040         }
1041 }
1042
1043 static void buttons_panel_context(const bContext *C, Panel *pa)
1044 {
1045         buttons_context_draw(C, pa->layout);
1046 }
1047
1048 void buttons_context_register(ARegionType *art)
1049 {
1050         PanelType *pt;
1051
1052         pt = MEM_callocN(sizeof(PanelType), "spacetype buttons panel context");
1053         strcpy(pt->idname, "BUTTONS_PT_context");
1054         strcpy(pt->label, N_("Context"));  /* XXX C panels are not available through RNA (bpy.types)! */
1055         strcpy(pt->translation_context, BLT_I18NCONTEXT_DEFAULT_BPYRNA);
1056         pt->draw = buttons_panel_context;
1057         pt->flag = PNL_NO_HEADER;
1058         BLI_addtail(&art->paneltypes, pt);
1059 }
1060
1061 ID *buttons_context_id_path(const bContext *C)
1062 {
1063         SpaceButs *sbuts = CTX_wm_space_buts(C);
1064         ButsContextPath *path = sbuts->path;
1065         PointerRNA *ptr;
1066         int a;
1067
1068         if (path->len) {
1069                 for (a = path->len - 1; a >= 0; a--) {
1070                         ptr = &path->ptr[a];
1071
1072                         if (ptr->id.data) {
1073                                 return ptr->id.data;
1074                         }
1075                 }
1076         }
1077
1078         return NULL;
1079 }
1080
1081 void ED_buttons_id_unref(SpaceButs *sbuts, const ID *id)
1082 {
1083         if (sbuts->pinid == id) {
1084                 sbuts->pinid = NULL;
1085                 sbuts->flag &= ~SB_PIN_CONTEXT;
1086         }
1087
1088         if (sbuts->path) {
1089                 ButsContextPath *path = sbuts->path;
1090                 int i;
1091
1092                 for (i = 0; i < path->len; i++) {
1093                         if (path->ptr[i].id.data == id) {
1094                                 break;
1095                         }
1096                 }
1097
1098                 if (i == path->len) {
1099                         /* pass */
1100                 }
1101                 else if (i == 0) {
1102                         MEM_SAFE_FREE(sbuts->path);
1103                 }
1104                 else {
1105                         memset(&path->ptr[i], 0, sizeof(path->ptr[i]) * (path->len - i));
1106                         path->len = i;
1107                 }
1108         }
1109 }