Changeset View
Changeset View
Standalone View
Standalone View
source/blender/editors/space_buttons/buttons_texture.c
| Show First 20 Lines • Show All 58 Lines • ▼ Show 20 Lines | |||||||||
| #include "UI_interface.h" | #include "UI_interface.h" | ||||||||
| #include "UI_resources.h" | #include "UI_resources.h" | ||||||||
| #include "ED_node.h" | #include "ED_node.h" | ||||||||
| #include "ED_screen.h" | #include "ED_screen.h" | ||||||||
| #include "WM_api.h" | #include "WM_api.h" | ||||||||
| #include "WM_types.h" | |||||||||
| #include "../interface/interface_intern.h" | #include "../interface/interface_intern.h" | ||||||||
| #include "buttons_intern.h" /* own include */ | #include "buttons_intern.h" /* own include */ | ||||||||
| static ScrArea *find_area_properties(const bContext *C); | |||||||||
| static SpaceProperties *find_space_properties(const bContext *C); | |||||||||
| /************************* Texture User **************************/ | /************************* Texture User **************************/ | ||||||||
| static void buttons_texture_user_node_property_add(ListBase *users, | |||||||||
| ID *id, | |||||||||
| PointerRNA ptr, | |||||||||
| PropertyRNA *prop, | |||||||||
| bNodeTree *ntree, | |||||||||
| bNode *node, | |||||||||
| const char *category, | |||||||||
| int icon, | |||||||||
| const char *name) | |||||||||
| { | |||||||||
| ButsTextureUser *user = MEM_callocN(sizeof(ButsTextureUser), "ButsTextureUser"); | |||||||||
| user->id = id; | |||||||||
| user->ptr = ptr; | |||||||||
| user->prop = prop; | |||||||||
| user->ntree = ntree; | |||||||||
| user->node = node; | |||||||||
| user->category = category; | |||||||||
| user->icon = icon; | |||||||||
| user->name = name; | |||||||||
| user->index = BLI_listbase_count(users); | |||||||||
| BLI_addtail(users, user); | |||||||||
| } | |||||||||
| static void buttons_texture_user_property_add(ListBase *users, | static void buttons_texture_user_property_add(ListBase *users, | ||||||||
| ID *id, | ID *id, | ||||||||
| PointerRNA ptr, | PointerRNA ptr, | ||||||||
| PropertyRNA *prop, | PropertyRNA *prop, | ||||||||
| const char *category, | const char *category, | ||||||||
| int icon, | int icon, | ||||||||
| const char *name) | const char *name) | ||||||||
| { | { | ||||||||
| ▲ Show 20 Lines • Show All 52 Lines • ▼ Show 20 Lines | for (node = ntree->nodes.first; node; node = node->next) { | ||||||||
| } | } | ||||||||
| else if (node->type == NODE_GROUP && node->id) { | else if (node->type == NODE_GROUP && node->id) { | ||||||||
| buttons_texture_users_find_nodetree(users, id, (bNodeTree *)node->id, category); | buttons_texture_users_find_nodetree(users, id, (bNodeTree *)node->id, category); | ||||||||
| } | } | ||||||||
| } | } | ||||||||
| } | } | ||||||||
| } | } | ||||||||
| static void buttons_texture_modifier_geonodes_users_add(Object *ob, | |||||||||
| NodesModifierData *nmd, | |||||||||
| bNodeTree *node_tree, | |||||||||
| ListBase *users) | |||||||||
| { | |||||||||
| PointerRNA ptr; | |||||||||
| PropertyRNA *prop; | |||||||||
| LISTBASE_FOREACH (bNode *, node, &node_tree->nodes) { | |||||||||
| if (node->type == NODE_GROUP && node->id) { | |||||||||
| /* Recurse into the node group */ | |||||||||
| buttons_texture_modifier_geonodes_users_add(ob, nmd, (bNodeTree *)node->id, users); | |||||||||
| } | |||||||||
| else if (node->type == GEO_NODE_ATTRIBUTE_SAMPLE_TEXTURE) { | |||||||||
| RNA_pointer_create(&node_tree->id, &RNA_Node, node, &ptr); | |||||||||
JacquesLucke: Better just use `RNA_Node` and check that `node->type == GEO_NODE_ATTRIBUTE_SAMPLE_TEXTURE`… | |||||||||
| prop = RNA_struct_find_property(&ptr, "texture"); | |||||||||
| if (prop == NULL) { | |||||||||
| continue; | |||||||||
| } | |||||||||
| PointerRNA texptr = RNA_property_pointer_get(&ptr, prop); | |||||||||
| Tex *tex = (RNA_struct_is_a(texptr.type, &RNA_Texture)) ? (Tex *)texptr.data : NULL; | |||||||||
| if (tex != NULL) { | |||||||||
| buttons_texture_user_node_property_add(users, | |||||||||
| &ob->id, | |||||||||
| ptr, | |||||||||
| prop, | |||||||||
| node_tree, | |||||||||
| node, | |||||||||
| N_("Geometry Nodes"), | |||||||||
| RNA_struct_ui_icon(ptr.type), | |||||||||
| nmd->modifier.name); | |||||||||
| } | |||||||||
| } | |||||||||
| } | |||||||||
| } | |||||||||
| static void buttons_texture_modifier_foreach(void *userData, | static void buttons_texture_modifier_foreach(void *userData, | ||||||||
| Object *ob, | Object *ob, | ||||||||
| ModifierData *md, | ModifierData *md, | ||||||||
| const char *propname) | const char *propname) | ||||||||
| { | { | ||||||||
| ListBase *users = userData; | |||||||||
| if (md->type == eModifierType_Nodes) { | |||||||||
| NodesModifierData *nmd = (NodesModifierData *)md; | |||||||||
| if (nmd->node_group != NULL) { | |||||||||
| buttons_texture_modifier_geonodes_users_add(ob, nmd, nmd->node_group, users); | |||||||||
| } | |||||||||
| } | |||||||||
| else { | |||||||||
| PointerRNA ptr; | PointerRNA ptr; | ||||||||
| PropertyRNA *prop; | PropertyRNA *prop; | ||||||||
| ListBase *users = userData; | |||||||||
| RNA_pointer_create(&ob->id, &RNA_Modifier, md, &ptr); | RNA_pointer_create(&ob->id, &RNA_Modifier, md, &ptr); | ||||||||
| prop = RNA_struct_find_property(&ptr, propname); | prop = RNA_struct_find_property(&ptr, propname); | ||||||||
| buttons_texture_user_property_add( | buttons_texture_user_property_add( | ||||||||
| users, &ob->id, ptr, prop, N_("Modifiers"), RNA_struct_ui_icon(ptr.type), md->name); | users, &ob->id, ptr, prop, N_("Modifiers"), RNA_struct_ui_icon(ptr.type), md->name); | ||||||||
| } | } | ||||||||
| } | |||||||||
| static void buttons_texture_modifier_gpencil_foreach(void *userData, | static void buttons_texture_modifier_gpencil_foreach(void *userData, | ||||||||
| Object *ob, | Object *ob, | ||||||||
| GpencilModifierData *md, | GpencilModifierData *md, | ||||||||
| const char *propname) | const char *propname) | ||||||||
| { | { | ||||||||
| PointerRNA ptr; | PointerRNA ptr; | ||||||||
| PropertyRNA *prop; | PropertyRNA *prop; | ||||||||
| ▲ Show 20 Lines • Show All 155 Lines • ▼ Show 20 Lines | else { | ||||||||
| if (ct->index >= BLI_listbase_count_at_most(&ct->users, ct->index + 1)) { | if (ct->index >= BLI_listbase_count_at_most(&ct->users, ct->index + 1)) { | ||||||||
| ct->index = 0; | ct->index = 0; | ||||||||
| } | } | ||||||||
| ct->user = BLI_findlink(&ct->users, ct->index); | ct->user = BLI_findlink(&ct->users, ct->index); | ||||||||
| ct->texture = NULL; | ct->texture = NULL; | ||||||||
| if (ct->user) { | if (ct->user) { | ||||||||
| if (ct->user->ptr.data) { | if (ct->user->node != NULL) { | ||||||||
| PointerRNA texptr; | /* Detect change of active texture node in same node tree, in that | ||||||||
| Tex *tex; | * case we also automatically switch to the other node. */ | ||||||||
| if ((ct->user->node->flag & NODE_ACTIVE_TEXTURE) == 0) { | |||||||||
Not Done Inline Actions
dfelinto: | |||||||||
| /* get texture datablock pointer if it's a property */ | |||||||||
| texptr = RNA_property_pointer_get(&ct->user->ptr, ct->user->prop); | |||||||||
| tex = (RNA_struct_is_a(texptr.type, &RNA_Texture)) ? texptr.data : NULL; | |||||||||
| ct->texture = tex; | |||||||||
| } | |||||||||
| else if (ct->user->node && !(ct->user->node->flag & NODE_ACTIVE_TEXTURE)) { | |||||||||
| ButsTextureUser *user; | ButsTextureUser *user; | ||||||||
| /* detect change of active texture node in same node tree, in that | |||||||||
| * case we also automatically switch to the other node */ | |||||||||
| for (user = ct->users.first; user; user = user->next) { | for (user = ct->users.first; user; user = user->next) { | ||||||||
| if (user->ntree == ct->user->ntree && user->node != ct->user->node) { | if (user->ntree == ct->user->ntree && user->node != ct->user->node) { | ||||||||
| if (user->node->flag & NODE_ACTIVE_TEXTURE) { | if (user->node->flag & NODE_ACTIVE_TEXTURE) { | ||||||||
| ct->user = user; | ct->user = user; | ||||||||
| ct->index = BLI_findindex(&ct->users, user); | ct->index = BLI_findindex(&ct->users, user); | ||||||||
| break; | break; | ||||||||
| } | } | ||||||||
| } | } | ||||||||
| } | } | ||||||||
| } | } | ||||||||
| } | } | ||||||||
| if (ct->user->ptr.data) { | |||||||||
| PointerRNA texptr; | |||||||||
| Tex *tex; | |||||||||
| /* Get texture datablock pointer if it's a property. */ | |||||||||
Not Done Inline ActionsComment style. JacquesLucke: Comment style. | |||||||||
| texptr = RNA_property_pointer_get(&ct->user->ptr, ct->user->prop); | |||||||||
| tex = (RNA_struct_is_a(texptr.type, &RNA_Texture)) ? texptr.data : NULL; | |||||||||
| ct->texture = tex; | |||||||||
| } | |||||||||
| } | |||||||||
| } | } | ||||||||
| } | } | ||||||||
| static void template_texture_select(bContext *C, void *user_p, void *UNUSED(arg)) | static void template_texture_select(bContext *C, void *user_p, void *UNUSED(arg)) | ||||||||
| { | { | ||||||||
| /* callback when selecting a texture user in the menu */ | /* callback when selecting a texture user in the menu */ | ||||||||
| SpaceProperties *sbuts = CTX_wm_space_properties(C); | SpaceProperties *sbuts = find_space_properties(C); | ||||||||
| ButsContextTexture *ct = (sbuts) ? sbuts->texuser : NULL; | ButsContextTexture *ct = (sbuts) ? sbuts->texuser : NULL; | ||||||||
| ButsTextureUser *user = (ButsTextureUser *)user_p; | ButsTextureUser *user = (ButsTextureUser *)user_p; | ||||||||
| PointerRNA texptr; | PointerRNA texptr; | ||||||||
| Tex *tex; | Tex *tex; | ||||||||
| if (!ct) { | if (!ct) { | ||||||||
| return; | return; | ||||||||
| } | } | ||||||||
| /* set user as active */ | /* set user as active */ | ||||||||
| if (user->node) { | if (user->node) { | ||||||||
| ED_node_set_active(CTX_data_main(C), user->ntree, user->node, NULL); | ED_node_set_active(CTX_data_main(C), user->ntree, user->node, NULL); | ||||||||
| ct->texture = NULL; | ct->texture = NULL; | ||||||||
| /* Not totally sure if we should also change selection? */ | |||||||||
Not Done Inline ActionsI'm not a huge fan of this, but it seems to make sense, and also Dalai approved the functionality. JacquesLucke: I'm not a huge fan of this, but it seems to make sense, and also Dalai approved the… | |||||||||
| LISTBASE_FOREACH (bNode *, node, &user->ntree->nodes) { | |||||||||
| nodeSetSelected(node, false); | |||||||||
| } | } | ||||||||
| else { | nodeSetSelected(user->node, true); | ||||||||
| WM_event_add_notifier(C, NC_NODE | NA_SELECTED, NULL); | |||||||||
| } | |||||||||
| if (user->ptr.data) { | |||||||||
| texptr = RNA_property_pointer_get(&user->ptr, user->prop); | texptr = RNA_property_pointer_get(&user->ptr, user->prop); | ||||||||
| tex = (RNA_struct_is_a(texptr.type, &RNA_Texture)) ? texptr.data : NULL; | tex = (RNA_struct_is_a(texptr.type, &RNA_Texture)) ? texptr.data : NULL; | ||||||||
| ct->texture = tex; | ct->texture = tex; | ||||||||
| if (user->ptr.type == &RNA_ParticleSettingsTextureSlot) { | if (user->ptr.type == &RNA_ParticleSettingsTextureSlot) { | ||||||||
| /* stupid exception for particle systems which still uses influence | /* stupid exception for particle systems which still uses influence | ||||||||
| * from the old texture system, set the active texture slots as well */ | * from the old texture system, set the active texture slots as well */ | ||||||||
| ▲ Show 20 Lines • Show All 122 Lines • ▼ Show 20 Lines | void uiTemplateTextureUser(uiLayout *layout, bContext *C) | ||||||||
| /* some cosmetic tweaks */ | /* some cosmetic tweaks */ | ||||||||
| UI_but_type_set_menu_from_pulldown(but); | UI_but_type_set_menu_from_pulldown(but); | ||||||||
| but->flag &= ~UI_BUT_ICON_SUBMENU; | but->flag &= ~UI_BUT_ICON_SUBMENU; | ||||||||
| } | } | ||||||||
| /************************* Texture Show **************************/ | /************************* Texture Show **************************/ | ||||||||
| static ScrArea *find_area_properties(const bContext *C) | |||||||||
| { | |||||||||
| bScreen *screen = CTX_wm_screen(C); | |||||||||
| Object *ob = CTX_data_active_object(C); | |||||||||
| LISTBASE_FOREACH (ScrArea *, area, &screen->areabase) { | |||||||||
| if (area->spacetype == SPACE_PROPERTIES) { | |||||||||
| /* Only if unpinned, or if pinned object matches. */ | |||||||||
| SpaceProperties *sbuts = area->spacedata.first; | |||||||||
| ID *pinid = sbuts->pinid; | |||||||||
| if (pinid == NULL || ((GS(pinid->name) == ID_OB) && (Object *)pinid == ob)) { | |||||||||
| return area; | |||||||||
| } | |||||||||
| } | |||||||||
| } | |||||||||
| return NULL; | |||||||||
| } | |||||||||
| static SpaceProperties *find_space_properties(const bContext *C) | |||||||||
| { | |||||||||
| ScrArea *area = find_area_properties(C); | |||||||||
| if (area != NULL) { | |||||||||
| return area->spacedata.first; | |||||||||
| } | |||||||||
| return NULL; | |||||||||
| } | |||||||||
| static void template_texture_show(bContext *C, void *data_p, void *prop_p) | static void template_texture_show(bContext *C, void *data_p, void *prop_p) | ||||||||
| { | { | ||||||||
| SpaceProperties *sbuts = CTX_wm_space_properties(C); | if (data_p == NULL || prop_p == NULL) { | ||||||||
| ButsContextTexture *ct = (sbuts) ? sbuts->texuser : NULL; | return; | ||||||||
| ButsTextureUser *user; | } | ||||||||
| ScrArea *area = find_area_properties(C); | |||||||||
| if (area == NULL) { | |||||||||
| return; | |||||||||
| } | |||||||||
| SpaceProperties *sbuts = (SpaceProperties *)area->spacedata.first; | |||||||||
| ButsContextTexture *ct = (sbuts) ? sbuts->texuser : NULL; | |||||||||
| if (!ct) { | if (!ct) { | ||||||||
| return; | return; | ||||||||
| } | } | ||||||||
| ButsTextureUser *user; | |||||||||
| for (user = ct->users.first; user; user = user->next) { | for (user = ct->users.first; user; user = user->next) { | ||||||||
| if (user->ptr.data == data_p && user->prop == prop_p) { | if (user->ptr.data == data_p && user->prop == prop_p) { | ||||||||
| break; | break; | ||||||||
| } | } | ||||||||
| } | } | ||||||||
| if (user) { | if (user) { | ||||||||
| /* select texture */ | /* select texture */ | ||||||||
| template_texture_select(C, user, NULL); | template_texture_select(C, user, NULL); | ||||||||
| /* change context */ | /* change context */ | ||||||||
| sbuts->mainb = BCONTEXT_TEXTURE; | sbuts->mainb = BCONTEXT_TEXTURE; | ||||||||
| sbuts->mainbuser = sbuts->mainb; | sbuts->mainbuser = sbuts->mainb; | ||||||||
| sbuts->preview = 1; | sbuts->preview = 1; | ||||||||
| /* redraw editor */ | /* redraw editor */ | ||||||||
| ED_area_tag_redraw(CTX_wm_area(C)); | ED_area_tag_redraw(area); | ||||||||
| } | } | ||||||||
| } | } | ||||||||
| /* Button to quickly show texture in Properties Editor texture tab. */ | |||||||||
| void uiTemplateTextureShow(uiLayout *layout, const bContext *C, PointerRNA *ptr, PropertyRNA *prop) | void uiTemplateTextureShow(uiLayout *layout, const bContext *C, PointerRNA *ptr, PropertyRNA *prop) | ||||||||
| { | { | ||||||||
| /* button to quickly show texture in texture tab */ | /* Only show the button if there is actually a texture assigned. */ | ||||||||
| SpaceProperties *sbuts = CTX_wm_space_properties(C); | Tex *texture = RNA_property_pointer_get(ptr, prop).data; | ||||||||
| ButsContextTexture *ct = (sbuts) ? sbuts->texuser : NULL; | if (texture == NULL) { | ||||||||
| ButsTextureUser *user; | return; | ||||||||
| } | |||||||||
| /* only show button in other tabs in properties editor */ | /* Only show the button if we are not in the Properties Editor's texture tab. */ | ||||||||
| if (!ct || sbuts->mainb == BCONTEXT_TEXTURE) { | SpaceProperties *sbuts_context = CTX_wm_space_properties(C); | ||||||||
| if (sbuts_context != NULL && sbuts_context->mainb == BCONTEXT_TEXTURE) { | |||||||||
| return; | return; | ||||||||
| } | } | ||||||||
| SpaceProperties *sbuts = find_space_properties(C); | |||||||||
| ButsContextTexture *ct = (sbuts) ? sbuts->texuser : NULL; | |||||||||
| /* find corresponding texture user */ | /* find corresponding texture user */ | ||||||||
| ButsTextureUser *user; | |||||||||
| bool user_found = false; | |||||||||
| if (ct != NULL) { | |||||||||
| for (user = ct->users.first; user; user = user->next) { | for (user = ct->users.first; user; user = user->next) { | ||||||||
| if (user->ptr.data == ptr->data && user->prop == prop) { | if (user->ptr.data == ptr->data && user->prop == prop) { | ||||||||
| user_found = true; | |||||||||
| break; | break; | ||||||||
| } | } | ||||||||
| } | } | ||||||||
| } | |||||||||
| /* draw button */ | /* Draw button (disabled if we cannot find a Properties Editor to display this in). */ | ||||||||
| if (user) { | |||||||||
| uiBlock *block = uiLayoutGetBlock(layout); | uiBlock *block = uiLayoutGetBlock(layout); | ||||||||
| uiBut *but; | uiBut *but; | ||||||||
| but = uiDefIconBut(block, | but = uiDefIconBut(block, | ||||||||
| UI_BTYPE_BUT, | UI_BTYPE_BUT, | ||||||||
| 0, | 0, | ||||||||
| ICON_PROPERTIES, | ICON_PROPERTIES, | ||||||||
| 0, | 0, | ||||||||
| 0, | 0, | ||||||||
| UI_UNIT_X, | UI_UNIT_X, | ||||||||
| UI_UNIT_Y, | UI_UNIT_Y, | ||||||||
| NULL, | NULL, | ||||||||
| 0.0, | 0.0, | ||||||||
| 0.0, | 0.0, | ||||||||
| 0.0, | 0.0, | ||||||||
| 0.0, | 0.0, | ||||||||
| TIP_("Show texture in texture tab")); | TIP_("Show texture in texture tab")); | ||||||||
| UI_but_func_set(but, template_texture_show, user->ptr.data, user->prop); | UI_but_func_set(but, | ||||||||
| template_texture_show, | |||||||||
| user_found ? user->ptr.data : NULL, | |||||||||
| user_found ? user->prop : NULL); | |||||||||
| if (ct == NULL) { | |||||||||
| UI_but_disable(but, TIP_("No (unpinned) Properties Editor found to display texture in")); | |||||||||
| } | |||||||||
| else if (!user_found) { | |||||||||
| UI_but_disable(but, TIP_("No texture user found")); | |||||||||
| } | } | ||||||||
| } | } | ||||||||
Better just use RNA_Node and check that node->type == GEO_NODE_ATTRIBUTE_SAMPLE_TEXTURE before.