diff options
author | Brecht Van Lommel <brechtvanlommel@pandora.be> | 2011-11-08 17:07:16 +0400 |
---|---|---|
committer | Brecht Van Lommel <brechtvanlommel@pandora.be> | 2011-11-08 17:07:16 +0400 |
commit | 28ee0f92184af8ba6f44d08eda23ce5eb3815697 (patch) | |
tree | 6aada8d509c7470bd3bff6e52ba32e1fd54ef2ee /source/blender/editors | |
parent | 19df3147f6920a2856bccb6e4601d57288119999 (diff) |
Texturing: texture and 3d view draw type changes, these should only have any
effect for a render engine using new shading nodes. In short:
* No longer uses images assigned to faces in the uv layer, rather the active
image texture node is what is edited/painted/drawn.
* Textured draw type now shows the active image texture node, with solid
lighting.
* Material draw mode shows GLSL shader of a simplified material node tree,
using solid lighting.
* Textures for modifiers, brushes, etc, are now available from a dropdown in
the texture tab in the properties editor. These do not use new shading nodes
yet.
http://wiki.blender.org/index.php/Dev:2.6/Source/Render/TextureWorkflow
Diffstat (limited to 'source/blender/editors')
20 files changed, 1098 insertions, 162 deletions
diff --git a/source/blender/editors/include/ED_uvedit.h b/source/blender/editors/include/ED_uvedit.h index 2b4c213bc52..0666884351a 100644 --- a/source/blender/editors/include/ED_uvedit.h +++ b/source/blender/editors/include/ED_uvedit.h @@ -33,19 +33,26 @@ struct ARegionType; struct EditFace; struct Image; +struct Main; +struct ImageUser; struct MTFace; struct Object; struct Scene; +struct SpaceImage; struct bContext; +struct bNode; struct wmKeyConfig; /* uvedit_ops.c */ void ED_operatortypes_uvedit(void); void ED_keymap_uvedit(struct wmKeyConfig *keyconf); -void ED_uvedit_assign_image(struct Scene *scene, struct Object *obedit, struct Image *ima, struct Image *previma); +void ED_uvedit_assign_image(struct Main *bmain, struct Scene *scene, struct Object *obedit, struct Image *ima, struct Image *previma); int ED_uvedit_minmax(struct Scene *scene, struct Image *ima, struct Object *obedit, float *min, float *max); +int ED_object_get_active_image(struct Object *ob, int mat_nr, struct Image **ima, struct ImageUser **iuser, struct bNode **node); +void ED_object_assign_active_image(struct Main *bmain, struct Object *ob, int mat_nr, struct Image *ima); + int ED_uvedit_test_silent(struct Object *obedit); int ED_uvedit_test(struct Object *obedit); diff --git a/source/blender/editors/include/UI_interface.h b/source/blender/editors/include/UI_interface.h index 02b8cc9e2c6..329f4599e01 100644 --- a/source/blender/editors/include/UI_interface.h +++ b/source/blender/editors/include/UI_interface.h @@ -758,6 +758,8 @@ void uiTemplateKeymapItemProperties(uiLayout *layout, struct PointerRNA *ptr); void uiTemplateList(uiLayout *layout, struct bContext *C, struct PointerRNA *ptr, const char *propname, struct PointerRNA *activeptr, const char *activeprop, const char *prop_list, int rows, int maxrows, int type); void uiTemplateNodeLink(uiLayout *layout, struct bNodeTree *ntree, struct bNode *node, struct bNodeSocket *input); void uiTemplateNodeView(uiLayout *layout, struct bContext *C, struct bNodeTree *ntree, struct bNode *node, struct bNodeSocket *input); +void uiTemplateTextureUser(uiLayout *layout, struct bContext *C); +void uiTemplateTextureShow(uiLayout *layout, struct bContext *C, struct PointerRNA *ptr, struct PropertyRNA *prop); void uiTemplateMovieClip(struct uiLayout *layout, struct bContext *C, struct PointerRNA *ptr, const char *propname, int compact); void uiTemplateTrack(struct uiLayout *layout, struct PointerRNA *ptr, const char *propname); diff --git a/source/blender/editors/interface/interface_templates.c b/source/blender/editors/interface/interface_templates.c index 7c745c3cfef..a3d71674a03 100644 --- a/source/blender/editors/interface/interface_templates.c +++ b/source/blender/editors/interface/interface_templates.c @@ -332,7 +332,7 @@ static const char *template_id_browse_tip(StructRNA *type) return N_("Browse ID data to be linked"); } -static void template_ID(bContext *C, uiLayout *layout, TemplateID *template, StructRNA *type, int flag, const char *newop, const char *openop, const char *unlinkop) +static void template_ID(bContext *C, uiLayout *layout, TemplateID *template, StructRNA *type, short idcode, int flag, const char *newop, const char *openop, const char *unlinkop) { uiBut *but; uiBlock *block; @@ -478,6 +478,9 @@ static void template_ID(bContext *C, uiLayout *layout, TemplateID *template, Str if((idfrom && idfrom->lib) || !editable) uiButSetFlag(but, UI_BUT_DISABLED); } + + if(idcode == ID_TE) + uiTemplateTextureShow(layout, C, &template->ptr, template->prop); uiBlockEndAlign(block); } @@ -487,6 +490,7 @@ static void ui_template_id(uiLayout *layout, bContext *C, PointerRNA *ptr, const TemplateID *template; PropertyRNA *prop; StructRNA *type; + short idcode; prop= RNA_struct_find_property(ptr, propname); @@ -507,14 +511,15 @@ static void ui_template_id(uiLayout *layout, bContext *C, PointerRNA *ptr, const flag |= UI_ID_OPEN; type= RNA_property_pointer_type(ptr, prop); - template->idlb= which_libbase(CTX_data_main(C), RNA_type_to_ID_code(type)); + idcode= RNA_type_to_ID_code(type); + template->idlb= which_libbase(CTX_data_main(C), idcode); /* create UI elements for this template * - template_ID makes a copy of the template data and assigns it to the relevant buttons */ if(template->idlb) { uiLayoutRow(layout, 1); - template_ID(C, layout, template, type, flag, newop, openop, unlinkop); + template_ID(C, layout, template, type, idcode, flag, newop, openop, unlinkop); } MEM_freeN(template); diff --git a/source/blender/editors/mesh/mesh_data.c b/source/blender/editors/mesh/mesh_data.c index ed890fd9b90..6e35865fb4d 100644 --- a/source/blender/editors/mesh/mesh_data.c +++ b/source/blender/editors/mesh/mesh_data.c @@ -51,6 +51,7 @@ #include "BKE_displist.h" #include "BKE_image.h" #include "BKE_library.h" +#include "BKE_main.h" #include "BKE_material.h" #include "BKE_mesh.h" #include "BKE_report.h" @@ -331,6 +332,7 @@ void MESH_OT_uv_texture_add(wmOperatorType *ot) static int drop_named_image_invoke(bContext *C, wmOperator *op, wmEvent *event) { + Main *bmain= CTX_data_main(C); Scene *scene= CTX_data_scene(C); View3D *v3d= CTX_wm_view3d(C); Base *base= ED_view3d_give_base_under_cursor(C, event->mval); @@ -375,7 +377,7 @@ static int drop_named_image_invoke(bContext *C, wmOperator *op, wmEvent *event) if(me->edit_mesh==NULL) return OPERATOR_CANCELLED; - ED_uvedit_assign_image(scene, obedit, ima, NULL); + ED_uvedit_assign_image(bmain, scene, obedit, ima, NULL); if(exitmode) { load_editMesh(scene, obedit); diff --git a/source/blender/editors/sculpt_paint/paint_image.c b/source/blender/editors/sculpt_paint/paint_image.c index ce603ce80b6..e283927b76f 100644 --- a/source/blender/editors/sculpt_paint/paint_image.c +++ b/source/blender/editors/sculpt_paint/paint_image.c @@ -79,6 +79,7 @@ #include "BKE_object.h" #include "BKE_paint.h" #include "BKE_report.h" +#include "BKE_scene.h" #include "BIF_gl.h" #include "BIF_glutil.h" @@ -88,6 +89,7 @@ #include "ED_image.h" #include "ED_screen.h" #include "ED_sculpt.h" +#include "ED_uvedit.h" #include "ED_view3d.h" #include "WM_api.h" @@ -498,6 +500,40 @@ static void image_undo_free(ListBase *lb) MEM_freeN(tile->rect); } +/* get active image for face depending on old/new shading system */ + +static Image *imapaint_face_image(const ImagePaintState *s, int face_index) +{ + Image *ima; + + if(scene_use_new_shading_nodes(s->scene)) { + MFace *mf = s->me->mface+face_index; + ED_object_get_active_image(s->ob, mf->mat_nr, &ima, NULL, NULL); + } + else { + MTFace *tf = s->me->mtface+face_index; + ima = tf->tpage; + } + + return ima; +} + +static Image *project_paint_face_image(const ProjPaintState *ps, int face_index) +{ + Image *ima; + + if(scene_use_new_shading_nodes(ps->scene)) { + MFace *mf = ps->dm_mface+face_index; + ED_object_get_active_image(ps->ob, mf->mat_nr, &ima, NULL, NULL); + } + else { + MTFace *tf = ps->dm_mtface+face_index; + ima = tf->tpage; + } + + return ima; +} + /* fast projection bucket array lookup, use the safe version for bound checking */ static int project_bucket_offset(const ProjPaintState *ps, const float projCoSS[2]) { @@ -670,6 +706,7 @@ static int project_paint_PickColor(const ProjPaintState *ps, float pt[2], float int side; int face_index; MTFace *tf; + Image *ima; ImBuf *ibuf; int xi, yi; @@ -687,8 +724,9 @@ static int project_paint_PickColor(const ProjPaintState *ps, float pt[2], float else { /* QUAD */ interp_v2_v2v2v2(uv, tf->uv[0], tf->uv[2], tf->uv[3], w); } - - ibuf = tf->tpage->ibufs.first; /* we must have got the imbuf before getting here */ + + ima = project_paint_face_image(ps, face_index); + ibuf = ima->ibufs.first; /* we must have got the imbuf before getting here */ if (!ibuf) return 0; if (interp) { @@ -1053,6 +1091,9 @@ static int check_seam(const ProjPaintState *ps, const int orig_face, const int o /* Only need to check if 'i2_fidx' is valid because we know i1_fidx is the same vert on both faces */ if (i2_fidx != -1) { + Image *tpage = project_paint_face_image(ps, face_index); + Image *orig_tpage = project_paint_face_image(ps, orig_face); + /* This IS an adjacent face!, now lets check if the UVs are ok */ tf = ps->dm_mtface + face_index; @@ -1061,7 +1102,7 @@ static int check_seam(const ProjPaintState *ps, const int orig_face, const int o *orig_fidx = (i1_fidx < i2_fidx) ? i1_fidx : i2_fidx; /* first test if they have the same image */ - if ( (orig_tf->tpage == tf->tpage) && + if ( (orig_tpage == tpage) && cmp_uv(orig_tf->uv[orig_i1_fidx], tf->uv[i1_fidx]) && cmp_uv(orig_tf->uv[orig_i2_fidx], tf->uv[i2_fidx]) ) { @@ -1308,9 +1349,10 @@ static float project_paint_uvpixel_mask( if (ps->do_layer_stencil) { /* another UV layers image is masking this one's */ ImBuf *ibuf_other; + Image *other_tpage = project_paint_face_image(ps, face_index); const MTFace *tf_other = ps->dm_mtface_stencil + face_index; - if (tf_other->tpage && (ibuf_other = BKE_image_get_ibuf(tf_other->tpage, NULL))) { + if (other_tpage && (ibuf_other = BKE_image_get_ibuf(other_tpage, NULL))) { /* BKE_image_get_ibuf - TODO - this may be slow */ unsigned char rgba_ub[4]; float rgba_f[4]; @@ -1464,9 +1506,10 @@ static ProjPixel *project_paint_uvpixel_init( if (ps->tool==PAINT_TOOL_CLONE) { if (ps->dm_mtface_clone) { ImBuf *ibuf_other; + Image *other_tpage = project_paint_face_image(ps, face_index); const MTFace *tf_other = ps->dm_mtface_clone + face_index; - if (tf_other->tpage && (ibuf_other = BKE_image_get_ibuf(tf_other->tpage, NULL))) { + if (other_tpage && (ibuf_other = BKE_image_get_ibuf(other_tpage, NULL))) { /* BKE_image_get_ibuf - TODO - this may be slow */ if (ibuf->rect_float) { @@ -2684,11 +2727,8 @@ static void project_bucket_init(const ProjPaintState *ps, const int thread_index LinkNode *node; int face_index, image_index=0; ImBuf *ibuf = NULL; + Image *tpage_last = NULL, *tpage; Image *ima = NULL; - MTFace *tf; - - Image *tpage_last = NULL; - if (ps->image_tot==1) { /* Simple loop, no context switching */ @@ -2706,9 +2746,9 @@ static void project_bucket_init(const ProjPaintState *ps, const int thread_index face_index = GET_INT_FROM_POINTER(node->link); /* Image context switching */ - tf = ps->dm_mtface+face_index; - if (tpage_last != tf->tpage) { - tpage_last = tf->tpage; + tpage = project_paint_face_image(ps, face_index); + if (tpage_last != tpage) { + tpage_last = tpage; for (image_index=0; image_index < ps->image_tot; image_index++) { if (ps->projImages[image_index].ima == tpage_last) { @@ -2876,7 +2916,7 @@ static void project_paint_begin(ProjPaintState *ps) LinkNode *node; ProjPaintImage *projIma; - Image *tpage_last = NULL; + Image *tpage_last = NULL, *tpage; /* Face vars */ MFace *mf; @@ -3210,7 +3250,9 @@ static void project_paint_begin(ProjPaintState *ps) } #endif - if (tf->tpage && ((((Mesh *)ps->ob->data)->editflag & ME_EDIT_PAINT_MASK)==0 || mf->flag & ME_FACE_SEL)) { + tpage = project_paint_face_image(ps, face_index); + + if (tpage && ((((Mesh *)ps->ob->data)->editflag & ME_EDIT_PAINT_MASK)==0 || mf->flag & ME_FACE_SEL)) { float *v1coSS, *v2coSS, *v3coSS, *v4coSS=NULL; @@ -3283,17 +3325,17 @@ static void project_paint_begin(ProjPaintState *ps) } } - if (tpage_last != tf->tpage) { + if (tpage_last != tpage) { - image_index = BLI_linklist_index(image_LinkList, tf->tpage); + image_index = BLI_linklist_index(image_LinkList, tpage); - if (image_index==-1 && BKE_image_get_ibuf(tf->tpage, NULL)) { /* MemArena dosnt have an append func */ - BLI_linklist_append(&image_LinkList, tf->tpage); + if (image_index==-1 && BKE_image_get_ibuf(tpage, NULL)) { /* MemArena dosnt have an append func */ + BLI_linklist_append(&image_LinkList, tpage); image_index = ps->image_tot; ps->image_tot++; } - tpage_last = tf->tpage; + tpage_last = tpage; } if (image_index != -1) { @@ -4481,7 +4523,7 @@ static int imapaint_paint_stroke(ViewContext *vc, ImagePaintState *s, BrushPaint ) { ImBuf *ibuf; - newimage = (s->me->mtface+newfaceindex)->tpage; + newimage = imapaint_face_image(s, newfaceindex); ibuf= BKE_image_get_ibuf(newimage, s->sima? &s->sima->iuser: NULL); if(ibuf && ibuf->rect) diff --git a/source/blender/editors/space_buttons/CMakeLists.txt b/source/blender/editors/space_buttons/CMakeLists.txt index dbb96b68587..ee118f12062 100644 --- a/source/blender/editors/space_buttons/CMakeLists.txt +++ b/source/blender/editors/space_buttons/CMakeLists.txt @@ -38,6 +38,7 @@ set(SRC buttons_context.c buttons_header.c buttons_ops.c + buttons_texture.c space_buttons.c buttons_intern.h diff --git a/source/blender/editors/space_buttons/buttons_context.c b/source/blender/editors/space_buttons/buttons_context.c index 6d6f73e98d8..e38ac7bd413 100644 --- a/source/blender/editors/space_buttons/buttons_context.c +++ b/source/blender/editors/space_buttons/buttons_context.c @@ -54,7 +54,6 @@ #include "BKE_screen.h" #include "BKE_texture.h" - #include "RNA_access.h" #include "ED_armature.h" @@ -66,13 +65,6 @@ #include "buttons_intern.h" // own include -typedef struct ButsContextPath { - PointerRNA ptr[8]; - int len; - int flag; - int tex_ctx; -} ButsContextPath; - static int set_pointer_type(ButsContextPath *path, bContextDataResult *result, StructRNA *type) { PointerRNA *ptr; @@ -373,102 +365,141 @@ static int buttons_context_path_brush(ButsContextPath *path) return 0; } -static int buttons_context_path_texture(ButsContextPath *path) +static int buttons_context_path_texture(ButsContextPath *path, ButsContextTexture *ct) { - Material *ma; - Lamp *la; - Brush *br; - World *wo; - ParticleSystem *psys; - Tex *tex; - PointerRNA *ptr= &path->ptr[path->len-1]; - int orig_len = path->len; + if(ct) { + /* new shading system */ + PointerRNA *ptr= &path->ptr[path->len-1]; + ID *id; - /* if we already have a (pinned) texture, we're done */ - if(RNA_struct_is_a(ptr->type, &RNA_Texture)) { - return 1; - } - /* try brush */ - if((path->tex_ctx == SB_TEXC_BRUSH) && buttons_context_path_brush(path)) { - br= path->ptr[path->len-1].data; - - if(br) { - tex= give_current_brush_texture(br); + /* if we already have a (pinned) texture, we're done */ + if(RNA_struct_is_a(ptr->type, &RNA_Texture)) + return 1; - RNA_id_pointer_create(&tex->id, &path->ptr[path->len]); + if(!ct->user) + return 0; + + id= ct->user->id; + + if(id) { + if(GS(id->name) == ID_BR) + buttons_context_path_brush(path); + else if(GS(id->name) == ID_MA) + buttons_context_path_material(path, 0); + else if(GS(id->name) == ID_WO) + buttons_context_path_world(path); + else if(GS(id->name) == ID_LA) + buttons_context_path_data(path, OB_LAMP); + else if(GS(id->name) == ID_PA) + buttons_context_path_particle(path); + else if(GS(id->name) == ID_OB) + buttons_context_path_object(path); + } + + if(ct->texture) { + RNA_id_pointer_create(&ct->texture->id, &path->ptr[path->len]); path->len++; - return 1; } - } - /* try world */ - if((path->tex_ctx == SB_TEXC_WORLD) && buttons_context_path_world(path)) { - wo= path->ptr[path->len-1].data; - - if(wo && GS(wo->id.name)==ID_WO) { - tex= give_current_world_texture(wo); - RNA_id_pointer_create(&tex->id, &path->ptr[path->len]); - path->len++; + return 1; + } + else { + /* old shading system */ + Material *ma; + Lamp *la; + Brush *br; + World *wo; + ParticleSystem *psys; + Tex *tex; + PointerRNA *ptr= &path->ptr[path->len-1]; + int orig_len = path->len; + + /* if we already have a (pinned) texture, we're done */ + if(RNA_struct_is_a(ptr->type, &RNA_Texture)) { return 1; } - } - /* try particles */ - if((path->tex_ctx == SB_TEXC_PARTICLES) && buttons_context_path_particle(path)) { - if(path->ptr[path->len-1].type == &RNA_ParticleSettings) { - ParticleSettings *part = path->ptr[path->len-1].data; + /* try brush */ + if((path->tex_ctx == SB_TEXC_BRUSH) && buttons_context_path_brush(path)) { + br= path->ptr[path->len-1].data; + + if(br) { + tex= give_current_brush_texture(br); - tex= give_current_particle_texture(part); - RNA_id_pointer_create(&tex->id, &path->ptr[path->len]); - path->len++; - return 1; + RNA_id_pointer_create(&tex->id, &path->ptr[path->len]); + path->len++; + return 1; + } } - else { - psys= path->ptr[path->len-1].data; + /* try world */ + if((path->tex_ctx == SB_TEXC_WORLD) && buttons_context_path_world(path)) { + wo= path->ptr[path->len-1].data; - if(psys && psys->part && GS(psys->part->id.name)==ID_PA) { - tex= give_current_particle_texture(psys->part); + if(wo && GS(wo->id.name)==ID_WO) { + tex= give_current_world_texture(wo); RNA_id_pointer_create(&tex->id, &path->ptr[path->len]); path->len++; return 1; } } - } - /* try material */ - if(buttons_context_path_material(path, 1)) { - ma= path->ptr[path->len-1].data; + /* try particles */ + if((path->tex_ctx == SB_TEXC_PARTICLES) && buttons_context_path_particle(path)) { + if(path->ptr[path->len-1].type == &RNA_ParticleSettings) { + ParticleSettings *part = path->ptr[path->len-1].data; - if(ma) { - tex= give_current_material_texture(ma); + tex= give_current_particle_texture(part); + RNA_id_pointer_create(&tex->id, &path->ptr[path->len]); + path->len++; + return 1; + } + else { + psys= path->ptr[path->len-1].data; - RNA_id_pointer_create(&tex->id, &path->ptr[path->len]); - path->len++; - return 1; + if(psys && psys->part && GS(psys->part->id.name)==ID_PA) { + tex= give_current_particle_texture(psys->part); + + RNA_id_pointer_create(&tex->id, &path->ptr[path->len]); + path->len++; + return 1; + } + } } - } - /* try lamp */ - if(buttons_context_path_data(path, OB_LAMP)) { - la= path->ptr[path->len-1].data; + /* try material */ + if(buttons_context_path_material(path, 1)) { + ma= path->ptr[path->len-1].data; - if(la) { - tex= give_current_lamp_texture(la); + if(ma) { + tex= give_current_material_texture(ma); - RNA_id_pointer_create(&tex->id, &path->ptr[path->len]); - path->len++; - return 1; + RNA_id_pointer_create(&tex->id, &path->ptr[path->len]); + path->len++; + return 1; + } } - } - /* try brushes again in case of no material, lamp, etc */ - path->len = orig_len; - if(buttons_context_path_brush(path)) { - br= path->ptr[path->len-1].data; - - if(br) { - tex= give_current_brush_texture(br); + /* try lamp */ + if(buttons_context_path_data(path, OB_LAMP)) { + la= path->ptr[path->len-1].data; + + if(la) { + tex= give_current_lamp_texture(la); + + RNA_id_pointer_create(&tex->id, &path->ptr[path->len]); + path->len++; + return 1; + } + } + /* try brushes again in case of no material, lamp, etc */ + path->len = orig_len; + if(buttons_context_path_brush(path)) { + br= path->ptr[path->len-1].data; - RNA_id_pointer_create(&tex->id, &path->ptr[path->len]); - path->len++; - return 1; + if(br) { + tex= give_current_brush_texture(br); + + RNA_id_pointer_create(&tex->id, &path->ptr[path->len]); + path->len++; + return 1; + } } } @@ -530,7 +561,7 @@ static int buttons_context_path(const bContext *C, ButsContextPath *path, int ma found= buttons_context_path_material(path, 0); break; case BCONTEXT_TEXTURE: - found= buttons_context_path_texture(path); + found= buttons_context_path_texture(path, sbuts->texuser); break; case BCONTEXT_BONE: found= buttons_context_path_bone(path); @@ -580,6 +611,8 @@ void buttons_context_compute(const bContext *C, SpaceButs *sbuts) PointerRNA *ptr; int a, pflag= 0, flag= 0; + buttons_texture_context_compute(C, sbuts); + if(!sbuts->path) sbuts->path= MEM_callocN(sizeof(ButsContextPath), "ButsContextPath"); @@ -649,7 +682,8 @@ void buttons_context_compute(const bContext *C, SpaceButs *sbuts) const char *buttons_context_dir[] = { "world", "object", "mesh", "armature", "lattice", "curve", "meta_ball", "lamp", "speaker", "camera", "material", "material_slot", - "texture", "texture_slot", "bone", "edit_bone", "pose_bone", "particle_system", "particle_system_editable", + "texture", "texture_slot", "texture_user", "bone", "edit_bone", + "pose_bone", "particle_system", "particle_system_editable", "cloth", "soft_body", "fluid", "smoke", "collision", "brush", NULL}; int buttons_context(const bContext *C, const char *member, bContextDataResult *result) @@ -710,7 +744,17 @@ int buttons_context(const bContext *C, const char *member, bContextDataResult *r return 1; } else if(CTX_data_equals(member, "texture")) { - set_pointer_type(path, result, &RNA_Texture); + ButsContextTexture *ct= sbuts->texuser; + + if(ct) { + /* new shading system */ + CTX_data_pointer_set(result, &ct->texture->id, &RNA_Texture, ct->texture); + } + else { + /* old shading system */ + set_pointer_type(path, result, &RNA_Texture); + } + return 1; } else if(CTX_data_equals(member, "material_slot")) { @@ -729,23 +773,52 @@ int buttons_context(const bContext *C, const char *member, bContextDataResult *r return 1; } - else if(CTX_data_equals(member, "texture_node")) { - PointerRNA *ptr; + else if(CTX_data_equals(member, "texture_user")) { + ButsContextTexture *ct= sbuts->texuser; - if((ptr=get_pointer_type(path, &RNA_Material))) { - Material *ma= ptr->data; + if(!ct) + return 0; /* old shading system */ - if(ma) { - bNode *node= give_current_material_texture_node(ma); - CTX_data_pointer_set(result, &ma->id, &RNA_Node, node); - } + if(ct->user && ct->user->ptr.data) { + ButsTextureUser *user= ct->user; + CTX_data_pointer_set(result, user->ptr.id.data, user->ptr.type, user->ptr.data); } return 1; } + else if(CTX_data_equals(member, "texture_node")) { + ButsContextTexture *ct= sbuts->texuser; + + if(ct) { + /* new shading system */ + if(ct->user && ct->user->node) + CTX_data_pointer_set(result, &ct->user->ntree->id, &RNA_Node, ct->user->node); + + return 1; + } + else { + /* old shading system */ + PointerRNA *ptr; + + if((ptr=get_pointer_type(path, &RNA_Material))) { + Material *ma= ptr->data; + + if(ma) { + bNode *node= give_current_material_texture_node(ma); + CTX_data_pointer_set(result, &ma->id, &RNA_Node, node); + } + } + + return 1; + } + } else if(CTX_data_equals(member, "texture_slot")) { + ButsContextTexture *ct= sbuts->texuser; PointerRNA *ptr; + if(ct) + return 0; /* new shading system */ + if((ptr=get_pointer_type(path, &RNA_Material))) { Material *ma= ptr->data; diff --git a/source/blender/editors/space_buttons/buttons_intern.h b/source/blender/editors/space_buttons/buttons_intern.h index 27084488163..aa692a940d8 100644 --- a/source/blender/editors/space_buttons/buttons_intern.h +++ b/source/blender/editors/space_buttons/buttons_intern.h @@ -31,14 +31,20 @@ #ifndef ED_BUTTONS_INTERN_H #define ED_BUTTONS_INTERN_H +#include "DNA_listBase.h" +#include "RNA_types.h" + struct ARegion; struct ARegionType; +struct ID; +struct SpaceButs; +struct Tex; struct bContext; struct bContextDataResult; -struct SpaceButs; +struct bNode; +struct bNodeTree; struct uiLayout; struct wmOperatorType; -struct ID; /* buts->scaflag */ #define BUTS_SENS_SEL 1 @@ -53,6 +59,42 @@ struct ID; #define BUTS_SENS_STATE 512 #define BUTS_ACT_STATE 1024 +/* context data */ + +typedef struct ButsContextPath { + PointerRNA ptr[8]; + int len; + int flag; + int tex_ctx; +} ButsContextPath; + +typedef struct ButsTextureUser { + struct ButsTextureUser *next, *prev; + + struct ID *id; + + PointerRNA ptr; + PropertyRNA *prop; + + struct bNodeTree *ntree; + struct bNode *node; + + const char *category; + int icon; + const char *name; + + int index; +} ButsTextureUser; + +typedef struct ButsContextTexture { + ListBase users; + + struct Tex *texture; + + struct ButsTextureUser *user; + int index; +} ButsContextTexture; + /* internal exports only */ /* buttons_header.c */ @@ -67,6 +109,9 @@ struct ID *buttons_context_id_path(const struct bContext *C); extern const char *buttons_context_dir[]; /* doc access */ +/* buttons_texture.c */ +void buttons_texture_context_compute(const struct bContext *C, struct SpaceButs *sbuts); + /* buttons_ops.c */ void BUTTONS_OT_file_browse(struct wmOperatorType *ot); void BUTTONS_OT_directory_browse(struct wmOperatorType *ot); diff --git a/source/blender/editors/space_buttons/buttons_texture.c b/source/blender/editors/space_buttons/buttons_texture.c new file mode 100644 index 00000000000..dd9f3c57896 --- /dev/null +++ b/source/blender/editors/space_buttons/buttons_texture.c @@ -0,0 +1,469 @@ +/* + * $Id$ + * + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2009 Blender Foundation. + * All rights reserved. + * + * Contributor(s): Blender Foundation + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file blender/editors/space_buttons/buttons_texture.c + * \ingroup spbuttons + */ + + +#include <stdlib.h> +#include <string.h> + +#include "MEM_guardedalloc.h" + +#include "BLI_listbase.h" +#include "BLI_string.h" +#include "BLI_utildefines.h" + +#include "DNA_brush_types.h" +#include "DNA_ID.h" +#include "DNA_lamp_types.h" +#include "DNA_material_types.h" +#include "DNA_node_types.h" +#include "DNA_object_types.h" +#include "DNA_object_force.h" +#include "DNA_particle_types.h" +#include "DNA_scene_types.h" +#include "DNA_screen_types.h" +#include "DNA_space_types.h" +#include "DNA_world_types.h" + +#include "BKE_context.h" +#include "BKE_material.h" +#include "BKE_modifier.h" +#include "BKE_node.h" +#include "BKE_paint.h" +#include "BKE_particle.h" +#include "BKE_scene.h" + +#include "RNA_access.h" + +#include "UI_interface.h" +#include "UI_resources.h" + +#include "ED_node.h" +#include "ED_screen.h" + +#include "../interface/interface_intern.h" + +#include "buttons_intern.h" // own include + +/************************* Texture User **************************/ + +static void buttons_texture_user_property_add(ListBase *users, ID *id, + PointerRNA ptr, PropertyRNA *prop, + 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->category = category; + user->icon = icon; + user->name = name; + user->index = BLI_countlist(users); + + BLI_addtail(users, user); +} + +static void buttons_texture_user_node_add(ListBase *users, ID *id, + bNodeTree *ntree, bNode *node, + const char *category, int icon, const char *name) +{ + ButsTextureUser *user = MEM_callocN(sizeof(ButsTextureUser), "ButsTextureUser"); + + user->id= id; + user->ntree = ntree; + user->node = node; + user->category = category; + user->icon = icon; + user->name = name; + user->index = BLI_countlist(users); + + BLI_addtail(users, user); +} + +static void buttons_texture_users_find_nodetree(ListBase *users, ID *id, + bNodeTree *ntree, const char *category) +{ + bNode *node; + + if(ntree) { + for(node=ntree->nodes.first; node; node=node->next) { + if(node->typeinfo->nclass == NODE_CLASS_TEXTURE) { + PointerRNA ptr; + PropertyRNA *prop; + + RNA_pointer_create(&ntree->id, &RNA_Node, node, &ptr); + prop = RNA_struct_find_property(&ptr, "texture"); + + buttons_texture_user_node_add(users, id, ntree, node, + category, RNA_struct_ui_icon(ptr.type), node->name); + } + else if(node->type == NODE_GROUP && node->id) { + buttons_texture_users_find_nodetree(users, id, (bNodeTree*)node->id, category); + } + } + } +} + +static void buttons_texture_modifier_foreach(void *userData, Object *ob, ModifierData *md, const char *propname) +{ + PointerRNA ptr; + PropertyRNA *prop; + ListBase *users = userData; + + RNA_pointer_create(&ob->id, &RNA_Modifier, md, &ptr); + prop = RNA_struct_find_property(&ptr, propname); + + buttons_texture_user_property_add(users, &ob->id, ptr, prop, + "Modifiers", RNA_struct_ui_icon(ptr.type), md->name); +} + +static void buttons_texture_users_from_context(ListBase *users, const bContext *C, SpaceButs *sbuts) +{ + Scene *scene= NULL; + Object *ob= NULL; + Material *ma= NULL; + Lamp *la= NULL; + World *wrld= NULL; + Brush *brush= NULL; + ID *pinid = sbuts->pinid; + + /* get data from context */ + if(pinid) { + if(GS(pinid->name) == ID_SCE) + scene= (Scene*)pinid; + else if(GS(pinid->name) == ID_OB) + ob= (Object*)pinid; + else if(GS(pinid->name) == ID_LA) + la= (Lamp*)pinid; + else if(GS(pinid->name) == ID_WO) + wrld= (World*)pinid; + else if(GS(pinid->name) == ID_MA) + ma= (Material*)pinid; + else if(GS(pinid->name) == ID_BR) + brush= (Brush*)pinid; + } + + if(!scene) + scene= CTX_data_scene(C); + + if(!(pinid || pinid == &scene->id)) { + ob= (scene->basact)? scene->basact->object: NULL; + wrld= scene->world; + brush= paint_brush(paint_get_active(scene)); + } + + if(ob && ob->type == OB_LAMP && !la) + la= ob->data; + if(ob && !ma) + ma= give_current_material(ob, ob->actcol); + + /* fill users */ + users->first = users->last = NULL; + + if(ma) + buttons_texture_users_find_nodetree(users, &ma->id, ma->nodetree, "Material"); + if(la) + buttons_texture_users_find_nodetree(users, &la->id, la->nodetree, "Lamp"); + if(wrld) + buttons_texture_users_find_nodetree(users, &wrld->id, wrld->nodetree, "World"); + + if(ob) { + ParticleSystem *psys= psys_get_current(ob); + MTex *mtex; + int a; + + /* modifiers */ + modifiers_foreachTexLink(ob, buttons_texture_modifier_foreach, users); + + /* particle systems */ + if(psys) { + /* todo: these slots are not in the UI */ + for(a=0; a<MAX_MTEX; a++) { + mtex = psys->part->mtex[a]; + + if(mtex) { + PointerRNA ptr; + PropertyRNA *prop; + + RNA_pointer_create(&psys->part->id, &RNA_ParticleSettingsTextureSlot, mtex, &ptr); + prop = RNA_struct_find_property(&ptr, "texture"); + + buttons_texture_user_property_add(users, &psys->part->id, ptr, prop, + "Particles", RNA_struct_ui_icon(&RNA_ParticleSettings), psys->name); + } + } + } + + /* field */ + if(ob->pd && ob->pd->forcefield == PFIELD_TEXTURE) { + PointerRNA ptr; + PropertyRNA *prop; + + RNA_pointer_create(&ob->id, &RNA_FieldSettings, ob->pd, &ptr); + prop = RNA_struct_find_property(&ptr, "texture"); + + buttons_texture_user_property_add(users, &ob->id, ptr, prop, + "Fields", ICON_FORCE_TEXTURE, "Texture Field"); + } + } + + /* brush */ + if(brush) { + PointerRNA ptr; + PropertyRNA *prop; + + RNA_pointer_create(&brush->id, &RNA_BrushTextureSlot, &brush->mtex, &ptr); + prop= RNA_struct_find_property(&ptr, "texture"); + + buttons_texture_user_property_add(users, &brush->id, ptr, prop, + "Brush", ICON_BRUSH_DATA, brush->id.name+2); + } +} + +void buttons_texture_context_compute(const bContext *C, SpaceButs *sbuts) +{ + /* gatheravailable texture users in context. runs on every draw of + properties editor, before the buttons are created. */ + ButsContextTexture *ct= sbuts->texuser; + Scene *scene= CTX_data_scene(C); + + if(!scene_use_new_shading_nodes(scene)) { + if(ct) { + MEM_freeN(ct); + BLI_freelistN(&ct->users); + sbuts->texuser= NULL; + } + + return; + } + + if(!ct) { + ct= MEM_callocN(sizeof(ButsContextTexture), "ButsContextTexture"); + sbuts->texuser= ct; + } + else { + BLI_freelistN(&ct->users); + } + + buttons_texture_users_from_context(&ct->users, C, sbuts); + + /* set one user as active based on active index */ + if(ct->index >= BLI_countlist(&ct->users)) + ct->index= 0; + + ct->user = BLI_findlink(&ct->users, ct->index); + ct->texture = NULL; + + if(ct->user) { + if(ct->user->ptr.data) { + PointerRNA texptr; + Tex *tex; + + /* 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; + + /* 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) { + if(user->ntree == ct->user->ntree && user->node != ct->user->node) { + if(user->node->flag & NODE_ACTIVE_TEXTURE) { + ct->user = user; + ct->index = BLI_findindex(&ct->users, user); + break; + } + } + } + } + } +} + +static void template_texture_select(bContext *C, void *user_p, void *UNUSED(arg)) +{ + /* callback when selecting a texture user in the menu */ + SpaceButs *sbuts = CTX_wm_space_buts(C); + ButsContextTexture *ct= (sbuts)? sbuts->texuser: NULL; + ButsTextureUser *user = (ButsTextureUser*)user_p; + PointerRNA texptr; + Tex *tex; + + if(!ct) + return; + + /* set user as active */ + if(user->node) { + ED_node_set_active(CTX_data_main(C), user->ntree, user->node); + ct->texture = NULL; + } + else { + texptr = RNA_property_pointer_get(&user->ptr, user->prop); + tex = (RNA_struct_is_a(texptr.type, &RNA_Texture))? texptr.data: NULL; + + ct->texture = tex; + } + + ct->user = user; + ct->index = user->index; +} + +static void template_texture_user_menu(bContext *C, uiLayout *layout, void *UNUSED(arg)) +{ + /* callback when opening texture user selection menu, to create buttons. */ + SpaceButs *sbuts = CTX_wm_space_buts(C); + ButsContextTexture *ct= (sbuts)? sbuts->texuser: NULL; + ButsTextureUser *user; + uiBlock *block = uiLayoutGetBlock(layout); + const char *last_category = NULL; + + for(user=ct->users.first; user; user=user->next) { + uiBut *but; + char name[UI_MAX_NAME_STR]; + + /* add label per category */ + if(!last_category || strcmp(last_category, user->category) != 0) { + uiItemL(layout, user->category, ICON_NONE); + but= block->buttons.last; + but->flag= UI_TEXT_LEFT; + } + + /* create button */ + BLI_snprintf(name, UI_MAX_NAME_STR, " %s", user->name); + + but = uiDefIconTextBut(block, BUT, 0, user->icon, name, 0, 0, UI_UNIT_X*4, UI_UNIT_Y, + NULL, 0.0, 0.0, 0.0, 0.0, ""); + uiButSetNFunc(but, template_texture_select, MEM_dupallocN(user), NULL); + + last_category = user->category; + } +} + +void uiTemplateTextureUser(uiLayout *layout, bContext *C) +{ + /* texture user selection dropdown menu. the available users have been + gathered before drawing in ButsContextTexture, we merely need to + display the current item. */ + SpaceButs *sbuts = CTX_wm_space_buts(C); + ButsContextTexture *ct= (sbuts)? sbuts->texuser: NULL; + uiBlock *block = uiLayoutGetBlock(layout); + uiBut *but; + ButsTextureUser *user; + char name[UI_MAX_NAME_STR]; + + if(!ct) + return; + + /* get current user */ + user= ct->user; + + if(!user) { + uiItemL(layout, "No textures in context.", ICON_NONE); + return; + } + + /* create button */ + BLI_snprintf(name, UI_MAX_NAME_STR, "%s", user->name); + + if(user->icon) { + but= uiDefIconTextMenuBut(block, template_texture_user_menu, NULL, + user->icon, name, 0, 0, UI_UNIT_X*4, UI_UNIT_Y, ""); + } + else { + but= uiDefMenuBut(block, template_texture_user_menu, NULL, + name, 0, 0, UI_UNIT_X*4, UI_UNIT_Y, ""); + } + + /* some cosmetic tweaks */ + but->type= MENU; + but->flag |= UI_TEXT_LEFT; + but->flag &= ~UI_ICON_SUBMENU; +} + +/************************* Texture Show **************************/ + +static void template_texture_show(bContext *C, void *data_p, void *prop_p) +{ + SpaceButs *sbuts = CTX_wm_space_buts(C); + ButsContextTexture *ct= (sbuts)? sbuts->texuser: NULL; + ButsTextureUser *user; + + if(!ct) + return; + + for(user=ct->users.first; user; user=user->next) + if(user->ptr.data == data_p && user->prop == prop_p) + break; + + if(user) { + /* select texture */ + template_texture_select(C, user, NULL); + + /* change context */ + sbuts->mainb= BCONTEXT_TEXTURE; + sbuts->mainbuser= sbuts->mainb; + sbuts->preview= 1; + + /* redraw editor */ + ED_area_tag_redraw(CTX_wm_area(C)); + } +} + +void uiTemplateTextureShow(uiLayout *layout, bContext *C, PointerRNA *ptr, PropertyRNA *prop) +{ + /* button to quickly show texture in texture tab */ + SpaceButs *sbuts = CTX_wm_space_buts(C); + ButsContextTexture *ct= (sbuts)? sbuts->texuser: NULL; + ButsTextureUser *user; + + /* only show button in other tabs in properties editor */ + if(!ct || sbuts->mainb == BCONTEXT_TEXTURE) + return; + + /* find corresponding texture user */ + for(user=ct->users.first; user; user=user->next) + if(user->ptr.data == ptr->data && user->prop == prop) + break; + + /* draw button */ + if(user) { + uiBlock *block = uiLayoutGetBlock(layout); + uiBut *but; + + but= uiDefIconBut(block, BUT, 0, ICON_BUTS, 0, 0, UI_UNIT_X, UI_UNIT_Y, + NULL, 0.0, 0.0, 0.0, 0.0, "Show texture in texture tab"); + uiButSetFunc(but, template_texture_show, user->ptr.data, user->prop); + } +} + diff --git a/source/blender/editors/space_buttons/space_buttons.c b/source/blender/editors/space_buttons/space_buttons.c index 4c328d174e9..0c326af406f 100644 --- a/source/blender/editors/space_buttons/space_buttons.c +++ b/source/blender/editors/space_buttons/space_buttons.c @@ -104,6 +104,12 @@ static void buttons_free(SpaceLink *sl) if(sbuts->path) MEM_freeN(sbuts->path); + + if(sbuts->texuser) { + ButsContextTexture *ct= sbuts->texuser; + BLI_freelistN(&ct->users); + MEM_freeN(ct); + } } /* spacetype; init callback */ @@ -127,6 +133,7 @@ static SpaceLink *buttons_duplicate(SpaceLink *sl) /* clear or remove stuff from old */ sbutsn->ri= NULL; sbutsn->path= NULL; + sbutsn->texuser= NULL; return (SpaceLink *)sbutsn; } diff --git a/source/blender/editors/space_image/space_image.c b/source/blender/editors/space_image/space_image.c index 3b9876329ec..c29553a9c87 100644 --- a/source/blender/editors/space_image/space_image.c +++ b/source/blender/editors/space_image/space_image.c @@ -47,7 +47,10 @@ #include "BKE_colortools.h" #include "BKE_context.h" #include "BKE_image.h" +#include "BKE_global.h" +#include "BKE_main.h" #include "BKE_mesh.h" +#include "BKE_scene.h" #include "BKE_screen.h" #include "IMB_imbuf_types.h" @@ -81,7 +84,7 @@ Image *ED_space_image(SpaceImage *sima) /* called to assign images to UV faces */ void ED_space_image_set(bContext *C, SpaceImage *sima, Scene *scene, Object *obedit, Image *ima) { - ED_uvedit_assign_image(scene, obedit, ima, sima->image); + ED_uvedit_assign_image(CTX_data_main(C), scene, obedit, ima, sima->image); /* change the space ima after because uvedit_face_visible uses the space ima * to check if the face is displayed in UV-localview */ @@ -572,6 +575,7 @@ static void image_dropboxes(void) static void image_refresh(const bContext *C, ScrArea *UNUSED(sa)) { + Scene *scene = CTX_data_scene(C); SpaceImage *sima= CTX_wm_space_image(C); Object *obedit= CTX_data_edit_object(C); Image *ima; @@ -586,19 +590,31 @@ static void image_refresh(const bContext *C, ScrArea *UNUSED(sa)) else if(obedit && obedit->type == OB_MESH) { Mesh *me= (Mesh*)obedit->data; EditMesh *em= BKE_mesh_get_editmesh(me); - MTFace *tf; - - if(em && EM_texFaceCheck(em)) { - sima->image= NULL; - - tf = EM_get_active_mtface(em, NULL, NULL, 1); /* partially selected face is ok */ + int sloppy= 1; /* partially selected face is ok */ + + if(scene_use_new_shading_nodes(scene)) { + /* new shading system, get image from material */ + EditFace *efa= EM_get_actFace(em, sloppy); + + if(efa) + ED_object_get_active_image(obedit, efa->mat_nr, &sima->image, NULL, NULL); + } + else { + /* old shading system, we set texface */ + MTFace *tf; - if(tf) { - /* don't need to check for pin here, see above */ - sima->image= tf->tpage; + if(em && EM_texFaceCheck(em)) { + sima->image= NULL; + + tf = EM_get_active_mtface(em, NULL, NULL, sloppy); - if(sima->flag & SI_EDITTILE); - else sima->curtile= tf->tile; + if(tf) { + /* don't need to check for pin here, see above */ + sima->image= tf->tpage; + + if(sima->flag & SI_EDITTILE); + else sima->curtile= tf->tile; + } } } diff --git a/source/blender/editors/space_node/CMakeLists.txt b/source/blender/editors/space_node/CMakeLists.txt index 991b35585a6..f33b784c5d2 100644 --- a/source/blender/editors/space_node/CMakeLists.txt +++ b/source/blender/editors/space_node/CMakeLists.txt @@ -25,6 +25,7 @@ set(INC ../../blenlib ../../blenloader ../../imbuf + ../../gpu ../../makesdna ../../makesrna ../../nodes diff --git a/source/blender/editors/space_node/SConscript b/source/blender/editors/space_node/SConscript index c4309dcfca3..6b72fd066e0 100644 --- a/source/blender/editors/space_node/SConscript +++ b/source/blender/editors/space_node/SConscript @@ -4,7 +4,7 @@ Import ('env') sources = env.Glob('*.c') incs = '../include ../../blenfont ../../blenlib ../../blenkernel ../../makesdna ../../makesrna ../../imbuf' -incs += ' ../../nodes ../../render/extern/include ../../blenloader' +incs += ' ../../nodes ../../render/extern/include ../../blenloader ../../gpu' incs += ' ../../windowmanager #intern/guardedalloc #extern/glew/include' defs = [] cf = [] diff --git a/source/blender/editors/space_node/node_edit.c b/source/blender/editors/space_node/node_edit.c index a1b705610f4..23855ff24e1 100644 --- a/source/blender/editors/space_node/node_edit.c +++ b/source/blender/editors/space_node/node_edit.c @@ -90,6 +90,8 @@ #include "RNA_enum_types.h" +#include "GPU_material.h" + #include "node_intern.h" static EnumPropertyItem socket_in_out_items[] = { @@ -598,6 +600,8 @@ static int has_nodetree(bNodeTree *ntree, bNodeTree *lookup) void ED_node_set_active(Main *bmain, bNodeTree *ntree, bNode *node) { + int was_active_texture = (node->flag & NODE_ACTIVE_TEXTURE); + nodeSetActive(ntree, node); if(node->type!=NODE_GROUP) { @@ -621,6 +625,15 @@ void ED_node_set_active(Main *bmain, bNodeTree *ntree, bNode *node) ED_node_generic_update(bmain, ntree, node); } + /* if active texture changed, free glsl materials */ + if((node->flag & NODE_ACTIVE_TEXTURE) && !was_active_texture) { + Material *ma; + + for(ma=bmain->mat.first; ma; ma=ma->id.next) + if(ma->nodetree && ma->use_nodes && has_nodetree(ma->nodetree, ntree)) + GPU_material_free(ma); + } + WM_main_add_notifier(NC_MATERIAL|ND_NODES, node->id); } else if(ntree->type==NTREE_COMPOSIT) { diff --git a/source/blender/editors/space_node/node_templates.c b/source/blender/editors/space_node/node_templates.c index 806a6f98828..5aa15cc68d6 100644 --- a/source/blender/editors/space_node/node_templates.c +++ b/source/blender/editors/space_node/node_templates.c @@ -215,6 +215,11 @@ static void node_socket_add_replace(Main *bmain, bNodeTree *ntree, bNode *node_t } } + /* also preserve mapping for texture nodes */ + if(node_from->typeinfo->nclass == NODE_CLASS_TEXTURE && + node_prev->typeinfo->nclass == NODE_CLASS_TEXTURE) + memcpy(node_from->storage, node_prev->storage, sizeof(NodeTexBase)); + /* remove node */ node_remove_linked(ntree, node_prev); } @@ -503,6 +508,10 @@ void uiTemplateNodeLink(uiLayout *layout, bNodeTree *ntree, bNode *node, bNodeSo but->flag |= UI_TEXT_LEFT|UI_BUT_NODE_LINK; but->poin= (char*)but; but->func_argN = arg; + + if(sock->link && sock->link->fromnode) + if(sock->link->fromnode->flag & NODE_ACTIVE_TEXTURE) + but->flag |= UI_BUT_NODE_ACTIVE; } /**************************** Node Tree Layout *******************************/ diff --git a/source/blender/editors/space_view3d/drawmesh.c b/source/blender/editors/space_view3d/drawmesh.c index 670943afdd3..e23824a2210 100644 --- a/source/blender/editors/space_view3d/drawmesh.c +++ b/source/blender/editors/space_view3d/drawmesh.c @@ -40,11 +40,12 @@ #include "DNA_material_types.h" #include "DNA_meshdata_types.h" +#include "DNA_node_types.h" +#include "DNA_object_types.h" #include "DNA_property_types.h" #include "DNA_scene_types.h" #include "DNA_screen_types.h" #include "DNA_view3d_types.h" -#include "DNA_object_types.h" #include "BKE_DerivedMesh.h" #include "BKE_effect.h" @@ -52,6 +53,7 @@ #include "BKE_material.h" #include "BKE_paint.h" #include "BKE_property.h" +#include "BKE_scene.h" #include "BIF_gl.h" #include "BIF_glutil.h" @@ -64,6 +66,7 @@ #include "GPU_material.h" #include "ED_mesh.h" +#include "ED_uvedit.h" #include "view3d_intern.h" // own include @@ -619,7 +622,7 @@ static void draw_mesh_text(Scene *scene, Object *ob, int glsl) ddm->release(ddm); } -void draw_mesh_textured(Scene *scene, View3D *v3d, RegionView3D *rv3d, Object *ob, DerivedMesh *dm, int faceselect) +void draw_mesh_textured_old(Scene *scene, View3D *v3d, RegionView3D *rv3d, Object *ob, DerivedMesh *dm, int faceselect) { Mesh *me= ob->data; @@ -676,3 +679,179 @@ void draw_mesh_textured(Scene *scene, View3D *v3d, RegionView3D *rv3d, Object *o glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); } +/************************** NEW SHADING NODES ********************************/ + +typedef struct TexMatCallback { + Scene *scene; + Object *ob; + Mesh *me; + DerivedMesh *dm; +} TexMatCallback; + +static void tex_mat_set_material_cb(void *UNUSED(userData), int mat_nr, void *attribs) +{ + /* all we have to do here is simply enable the GLSL material, but note + that the GLSL code will give different result depending on the drawtype, + in texture draw mode it will output the active texture node, in material + draw mode it will show the full material. */ + GPU_enable_material(mat_nr, attribs); +} + +static void tex_mat_set_texture_cb(void *userData, int mat_nr, void *attribs) +{ + /* texture draw mode without GLSL */ + TexMatCallback *data= (TexMatCallback*)userData; + GPUVertexAttribs *gattribs = attribs; + Image *ima; + ImageUser *iuser; + bNode *node; + int texture_set= 0; + + /* draw image texture if we find one */ + if(ED_object_get_active_image(data->ob, mat_nr, &ima, &iuser, &node)) { + /* get openl texture */ + int mipmap= 1; + int bindcode= (ima)? GPU_verify_image(ima, iuser, 0, 0, mipmap): 0; + float zero[4] = {0.0f, 0.0f, 0.0f, 0.0f}; + + if(bindcode) { + NodeTexBase *texbase= node->storage; + + /* disable existing material */ + GPU_disable_material(); + glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, zero); + glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, zero); + glMateriali(GL_FRONT_AND_BACK, GL_SHININESS, 0); + + /* bind texture */ + glEnable(GL_COLOR_MATERIAL); + glEnable(GL_TEXTURE_2D); + + glBindTexture(GL_TEXTURE_2D, ima->bindcode); + glColor3f(1.0f, 1.0f, 1.0f); + + glMatrixMode(GL_TEXTURE); + glLoadMatrixf(texbase->tex_mapping.mat); + glMatrixMode(GL_MODELVIEW); + + /* use active UV texture layer */ + memset(gattribs, 0, sizeof(*gattribs)); + + gattribs->layer[0].type= CD_MTFACE; + gattribs->layer[0].name[0]= '\0'; + gattribs->layer[0].gltexco= 1; + gattribs->totlayer= 1; + + texture_set= 1; + } + } + + if(!texture_set) { + glMatrixMode(GL_TEXTURE); + glLoadIdentity(); + glMatrixMode(GL_MODELVIEW); + + /* disable texture */ + glDisable(GL_TEXTURE_2D); + glDisable(GL_COLOR_MATERIAL); + + /* draw single color */ + GPU_enable_material(mat_nr, attribs); + } +} + +static int tex_mat_set_face_mesh_cb(void *userData, int index) +{ + /* faceselect mode face hiding */ + TexMatCallback *data= (TexMatCallback*)userData; + Mesh *me = (Mesh*)data->me; + MFace *mface = &me->mface[index]; + + return !(mface->flag & ME_HIDE); +} + +static int tex_mat_set_face_editmesh_cb(void *UNUSED(userData), int index) +{ + /* editmode face hiding */ + EditFace *efa= EM_get_face_for_index(index); + + return !(efa->h); +} + +void draw_mesh_textured(Scene *scene, View3D *v3d, RegionView3D *rv3d, Object *ob, DerivedMesh *dm, int faceselect) +{ + if(!scene_use_new_shading_nodes(scene)) { + draw_mesh_textured_old(scene, v3d, rv3d, ob, dm, faceselect); + return; + } + + /* set opengl state for negative scale & color */ + if(ob->transflag & OB_NEG_SCALE) glFrontFace(GL_CW); + else glFrontFace(GL_CCW); + + glEnable(GL_LIGHTING); + + if(ob->mode & OB_MODE_WEIGHT_PAINT) { + /* weight paint mode exception */ + int useColors= 1; + + dm->drawMappedFaces(dm, wpaint__setSolidDrawOptions, + ob->data, useColors, GPU_enable_material, NULL); + } + else { + Mesh *me= ob->data; + TexMatCallback data = {scene, ob, me, dm}; + int (*set_face_cb)(void*, int); + int glsl; + + /* face hiding callback depending on mode */ + if(ob == scene->obedit) + set_face_cb= tex_mat_set_face_editmesh_cb; + else if(faceselect) + set_face_cb= tex_mat_set_face_mesh_cb; + else + set_face_cb= NULL; + + /* test if we can use glsl */ + glsl= (v3d->drawtype == OB_MATERIAL) && GPU_glsl_support(); + + GPU_begin_object_materials(v3d, rv3d, scene, ob, glsl, NULL); + + if(glsl) { + /* draw glsl */ + dm->drawMappedFacesMat(dm, + tex_mat_set_material_cb, + set_face_cb, &data); + } + else { + float zero[4] = {0.0f, 0.0f, 0.0f, 0.0f}; + + /* draw textured */ + glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, zero); + glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, zero); + glMateriali(GL_FRONT_AND_BACK, GL_SHININESS, 0); + + dm->drawMappedFacesMat(dm, + tex_mat_set_texture_cb, + set_face_cb, &data); + } + + GPU_end_object_materials(); + } + + /* reset opengl state */ + glDisable(GL_COLOR_MATERIAL); + glDisable(GL_TEXTURE_2D); + glDisable(GL_LIGHTING); + glBindTexture(GL_TEXTURE_2D, 0); + glFrontFace(GL_CCW); + + glMatrixMode(GL_TEXTURE); + glLoadIdentity(); + glMatrixMode(GL_MODELVIEW); + + /* faceselect mode drawing over textured mesh */ + if(!(ob == scene->obedit) && faceselect) + draw_mesh_face_select(rv3d, ob->data, dm); +} + diff --git a/source/blender/editors/space_view3d/drawobject.c b/source/blender/editors/space_view3d/drawobject.c index f2bd4b51d94..8e592ad9f68 100644 --- a/source/blender/editors/space_view3d/drawobject.c +++ b/source/blender/editors/space_view3d/drawobject.c @@ -108,7 +108,7 @@ /* this condition has been made more complex since editmode can draw textures */ #define CHECK_OB_DRAWTEXTURE(vd, dt) \ - ((vd->drawtype==OB_TEXTURE && dt>OB_SOLID) || \ + ((ELEM(vd->drawtype, OB_TEXTURE, OB_MATERIAL) && dt>OB_SOLID) || \ (vd->drawtype==OB_SOLID && vd->flag2 & V3D_SOLID_TEX)) static void draw_bounding_volume(Scene *scene, Object *ob, char type); @@ -252,6 +252,8 @@ int draw_glsl_material(Scene *scene, Object *ob, View3D *v3d, int dt) return 0; if(ob==OBACT && (ob && ob->mode & OB_MODE_WEIGHT_PAINT)) return 0; + if(scene_use_new_shading_nodes(scene)) + return 0; return (scene->gm.matmode == GAME_MAT_GLSL) && (dt > OB_SOLID); } diff --git a/source/blender/editors/space_view3d/view3d_draw.c b/source/blender/editors/space_view3d/view3d_draw.c index 51bbf591bb3..8e20f331698 100644 --- a/source/blender/editors/space_view3d/view3d_draw.c +++ b/source/blender/editors/space_view3d/view3d_draw.c @@ -2229,11 +2229,17 @@ CustomDataMask ED_view3d_datamask(Scene *scene, View3D *v3d) { CustomDataMask mask= 0; - if((v3d->drawtype == OB_TEXTURE) || ((v3d->drawtype == OB_SOLID) && (v3d->flag2 & V3D_SOLID_TEX))) { + if(ELEM(v3d->drawtype, OB_TEXTURE, OB_MATERIAL) || ((v3d->drawtype == OB_SOLID) && (v3d->flag2 & V3D_SOLID_TEX))) { mask |= CD_MASK_MTFACE | CD_MASK_MCOL; - if(scene->gm.matmode == GAME_MAT_GLSL) - mask |= CD_MASK_ORCO; + if(scene_use_new_shading_nodes(scene)) { + if(v3d->drawtype == OB_MATERIAL) + mask |= CD_MASK_ORCO; + } + else { + if(scene->gm.matmode == GAME_MAT_GLSL) + mask |= CD_MASK_ORCO; + } } return mask; diff --git a/source/blender/editors/uvedit/uvedit_ops.c b/source/blender/editors/uvedit/uvedit_ops.c index 62b875c82de..173ab809b53 100644 --- a/source/blender/editors/uvedit/uvedit_ops.c +++ b/source/blender/editors/uvedit/uvedit_ops.c @@ -37,7 +37,9 @@ #include "MEM_guardedalloc.h" #include "DNA_object_types.h" +#include "DNA_material_types.h" #include "DNA_meshdata_types.h" +#include "DNA_node_types.h" #include "DNA_scene_types.h" #include "BLI_math.h" @@ -50,11 +52,16 @@ #include "BKE_depsgraph.h" #include "BKE_image.h" #include "BKE_library.h" +#include "BKE_main.h" +#include "BKE_material.h" #include "BKE_mesh.h" +#include "BKE_node.h" #include "BKE_report.h" +#include "BKE_scene.h" #include "ED_image.h" #include "ED_mesh.h" +#include "ED_node.h" #include "ED_uvedit.h" #include "ED_object.h" #include "ED_screen.h" @@ -87,9 +94,46 @@ int ED_uvedit_test(Object *obedit) return ret; } +/**************************** object active image *****************************/ + +static int is_image_texture_node(bNode *node) +{ + return ELEM(node->type, SH_NODE_TEX_IMAGE, SH_NODE_TEX_ENVIRONMENT); +} + +int ED_object_get_active_image(Object *ob, int mat_nr, Image **ima, ImageUser **iuser, bNode **node_r) +{ + Material *ma= give_current_material(ob, mat_nr); + bNode *node= (ma && ma->use_nodes)? nodeGetActiveTexture(ma->nodetree): NULL; + + if(node && is_image_texture_node(node)) { + if(ima) *ima= (Image*)node->id; + if(iuser) *iuser= NULL; + if(node_r) *node_r= node; + return TRUE; + } + + if(ima) *ima= NULL; + if(iuser) *iuser= NULL; + if(node_r) *node_r= node; + + return FALSE; +} + +void ED_object_assign_active_image(Main *bmain, Object *ob, int mat_nr, Image *ima) +{ + Material *ma= give_current_material(ob, mat_nr); + bNode *node= (ma && ma->use_nodes)? nodeGetActiveTexture(ma->nodetree): NULL; + + if(node && is_image_texture_node(node)) { + node->id= &ima->id; + ED_node_generic_update(bmain, ma->nodetree, node); + } +} + /************************* assign image ************************/ -void ED_uvedit_assign_image(Scene *scene, Object *obedit, Image *ima, Image *previma) +void ED_uvedit_assign_image(Main *bmain, Scene *scene, Object *obedit, Image *ima, Image *previma) { EditMesh *em; EditFace *efa; @@ -109,35 +153,46 @@ void ED_uvedit_assign_image(Scene *scene, Object *obedit, Image *ima, Image *pre BKE_mesh_end_editmesh(obedit->data, em); return; } - - /* ensure we have a uv layer */ - if(!CustomData_has_layer(&em->fdata, CD_MTFACE)) { - EM_add_data_layer(em, &em->fdata, CD_MTFACE, NULL); - update= 1; + + if(scene_use_new_shading_nodes(scene)) { + /* new shading system, assign image in material */ + int sloppy= 1; + EditFace *efa= EM_get_actFace(em, sloppy); + + if(efa) + ED_object_assign_active_image(bmain, obedit, efa->mat_nr, ima); } + else { + /* old shading system, assign image to selected faces */ + + /* ensure we have a uv layer */ + if(!CustomData_has_layer(&em->fdata, CD_MTFACE)) { + EM_add_data_layer(em, &em->fdata, CD_MTFACE, NULL); + update= 1; + } - /* now assign to all visible faces */ - for(efa= em->faces.first; efa; efa= efa->next) { - tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE); + /* now assign to all visible faces */ + for(efa= em->faces.first; efa; efa= efa->next) { + tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE); - if(uvedit_face_visible(scene, previma, efa, tf)) { - if(ima) { - tf->tpage= ima; - - if(ima->id.us==0) id_us_plus(&ima->id); - else id_lib_extern(&ima->id); - } - else { - tf->tpage= NULL; - } + if(uvedit_face_visible(scene, previma, efa, tf)) { + if(ima) { + tf->tpage= ima; + + if(ima->id.us==0) id_us_plus(&ima->id); + else id_lib_extern(&ima->id); + } + else + tf->tpage= NULL; - update = 1; + update = 1; + } } - } - /* and update depdency graph */ - if(update) - DAG_id_tag_update(obedit->data, 0); + /* and update depdency graph */ + if(update) + DAG_id_tag_update(obedit->data, 0); + } BKE_mesh_end_editmesh(obedit->data, em); } diff --git a/source/blender/editors/uvedit/uvedit_unwrap_ops.c b/source/blender/editors/uvedit/uvedit_unwrap_ops.c index 29a9ae84cd5..11cd50a7d4e 100644 --- a/source/blender/editors/uvedit/uvedit_unwrap_ops.c +++ b/source/blender/editors/uvedit/uvedit_unwrap_ops.c @@ -51,6 +51,7 @@ #include "BKE_customdata.h" #include "BKE_depsgraph.h" #include "BKE_image.h" +#include "BKE_main.h" #include "BKE_mesh.h" #include "PIL_time.h" @@ -73,6 +74,7 @@ static int ED_uvedit_ensure_uvs(bContext *C, Scene *scene, Object *obedit) { + Main *bmain= CTX_data_main(C); EditMesh *em= BKE_mesh_get_editmesh((Mesh*)obedit->data); EditFace *efa; MTFace *tf; @@ -118,7 +120,7 @@ static int ED_uvedit_ensure_uvs(bContext *C, Scene *scene, Object *obedit) } if(ima) - ED_uvedit_assign_image(scene, obedit, ima, NULL); + ED_uvedit_assign_image(bmain, scene, obedit, ima, NULL); /* select new UV's */ for(efa=em->faces.first; efa; efa=efa->next) { |