Blender  V2.59
buttons_context.c
Go to the documentation of this file.
00001 /*
00002  * $Id: buttons_context.c 38370 2011-07-13 17:52:23Z blendix $
00003  *
00004  * ***** BEGIN GPL LICENSE BLOCK *****
00005  *
00006  * This program is free software; you can redistribute it and/or
00007  * modify it under the terms of the GNU General Public License
00008  * as published by the Free Software Foundation; either version 2
00009  * of the License, or (at your option) any later version. 
00010  *
00011  * This program is distributed in the hope that it will be useful,
00012  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014  * GNU General Public License for more details.
00015  *
00016  * You should have received a copy of the GNU General Public License
00017  * along with this program; if not, write to the Free Software Foundation,
00018  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00019  *
00020  * The Original Code is Copyright (C) 2009 Blender Foundation.
00021  * All rights reserved.
00022  *
00023  * Contributor(s): Blender Foundation
00024  *
00025  * ***** END GPL LICENSE BLOCK *****
00026  */
00027 
00033 #include <stdlib.h>
00034 #include <string.h>
00035 
00036 #include "MEM_guardedalloc.h"
00037 
00038 #include "BLI_listbase.h"
00039 #include "BLI_utildefines.h"
00040 
00041 #include "DNA_armature_types.h"
00042 #include "DNA_lamp_types.h"
00043 #include "DNA_material_types.h"
00044 #include "DNA_node_types.h"
00045 #include "DNA_scene_types.h"
00046 #include "DNA_world_types.h"
00047 #include "DNA_brush_types.h"
00048 
00049 #include "BKE_context.h"
00050 #include "BKE_action.h"
00051 #include "BKE_material.h"
00052 #include "BKE_modifier.h"
00053 #include "BKE_paint.h"
00054 #include "BKE_particle.h"
00055 #include "BKE_screen.h"
00056 #include "BKE_texture.h"
00057 
00058 
00059 #include "RNA_access.h"
00060 
00061 #include "ED_armature.h"
00062 #include "ED_screen.h"
00063 #include "ED_physics.h"
00064 
00065 #include "UI_interface.h"
00066 #include "UI_resources.h"
00067 
00068 #include "buttons_intern.h"     // own include
00069 
00070 typedef struct ButsContextPath {
00071         PointerRNA ptr[8];
00072         int len;
00073         int flag;
00074         int tex_ctx;
00075 } ButsContextPath;
00076 
00077 static int set_pointer_type(ButsContextPath *path, bContextDataResult *result, StructRNA *type)
00078 {
00079         PointerRNA *ptr;
00080         int a;
00081 
00082         for(a=0; a<path->len; a++) {
00083                 ptr= &path->ptr[a];
00084 
00085                 if(RNA_struct_is_a(ptr->type, type)) {
00086                         CTX_data_pointer_set(result, ptr->id.data, ptr->type, ptr->data);
00087                         return 1;
00088                 }
00089         }
00090 
00091         return 0;
00092 }
00093 
00094 static PointerRNA *get_pointer_type(ButsContextPath *path, StructRNA *type)
00095 {
00096         PointerRNA *ptr;
00097         int a;
00098 
00099         for(a=0; a<path->len; a++) {
00100                 ptr= &path->ptr[a];
00101 
00102                 if(RNA_struct_is_a(ptr->type, type))
00103                         return ptr;
00104         }
00105 
00106         return NULL;
00107 }
00108 
00109 /************************* Creating the Path ************************/
00110 
00111 static int buttons_context_path_scene(ButsContextPath *path)
00112 {
00113         PointerRNA *ptr= &path->ptr[path->len-1];
00114 
00115         /* this one just verifies */
00116         return RNA_struct_is_a(ptr->type, &RNA_Scene);
00117 }
00118 
00119 /* note: this function can return 1 without adding a world to the path
00120  * so the buttons stay visible, but be sure to check the ID type if a ID_WO */
00121 static int buttons_context_path_world(ButsContextPath *path)
00122 {
00123         Scene *scene;
00124         World *world;
00125         PointerRNA *ptr= &path->ptr[path->len-1];
00126 
00127         /* if we already have a (pinned) world, we're done */
00128         if(RNA_struct_is_a(ptr->type, &RNA_World)) {
00129                 return 1;
00130         }
00131         /* if we have a scene, use the scene's world */
00132         else if(buttons_context_path_scene(path)) {
00133                 scene= path->ptr[path->len-1].data;
00134                 world= scene->world;
00135                 
00136                 if(world) {
00137                         RNA_id_pointer_create(&scene->world->id, &path->ptr[path->len]);
00138                         path->len++;
00139                         return 1;
00140                 }
00141                 else {
00142                         return 1;
00143                 }
00144         }
00145 
00146         /* no path to a world possible */
00147         return 0;
00148 }
00149 
00150 
00151 static int buttons_context_path_object(ButsContextPath *path)
00152 {
00153         Scene *scene;
00154         Object *ob;
00155         PointerRNA *ptr= &path->ptr[path->len-1];
00156 
00157         /* if we already have a (pinned) object, we're done */
00158         if(RNA_struct_is_a(ptr->type, &RNA_Object)) {
00159                 return 1;
00160         }
00161         /* if we have a scene, use the scene's active object */
00162         else if(buttons_context_path_scene(path)) {
00163                 scene= path->ptr[path->len-1].data;
00164                 ob= (scene->basact)? scene->basact->object: NULL;
00165 
00166                 if(ob) {
00167                         RNA_id_pointer_create(&ob->id, &path->ptr[path->len]);
00168                         path->len++;
00169 
00170                         return 1;
00171                 }
00172         }
00173 
00174         /* no path to a object possible */
00175         return 0;
00176 }
00177 
00178 static int buttons_context_path_data(ButsContextPath *path, int type)
00179 {
00180         Object *ob;
00181         PointerRNA *ptr= &path->ptr[path->len-1];
00182 
00183         /* if we already have a data, we're done */
00184         if(RNA_struct_is_a(ptr->type, &RNA_Mesh) && (type == -1 || type == OB_MESH)) return 1;
00185         else if(RNA_struct_is_a(ptr->type, &RNA_Curve) && (type == -1 || ELEM3(type, OB_CURVE, OB_SURF, OB_FONT))) return 1;
00186         else if(RNA_struct_is_a(ptr->type, &RNA_Armature) && (type == -1 || type == OB_ARMATURE)) return 1;
00187         else if(RNA_struct_is_a(ptr->type, &RNA_MetaBall) && (type == -1 || type == OB_MBALL)) return 1;
00188         else if(RNA_struct_is_a(ptr->type, &RNA_Lattice) && (type == -1 || type == OB_LATTICE)) return 1;
00189         else if(RNA_struct_is_a(ptr->type, &RNA_Camera) && (type == -1 || type == OB_CAMERA)) return 1;
00190         else if(RNA_struct_is_a(ptr->type, &RNA_Lamp) && (type == -1 || type == OB_LAMP)) return 1;
00191         /* try to get an object in the path, no pinning supported here */
00192         else if(buttons_context_path_object(path)) {
00193                 ob= path->ptr[path->len-1].data;
00194 
00195                 if(ob && (type == -1 || type == ob->type)) {
00196                         RNA_id_pointer_create(ob->data, &path->ptr[path->len]);
00197                         path->len++;
00198 
00199                         return 1;
00200                 }
00201         }
00202 
00203         /* no path to data possible */
00204         return 0;
00205 }
00206 
00207 static int buttons_context_path_modifier(ButsContextPath *path)
00208 {
00209         Object *ob;
00210 
00211         if(buttons_context_path_object(path)) {
00212                 ob= path->ptr[path->len-1].data;
00213 
00214                 if(ob && ELEM5(ob->type, OB_MESH, OB_CURVE, OB_FONT, OB_SURF, OB_LATTICE))
00215                         return 1;
00216         }
00217 
00218         return 0;
00219 }
00220 
00221 static int buttons_context_path_material(ButsContextPath *path, int for_texture)
00222 {
00223         Object *ob;
00224         PointerRNA *ptr= &path->ptr[path->len-1];
00225         Material *ma;
00226 
00227         /* if we already have a (pinned) material, we're done */
00228         if(RNA_struct_is_a(ptr->type, &RNA_Material)) {
00229                 return 1;
00230         }
00231         /* if we have an object, use the object material slot */
00232         else if(buttons_context_path_object(path)) {
00233                 ob= path->ptr[path->len-1].data;
00234 
00235                 if(ob && ob->type && (ob->type<OB_LAMP)) {
00236                         ma= give_current_material(ob, ob->actcol);
00237                         RNA_id_pointer_create(&ma->id, &path->ptr[path->len]);
00238                         path->len++;
00239 
00240                         if(for_texture && give_current_material_texture_node(ma))
00241                                 return 1;
00242                         
00243                         ma= give_node_material(ma);
00244                         if(ma) {
00245                                 RNA_id_pointer_create(&ma->id, &path->ptr[path->len]);
00246                                 path->len++;
00247                         }                       
00248                         return 1;
00249                 }
00250         }
00251 
00252         /* no path to a material possible */
00253         return 0;
00254 }
00255 
00256 static int buttons_context_path_bone(ButsContextPath *path)
00257 {
00258         bArmature *arm;
00259         EditBone *edbo;
00260 
00261         /* if we have an armature, get the active bone */
00262         if(buttons_context_path_data(path, OB_ARMATURE)) {
00263                 arm= path->ptr[path->len-1].data;
00264 
00265                 if(arm->edbo) {
00266                         if(arm->act_edbone) {
00267                                 edbo= arm->act_edbone;
00268                                 RNA_pointer_create(&arm->id, &RNA_EditBone, edbo, &path->ptr[path->len]);
00269                                 path->len++;
00270                                 return 1;
00271                         }
00272                 }
00273                 else {
00274                         if(arm->act_bone) {
00275                                 RNA_pointer_create(&arm->id, &RNA_Bone, arm->act_bone, &path->ptr[path->len]);
00276                                 path->len++;
00277                                 return 1;
00278                         }
00279                 }
00280         }
00281 
00282         /* no path to a bone possible */
00283         return 0;
00284 }
00285 
00286 static int buttons_context_path_pose_bone(ButsContextPath *path)
00287 {
00288         PointerRNA *ptr= &path->ptr[path->len-1];
00289 
00290         /* if we already have a (pinned) PoseBone, we're done */
00291         if(RNA_struct_is_a(ptr->type, &RNA_PoseBone)) {
00292                 return 1;
00293         }
00294 
00295         /* if we have an armature, get the active bone */
00296         if(buttons_context_path_object(path)) {
00297                 Object *ob= path->ptr[path->len-1].data;
00298                 bArmature *arm= ob->data; /* path->ptr[path->len-1].data - works too */
00299 
00300                 if(ob->type != OB_ARMATURE || arm->edbo) {
00301                         return 0;
00302                 }
00303                 else {
00304                         if(arm->act_bone) {
00305                                 bPoseChannel *pchan= get_pose_channel(ob->pose, arm->act_bone->name);
00306                                 if(pchan) {
00307                                         RNA_pointer_create(&ob->id, &RNA_PoseBone, pchan, &path->ptr[path->len]);
00308                                         path->len++;
00309                                         return 1;
00310                                 }
00311                         }
00312                 }
00313         }
00314 
00315         /* no path to a bone possible */
00316         return 0;
00317 }
00318 
00319 
00320 static int buttons_context_path_particle(ButsContextPath *path)
00321 {
00322         Object *ob;
00323         ParticleSystem *psys;
00324         PointerRNA *ptr= &path->ptr[path->len-1];
00325 
00326         /* if we already have (pinned) particle settings, we're done */
00327         if(RNA_struct_is_a(ptr->type, &RNA_ParticleSettings)) {
00328                 return 1;
00329         }
00330         /* if we have an object, get the active particle system */
00331         if(buttons_context_path_object(path)) {
00332                 ob= path->ptr[path->len-1].data;
00333 
00334                 if(ob && ob->type == OB_MESH) {
00335                         psys= psys_get_current(ob);
00336 
00337                         RNA_pointer_create(&ob->id, &RNA_ParticleSystem, psys, &path->ptr[path->len]);
00338                         path->len++;
00339                         return 1;
00340                 }
00341         }
00342 
00343         /* no path to a particle system possible */
00344         return 0;
00345 }
00346 
00347 static int buttons_context_path_brush(ButsContextPath *path)
00348 {
00349         Scene *scene;
00350         Brush *br= NULL;
00351         PointerRNA *ptr= &path->ptr[path->len-1];
00352 
00353         /* if we already have a (pinned) brush, we're done */
00354         if(RNA_struct_is_a(ptr->type, &RNA_Brush)) {
00355                 return 1;
00356         }
00357         /* if we have a scene, use the toolsettings brushes */
00358         else if(buttons_context_path_scene(path)) {
00359                 scene= path->ptr[path->len-1].data;
00360 
00361                 if(scene)
00362                         br= paint_brush(paint_get_active(scene));
00363 
00364                 if(br) {
00365                         RNA_id_pointer_create((ID *)br, &path->ptr[path->len]);
00366                         path->len++;
00367 
00368                         return 1;
00369                 }
00370         }
00371 
00372         /* no path to a brush possible */
00373         return 0;
00374 }
00375 
00376 static int buttons_context_path_texture(ButsContextPath *path)
00377 {
00378         Material *ma;
00379         Lamp *la;
00380         Brush *br;
00381         World *wo;
00382         ParticleSystem *psys;
00383         Tex *tex;
00384         PointerRNA *ptr= &path->ptr[path->len-1];
00385         int orig_len = path->len;
00386 
00387         /* if we already have a (pinned) texture, we're done */
00388         if(RNA_struct_is_a(ptr->type, &RNA_Texture)) {
00389                 return 1;
00390         }
00391         /* try brush */
00392         if((path->tex_ctx == SB_TEXC_BRUSH) && buttons_context_path_brush(path)) {
00393                 br= path->ptr[path->len-1].data;
00394                 
00395                 if(br) {
00396                         tex= give_current_brush_texture(br);
00397 
00398                         RNA_id_pointer_create(&tex->id, &path->ptr[path->len]);
00399                         path->len++;
00400                         return 1;
00401                 }
00402         }
00403         /* try world */
00404         if((path->tex_ctx == SB_TEXC_WORLD) && buttons_context_path_world(path)) {
00405                 wo= path->ptr[path->len-1].data;
00406 
00407                 if(wo && GS(wo->id.name)==ID_WO) {
00408                         tex= give_current_world_texture(wo);
00409 
00410                         RNA_id_pointer_create(&tex->id, &path->ptr[path->len]);
00411                         path->len++;
00412                         return 1;
00413                 }
00414         }
00415         /* try particles */
00416         if((path->tex_ctx == SB_TEXC_PARTICLES) && buttons_context_path_particle(path)) {
00417                 if(path->ptr[path->len-1].type == &RNA_ParticleSettings) {
00418                         ParticleSettings *part = path->ptr[path->len-1].data;
00419 
00420                         tex= give_current_particle_texture(part);
00421                         RNA_id_pointer_create(&tex->id, &path->ptr[path->len]);
00422                         path->len++;
00423                         return 1;
00424                 }
00425                 else {
00426                         psys= path->ptr[path->len-1].data;
00427 
00428                         if(psys && psys->part && GS(psys->part->id.name)==ID_PA) {
00429                                 tex= give_current_particle_texture(psys->part);
00430 
00431                                 RNA_id_pointer_create(&tex->id, &path->ptr[path->len]);
00432                                 path->len++;
00433                                 return 1;
00434                         }
00435                 }
00436         }
00437         /* try material */
00438         if(buttons_context_path_material(path, 1)) {
00439                 ma= path->ptr[path->len-1].data;
00440 
00441                 if(ma) {
00442                         tex= give_current_material_texture(ma);
00443 
00444                         RNA_id_pointer_create(&tex->id, &path->ptr[path->len]);
00445                         path->len++;
00446                         return 1;
00447                 }
00448         }
00449         /* try lamp */
00450         if(buttons_context_path_data(path, OB_LAMP)) {
00451                 la= path->ptr[path->len-1].data;
00452 
00453                 if(la) {
00454                         tex= give_current_lamp_texture(la);
00455 
00456                         RNA_id_pointer_create(&tex->id, &path->ptr[path->len]);
00457                         path->len++;
00458                         return 1;
00459                 }
00460         }
00461         /* try brushes again in case of no material, lamp, etc */
00462         path->len = orig_len;
00463         if(buttons_context_path_brush(path)) {
00464                 br= path->ptr[path->len-1].data;
00465                 
00466                 if(br) {
00467                         tex= give_current_brush_texture(br);
00468                         
00469                         RNA_id_pointer_create(&tex->id, &path->ptr[path->len]);
00470                         path->len++;
00471                         return 1;
00472                 }
00473         }
00474 
00475         /* no path to a texture possible */
00476         return 0;
00477 }
00478 
00479 
00480 static int buttons_context_path(const bContext *C, ButsContextPath *path, int mainb, int flag)
00481 {
00482         SpaceButs *sbuts= CTX_wm_space_buts(C);
00483         ID *id;
00484         int found;
00485 
00486         memset(path, 0, sizeof(*path));
00487         path->flag= flag;
00488         path->tex_ctx = sbuts->texture_context;
00489 
00490         /* if some ID datablock is pinned, set the root pointer */
00491         if(sbuts->pinid) {
00492                 id= sbuts->pinid;
00493 
00494                 RNA_id_pointer_create(id, &path->ptr[0]);
00495                 path->len++;
00496         }
00497 
00498         /* no pinned root, use scene as root */
00499         if(path->len == 0) {
00500                 id= (ID*)CTX_data_scene(C);
00501                 RNA_id_pointer_create(id, &path->ptr[0]);
00502                 path->len++;
00503         }
00504 
00505         /* now for each buttons context type, we try to construct a path,
00506          * tracing back recursively */
00507         switch(mainb) {
00508                 case BCONTEXT_SCENE:
00509                 case BCONTEXT_RENDER:
00510                         found= buttons_context_path_scene(path);
00511                         break;
00512                 case BCONTEXT_WORLD:
00513                         found= buttons_context_path_world(path);
00514                         break;
00515                 case BCONTEXT_OBJECT:
00516                 case BCONTEXT_PHYSICS:
00517                 case BCONTEXT_CONSTRAINT:
00518                         found= buttons_context_path_object(path);
00519                         break;
00520                 case BCONTEXT_MODIFIER:
00521                         found= buttons_context_path_modifier(path);
00522                         break;
00523                 case BCONTEXT_DATA:
00524                         found= buttons_context_path_data(path, -1);
00525                         break;
00526                 case BCONTEXT_PARTICLE:
00527                         found= buttons_context_path_particle(path);
00528                         break;
00529                 case BCONTEXT_MATERIAL:
00530                         found= buttons_context_path_material(path, 0);
00531                         break;
00532                 case BCONTEXT_TEXTURE:
00533                         found= buttons_context_path_texture(path);
00534                         break;
00535                 case BCONTEXT_BONE:
00536                         found= buttons_context_path_bone(path);
00537                         if(!found)
00538                                 found= buttons_context_path_data(path, OB_ARMATURE);
00539                         break;
00540                 case BCONTEXT_BONE_CONSTRAINT:
00541                         found= buttons_context_path_pose_bone(path);
00542                         break;
00543                 default:
00544                         found= 0;
00545                         break;
00546         }
00547 
00548         return found;
00549 }
00550 
00551 static int buttons_shading_context(const bContext *C, int mainb)
00552 {
00553         Object *ob= CTX_data_active_object(C);
00554 
00555         if(ELEM3(mainb, BCONTEXT_MATERIAL, BCONTEXT_WORLD, BCONTEXT_TEXTURE))
00556                 return 1;
00557         if(mainb == BCONTEXT_DATA && ob && ELEM(ob->type, OB_LAMP, OB_CAMERA))
00558                 return 1;
00559         
00560         return 0;
00561 }
00562 
00563 static int buttons_shading_new_context(const bContext *C, int flag)
00564 {
00565         Object *ob= CTX_data_active_object(C);
00566 
00567         if(flag & (1 << BCONTEXT_MATERIAL))
00568                 return BCONTEXT_MATERIAL;
00569         else if(ob && ELEM(ob->type, OB_LAMP, OB_CAMERA) && (flag & (1 << BCONTEXT_DATA)))
00570                 return BCONTEXT_DATA;
00571         else if(flag & (1 << BCONTEXT_WORLD))
00572                 return BCONTEXT_WORLD;
00573         
00574         return BCONTEXT_RENDER;
00575 }
00576 
00577 void buttons_context_compute(const bContext *C, SpaceButs *sbuts)
00578 {
00579         ButsContextPath *path;
00580         PointerRNA *ptr;
00581         int a, pflag= 0, flag= 0;
00582 
00583         if(!sbuts->path)
00584                 sbuts->path= MEM_callocN(sizeof(ButsContextPath), "ButsContextPath");
00585         
00586         path= sbuts->path;
00587         
00588         /* for each context, see if we can compute a valid path to it, if
00589          * this is the case, we know we have to display the button */
00590         for(a=0; a<BCONTEXT_TOT; a++) {
00591                 if(buttons_context_path(C, path, a, pflag)) {
00592                         flag |= (1<<a);
00593 
00594                         /* setting icon for data context */
00595                         if(a == BCONTEXT_DATA) {
00596                                 ptr= &path->ptr[path->len-1];
00597 
00598                                 if(ptr->type)
00599                                         sbuts->dataicon= RNA_struct_ui_icon(ptr->type);
00600                                 else
00601                                         sbuts->dataicon= ICON_EMPTY_DATA;
00602                         }
00603                 }
00604         }
00605 
00606         /* always try to use the tab that was explicitly
00607          * set to the user, so that once that context comes
00608          * back, the tab is activated again */
00609         sbuts->mainb= sbuts->mainbuser;
00610 
00611         /* in case something becomes invalid, change */
00612         if((flag & (1 << sbuts->mainb)) == 0) {
00613                 if(sbuts->flag & SB_SHADING_CONTEXT) {
00614                         /* try to keep showing shading related buttons */
00615                         sbuts->mainb= buttons_shading_new_context(C, flag);
00616                 }
00617                 else if(flag & BCONTEXT_OBJECT) {
00618                         sbuts->mainb= BCONTEXT_OBJECT;
00619                 }
00620                 else {
00621                         for(a=0; a<BCONTEXT_TOT; a++) {
00622                                 if(flag & (1 << a)) {
00623                                         sbuts->mainb= a;
00624                                         break;
00625                                 }
00626                         }
00627                 }
00628         }
00629 
00630         buttons_context_path(C, path, sbuts->mainb, pflag);
00631 
00632         if(!(flag & (1 << sbuts->mainb))) {
00633                 if(flag & (1 << BCONTEXT_OBJECT))
00634                         sbuts->mainb= BCONTEXT_OBJECT;
00635                 else
00636                         sbuts->mainb= BCONTEXT_SCENE;
00637         }
00638 
00639         if(buttons_shading_context(C, sbuts->mainb))
00640                 sbuts->flag |= SB_SHADING_CONTEXT;
00641         else
00642                 sbuts->flag &= ~SB_SHADING_CONTEXT;
00643 
00644         sbuts->pathflag= flag;
00645 }
00646 
00647 /************************* Context Callback ************************/
00648 
00649 const char *buttons_context_dir[] = {
00650         "world", "object", "mesh", "armature", "lattice", "curve",
00651         "meta_ball", "lamp", "camera", "material", "material_slot",
00652         "texture", "texture_slot", "bone", "edit_bone", "pose_bone", "particle_system", "particle_system_editable",
00653         "cloth", "soft_body", "fluid", "smoke", "collision", "brush", NULL};
00654 
00655 int buttons_context(const bContext *C, const char *member, bContextDataResult *result)
00656 {
00657         SpaceButs *sbuts= CTX_wm_space_buts(C);
00658         ButsContextPath *path= sbuts?sbuts->path:NULL;
00659 
00660         if(!path)
00661                 return 0;
00662 
00663         /* here we handle context, getting data from precomputed path */
00664         if(CTX_data_dir(member)) {
00665                 CTX_data_dir_set(result, buttons_context_dir);
00666                 return 1;
00667         }
00668         else if(CTX_data_equals(member, "world")) {
00669                 set_pointer_type(path, result, &RNA_World);
00670                 return 1;
00671         }
00672         else if(CTX_data_equals(member, "object")) {
00673                 set_pointer_type(path, result, &RNA_Object);
00674                 return 1;
00675         }
00676         else if(CTX_data_equals(member, "mesh")) {
00677                 set_pointer_type(path, result, &RNA_Mesh);
00678                 return 1;
00679         }
00680         else if(CTX_data_equals(member, "armature")) {
00681                 set_pointer_type(path, result, &RNA_Armature);
00682                 return 1;
00683         }
00684         else if(CTX_data_equals(member, "lattice")) {
00685                 set_pointer_type(path, result, &RNA_Lattice);
00686                 return 1;
00687         }
00688         else if(CTX_data_equals(member, "curve")) {
00689                 set_pointer_type(path, result, &RNA_Curve);
00690                 return 1;
00691         }
00692         else if(CTX_data_equals(member, "meta_ball")) {
00693                 set_pointer_type(path, result, &RNA_MetaBall);
00694                 return 1;
00695         }
00696         else if(CTX_data_equals(member, "lamp")) {
00697                 set_pointer_type(path, result, &RNA_Lamp);
00698                 return 1;
00699         }
00700         else if(CTX_data_equals(member, "camera")) {
00701                 set_pointer_type(path, result, &RNA_Camera);
00702                 return 1;
00703         }
00704         else if(CTX_data_equals(member, "material")) {
00705                 set_pointer_type(path, result, &RNA_Material);
00706                 return 1;
00707         }
00708         else if(CTX_data_equals(member, "texture")) {
00709                 set_pointer_type(path, result, &RNA_Texture);
00710                 return 1;
00711         }
00712         else if(CTX_data_equals(member, "material_slot")) {
00713                 PointerRNA *ptr= get_pointer_type(path, &RNA_Object);
00714 
00715                 if(ptr) {
00716                         Object *ob= ptr->data;
00717 
00718                         if(ob && ob->type && (ob->type<OB_LAMP) && ob->totcol)
00719                                 CTX_data_pointer_set(result, &ob->id, &RNA_MaterialSlot, ob->mat+ob->actcol-1);
00720                 }
00721 
00722                 return 1;
00723         }
00724         else if(CTX_data_equals(member, "texture_node")) {
00725                 PointerRNA *ptr;
00726 
00727                 if((ptr=get_pointer_type(path, &RNA_Material))) {
00728                         Material *ma= ptr->data;
00729 
00730                         if(ma) {
00731                                 bNode *node= give_current_material_texture_node(ma);
00732                                 CTX_data_pointer_set(result, &ma->id, &RNA_Node, node);
00733                         }
00734                 }
00735 
00736                 return 1;
00737         }
00738         else if(CTX_data_equals(member, "texture_slot")) {
00739                 PointerRNA *ptr;
00740 
00741                 if((ptr=get_pointer_type(path, &RNA_Material))) {
00742                         Material *ma= ptr->data;
00743 
00744                         /* if we have a node material, get slot from material in material node */
00745                         if(ma && ma->use_nodes && ma->nodetree) {
00746                                 /* if there's an active texture node in the node tree,
00747                                  * then that texture is in context directly, without a texture slot */
00748                                 if (give_current_material_texture_node(ma))
00749                                         return 0;
00750                                 
00751                                 ma= give_node_material(ma);
00752                                 if (ma)
00753                                         CTX_data_pointer_set(result, &ma->id, &RNA_MaterialTextureSlot, ma->mtex[(int)ma->texact]);
00754                                 else
00755                                         return 0;
00756                         } else if(ma) {
00757                                 CTX_data_pointer_set(result, &ma->id, &RNA_MaterialTextureSlot, ma->mtex[(int)ma->texact]);
00758                         }
00759                 }
00760                 else if((ptr=get_pointer_type(path, &RNA_Lamp))) {
00761                         Lamp *la= ptr->data;
00762 
00763                         if(la)
00764                                 CTX_data_pointer_set(result, &la->id, &RNA_LampTextureSlot, la->mtex[(int)la->texact]);
00765                 }
00766                 else if((ptr=get_pointer_type(path, &RNA_World))) {
00767                         World *wo= ptr->data;
00768 
00769                         if(wo)
00770                                 CTX_data_pointer_set(result, &wo->id, &RNA_WorldTextureSlot, wo->mtex[(int)wo->texact]);
00771                 }
00772                 else if((ptr=get_pointer_type(path, &RNA_Brush))) { /* how to get this into context? */
00773                         Brush *br= ptr->data;
00774 
00775                         if(br)
00776                                 CTX_data_pointer_set(result, &br->id, &RNA_BrushTextureSlot, &br->mtex);
00777                 }
00778                 else if((ptr=get_pointer_type(path, &RNA_ParticleSystem))) {
00779                         ParticleSettings *part= ((ParticleSystem *)ptr->data)->part;
00780 
00781                         if(part)
00782                                 CTX_data_pointer_set(result, &part->id, &RNA_ParticleSettingsTextureSlot, part->mtex[(int)part->texact]);
00783                 }
00784 
00785                 return 1;
00786         }
00787         else if(CTX_data_equals(member, "bone")) {
00788                 set_pointer_type(path, result, &RNA_Bone);
00789                 return 1;
00790         }
00791         else if(CTX_data_equals(member, "edit_bone")) {
00792                 set_pointer_type(path, result, &RNA_EditBone);
00793                 return 1;
00794         }
00795         else if(CTX_data_equals(member, "pose_bone")) {
00796                 set_pointer_type(path, result, &RNA_PoseBone);
00797                 return 1;
00798         }
00799         else if(CTX_data_equals(member, "particle_system")) {
00800                 set_pointer_type(path, result, &RNA_ParticleSystem);
00801                 return 1;
00802         }
00803         else if(CTX_data_equals(member, "particle_system_editable")) {
00804                 if(PE_poll((bContext*)C))
00805                         set_pointer_type(path, result, &RNA_ParticleSystem);
00806                 else
00807                         CTX_data_pointer_set(result, NULL, &RNA_ParticleSystem, NULL);
00808                 return 1;
00809         }       
00810         else if(CTX_data_equals(member, "cloth")) {
00811                 PointerRNA *ptr= get_pointer_type(path, &RNA_Object);
00812 
00813                 if(ptr && ptr->data) {
00814                         Object *ob= ptr->data;
00815                         ModifierData *md= modifiers_findByType(ob, eModifierType_Cloth);
00816                         CTX_data_pointer_set(result, &ob->id, &RNA_ClothModifier, md);
00817                         return 1;
00818                 }
00819         }
00820         else if(CTX_data_equals(member, "soft_body")) {
00821                 PointerRNA *ptr= get_pointer_type(path, &RNA_Object);
00822 
00823                 if(ptr && ptr->data) {
00824                         Object *ob= ptr->data;
00825                         ModifierData *md= modifiers_findByType(ob, eModifierType_Softbody);
00826                         CTX_data_pointer_set(result, &ob->id, &RNA_SoftBodyModifier, md);
00827                         return 1;
00828                 }
00829         }
00830         else if(CTX_data_equals(member, "fluid")) {
00831                 PointerRNA *ptr= get_pointer_type(path, &RNA_Object);
00832 
00833                 if(ptr && ptr->data) {
00834                         Object *ob= ptr->data;
00835                         ModifierData *md= modifiers_findByType(ob, eModifierType_Fluidsim);
00836                         CTX_data_pointer_set(result, &ob->id, &RNA_FluidSimulationModifier, md);
00837                         return 1;
00838                 }
00839         }
00840         
00841         else if(CTX_data_equals(member, "smoke")) {
00842                 PointerRNA *ptr= get_pointer_type(path, &RNA_Object);
00843 
00844                 if(ptr && ptr->data) {
00845                         Object *ob= ptr->data;
00846                         ModifierData *md= modifiers_findByType(ob, eModifierType_Smoke);
00847                         CTX_data_pointer_set(result, &ob->id, &RNA_SmokeModifier, md);
00848                         return 1;
00849                 }
00850         }
00851         else if(CTX_data_equals(member, "collision")) {
00852                 PointerRNA *ptr= get_pointer_type(path, &RNA_Object);
00853 
00854                 if(ptr && ptr->data) {
00855                         Object *ob= ptr->data;
00856                         ModifierData *md= modifiers_findByType(ob, eModifierType_Collision);
00857                         CTX_data_pointer_set(result, &ob->id, &RNA_CollisionModifier, md);
00858                         return 1;
00859                 }
00860         }
00861         else if(CTX_data_equals(member, "brush")) {
00862                 set_pointer_type(path, result, &RNA_Brush);
00863                 return 1;
00864         }
00865         else {
00866                 return 0; /* not found */
00867         }
00868 
00869         return -1; /* found but not available */
00870 }
00871 
00872 /************************* Drawing the Path ************************/
00873 
00874 static void pin_cb(bContext *C, void *UNUSED(arg1), void *UNUSED(arg2))
00875 {
00876         SpaceButs *sbuts= CTX_wm_space_buts(C);
00877 
00878         if(sbuts->flag & SB_PIN_CONTEXT) {
00879                 sbuts->pinid= buttons_context_id_path(C);
00880         }
00881         else
00882                 sbuts->pinid= NULL;
00883         
00884         ED_area_tag_redraw(CTX_wm_area(C));
00885 }
00886 
00887 void buttons_context_draw(const bContext *C, uiLayout *layout)
00888 {
00889         SpaceButs *sbuts= CTX_wm_space_buts(C);
00890         ButsContextPath *path= sbuts->path;
00891         uiLayout *row;
00892         uiBlock *block;
00893         uiBut *but;
00894         PointerRNA *ptr;
00895         char namebuf[128], *name;
00896         int a, icon;
00897 
00898         if(!path)
00899                 return;
00900 
00901         row= uiLayoutRow(layout, 1);
00902         uiLayoutSetAlignment(row, UI_LAYOUT_ALIGN_LEFT);
00903 
00904         block= uiLayoutGetBlock(row);
00905         uiBlockSetEmboss(block, UI_EMBOSSN);
00906         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");
00907         uiButSetFunc(but, pin_cb, NULL, NULL);
00908 
00909         for(a=0; a<path->len; a++) {
00910                 ptr= &path->ptr[a];
00911 
00912                 if(a != 0)
00913                         uiItemL(row, "", VICO_SMALL_TRI_RIGHT_VEC);
00914 
00915                 if(ptr->data) {
00916                         icon= RNA_struct_ui_icon(ptr->type);
00917                         name= RNA_struct_name_get_alloc(ptr, namebuf, sizeof(namebuf));
00918 
00919                         if(name) {
00920                                 if(!ELEM(sbuts->mainb, BCONTEXT_RENDER, BCONTEXT_SCENE) && ptr->type == &RNA_Scene)
00921                                         uiItemLDrag(row, ptr, "", icon); /* save some space */
00922                                 else
00923                                         uiItemLDrag(row, ptr, name, icon);
00924                                                                  
00925                                 if(name != namebuf)
00926                                         MEM_freeN(name);
00927                         }
00928                         else
00929                                 uiItemL(row, "", icon);
00930                 }
00931         }
00932 }
00933 
00934 static void buttons_panel_context(const bContext *C, Panel *pa)
00935 {
00936         buttons_context_draw(C, pa->layout);
00937 }
00938 
00939 void buttons_context_register(ARegionType *art)
00940 {
00941         PanelType *pt;
00942 
00943         pt= MEM_callocN(sizeof(PanelType), "spacetype buttons panel context");
00944         strcpy(pt->idname, "BUTTONS_PT_context");
00945         strcpy(pt->label, "Context");
00946         pt->draw= buttons_panel_context;
00947         pt->flag= PNL_NO_HEADER;
00948         BLI_addtail(&art->paneltypes, pt);
00949 }
00950 
00951 ID *buttons_context_id_path(const bContext *C)
00952 {
00953         SpaceButs *sbuts= CTX_wm_space_buts(C);
00954         ButsContextPath *path= sbuts->path;
00955         PointerRNA *ptr;
00956         int a;
00957 
00958         if(path->len) {
00959                 for(a=path->len-1; a>=0; a--) {
00960                         ptr= &path->ptr[a];
00961 
00962                         /* pin particle settings instead of system, since only settings are an idblock*/
00963                         if(sbuts->mainb == BCONTEXT_PARTICLE && sbuts->flag & SB_PIN_CONTEXT) {
00964                                 if(ptr->type == &RNA_ParticleSystem && ptr->data) {
00965                                         ParticleSystem *psys = (ParticleSystem *)ptr->data;
00966                                         return &psys->part->id;
00967                                 }
00968                         }
00969 
00970                         if(ptr->id.data) {
00971                                 return ptr->id.data;
00972                                 break;
00973                         }
00974                 }
00975         }
00976 
00977         return NULL;
00978 }