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_texture.c
34
#include "MEM_guardedalloc.h"
36
#include "BLI_listbase.h"
37
#include "BLI_string.h"
38
#include "BLI_utildefines.h"
40
#include "DNA_brush_types.h"
42
#include "DNA_lamp_types.h"
43
#include "DNA_material_types.h"
44
#include "DNA_node_types.h"
45
#include "DNA_object_types.h"
46
#include "DNA_object_force.h"
47
#include "DNA_particle_types.h"
48
#include "DNA_scene_types.h"
49
#include "DNA_screen_types.h"
50
#include "DNA_space_types.h"
51
#include "DNA_world_types.h"
53
#include "BKE_context.h"
54
#include "BKE_material.h"
55
#include "BKE_modifier.h"
57
#include "BKE_paint.h"
58
#include "BKE_particle.h"
59
#include "BKE_scene.h"
61
#include "RNA_access.h"
63
#include "UI_interface.h"
64
#include "UI_resources.h"
67
#include "ED_screen.h"
69
#include "../interface/interface_intern.h"
71
#include "buttons_intern.h" // own include
73
/************************* Texture User **************************/
75
static void buttons_texture_user_property_add(ListBase *users, ID *id,
76
PointerRNA ptr, PropertyRNA *prop,
77
const char *category, int icon, const char *name)
79
ButsTextureUser *user = MEM_callocN(sizeof(ButsTextureUser), "ButsTextureUser");
84
user->category = category;
87
user->index = BLI_countlist(users);
89
BLI_addtail(users, user);
92
static void buttons_texture_user_node_add(ListBase *users, ID *id,
93
bNodeTree *ntree, bNode *node,
94
const char *category, int icon, const char *name)
96
ButsTextureUser *user = MEM_callocN(sizeof(ButsTextureUser), "ButsTextureUser");
101
user->category = category;
104
user->index = BLI_countlist(users);
106
BLI_addtail(users, user);
109
static void buttons_texture_users_find_nodetree(ListBase *users, ID *id,
110
bNodeTree *ntree, const char *category)
115
for (node=ntree->nodes.first; node; node=node->next) {
116
if (node->typeinfo->nclass == NODE_CLASS_TEXTURE) {
118
/* PropertyRNA *prop; */ /* UNUSED */
120
RNA_pointer_create(&ntree->id, &RNA_Node, node, &ptr);
121
/* prop = RNA_struct_find_property(&ptr, "texture"); */ /* UNUSED */
123
buttons_texture_user_node_add(users, id, ntree, node,
124
category, RNA_struct_ui_icon(ptr.type), node->name);
126
else if (node->type == NODE_GROUP && node->id) {
127
buttons_texture_users_find_nodetree(users, id, (bNodeTree*)node->id, category);
133
static void buttons_texture_modifier_foreach(void *userData, Object *ob, ModifierData *md, const char *propname)
137
ListBase *users = userData;
139
RNA_pointer_create(&ob->id, &RNA_Modifier, md, &ptr);
140
prop = RNA_struct_find_property(&ptr, propname);
142
buttons_texture_user_property_add(users, &ob->id, ptr, prop,
143
"Modifiers", RNA_struct_ui_icon(ptr.type), md->name);
146
static void buttons_texture_users_from_context(ListBase *users, const bContext *C, SpaceButs *sbuts)
154
ID *pinid = sbuts->pinid;
156
/* get data from context */
158
if (GS(pinid->name) == ID_SCE)
159
scene= (Scene*)pinid;
160
else if (GS(pinid->name) == ID_OB)
162
else if (GS(pinid->name) == ID_LA)
164
else if (GS(pinid->name) == ID_WO)
166
else if (GS(pinid->name) == ID_MA)
167
ma= (Material*)pinid;
168
else if (GS(pinid->name) == ID_BR)
169
brush= (Brush*)pinid;
173
scene= CTX_data_scene(C);
175
if (!(pinid || pinid == &scene->id)) {
176
ob= (scene->basact)? scene->basact->object: NULL;
178
brush= paint_brush(paint_get_active(scene));
181
if (ob && ob->type == OB_LAMP && !la)
184
ma= give_current_material(ob, ob->actcol);
187
users->first = users->last = NULL;
190
buttons_texture_users_find_nodetree(users, &ma->id, ma->nodetree, "Material");
192
buttons_texture_users_find_nodetree(users, &la->id, la->nodetree, "Lamp");
194
buttons_texture_users_find_nodetree(users, &wrld->id, wrld->nodetree, "World");
197
ParticleSystem *psys= psys_get_current(ob);
202
modifiers_foreachTexLink(ob, buttons_texture_modifier_foreach, users);
204
/* particle systems */
206
/* todo: these slots are not in the UI */
207
for (a=0; a<MAX_MTEX; a++) {
208
mtex = psys->part->mtex[a];
214
RNA_pointer_create(&psys->part->id, &RNA_ParticleSettingsTextureSlot, mtex, &ptr);
215
prop = RNA_struct_find_property(&ptr, "texture");
217
buttons_texture_user_property_add(users, &psys->part->id, ptr, prop,
218
"Particles", RNA_struct_ui_icon(&RNA_ParticleSettings), psys->name);
224
if (ob->pd && ob->pd->forcefield == PFIELD_TEXTURE) {
228
RNA_pointer_create(&ob->id, &RNA_FieldSettings, ob->pd, &ptr);
229
prop = RNA_struct_find_property(&ptr, "texture");
231
buttons_texture_user_property_add(users, &ob->id, ptr, prop,
232
"Fields", ICON_FORCE_TEXTURE, "Texture Field");
241
RNA_pointer_create(&brush->id, &RNA_BrushTextureSlot, &brush->mtex, &ptr);
242
prop= RNA_struct_find_property(&ptr, "texture");
244
buttons_texture_user_property_add(users, &brush->id, ptr, prop,
245
"Brush", ICON_BRUSH_DATA, brush->id.name+2);
249
void buttons_texture_context_compute(const bContext *C, SpaceButs *sbuts)
251
/* gatheravailable texture users in context. runs on every draw of
252
* properties editor, before the buttons are created. */
253
ButsContextTexture *ct= sbuts->texuser;
254
Scene *scene= CTX_data_scene(C);
256
if (!scene_use_new_shading_nodes(scene)) {
258
BLI_freelistN(&ct->users);
260
sbuts->texuser= NULL;
267
ct= MEM_callocN(sizeof(ButsContextTexture), "ButsContextTexture");
271
BLI_freelistN(&ct->users);
274
buttons_texture_users_from_context(&ct->users, C, sbuts);
276
/* set one user as active based on active index */
277
if (ct->index >= BLI_countlist(&ct->users))
280
ct->user = BLI_findlink(&ct->users, ct->index);
284
if (ct->user->ptr.data) {
288
/* get texture datablock pointer if it's a property */
289
texptr = RNA_property_pointer_get(&ct->user->ptr, ct->user->prop);
290
tex = (RNA_struct_is_a(texptr.type, &RNA_Texture))? texptr.data: NULL;
294
else if (ct->user->node && !(ct->user->node->flag & NODE_ACTIVE_TEXTURE)) {
295
ButsTextureUser *user;
297
/* detect change of active texture node in same node tree, in that
298
* case we also automatically switch to the other node */
299
for (user=ct->users.first; user; user=user->next) {
300
if (user->ntree == ct->user->ntree && user->node != ct->user->node) {
301
if (user->node->flag & NODE_ACTIVE_TEXTURE) {
303
ct->index = BLI_findindex(&ct->users, user);
312
static void template_texture_select(bContext *C, void *user_p, void *UNUSED(arg))
314
/* callback when selecting a texture user in the menu */
315
SpaceButs *sbuts = CTX_wm_space_buts(C);
316
ButsContextTexture *ct= (sbuts)? sbuts->texuser: NULL;
317
ButsTextureUser *user = (ButsTextureUser*)user_p;
324
/* set user as active */
326
ED_node_set_active(CTX_data_main(C), user->ntree, user->node);
330
texptr = RNA_property_pointer_get(&user->ptr, user->prop);
331
tex = (RNA_struct_is_a(texptr.type, &RNA_Texture))? texptr.data: NULL;
337
ct->index = user->index;
340
static void template_texture_user_menu(bContext *C, uiLayout *layout, void *UNUSED(arg))
342
/* callback when opening texture user selection menu, to create buttons. */
343
SpaceButs *sbuts = CTX_wm_space_buts(C);
344
ButsContextTexture *ct= (sbuts)? sbuts->texuser: NULL;
345
ButsTextureUser *user;
346
uiBlock *block = uiLayoutGetBlock(layout);
347
const char *last_category = NULL;
349
for (user=ct->users.first; user; user=user->next) {
351
char name[UI_MAX_NAME_STR];
353
/* add label per category */
354
if (!last_category || strcmp(last_category, user->category) != 0) {
355
uiItemL(layout, user->category, ICON_NONE);
356
but= block->buttons.last;
357
but->flag= UI_TEXT_LEFT;
361
BLI_snprintf(name, UI_MAX_NAME_STR, " %s", user->name);
363
but = uiDefIconTextBut(block, BUT, 0, user->icon, name, 0, 0, UI_UNIT_X*4, UI_UNIT_Y,
364
NULL, 0.0, 0.0, 0.0, 0.0, "");
365
uiButSetNFunc(but, template_texture_select, MEM_dupallocN(user), NULL);
367
last_category = user->category;
371
void uiTemplateTextureUser(uiLayout *layout, bContext *C)
373
/* texture user selection dropdown menu. the available users have been
374
* gathered before drawing in ButsContextTexture, we merely need to
375
* display the current item. */
376
SpaceButs *sbuts = CTX_wm_space_buts(C);
377
ButsContextTexture *ct= (sbuts)? sbuts->texuser: NULL;
378
uiBlock *block = uiLayoutGetBlock(layout);
380
ButsTextureUser *user;
381
char name[UI_MAX_NAME_STR];
386
/* get current user */
390
uiItemL(layout, "No textures in context.", ICON_NONE);
395
BLI_snprintf(name, UI_MAX_NAME_STR, "%s", user->name);
398
but = uiDefIconTextMenuBut(block, template_texture_user_menu, NULL,
399
user->icon, name, 0, 0, UI_UNIT_X*4, UI_UNIT_Y, "");
402
but = uiDefMenuBut(block, template_texture_user_menu, NULL,
403
name, 0, 0, UI_UNIT_X*4, UI_UNIT_Y, "");
406
/* some cosmetic tweaks */
408
but->flag |= UI_TEXT_LEFT;
409
but->flag &= ~UI_ICON_SUBMENU;
412
/************************* Texture Show **************************/
414
static void template_texture_show(bContext *C, void *data_p, void *prop_p)
416
SpaceButs *sbuts = CTX_wm_space_buts(C);
417
ButsContextTexture *ct= (sbuts)? sbuts->texuser: NULL;
418
ButsTextureUser *user;
423
for (user=ct->users.first; user; user=user->next)
424
if (user->ptr.data == data_p && user->prop == prop_p)
429
template_texture_select(C, user, NULL);
432
sbuts->mainb= BCONTEXT_TEXTURE;
433
sbuts->mainbuser= sbuts->mainb;
437
ED_area_tag_redraw(CTX_wm_area(C));
441
void uiTemplateTextureShow(uiLayout *layout, bContext *C, PointerRNA *ptr, PropertyRNA *prop)
443
/* button to quickly show texture in texture tab */
444
SpaceButs *sbuts = CTX_wm_space_buts(C);
445
ButsContextTexture *ct= (sbuts)? sbuts->texuser: NULL;
446
ButsTextureUser *user;
448
/* only show button in other tabs in properties editor */
449
if (!ct || sbuts->mainb == BCONTEXT_TEXTURE)
452
/* find corresponding texture user */
453
for (user=ct->users.first; user; user=user->next)
454
if (user->ptr.data == ptr->data && user->prop == prop)
459
uiBlock *block = uiLayoutGetBlock(layout);
462
but = uiDefIconBut(block, BUT, 0, ICON_BUTS, 0, 0, UI_UNIT_X, UI_UNIT_Y,
463
NULL, 0.0, 0.0, 0.0, 0.0, "Show texture in texture tab");
464
uiButSetFunc(but, template_texture_show, user->ptr.data, user->prop);