diff options
author | Miika Hamalainen <blender@miikah.org> | 2011-11-09 19:46:53 +0400 |
---|---|---|
committer | Miika Hamalainen <blender@miikah.org> | 2011-11-09 19:46:53 +0400 |
commit | 1b4a54ad73c058baa59ffdc9e5f18b0b79030fb0 (patch) | |
tree | a5b84d392ea14b0d760a5e24f7a8e51f203d558c /source/blender/editors | |
parent | edec46b0a6aac18f406991b9e16228d4bd848c61 (diff) | |
parent | bc5ec4e69cf3308c2563239c0e8372b853800a78 (diff) |
Merge with trunk r41701soc-2011-carrot
Diffstat (limited to 'source/blender/editors')
41 files changed, 2142 insertions, 393 deletions
diff --git a/source/blender/editors/armature/reeb.c b/source/blender/editors/armature/reeb.c index 0b214e48b6a..ce4092b2b84 100644 --- a/source/blender/editors/armature/reeb.c +++ b/source/blender/editors/armature/reeb.c @@ -3684,7 +3684,7 @@ void REEB_draw() if (G.scene->toolsettings->skgen_options & SKGEN_DISP_INDEX) { - interp_v3_v3v3(vec, arc->head->p, arc->tail->p, 0.5f); + mid_v3_v3v3(vec, arc->head->p, arc->tail->p); s += sprintf(s, "%i (%i-%i-%i) ", i, arc->symmetry_level, arc->symmetry_flag, arc->symmetry_group); if (G.scene->toolsettings->skgen_options & SKGEN_DISP_WEIGHT) 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 942252bc00f..31b47325aa7 100644 --- a/source/blender/editors/include/UI_interface.h +++ b/source/blender/editors/include/UI_interface.h @@ -66,6 +66,9 @@ struct uiWidgetColors; struct Tex; struct MTex; struct ImBuf; +struct bNodeTree; +struct bNode; +struct bNodeSocket; typedef struct uiBut uiBut; typedef struct uiBlock uiBlock; @@ -74,6 +77,10 @@ typedef struct uiLayout uiLayout; /* Defines */ +/* names */ +#define UI_MAX_DRAW_STR 400 +#define UI_MAX_NAME_STR 128 + /* uiBlock->dt */ #define UI_EMBOSS 0 /* use widget style for drawing */ #define UI_EMBOSSN 1 /* Nothing, only icon and/or text */ @@ -128,11 +135,11 @@ typedef struct uiLayout uiLayout; #define UI_ICON_LEFT 128 #define UI_ICON_SUBMENU 256 #define UI_ICON_PREVIEW 512 - /* control for button type block */ -#define UI_MAKE_TOP 1024 -#define UI_MAKE_DOWN 2048 -#define UI_MAKE_LEFT 4096 -#define UI_MAKE_RIGHT 8192 + +#define UI_TEXT_RIGHT 1024 +#define UI_BUT_NODE_LINK 2048 +#define UI_BUT_NODE_ACTIVE 4096 +#define UI_FLAG_UNUSED 8192 /* button align flag, for drawing groups together */ #define UI_BUT_ALIGN (UI_BUT_ALIGN_TOP|UI_BUT_ALIGN_LEFT|UI_BUT_ALIGN_RIGHT|UI_BUT_ALIGN_DOWN) @@ -749,6 +756,10 @@ void uiTemplateReportsBanner(uiLayout *layout, struct bContext *C); 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); @@ -809,16 +820,6 @@ uiStyle* UI_GetStyle(void); /* linker workaround ack! */ void UI_template_fix_linking(void); -/* translation */ -int UI_translate_iface(void); -int UI_translate_tooltips(void); -const char *UI_translate_do_iface(const char *msgid); -const char *UI_translate_do_tooltip(const char *msgid); - -/* Those macros should be used everywhere in UI code. */ -#define IFACE_(msgid) UI_translate_do_iface(msgid) -#define TIP_(msgid) UI_translate_do_tooltip(msgid) - /* UI_OT_editsource helpers */ int UI_editsource_enable_check(void); void UI_editsource_active_but_test(uiBut *but); diff --git a/source/blender/editors/interface/interface.c b/source/blender/editors/interface/interface.c index e5092c82304..fab983cee43 100644 --- a/source/blender/editors/interface/interface.c +++ b/source/blender/editors/interface/interface.c @@ -90,50 +90,6 @@ static void ui_free_but(const bContext *C, uiBut *but); -/* ************* translation ************** */ - -int UI_translate_iface(void) -{ -#ifdef WITH_INTERNATIONAL - return (U.transopts & USER_DOTRANSLATE) && (U.transopts & USER_TR_IFACE); -#else - return 0; -#endif -} - -int UI_translate_tooltips(void) -{ -#ifdef WITH_INTERNATIONAL - return (U.transopts & USER_DOTRANSLATE) && (U.transopts & USER_TR_TOOLTIPS); -#else - return 0; -#endif -} - -const char *UI_translate_do_iface(const char *msgid) -{ -#ifdef WITH_INTERNATIONAL - if(UI_translate_iface()) - return BLF_gettext(msgid); - else - return msgid; -#else - return msgid; -#endif -} - -const char *UI_translate_do_tooltip(const char *msgid) -{ -#ifdef WITH_INTERNATIONAL - if(UI_translate_tooltips()) - return BLF_gettext(msgid); - else - return msgid; -#else - return msgid; -#endif -} - /* ************* window matrix ************** */ void ui_block_to_window_fl(const ARegion *ar, uiBlock *block, float *x, float *y) @@ -756,6 +712,9 @@ static int ui_but_is_rna_undo(uiBut *but) return TRUE; } } + else if (but->rnapoin.type && !RNA_struct_undo_check(but->rnapoin.type)) { + return FALSE; + } return TRUE; } diff --git a/source/blender/editors/interface/interface_intern.h b/source/blender/editors/interface/interface_intern.h index 29447d492c5..aa4158ad4b7 100644 --- a/source/blender/editors/interface/interface_intern.h +++ b/source/blender/editors/interface/interface_intern.h @@ -79,6 +79,7 @@ typedef enum { UI_WTYPE_MENU_RADIO, UI_WTYPE_MENU_ICON_RADIO, UI_WTYPE_MENU_POINTER_LINK, + UI_WTYPE_MENU_NODE_LINK, UI_WTYPE_PULLDOWN, UI_WTYPE_MENU_ITEM, @@ -96,11 +97,6 @@ typedef enum { } uiWidgetTypeEnum; - - -#define UI_MAX_DRAW_STR 400 -#define UI_MAX_NAME_STR 128 - /* panel limits */ #define UI_PANEL_MINX 100 #define UI_PANEL_MINY 70 diff --git a/source/blender/editors/interface/interface_panel.c b/source/blender/editors/interface/interface_panel.c index 9a253952e6d..aa80cb632ec 100644 --- a/source/blender/editors/interface/interface_panel.c +++ b/source/blender/editors/interface/interface_panel.c @@ -43,6 +43,8 @@ #include "BLI_math.h" #include "BLI_utildefines.h" +#include "BLF_translation.h" + #include "DNA_userdef_types.h" #include "BKE_context.h" diff --git a/source/blender/editors/interface/interface_regions.c b/source/blender/editors/interface/interface_regions.c index edbd5c5684e..34b62155314 100644 --- a/source/blender/editors/interface/interface_regions.c +++ b/source/blender/editors/interface/interface_regions.c @@ -1533,15 +1533,6 @@ uiPopupBlockHandle *ui_popup_block_create(bContext *C, ARegion *butregion, uiBut if(ELEM(but->type, BLOCK, PULLDOWN)) block->xofs = -2; /* for proper alignment */ - /* only used for automatic toolbox, so can set the shift flag */ - if(but->flag & UI_MAKE_TOP) { - block->direction= UI_TOP|UI_SHIFT_FLIPPED; - uiBlockFlipOrder(block); - } - if(but->flag & UI_MAKE_DOWN) block->direction= UI_DOWN|UI_SHIFT_FLIPPED; - if(but->flag & UI_MAKE_LEFT) block->direction |= UI_LEFT; - if(but->flag & UI_MAKE_RIGHT) block->direction |= UI_RIGHT; - ui_block_position(window, butregion, but, block); } else { diff --git a/source/blender/editors/interface/interface_templates.c b/source/blender/editors/interface/interface_templates.c index 6a3e6025653..263d689cf62 100644 --- a/source/blender/editors/interface/interface_templates.c +++ b/source/blender/editors/interface/interface_templates.c @@ -41,6 +41,8 @@ #include "BLI_string.h" #include "BLI_ghash.h" +#include "BLF_translation.h" + #include "BKE_animsys.h" #include "BKE_colortools.h" #include "BKE_context.h" @@ -334,7 +336,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; @@ -480,6 +482,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); } @@ -489,6 +494,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); @@ -509,14 +515,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/interface/interface_widgets.c b/source/blender/editors/interface/interface_widgets.c index 8ab48ac8ffa..aa407bbf6d4 100644 --- a/source/blender/editors/interface/interface_widgets.c +++ b/source/blender/editors/interface/interface_widgets.c @@ -1181,6 +1181,12 @@ static void widget_draw_text_icon(uiFontStyle *fstyle, uiWidgetColors *wcol, uiB widget_draw_icon(but, ICON_DOT, dualset?1.0f:0.25f, rect); } + else if(but->type==MENU && (but->flag & UI_BUT_NODE_LINK)) { + int tmp = rect->xmin; + rect->xmin = rect->xmax - (rect->ymax - rect->ymin) - 1; + widget_draw_icon(but, ICON_LAYER_USED, 1.0f, rect); + rect->xmin = tmp; + } /* If there's an icon too (made with uiDefIconTextBut) then draw the icon and offset the text label to accommodate it */ @@ -1543,6 +1549,10 @@ static void widget_state(uiWidgetType *wt, int state) char red[4]= {255, 0, 0}; widget_state_blend(wt->wcol.inner, red, 0.4f); } + if(state & UI_BUT_NODE_ACTIVE) { + char blue[4]= {86, 128, 194}; + widget_state_blend(wt->wcol.inner, blue, 0.3f); + } } /* sliders use special hack which sets 'item' as inner when drawing filling */ @@ -2530,6 +2540,29 @@ static void widget_menuiconbut(uiWidgetColors *wcol, rcti *rect, int UNUSED(stat widgetbase_draw(&wtb, wcol); } +static void widget_menunodebut(uiWidgetColors *wcol, rcti *rect, int UNUSED(state), int roundboxalign) +{ + /* silly node link button hacks */ + uiWidgetBase wtb; + uiWidgetColors wcol_backup= *wcol; + + widget_init(&wtb); + + /* half rounded */ + round_box_edges(&wtb, roundboxalign, rect, 4.0f); + + wcol->inner[0] += 15; + wcol->inner[1] += 15; + wcol->inner[2] += 15; + wcol->outline[0] += 15; + wcol->outline[1] += 15; + wcol->outline[2] += 15; + + /* decoration */ + widgetbase_draw(&wtb, wcol); + *wcol= wcol_backup; +} + static void widget_pulldownbut(uiWidgetColors *wcol, rcti *rect, int state, int UNUSED(roundboxalign)) { if(state & UI_ACTIVE) { @@ -2804,6 +2837,11 @@ static uiWidgetType *widget_type(uiWidgetTypeEnum type) wt.wcol_theme= &btheme->tui.wcol_menu; wt.draw= widget_menubut; break; + + case UI_WTYPE_MENU_NODE_LINK: + wt.wcol_theme= &btheme->tui.wcol_menu; + wt.draw= widget_menunodebut; + break; case UI_WTYPE_PULLDOWN: wt.wcol_theme= &btheme->tui.wcol_pulldown; @@ -2996,7 +3034,9 @@ void ui_draw_but(const bContext *C, ARegion *ar, uiStyle *style, uiBut *but, rct case MENU: case BLOCK: case ICONTEXTROW: - if(!but->str[0] && but->icon) + if(but->flag & UI_BUT_NODE_LINK) + wt= widget_type(UI_WTYPE_MENU_NODE_LINK); + else if(!but->str[0] && but->icon) wt= widget_type(UI_WTYPE_MENU_ICON_RADIO); else wt= widget_type(UI_WTYPE_MENU_RADIO); diff --git a/source/blender/editors/interface/resources.c b/source/blender/editors/interface/resources.c index 5f392daeec6..738531e3bad 100644 --- a/source/blender/editors/interface/resources.c +++ b/source/blender/editors/interface/resources.c @@ -1611,41 +1611,33 @@ void init_userdef_do_versions(void) } } - if (bmain->versionfile < 258 || (bmain->versionfile == 258 && bmain->subversionfile < 1)) { - bTheme *btheme; - - /* if new keyframes handle default is stuff "auto", make it "auto-clamped" instead */ - if (U.keyhandles_new == HD_AUTO) - U.keyhandles_new = HD_AUTO_ANIM; - - /* theme color additions */ - for (btheme= U.themes.first; btheme; btheme= btheme->next) { - /* auto-clamped handles -> based on auto */ - SETCOL(btheme->tipo.handle_auto_clamped, 0x99, 0x40, 0x30, 255); - SETCOL(btheme->tipo.handle_sel_auto_clamped, 0xf0, 0xaf, 0x90, 255); - } - } - if (bmain->versionfile < 259 || (bmain->versionfile == 259 && bmain->subversionfile < 1)) { bTheme *btheme; - + for(btheme= U.themes.first; btheme; btheme= btheme->next) { btheme->tv3d.speaker[3] = 255; } } - { + if (bmain->versionfile < 260 || (bmain->versionfile == 260 && bmain->subversionfile < 3)) { bTheme *btheme; - for(btheme= U.themes.first; btheme; btheme= btheme->next) { + + /* if new keyframes handle default is stuff "auto", make it "auto-clamped" instead + * was changed in 260 as part of GSoC11, but version patch was wrong + */ + if (U.keyhandles_new == HD_AUTO) + U.keyhandles_new = HD_AUTO_ANIM; + + for(btheme= U.themes.first; btheme; btheme= btheme->next) { if(btheme->tv3d.bundle_solid[3] == 0) SETCOL(btheme->tv3d.bundle_solid, 200, 200, 200, 255); - + if(btheme->tv3d.camera_path[3] == 0) SETCOL(btheme->tv3d.camera_path, 0x00, 0x00, 0x00, 255); - + if((btheme->tclip.back[3]) == 0) { btheme->tclip= btheme->tv3d; - + SETCOL(btheme->tclip.marker_outline, 0x00, 0x00, 0x00, 255); SETCOL(btheme->tclip.marker, 0x7f, 0x7f, 0x00, 255); SETCOL(btheme->tclip.act_marker, 0xff, 0xff, 0xff, 255); @@ -1660,6 +1652,19 @@ void init_userdef_do_versions(void) SETCOL(btheme->tclip.handle_vertex_select, 0xff, 0xff, 0, 0xff); btheme->tclip.handle_vertex_size= 4; } + + /* auto-clamped handles -> based on auto */ + if(btheme->tipo.handle_auto_clamped[3] == 0) + SETCOL(btheme->tipo.handle_auto_clamped, 0x99, 0x40, 0x30, 255); + if(btheme->tipo.handle_sel_auto_clamped[3] == 0) + SETCOL(btheme->tipo.handle_sel_auto_clamped, 0xf0, 0xaf, 0x90, 255); + } + + /* enable (Cycles) addon by default */ + if(!BLI_findstring(&U.addons, "cycles", offsetof(bAddon, module))) { + bAddon *baddon= MEM_callocN(sizeof(bAddon), "bAddon"); + BLI_strncpy(baddon->module, "cycles", sizeof(baddon->module)); + BLI_addtail(&U.addons, baddon); } } diff --git a/source/blender/editors/mesh/mesh_data.c b/source/blender/editors/mesh/mesh_data.c index 5a7414d8edd..9164dc7d4c8 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" @@ -350,6 +351,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); @@ -394,7 +396,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/object/object_add.c b/source/blender/editors/object/object_add.c index 8d4d29dbe50..9b539871cbc 100644 --- a/source/blender/editors/object/object_add.c +++ b/source/blender/editors/object/object_add.c @@ -78,6 +78,7 @@ #include "BKE_particle.h" #include "BKE_report.h" #include "BKE_sca.h" +#include "BKE_scene.h" #include "BKE_speaker.h" #include "BKE_texture.h" @@ -92,6 +93,7 @@ #include "ED_curve.h" #include "ED_mball.h" #include "ED_mesh.h" +#include "ED_node.h" #include "ED_object.h" #include "ED_render.h" #include "ED_screen.h" @@ -322,6 +324,7 @@ Object *ED_object_add_type(bContext *C, int type, float *loc, float *rot, int en /* more editor stuff */ ED_object_base_init_transform(C, BASACT, loc, rot); + DAG_id_type_tag(bmain, ID_OB); DAG_scene_sort(bmain, scene); ED_render_id_flush_update(bmain, ob->data); @@ -700,7 +703,9 @@ static const char *get_lamp_defname(int type) static int object_lamp_add_exec(bContext *C, wmOperator *op) { + Scene *scene= CTX_data_scene(C); Object *ob; + Lamp *la; int type= RNA_enum_get(op->ptr, "type"); int enter_editmode; unsigned int layer; @@ -711,9 +716,16 @@ static int object_lamp_add_exec(bContext *C, wmOperator *op) return OPERATOR_CANCELLED; ob= ED_object_add_type(C, OB_LAMP, loc, rot, FALSE, layer); - ((Lamp*)ob->data)->type= type; - rename_id((ID *)ob, get_lamp_defname(type)); - rename_id((ID *)ob->data, get_lamp_defname(type)); + la= (Lamp*)ob->data; + + la->type= type; + rename_id(&ob->id, get_lamp_defname(type)); + rename_id(&la->id, get_lamp_defname(type)); + + if(scene_use_new_shading_nodes(scene)) { + ED_node_shader_default(scene, &la->id); + la->use_nodes= 1; + } return OPERATOR_FINISHED; } diff --git a/source/blender/editors/screen/screen_context.c b/source/blender/editors/screen/screen_context.c index cb42cd786ed..581c1e3597b 100644 --- a/source/blender/editors/screen/screen_context.c +++ b/source/blender/editors/screen/screen_context.c @@ -35,6 +35,8 @@ #include "DNA_sequence_types.h" #include "DNA_scene_types.h" #include "DNA_screen_types.h" +#include "DNA_space_types.h" +#include "DNA_windowmanager_types.h" #include "BLI_utildefines.h" @@ -50,6 +52,8 @@ #include "ED_object.h" #include "ED_armature.h" +#include "WM_api.h" + #include "screen_intern.h" const char *screen_context_dir[] = { @@ -62,6 +66,7 @@ const char *screen_context_dir[] = { "sculpt_object", "vertex_paint_object", "weight_paint_object", "image_paint_object", "particle_edit_object", "sequences", "selected_sequences", "selected_editable_sequences", /* sequencer */ + "active_operator", NULL}; int ed_screen_context(const bContext *C, const char *member, bContextDataResult *result) @@ -387,6 +392,25 @@ int ed_screen_context(const bContext *C, const char *member, bContextDataResult return 1; } } + else if(CTX_data_equals(member, "active_operator")) { + wmOperator *op= NULL; + + SpaceFile *sfile= CTX_wm_space_file(C); + if(sfile) { + op= sfile->op; + } + else { + /* note, this checks poll, could be a problem, but this also + * happens for the toolbar */ + op= WM_operator_last_redo(C); + } + /* TODO, get the operator from popup's */ + + if (op && op->ptr) { + CTX_data_pointer_set(result, NULL, &RNA_Operator, op); + return 1; + } + } else { return 0; /* not found */ } 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 98295f21cd4..9de804d275f 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", "dynamic_paint", 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_clip/clip_graph_ops.c b/source/blender/editors/space_clip/clip_graph_ops.c index 831b225386a..56ca1632bae 100644 --- a/source/blender/editors/space_clip/clip_graph_ops.c +++ b/source/blender/editors/space_clip/clip_graph_ops.c @@ -280,7 +280,7 @@ void CLIP_OT_graph_select(wmOperatorType *ot) /* properties */ RNA_def_float_vector(ot->srna, "location", 2, NULL, -FLT_MAX, FLT_MAX, - "Location", "Mouse location to select nearest entity closest to", -100.0f, 100.0f); + "Location", "Mouse location to select nearest entity", -100.0f, 100.0f); RNA_def_boolean(ot->srna, "extend", 0, "Extend", "Extend selection rather than clearing the existing selection"); } diff --git a/source/blender/editors/space_clip/clip_ops.c b/source/blender/editors/space_clip/clip_ops.c index c52346fd4b6..98abbad13dd 100644 --- a/source/blender/editors/space_clip/clip_ops.c +++ b/source/blender/editors/space_clip/clip_ops.c @@ -970,7 +970,7 @@ void CLIP_OT_mode_set(wmOperatorType *ot) /* identifiers */ ot->name= "Set Clip Mode"; - ot->description = "Sets the clip interaction mode"; + ot->description = "Set the clip interaction mode"; ot->idname= "CLIP_OT_mode_set"; /* api callbacks */ diff --git a/source/blender/editors/space_clip/tracking_ops.c b/source/blender/editors/space_clip/tracking_ops.c index e5bf053aa1c..78bfb1498ac 100644 --- a/source/blender/editors/space_clip/tracking_ops.c +++ b/source/blender/editors/space_clip/tracking_ops.c @@ -1159,7 +1159,7 @@ void CLIP_OT_select_grouped(wmOperatorType *ot) {2, "TRACKED", 0, "Tracked tracks", "Select all tracked tracks"}, {3, "LOCKED", 0, "Locked tracks", "Select all locked tracks"}, {4, "DISABLED", 0, "Disabled tracks", "Select all disabled tracks"}, - {5, "COLOR", 0, "Tracks with same color", "Select all tracks with same color as actiev track"}, + {5, "COLOR", 0, "Tracks with same color", "Select all tracks with same color as active track"}, {6, "FAILED", 0, "Failed Tracks", "Select all tracks which failed to be reconstructed"}, {0, NULL, 0, NULL, NULL} }; @@ -1537,7 +1537,7 @@ static int solve_camera_exec(bContext *C, wmOperator *op) } /* could fail if footage uses images with different sizes */ - BKE_movieclip_get_size(clip, NULL, &width, &height); + BKE_movieclip_get_size(clip, &sc->user, &width, &height); error= BKE_tracking_solve_reconstruction(tracking, width, height); @@ -1546,6 +1546,9 @@ static int solve_camera_exec(bContext *C, wmOperator *op) else BKE_reportf(op->reports, RPT_INFO, "Average reprojection error %.3f", error); + if(scene->clip) + id_us_min(&clip->id); + scene->clip= clip; id_us_plus(&clip->id); @@ -1659,7 +1662,7 @@ void CLIP_OT_clear_track_path(wmOperatorType *ot) { static EnumPropertyItem clear_path_actions[] = { {TRACK_CLEAR_UPTO, "UPTO", 0, "Clear up-to", "Clear path up to current frame"}, - {TRACK_CLEAR_REMAINED, "REMAINED", 0, "Clear remained", "Clear path at remained frames (after current)"}, + {TRACK_CLEAR_REMAINED, "REMAINED", 0, "Clear remained", "Clear path at remaining frames (after current)"}, {TRACK_CLEAR_ALL, "ALL", 0, "Clear all", "Clear the whole path"}, {0, NULL, 0, NULL, NULL} }; @@ -1797,7 +1800,7 @@ void CLIP_OT_set_origin(wmOperatorType *ot) { /* identifiers */ ot->name= "Set Origin"; - ot->description= "Set active marker as origin by moving camera (or it's parent if present) in 3d space"; + ot->description= "Set active marker as origin by moving camera (or it's parent if present) in 3D space"; ot->idname= "CLIP_OT_set_origin"; /* api callbacks */ @@ -1949,7 +1952,7 @@ void CLIP_OT_set_floor(wmOperatorType *ot) { /* identifiers */ ot->name= "Set Floor"; - ot->description= "Set floor based on 3 selected bundles by moving camera (or it's parent if present) in 3d space"; + ot->description= "Set floor based on 3 selected bundles by moving camera (or it's parent if present) in 3D space"; ot->idname= "CLIP_OT_set_floor"; /* api callbacks */ @@ -2291,8 +2294,8 @@ void CLIP_OT_detect_features(wmOperatorType *ot) { static EnumPropertyItem placement_items[] = { {0, "FRAME", 0, "Whole Frame", "Place markers across the whole frame"}, - {1, "INSIDE_GPENCIL", 0, "Inside grease pencil", "Place markers only inside areas oulined with grease pencil"}, - {2, "OUTSIDE_GPENCIL", 0, "Outside grease pencil", "Place markers only outside areas oulined with grease pencil"}, + {1, "INSIDE_GPENCIL", 0, "Inside grease pencil", "Place markers only inside areas outlined with grease pencil"}, + {2, "OUTSIDE_GPENCIL", 0, "Outside grease pencil", "Place markers only outside areas outlined with grease pencil"}, {0, NULL, 0, NULL, NULL} }; @@ -2383,7 +2386,7 @@ void CLIP_OT_frame_jump(wmOperatorType *ot) static EnumPropertyItem position_items[] = { {0, "PATHSTART", 0, "Path Start", "Jump to start of current path"}, {1, "PATHEND", 0, "Path End", "Jump to end of current path"}, - {2, "FAILEDPREV", 0, "Previons Failed", "Jump to previous failed frame"}, + {2, "FAILEDPREV", 0, "Previous Failed", "Jump to previous failed frame"}, {2, "FAILNEXT", 0, "Next Failed", "Jump to next failed frame"}, {0, NULL, 0, NULL, NULL} }; @@ -2454,7 +2457,7 @@ void CLIP_OT_join_tracks(wmOperatorType *ot) { /* identifiers */ ot->name= "Join Tracks"; - ot->description= "Joint Selected Tracks"; + ot->description= "Join selected tracks"; ot->idname= "CLIP_OT_join_tracks"; /* api callbacks */ @@ -2734,7 +2737,7 @@ void CLIP_OT_stabilize_2d_set_rotation(wmOperatorType *ot) { /* identifiers */ ot->name= "Set Rotation Track"; - ot->description= "Use active track to compensate rotaiton when doing 2D stabilization"; + ot->description= "Use active track to compensate rotation when doing 2D stabilization"; ot->idname= "CLIP_OT_stabilize_2d_set_rotation"; /* api callbacks */ 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 8a27bcca8af..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 @@ -47,6 +48,7 @@ set(SRC node_ops.c node_select.c node_state.c + node_templates.c space_node.c node_intern.h 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/drawnode.c b/source/blender/editors/space_node/drawnode.c index b4d89e1365d..4394b4b1920 100644 --- a/source/blender/editors/space_node/drawnode.c +++ b/source/blender/editors/space_node/drawnode.c @@ -95,6 +95,14 @@ static void node_sync_cb(bContext *UNUSED(C), void *snode_v, void *node_v) } } +static void node_socket_button_label(const bContext *UNUSED(C), uiBlock *block, + bNodeTree *UNUSED(ntree), bNode *UNUSED(node), bNodeSocket *sock, + const char *UNUSED(name), int x, int y, int width) +{ + uiDefBut(block, LABEL, 0, sock->name, x, y, width, NODE_DY, NULL, 0, 0, 0, 0, ""); +} + + static void node_socket_button_default(const bContext *C, uiBlock *block, bNodeTree *ntree, bNode *node, bNodeSocket *sock, const char *name, int x, int y, int width) @@ -938,28 +946,28 @@ static void node_shader_buts_material(uiLayout *layout, bContext *C, PointerRNA static void node_shader_buts_mapping(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) { + PointerRNA mappingptr = RNA_pointer_get(ptr, "mapping"); uiLayout *row; uiItemL(layout, "Location:", ICON_NONE); row= uiLayoutRow(layout, 1); - uiItemR(row, ptr, "location", 0, "", ICON_NONE); + uiItemR(row, &mappingptr, "location", 0, "", ICON_NONE); uiItemL(layout, "Rotation:", ICON_NONE); row= uiLayoutRow(layout, 1); - uiItemR(row, ptr, "rotation", 0, "", ICON_NONE); + uiItemR(row, &mappingptr, "rotation", 0, "", ICON_NONE); uiItemL(layout, "Scale:", ICON_NONE); row= uiLayoutRow(layout, 1); - uiItemR(row, ptr, "scale", 0, "", ICON_NONE); + uiItemR(row, &mappingptr, "scale", 0, "", ICON_NONE); row= uiLayoutRow(layout, 1); - uiItemR(row, ptr, "use_min", 0, "Min", ICON_NONE); - uiItemR(row, ptr, "min", 0, "", ICON_NONE); + uiItemR(row, &mappingptr, "use_min", 0, "Min", ICON_NONE); + uiItemR(row, &mappingptr, "min", 0, "", ICON_NONE); row= uiLayoutRow(layout, 1); - uiItemR(row, ptr, "use_max", 0, "Max", ICON_NONE); - uiItemR(row, ptr, "max", 0, "", ICON_NONE); - + uiItemR(row, &mappingptr, "use_max", 0, "Max", ICON_NONE); + uiItemR(row, &mappingptr, "max", 0, "", ICON_NONE); } static void node_shader_buts_vect_math(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) @@ -986,6 +994,54 @@ static void node_shader_buts_geometry(uiLayout *layout, bContext *C, PointerRNA } } +static void node_shader_buts_attribute(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) +{ + uiItemR(layout, ptr, "attribute_name", 0, "Name", ICON_NONE); +} + +static void node_shader_buts_tex_image(uiLayout *layout, bContext *C, PointerRNA *ptr) +{ + //uiItemR(layout, ptr, "image", 0, "", ICON_NONE); + uiTemplateID(layout, C, ptr, "image", NULL, "IMAGE_OT_open", NULL); + uiItemR(layout, ptr, "color_space", 0, "", ICON_NONE); +} + +static void node_shader_buts_tex_sky(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) +{ + uiItemR(layout, ptr, "sun_direction", 0, "", ICON_NONE); + uiItemR(layout, ptr, "turbidity", 0, NULL, ICON_NONE); +} + +static void node_shader_buts_tex_gradient(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) +{ + uiItemR(layout, ptr, "gradient_type", 0, "", ICON_NONE); +} + +static void node_shader_buts_tex_magic(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) +{ + uiItemR(layout, ptr, "turbulence_depth", 0, NULL, ICON_NONE); +} + +static void node_shader_buts_tex_wave(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) +{ + uiItemR(layout, ptr, "wave_type", 0, "", ICON_NONE); +} + +static void node_shader_buts_tex_musgrave(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) +{ + uiItemR(layout, ptr, "musgrave_type", 0, "", ICON_NONE); +} + +static void node_shader_buts_tex_voronoi(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) +{ + uiItemR(layout, ptr, "coloring", 0, "", ICON_NONE); +} + +static void node_shader_buts_glossy(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) +{ + uiItemR(layout, ptr, "distribution", 0, "", ICON_NONE); +} + static void node_shader_buts_dynamic(uiLayout *layout, bContext *C, PointerRNA *ptr) { Main *bmain= CTX_data_main(C); @@ -1072,6 +1128,37 @@ static void node_shader_set_butfunc(bNodeType *ntype) case SH_NODE_GEOMETRY: ntype->uifunc= node_shader_buts_geometry; break; + case SH_NODE_ATTRIBUTE: + ntype->uifunc= node_shader_buts_attribute; + break; + case SH_NODE_TEX_SKY: + ntype->uifunc= node_shader_buts_tex_sky; + break; + case SH_NODE_TEX_IMAGE: + ntype->uifunc= node_shader_buts_tex_image; + break; + case SH_NODE_TEX_ENVIRONMENT: + ntype->uifunc= node_shader_buts_tex_image; + break; + case SH_NODE_TEX_GRADIENT: + ntype->uifunc= node_shader_buts_tex_gradient; + break; + case SH_NODE_TEX_MAGIC: + ntype->uifunc= node_shader_buts_tex_magic; + break; + case SH_NODE_TEX_WAVE: + ntype->uifunc= node_shader_buts_tex_wave; + break; + case SH_NODE_TEX_MUSGRAVE: + ntype->uifunc= node_shader_buts_tex_musgrave; + break; + case SH_NODE_TEX_VORONOI: + ntype->uifunc= node_shader_buts_tex_voronoi; + break; + case SH_NODE_BSDF_GLOSSY: + case SH_NODE_BSDF_GLASS: + ntype->uifunc= node_shader_buts_glossy; + break; case NODE_DYNAMIC: ntype->uifunc= node_shader_buts_dynamic; break; @@ -2089,6 +2176,9 @@ void ED_init_node_butfuncs(void) case SOCK_RGBA: stype->buttonfunc = node_socket_button_color; break; + case SOCK_SHADER: + stype->buttonfunc = node_socket_button_label; + break; default: stype->buttonfunc = NULL; } diff --git a/source/blender/editors/space_node/node_buttons.c b/source/blender/editors/space_node/node_buttons.c index 3886c709196..15e5719be37 100644 --- a/source/blender/editors/space_node/node_buttons.c +++ b/source/blender/editors/space_node/node_buttons.c @@ -45,6 +45,7 @@ #include "BLI_utildefines.h" #include "BKE_context.h" +#include "BKE_global.h" #include "BKE_node.h" #include "BKE_screen.h" @@ -122,6 +123,34 @@ static void active_node_panel(const bContext *C, Panel *pa) node->typeinfo->uifunc(layout, (bContext *)C, &ptr); } +static int node_sockets_poll(const bContext *C, PanelType *UNUSED(pt)) +{ + SpaceNode *snode= CTX_wm_space_node(C); + + return (snode && snode->nodetree && G.rt == 777); +} + +static void node_sockets_panel(const bContext *C, Panel *pa) +{ + SpaceNode *snode= CTX_wm_space_node(C); + bNodeTree *ntree= (snode) ? snode->edittree : NULL; + bNode *node = (ntree) ? nodeGetActive(ntree) : NULL; + bNodeSocket *sock; + uiLayout *layout= pa->layout, *split; + char name[UI_MAX_NAME_STR]; + + if(ELEM(NULL, ntree, node)) + return; + + for(sock=node->inputs.first; sock; sock=sock->next) { + BLI_snprintf(name, sizeof(name), "%s:", sock->name); + + split = uiLayoutSplit(layout, 0.35f, 0); + uiItemL(split, name, ICON_NONE); + uiTemplateNodeLink(split, ntree, node, sock); + } +} + /* ******************* node buttons registration ************** */ void node_buttons_register(ARegionType *art) @@ -134,6 +163,14 @@ void node_buttons_register(ARegionType *art) pt->draw= active_node_panel; pt->poll= active_node_poll; BLI_addtail(&art->paneltypes, pt); + + pt= MEM_callocN(sizeof(PanelType), "spacetype node panel node sockets"); + strcpy(pt->idname, "NODE_PT_sockets"); + strcpy(pt->label, "Sockets"); + pt->draw= node_sockets_panel; + pt->poll= node_sockets_poll; + pt->flag |= PNL_DEFAULT_CLOSED; + BLI_addtail(&art->paneltypes, pt); pt= MEM_callocN(sizeof(PanelType), "spacetype node panel gpencil"); strcpy(pt->idname, "NODE_PT_gpencil"); diff --git a/source/blender/editors/space_node/node_draw.c b/source/blender/editors/space_node/node_draw.c index c2a2f319c28..a932f1b10d9 100644 --- a/source/blender/editors/space_node/node_draw.c +++ b/source/blender/editors/space_node/node_draw.c @@ -108,7 +108,8 @@ void ED_node_changed_update(ID *id, bNode *node) WM_main_add_notifier(NC_WORLD|ND_WORLD_DRAW, id); } else if(treetype==NTREE_COMPOSIT) { - nodeUpdate(edittree, node); + if(node) + nodeUpdate(edittree, node); /* don't use NodeTagIDChanged, it gives far too many recomposites for image, scene layers, ... */ node= node_tree_get_editgroup(nodetree); @@ -691,7 +692,7 @@ static void node_draw_basis(const bContext *C, ARegion *ar, SpaceNode *snode, bN node_socket_circle_draw(ntree, sock, NODE_SOCKSIZE); - if (sock->link) { + if (sock->link || (sock->flag & SOCK_HIDE_VALUE)) { uiDefBut(node->block, LABEL, 0, sock->name, sock->locx+NODE_DYS, sock->locy-NODE_DYS, node->width-NODE_DY, NODE_DY, NULL, 0, 0, 0, 0, ""); } diff --git a/source/blender/editors/space_node/node_edit.c b/source/blender/editors/space_node/node_edit.c index 745611c6251..23855ff24e1 100644 --- a/source/blender/editors/space_node/node_edit.c +++ b/source/blender/editors/space_node/node_edit.c @@ -61,6 +61,7 @@ #include "BKE_material.h" #include "BKE_modifier.h" #include "BKE_paint.h" +#include "BKE_scene.h" #include "BKE_screen.h" #include "BKE_texture.h" #include "BKE_report.h" @@ -89,6 +90,8 @@ #include "RNA_enum_types.h" +#include "GPU_material.h" + #include "node_intern.h" static EnumPropertyItem socket_in_out_items[] = { @@ -269,13 +272,14 @@ bNode *node_tree_get_editgroup(bNodeTree *nodetree) /* assumes nothing being done in ntree yet, sets the default in/out node */ /* called from shading buttons or header */ -void ED_node_shader_default(Scene *UNUSED(scene), ID *id) +void ED_node_shader_default(Scene *scene, ID *id) { bNode *in, *out; - bNodeSocket *fromsock, *tosock; + bNodeSocket *fromsock, *tosock, *sock; bNodeTree *ntree; bNodeTemplate ntemp; int output_type, shader_type; + float color[3], strength = 1.0f; ntree= ntreeAddTree("Shader Nodetree", NTREE_SHADER, 0); @@ -284,24 +288,42 @@ void ED_node_shader_default(Scene *UNUSED(scene), ID *id) Material *ma= (Material*)id; ma->nodetree = ntree; - output_type = SH_NODE_OUTPUT; - shader_type = SH_NODE_MATERIAL; + if(scene_use_new_shading_nodes(scene)) { + output_type = SH_NODE_OUTPUT_MATERIAL; + shader_type = SH_NODE_BSDF_DIFFUSE; + } + else { + output_type = SH_NODE_OUTPUT; + shader_type = SH_NODE_MATERIAL; + } + + copy_v3_v3(color, &ma->r); + strength= 0.0f; break; } case ID_WO: { World *wo= (World*)id; wo->nodetree = ntree; - output_type = SH_NODE_OUTPUT; - shader_type = SH_NODE_MATERIAL; + output_type = SH_NODE_OUTPUT_WORLD; + shader_type = SH_NODE_BACKGROUND; + + copy_v3_v3(color, &wo->horr); + strength= 1.0f; break; } case ID_LA: { Lamp *la= (Lamp*)id; la->nodetree = ntree; - output_type = SH_NODE_OUTPUT; - shader_type = SH_NODE_MATERIAL; + output_type = SH_NODE_OUTPUT_LAMP; + shader_type = SH_NODE_EMISSION; + + copy_v3_v3(color, &la->r); + if(la->type == LA_LOCAL || la->type == LA_SPOT || la->type == LA_AREA) + strength= 100.0f; + else + strength= 1.0f; break; } default: @@ -322,6 +344,17 @@ void ED_node_shader_default(Scene *UNUSED(scene), ID *id) fromsock= in->outputs.first; tosock= out->inputs.first; nodeAddLink(ntree, in, fromsock, out, tosock); + + /* default values */ + if(scene_use_new_shading_nodes(scene)) { + sock= in->inputs.first; + copy_v3_v3(((bNodeSocketValueRGBA*)sock->default_value)->value, color); + + if(strength != 0.0f) { + sock= in->inputs.last; + ((bNodeSocketValueFloat*)sock->default_value)->value= strength; + } + } ntreeUpdateTree(ntree); } @@ -567,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) { @@ -590,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) { @@ -2211,9 +2255,7 @@ bNode *node_add_node(SpaceNode *snode, Main *bmain, Scene *scene, bNodeTemplate node->id = &scene->id; } else if(ELEM3(node->type, CMP_NODE_MOVIECLIP, CMP_NODE_MOVIEDISTORTION, CMP_NODE_STABILIZE2D)) { - if(G.main->movieclip.first == G.main->movieclip.last) { - node->id= G.main->movieclip.first; - } + node->id = (ID *)scene->clip; } ntreeCompositForceHidden(snode->edittree, scene); diff --git a/source/blender/editors/space_node/node_header.c b/source/blender/editors/space_node/node_header.c index 42b5dafa3e1..6dd5eeba832 100644 --- a/source/blender/editors/space_node/node_header.c +++ b/source/blender/editors/space_node/node_header.c @@ -226,52 +226,24 @@ static void node_add_menu(bContext *C, uiLayout *layout, void *arg_nodeclass) } } +static void node_menu_add_foreach_cb(void *calldata, int nclass, const char *name) +{ + uiLayout *layout= calldata; + uiItemMenuF(layout, name, 0, node_add_menu, SET_INT_IN_POINTER(nclass)); +} + static void node_menu_add(const bContext *C, Menu *menu) { Scene *scene= CTX_data_scene(C); SpaceNode *snode= CTX_wm_space_node(C); uiLayout *layout= menu->layout; + bNodeTreeType *ntreetype= ntreeGetType(snode->treetype); if(!snode->nodetree) uiLayoutSetActive(layout, 0); - - if(snode->treetype==NTREE_SHADER) { - uiItemMenuF(layout, IFACE_("Input"), 0, node_add_menu, SET_INT_IN_POINTER(NODE_CLASS_INPUT)); - uiItemMenuF(layout, IFACE_("Output"), 0, node_add_menu, SET_INT_IN_POINTER(NODE_CLASS_OUTPUT)); - if(scene_use_new_shading_nodes(scene)) { - uiItemMenuF(layout, IFACE_("Shader"), 0, node_add_menu, SET_INT_IN_POINTER(NODE_CLASS_SHADER)); - uiItemMenuF(layout, IFACE_("Texture"), 0, node_add_menu, SET_INT_IN_POINTER(NODE_CLASS_TEXTURE)); - } - uiItemMenuF(layout, IFACE_("Color"), 0, node_add_menu, SET_INT_IN_POINTER(NODE_CLASS_OP_COLOR)); - uiItemMenuF(layout, IFACE_("Vector"), 0, node_add_menu, SET_INT_IN_POINTER(NODE_CLASS_OP_VECTOR)); - uiItemMenuF(layout, IFACE_("Convertor"), 0, node_add_menu, SET_INT_IN_POINTER(NODE_CLASS_CONVERTOR)); - uiItemMenuF(layout, IFACE_("Group"), 0, node_add_menu, SET_INT_IN_POINTER(NODE_CLASS_GROUP)); - //uiItemMenuF(layout, IFACE_("Dynamic"), 0, node_add_menu, SET_INT_IN_POINTER(NODE_CLASS_OP_DYNAMIC)); - uiItemMenuF(layout, IFACE_("Layout"), 0, node_add_menu, SET_INT_IN_POINTER(NODE_CLASS_LAYOUT)); - } - else if(snode->treetype==NTREE_COMPOSIT) { - uiItemMenuF(layout, IFACE_("Input"), 0, node_add_menu, SET_INT_IN_POINTER(NODE_CLASS_INPUT)); - uiItemMenuF(layout, IFACE_("Output"), 0, node_add_menu, SET_INT_IN_POINTER(NODE_CLASS_OUTPUT)); - uiItemMenuF(layout, IFACE_("Color"), 0, node_add_menu, SET_INT_IN_POINTER(NODE_CLASS_OP_COLOR)); - uiItemMenuF(layout, IFACE_("Vector"), 0, node_add_menu, SET_INT_IN_POINTER(NODE_CLASS_OP_VECTOR)); - uiItemMenuF(layout, IFACE_("Filter"), 0, node_add_menu, SET_INT_IN_POINTER(NODE_CLASS_OP_FILTER)); - uiItemMenuF(layout, IFACE_("Convertor"), 0, node_add_menu, SET_INT_IN_POINTER(NODE_CLASS_CONVERTOR)); - uiItemMenuF(layout, IFACE_("Matte"), 0, node_add_menu, SET_INT_IN_POINTER(NODE_CLASS_MATTE)); - uiItemMenuF(layout, IFACE_("Distort"), 0, node_add_menu, SET_INT_IN_POINTER(NODE_CLASS_DISTORT)); - uiItemMenuF(layout, IFACE_("Group"), 0, node_add_menu, SET_INT_IN_POINTER(NODE_CLASS_GROUP)); - uiItemMenuF(layout, IFACE_("Layout"), 0, node_add_menu, SET_INT_IN_POINTER(NODE_CLASS_LAYOUT)); - } - else if(snode->treetype==NTREE_TEXTURE) { - uiItemMenuF(layout, IFACE_("Input"), 0, node_add_menu, SET_INT_IN_POINTER(NODE_CLASS_INPUT)); - uiItemMenuF(layout, IFACE_("Output"), 0, node_add_menu, SET_INT_IN_POINTER(NODE_CLASS_OUTPUT)); - uiItemMenuF(layout, IFACE_("Color"), 0, node_add_menu, SET_INT_IN_POINTER(NODE_CLASS_OP_COLOR)); - uiItemMenuF(layout, IFACE_("Patterns"), 0, node_add_menu, SET_INT_IN_POINTER(NODE_CLASS_PATTERN)); - uiItemMenuF(layout, IFACE_("Textures"), 0, node_add_menu, SET_INT_IN_POINTER(NODE_CLASS_TEXTURE)); - uiItemMenuF(layout, IFACE_("Convertor"), 0, node_add_menu, SET_INT_IN_POINTER(NODE_CLASS_CONVERTOR)); - uiItemMenuF(layout, IFACE_("Distort"), 0, node_add_menu, SET_INT_IN_POINTER(NODE_CLASS_DISTORT)); - uiItemMenuF(layout, IFACE_("Group"), 0, node_add_menu, SET_INT_IN_POINTER(NODE_CLASS_GROUP)); - uiItemMenuF(layout, IFACE_("Layout"), 0, node_add_menu, SET_INT_IN_POINTER(NODE_CLASS_LAYOUT)); - } + + if(ntreetype && ntreetype->foreach_nodeclass) + ntreetype->foreach_nodeclass(scene, layout, node_menu_add_foreach_cb); } void node_menus_register(void) diff --git a/source/blender/editors/space_node/node_templates.c b/source/blender/editors/space_node/node_templates.c new file mode 100644 index 00000000000..fedb12f747c --- /dev/null +++ b/source/blender/editors/space_node/node_templates.c @@ -0,0 +1,647 @@ +/* + * $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. + * + * Contributor(s): Blender Foundation 2009. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file blender/editors/interface/interface_node.c + * \ingroup edinterface + */ + +#include <stdlib.h> +#include <stddef.h> +#include <string.h> + +#include "MEM_guardedalloc.h" + +#include "DNA_node_types.h" +#include "DNA_scene_types.h" +#include "DNA_screen_types.h" + +#include "BLI_listbase.h" +#include "BLI_string.h" +#include "BLI_utildefines.h" + +#include "BLF_translation.h" + +#include "BKE_context.h" +#include "BKE_depsgraph.h" +#include "BKE_library.h" +#include "BKE_main.h" +#include "BKE_node.h" +#include "BKE_scene.h" + +#include "RNA_access.h" + +#include "WM_api.h" +#include "WM_types.h" + +#include "UI_interface.h" +#include "UI_resources.h" +#include "../interface/interface_intern.h" + +#include "ED_node.h" + +/************************* Node Socket Manipulation **************************/ + +static void node_tag_recursive(bNode *node) +{ + bNodeSocket *input; + + if(!node || (node->flag & NODE_TEST)) + return; /* in case of cycles */ + + node->flag |= NODE_TEST; + + for(input=node->inputs.first; input; input=input->next) + if(input->link) + node_tag_recursive(input->link->fromnode); +} + +static void node_clear_recursive(bNode *node) +{ + bNodeSocket *input; + + if(!node || !(node->flag & NODE_TEST)) + return; /* in case of cycles */ + + node->flag &= ~NODE_TEST; + + for(input=node->inputs.first; input; input=input->next) + if(input->link) + node_clear_recursive(input->link->fromnode); +} + +static void node_remove_linked(bNodeTree *ntree, bNode *rem_node) +{ + bNode *node, *next; + bNodeSocket *sock; + + if(!rem_node) + return; + + /* tag linked nodes to be removed */ + for(node=ntree->nodes.first; node; node=node->next) + node->flag &= ~NODE_TEST; + + node_tag_recursive(rem_node); + + /* clear tags on nodes that are still used by other nodes */ + for(node=ntree->nodes.first; node; node=node->next) + if(!(node->flag & NODE_TEST)) + for(sock=node->inputs.first; sock; sock=sock->next) + if(sock->link && sock->link->fromnode != rem_node) + node_clear_recursive(sock->link->fromnode); + + /* remove nodes */ + for(node=ntree->nodes.first; node; node=next) { + next = node->next; + + if(node->flag & NODE_TEST) { + if(node->id) + node->id->us--; + nodeFreeNode(ntree, node); + } + } +} + +/* disconnect socket from the node it is connected to */ +static void node_socket_disconnect(Main *bmain, bNodeTree *ntree, bNode *node_to, bNodeSocket *sock_to) +{ + if(!sock_to->link) + return; + + nodeRemLink(ntree, sock_to->link); + + nodeUpdate(ntree, node_to); + ntreeUpdateTree(ntree); + + ED_node_generic_update(bmain, ntree, node_to); +} + +/* remove all nodes connected to this socket, if they aren't connected to other nodes */ +static void node_socket_remove(Main *bmain, bNodeTree *ntree, bNode *node_to, bNodeSocket *sock_to) +{ + if(!sock_to->link) + return; + + node_remove_linked(ntree, sock_to->link->fromnode); + + nodeUpdate(ntree, node_to); + ntreeUpdateTree(ntree); + + ED_node_generic_update(bmain, ntree, node_to); +} + +/* add new node connected to this socket, or replace an existing one */ +static void node_socket_add_replace(Main *bmain, bNodeTree *ntree, bNode *node_to, bNodeSocket *sock_to, bNodeTemplate *ntemp, int sock_num) +{ + bNode *node_from; + bNodeSocket *sock_from; + bNode *node_prev = NULL; + + /* unlink existing node */ + if(sock_to->link) { + node_prev = sock_to->link->fromnode; + nodeRemLink(ntree, sock_to->link); + } + + /* find existing node that we can use */ + for(node_from=ntree->nodes.first; node_from; node_from=node_from->next) + if(node_from->type == ntemp->type) + break; + + if(node_from) + if(!(node_from->inputs.first == NULL && !(node_from->typeinfo->flag & NODE_OPTIONS))) + node_from = NULL; + + if(node_prev && node_prev->type == ntemp->type && + (ntemp->type != NODE_GROUP || node_prev->id == &ntemp->ngroup->id)) { + /* keep the previous node if it's the same type */ + node_from = node_prev; + } + else if(!node_from) { + node_from= nodeAddNode(ntree, ntemp); + node_from->locx = node_to->locx - (node_from->typeinfo->width + 50); + node_from->locy = node_to->locy; + + if(node_from->id) + id_us_plus(node_from->id); + } + + nodeSetActive(ntree, node_from); + + /* add link */ + sock_from = BLI_findlink(&node_from->outputs, sock_num); + nodeAddLink(ntree, node_from, sock_from, node_to, sock_to); + + /* copy input sockets from previous node */ + if(node_prev && node_from != node_prev) { + bNodeSocket *sock_prev, *sock_from; + + for(sock_prev=node_prev->inputs.first; sock_prev; sock_prev=sock_prev->next) { + for(sock_from=node_from->inputs.first; sock_from; sock_from=sock_from->next) { + if(strcmp(sock_prev->name, sock_from->name) == 0 && sock_prev->type == sock_from->type) { + bNodeLink *link = sock_prev->link; + + if(link && link->fromnode) { + nodeAddLink(ntree, link->fromnode, link->fromsock, node_from, sock_from); + nodeRemLink(ntree, link); + } + + if(sock_prev->default_value) { + if(sock_from->default_value) + MEM_freeN(sock_from->default_value); + + sock_from->default_value = MEM_dupallocN(sock_prev->default_value); + } + } + } + } + + /* 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); + } + + nodeUpdate(ntree, node_from); + nodeUpdate(ntree, node_to); + ntreeUpdateTree(ntree); + + ED_node_generic_update(bmain, ntree, node_to); +} + +/****************************** Node Link Menu *******************************/ + +#define UI_NODE_LINK_ADD 0 +#define UI_NODE_LINK_DISCONNECT -1 +#define UI_NODE_LINK_REMOVE -2 + +typedef struct NodeLinkArg { + Main *bmain; + Scene *scene; + bNodeTree *ntree; + bNode *node; + bNodeSocket *sock; + + bNodeTree *ngroup; + int type; + int output; + + uiLayout *layout; +} NodeLinkArg; + +static void ui_node_link(bContext *UNUSED(C), void *arg_p, void *event_p) +{ + NodeLinkArg *arg = (NodeLinkArg*)arg_p; + Main *bmain = arg->bmain; + bNode *node_to = arg->node; + bNodeSocket *sock_to = arg->sock; + bNodeTree *ntree = arg->ntree; + int event = GET_INT_FROM_POINTER(event_p); + bNodeTemplate ntemp; + + ntemp.type = arg->type; + ntemp.ngroup = arg->ngroup; + + if(event == UI_NODE_LINK_DISCONNECT) + node_socket_disconnect(bmain, ntree, node_to, sock_to); + else if(event == UI_NODE_LINK_REMOVE) + node_socket_remove(bmain, ntree, node_to, sock_to); + else + node_socket_add_replace(bmain, ntree, node_to, sock_to, &ntemp, arg->output); +} + +static void ui_node_sock_name(bNodeSocket *sock, char name[UI_MAX_NAME_STR]) +{ + if(sock->link && sock->link->fromnode) { + bNode *node = sock->link->fromnode; + char node_name[UI_MAX_NAME_STR]; + + if(node->type == NODE_GROUP) + BLI_strncpy(node_name, node->id->name+2, UI_MAX_NAME_STR); + else + BLI_strncpy(node_name, node->typeinfo->name, UI_MAX_NAME_STR); + + if(node->inputs.first == NULL && + node->outputs.first != node->outputs.last && + !(node->typeinfo->flag & NODE_OPTIONS)) + BLI_snprintf(name, UI_MAX_NAME_STR, "%s | %s", node_name, sock->link->fromsock->name); + else + BLI_strncpy(name, node_name, UI_MAX_NAME_STR); + } + else if(sock->type == SOCK_SHADER) + BLI_strncpy(name, "None", UI_MAX_NAME_STR); + else + BLI_strncpy(name, "Default", UI_MAX_NAME_STR); +} + +static int ui_compatible_sockets(int typeA, int typeB) +{ + return (typeA == typeB); +} + +static void ui_node_menu_column(NodeLinkArg *arg, int nclass, const char *cname) +{ + Main *bmain = arg->bmain; + bNodeTree *ntree = arg->ntree; + bNodeSocket *sock = arg->sock; + uiLayout *layout = arg->layout; + uiLayout *column = NULL; + uiBlock *block = uiLayoutGetBlock(layout); + uiBut *but; + bNodeType *ntype; + bNodeTree *ngroup; + NodeLinkArg *argN; + int first = 1; + int compatibility= 0; + + if(ntree->type == NTREE_SHADER) { + if(scene_use_new_shading_nodes(arg->scene)) + compatibility= NODE_NEW_SHADING; + else + compatibility= NODE_OLD_SHADING; + } + + if(nclass == NODE_CLASS_GROUP) { + for(ngroup=bmain->nodetree.first; ngroup; ngroup=ngroup->id.next) { + bNodeSocket *gsock; + char name[UI_MAX_NAME_STR]; + int i, j, num = 0; + + if(ngroup->type != ntree->type) + continue; + + for(gsock=ngroup->inputs.first; gsock; gsock=gsock->next) + if(ui_compatible_sockets(gsock->type, sock->type)) + num++; + + for(i=0, j=0, gsock=ngroup->outputs.first; gsock; gsock=gsock->next, i++) { + if(!ui_compatible_sockets(gsock->type, sock->type)) + continue; + + if(first) { + column= uiLayoutColumn(layout, 0); + uiBlockSetCurLayout(block, column); + + uiItemL(column, cname, ICON_NODE); + but= block->buttons.last; + but->flag= UI_TEXT_LEFT; + + first = 0; + } + + if(num > 1) { + if(j == 0) { + uiItemL(column, ngroup->id.name+2, ICON_NODE); + but= block->buttons.last; + but->flag= UI_TEXT_LEFT; + } + + BLI_snprintf(name, UI_MAX_NAME_STR, " %s", gsock->name); + j++; + } + else + BLI_strncpy(name, ngroup->id.name+2, UI_MAX_NAME_STR); + + but = uiDefBut(block, BUT, 0, ngroup->id.name+2, 0, 0, UI_UNIT_X*4, UI_UNIT_Y, + NULL, 0.0, 0.0, 0.0, 0.0, "Add node to input"); + + argN = MEM_dupallocN(arg); + argN->ngroup = ngroup; + argN->output = i; + uiButSetNFunc(but, ui_node_link, argN, NULL); + } + } + } + else { + bNodeTreeType *ttype= ntreeGetType(ntree->type); + + for(ntype=ttype->node_types.first; ntype; ntype=ntype->next) { + bNodeSocketTemplate *stemp; + char name[UI_MAX_NAME_STR]; + int i, j, num = 0; + + if(compatibility && !(ntype->compatibility & compatibility)) + continue; + + if(ntype->nclass != nclass) + continue; + + for(i=0, stemp=ntype->outputs; stemp && stemp->type != -1; stemp++, i++) + if(ui_compatible_sockets(stemp->type, sock->type)) + num++; + + for(i=0, j=0, stemp=ntype->outputs; stemp && stemp->type != -1; stemp++, i++) { + if(!ui_compatible_sockets(stemp->type, sock->type)) + continue; + + if(first) { + column= uiLayoutColumn(layout, 0); + uiBlockSetCurLayout(block, column); + + uiItemL(column, cname, ICON_NODE); + but= block->buttons.last; + but->flag= UI_TEXT_LEFT; + + first = 0; + } + + if(num > 1) { + if(j == 0) { + uiItemL(column, ntype->name, ICON_NODE); + but= block->buttons.last; + but->flag= UI_TEXT_LEFT; + } + + BLI_snprintf(name, UI_MAX_NAME_STR, " %s", stemp->name); + j++; + } + else + BLI_strncpy(name, ntype->name, UI_MAX_NAME_STR); + + but = uiDefBut(block, BUT, 0, name, 0, 0, UI_UNIT_X*4, UI_UNIT_Y, + NULL, 0.0, 0.0, 0.0, 0.0, "Add node to input"); + + argN = MEM_dupallocN(arg); + argN->type = ntype->type; + argN->output = i; + uiButSetNFunc(but, ui_node_link, argN, NULL); + } + } + } +} + +static void node_menu_column_foreach_cb(void *calldata, int nclass, const char *name) +{ + NodeLinkArg *arg = (NodeLinkArg*)calldata; + + if(!ELEM(nclass, NODE_CLASS_GROUP, NODE_CLASS_LAYOUT)) + ui_node_menu_column(arg, nclass, name); +} + +static void ui_template_node_link_menu(bContext *C, uiLayout *layout, void *but_p) +{ + Main *bmain= CTX_data_main(C); + Scene *scene= CTX_data_scene(C); + uiBlock *block = uiLayoutGetBlock(layout); + uiBut *but = (uiBut*)but_p; + uiLayout *split, *column; + NodeLinkArg *arg = (NodeLinkArg*)but->func_argN; + bNodeSocket *sock = arg->sock; + bNodeTreeType *ntreetype= ntreeGetType(arg->ntree->type); + + uiBlockSetCurLayout(block, layout); + split= uiLayoutSplit(layout, 0, 0); + + arg->bmain= bmain; + arg->scene= scene; + arg->layout= split; + + if(ntreetype && ntreetype->foreach_nodeclass) + ntreetype->foreach_nodeclass(scene, arg, node_menu_column_foreach_cb); + + column= uiLayoutColumn(split, 0); + uiBlockSetCurLayout(block, column); + + if(sock->link) { + uiItemL(column, "Link", ICON_NONE); + but= block->buttons.last; + but->flag= UI_TEXT_LEFT; + + but = uiDefBut(block, BUT, 0, "Remove", 0, 0, UI_UNIT_X*4, UI_UNIT_Y, + NULL, 0.0, 0.0, 0.0, 0.0, "Remove nodes connected to the input"); + uiButSetNFunc(but, ui_node_link, MEM_dupallocN(arg), SET_INT_IN_POINTER(UI_NODE_LINK_REMOVE)); + + but = uiDefBut(block, BUT, 0, "Disconnect", 0, 0, UI_UNIT_X*4, UI_UNIT_Y, + NULL, 0.0, 0.0, 0.0, 0.0, "Disconnect nodes connected to the input"); + uiButSetNFunc(but, ui_node_link, MEM_dupallocN(arg), SET_INT_IN_POINTER(UI_NODE_LINK_DISCONNECT)); + } + + ui_node_menu_column(arg, NODE_CLASS_GROUP, IFACE_("Group")); +} + +void uiTemplateNodeLink(uiLayout *layout, bNodeTree *ntree, bNode *node, bNodeSocket *sock) +{ + uiBlock *block = uiLayoutGetBlock(layout); + NodeLinkArg *arg; + uiBut *but; + + arg = MEM_callocN(sizeof(NodeLinkArg), "NodeLinkArg"); + arg->ntree = ntree; + arg->node = node; + arg->sock = sock; + arg->type = 0; + arg->output = 0; + + uiBlockSetCurLayout(block, layout); + + if(sock->link || sock->type == SOCK_SHADER || (sock->flag & SOCK_HIDE_VALUE)) { + char name[UI_MAX_NAME_STR]; + ui_node_sock_name(sock, name); + but= uiDefMenuBut(block, ui_template_node_link_menu, NULL, name, 0, 0, UI_UNIT_X*4, UI_UNIT_Y, ""); + } + else + but= uiDefIconMenuBut(block, ui_template_node_link_menu, NULL, ICON_NONE, 0, 0, UI_UNIT_X, UI_UNIT_Y, ""); + + but->type= MENU; + 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 *******************************/ + +static void ui_node_draw_input(uiLayout *layout, bContext *C, + bNodeTree *ntree, bNode *node, bNodeSocket *input, int depth); + +static void ui_node_draw_node(uiLayout *layout, bContext *C, bNodeTree *ntree, bNode *node, int depth) +{ + bNodeSocket *input; + uiLayout *col, *split; + PointerRNA nodeptr; + + RNA_pointer_create(&ntree->id, &RNA_Node, node, &nodeptr); + + if(node->typeinfo->uifunc) { + if(node->type != NODE_GROUP) { + split = uiLayoutSplit(layout, 0.35f, 0); + col = uiLayoutColumn(split, 0); + col = uiLayoutColumn(split, 0); + + node->typeinfo->uifunc(col, C, &nodeptr); + } + } + + for(input=node->inputs.first; input; input=input->next) + ui_node_draw_input(layout, C, ntree, node, input, depth+1); +} + +static void ui_node_draw_input(uiLayout *layout, bContext *C, bNodeTree *ntree, bNode *node, bNodeSocket *input, int depth) +{ + PointerRNA inputptr; + uiBlock *block = uiLayoutGetBlock(layout); + uiBut *bt; + uiLayout *split, *row, *col; + bNode *lnode; + char label[UI_MAX_NAME_STR]; + int indent = (depth > 1)? 2*(depth - 1): 0; + + if(input->flag & SOCK_UNAVAIL) + return; + + /* to avoid eternal loops on cyclic dependencies */ + node->flag |= NODE_TEST; + lnode = (input->link)? input->link->fromnode: NULL; + + /* socket RNA pointer */ + RNA_pointer_create(&ntree->id, &RNA_NodeSocket, input, &inputptr); + + /* indented label */ + memset(label, ' ', indent); + label[indent] = '\0'; + BLI_snprintf(label, UI_MAX_NAME_STR, "%s%s:", label, input->name); + + /* split in label and value */ + split = uiLayoutSplit(layout, 0.35f, 0); + + row = uiLayoutRow(split, 1); + + if(depth > 0) { + uiBlockSetEmboss(block, UI_EMBOSSN); + + if(lnode && (lnode->inputs.first || (lnode->typeinfo->uifunc && lnode->type != NODE_GROUP))) { + int icon = (input->flag & SOCK_COLLAPSED)? ICON_DISCLOSURE_TRI_RIGHT: ICON_DISCLOSURE_TRI_DOWN; + uiItemR(row, &inputptr, "show_expanded", UI_ITEM_R_ICON_ONLY, "", icon); + } + else + uiItemL(row, "", ICON_BLANK1); + + bt = block->buttons.last; + bt->x2 = UI_UNIT_X/2; + + uiBlockSetEmboss(block, UI_EMBOSS); + } + + uiItemL(row, label, ICON_NONE); + bt= block->buttons.last; + bt->flag= UI_TEXT_LEFT; + + if(lnode) { + /* input linked to a node */ + uiTemplateNodeLink(split, ntree, node, input); + + if(!(input->flag & SOCK_COLLAPSED)) { + if(depth == 0) + uiItemS(layout); + + ui_node_draw_node(layout, C, ntree, lnode, depth); + } + } + else { + /* input not linked, show value */ + if(input->type != SOCK_SHADER && !(input->flag & SOCK_HIDE_VALUE)) { + if(input->type == SOCK_VECTOR) { + row = uiLayoutRow(split, 0); + col = uiLayoutColumn(row, 0); + + uiItemR(col, &inputptr, "default_value", 0, "", 0); + } + else { + row = uiLayoutRow(split, 1); + uiItemR(row, &inputptr, "default_value", 0, "", 0); + } + } + else + row = uiLayoutRow(split, 0); + + uiTemplateNodeLink(row, ntree, node, input); + } + + /* clear */ + node->flag &= ~NODE_TEST; +} + +void uiTemplateNodeView(uiLayout *layout, bContext *C, bNodeTree *ntree, bNode *node, bNodeSocket *input) +{ + bNode *tnode; + + if(!ntree) + return; + + /* clear for cycle check */ + for(tnode=ntree->nodes.first; tnode; tnode=tnode->next) + tnode->flag &= ~NODE_TEST; + + if(input) + ui_node_draw_input(layout, C, ntree, node, input, 0); + else + ui_node_draw_node(layout, C, ntree, node, 0); +} + diff --git a/source/blender/editors/space_view3d/drawmesh.c b/source/blender/editors/space_view3d/drawmesh.c index 0a332875cae..ade3a65054f 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 @@ -626,7 +629,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 draw_flags) +void draw_mesh_textured_old(Scene *scene, View3D *v3d, RegionView3D *rv3d, Object *ob, DerivedMesh *dm, int draw_flags) { Mesh *me= ob->data; @@ -648,7 +651,7 @@ void draw_mesh_textured(Scene *scene, View3D *v3d, RegionView3D *rv3d, Object *o dm->drawMappedFacesTex(dm, draw_em_tf_mapped__set_draw, &data); } - else if(draw_flags & DRAW_IS_PAINT_SEL) { + else if(draw_flags & DRAW_FACE_SELECT) { if(ob->mode & OB_MODE_WEIGHT_PAINT) dm->drawMappedFaces(dm, wpaint__setSolidDrawOptions, me, 1, GPU_enable_material, NULL); else @@ -676,7 +679,7 @@ void draw_mesh_textured(Scene *scene, View3D *v3d, RegionView3D *rv3d, Object *o draw_textured_end(); /* draw edges and selected faces over textured mesh */ - if(!(ob == scene->obedit) && (draw_flags & DRAW_IS_PAINT_SEL)) + if(!(ob == scene->obedit) && (draw_flags & DRAW_FACE_SELECT)) draw_mesh_face_select(rv3d, me, dm); /* reset from negative scale correction */ @@ -686,3 +689,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 draw_flags) +{ + if((!scene_use_new_shading_nodes(scene)) || (draw_flags & DRAW_DYNAMIC_PAINT_PREVIEW)) { + draw_mesh_textured_old(scene, v3d, rv3d, ob, dm, draw_flags); + 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(draw_flags & DRAW_FACE_SELECT) + 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) && (draw_flags & DRAW_FACE_SELECT)) + 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 bfb3d849c80..2c5df072f76 100644 --- a/source/blender/editors/space_view3d/drawobject.c +++ b/source/blender/editors/space_view3d/drawobject.c @@ -109,7 +109,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); @@ -253,6 +253,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); } @@ -2562,7 +2564,7 @@ static void draw_em_measure_stats(View3D *v3d, RegionView3D *rv3d, Object *ob, E copy_v3_v3(v1, eed->v1->co); copy_v3_v3(v2, eed->v2->co); - interp_v3_v3v3(vmid, v1, v2, 0.5f); + mid_v3_v3v3(vmid, v1, v2); if(do_global) { mul_mat3_m4_v3(ob->obmat, v1); @@ -2914,7 +2916,7 @@ static void draw_mesh_fancy(Scene *scene, ARegion *ar, View3D *v3d, RegionView3D int /* totvert,*/ totedge, totface; DerivedMesh *dm= mesh_get_derived_final(scene, ob, scene->customdata_mask); ModifierData *md = NULL; - int draw_flags = (ob==OBACT && paint_facesel_test(ob)) ? DRAW_IS_PAINT_SEL : 0; + int draw_flags = (ob==OBACT && paint_facesel_test(ob)) ? DRAW_FACE_SELECT : 0; if(!dm) return; @@ -2946,7 +2948,7 @@ static void draw_mesh_fancy(Scene *scene, ARegion *ar, View3D *v3d, RegionView3D glFrontFace((ob->transflag&OB_NEG_SCALE)?GL_CW:GL_CCW); // Unwanted combination. - if (draw_flags & DRAW_IS_PAINT_SEL) draw_wire = 0; + if (draw_flags & DRAW_FACE_SELECT) draw_wire = 0; if(dt==OB_BOUNDBOX) { if((v3d->flag2 & V3D_RENDER_OVERRIDE && v3d->drawtype >= OB_WIRE)==0) @@ -2960,10 +2962,10 @@ static void draw_mesh_fancy(Scene *scene, ARegion *ar, View3D *v3d, RegionView3D else if(dt==OB_WIRE || totface==0) { draw_wire = 1; /* draw wire only, no depth buffer stuff */ } - else if( (draw_flags & DRAW_IS_PAINT_SEL || (ob==OBACT && ob->mode & OB_MODE_TEXTURE_PAINT)) || + else if( (draw_flags & DRAW_FACE_SELECT || (ob==OBACT && ob->mode & OB_MODE_TEXTURE_PAINT)) || CHECK_OB_DRAWTEXTURE(v3d, dt)) { - if ((v3d->flag&V3D_SELECT_OUTLINE) && ((v3d->flag2 & V3D_RENDER_OVERRIDE)==0) && (base->flag&SELECT) && !(G.f&G_PICKSEL || (draw_flags & DRAW_IS_PAINT_SEL)) && !draw_wire) { + if ((v3d->flag&V3D_SELECT_OUTLINE) && ((v3d->flag2 & V3D_RENDER_OVERRIDE)==0) && (base->flag&SELECT) && !(G.f&G_PICKSEL || (draw_flags & DRAW_FACE_SELECT)) && !draw_wire) { draw_mesh_object_outline(v3d, ob, dm); } @@ -2981,7 +2983,7 @@ static void draw_mesh_fancy(Scene *scene, ARegion *ar, View3D *v3d, RegionView3D draw_mesh_textured(scene, v3d, rv3d, ob, dm, draw_flags); } - if(!(draw_flags & DRAW_IS_PAINT_SEL)) { + if(!(draw_flags & DRAW_FACE_SELECT)) { if(base->flag & SELECT) UI_ThemeColor((ob==OBACT)?TH_ACTIVE:TH_SELECT); else 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/space_view3d/view3d_intern.h b/source/blender/editors/space_view3d/view3d_intern.h index 79b7681260a..696ad9628a0 100644 --- a/source/blender/editors/space_view3d/view3d_intern.h +++ b/source/blender/editors/space_view3d/view3d_intern.h @@ -60,7 +60,7 @@ struct wmNDOFMotionData; /* draw_mesh_fancy draw_flags */ #define DRAW_DYNAMIC_PAINT_PREVIEW 1 -#define DRAW_IS_PAINT_SEL 2 +#define DRAW_FACE_SELECT 2 /* view3d_header.c */ void view3d_header_buttons(const struct bContext *C, struct ARegion *ar); diff --git a/source/blender/editors/space_view3d/view3d_snap.c b/source/blender/editors/space_view3d/view3d_snap.c index 012e08f98cb..7cd9c07c00c 100644 --- a/source/blender/editors/space_view3d/view3d_snap.c +++ b/source/blender/editors/space_view3d/view3d_snap.c @@ -781,7 +781,7 @@ static void bundle_midpoint(Scene *scene, Object *ob, float vec[3]) } if(ok) { - interp_v3_v3v3(vec, min, max, 0.5); + mid_v3_v3v3(vec, min, max); } } diff --git a/source/blender/editors/transform/transform.c b/source/blender/editors/transform/transform.c index 13d686508de..95daa11d97f 100644 --- a/source/blender/editors/transform/transform.c +++ b/source/blender/editors/transform/transform.c @@ -513,7 +513,7 @@ wmKeyMap* transform_modal_keymap(wmKeyConfig *keyconf) {NUM_MODAL_INCREMENT_UP, "INCREMENT_UP", 0, "Numinput Increment Up", ""}, {NUM_MODAL_INCREMENT_DOWN, "INCREMENT_DOWN", 0, "Numinput Increment Down", ""}, {TFM_MODAL_PROPSIZE_UP, "PROPORTIONAL_SIZE_UP", 0, "Increase Proportional Influence", ""}, - {TFM_MODAL_PROPSIZE_DOWN, "PROPORTIONAL_SIZE_DOWN", 0, "Decrease Poportional Influence", ""}, + {TFM_MODAL_PROPSIZE_DOWN, "PROPORTIONAL_SIZE_DOWN", 0, "Decrease Proportional Influence", ""}, {TFM_MODAL_AUTOIK_LEN_INC, "AUTOIK_CHAIN_LEN_UP", 0, "Increase Max AutoIK Chain Length", ""}, {TFM_MODAL_AUTOIK_LEN_DEC, "AUTOIK_CHAIN_LEN_DOWN", 0, "Decrease Max AutoIK Chain Length", ""}, {0, NULL, 0, NULL, NULL}}; diff --git a/source/blender/editors/transform/transform_conversions.c b/source/blender/editors/transform/transform_conversions.c index 0a6f49f7c9f..7ab1b24e9b3 100644 --- a/source/blender/editors/transform/transform_conversions.c +++ b/source/blender/editors/transform/transform_conversions.c @@ -5396,7 +5396,7 @@ static void createTransTrackingData(bContext *C, TransInfo *t) TransDataTracking *tdt; int framenr = sc->user.framenr; - if(clip && !BKE_movieclip_has_frame(clip, &sc->user)) { + if(!clip || !BKE_movieclip_has_frame(clip, &sc->user)) { t->total = 0; return; } diff --git a/source/blender/editors/transform/transform_generics.c b/source/blender/editors/transform/transform_generics.c index 53e379a2d27..0e053e68496 100644 --- a/source/blender/editors/transform/transform_generics.c +++ b/source/blender/editors/transform/transform_generics.c @@ -619,6 +619,65 @@ static void recalcData_nla(TransInfo *t) } } +/* helper for recalcData() - for Image Editor transforms */ +static void recalcData_image(TransInfo *t) +{ + if (t->obedit && t->obedit->type == OB_MESH) { + SpaceImage *sima= t->sa->spacedata.first; + + flushTransUVs(t); + if(sima->flag & SI_LIVE_UNWRAP) + ED_uvedit_live_unwrap_re_solve(); + + DAG_id_tag_update(t->obedit->data, 0); + } +} + +/* helper for recalcData() - for Movie Clip transforms */ +static void recalcData_clip(TransInfo *t) +{ + SpaceClip *sc= t->sa->spacedata.first; + MovieClip *clip= ED_space_clip(sc); + MovieTrackingTrack *track; + + if(t->state == TRANS_CANCEL) { + track= clip->tracking.tracks.first; + while(track) { + if(TRACK_VIEW_SELECTED(sc, track)) { + MovieTrackingMarker *marker= BKE_tracking_ensure_marker(track, sc->user.framenr); + + marker->flag= track->transflag; + } + + track= track->next; + } + } + + flushTransTracking(t); + + track= clip->tracking.tracks.first; + while(track) { + if(TRACK_VIEW_SELECTED(sc, track)) { + if (t->mode == TFM_TRANSLATION) { + if(TRACK_AREA_SELECTED(track, TRACK_AREA_PAT)) + BKE_tracking_clamp_track(track, CLAMP_PAT_POS); + if(TRACK_AREA_SELECTED(track, TRACK_AREA_SEARCH)) + BKE_tracking_clamp_track(track, CLAMP_SEARCH_POS); + } + else if (t->mode == TFM_RESIZE) { + if(TRACK_AREA_SELECTED(track, TRACK_AREA_PAT)) + BKE_tracking_clamp_track(track, CLAMP_PAT_DIM); + if(TRACK_AREA_SELECTED(track, TRACK_AREA_SEARCH)) + BKE_tracking_clamp_track(track, CLAMP_SEARCH_DIM); + } + } + + track= track->next; + } + + DAG_id_tag_update(&clip->id, 0); +} + /* helper for recalcData() - for 3d-view transforms */ static void recalcData_view3d(TransInfo *t) { @@ -853,60 +912,13 @@ void recalcData(TransInfo *t) recalcData_nla(t); } else if (t->spacetype == SPACE_IMAGE) { - if (t->obedit && t->obedit->type == OB_MESH) { - SpaceImage *sima= t->sa->spacedata.first; - - flushTransUVs(t); - if(sima->flag & SI_LIVE_UNWRAP) - ED_uvedit_live_unwrap_re_solve(); - - DAG_id_tag_update(t->obedit->data, 0); - } + recalcData_image(t); } else if (t->spacetype == SPACE_VIEW3D) { recalcData_view3d(t); } else if (t->spacetype == SPACE_CLIP) { - SpaceClip *sc= t->sa->spacedata.first; - MovieClip *clip= ED_space_clip(sc); - MovieTrackingTrack *track; - - if(t->state == TRANS_CANCEL) { - track= clip->tracking.tracks.first; - while(track) { - if(TRACK_VIEW_SELECTED(sc, track)) { - MovieTrackingMarker *marker= BKE_tracking_ensure_marker(track, sc->user.framenr); - - marker->flag= track->transflag; - } - - track= track->next; - } - } - - flushTransTracking(t); - - track= clip->tracking.tracks.first; - while(track) { - if(TRACK_VIEW_SELECTED(sc, track)) { - if (t->mode == TFM_TRANSLATION) { - if(TRACK_AREA_SELECTED(track, TRACK_AREA_PAT)) - BKE_tracking_clamp_track(track, CLAMP_PAT_POS); - if(TRACK_AREA_SELECTED(track, TRACK_AREA_SEARCH)) - BKE_tracking_clamp_track(track, CLAMP_SEARCH_POS); - } - else if (t->mode == TFM_RESIZE) { - if(TRACK_AREA_SELECTED(track, TRACK_AREA_PAT)) - BKE_tracking_clamp_track(track, CLAMP_PAT_DIM); - if(TRACK_AREA_SELECTED(track, TRACK_AREA_SEARCH)) - BKE_tracking_clamp_track(track, CLAMP_SEARCH_DIM); - } - } - - track= track->next; - } - - DAG_id_tag_update(&clip->id, 0); + recalcData_clip(t); } } 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) { |