Blender V2.61 - r43446
|
00001 /* 00002 * ***** BEGIN GPL LICENSE BLOCK ***** 00003 * 00004 * This program is free software; you can redistribute it and/or 00005 * modify it under the terms of the GNU General Public License 00006 * as published by the Free Software Foundation; either version 2 00007 * of the License, or (at your option) any later version. 00008 * 00009 * This program is distributed in the hope that it will be useful, 00010 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00012 * GNU General Public License for more details. 00013 * 00014 * You should have received a copy of the GNU General Public License 00015 * along with this program; if not, write to the Free Software Foundation, 00016 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 00017 * 00018 * The Original Code is Copyright (C) 2009 Blender Foundation. 00019 * All rights reserved. 00020 * 00021 * Contributor(s): Blender Foundation 00022 * 00023 * ***** END GPL LICENSE BLOCK ***** 00024 */ 00025 00031 #include <stdlib.h> 00032 #include <string.h> 00033 00034 #include "MEM_guardedalloc.h" 00035 00036 #include "BLI_listbase.h" 00037 #include "BLI_string.h" 00038 #include "BLI_utildefines.h" 00039 00040 #include "DNA_brush_types.h" 00041 #include "DNA_ID.h" 00042 #include "DNA_lamp_types.h" 00043 #include "DNA_material_types.h" 00044 #include "DNA_node_types.h" 00045 #include "DNA_object_types.h" 00046 #include "DNA_object_force.h" 00047 #include "DNA_particle_types.h" 00048 #include "DNA_scene_types.h" 00049 #include "DNA_screen_types.h" 00050 #include "DNA_space_types.h" 00051 #include "DNA_world_types.h" 00052 00053 #include "BKE_context.h" 00054 #include "BKE_material.h" 00055 #include "BKE_modifier.h" 00056 #include "BKE_node.h" 00057 #include "BKE_paint.h" 00058 #include "BKE_particle.h" 00059 #include "BKE_scene.h" 00060 00061 #include "RNA_access.h" 00062 00063 #include "UI_interface.h" 00064 #include "UI_resources.h" 00065 00066 #include "ED_node.h" 00067 #include "ED_screen.h" 00068 00069 #include "../interface/interface_intern.h" 00070 00071 #include "buttons_intern.h" // own include 00072 00073 /************************* Texture User **************************/ 00074 00075 static void buttons_texture_user_property_add(ListBase *users, ID *id, 00076 PointerRNA ptr, PropertyRNA *prop, 00077 const char *category, int icon, const char *name) 00078 { 00079 ButsTextureUser *user = MEM_callocN(sizeof(ButsTextureUser), "ButsTextureUser"); 00080 00081 user->id= id; 00082 user->ptr = ptr; 00083 user->prop = prop; 00084 user->category = category; 00085 user->icon = icon; 00086 user->name = name; 00087 user->index = BLI_countlist(users); 00088 00089 BLI_addtail(users, user); 00090 } 00091 00092 static void buttons_texture_user_node_add(ListBase *users, ID *id, 00093 bNodeTree *ntree, bNode *node, 00094 const char *category, int icon, const char *name) 00095 { 00096 ButsTextureUser *user = MEM_callocN(sizeof(ButsTextureUser), "ButsTextureUser"); 00097 00098 user->id= id; 00099 user->ntree = ntree; 00100 user->node = node; 00101 user->category = category; 00102 user->icon = icon; 00103 user->name = name; 00104 user->index = BLI_countlist(users); 00105 00106 BLI_addtail(users, user); 00107 } 00108 00109 static void buttons_texture_users_find_nodetree(ListBase *users, ID *id, 00110 bNodeTree *ntree, const char *category) 00111 { 00112 bNode *node; 00113 00114 if(ntree) { 00115 for(node=ntree->nodes.first; node; node=node->next) { 00116 if(node->typeinfo->nclass == NODE_CLASS_TEXTURE) { 00117 PointerRNA ptr; 00118 /* PropertyRNA *prop; */ /* UNUSED */ 00119 00120 RNA_pointer_create(&ntree->id, &RNA_Node, node, &ptr); 00121 /* prop = RNA_struct_find_property(&ptr, "texture"); */ /* UNUSED */ 00122 00123 buttons_texture_user_node_add(users, id, ntree, node, 00124 category, RNA_struct_ui_icon(ptr.type), node->name); 00125 } 00126 else if(node->type == NODE_GROUP && node->id) { 00127 buttons_texture_users_find_nodetree(users, id, (bNodeTree*)node->id, category); 00128 } 00129 } 00130 } 00131 } 00132 00133 static void buttons_texture_modifier_foreach(void *userData, Object *ob, ModifierData *md, const char *propname) 00134 { 00135 PointerRNA ptr; 00136 PropertyRNA *prop; 00137 ListBase *users = userData; 00138 00139 RNA_pointer_create(&ob->id, &RNA_Modifier, md, &ptr); 00140 prop = RNA_struct_find_property(&ptr, propname); 00141 00142 buttons_texture_user_property_add(users, &ob->id, ptr, prop, 00143 "Modifiers", RNA_struct_ui_icon(ptr.type), md->name); 00144 } 00145 00146 static void buttons_texture_users_from_context(ListBase *users, const bContext *C, SpaceButs *sbuts) 00147 { 00148 Scene *scene= NULL; 00149 Object *ob= NULL; 00150 Material *ma= NULL; 00151 Lamp *la= NULL; 00152 World *wrld= NULL; 00153 Brush *brush= NULL; 00154 ID *pinid = sbuts->pinid; 00155 00156 /* get data from context */ 00157 if(pinid) { 00158 if(GS(pinid->name) == ID_SCE) 00159 scene= (Scene*)pinid; 00160 else if(GS(pinid->name) == ID_OB) 00161 ob= (Object*)pinid; 00162 else if(GS(pinid->name) == ID_LA) 00163 la= (Lamp*)pinid; 00164 else if(GS(pinid->name) == ID_WO) 00165 wrld= (World*)pinid; 00166 else if(GS(pinid->name) == ID_MA) 00167 ma= (Material*)pinid; 00168 else if(GS(pinid->name) == ID_BR) 00169 brush= (Brush*)pinid; 00170 } 00171 00172 if(!scene) 00173 scene= CTX_data_scene(C); 00174 00175 if(!(pinid || pinid == &scene->id)) { 00176 ob= (scene->basact)? scene->basact->object: NULL; 00177 wrld= scene->world; 00178 brush= paint_brush(paint_get_active(scene)); 00179 } 00180 00181 if(ob && ob->type == OB_LAMP && !la) 00182 la= ob->data; 00183 if(ob && !ma) 00184 ma= give_current_material(ob, ob->actcol); 00185 00186 /* fill users */ 00187 users->first = users->last = NULL; 00188 00189 if(ma) 00190 buttons_texture_users_find_nodetree(users, &ma->id, ma->nodetree, "Material"); 00191 if(la) 00192 buttons_texture_users_find_nodetree(users, &la->id, la->nodetree, "Lamp"); 00193 if(wrld) 00194 buttons_texture_users_find_nodetree(users, &wrld->id, wrld->nodetree, "World"); 00195 00196 if(ob) { 00197 ParticleSystem *psys= psys_get_current(ob); 00198 MTex *mtex; 00199 int a; 00200 00201 /* modifiers */ 00202 modifiers_foreachTexLink(ob, buttons_texture_modifier_foreach, users); 00203 00204 /* particle systems */ 00205 if(psys) { 00206 /* todo: these slots are not in the UI */ 00207 for(a=0; a<MAX_MTEX; a++) { 00208 mtex = psys->part->mtex[a]; 00209 00210 if(mtex) { 00211 PointerRNA ptr; 00212 PropertyRNA *prop; 00213 00214 RNA_pointer_create(&psys->part->id, &RNA_ParticleSettingsTextureSlot, mtex, &ptr); 00215 prop = RNA_struct_find_property(&ptr, "texture"); 00216 00217 buttons_texture_user_property_add(users, &psys->part->id, ptr, prop, 00218 "Particles", RNA_struct_ui_icon(&RNA_ParticleSettings), psys->name); 00219 } 00220 } 00221 } 00222 00223 /* field */ 00224 if(ob->pd && ob->pd->forcefield == PFIELD_TEXTURE) { 00225 PointerRNA ptr; 00226 PropertyRNA *prop; 00227 00228 RNA_pointer_create(&ob->id, &RNA_FieldSettings, ob->pd, &ptr); 00229 prop = RNA_struct_find_property(&ptr, "texture"); 00230 00231 buttons_texture_user_property_add(users, &ob->id, ptr, prop, 00232 "Fields", ICON_FORCE_TEXTURE, "Texture Field"); 00233 } 00234 } 00235 00236 /* brush */ 00237 if(brush) { 00238 PointerRNA ptr; 00239 PropertyRNA *prop; 00240 00241 RNA_pointer_create(&brush->id, &RNA_BrushTextureSlot, &brush->mtex, &ptr); 00242 prop= RNA_struct_find_property(&ptr, "texture"); 00243 00244 buttons_texture_user_property_add(users, &brush->id, ptr, prop, 00245 "Brush", ICON_BRUSH_DATA, brush->id.name+2); 00246 } 00247 } 00248 00249 void buttons_texture_context_compute(const bContext *C, SpaceButs *sbuts) 00250 { 00251 /* gatheravailable texture users in context. runs on every draw of 00252 properties editor, before the buttons are created. */ 00253 ButsContextTexture *ct= sbuts->texuser; 00254 Scene *scene= CTX_data_scene(C); 00255 00256 if(!scene_use_new_shading_nodes(scene)) { 00257 if(ct) { 00258 BLI_freelistN(&ct->users); 00259 MEM_freeN(ct); 00260 sbuts->texuser= NULL; 00261 } 00262 00263 return; 00264 } 00265 00266 if(!ct) { 00267 ct= MEM_callocN(sizeof(ButsContextTexture), "ButsContextTexture"); 00268 sbuts->texuser= ct; 00269 } 00270 else { 00271 BLI_freelistN(&ct->users); 00272 } 00273 00274 buttons_texture_users_from_context(&ct->users, C, sbuts); 00275 00276 /* set one user as active based on active index */ 00277 if(ct->index >= BLI_countlist(&ct->users)) 00278 ct->index= 0; 00279 00280 ct->user = BLI_findlink(&ct->users, ct->index); 00281 ct->texture = NULL; 00282 00283 if(ct->user) { 00284 if(ct->user->ptr.data) { 00285 PointerRNA texptr; 00286 Tex *tex; 00287 00288 /* get texture datablock pointer if it's a property */ 00289 texptr = RNA_property_pointer_get(&ct->user->ptr, ct->user->prop); 00290 tex = (RNA_struct_is_a(texptr.type, &RNA_Texture))? texptr.data: NULL; 00291 00292 ct->texture = tex; 00293 } 00294 else if(ct->user->node && !(ct->user->node->flag & NODE_ACTIVE_TEXTURE)) { 00295 ButsTextureUser *user; 00296 00297 /* detect change of active texture node in same node tree, in that 00298 case we also automatically switch to the other node */ 00299 for(user=ct->users.first; user; user=user->next) { 00300 if(user->ntree == ct->user->ntree && user->node != ct->user->node) { 00301 if(user->node->flag & NODE_ACTIVE_TEXTURE) { 00302 ct->user = user; 00303 ct->index = BLI_findindex(&ct->users, user); 00304 break; 00305 } 00306 } 00307 } 00308 } 00309 } 00310 } 00311 00312 static void template_texture_select(bContext *C, void *user_p, void *UNUSED(arg)) 00313 { 00314 /* callback when selecting a texture user in the menu */ 00315 SpaceButs *sbuts = CTX_wm_space_buts(C); 00316 ButsContextTexture *ct= (sbuts)? sbuts->texuser: NULL; 00317 ButsTextureUser *user = (ButsTextureUser*)user_p; 00318 PointerRNA texptr; 00319 Tex *tex; 00320 00321 if(!ct) 00322 return; 00323 00324 /* set user as active */ 00325 if(user->node) { 00326 ED_node_set_active(CTX_data_main(C), user->ntree, user->node); 00327 ct->texture = NULL; 00328 } 00329 else { 00330 texptr = RNA_property_pointer_get(&user->ptr, user->prop); 00331 tex = (RNA_struct_is_a(texptr.type, &RNA_Texture))? texptr.data: NULL; 00332 00333 ct->texture = tex; 00334 } 00335 00336 ct->user = user; 00337 ct->index = user->index; 00338 } 00339 00340 static void template_texture_user_menu(bContext *C, uiLayout *layout, void *UNUSED(arg)) 00341 { 00342 /* callback when opening texture user selection menu, to create buttons. */ 00343 SpaceButs *sbuts = CTX_wm_space_buts(C); 00344 ButsContextTexture *ct= (sbuts)? sbuts->texuser: NULL; 00345 ButsTextureUser *user; 00346 uiBlock *block = uiLayoutGetBlock(layout); 00347 const char *last_category = NULL; 00348 00349 for(user=ct->users.first; user; user=user->next) { 00350 uiBut *but; 00351 char name[UI_MAX_NAME_STR]; 00352 00353 /* add label per category */ 00354 if(!last_category || strcmp(last_category, user->category) != 0) { 00355 uiItemL(layout, user->category, ICON_NONE); 00356 but= block->buttons.last; 00357 but->flag= UI_TEXT_LEFT; 00358 } 00359 00360 /* create button */ 00361 BLI_snprintf(name, UI_MAX_NAME_STR, " %s", user->name); 00362 00363 but = uiDefIconTextBut(block, BUT, 0, user->icon, name, 0, 0, UI_UNIT_X*4, UI_UNIT_Y, 00364 NULL, 0.0, 0.0, 0.0, 0.0, ""); 00365 uiButSetNFunc(but, template_texture_select, MEM_dupallocN(user), NULL); 00366 00367 last_category = user->category; 00368 } 00369 } 00370 00371 void uiTemplateTextureUser(uiLayout *layout, bContext *C) 00372 { 00373 /* texture user selection dropdown menu. the available users have been 00374 gathered before drawing in ButsContextTexture, we merely need to 00375 display the current item. */ 00376 SpaceButs *sbuts = CTX_wm_space_buts(C); 00377 ButsContextTexture *ct= (sbuts)? sbuts->texuser: NULL; 00378 uiBlock *block = uiLayoutGetBlock(layout); 00379 uiBut *but; 00380 ButsTextureUser *user; 00381 char name[UI_MAX_NAME_STR]; 00382 00383 if(!ct) 00384 return; 00385 00386 /* get current user */ 00387 user= ct->user; 00388 00389 if(!user) { 00390 uiItemL(layout, "No textures in context.", ICON_NONE); 00391 return; 00392 } 00393 00394 /* create button */ 00395 BLI_snprintf(name, UI_MAX_NAME_STR, "%s", user->name); 00396 00397 if(user->icon) { 00398 but= uiDefIconTextMenuBut(block, template_texture_user_menu, NULL, 00399 user->icon, name, 0, 0, UI_UNIT_X*4, UI_UNIT_Y, ""); 00400 } 00401 else { 00402 but= uiDefMenuBut(block, template_texture_user_menu, NULL, 00403 name, 0, 0, UI_UNIT_X*4, UI_UNIT_Y, ""); 00404 } 00405 00406 /* some cosmetic tweaks */ 00407 but->type= MENU; 00408 but->flag |= UI_TEXT_LEFT; 00409 but->flag &= ~UI_ICON_SUBMENU; 00410 } 00411 00412 /************************* Texture Show **************************/ 00413 00414 static void template_texture_show(bContext *C, void *data_p, void *prop_p) 00415 { 00416 SpaceButs *sbuts = CTX_wm_space_buts(C); 00417 ButsContextTexture *ct= (sbuts)? sbuts->texuser: NULL; 00418 ButsTextureUser *user; 00419 00420 if(!ct) 00421 return; 00422 00423 for(user=ct->users.first; user; user=user->next) 00424 if(user->ptr.data == data_p && user->prop == prop_p) 00425 break; 00426 00427 if(user) { 00428 /* select texture */ 00429 template_texture_select(C, user, NULL); 00430 00431 /* change context */ 00432 sbuts->mainb= BCONTEXT_TEXTURE; 00433 sbuts->mainbuser= sbuts->mainb; 00434 sbuts->preview= 1; 00435 00436 /* redraw editor */ 00437 ED_area_tag_redraw(CTX_wm_area(C)); 00438 } 00439 } 00440 00441 void uiTemplateTextureShow(uiLayout *layout, bContext *C, PointerRNA *ptr, PropertyRNA *prop) 00442 { 00443 /* button to quickly show texture in texture tab */ 00444 SpaceButs *sbuts = CTX_wm_space_buts(C); 00445 ButsContextTexture *ct= (sbuts)? sbuts->texuser: NULL; 00446 ButsTextureUser *user; 00447 00448 /* only show button in other tabs in properties editor */ 00449 if(!ct || sbuts->mainb == BCONTEXT_TEXTURE) 00450 return; 00451 00452 /* find corresponding texture user */ 00453 for(user=ct->users.first; user; user=user->next) 00454 if(user->ptr.data == ptr->data && user->prop == prop) 00455 break; 00456 00457 /* draw button */ 00458 if(user) { 00459 uiBlock *block = uiLayoutGetBlock(layout); 00460 uiBut *but; 00461 00462 but= uiDefIconBut(block, BUT, 0, ICON_BUTS, 0, 0, UI_UNIT_X, UI_UNIT_Y, 00463 NULL, 0.0, 0.0, 0.0, 0.0, "Show texture in texture tab"); 00464 uiButSetFunc(but, template_texture_show, user->ptr.data, user->prop); 00465 } 00466 } 00467