2.5: Various Fixes
[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., 59 Temple Place - Suite 330, Boston, MA  02111-1307, 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_lamp_types.h"
35 #include "DNA_material_types.h"
36 #include "DNA_modifier_types.h"
37 #include "DNA_object_types.h"
38 #include "DNA_scene_types.h"
39 #include "DNA_screen_types.h"
40 #include "DNA_space_types.h"
41 #include "DNA_particle_types.h"
42 #include "DNA_texture_types.h"
43 #include "DNA_world_types.h"
44
45 #include "BLI_listbase.h"
46
47 #include "BKE_context.h"
48 #include "BKE_material.h"
49 #include "BKE_modifier.h"
50 #include "BKE_particle.h"
51 #include "BKE_screen.h"
52 #include "BKE_utildefines.h"
53 #include "BKE_world.h"
54
55 #include "RNA_access.h"
56
57 #include "ED_armature.h"
58 #include "ED_screen.h"
59
60 #include "UI_interface.h"
61 #include "UI_resources.h"
62
63 #include "buttons_intern.h"     // own include
64
65 typedef struct ButsContextPath {
66         PointerRNA ptr[8];
67         int len;
68         int worldtex;
69 } ButsContextPath;
70
71 static int set_pointer_type(ButsContextPath *path, bContextDataResult *result, StructRNA *type)
72 {
73         PointerRNA *ptr;
74         int a;
75
76         for(a=0; a<path->len; a++) {
77                 ptr= &path->ptr[a];
78
79                 if(RNA_struct_is_a(ptr->type, type)) {
80                         CTX_data_pointer_set(result, ptr->id.data, ptr->type, ptr->data);
81                         return 1;
82                 }
83         }
84
85         return 0;
86 }
87
88 static PointerRNA *get_pointer_type(ButsContextPath *path, StructRNA *type)
89 {
90         PointerRNA *ptr;
91         int a;
92
93         for(a=0; a<path->len; a++) {
94                 ptr= &path->ptr[a];
95
96                 if(RNA_struct_is_a(ptr->type, type))
97                         return ptr;
98         }
99
100         return NULL;
101 }
102
103 /************************* Creating the Path ************************/
104
105 static int buttons_context_path_scene(ButsContextPath *path)
106 {
107         PointerRNA *ptr= &path->ptr[path->len-1];
108
109         /* this one just verifies */
110         return RNA_struct_is_a(ptr->type, &RNA_Scene);
111 }
112
113 static int buttons_context_path_world(ButsContextPath *path)
114 {
115         Scene *scene;
116         PointerRNA *ptr= &path->ptr[path->len-1];
117
118         /* if we already have a (pinned) world, we're done */
119         if(RNA_struct_is_a(ptr->type, &RNA_World)) {
120                 return 1;
121         }
122         /* if we have a scene, use the scene's world */
123         else if(buttons_context_path_scene(path)) {
124                 scene= path->ptr[path->len-1].data;
125
126                 RNA_id_pointer_create(&scene->world->id, &path->ptr[path->len]);
127                 path->len++;
128
129                 return 1;
130         }
131
132         /* no path to a world possible */
133         return 0;
134 }
135
136
137 static int buttons_context_path_object(ButsContextPath *path)
138 {
139         Scene *scene;
140         Object *ob;
141         PointerRNA *ptr= &path->ptr[path->len-1];
142
143         /* if we already have a (pinned) object, we're done */
144         if(RNA_struct_is_a(ptr->type, &RNA_Object)) {
145                 return 1;
146         }
147         /* if we have a scene, use the scene's active object */
148         else if(buttons_context_path_scene(path)) {
149                 scene= path->ptr[path->len-1].data;
150                 ob= (scene->basact)? scene->basact->object: NULL;
151
152                 if(ob) {
153                         RNA_id_pointer_create(&ob->id, &path->ptr[path->len]);
154                         path->len++;
155
156                         return 1;
157                 }
158         }
159
160         /* no path to a object possible */
161         return 0;
162 }
163
164 static int buttons_context_path_data(ButsContextPath *path, int type)
165 {
166         Object *ob;
167         PointerRNA *ptr= &path->ptr[path->len-1];
168
169         /* if we already have a data, we're done */
170         if(RNA_struct_is_a(ptr->type, &RNA_Mesh) && (type == -1 || type == OB_MESH)) return 1;
171         else if(RNA_struct_is_a(ptr->type, &RNA_Curve) && (type == -1 || ELEM3(type, OB_CURVE, OB_SURF, OB_FONT))) return 1;
172         else if(RNA_struct_is_a(ptr->type, &RNA_Armature) && (type == -1 || type == OB_ARMATURE)) return 1;
173         else if(RNA_struct_is_a(ptr->type, &RNA_MetaBall) && (type == -1 || type == OB_MBALL)) return 1;
174         else if(RNA_struct_is_a(ptr->type, &RNA_Lattice) && (type == -1 || type == OB_LATTICE)) return 1;
175         else if(RNA_struct_is_a(ptr->type, &RNA_Camera) && (type == -1 || type == OB_CAMERA)) return 1;
176         else if(RNA_struct_is_a(ptr->type, &RNA_Lamp) && (type == -1 || type == OB_LAMP)) return 1;
177         /* try to get an object in the path, no pinning supported here */
178         else if(buttons_context_path_object(path)) {
179                 ob= path->ptr[path->len-1].data;
180
181                 if(ob && (type == -1 || type == ob->type)) {
182                         RNA_id_pointer_create(ob->data, &path->ptr[path->len]);
183                         path->len++;
184
185                         return 1;
186                 }
187         }
188
189         /* no path to data possible */
190         return 0;
191 }
192
193 static int buttons_context_path_modifier(ButsContextPath *path)
194 {
195         Object *ob;
196
197         if(buttons_context_path_object(path)) {
198                 ob= path->ptr[path->len-1].data;
199
200                 if(ob && ELEM4(ob->type, OB_MESH, OB_CURVE, OB_FONT, OB_SURF))
201                         return 1;
202         }
203
204         return 0;
205 }
206
207 static int buttons_context_path_material(ButsContextPath *path)
208 {
209         Object *ob;
210         PointerRNA *ptr= &path->ptr[path->len-1];
211         Material *ma;
212
213         /* if we already have a (pinned) material, we're done */
214         if(RNA_struct_is_a(ptr->type, &RNA_Material)) {
215                 return 1;
216         }
217         /* if we have an object, use the object material slot */
218         else if(buttons_context_path_object(path)) {
219                 ob= path->ptr[path->len-1].data;
220
221                 if(ob && ob->type && (ob->type<OB_LAMP)) {
222                         ma= give_current_material(ob, ob->actcol);
223                         RNA_id_pointer_create(&ma->id, &path->ptr[path->len]);
224                         path->len++;
225                         return 1;
226                 }
227         }
228
229         /* no path to a material possible */
230         return 0;
231 }
232
233 static Bone *find_active_bone(Bone *bone)
234 {
235         Bone *active;
236
237         for(; bone; bone=bone->next) {
238                 if(bone->flag & BONE_ACTIVE)
239                         return bone;
240
241                 active= find_active_bone(bone->childbase.first);
242                 if(active)
243                         return active;
244         }
245
246         return NULL;
247 }
248
249 static int buttons_context_path_bone(ButsContextPath *path)
250 {
251         bArmature *arm;
252         Bone *bone;
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                         for(edbo=arm->edbo->first; edbo; edbo=edbo->next) {
261                                 if(edbo->flag & BONE_ACTIVE) {
262                                         RNA_pointer_create(&arm->id, &RNA_EditBone, edbo, &path->ptr[path->len]);
263                                         path->len++;
264                                         return 1;
265                                 }
266                         }
267                 }
268                 else {
269                         bone= find_active_bone(arm->bonebase.first);
270
271                         if(bone) {
272                                 RNA_pointer_create(&arm->id, &RNA_Bone, bone, &path->ptr[path->len]);
273                                 path->len++;
274                                 return 1;
275                         }
276                 }
277         }
278
279         /* no path to a bone possible */
280         return 0;
281 }
282
283 static int buttons_context_path_particle(ButsContextPath *path)
284 {
285         Object *ob;
286         ParticleSystem *psys;
287
288         /* if we have an object, get the active particle system */
289         if(buttons_context_path_object(path)) {
290                 ob= path->ptr[path->len-1].data;
291
292                 if(ob && ob->type == OB_MESH) {
293                         psys= psys_get_current(ob);
294
295                         RNA_pointer_create(&ob->id, &RNA_ParticleSystem, psys, &path->ptr[path->len]);
296                         path->len++;
297                         return 1;
298                 }
299         }
300
301         /* no path to a particle system possible */
302         return 0;
303 }
304
305 static int buttons_context_path_texture(ButsContextPath *path)
306 {
307         Material *ma;
308         Lamp *la;
309         World *wo;
310         MTex *mtex;
311         Tex *tex;
312         PointerRNA *ptr= &path->ptr[path->len-1];
313
314         /* if we already have a (pinned) texture, we're done */
315         if(RNA_struct_is_a(ptr->type, &RNA_Texture)) {
316                 return 1;
317         }
318         /* try world */
319         else if(path->worldtex && buttons_context_path_world(path)) {
320                 wo= path->ptr[path->len-1].data;
321
322                 if(wo) {
323                         mtex= wo->mtex[(int)wo->texact];
324                         tex= (mtex)? mtex->tex: NULL;
325
326                         RNA_id_pointer_create(&tex->id, &path->ptr[path->len]);
327                         path->len++;
328                         return 1;
329                 }
330         }
331         /* try material */
332         else if(buttons_context_path_material(path)) {
333                 ma= path->ptr[path->len-1].data;
334
335                 if(ma) {
336                         mtex= ma->mtex[(int)ma->texact];
337                         tex= (mtex)? mtex->tex: NULL;
338
339                         RNA_id_pointer_create(&tex->id, &path->ptr[path->len]);
340                         path->len++;
341                         return 1;
342                 }
343         }
344         /* try lamp */
345         else if(buttons_context_path_data(path, OB_LAMP)) {
346                 la= path->ptr[path->len-1].data;
347
348                 if(la) {
349                         mtex= la->mtex[(int)la->texact];
350                         tex= (mtex)? mtex->tex: NULL;
351
352                         RNA_id_pointer_create(&tex->id, &path->ptr[path->len]);
353                         path->len++;
354                         return 1;
355                 }
356         }
357         /* TODO: material nodes, brush */
358
359         /* no path to a particle system possible */
360         return 0;
361 }
362
363
364 static int buttons_context_path(const bContext *C, ButsContextPath *path, int mainb, int worldtex)
365 {
366         SpaceButs *sbuts= (SpaceButs*)CTX_wm_space_data(C);
367         ID *id;
368         int found;
369
370         memset(path, 0, sizeof(*path));
371         path->worldtex= worldtex;
372
373         /* if some ID datablock is pinned, set the root pointer */
374         if(sbuts->pinid) {
375                 id= sbuts->pinid;
376
377                 RNA_id_pointer_create(id, &path->ptr[0]);
378                 path->len++;
379         }
380
381         /* no pinned root, use scene as root */
382         if(path->len == 0) {
383                 id= (ID*)CTX_data_scene(C);
384                 RNA_id_pointer_create(id, &path->ptr[0]);
385                 path->len++;
386         }
387
388         /* now for each buttons context type, we try to construct a path,
389          * tracing back recursively */
390         switch(mainb) {
391                 case BCONTEXT_SCENE:
392                         found= buttons_context_path_scene(path);
393                         break;
394                 case BCONTEXT_WORLD:
395                         found= buttons_context_path_world(path);
396                         break;
397                 case BCONTEXT_OBJECT:
398                 case BCONTEXT_PHYSICS:
399                 case BCONTEXT_CONSTRAINT:
400                         found= buttons_context_path_object(path);
401                         break;
402                 case BCONTEXT_MODIFIER:
403                         found= buttons_context_path_modifier(path);
404                         break;
405                 case BCONTEXT_DATA:
406                         found= buttons_context_path_data(path, -1);
407                         break;
408                 case BCONTEXT_PARTICLE:
409                         found= buttons_context_path_particle(path);
410                         break;
411                 case BCONTEXT_MATERIAL:
412                         found= buttons_context_path_material(path);
413                         break;
414                 case BCONTEXT_TEXTURE:
415                         found= buttons_context_path_texture(path);
416                         break;
417                 case BCONTEXT_BONE:
418                         found= buttons_context_path_bone(path);
419                         if(!found)
420                                 found= buttons_context_path_data(path, OB_ARMATURE);
421                         break;
422                 default:
423                         found= 0;
424                         break;
425         }
426
427         return found;
428 }
429
430 void buttons_context_compute(const bContext *C, SpaceButs *sbuts)
431 {
432         ButsContextPath *path;
433         PointerRNA *ptr;
434         int a, worldtex, flag= 0;
435
436         if(!sbuts->path)
437                 sbuts->path= MEM_callocN(sizeof(ButsContextPath), "ButsContextPath");
438         
439         path= sbuts->path;
440         worldtex= (sbuts->flag & SB_WORLD_TEX);
441         
442         /* for each context, see if we can compute a valid path to it, if
443          * this is the case, we know we have to display the button */
444         for(a=0; a<BCONTEXT_TOT; a++) {
445                 if(buttons_context_path(C, path, a, worldtex)) {
446                         flag |= (1<<a);
447
448                         /* setting icon for data context */
449                         if(a == BCONTEXT_DATA) {
450                                 ptr= &path->ptr[path->len-1];
451
452                                 if(ptr->type)
453                                         sbuts->dataicon= RNA_struct_ui_icon(ptr->type);
454                                 else
455                                         sbuts->dataicon= ICON_EMPTY_DATA;
456                         }
457                 }
458         }
459
460         /* always try to use the tab that was explicitly
461          * set to the user, so that once that context comes
462          * back, the tab is activated again */
463         sbuts->mainb= sbuts->mainbuser;
464
465         /* in case something becomes invalid, change */
466         if((flag & (1 << sbuts->mainb)) == 0) {
467                 if(flag & BCONTEXT_OBJECT) {
468                         sbuts->mainb= BCONTEXT_OBJECT;
469                 }
470                 else {
471                         for(a=0; a<BCONTEXT_TOT; a++) {
472                                 if(flag & (1 << a)) {
473                                         sbuts->mainb= a;
474                                         break;
475                                 }
476                         }
477                 }
478         }
479
480         buttons_context_path(C, path, sbuts->mainb, worldtex);
481
482         if(!(flag & (1 << sbuts->mainb))) {
483                 if(flag & (1 << BCONTEXT_OBJECT))
484                         sbuts->mainb= BCONTEXT_OBJECT;
485                 else
486                         sbuts->mainb= BCONTEXT_SCENE;
487         }
488
489         sbuts->pathflag= flag;
490 }
491
492 /************************* Context Callback ************************/
493
494 int buttons_context(const bContext *C, const char *member, bContextDataResult *result)
495 {
496         SpaceButs *sbuts= (SpaceButs*)CTX_wm_space_data(C);
497         ButsContextPath *path= sbuts?sbuts->path:NULL;
498
499         if(!path)
500                 return 0;
501
502         /* here we handle context, getting data from precomputed path */
503         if(CTX_data_dir(member)) {
504                 static const char *dir[] = {
505                         "world", "object", "mesh", "armature", "lattice", "curve",
506                         "meta_ball", "lamp", "camera", "material", "material_slot",
507                         "texture", "texture_slot", "bone", "edit_bone", "particle_system",
508                         "cloth", "soft_body", "fluid", "collision", NULL};
509
510                 CTX_data_dir_set(result, dir);
511                 return 1;
512         }
513         else if(CTX_data_equals(member, "world")) {
514                 set_pointer_type(path, result, &RNA_World);
515                 return 1;
516         }
517         else if(CTX_data_equals(member, "object")) {
518                 set_pointer_type(path, result, &RNA_Object);
519                 return 1;
520         }
521         else if(CTX_data_equals(member, "mesh")) {
522                 set_pointer_type(path, result, &RNA_Mesh);
523                 return 1;
524         }
525         else if(CTX_data_equals(member, "armature")) {
526                 set_pointer_type(path, result, &RNA_Armature);
527                 return 1;
528         }
529         else if(CTX_data_equals(member, "lattice")) {
530                 set_pointer_type(path, result, &RNA_Lattice);
531                 return 1;
532         }
533         else if(CTX_data_equals(member, "curve")) {
534                 set_pointer_type(path, result, &RNA_Curve);
535                 return 1;
536         }
537         else if(CTX_data_equals(member, "meta_ball")) {
538                 set_pointer_type(path, result, &RNA_MetaBall);
539                 return 1;
540         }
541         else if(CTX_data_equals(member, "lamp")) {
542                 set_pointer_type(path, result, &RNA_Lamp);
543                 return 1;
544         }
545         else if(CTX_data_equals(member, "camera")) {
546                 set_pointer_type(path, result, &RNA_Camera);
547                 return 1;
548         }
549         else if(CTX_data_equals(member, "material")) {
550                 set_pointer_type(path, result, &RNA_Material);
551                 return 1;
552         }
553         else if(CTX_data_equals(member, "texture")) {
554                 set_pointer_type(path, result, &RNA_Texture);
555                 return 1;
556         }
557         else if(CTX_data_equals(member, "material_slot")) {
558                 PointerRNA *ptr= get_pointer_type(path, &RNA_Object);
559
560                 if(ptr) {
561                         Object *ob= ptr->data;
562
563                         if(ob && ob->type && (ob->type<OB_LAMP) && ob->totcol)
564                                 CTX_data_pointer_set(result, &ob->id, &RNA_MaterialSlot, ob->mat+ob->actcol-1);
565                 }
566
567                 return 1;
568         }
569         else if(CTX_data_equals(member, "texture_slot")) {
570                 PointerRNA *ptr;
571
572                 if((ptr=get_pointer_type(path, &RNA_Material))) {
573                         Material *ma= ptr->data;
574
575                         if(ma)
576                                 CTX_data_pointer_set(result, &ma->id, &RNA_MaterialTextureSlot, ma->mtex[(int)ma->texact]);
577                 }
578                 else if((ptr=get_pointer_type(path, &RNA_Lamp))) {
579                         Lamp *la= ptr->data;
580
581                         if(la)
582                                 CTX_data_pointer_set(result, &la->id, &RNA_LampTextureSlot, la->mtex[(int)la->texact]);
583                 }
584                 else if((ptr=get_pointer_type(path, &RNA_World))) {
585                         World *wo= ptr->data;
586
587                         if(wo)
588                                 CTX_data_pointer_set(result, &wo->id, &RNA_WorldTextureSlot, wo->mtex[(int)wo->texact]);
589                 }
590                 else if((ptr=get_pointer_type(path, &RNA_Brush))) { /* how to get this into context? */
591                         Brush *br= ptr->data;
592
593                         if(br)
594                                 CTX_data_pointer_set(result, &br->id, &RNA_TextureSlot, br->mtex[(int)br->texact]);
595                 }
596
597                 return 1;
598         }
599         else if(CTX_data_equals(member, "bone")) {
600                 set_pointer_type(path, result, &RNA_Bone);
601                 return 1;
602         }
603         else if(CTX_data_equals(member, "edit_bone")) {
604                 set_pointer_type(path, result, &RNA_EditBone);
605                 return 1;
606         }
607         else if(CTX_data_equals(member, "particle_system")) {
608                 set_pointer_type(path, result, &RNA_ParticleSystem);
609                 return 1;
610         }
611         else if(CTX_data_equals(member, "cloth")) {
612                 PointerRNA *ptr= get_pointer_type(path, &RNA_Object);
613
614                 if(ptr && ptr->data) {
615                         Object *ob= ptr->data;
616                         ModifierData *md= modifiers_findByType(ob, eModifierType_Cloth);
617                         CTX_data_pointer_set(result, &ob->id, &RNA_ClothModifier, md);
618                         return 1;
619                 }
620         }
621         else if(CTX_data_equals(member, "soft_body")) {
622                 PointerRNA *ptr= get_pointer_type(path, &RNA_Object);
623
624                 if(ptr && ptr->data) {
625                         Object *ob= ptr->data;
626                         ModifierData *md= modifiers_findByType(ob, eModifierType_Softbody);
627                         CTX_data_pointer_set(result, &ob->id, &RNA_SoftBodyModifier, md);
628                         return 1;
629                 }
630         }
631         else if(CTX_data_equals(member, "fluid")) {
632                 PointerRNA *ptr= get_pointer_type(path, &RNA_Object);
633
634                 if(ptr && ptr->data) {
635                         Object *ob= ptr->data;
636                         ModifierData *md= modifiers_findByType(ob, eModifierType_Fluidsim);
637                         CTX_data_pointer_set(result, &ob->id, &RNA_FluidSimulationModifier, md);
638                         return 1;
639                 }
640         }
641         else if(CTX_data_equals(member, "collision")) {
642                 PointerRNA *ptr= get_pointer_type(path, &RNA_Object);
643
644                 if(ptr && ptr->data) {
645                         Object *ob= ptr->data;
646                         ModifierData *md= modifiers_findByType(ob, eModifierType_Collision);
647                         CTX_data_pointer_set(result, &ob->id, &RNA_CollisionModifier, md);
648                         return 1;
649                 }
650         }
651
652         return 0;
653 }
654
655 /************************* Drawing the Path ************************/
656
657 static void pin_cb(bContext *C, void *arg1, void *arg2)
658 {
659         SpaceButs *sbuts= (SpaceButs*)CTX_wm_space_data(C);
660         ButsContextPath *path= sbuts->path;
661         PointerRNA *ptr;
662         int a;
663
664         if(sbuts->flag & SB_PIN_CONTEXT) {
665                 if(path->len) {
666                         for(a=path->len-1; a>=0; a--) {
667                                 ptr= &path->ptr[a];
668
669                                 if(ptr->id.data) {
670                                         sbuts->pinid= ptr->id.data;
671                                         break;
672                                 }
673                         }
674                 }
675         }
676         else
677                 sbuts->pinid= NULL;
678         
679         ED_area_tag_redraw(CTX_wm_area(C));
680 }
681
682 void buttons_context_draw(const bContext *C, uiLayout *layout)
683 {
684         SpaceButs *sbuts= (SpaceButs*)CTX_wm_space_data(C);
685         ButsContextPath *path= sbuts->path;
686         uiLayout *row;
687         uiBlock *block;
688         uiBut *but;
689         PointerRNA *ptr;
690         char namebuf[128], *name;
691         int a, icon;
692
693         if(!path)
694                 return;
695
696         row= uiLayoutRow(layout, 1);
697         uiLayoutSetAlignment(row, UI_LAYOUT_ALIGN_LEFT);
698
699         block= uiLayoutGetBlock(row);
700         uiBlockSetEmboss(block, UI_EMBOSSN);
701         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.");
702         uiButSetFunc(but, pin_cb, NULL, NULL);
703
704         for(a=0; a<path->len; a++) {
705                 ptr= &path->ptr[a];
706
707                 if(a != 0)
708                         uiDefIconBut(block, LABEL, 0, VICON_SMALL_TRI_RIGHT, 0, 0, 10, UI_UNIT_Y, NULL, 0, 0, 0, 0, "");
709
710                 if(ptr->data) {
711                         icon= RNA_struct_ui_icon(ptr->type);
712                         name= RNA_struct_name_get_alloc(ptr, namebuf, sizeof(namebuf));
713
714                         if(name) {
715                                 if(sbuts->mainb != BCONTEXT_SCENE && ptr->type == &RNA_Scene)
716                                         uiItemL(row, "", icon); /* save some space */
717                                 else
718                                         uiItemL(row, name, icon);
719
720                                 if(name != namebuf)
721                                         MEM_freeN(name);
722                         }
723                         else
724                                 uiItemL(row, "", icon);
725                 }
726         }
727 }
728
729 static void buttons_panel_context(const bContext *C, Panel *pa)
730 {
731         buttons_context_draw(C, pa->layout);
732 }
733
734 void buttons_context_register(ARegionType *art)
735 {
736         PanelType *pt;
737
738         pt= MEM_callocN(sizeof(PanelType), "spacetype buttons panel context");
739         strcpy(pt->idname, "BUTTONS_PT_context");
740         strcpy(pt->label, "Context");
741         pt->draw= buttons_panel_context;
742         pt->flag= PNL_NO_HEADER;
743         BLI_addtail(&art->paneltypes, pt);
744 }