|
Blender
V2.59
|
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 }