2 * ***** BEGIN GPL LICENSE BLOCK *****
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version 2
7 * of the License, or (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software Foundation,
16 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18 * The Original Code is Copyright (C) 2009 Blender Foundation.
19 * All rights reserved.
21 * Contributor(s): Blender Foundation
23 * ***** END GPL LICENSE BLOCK *****
26 /** \file blender/editors/space_buttons/buttons_context.c
34 #include "MEM_guardedalloc.h"
36 #include "BLI_listbase.h"
37 #include "BLI_utildefines.h"
39 #include "BLT_translation.h"
41 #include "DNA_armature_types.h"
42 #include "DNA_lamp_types.h"
43 #include "DNA_material_types.h"
44 #include "DNA_node_types.h"
45 #include "DNA_scene_types.h"
46 #include "DNA_world_types.h"
47 #include "DNA_brush_types.h"
48 #include "DNA_linestyle_types.h"
50 #include "BKE_context.h"
51 #include "BKE_action.h"
52 #include "BKE_material.h"
53 #include "BKE_modifier.h"
54 #include "BKE_paint.h"
55 #include "BKE_particle.h"
56 #include "BKE_screen.h"
57 #include "BKE_texture.h"
58 #include "BKE_linestyle.h"
60 #include "RNA_access.h"
62 #include "ED_buttons.h"
63 #include "ED_armature.h"
64 #include "ED_screen.h"
65 #include "ED_physics.h"
67 #include "UI_interface.h"
68 #include "UI_resources.h"
70 #include "buttons_intern.h" // own include
72 static int set_pointer_type(ButsContextPath *path, bContextDataResult *result, StructRNA *type)
77 for (a = 0; a < path->len; a++) {
80 if (RNA_struct_is_a(ptr->type, type)) {
81 CTX_data_pointer_set(result, ptr->id.data, ptr->type, ptr->data);
89 static PointerRNA *get_pointer_type(ButsContextPath *path, StructRNA *type)
94 for (a = 0; a < path->len; a++) {
97 if (RNA_struct_is_a(ptr->type, type))
104 /************************* Creating the Path ************************/
106 static int buttons_context_path_scene(ButsContextPath *path)
108 PointerRNA *ptr = &path->ptr[path->len - 1];
110 /* this one just verifies */
111 return RNA_struct_is_a(ptr->type, &RNA_Scene);
114 /* note: this function can return 1 without adding a world to the path
115 * so the buttons stay visible, but be sure to check the ID type if a ID_WO */
116 static int buttons_context_path_world(ButsContextPath *path)
120 PointerRNA *ptr = &path->ptr[path->len - 1];
122 /* if we already have a (pinned) world, we're done */
123 if (RNA_struct_is_a(ptr->type, &RNA_World)) {
126 /* if we have a scene, use the scene's world */
127 else if (buttons_context_path_scene(path)) {
128 scene = path->ptr[path->len - 1].data;
129 world = scene->world;
132 RNA_id_pointer_create(&scene->world->id, &path->ptr[path->len]);
141 /* no path to a world possible */
145 static int buttons_context_path_linestyle(ButsContextPath *path)
148 FreestyleLineStyle *linestyle;
149 PointerRNA *ptr = &path->ptr[path->len - 1];
151 /* if we already have a (pinned) linestyle, we're done */
152 if (RNA_struct_is_a(ptr->type, &RNA_FreestyleLineStyle)) {
155 /* if we have a scene, use the lineset's linestyle */
156 else if (buttons_context_path_scene(path)) {
157 scene = path->ptr[path->len - 1].data;
158 linestyle = BKE_linestyle_active_from_scene(scene);
160 RNA_id_pointer_create(&linestyle->id, &path->ptr[path->len]);
166 /* no path to a linestyle possible */
170 static int buttons_context_path_object(ButsContextPath *path)
174 PointerRNA *ptr = &path->ptr[path->len - 1];
176 /* if we already have a (pinned) object, we're done */
177 if (RNA_struct_is_a(ptr->type, &RNA_Object)) {
180 /* if we have a scene, use the scene's active object */
181 else if (buttons_context_path_scene(path)) {
182 scene = path->ptr[path->len - 1].data;
183 ob = (scene->basact) ? scene->basact->object : NULL;
186 RNA_id_pointer_create(&ob->id, &path->ptr[path->len]);
193 /* no path to a object possible */
197 static int buttons_context_path_data(ButsContextPath *path, int type)
200 PointerRNA *ptr = &path->ptr[path->len - 1];
202 /* if we already have a data, we're done */
203 if (RNA_struct_is_a(ptr->type, &RNA_Mesh) && (type == -1 || type == OB_MESH)) return 1;
204 else if (RNA_struct_is_a(ptr->type, &RNA_Curve) && (type == -1 || ELEM(type, OB_CURVE, OB_SURF, OB_FONT))) return 1;
205 else if (RNA_struct_is_a(ptr->type, &RNA_Armature) && (type == -1 || type == OB_ARMATURE)) return 1;
206 else if (RNA_struct_is_a(ptr->type, &RNA_MetaBall) && (type == -1 || type == OB_MBALL)) return 1;
207 else if (RNA_struct_is_a(ptr->type, &RNA_Lattice) && (type == -1 || type == OB_LATTICE)) return 1;
208 else if (RNA_struct_is_a(ptr->type, &RNA_Camera) && (type == -1 || type == OB_CAMERA)) return 1;
209 else if (RNA_struct_is_a(ptr->type, &RNA_Lamp) && (type == -1 || type == OB_LAMP)) return 1;
210 else if (RNA_struct_is_a(ptr->type, &RNA_Speaker) && (type == -1 || type == OB_SPEAKER)) return 1;
211 /* try to get an object in the path, no pinning supported here */
212 else if (buttons_context_path_object(path)) {
213 ob = path->ptr[path->len - 1].data;
215 if (ob && (type == -1 || type == ob->type)) {
216 RNA_id_pointer_create(ob->data, &path->ptr[path->len]);
223 /* no path to data possible */
227 static int buttons_context_path_modifier(ButsContextPath *path)
231 if (buttons_context_path_object(path)) {
232 ob = path->ptr[path->len - 1].data;
234 if (ob && ELEM(ob->type, OB_MESH, OB_CURVE, OB_FONT, OB_SURF, OB_LATTICE))
241 static int buttons_context_path_material(ButsContextPath *path, bool for_texture, bool new_shading)
244 PointerRNA *ptr = &path->ptr[path->len - 1];
247 /* if we already have a (pinned) material, we're done */
248 if (RNA_struct_is_a(ptr->type, &RNA_Material)) {
251 /* if we have an object, use the object material slot */
252 else if (buttons_context_path_object(path)) {
253 ob = path->ptr[path->len - 1].data;
255 if (ob && OB_TYPE_SUPPORT_MATERIAL(ob->type)) {
256 ma = give_current_material(ob, ob->actcol);
257 RNA_id_pointer_create(&ma->id, &path->ptr[path->len]);
260 if (for_texture && give_current_material_texture_node(ma))
264 /* Only try to get mat from node in case of old shading system (see T40331). */
265 ma = give_node_material(ma);
267 RNA_id_pointer_create(&ma->id, &path->ptr[path->len]);
275 /* no path to a material possible */
279 static int buttons_context_path_bone(ButsContextPath *path)
284 /* if we have an armature, get the active bone */
285 if (buttons_context_path_data(path, OB_ARMATURE)) {
286 arm = path->ptr[path->len - 1].data;
289 if (arm->act_edbone) {
290 edbo = arm->act_edbone;
291 RNA_pointer_create(&arm->id, &RNA_EditBone, edbo, &path->ptr[path->len]);
298 RNA_pointer_create(&arm->id, &RNA_Bone, arm->act_bone, &path->ptr[path->len]);
305 /* no path to a bone possible */
309 static int buttons_context_path_pose_bone(ButsContextPath *path)
311 PointerRNA *ptr = &path->ptr[path->len - 1];
313 /* if we already have a (pinned) PoseBone, we're done */
314 if (RNA_struct_is_a(ptr->type, &RNA_PoseBone)) {
318 /* if we have an armature, get the active bone */
319 if (buttons_context_path_object(path)) {
320 Object *ob = path->ptr[path->len - 1].data;
321 bArmature *arm = ob->data; /* path->ptr[path->len-1].data - works too */
323 if (ob->type != OB_ARMATURE || arm->edbo) {
328 bPoseChannel *pchan = BKE_pose_channel_find_name(ob->pose, arm->act_bone->name);
330 RNA_pointer_create(&ob->id, &RNA_PoseBone, pchan, &path->ptr[path->len]);
338 /* no path to a bone possible */
343 static int buttons_context_path_particle(ButsContextPath *path)
346 ParticleSystem *psys;
347 PointerRNA *ptr = &path->ptr[path->len - 1];
349 /* if we already have (pinned) particle settings, we're done */
350 if (RNA_struct_is_a(ptr->type, &RNA_ParticleSettings)) {
353 /* if we have an object, get the active particle system */
354 if (buttons_context_path_object(path)) {
355 ob = path->ptr[path->len - 1].data;
357 if (ob && ob->type == OB_MESH) {
358 psys = psys_get_current(ob);
360 RNA_pointer_create(&ob->id, &RNA_ParticleSystem, psys, &path->ptr[path->len]);
366 /* no path to a particle system possible */
370 static int buttons_context_path_brush(ButsContextPath *path)
374 PointerRNA *ptr = &path->ptr[path->len - 1];
376 /* if we already have a (pinned) brush, we're done */
377 if (RNA_struct_is_a(ptr->type, &RNA_Brush)) {
380 /* if we have a scene, use the toolsettings brushes */
381 else if (buttons_context_path_scene(path)) {
382 scene = path->ptr[path->len - 1].data;
385 br = BKE_paint_brush(BKE_paint_get_active(scene));
388 RNA_id_pointer_create((ID *)br, &path->ptr[path->len]);
395 /* no path to a brush possible */
399 static int buttons_context_path_texture(ButsContextPath *path, ButsContextTexture *ct)
402 /* new shading system */
403 PointerRNA *ptr = &path->ptr[path->len - 1];
406 /* if we already have a (pinned) texture, we're done */
407 if (RNA_struct_is_a(ptr->type, &RNA_Texture))
416 if (GS(id->name) == ID_BR)
417 buttons_context_path_brush(path);
418 else if (GS(id->name) == ID_MA)
419 buttons_context_path_material(path, false, true);
420 else if (GS(id->name) == ID_WO)
421 buttons_context_path_world(path);
422 else if (GS(id->name) == ID_LA)
423 buttons_context_path_data(path, OB_LAMP);
424 else if (GS(id->name) == ID_PA)
425 buttons_context_path_particle(path);
426 else if (GS(id->name) == ID_OB)
427 buttons_context_path_object(path);
428 else if (GS(id->name) == ID_LS)
429 buttons_context_path_linestyle(path);
433 RNA_id_pointer_create(&ct->texture->id, &path->ptr[path->len]);
440 /* old shading system */
444 ParticleSystem *psys;
445 FreestyleLineStyle *ls;
447 PointerRNA *ptr = &path->ptr[path->len - 1];
449 /* if we already have a (pinned) texture, we're done */
450 if (RNA_struct_is_a(ptr->type, &RNA_Texture)) {
454 else if ((path->tex_ctx == SB_TEXC_WORLD) && buttons_context_path_world(path)) {
455 wo = path->ptr[path->len - 1].data;
457 if (wo && GS(wo->id.name) == ID_WO) {
458 tex = give_current_world_texture(wo);
460 RNA_id_pointer_create(&tex->id, &path->ptr[path->len]);
466 else if ((path->tex_ctx == SB_TEXC_PARTICLES) && buttons_context_path_particle(path)) {
467 if (path->ptr[path->len - 1].type == &RNA_ParticleSettings) {
468 ParticleSettings *part = path->ptr[path->len - 1].data;
470 tex = give_current_particle_texture(part);
471 RNA_id_pointer_create(&tex->id, &path->ptr[path->len]);
476 psys = path->ptr[path->len - 1].data;
478 if (psys && psys->part && GS(psys->part->id.name) == ID_PA) {
479 tex = give_current_particle_texture(psys->part);
481 RNA_id_pointer_create(&tex->id, &path->ptr[path->len]);
488 else if ((path->tex_ctx == SB_TEXC_MATERIAL) && buttons_context_path_material(path, true, false)) {
489 ma = path->ptr[path->len - 1].data;
492 tex = give_current_material_texture(ma);
494 RNA_id_pointer_create(&tex->id, &path->ptr[path->len]);
500 else if ((path->tex_ctx == SB_TEXC_LAMP) && buttons_context_path_data(path, OB_LAMP)) {
501 la = path->ptr[path->len - 1].data;
504 tex = give_current_lamp_texture(la);
506 RNA_id_pointer_create(&tex->id, &path->ptr[path->len]);
512 else if ((path->tex_ctx == SB_TEXC_LINESTYLE) && buttons_context_path_linestyle(path)) {
513 ls = path->ptr[path->len - 1].data;
516 tex = give_current_linestyle_texture(ls);
518 RNA_id_pointer_create(&tex->id, &path->ptr[path->len]);
525 /* no path to a texture possible */
529 #ifdef WITH_FREESTYLE
530 static bool buttons_context_linestyle_pinnable(const bContext *C)
532 Scene *scene = CTX_data_scene(C);
533 SceneRenderLayer *actsrl;
534 FreestyleConfig *config;
537 /* if Freestyle is disabled in the scene */
538 if ((scene->r.mode & R_EDGE_FRS) == 0) {
541 /* if Freestyle is not in the Parameter Editor mode */
542 actsrl = BLI_findlink(&scene->r.layers, scene->r.actlay);
543 config = &actsrl->freestyleConfig;
544 if (config->mode != FREESTYLE_CONTROL_EDITOR_MODE) {
547 /* if the scene has already been pinned */
548 sbuts = CTX_wm_space_buts(C);
549 if (sbuts->pinid && sbuts->pinid == &scene->id) {
556 static int buttons_context_path(const bContext *C, ButsContextPath *path, int mainb, int flag)
558 SpaceButs *sbuts = CTX_wm_space_buts(C);
562 memset(path, 0, sizeof(*path));
564 path->tex_ctx = sbuts->texture_context;
566 /* if some ID datablock is pinned, set the root pointer */
570 RNA_id_pointer_create(id, &path->ptr[0]);
574 /* no pinned root, use scene as root */
575 if (path->len == 0) {
576 id = (ID *)CTX_data_scene(C);
577 RNA_id_pointer_create(id, &path->ptr[0]);
581 /* now for each buttons context type, we try to construct a path,
582 * tracing back recursively */
585 case BCONTEXT_RENDER:
586 found = buttons_context_path_scene(path);
588 case BCONTEXT_RENDER_LAYER:
589 #ifdef WITH_FREESTYLE
590 if (buttons_context_linestyle_pinnable(C)) {
591 found = buttons_context_path_linestyle(path);
597 found = buttons_context_path_scene(path);
600 found = buttons_context_path_world(path);
602 case BCONTEXT_OBJECT:
603 case BCONTEXT_PHYSICS:
604 case BCONTEXT_CONSTRAINT:
605 found = buttons_context_path_object(path);
607 case BCONTEXT_MODIFIER:
608 found = buttons_context_path_modifier(path);
611 found = buttons_context_path_data(path, -1);
613 case BCONTEXT_PARTICLE:
614 found = buttons_context_path_particle(path);
616 case BCONTEXT_MATERIAL:
617 found = buttons_context_path_material(path, false, (sbuts->texuser != NULL));
619 case BCONTEXT_TEXTURE:
620 found = buttons_context_path_texture(path, sbuts->texuser);
623 found = buttons_context_path_bone(path);
625 found = buttons_context_path_data(path, OB_ARMATURE);
627 case BCONTEXT_BONE_CONSTRAINT:
628 found = buttons_context_path_pose_bone(path);
638 static int buttons_shading_context(const bContext *C, int mainb)
640 Object *ob = CTX_data_active_object(C);
642 if (ELEM(mainb, BCONTEXT_MATERIAL, BCONTEXT_WORLD, BCONTEXT_TEXTURE))
644 if (mainb == BCONTEXT_DATA && ob && ELEM(ob->type, OB_LAMP, OB_CAMERA))
650 static int buttons_shading_new_context(const bContext *C, int flag)
652 Object *ob = CTX_data_active_object(C);
654 if (flag & (1 << BCONTEXT_MATERIAL))
655 return BCONTEXT_MATERIAL;
656 else if (ob && ELEM(ob->type, OB_LAMP, OB_CAMERA) && (flag & (1 << BCONTEXT_DATA)))
657 return BCONTEXT_DATA;
658 else if (flag & (1 << BCONTEXT_WORLD))
659 return BCONTEXT_WORLD;
661 return BCONTEXT_RENDER;
664 void buttons_context_compute(const bContext *C, SpaceButs *sbuts)
666 ButsContextPath *path;
668 int a, pflag = 0, flag = 0;
671 sbuts->path = MEM_callocN(sizeof(ButsContextPath), "ButsContextPath");
675 /* We need to set Scene path now! Else, buttons_texture_context_compute() might not get a valid scene. */
676 buttons_context_path(C, path, BCONTEXT_SCENE, pflag);
678 buttons_texture_context_compute(C, sbuts);
680 /* for each context, see if we can compute a valid path to it, if
681 * this is the case, we know we have to display the button */
682 for (a = 0; a < BCONTEXT_TOT; a++) {
683 if (buttons_context_path(C, path, a, pflag)) {
686 /* setting icon for data context */
687 if (a == BCONTEXT_DATA) {
688 ptr = &path->ptr[path->len - 1];
691 sbuts->dataicon = RNA_struct_ui_icon(ptr->type);
693 sbuts->dataicon = ICON_EMPTY_DATA;
698 /* always try to use the tab that was explicitly
699 * set to the user, so that once that context comes
700 * back, the tab is activated again */
701 sbuts->mainb = sbuts->mainbuser;
703 /* in case something becomes invalid, change */
704 if ((flag & (1 << sbuts->mainb)) == 0) {
705 if (sbuts->flag & SB_SHADING_CONTEXT) {
706 /* try to keep showing shading related buttons */
707 sbuts->mainb = buttons_shading_new_context(C, flag);
709 else if (flag & BCONTEXT_OBJECT) {
710 sbuts->mainb = BCONTEXT_OBJECT;
713 for (a = 0; a < BCONTEXT_TOT; a++) {
714 if (flag & (1 << a)) {
722 buttons_context_path(C, path, sbuts->mainb, pflag);
724 if (!(flag & (1 << sbuts->mainb))) {
725 if (flag & (1 << BCONTEXT_OBJECT))
726 sbuts->mainb = BCONTEXT_OBJECT;
728 sbuts->mainb = BCONTEXT_SCENE;
731 if (buttons_shading_context(C, sbuts->mainb))
732 sbuts->flag |= SB_SHADING_CONTEXT;
734 sbuts->flag &= ~SB_SHADING_CONTEXT;
736 sbuts->pathflag = flag;
739 /************************* Context Callback ************************/
741 const char *buttons_context_dir[] = {
742 "texture_slot", "scene", "world", "object", "mesh", "armature", "lattice", "curve",
743 "meta_ball", "lamp", "speaker", "camera", "material", "material_slot",
744 "texture", "texture_user", "texture_user_property", "bone", "edit_bone",
745 "pose_bone", "particle_system", "particle_system_editable", "particle_settings",
746 "cloth", "soft_body", "fluid", "smoke", "collision", "brush", "dynamic_paint",
750 int buttons_context(const bContext *C, const char *member, bContextDataResult *result)
752 SpaceButs *sbuts = CTX_wm_space_buts(C);
753 ButsContextPath *path = sbuts ? sbuts->path : NULL;
758 /* here we handle context, getting data from precomputed path */
759 if (CTX_data_dir(member)) {
760 /* in case of new shading system we skip texture_slot, complex python
761 * UI script logic depends on checking if this is available */
763 CTX_data_dir_set(result, buttons_context_dir + 1);
765 CTX_data_dir_set(result, buttons_context_dir);
768 else if (CTX_data_equals(member, "scene")) {
769 /* Do not return one here if scene not found in path, in this case we want to get default context scene! */
770 return set_pointer_type(path, result, &RNA_Scene);
772 else if (CTX_data_equals(member, "world")) {
773 set_pointer_type(path, result, &RNA_World);
776 else if (CTX_data_equals(member, "object")) {
777 set_pointer_type(path, result, &RNA_Object);
780 else if (CTX_data_equals(member, "mesh")) {
781 set_pointer_type(path, result, &RNA_Mesh);
784 else if (CTX_data_equals(member, "armature")) {
785 set_pointer_type(path, result, &RNA_Armature);
788 else if (CTX_data_equals(member, "lattice")) {
789 set_pointer_type(path, result, &RNA_Lattice);
792 else if (CTX_data_equals(member, "curve")) {
793 set_pointer_type(path, result, &RNA_Curve);
796 else if (CTX_data_equals(member, "meta_ball")) {
797 set_pointer_type(path, result, &RNA_MetaBall);
800 else if (CTX_data_equals(member, "lamp")) {
801 set_pointer_type(path, result, &RNA_Lamp);
804 else if (CTX_data_equals(member, "camera")) {
805 set_pointer_type(path, result, &RNA_Camera);
808 else if (CTX_data_equals(member, "speaker")) {
809 set_pointer_type(path, result, &RNA_Speaker);
812 else if (CTX_data_equals(member, "material")) {
813 set_pointer_type(path, result, &RNA_Material);
816 else if (CTX_data_equals(member, "texture")) {
817 ButsContextTexture *ct = sbuts->texuser;
820 /* new shading system */
821 CTX_data_pointer_set(result, &ct->texture->id, &RNA_Texture, ct->texture);
824 /* old shading system */
825 set_pointer_type(path, result, &RNA_Texture);
830 else if (CTX_data_equals(member, "material_slot")) {
831 PointerRNA *ptr = get_pointer_type(path, &RNA_Object);
834 Object *ob = ptr->data;
836 if (ob && OB_TYPE_SUPPORT_MATERIAL(ob->type) && ob->totcol) {
837 /* a valid actcol isn't ensured [#27526] */
838 int matnr = ob->actcol - 1;
839 if (matnr < 0) matnr = 0;
840 CTX_data_pointer_set(result, &ob->id, &RNA_MaterialSlot, &ob->mat[matnr]);
846 else if (CTX_data_equals(member, "texture_user")) {
847 ButsContextTexture *ct = sbuts->texuser;
850 return -1; /* old shading system (found but not available) */
852 if (ct->user && ct->user->ptr.data) {
853 ButsTextureUser *user = ct->user;
854 CTX_data_pointer_set(result, user->ptr.id.data, user->ptr.type, user->ptr.data);
859 else if (CTX_data_equals(member, "texture_user_property")) {
860 ButsContextTexture *ct = sbuts->texuser;
863 return -1; /* old shading system (found but not available) */
865 if (ct->user && ct->user->ptr.data) {
866 ButsTextureUser *user = ct->user;
867 CTX_data_pointer_set(result, NULL, &RNA_Property, user->prop);
872 else if (CTX_data_equals(member, "texture_node")) {
873 ButsContextTexture *ct = sbuts->texuser;
876 /* new shading system */
877 if (ct->user && ct->user->node) {
878 CTX_data_pointer_set(result, &ct->user->ntree->id, &RNA_Node, ct->user->node);
884 /* old shading system */
887 if ((ptr = get_pointer_type(path, &RNA_Material))) {
888 Material *ma = ptr->data;
891 bNode *node = give_current_material_texture_node(ma);
892 CTX_data_pointer_set(result, &ma->nodetree->id, &RNA_Node, node);
899 else if (CTX_data_equals(member, "texture_slot")) {
900 ButsContextTexture *ct = sbuts->texuser;
903 /* Particles slots are used in both old and new textures handling. */
904 if ((ptr = get_pointer_type(path, &RNA_ParticleSystem))) {
905 ParticleSettings *part = ((ParticleSystem *)ptr->data)->part;
908 CTX_data_pointer_set(result, &part->id, &RNA_ParticleSettingsTextureSlot, part->mtex[(int)part->texact]);
911 return 0; /* new shading system */
913 else if ((ptr = get_pointer_type(path, &RNA_Material))) {
914 Material *ma = ptr->data;
916 /* if we have a node material, get slot from material in material node */
917 if (ma && ma->use_nodes && ma->nodetree) {
918 /* if there's an active texture node in the node tree,
919 * then that texture is in context directly, without a texture slot */
920 if (give_current_material_texture_node(ma))
923 ma = give_node_material(ma);
925 CTX_data_pointer_set(result, &ma->id, &RNA_MaterialTextureSlot, ma->mtex[(int)ma->texact]);
930 CTX_data_pointer_set(result, &ma->id, &RNA_MaterialTextureSlot, ma->mtex[(int)ma->texact]);
933 else if ((ptr = get_pointer_type(path, &RNA_Lamp))) {
934 Lamp *la = ptr->data;
937 CTX_data_pointer_set(result, &la->id, &RNA_LampTextureSlot, la->mtex[(int)la->texact]);
939 else if ((ptr = get_pointer_type(path, &RNA_World))) {
940 World *wo = ptr->data;
943 CTX_data_pointer_set(result, &wo->id, &RNA_WorldTextureSlot, wo->mtex[(int)wo->texact]);
945 else if ((ptr = get_pointer_type(path, &RNA_FreestyleLineStyle))) {
946 FreestyleLineStyle *ls = ptr->data;
949 CTX_data_pointer_set(result, &ls->id, &RNA_LineStyleTextureSlot, ls->mtex[(int)ls->texact]);
954 else if (CTX_data_equals(member, "bone")) {
955 set_pointer_type(path, result, &RNA_Bone);
958 else if (CTX_data_equals(member, "edit_bone")) {
959 set_pointer_type(path, result, &RNA_EditBone);
962 else if (CTX_data_equals(member, "pose_bone")) {
963 set_pointer_type(path, result, &RNA_PoseBone);
966 else if (CTX_data_equals(member, "particle_system")) {
967 set_pointer_type(path, result, &RNA_ParticleSystem);
970 else if (CTX_data_equals(member, "particle_system_editable")) {
971 if (PE_poll((bContext *)C))
972 set_pointer_type(path, result, &RNA_ParticleSystem);
974 CTX_data_pointer_set(result, NULL, &RNA_ParticleSystem, NULL);
977 else if (CTX_data_equals(member, "particle_settings")) {
978 /* only available when pinned */
979 PointerRNA *ptr = get_pointer_type(path, &RNA_ParticleSettings);
981 if (ptr && ptr->data) {
982 CTX_data_pointer_set(result, ptr->id.data, &RNA_ParticleSettings, ptr->data);
986 /* get settings from active particle system instead */
987 ptr = get_pointer_type(path, &RNA_ParticleSystem);
989 if (ptr && ptr->data) {
990 ParticleSettings *part = ((ParticleSystem *)ptr->data)->part;
991 CTX_data_pointer_set(result, ptr->id.data, &RNA_ParticleSettings, part);
995 set_pointer_type(path, result, &RNA_ParticleSettings);
998 else if (CTX_data_equals(member, "cloth")) {
999 PointerRNA *ptr = get_pointer_type(path, &RNA_Object);
1001 if (ptr && ptr->data) {
1002 Object *ob = ptr->data;
1003 ModifierData *md = modifiers_findByType(ob, eModifierType_Cloth);
1004 CTX_data_pointer_set(result, &ob->id, &RNA_ClothModifier, md);
1008 else if (CTX_data_equals(member, "soft_body")) {
1009 PointerRNA *ptr = get_pointer_type(path, &RNA_Object);
1011 if (ptr && ptr->data) {
1012 Object *ob = ptr->data;
1013 ModifierData *md = modifiers_findByType(ob, eModifierType_Softbody);
1014 CTX_data_pointer_set(result, &ob->id, &RNA_SoftBodyModifier, md);
1018 else if (CTX_data_equals(member, "fluid")) {
1019 PointerRNA *ptr = get_pointer_type(path, &RNA_Object);
1021 if (ptr && ptr->data) {
1022 Object *ob = ptr->data;
1023 ModifierData *md = modifiers_findByType(ob, eModifierType_Fluidsim);
1024 CTX_data_pointer_set(result, &ob->id, &RNA_FluidSimulationModifier, md);
1029 else if (CTX_data_equals(member, "smoke")) {
1030 PointerRNA *ptr = get_pointer_type(path, &RNA_Object);
1032 if (ptr && ptr->data) {
1033 Object *ob = ptr->data;
1034 ModifierData *md = modifiers_findByType(ob, eModifierType_Smoke);
1035 CTX_data_pointer_set(result, &ob->id, &RNA_SmokeModifier, md);
1039 else if (CTX_data_equals(member, "collision")) {
1040 PointerRNA *ptr = get_pointer_type(path, &RNA_Object);
1042 if (ptr && ptr->data) {
1043 Object *ob = ptr->data;
1044 ModifierData *md = modifiers_findByType(ob, eModifierType_Collision);
1045 CTX_data_pointer_set(result, &ob->id, &RNA_CollisionModifier, md);
1049 else if (CTX_data_equals(member, "brush")) {
1050 set_pointer_type(path, result, &RNA_Brush);
1053 else if (CTX_data_equals(member, "dynamic_paint")) {
1054 PointerRNA *ptr = get_pointer_type(path, &RNA_Object);
1056 if (ptr && ptr->data) {
1057 Object *ob = ptr->data;
1058 ModifierData *md = modifiers_findByType(ob, eModifierType_DynamicPaint);
1059 CTX_data_pointer_set(result, &ob->id, &RNA_DynamicPaintModifier, md);
1063 else if (CTX_data_equals(member, "line_style")) {
1064 set_pointer_type(path, result, &RNA_FreestyleLineStyle);
1068 return 0; /* not found */
1071 return -1; /* found but not available */
1074 /************************* Drawing the Path ************************/
1076 static void pin_cb(bContext *C, void *UNUSED(arg1), void *UNUSED(arg2))
1078 SpaceButs *sbuts = CTX_wm_space_buts(C);
1080 if (sbuts->flag & SB_PIN_CONTEXT) {
1081 sbuts->pinid = buttons_context_id_path(C);
1084 sbuts->pinid = NULL;
1086 ED_area_tag_redraw(CTX_wm_area(C));
1089 void buttons_context_draw(const bContext *C, uiLayout *layout)
1091 SpaceButs *sbuts = CTX_wm_space_buts(C);
1092 ButsContextPath *path = sbuts->path;
1097 char namebuf[128], *name;
1103 row = uiLayoutRow(layout, true);
1104 uiLayoutSetAlignment(row, UI_LAYOUT_ALIGN_LEFT);
1106 block = uiLayoutGetBlock(row);
1107 UI_block_emboss_set(block, UI_EMBOSS_NONE);
1108 but = uiDefIconButBitC(block, UI_BTYPE_ICON_TOGGLE, SB_PIN_CONTEXT, 0, ICON_UNPINNED, 0, 0, UI_UNIT_X, UI_UNIT_Y, &sbuts->flag,
1109 0, 0, 0, 0, TIP_("Follow context or keep fixed data-block displayed"));
1110 UI_but_flag_disable(but, UI_BUT_UNDO); /* skip undo on screen buttons */
1111 UI_but_func_set(but, pin_cb, NULL, NULL);
1113 for (a = 0; a < path->len; a++) {
1114 ptr = &path->ptr[a];
1117 uiItemL(row, "", VICO_SMALL_TRI_RIGHT_VEC);
1120 icon = RNA_struct_ui_icon(ptr->type);
1121 name = RNA_struct_name_get_alloc(ptr, namebuf, sizeof(namebuf), NULL);
1124 if (!ELEM(sbuts->mainb, BCONTEXT_RENDER, BCONTEXT_SCENE, BCONTEXT_RENDER_LAYER) && ptr->type == &RNA_Scene)
1125 uiItemLDrag(row, ptr, "", icon); /* save some space */
1127 uiItemLDrag(row, ptr, name, icon);
1129 if (name != namebuf)
1133 uiItemL(row, "", icon);
1138 static void buttons_panel_context(const bContext *C, Panel *pa)
1140 buttons_context_draw(C, pa->layout);
1143 void buttons_context_register(ARegionType *art)
1147 pt = MEM_callocN(sizeof(PanelType), "spacetype buttons panel context");
1148 strcpy(pt->idname, "BUTTONS_PT_context");
1149 strcpy(pt->label, N_("Context")); /* XXX C panels are not available through RNA (bpy.types)! */
1150 strcpy(pt->translation_context, BLT_I18NCONTEXT_DEFAULT_BPYRNA);
1151 pt->draw = buttons_panel_context;
1152 pt->flag = PNL_NO_HEADER;
1153 BLI_addtail(&art->paneltypes, pt);
1156 ID *buttons_context_id_path(const bContext *C)
1158 SpaceButs *sbuts = CTX_wm_space_buts(C);
1159 ButsContextPath *path = sbuts->path;
1164 for (a = path->len - 1; a >= 0; a--) {
1165 ptr = &path->ptr[a];
1167 /* pin particle settings instead of system, since only settings are an idblock*/
1168 if (sbuts->mainb == BCONTEXT_PARTICLE && sbuts->flag & SB_PIN_CONTEXT) {
1169 if (ptr->type == &RNA_ParticleSystem && ptr->data) {
1170 ParticleSystem *psys = (ParticleSystem *)ptr->data;
1171 return &psys->part->id;
1176 return ptr->id.data;