diff options
author | Tamito Kajiyama <rd6t-kjym@asahi-net.or.jp> | 2013-01-27 03:49:13 +0400 |
---|---|---|
committer | Tamito Kajiyama <rd6t-kjym@asahi-net.or.jp> | 2013-01-27 03:49:13 +0400 |
commit | 556912792ad3c37c294256a558c96b39f264e7b5 (patch) | |
tree | 9b6ee8cf1ad92ee89c04f27a89be11599c5b40c0 /source/blender/editors | |
parent | 9251d628db0abe599d927d79170025d8545c8ace (diff) | |
parent | c84383301c5a2582e95259a7e4468a23a3566401 (diff) |
Merged changes in the trunk up to revision 54110.
Conflicts resolved:
source/blender/blenfont/SConscript
source/blender/blenkernel/intern/subsurf_ccg.c
source/blender/makesdna/intern/makesdna.c
source/blender/makesrna/intern/rna_scene.c
Diffstat (limited to 'source/blender/editors')
107 files changed, 4008 insertions, 1769 deletions
diff --git a/source/blender/editors/armature/editarmature.c b/source/blender/editors/armature/editarmature.c index 37314373e98..ca2fe48543a 100644 --- a/source/blender/editors/armature/editarmature.c +++ b/source/blender/editors/armature/editarmature.c @@ -2002,7 +2002,7 @@ float ED_rollBoneToVector(EditBone *bone, const float align_axis[3], const short sub_v3_v3v3(nor, bone->tail, bone->head); vec_roll_to_mat3(nor, 0.0f, mat); - + /* check the bone isn't aligned with the axis */ if (!is_zero_v3(align_axis) && angle_v3v3(align_axis, mat[2]) > FLT_EPSILON) { float vec[3], align_axis_proj[3], roll; @@ -4349,7 +4349,7 @@ void ARMATURE_OT_select_hierarchy(wmOperatorType *ot) /* props */ RNA_def_enum(ot->srna, "direction", direction_items, BONE_SELECT_PARENT, "Direction", ""); - RNA_def_boolean(ot->srna, "extend", 0, "Add to Selection", ""); + RNA_def_boolean(ot->srna, "extend", false, "Extend", "Extend the selection"); } /* ***************** EditBone Alignment ********************* */ @@ -4997,13 +4997,18 @@ void create_vgroups_from_armature(ReportList *reports, Scene *scene, Object *ob, bArmature *arm = par->data; if (mode == ARM_GROUPS_NAME) { + const int defbase_tot = BLI_countlist(&ob->defbase); + int defbase_add; /* Traverse the bone list, trying to create empty vertex * groups corresponding to the bone. */ - bone_looper(ob, arm->bonebase.first, NULL, vgroup_add_unique_bone_cb); + defbase_add = bone_looper(ob, arm->bonebase.first, NULL, vgroup_add_unique_bone_cb); - if (ob->type == OB_MESH) - ED_vgroup_data_create(ob->data); + if (defbase_add) { + /* its possible there are DWeight's outside the range of the current + * objects deform groups, in this case the new groups wont be empty [#33889] */ + ED_vgroup_data_clamp_range(ob->data, defbase_tot); + } } else if (mode == ARM_GROUPS_ENVELOPE || mode == ARM_GROUPS_AUTO) { /* Traverse the bone list, trying to create vertex groups diff --git a/source/blender/editors/armature/poseobject.c b/source/blender/editors/armature/poseobject.c index 49d4b670cde..38924105316 100644 --- a/source/blender/editors/armature/poseobject.c +++ b/source/blender/editors/armature/poseobject.c @@ -576,7 +576,7 @@ void POSE_OT_select_hierarchy(wmOperatorType *ot) /* props */ ot->prop = RNA_def_enum(ot->srna, "direction", direction_items, BONE_SELECT_PARENT, "Direction", ""); - RNA_def_boolean(ot->srna, "extend", 0, "Add to Selection", ""); + RNA_def_boolean(ot->srna, "extend", false, "Extend", "Extend the selection"); } /* ******************* select grouped operator ************* */ diff --git a/source/blender/editors/curve/editcurve.c b/source/blender/editors/curve/editcurve.c index 53e610401b7..a67bf00a559 100644 --- a/source/blender/editors/curve/editcurve.c +++ b/source/blender/editors/curve/editcurve.c @@ -1279,8 +1279,24 @@ void CU_deselect_all(Object *obedit) ListBase *editnurb = object_editcurve_get(obedit); if (editnurb) { - selectend_nurb(obedit, FIRST, 0, DESELECT); /* set first control points as unselected */ - select_adjacent_cp(editnurb, 1, 1, DESELECT); /* cascade selection */ + Nurb *nu; + int a; + for (nu = editnurb->first; nu; nu = nu->next) { + if (nu->bezt) { + BezTriple *bezt; + for (bezt = nu->bezt, a = 0; a < nu->pntsu; a++, bezt++) { + bezt->f1 &= ~SELECT; + bezt->f2 &= ~SELECT; + bezt->f3 &= ~SELECT; + } + } + else if (nu->bp) { + BPoint *bp; + for (bp = nu->bp, a = 0; a < nu->pntsu * nu->pntsv; a++, bp++) { + bp->f1 &= ~SELECT; + } + } + } } } @@ -1289,8 +1305,27 @@ void CU_select_all(Object *obedit) ListBase *editnurb = object_editcurve_get(obedit); if (editnurb) { - selectend_nurb(obedit, FIRST, 0, SELECT); /* set first control points as unselected */ - select_adjacent_cp(editnurb, 1, 1, SELECT); /* cascade selection */ + Nurb *nu; + int a; + for (nu = editnurb->first; nu; nu = nu->next) { + if (nu->bezt) { + BezTriple *bezt; + for (bezt = nu->bezt, a = 0; a < nu->pntsu; a++, bezt++) { + if (bezt->hide == 0) { + bezt->f1 |= SELECT; + bezt->f2 |= SELECT; + bezt->f3 |= SELECT; + } + } + } + else if (nu->bp) { + BPoint *bp; + for (bp = nu->bp, a = 0; a < nu->pntsu * nu->pntsv; a++, bp++) { + if (bp->hide == 0) + bp->f1 |= SELECT; + } + } + } } } @@ -5510,7 +5545,7 @@ void CURVE_OT_select_random(wmOperatorType *ot) /* properties */ RNA_def_float_percentage(ot->srna, "percent", 50.f, 0.0f, 100.0f, "Percent", "Percentage of elements to select randomly", 0.f, 100.0f); - RNA_def_boolean(ot->srna, "extend", FALSE, "Extend Selection", "Extend selection instead of deselecting everything first"); + RNA_def_boolean(ot->srna, "extend", false, "Extend", "Extend the selection"); } /********************* every nth number of point *******************/ diff --git a/source/blender/editors/datafiles/CMakeLists.txt b/source/blender/editors/datafiles/CMakeLists.txt index 6d6b7ecdd82..e9b33a6c2a6 100644 --- a/source/blender/editors/datafiles/CMakeLists.txt +++ b/source/blender/editors/datafiles/CMakeLists.txt @@ -81,6 +81,25 @@ if(WITH_BLENDER) data_to_c_simple(../../../../release/datafiles/brushicons/thumb.png SRC) data_to_c_simple(../../../../release/datafiles/brushicons/twist.png SRC) data_to_c_simple(../../../../release/datafiles/brushicons/vertexdraw.png SRC) + + # matcap + data_to_c_simple(../../../../release/datafiles/matcaps/mc01.jpg SRC) + data_to_c_simple(../../../../release/datafiles/matcaps/mc02.jpg SRC) + data_to_c_simple(../../../../release/datafiles/matcaps/mc03.jpg SRC) + data_to_c_simple(../../../../release/datafiles/matcaps/mc04.jpg SRC) + data_to_c_simple(../../../../release/datafiles/matcaps/mc05.jpg SRC) + data_to_c_simple(../../../../release/datafiles/matcaps/mc06.jpg SRC) + data_to_c_simple(../../../../release/datafiles/matcaps/mc07.jpg SRC) + data_to_c_simple(../../../../release/datafiles/matcaps/mc08.jpg SRC) + data_to_c_simple(../../../../release/datafiles/matcaps/mc09.jpg SRC) + data_to_c_simple(../../../../release/datafiles/matcaps/mc10.jpg SRC) + data_to_c_simple(../../../../release/datafiles/matcaps/mc11.jpg SRC) + data_to_c_simple(../../../../release/datafiles/matcaps/mc12.jpg SRC) + data_to_c_simple(../../../../release/datafiles/matcaps/mc13.jpg SRC) + data_to_c_simple(../../../../release/datafiles/matcaps/mc14.jpg SRC) + data_to_c_simple(../../../../release/datafiles/matcaps/mc15.jpg SRC) + data_to_c_simple(../../../../release/datafiles/matcaps/mc16.jpg SRC) + endif() data_to_c_simple(../../../../release/datafiles/startup.blend SRC) diff --git a/source/blender/editors/datafiles/SConscript b/source/blender/editors/datafiles/SConscript index cb6fe11dbb2..49888d573a0 100644 --- a/source/blender/editors/datafiles/SConscript +++ b/source/blender/editors/datafiles/SConscript @@ -77,6 +77,24 @@ sources.extend(( os.path.join(env['DATA_SOURCES'], "thumb.png.c"), os.path.join(env['DATA_SOURCES'], "twist.png.c"), os.path.join(env['DATA_SOURCES'], "vertexdraw.png.c"), + + os.path.join(env['DATA_SOURCES'], "mc01.jpg.c"), + os.path.join(env['DATA_SOURCES'], "mc02.jpg.c"), + os.path.join(env['DATA_SOURCES'], "mc03.jpg.c"), + os.path.join(env['DATA_SOURCES'], "mc04.jpg.c"), + os.path.join(env['DATA_SOURCES'], "mc05.jpg.c"), + os.path.join(env['DATA_SOURCES'], "mc06.jpg.c"), + os.path.join(env['DATA_SOURCES'], "mc07.jpg.c"), + os.path.join(env['DATA_SOURCES'], "mc08.jpg.c"), + os.path.join(env['DATA_SOURCES'], "mc09.jpg.c"), + os.path.join(env['DATA_SOURCES'], "mc10.jpg.c"), + os.path.join(env['DATA_SOURCES'], "mc11.jpg.c"), + os.path.join(env['DATA_SOURCES'], "mc12.jpg.c"), + os.path.join(env['DATA_SOURCES'], "mc13.jpg.c"), + os.path.join(env['DATA_SOURCES'], "mc14.jpg.c"), + os.path.join(env['DATA_SOURCES'], "mc15.jpg.c"), + os.path.join(env['DATA_SOURCES'], "mc16.jpg.c"), + )) env.BlenderLib ( 'bf_editor_datafiles', sources, Split(incs), [], libtype=['core', 'player'], priority=[235, 30] ) diff --git a/source/blender/editors/gpencil/gpencil_edit.c b/source/blender/editors/gpencil/gpencil_edit.c index e4e640eeefc..671adfb8d1e 100644 --- a/source/blender/editors/gpencil/gpencil_edit.c +++ b/source/blender/editors/gpencil/gpencil_edit.c @@ -1387,12 +1387,15 @@ static void gp_layer_to_curve(bContext *C, ReportList *reports, bGPdata *gpd, bG static int gp_convert_check_has_valid_timing(bContext *C, bGPDlayer *gpl, wmOperator *op) { Scene *scene = CTX_data_scene(C); - bGPDframe *gpf = gpencil_layer_getframe(gpl, CFRA, 0); - bGPDstroke *gps = gpf->strokes.first; + bGPDframe *gpf = NULL; + bGPDstroke *gps = NULL; bGPDspoint *pt; double base_time, cur_time, prev_time = -1.0; int i, valid = TRUE; + if (!gpl || !(gpf = gpencil_layer_getframe(gpl, CFRA, 0)) || !(gps = gpf->strokes.first)) + return FALSE; + do { base_time = cur_time = gps->inittime; if (cur_time <= prev_time) { @@ -1438,11 +1441,19 @@ static void gp_convert_set_end_frame(struct Main *UNUSED(main), struct Scene *UN static int gp_convert_poll(bContext *C) { bGPdata *gpd = gpencil_data_get_active(C); + bGPDlayer *gpl = NULL; + bGPDframe *gpf = NULL; ScrArea *sa = CTX_wm_area(C); Scene *scene = CTX_data_scene(C); - /* only if there's valid data, and the current view is 3D View */ - return ((sa && sa->spacetype == SPACE_VIEW3D) && gpencil_layer_getactive(gpd) && (scene->obedit == NULL)); + /* only if the current view is 3D View, if there's valid data (i.e. at least one stroke!), + * and if we are not in edit mode! + */ + return ((sa && sa->spacetype == SPACE_VIEW3D) && + (gpl = gpencil_layer_getactive(gpd)) && + (gpf = gpencil_layer_getframe(gpl, CFRA, 0)) && + (gpf->strokes.first) && + (scene->obedit == NULL)); } static int gp_convert_layer_exec(bContext *C, wmOperator *op) diff --git a/source/blender/editors/gpencil/gpencil_paint.c b/source/blender/editors/gpencil/gpencil_paint.c index c40312758fc..41ef4bd0b95 100644 --- a/source/blender/editors/gpencil/gpencil_paint.c +++ b/source/blender/editors/gpencil/gpencil_paint.c @@ -1564,8 +1564,8 @@ static void gpencil_draw_apply_event(wmOperator *op, wmEvent *event) p->curtime = PIL_check_seconds_timer(); /* handle pressure sensitivity (which is supplied by tablets) */ - if (event->custom == EVT_DATA_TABLET) { - wmTabletData *wmtab = event->customdata; + if (event->tablet_data) { + wmTabletData *wmtab = event->tablet_data; tablet = (wmtab->Active != EVT_TABLET_NONE); p->pressure = wmtab->Pressure; diff --git a/source/blender/editors/include/ED_datafiles.h b/source/blender/editors/include/ED_datafiles.h index 6d7bcecc630..afe23090ae3 100644 --- a/source/blender/editors/include/ED_datafiles.h +++ b/source/blender/editors/include/ED_datafiles.h @@ -150,6 +150,57 @@ extern char datatoc_twist_png[]; extern int datatoc_vertexdraw_png_size; extern char datatoc_vertexdraw_png[]; +/* Matcap files */ + +extern int datatoc_mc01_jpg_size; +extern char datatoc_mc01_jpg[]; + +extern int datatoc_mc02_jpg_size; +extern char datatoc_mc02_jpg[]; + +extern int datatoc_mc03_jpg_size; +extern char datatoc_mc03_jpg[]; + +extern int datatoc_mc04_jpg_size; +extern char datatoc_mc04_jpg[]; + +extern int datatoc_mc05_jpg_size; +extern char datatoc_mc05_jpg[]; + +extern int datatoc_mc06_jpg_size; +extern char datatoc_mc06_jpg[]; + +extern int datatoc_mc07_jpg_size; +extern char datatoc_mc07_jpg[]; + +extern int datatoc_mc08_jpg_size; +extern char datatoc_mc08_jpg[]; + +extern int datatoc_mc09_jpg_size; +extern char datatoc_mc09_jpg[]; + +extern int datatoc_mc10_jpg_size; +extern char datatoc_mc10_jpg[]; + +extern int datatoc_mc11_jpg_size; +extern char datatoc_mc11_jpg[]; + +extern int datatoc_mc12_jpg_size; +extern char datatoc_mc12_jpg[]; + +extern int datatoc_mc13_jpg_size; +extern char datatoc_mc13_jpg[]; + +extern int datatoc_mc14_jpg_size; +extern char datatoc_mc14_jpg[]; + +extern int datatoc_mc15_jpg_size; +extern char datatoc_mc15_jpg[]; + +extern int datatoc_mc16_jpg_size; +extern char datatoc_mc16_jpg[]; + + #endif /* __ED_DATAFILES_H__ */ diff --git a/source/blender/editors/include/ED_mesh.h b/source/blender/editors/include/ED_mesh.h index f5ab002e0ef..d3de2593b9d 100644 --- a/source/blender/editors/include/ED_mesh.h +++ b/source/blender/editors/include/ED_mesh.h @@ -119,7 +119,7 @@ int EDBM_vert_color_check(struct BMEditMesh *em); void EDBM_mesh_hide(struct BMEditMesh *em, int swap); void EDBM_mesh_reveal(struct BMEditMesh *em); -void EDBM_update_generic(struct BMEditMesh *em, const short do_tessface, const short is_destructive); +void EDBM_update_generic(struct BMEditMesh *em, const bool do_tessface, const bool is_destructive); struct UvElementMap *EDBM_uv_element_map_create(struct BMEditMesh *em, int selected, int doIslands); void EDBM_uv_element_map_free(struct UvElementMap *vmap); @@ -130,7 +130,7 @@ struct MTexPoly *EDBM_mtexpoly_active_get(struct BMEditMesh *em, struct BMFace * void EDBM_uv_vert_map_free(struct UvVertMap *vmap); struct UvMapVert *EDBM_uv_vert_map_at_index(struct UvVertMap *vmap, unsigned int v); -struct UvVertMap *EDBM_uv_vert_map_create(struct BMEditMesh *em, int selected, const float limit[2]); +struct UvVertMap *EDBM_uv_vert_map_create(struct BMEditMesh *em, bool use_select, const float limit[2]); void EDBM_flag_enable_all(struct BMEditMesh *em, const char hflag); void EDBM_flag_disable_all(struct BMEditMesh *em, const char hflag); @@ -227,6 +227,7 @@ void ED_vgroup_delete(struct Object *ob, struct bDeformGroup *de void ED_vgroup_clear(struct Object *ob); void ED_vgroup_select_by_name(struct Object *ob, const char *name); int ED_vgroup_data_create(struct ID *id); +void ED_vgroup_data_clamp_range(struct ID *id, const int total); int ED_vgroup_give_array(struct ID *id, struct MDeformVert **dvert_arr, int *dvert_tot); int ED_vgroup_copy_array(struct Object *ob, struct Object *ob_from); void ED_vgroup_mirror(struct Object *ob, const short mirror_weights, const short flip_vgroups, const short all_vgroups); diff --git a/source/blender/editors/include/ED_physics.h b/source/blender/editors/include/ED_physics.h index cd9ddd3d7d1..192bcd8f712 100644 --- a/source/blender/editors/include/ED_physics.h +++ b/source/blender/editors/include/ED_physics.h @@ -32,13 +32,26 @@ #ifndef __ED_PHYSICS_H__ #define __ED_PHYSICS_H__ +struct bContext; +struct wmOperator; struct wmKeyConfig; +struct Scene; +struct Object; + /* particle_edit.c */ int PE_poll(struct bContext *C); int PE_hair_poll(struct bContext *C); int PE_poll_view3d(struct bContext *C); +/* rigidbody_object.c */ +void ED_rigidbody_ob_add(struct wmOperator *op, struct Scene *scene, struct Object *ob, int type); +void ED_rigidbody_ob_remove(struct Scene *scene, struct Object *ob); + +/* rigidbody_constraint.c */ +void ED_rigidbody_con_add(struct wmOperator *op, struct Scene *scene, struct Object *ob, int type); +void ED_rigidbody_con_remove(struct Scene *scene, struct Object *ob); + /* operators */ void ED_operatortypes_physics(void); void ED_keymap_physics(struct wmKeyConfig *keyconf); diff --git a/source/blender/editors/include/ED_transform.h b/source/blender/editors/include/ED_transform.h index 03c1dd5a86d..a41aaca15bd 100644 --- a/source/blender/editors/include/ED_transform.h +++ b/source/blender/editors/include/ED_transform.h @@ -83,6 +83,7 @@ enum { TFM_BWEIGHT, TFM_ALIGN, TFM_EDGE_SLIDE, + TFM_VERT_SLIDE, TFM_SEQ_SLIDE } TfmMode; diff --git a/source/blender/editors/include/UI_icons.h b/source/blender/editors/include/UI_icons.h index 0a794040692..f5ac3f19b5b 100644 --- a/source/blender/editors/include/UI_icons.h +++ b/source/blender/editors/include/UI_icons.h @@ -990,11 +990,29 @@ DEF_ICON(BRUSH_THUMB) DEF_ICON(BRUSH_ROTATE) DEF_ICON(BRUSH_VERTEXDRAW) + /* Matcaps */ +DEF_ICON(MATCAP_01) +DEF_ICON(MATCAP_02) +DEF_ICON(MATCAP_03) +DEF_ICON(MATCAP_04) +DEF_ICON(MATCAP_05) +DEF_ICON(MATCAP_06) +DEF_ICON(MATCAP_07) +DEF_ICON(MATCAP_08) +DEF_ICON(MATCAP_09) +DEF_ICON(MATCAP_10) +DEF_ICON(MATCAP_11) +DEF_ICON(MATCAP_12) +DEF_ICON(MATCAP_13) +DEF_ICON(MATCAP_14) +DEF_ICON(MATCAP_15) +DEF_ICON(MATCAP_16) + /* vector icons, VICO_ prefix added */ DEF_VICO(VIEW3D_VEC) DEF_VICO(EDIT_VEC) -DEF_VICO(EDITMODE_DEHLT) -DEF_VICO(EDITMODE_HLT) +DEF_VICO(EDITMODE_VEC_DEHLT) +DEF_VICO(EDITMODE_VEC_HLT) DEF_VICO(DISCLOSURE_TRI_RIGHT_VEC) DEF_VICO(DISCLOSURE_TRI_DOWN_VEC) DEF_VICO(MOVE_UP_VEC) diff --git a/source/blender/editors/include/UI_interface.h b/source/blender/editors/include/UI_interface.h index 292cc4cdca0..e9cb2eff7e3 100644 --- a/source/blender/editors/include/UI_interface.h +++ b/source/blender/editors/include/UI_interface.h @@ -807,6 +807,7 @@ uiLayout *uiTemplateModifier(uiLayout *layout, struct bContext *C, struct Pointe uiLayout *uiTemplateConstraint(uiLayout *layout, struct PointerRNA *ptr); void uiTemplatePreview(uiLayout *layout, struct ID *id, int show_buttons, struct ID *parent, struct MTex *slot); void uiTemplateColorRamp(uiLayout *layout, struct PointerRNA *ptr, const char *propname, int expand); +void uiTemplateIconView(uiLayout *layout, struct PointerRNA *ptr, const char *propname); void uiTemplateHistogram(uiLayout *layout, struct PointerRNA *ptr, const char *propname); void uiTemplateWaveform(uiLayout *layout, struct PointerRNA *ptr, const char *propname); void uiTemplateVectorscope(uiLayout *layout, struct PointerRNA *ptr, const char *propname); diff --git a/source/blender/editors/include/UI_interface_icons.h b/source/blender/editors/include/UI_interface_icons.h index f578d68b852..10026bbd50f 100644 --- a/source/blender/editors/include/UI_interface_icons.h +++ b/source/blender/editors/include/UI_interface_icons.h @@ -39,6 +39,7 @@ struct World; struct Tex; struct Lamp; struct Material; +struct PreviewImage; struct PointerRNA; typedef struct IconFile { @@ -76,6 +77,8 @@ void UI_icons_free_drawinfo(void *drawinfo); struct ListBase *UI_iconfile_list(void); int UI_iconfile_get_index(const char *filename); +struct PreviewImage *UI_icon_to_preview(int icon_id); + int UI_rnaptr_icon_get(struct bContext *C, struct PointerRNA *ptr, int rnaicon, int big); #endif /* __UI_INTERFACE_ICONS_H__ */ diff --git a/source/blender/editors/include/UI_resources.h b/source/blender/editors/include/UI_resources.h index 29b1a74e859..df07e05ec06 100644 --- a/source/blender/editors/include/UI_resources.h +++ b/source/blender/editors/include/UI_resources.h @@ -147,6 +147,8 @@ enum { TH_NODE_CONVERTOR, TH_NODE_GROUP, TH_NODE_FRAME, + TH_NODE_MATTE, + TH_NODE_DISTORT, TH_CONSOLE_OUTPUT, TH_CONSOLE_INPUT, diff --git a/source/blender/editors/interface/interface_handlers.c b/source/blender/editors/interface/interface_handlers.c index c87bb2a97a1..0d65cd19034 100644 --- a/source/blender/editors/interface/interface_handlers.c +++ b/source/blender/editors/interface/interface_handlers.c @@ -1416,11 +1416,11 @@ static int ui_textedit_delete_selection(uiBut *but, uiHandleButtonData *data) } /* note, but->block->aspect is used here, when drawing button style is getting scaled too */ -static void ui_textedit_set_cursor_pos(uiBut *but, uiHandleButtonData *data, short x) +static void ui_textedit_set_cursor_pos(uiBut *but, uiHandleButtonData *data, const float x) { uiStyle *style = UI_GetStyle(); // XXX pass on as arg uiFontStyle *fstyle = &style->widget; - int startx = but->rect.xmin; + float startx = but->rect.xmin; char *origstr, password_str[UI_MAX_DRAW_STR]; uiStyleFontSet(fstyle); @@ -1430,24 +1430,27 @@ static void ui_textedit_set_cursor_pos(uiBut *but, uiHandleButtonData *data, sho ui_button_text_password_hide(password_str, but, FALSE); - origstr = MEM_callocN(sizeof(char) * data->maxlen, "ui_textedit origstr"); + origstr = MEM_mallocN(sizeof(char) * data->maxlen, "ui_textedit origstr"); BLI_strncpy(origstr, but->drawstr, data->maxlen); - /* XXX solve generic */ - if (but->type == NUM || but->type == NUMSLI) + /* XXX solve generic, see: #widget_draw_text_icon */ + if (but->type == NUM || but->type == NUMSLI) { startx += (int)(0.5f * (BLI_rctf_size_y(&but->rect))); + } else if (ELEM3(but->type, TEX, SEARCH_MENU, SEARCH_MENU_UNLINK)) { - startx += 5; - if (but->flag & UI_HAS_ICON) + if (but->flag & UI_HAS_ICON) { startx += UI_DPI_ICON_SIZE; + } + /* but this extra .05 makes clicks inbetween characters feel nicer */ + startx += ((UI_TEXT_MARGIN_X + 0.05f) * U.widget_unit); } /* mouse dragged outside the widget to the left */ - if (x < startx && but->ofs > 0) { + if (x < startx) { int i = but->ofs; - origstr[but->ofs] = 0; + origstr[but->ofs] = '\0'; while (i > 0) { if (BLI_str_cursor_step_prev_utf8(origstr, but->ofs, &i)) { @@ -1463,21 +1466,18 @@ static void ui_textedit_set_cursor_pos(uiBut *but, uiHandleButtonData *data, sho but->ofs = i; but->pos = but->ofs; } - /* mouse inside the widget */ - else if (x >= startx) { + /* mouse inside the widget, mouse coords mapped in widget space */ + else { /* (x >= startx) */ int pos_i; /* keep track of previous distance from the cursor to the char */ float cdist, cdist_prev = 0.0f; short pos_prev; - - const float aspect_sqrt = sqrtf(but->block->aspect); but->pos = pos_prev = strlen(origstr) - but->ofs; - while (TRUE) { - /* XXX does not take zoom level into account */ - cdist = startx + aspect_sqrt * BLF_width(fstyle->uifont_id, origstr + but->ofs); + while (true) { + cdist = startx + BLF_width(fstyle->uifont_id, origstr + but->ofs); /* check if position is found */ if (cdist < x) { @@ -1513,7 +1513,7 @@ static void ui_textedit_set_cursor_pos(uiBut *but, uiHandleButtonData *data, sho MEM_freeN(origstr); } -static void ui_textedit_set_cursor_select(uiBut *but, uiHandleButtonData *data, short x) +static void ui_textedit_set_cursor_select(uiBut *but, uiHandleButtonData *data, const float x) { if (x > data->selstartx) data->selextend = EXTEND_RIGHT; else if (x < data->selstartx) data->selextend = EXTEND_LEFT; @@ -2593,6 +2593,7 @@ static int ui_numedit_but_NUM(uiBut *but, uiHandleButtonData *data, float fac, i { float deler, tempf, softmin, softmax, softrange; int lvalue, temp, changed = 0; + const bool is_float = ui_is_but_float(but); if (mx == data->draglastx) return changed; @@ -2614,7 +2615,7 @@ static int ui_numedit_but_NUM(uiBut *but, uiHandleButtonData *data, float fac, i if (ui_is_a_warp_but(but)) { /* Mouse location isn't screen clamped to the screen so use a linear mapping * 2px == 1-int, or 1px == 1-ClickStep */ - if (ui_is_but_float(but)) { + if (is_float) { fac *= 0.01f * but->a1; tempf = (float)data->startvalue + ((float)(mx - data->dragstartx) * fac); tempf = ui_numedit_apply_snapf(but, tempf, softmin, softmax, softrange, snap); @@ -2671,21 +2672,21 @@ static int ui_numedit_but_NUM(uiBut *but, uiHandleButtonData *data, float fac, i else { /* Use a non-linear mapping of the mouse drag especially for large floats (normal behavior) */ deler = 500; - if (!ui_is_but_float(but)) { + if (!is_float) { /* prevent large ranges from getting too out of control */ - if (softrange > 600) deler = powf(softrange, 0.75); - else if (softrange < 100) deler = 200.0; + if (softrange > 600) deler = powf(softrange, 0.75f); else if (softrange < 25) deler = 50.0; + else if (softrange < 100) deler = 100.0; } deler /= fac; - if (softrange > 11) { + if ((is_float == true) && (softrange > 11)) { /* non linear change in mouse input- good for high precicsion */ - data->dragf += (((float)(mx - data->draglastx)) / deler) * (fabsf(data->dragstartx - mx) * 0.002f); + data->dragf += (((float)(mx - data->draglastx)) / deler) * (fabsf(mx - data->dragstartx) / 500.0f); } - else if (softrange > 129) { /* only scale large int buttons */ + else if ((is_float == false) && (softrange > 129)) { /* only scale large int buttons */ /* non linear change in mouse input- good for high precicsionm ints need less fine tuning */ - data->dragf += (((float)(mx - data->draglastx)) / deler) * (fabsf(data->dragstartx - mx) * 0.004f); + data->dragf += (((float)(mx - data->draglastx)) / deler) * (fabsf(mx - data->dragstartx) / 250.0f); } else { /*no scaling */ @@ -2697,7 +2698,7 @@ static int ui_numedit_but_NUM(uiBut *but, uiHandleButtonData *data, float fac, i tempf = (softmin + data->dragf * softrange); - if (!ui_is_but_float(but)) { + if (!is_float) { temp = floorf(tempf + 0.5f); temp = ui_numedit_apply_snap(temp, softmin, softmax, snap); @@ -6559,6 +6560,7 @@ static int ui_handle_menu_event(bContext *C, wmEvent *event, uiPopupBlockHandle ui_pan_to_scroll(event, &type, &val); if (val == KM_PRESS) { + const eButType type_flip = BUT | ROW; PASS_EVENT_TO_PARENT_IF_NONACTIVE; @@ -6571,13 +6573,13 @@ static int ui_handle_menu_event(bContext *C, wmEvent *event, uiPopupBlockHandle { /* the following is just a hack - uiBut->type set to BUT and BUTM have there menus built * opposite ways - this should be changed so that all popup-menus use the same uiBlock->direction */ - if (but->type & BUT) + if (but->type & type_flip) but = ui_but_next(but); else but = ui_but_prev(but); } else { - if (but->type & BUT) + if (but->type & type_flip) but = ui_but_prev(but); else but = ui_but_next(but); @@ -6594,7 +6596,7 @@ static int ui_handle_menu_event(bContext *C, wmEvent *event, uiPopupBlockHandle ((ELEM(type, UPARROWKEY, WHEELUPMOUSE)) && (block->direction & UI_RIGHT)) || ((ELEM(type, DOWNARROWKEY, WHEELDOWNMOUSE)) && (block->direction & UI_TOP))) { - if ((bt = ui_but_first(block)) && (bt->type & BUT)) { + if ((bt = ui_but_first(block)) && (bt->type & type_flip)) { bt = ui_but_last(block); } else { @@ -6602,7 +6604,7 @@ static int ui_handle_menu_event(bContext *C, wmEvent *event, uiPopupBlockHandle } } else { - if ((bt = ui_but_first(block)) && (bt->type & BUT)) { + if ((bt = ui_but_first(block)) && (bt->type & type_flip)) { /* keep ui_but_first() */ } else { diff --git a/source/blender/editors/interface/interface_icons.c b/source/blender/editors/interface/interface_icons.c index 68780083b97..8b4b1752774 100644 --- a/source/blender/editors/interface/interface_icons.c +++ b/source/blender/editors/interface/interface_icons.c @@ -75,10 +75,6 @@ #include "interface_intern.h" - -// #define ICON_IMAGE_W 600 -// #define ICON_IMAGE_H 640 - #define ICON_GRID_COLS 26 #define ICON_GRID_ROWS 30 @@ -89,7 +85,9 @@ typedef struct IconImage { int w; int h; - unsigned int *rect; + unsigned int *rect; + unsigned char *datatoc_rect; + int datatoc_size; } IconImage; typedef void (*VectorDrawFunc)(int x, int y, int w, int h, float alpha); @@ -132,13 +130,12 @@ static IconTexture icongltex = {0, 0, 0, 0.0f, 0.0f}; /* **************************************************** */ -static void def_internal_icon(ImBuf *bbuf, int icon_id, int xofs, int yofs, int size, int type) + +static DrawInfo *def_internal_icon(ImBuf *bbuf, int icon_id, int xofs, int yofs, int size, int type) { Icon *new_icon = NULL; IconImage *iimg = NULL; DrawInfo *di; - int y = 0; - int imgsize = 0; new_icon = MEM_callocN(sizeof(Icon), "texicon"); @@ -155,17 +152,27 @@ static void def_internal_icon(ImBuf *bbuf, int icon_id, int xofs, int yofs, int di->data.texture.h = size; } else if (type == ICON_TYPE_BUFFER) { - iimg = MEM_mallocN(sizeof(IconImage), "icon_img"); - iimg->rect = MEM_mallocN(size * size * sizeof(unsigned int), "icon_rect"); + iimg = MEM_callocN(sizeof(IconImage), "icon_img"); iimg->w = size; iimg->h = size; - /* Here we store the rect in the icon - same as before */ - imgsize = bbuf->x; - for (y = 0; y < size; y++) { - memcpy(&iimg->rect[y * size], &bbuf->rect[(y + yofs) * imgsize + xofs], size * sizeof(int)); + /* icon buffers can get initialized runtime now, via datatoc */ + if (bbuf) { + int y, imgsize; + + iimg->rect = MEM_mallocN(size * size * sizeof(unsigned int), "icon_rect"); + + /* Here we store the rect in the icon - same as before */ + if (size == bbuf->x && size == bbuf->y && xofs == 0 && yofs == 0) + memcpy(iimg->rect, bbuf->rect, size * size * sizeof(int)); + else { + /* this code assumes square images */ + imgsize = bbuf->x; + for (y = 0; y < size; y++) { + memcpy(&iimg->rect[y * size], &bbuf->rect[(y + yofs) * imgsize + xofs], imgsize * sizeof(int)); + } + } } - di->data.buffer.image = iimg; } @@ -173,6 +180,8 @@ static void def_internal_icon(ImBuf *bbuf, int icon_id, int xofs, int yofs, int new_icon->drawinfo = di; BKE_icon_set(icon_id, new_icon); + + return di; } static void def_internal_vicon(int icon_id, VectorDrawFunc drawFunc) @@ -463,21 +472,19 @@ static void vicon_move_down_draw(int x, int y, int w, int h, float UNUSED(alpha) static void init_brush_icons(void) { -#define INIT_BRUSH_ICON(icon_id, name) \ - { \ - bbuf = IMB_ibImageFromMemory((unsigned char *)datatoc_ ##name## _png, \ - datatoc_ ##name## _png_size, \ - IB_rect, NULL, "<brush icon>"); \ - if (bbuf) { \ - IMB_premultiply_alpha(bbuf); \ - def_internal_icon(bbuf, icon_id, 0, 0, w, ICON_TYPE_BUFFER); \ - } \ - IMB_freeImBuf(bbuf); \ - } (void)0 +#define INIT_BRUSH_ICON(icon_id, name) \ + { \ + unsigned char *rect = (unsigned char *)datatoc_ ##name## _png; \ + int size = datatoc_ ##name## _png_size; \ + DrawInfo *di; \ + \ + di = def_internal_icon(NULL, icon_id, 0, 0, w, ICON_TYPE_BUFFER); \ + di->data.buffer.image->datatoc_rect = rect; \ + di->data.buffer.image->datatoc_size = size; \ + } /* end INIT_BRUSH_ICON */ - ImBuf *bbuf; - const int w = 96; + const int w = 96; /* warning, brush size hardcoded in C, but it gets scaled */ INIT_BRUSH_ICON(ICON_BRUSH_ADD, add); INIT_BRUSH_ICON(ICON_BRUSH_BLOB, blob); @@ -513,6 +520,60 @@ static void init_brush_icons(void) #undef INIT_BRUSH_ICON } +static void icon_verify_datatoc(IconImage *iimg) +{ + /* if it has own rect, things are all OK */ + if (iimg->rect) + return; + + if (iimg->datatoc_rect) { + ImBuf *bbuf = IMB_ibImageFromMemory(iimg->datatoc_rect, + iimg->datatoc_size, IB_rect, NULL, "<matcap icon>"); + /* w and h were set on initialize */ + if (bbuf->x != iimg->h && bbuf->y != iimg->w) + IMB_scalefastImBuf(bbuf, iimg->w, iimg->h); + + iimg->rect = bbuf->rect; + bbuf->rect = NULL; + IMB_freeImBuf(bbuf); + } +} + +static void init_matcap_icons(void) +{ + /* dynamic allocation now, tucking datatoc pointers in DrawInfo */ +#define INIT_MATCAP_ICON(icon_id, name) \ + { \ + unsigned char *rect = (unsigned char *)datatoc_ ##name## _jpg; \ + int size = datatoc_ ##name## _jpg_size; \ + DrawInfo *di; \ + \ + di = def_internal_icon(NULL, icon_id, 0, 0, 128, ICON_TYPE_BUFFER); \ + di->data.buffer.image->datatoc_rect = rect; \ + di->data.buffer.image->datatoc_size = size; \ + } (void)0 + + INIT_MATCAP_ICON(ICON_MATCAP_01, mc01); + INIT_MATCAP_ICON(ICON_MATCAP_02, mc02); + INIT_MATCAP_ICON(ICON_MATCAP_03, mc03); + INIT_MATCAP_ICON(ICON_MATCAP_04, mc04); + INIT_MATCAP_ICON(ICON_MATCAP_05, mc05); + INIT_MATCAP_ICON(ICON_MATCAP_06, mc06); + INIT_MATCAP_ICON(ICON_MATCAP_07, mc07); + INIT_MATCAP_ICON(ICON_MATCAP_08, mc08); + INIT_MATCAP_ICON(ICON_MATCAP_09, mc09); + INIT_MATCAP_ICON(ICON_MATCAP_10, mc10); + INIT_MATCAP_ICON(ICON_MATCAP_11, mc11); + INIT_MATCAP_ICON(ICON_MATCAP_12, mc12); + INIT_MATCAP_ICON(ICON_MATCAP_13, mc13); + INIT_MATCAP_ICON(ICON_MATCAP_14, mc14); + INIT_MATCAP_ICON(ICON_MATCAP_15, mc15); + INIT_MATCAP_ICON(ICON_MATCAP_16, mc16); + +#undef INIT_MATCAP_ICON + +} + static void init_internal_icons(void) { // bTheme *btheme = UI_GetTheme(); @@ -613,8 +674,8 @@ static void init_internal_icons(void) def_internal_vicon(VICO_VIEW3D_VEC, vicon_view3d_draw); def_internal_vicon(VICO_EDIT_VEC, vicon_edit_draw); - def_internal_vicon(VICO_EDITMODE_DEHLT, vicon_editmode_dehlt_draw); - def_internal_vicon(VICO_EDITMODE_HLT, vicon_editmode_hlt_draw); + def_internal_vicon(VICO_EDITMODE_VEC_DEHLT, vicon_editmode_dehlt_draw); + def_internal_vicon(VICO_EDITMODE_VEC_HLT, vicon_editmode_hlt_draw); def_internal_vicon(VICO_DISCLOSURE_TRI_RIGHT_VEC, vicon_disclosure_tri_right_draw); def_internal_vicon(VICO_DISCLOSURE_TRI_DOWN_VEC, vicon_disclosure_tri_down_draw); def_internal_vicon(VICO_MOVE_UP_VEC, vicon_move_up_draw); @@ -762,7 +823,8 @@ void UI_icons_free_drawinfo(void *drawinfo) if (di) { if (di->type == ICON_TYPE_BUFFER) { if (di->data.buffer.image) { - MEM_freeN(di->data.buffer.image->rect); + if (di->data.buffer.image->rect) + MEM_freeN(di->data.buffer.image->rect); MEM_freeN(di->data.buffer.image); } } @@ -842,6 +904,7 @@ void UI_icons_init(int first_dyn_id) BKE_icons_init(first_dyn_id); init_internal_icons(); init_brush_icons(); + init_matcap_icons(); #endif } @@ -891,6 +954,34 @@ static void icon_set_image(bContext *C, ID *id, PreviewImage *prv_img, enum eIco prv_img->w[size], prv_img->h[size]); } +PreviewImage *UI_icon_to_preview(int icon_id) +{ + Icon *icon = BKE_icon_get(icon_id); + + if (icon) { + DrawInfo *di = (DrawInfo *)icon->drawinfo; + if (di && di->data.buffer.image) { + ImBuf *bbuf; + + bbuf = IMB_ibImageFromMemory(di->data.buffer.image->datatoc_rect, di->data.buffer.image->datatoc_size, IB_rect, NULL, "<matcap buffer>"); + if (bbuf) { + PreviewImage *prv = BKE_previewimg_create(); + + prv->rect[0] = bbuf->rect; + + prv->w[0] = bbuf->x; + prv->h[0] = bbuf->y; + + bbuf->rect = NULL; + IMB_freeImBuf(bbuf); + + return prv; + } + } + } + return NULL; +} + static void icon_draw_rect(float x, float y, int w, int h, float UNUSED(aspect), int rw, int rh, unsigned int *rect, float alpha, const float rgb[3], short is_preview) { @@ -994,6 +1085,8 @@ static int get_draw_size(enum eIconSizes size) return 0; } + + static void icon_draw_size(float x, float y, int icon_id, float aspect, float alpha, const float rgb[3], enum eIconSizes size, int draw_size, int UNUSED(nocreate), short is_preview) { @@ -1029,7 +1122,7 @@ static void icon_draw_size(float x, float y, int icon_id, float aspect, float al if (di->type == ICON_TYPE_VECTOR) { /* vector icons use the uiBlock transformation, they are not drawn * with untransformed coordinates like the other icons */ - di->data.vector.func((int)x, (int)y, ICON_DEFAULT_HEIGHT, ICON_DEFAULT_HEIGHT, 1.0f); + di->data.vector.func((int)x, (int)y, w, h, 1.0f); } else if (di->type == ICON_TYPE_TEXTURE) { /* texture image use premul alpha for correct scaling */ @@ -1042,6 +1135,8 @@ static void icon_draw_size(float x, float y, int icon_id, float aspect, float al /* it is a builtin icon */ iimg = di->data.buffer.image; + icon_verify_datatoc(iimg); + if (!iimg->rect) return; /* something has gone wrong! */ glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA); diff --git a/source/blender/editors/interface/interface_intern.h b/source/blender/editors/interface/interface_intern.h index 706301dc060..0b94a0dabdc 100644 --- a/source/blender/editors/interface/interface_intern.h +++ b/source/blender/editors/interface/interface_intern.h @@ -537,6 +537,8 @@ extern unsigned char checker_stipple_sml[32 * 32 / 8]; #define UI_TRANSP_DARK 100 #define UI_TRANSP_LIGHT 160 +#define UI_TEXT_MARGIN_X 0.4f + /* interface_style.c */ void uiStyleInit(void); diff --git a/source/blender/editors/interface/interface_layout.c b/source/blender/editors/interface/interface_layout.c index 3b0a1cd3eb5..10375824518 100644 --- a/source/blender/editors/interface/interface_layout.c +++ b/source/blender/editors/interface/interface_layout.c @@ -491,7 +491,14 @@ static void ui_item_enum_expand(uiLayout *layout, uiBlock *block, PointerRNA *pt RNA_property_enum_items_gettexted(block->evil_C, ptr, prop, &item, &totitem, &free); - uiBlockSetCurLayout(block, ui_item_local_sublayout(layout, layout, 1)); + /* we dont want nested rows, cols in menus */ + if (layout->root->type != UI_LAYOUT_MENU) { + uiBlockSetCurLayout(block, ui_item_local_sublayout(layout, layout, 1)); + } + else { + uiBlockSetCurLayout(block, layout); + } + for (a = 0; a < totitem; a++) { if (!item[a].identifier[0]) continue; @@ -1456,6 +1463,7 @@ void uiItemPointerR(uiLayout *layout, struct PointerRNA *ptr, const char *propna block = uiLayoutGetBlock(layout); ui_item_rna_size(layout, name, icon, ptr, prop, 0, 0, &w, &h); + w += UI_UNIT_X; /* X icon needs more space */ but = ui_item_with_label(layout, block, name, icon, ptr, prop, 0, 0, 0, w, h, 0); ui_but_add_search(but, ptr, prop, searchptr, searchprop); diff --git a/source/blender/editors/interface/interface_panel.c b/source/blender/editors/interface/interface_panel.c index 9fbf2fe8898..00c45e41587 100644 --- a/source/blender/editors/interface/interface_panel.c +++ b/source/blender/editors/interface/interface_panel.c @@ -522,11 +522,9 @@ void ui_draw_aligned_panel(uiStyle *style, uiBlock *block, rcti *rect) float y = headrect.ymax; glEnable(GL_BLEND); - if (UI_GetThemeValue(TH_PANEL_SHOW_HEADER)) { /* draw with background color */ - glEnable(GL_BLEND); UI_ThemeColor4(TH_PANEL_HEADER); glRectf(minx, headrect.ymin + 1, maxx, y); @@ -542,7 +540,6 @@ void ui_draw_aligned_panel(uiStyle *style, uiBlock *block, rcti *rect) fdrawline(minx, y, maxx, y); glColor4f(1.0f, 1.0f, 1.0f, 0.25f); fdrawline(minx, y - 1, maxx, y - 1); - glDisable(GL_BLEND); } glDisable(GL_BLEND); @@ -1157,6 +1154,9 @@ int ui_handler_panel_region(bContext *C, wmEvent *event) if (block->rect.xmin <= mx && block->rect.xmin + PNL_HEADER >= mx) inside_header = 1; } + else if (block->rect.xmin > mx || block->rect.xmax < mx) { + /* outside left/right side */ + } else if ((block->rect.ymax <= my) && (block->rect.ymax + PNL_HEADER >= my)) { inside_header = 1; } diff --git a/source/blender/editors/interface/interface_regions.c b/source/blender/editors/interface/interface_regions.c index ca5e2a1926c..e846fc3f078 100644 --- a/source/blender/editors/interface/interface_regions.c +++ b/source/blender/editors/interface/interface_regions.c @@ -651,7 +651,7 @@ ARegion *ui_tooltip_create(bContext *C, ARegion *butregion, uiBut *but) ofsx = 0; //(but->block->panel) ? but->block->panel->ofsx : 0; ofsy = 0; //(but->block->panel) ? but->block->panel->ofsy : 0; - rect_fl.xmin = (but->rect.xmin + but->rect.xmax) * 0.5f + ofsx - TIP_BORDER_X; + rect_fl.xmin = BLI_rctf_cent_x(&but->rect) + ofsx - TIP_BORDER_X; rect_fl.xmax = rect_fl.xmin + fontw + TIP_BORDER_X; rect_fl.ymax = but->rect.ymin + ofsy - TIP_BORDER_Y; rect_fl.ymin = rect_fl.ymax - fonth - TIP_BORDER_Y; diff --git a/source/blender/editors/interface/interface_templates.c b/source/blender/editors/interface/interface_templates.c index f704ac0e203..ec2b4f5adf0 100644 --- a/source/blender/editors/interface/interface_templates.c +++ b/source/blender/editors/interface/interface_templates.c @@ -34,11 +34,14 @@ #include "DNA_dynamicpaint_types.h" #include "DNA_scene_types.h" #include "DNA_object_types.h" +#include "DNA_object_force.h" #include "BLI_utildefines.h" #include "BLI_string.h" #include "BLI_ghash.h" #include "BLI_rect.h" +#include "BLI_math.h" +#include "BLI_listbase.h" #include "BLF_api.h" #include "BLF_translation.h" @@ -46,22 +49,26 @@ #include "BKE_animsys.h" #include "BKE_colortools.h" #include "BKE_context.h" +#include "BKE_depsgraph.h" +#include "BKE_displist.h" #include "BKE_dynamicpaint.h" #include "BKE_global.h" #include "BKE_library.h" #include "BKE_main.h" -#include "BKE_object.h" #include "BKE_material.h" -#include "BKE_texture.h" +#include "BKE_modifier.h" +#include "BKE_object.h" +#include "BKE_particle.h" #include "BKE_report.h" -#include "BKE_displist.h" #include "BKE_sca.h" #include "BKE_scene.h" #include "BKE_screen.h" +#include "BKE_texture.h" #include "ED_screen.h" #include "ED_object.h" #include "ED_render.h" +#include "ED_util.h" #include "RNA_access.h" #include "RNA_enum_types.h" @@ -726,21 +733,6 @@ void uiTemplatePathBuilder(uiLayout *layout, PointerRNA *ptr, const char *propna #define ERROR_LIBDATA_MESSAGE "Can't edit external libdata" -#include <string.h> - -#include "DNA_object_force.h" - -#include "BKE_depsgraph.h" -#include "BKE_modifier.h" -#include "BKE_particle.h" - -#include "ED_util.h" - -#include "BLI_math.h" -#include "BLI_listbase.h" - -#include "ED_object.h" - static void modifiers_setOnCage(bContext *C, void *ob_v, void *md_v) { Scene *scene = CTX_data_scene(C); @@ -1564,6 +1556,88 @@ void uiTemplateColorRamp(uiLayout *layout, PointerRNA *ptr, const char *propname MEM_freeN(cb); } + +/********************* Icon viewer Template ************************/ + +/* ID Search browse menu, open */ +static uiBlock *icon_view_menu(bContext *C, ARegion *ar, void *arg_litem) +{ + static RNAUpdateCb cb; + uiBlock *block; + uiBut *but; + int icon; + EnumPropertyItem *item; + int a, free; + + /* arg_litem is malloced, can be freed by parent button */ + cb = *((RNAUpdateCb *)arg_litem); + + icon = RNA_property_enum_get(&cb.ptr, cb.prop); + + block = uiBeginBlock(C, ar, "_popup", UI_EMBOSS); + uiBlockSetFlag(block, UI_BLOCK_LOOP | UI_BLOCK_REDRAW); + + + RNA_property_enum_items(C, &cb.ptr, cb.prop, &item, NULL, &free); + + for (a = 0; item[a].identifier; a++) { + int x, y; + + x = (a % 8) * UI_UNIT_X * 6; + y = (a / 8) * UI_UNIT_X * 6; + + icon = item[a].icon; + but = uiDefIconButR_prop(block, ROW, 0, icon, x, y, UI_UNIT_X * 6, UI_UNIT_Y * 6, &cb.ptr, cb.prop, -1, 0, icon, -1, -1, NULL); + uiButSetFlag(but, UI_HAS_ICON | UI_ICON_PREVIEW); + } + + uiBoundsBlock(block, 0.3f * U.widget_unit); + uiBlockSetDirection(block, UI_TOP); + uiEndBlock(C, block); + + if (free) { + MEM_freeN(item); + } + + return block; +} + +void uiTemplateIconView(uiLayout *layout, PointerRNA *ptr, const char *propname) +{ + PropertyRNA *prop = RNA_struct_find_property(ptr, propname); + RNAUpdateCb *cb; + uiBlock *block; + uiBut *but; +// rctf rect; /* UNUSED */ + int icon; + + if (!prop || RNA_property_type(prop) != PROP_ENUM) + return; + + icon = RNA_property_enum_get(ptr, prop); + + cb = MEM_callocN(sizeof(RNAUpdateCb), "RNAUpdateCb"); + cb->ptr = *ptr; + cb->prop = prop; + +// rect.xmin = 0; rect.xmax = 10.0f * UI_UNIT_X; +// rect.ymin = 0; rect.ymax = 10.0f * UI_UNIT_X; + + block = uiLayoutAbsoluteBlock(layout); + + but = uiDefBlockButN(block, icon_view_menu, MEM_dupallocN(cb), "", 0, 0, UI_UNIT_X * 6, UI_UNIT_Y * 6, ""); + + +// but = uiDefIconButR_prop(block, ROW, 0, icon, 0, 0, BLI_rctf_size_x(&rect), BLI_rctf_size_y(&rect), ptr, prop, -1, 0, icon, -1, -1, NULL); + + but->icon = icon; + uiButSetFlag(but, UI_HAS_ICON | UI_ICON_PREVIEW); + + uiButSetNFunc(but, rna_update_cb, MEM_dupallocN(cb), NULL); + + MEM_freeN(cb); +} + /********************* Histogram Template ************************/ void uiTemplateHistogram(uiLayout *layout, PointerRNA *ptr, const char *propname) @@ -2030,16 +2104,22 @@ static void curvemap_buttons_layout(uiLayout *layout, PointerRNA *ptr, char labe } if (cmp) { - const float range_clamp[2] = {0.0f, 1.0f}; - const float range_unclamp[2] = {-1000.0f, 1000.0f}; /* arbitrary limits here */ - const float *range = (cumap->flag & CUMA_DO_CLIP) ? range_clamp : range_unclamp; + rctf bounds; + + if (cumap->flag & CUMA_DO_CLIP) { + bounds = cumap->clipr; + } + else { + bounds.xmin = bounds.ymin = -1000.0; + bounds.xmax = bounds.ymax = 1000.0; + } uiLayoutRow(layout, TRUE); uiBlockSetNFunc(block, curvemap_buttons_update, MEM_dupallocN(cb), cumap); bt = uiDefButF(block, NUM, 0, "X", 0, 2 * UI_UNIT_Y, UI_UNIT_X * 10, UI_UNIT_Y, - &cmp->x, range[0], range[1], 1, 5, ""); + &cmp->x, bounds.xmin, bounds.xmax, 1, 5, ""); bt = uiDefButF(block, NUM, 0, "Y", 0, 1 * UI_UNIT_Y, UI_UNIT_X * 10, UI_UNIT_Y, - &cmp->y, range[0], range[1], 1, 5, ""); + &cmp->y, bounds.ymin, bounds.ymax, 1, 5, ""); } /* black/white levels */ diff --git a/source/blender/editors/interface/interface_widgets.c b/source/blender/editors/interface/interface_widgets.c index 6b44a82a52a..142ea5128c0 100644 --- a/source/blender/editors/interface/interface_widgets.c +++ b/source/blender/editors/interface/interface_widgets.c @@ -346,7 +346,7 @@ static void round_box__edges(uiWidgetBase *wt, int roundboxalign, const rcti *re (roundboxalign & (UI_CNR_TOP_RIGHT | UI_CNR_BOTTOM_RIGHT)) == (UI_CNR_TOP_RIGHT | UI_CNR_BOTTOM_RIGHT)) ? 1 : 2; minsize = min_ii(BLI_rcti_size_x(rect) * hnum, - BLI_rcti_size_y(rect) * vnum); + BLI_rcti_size_y(rect) * vnum); if (2.0f * rad > minsize) rad = 0.5f * minsize; @@ -1325,11 +1325,11 @@ static void widget_draw_text_icon(uiFontStyle *fstyle, uiWidgetColors *wcol, uiB rect->xmin += (int)(0.8f * BLI_rcti_size_y(rect)); if (but->editstr || (but->flag & UI_TEXT_LEFT)) { - rect->xmin += (0.4f * U.widget_unit) / but->block->aspect; + rect->xmin += (UI_TEXT_MARGIN_X * U.widget_unit) / but->block->aspect; } } else if ((but->flag & UI_TEXT_LEFT)) { - rect->xmin += (0.4f * U.widget_unit) / but->block->aspect; + rect->xmin += (UI_TEXT_MARGIN_X * U.widget_unit) / but->block->aspect; } /* unlink icon for this button type */ @@ -1794,11 +1794,19 @@ static void widget_state_menu_item(uiWidgetType *wt, int state) { wt->wcol = *(wt->wcol_theme); - if (state & (UI_BUT_DISABLED | UI_BUT_INACTIVE)) { - wt->wcol.text[0] = 0.5f * (wt->wcol.text[0] + wt->wcol.text_sel[0]); - wt->wcol.text[1] = 0.5f * (wt->wcol.text[1] + wt->wcol.text_sel[1]); - wt->wcol.text[2] = 0.5f * (wt->wcol.text[2] + wt->wcol.text_sel[2]); + /* active and disabled (not so common) */ + if ((state & UI_BUT_DISABLED) && (state & UI_ACTIVE)) { + widget_state_blend(wt->wcol.text, wt->wcol.text_sel, 0.5f); + /* draw the backdrop at low alpha, helps navigating with keys + * when disabled items are active */ + copy_v4_v4_char(wt->wcol.inner, wt->wcol.inner_sel); + wt->wcol.inner[3] = 64; + } + /* regular disabled */ + else if (state & (UI_BUT_DISABLED | UI_BUT_INACTIVE)) { + widget_state_blend(wt->wcol.text, wt->wcol.text_sel, 0.5f); } + /* regular active */ else if (state & UI_ACTIVE) { copy_v4_v4_char(wt->wcol.inner, wt->wcol.inner_sel); copy_v3_v3_char(wt->wcol.text, wt->wcol.text_sel); @@ -3443,7 +3451,7 @@ void ui_draw_menu_item(uiFontStyle *fstyle, rcti *rect, const char *name, int ic uiWidgetType *wt = widget_type(UI_WTYPE_MENU_ITEM); rcti _rect = *rect; char *cpoin; - + wt->state(wt, state); wt->draw(&wt->wcol, rect, 0, 0); diff --git a/source/blender/editors/interface/resources.c b/source/blender/editors/interface/resources.c index 471193d10d8..7efda2f56c3 100644 --- a/source/blender/editors/interface/resources.c +++ b/source/blender/editors/interface/resources.c @@ -395,6 +395,10 @@ const unsigned char *UI_ThemeGetColorPtr(bTheme *btheme, int spacetype, int colo cp = ts->syntaxc; break; case TH_NODE_FRAME: cp = ts->movie; break; + case TH_NODE_MATTE: + cp = ts->syntaxs; break; + case TH_NODE_DISTORT: + cp = ts->syntaxd; break; case TH_NODE_CURVING: cp = &ts->noodle_curving; break; @@ -2116,7 +2120,7 @@ void init_userdef_do_versions(void) btheme->tclip.panelcolors = btheme->tui.panel; } } - + if (bmain->versionfile < 266) { bTheme *btheme; @@ -2145,6 +2149,14 @@ void init_userdef_do_versions(void) } } + if (!MAIN_VERSION_ATLEAST(bmain, 265, 9)) { + bTheme *btheme; + for (btheme = U.themes.first; btheme; btheme = btheme->next) { + rgba_char_args_test_set(btheme->tnode.syntaxs, 151, 116, 116, 255); /* matte nodes */ + rgba_char_args_test_set(btheme->tnode.syntaxd, 116, 151, 151, 255); /* distort nodes */ + } + } + if (U.pixelsize == 0.0f) U.pixelsize = 1.0f; diff --git a/source/blender/editors/interface/view2d_ops.c b/source/blender/editors/interface/view2d_ops.c index 9236800c16b..fbbcb650e68 100644 --- a/source/blender/editors/interface/view2d_ops.c +++ b/source/blender/editors/interface/view2d_ops.c @@ -952,6 +952,13 @@ static int view_zoomdrag_invoke(bContext *C, wmOperator *op, wmEvent *event) fac = 0.01f * (event->prevy - event->y); dy = fac * BLI_rctf_size_y(&v2d->cur) / 10.0f; + /* support trackpad zoom to always zoom entirely - the v2d code uses portrait or landscape exceptions */ + if (v2d->keepzoom & V2D_KEEPASPECT) { + if (fabsf(dx) > fabsf(dy)) + dy = dx; + else + dx = dy; + } RNA_float_set(op->ptr, "deltax", dx); RNA_float_set(op->ptr, "deltay", dy); @@ -1039,6 +1046,14 @@ static int view_zoomdrag_modal(bContext *C, wmOperator *op, wmEvent *event) } + /* support zoom to always zoom entirely - the v2d code uses portrait or landscape exceptions */ + if (v2d->keepzoom & V2D_KEEPASPECT) { + if (fabsf(dx) > fabsf(dy)) + dy = dx; + else + dx = dy; + } + /* set transform amount, and add current deltas to stored total delta (for redo) */ RNA_float_set(op->ptr, "deltax", dx); RNA_float_set(op->ptr, "deltay", dy); diff --git a/source/blender/editors/io/io_collada.c b/source/blender/editors/io/io_collada.c index ba93206e63a..f53672b7092 100644 --- a/source/blender/editors/io/io_collada.c +++ b/source/blender/editors/io/io_collada.c @@ -84,6 +84,7 @@ static int wm_collada_export_exec(bContext *C, wmOperator *op) int selected; int include_children; int include_armatures; + int include_shapekeys; int deform_bones_only; int include_uv_textures; @@ -109,6 +110,7 @@ static int wm_collada_export_exec(bContext *C, wmOperator *op) selected = RNA_boolean_get(op->ptr, "selected"); include_children = RNA_boolean_get(op->ptr, "include_children"); include_armatures = RNA_boolean_get(op->ptr, "include_armatures"); + include_shapekeys = RNA_boolean_get(op->ptr, "include_shapekeys"); deform_bones_only = RNA_boolean_get(op->ptr, "deform_bones_only"); include_uv_textures = RNA_boolean_get(op->ptr, "include_uv_textures"); @@ -130,6 +132,7 @@ static int wm_collada_export_exec(bContext *C, wmOperator *op) selected, include_children, include_armatures, + include_shapekeys, deform_bones_only, active_uv_only, @@ -176,6 +179,10 @@ static void uiCollada_exportSettings(uiLayout *layout, PointerRNA *imfptr) uiItemR(row, imfptr, "include_armatures", 0, NULL, ICON_NONE); uiLayoutSetEnabled(row, RNA_boolean_get(imfptr, "selected")); + row = uiLayoutRow(box, FALSE); + uiItemR(row, imfptr, "include_shapekeys", 0, NULL, ICON_NONE); + uiLayoutSetEnabled(row, RNA_boolean_get(imfptr, "selected")); + /* Texture options */ box = uiLayoutBox(layout); row = uiLayoutRow(box, FALSE); @@ -266,6 +273,9 @@ void WM_OT_collada_export(wmOperatorType *ot) RNA_def_boolean(ot->srna, "include_armatures", 0, "Include Armatures", "Export related armatures (even if not selected)"); + RNA_def_boolean(ot->srna, "include_shapekeys", 1, "Include Shape Keys", + "Export all Shape Keys from Mesh Objects"); + RNA_def_boolean(ot->srna, "deform_bones_only", 0, "Deform Bones only", "Only export deforming bones with armatures"); diff --git a/source/blender/editors/mask/mask_draw.c b/source/blender/editors/mask/mask_draw.c index 74cdf4c2a11..af9d3341e61 100644 --- a/source/blender/editors/mask/mask_draw.c +++ b/source/blender/editors/mask/mask_draw.c @@ -409,7 +409,7 @@ static void draw_spline_curve(const bContext *C, MaskLayer *masklay, MaskSpline int width, int height) { const unsigned int resol = max_ii(BKE_mask_spline_feather_resolution(spline, width, height), - BKE_mask_spline_resolution(spline, width, height)); + BKE_mask_spline_resolution(spline, width, height)); unsigned char rgb_tmp[4]; diff --git a/source/blender/editors/mesh/CMakeLists.txt b/source/blender/editors/mesh/CMakeLists.txt index 3180886b2b6..b51d55aaf0e 100644 --- a/source/blender/editors/mesh/CMakeLists.txt +++ b/source/blender/editors/mesh/CMakeLists.txt @@ -48,7 +48,6 @@ set(SRC editmesh_select.c editmesh_tools.c editmesh_utils.c - editmesh_slide.c mesh_data.c mesh_ops.c meshtools.c diff --git a/source/blender/editors/mesh/editmesh_knife.c b/source/blender/editors/mesh/editmesh_knife.c index 5e1d954a2ea..e49dc3c28f9 100644 --- a/source/blender/editors/mesh/editmesh_knife.c +++ b/source/blender/editors/mesh/editmesh_knife.c @@ -128,7 +128,7 @@ typedef struct KnifePosData { BMFace *bmface; int is_space; - int mval[2]; /* mouse screen position */ + float mval[2]; /* mouse screen position (may be non-integral if snapped to something) */ } KnifePosData; /* struct for properties used while drawing */ @@ -204,10 +204,10 @@ typedef struct KnifeTool_OpData { static ListBase *knife_get_face_kedges(KnifeTool_OpData *kcd, BMFace *f); #if 0 -static void knife_input_ray_cast(KnifeTool_OpData *kcd, const int mval_i[2], +static void knife_input_ray_cast(KnifeTool_OpData *kcd, const float mval[2], float r_origin[3], float r_ray[3]); #endif -static void knife_input_ray_segment(KnifeTool_OpData *kcd, const int mval_i[2], const float ofs, +static void knife_input_ray_segment(KnifeTool_OpData *kcd, const float mval[2], const float ofs, float r_origin[3], float r_dest[3]); static void knife_update_header(bContext *C, KnifeTool_OpData *kcd) @@ -225,6 +225,10 @@ static void knife_update_header(bContext *C, KnifeTool_OpData *kcd) ED_area_headerprint(CTX_wm_area(C), header); } +BLI_INLINE int round_ftoi(float x) +{ + return x > 0.0f ? (int)(x + 0.5f) : (int)(x - 0.5f); +} static void knife_project_v3(KnifeTool_OpData *kcd, const float co[3], float sco[3]) { @@ -238,8 +242,8 @@ static void knife_pos_data_clear(KnifePosData *kpd) kpd->vert = NULL; kpd->edge = NULL; kpd->bmface = NULL; - kpd->mval[0] = 0; - kpd->mval[1] = 0; + kpd->mval[0] = 0.0f; + kpd->mval[1] = 0.0f; } static ListBase *knife_empty_list(KnifeTool_OpData *kcd) @@ -1420,17 +1424,14 @@ static void knife_find_line_hits(KnifeTool_OpData *kcd) /* this works but gives numeric problems [#33400] */ #if 0 -static void knife_input_ray_cast(KnifeTool_OpData *kcd, const int mval_i[2], +static void knife_input_ray_cast(KnifeTool_OpData *kcd, const float mval[2], float r_origin[3], float r_ray[3]) { bglMats mats; - float mval[2], imat[3][3]; + float imat[3][3]; knife_bgl_get_mats(kcd, &mats); - mval[0] = (float)mval_i[0]; - mval[1] = (float)mval_i[1]; - /* unproject to find view ray */ ED_view3d_unproject(&mats, r_origin, mval[0], mval[1], 0.0f); @@ -1452,23 +1453,19 @@ static void knife_input_ray_cast(KnifeTool_OpData *kcd, const int mval_i[2], } #endif -static void knife_input_ray_segment(KnifeTool_OpData *kcd, const int mval_i[2], const float ofs, +static void knife_input_ray_segment(KnifeTool_OpData *kcd, const float mval[2], const float ofs, float r_origin[3], float r_origin_ofs[3]) { bglMats mats; - float mval[2]; knife_bgl_get_mats(kcd, &mats); - mval[0] = (float)mval_i[0]; - mval[1] = (float)mval_i[1]; - /* unproject to find view ray */ ED_view3d_unproject(&mats, r_origin, mval[0], mval[1], 0.0f); ED_view3d_unproject(&mats, r_origin_ofs, mval[0], mval[1], ofs); /* transform into object space */ - invert_m4_m4(kcd->ob->imat, kcd->ob->obmat); + invert_m4_m4(kcd->ob->imat, kcd->ob->obmat); mul_m4_v3(kcd->ob->imat, r_origin); mul_m4_v3(kcd->ob->imat, r_origin_ofs); @@ -1483,7 +1480,7 @@ static BMFace *knife_find_closest_face(KnifeTool_OpData *kcd, float co[3], float float ray[3]; /* unproject to find view ray */ - knife_input_ray_segment(kcd, kcd->vc.mval, 1.0f, origin, origin_ofs); + knife_input_ray_segment(kcd, kcd->curr.mval, 1.0f, origin, origin_ofs); sub_v3_v3v3(ray, origin_ofs, origin); f = BMBVH_RayCast(kcd->bmbvh, origin, ray, co, cageco); @@ -1641,8 +1638,8 @@ static KnifeEdge *knife_find_closest_edge(KnifeTool_OpData *kcd, float p[3], flo /* update mouse coordinates to the snapped-to edge's screen coordinates * this is important for angle snap, which uses the previous mouse position */ edgesnap = new_knife_vert(kcd, p, cagep); - kcd->curr.mval[0] = (int)edgesnap->sco[0]; - kcd->curr.mval[1] = (int)edgesnap->sco[1]; + kcd->curr.mval[0] = edgesnap->sco[0]; + kcd->curr.mval[1] = edgesnap->sco[1]; } else { @@ -1720,8 +1717,8 @@ static KnifeVert *knife_find_closest_vert(KnifeTool_OpData *kcd, float p[3], flo /* update mouse coordinates to the snapped-to vertex's screen coordinates * this is important for angle snap, which uses the previous mouse position */ - kcd->curr.mval[0] = (int)curv->sco[0]; - kcd->curr.mval[1] = (int)curv->sco[1]; + kcd->curr.mval[0] = curv->sco[0]; + kcd->curr.mval[1] = curv->sco[1]; } return curv; @@ -1740,48 +1737,56 @@ static KnifeVert *knife_find_closest_vert(KnifeTool_OpData *kcd, float p[3], flo return NULL; } +/* update both kcd->curr.mval and kcd->vc.mval to snap to required angle */ static void knife_snap_angle(KnifeTool_OpData *kcd) { - int dx, dy; + float dx, dy; float w, abs_tan; - dx = kcd->vc.mval[0] - kcd->prev.mval[0]; - dy = kcd->vc.mval[1] - kcd->prev.mval[1]; - if (dx == 0 || dy == 0) + dx = kcd->curr.mval[0] - kcd->prev.mval[0]; + dy = kcd->curr.mval[1] - kcd->prev.mval[1]; + if (dx == 0.0f && dy == 0.0f) return; - w = (float)dy / (float)dx; + if (dx == 0.0f) { + kcd->angle_snapping = ANGLE_90; + kcd->curr.mval[0] = kcd->prev.mval[0]; + } + + w = dy / dx; abs_tan = fabsf(w); if (abs_tan <= 0.4142f) { /* tan(22.5 degrees) = 0.4142 */ kcd->angle_snapping = ANGLE_0; - kcd->vc.mval[1] = kcd->prev.mval[1]; + kcd->curr.mval[1] = kcd->prev.mval[1]; } else if (abs_tan < 2.4142f) { /* tan(67.5 degrees) = 2.4142 */ if (w > 0) { kcd->angle_snapping = ANGLE_45; - kcd->vc.mval[1] = kcd->prev.mval[1] + dx; + kcd->curr.mval[1] = kcd->prev.mval[1] + dx; } else { kcd->angle_snapping = ANGLE_135; - kcd->vc.mval[1] = kcd->prev.mval[1] - dx; + kcd->curr.mval[1] = kcd->prev.mval[1] - dx; } } else { kcd->angle_snapping = ANGLE_90; - kcd->vc.mval[0] = kcd->prev.mval[0]; + kcd->curr.mval[0] = kcd->prev.mval[0]; } + + kcd->vc.mval[0] = round_ftoi(kcd->curr.mval[0]); + kcd->vc.mval[1] = round_ftoi(kcd->curr.mval[1]); } /* update active knife edge/vert pointers */ static int knife_update_active(KnifeTool_OpData *kcd) { + knife_pos_data_clear(&kcd->curr); + kcd->curr.mval[0] = (float)kcd->vc.mval[0]; + kcd->curr.mval[1] = (float)kcd->vc.mval[1]; if (kcd->angle_snapping != ANGLE_FREE && kcd->mode == MODE_DRAGGING) knife_snap_angle(kcd); - knife_pos_data_clear(&kcd->curr); - kcd->curr.mval[0] = kcd->vc.mval[0]; - kcd->curr.mval[1] = kcd->vc.mval[1]; - /* XXX knife_snap_angle updates the view coordinate mouse values to constrained angles, * which current mouse values are set to current mouse values are then used * for vertex and edge snap detection, without regard to the exact angle constraint */ @@ -1799,7 +1804,7 @@ static int knife_update_active(KnifeTool_OpData *kcd) float origin[3]; float origin_ofs[3]; - knife_input_ray_segment(kcd, kcd->vc.mval, 1.0f, origin, origin_ofs); + knife_input_ray_segment(kcd, kcd->curr.mval, 1.0f, origin, origin_ofs); closest_to_line_v3(kcd->curr.cage, kcd->prev.cage, origin_ofs, origin); } @@ -2929,11 +2934,11 @@ static void cage_mapped_verts_callback(void *userData, int index, const float co } } -static void knifetool_update_mval(KnifeTool_OpData *kcd, int mval[2]) +static void knifetool_update_mval(KnifeTool_OpData *kcd, int mval_i[2]) { knife_recalc_projmat(kcd); - kcd->vc.mval[0] = mval[0]; - kcd->vc.mval[1] = mval[1]; + kcd->vc.mval[0] = mval_i[0]; + kcd->vc.mval[1] = mval_i[1]; if (knife_update_active(kcd)) { ED_region_tag_redraw(kcd->ar); diff --git a/source/blender/editors/mesh/editmesh_loopcut.c b/source/blender/editors/mesh/editmesh_loopcut.c index 5f923dd65c6..d1373363992 100644 --- a/source/blender/editors/mesh/editmesh_loopcut.c +++ b/source/blender/editors/mesh/editmesh_loopcut.c @@ -154,9 +154,9 @@ static void edgering_find_order(BMEdge *lasteed, BMEdge *eed, static void edgering_sel(RingSelOpData *lcd, int previewlines, int select) { BMEditMesh *em = lcd->em; - BMEdge *startedge = lcd->eed; - BMEdge *eed, *lasteed; - BMVert *v[2][2], *lastv1; + BMEdge *eed_start = lcd->eed; + BMEdge *eed, *eed_last; + BMVert *v[2][2], *v_last; BMWalker walker; float (*edges)[2][3] = NULL; BLI_array_declare(edges); @@ -164,7 +164,7 @@ static void edgering_sel(RingSelOpData *lcd, int previewlines, int select) memset(v, 0, sizeof(v)); - if (!startedge) + if (!eed_start) return; if (lcd->edges) { @@ -183,8 +183,7 @@ static void edgering_sel(RingSelOpData *lcd, int previewlines, int select) BMW_FLAG_TEST_HIDDEN, BMW_NIL_LAY); - eed = BMW_begin(&walker, startedge); - for ( ; eed; eed = BMW_step(&walker)) { + for (eed = BMW_begin(&walker, eed_start); eed; eed = BMW_step(&walker)) { BM_edge_select_set(em->bm, eed, TRUE); } BMW_end(&walker); @@ -197,22 +196,23 @@ static void edgering_sel(RingSelOpData *lcd, int previewlines, int select) BMW_FLAG_TEST_HIDDEN, BMW_NIL_LAY); - eed = startedge = BMW_begin(&walker, startedge); - lastv1 = NULL; - for (lasteed = NULL; eed; eed = BMW_step(&walker)) { - if (lasteed) { - if (lastv1) { + v_last = NULL; + eed_last = NULL; + + for (eed = eed_start = BMW_begin(&walker, eed_start); eed; eed = BMW_step(&walker)) { + if (eed_last) { + if (v_last) { v[1][0] = v[0][0]; v[1][1] = v[0][1]; } else { - v[1][0] = lasteed->v1; - v[1][1] = lasteed->v2; - lastv1 = lasteed->v1; + v[1][0] = eed_last->v1; + v[1][1] = eed_last->v2; + v_last = eed_last->v1; } - edgering_find_order(lasteed, eed, lastv1, v); - lastv1 = v[0][0]; + edgering_find_order(eed_last, eed, v_last, v); + v_last = v[0][0]; BLI_array_grow_items(edges, previewlines); @@ -223,18 +223,18 @@ static void edgering_sel(RingSelOpData *lcd, int previewlines, int select) tot++; } } - lasteed = eed; + eed_last = eed; } #ifdef BMW_EDGERING_NGON if (lasteed != startedge && BM_edge_share_face_check(lasteed, startedge)) { #else - if (lasteed != startedge && BM_edge_share_quad_check(lasteed, startedge)) { + if (eed_last != eed_start && BM_edge_share_quad_check(eed_last, eed_start)) { #endif v[1][0] = v[0][0]; v[1][1] = v[0][1]; - edgering_find_order(lasteed, startedge, lastv1, v); + edgering_find_order(eed_last, eed_start, v_last, v); BLI_array_grow_items(edges, previewlines); @@ -502,7 +502,8 @@ static int loopcut_modal(bContext *C, wmOperator *op, wmEvent *event) ED_region_tag_redraw(lcd->ar); break; - case MOUSEMOVE: { /* mouse moved somewhere to select another loop */ + case MOUSEMOVE: /* mouse moved somewhere to select another loop */ + { float dist = 75.0f; BMEdge *edge; diff --git a/source/blender/editors/mesh/editmesh_select.c b/source/blender/editors/mesh/editmesh_select.c index 38887307a76..88d826c2f98 100644 --- a/source/blender/editors/mesh/editmesh_select.c +++ b/source/blender/editors/mesh/editmesh_select.c @@ -995,8 +995,8 @@ static void walker_select(BMEditMesh *em, int walkercode, void *start, int selec BMW_MASK_NOP, BMW_MASK_NOP, BMW_MASK_NOP, BMW_FLAG_TEST_HIDDEN, BMW_NIL_LAY); - ele = BMW_begin(&walker, start); - for (; ele; ele = BMW_step(&walker)) { + + for (ele = BMW_begin(&walker, start); ele; ele = BMW_step(&walker)) { if (!select) { BM_select_history_remove(bm, ele); } @@ -1782,7 +1782,7 @@ void MESH_OT_select_shortest_path(wmOperatorType *ot) ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; /* properties */ - RNA_def_boolean(ot->srna, "extend", 0, "Extend Select", ""); + RNA_def_boolean(ot->srna, "extend", false, "Extend", "Extend the selection"); } /* ************************************************** */ @@ -2286,8 +2286,7 @@ static int edbm_select_linked_pick_invoke(bContext *C, wmOperator *op, wmEvent * BMW_FLAG_TEST_HIDDEN, BMW_NIL_LAY); - efa = BMW_begin(&walker, efa); - for (; efa; efa = BMW_step(&walker)) { + for (efa = BMW_begin(&walker, efa); efa; efa = BMW_step(&walker)) { BM_face_select_set(bm, efa, sel); } BMW_end(&walker); @@ -2308,8 +2307,7 @@ static int edbm_select_linked_pick_invoke(bContext *C, wmOperator *op, wmEvent * BMW_FLAG_TEST_HIDDEN, BMW_NIL_LAY); - e = BMW_begin(&walker, eed->v1); - for (; e; e = BMW_step(&walker)) { + for (e = BMW_begin(&walker, eed->v1); e; e = BMW_step(&walker)) { BM_edge_select_set(bm, e, sel); } BMW_end(&walker); @@ -2380,8 +2378,7 @@ static int edbm_select_linked_exec(bContext *C, wmOperator *op) BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { if (BM_elem_flag_test(efa, BM_ELEM_TAG)) { - efa = BMW_begin(&walker, efa); - for (; efa; efa = BMW_step(&walker)) { + for (efa = BMW_begin(&walker, efa); efa; efa = BMW_step(&walker)) { BM_face_select_set(bm, efa, TRUE); } } @@ -2409,10 +2406,8 @@ static int edbm_select_linked_exec(bContext *C, wmOperator *op) BM_ITER_MESH (v, &iter, em->bm, BM_VERTS_OF_MESH) { if (BM_elem_flag_test(v, BM_ELEM_TAG)) { - e = BMW_begin(&walker, v); - for (; e; e = BMW_step(&walker)) { - BM_vert_select_set(em->bm, e->v1, TRUE); - BM_vert_select_set(em->bm, e->v2, TRUE); + for (e = BMW_begin(&walker, v); e; e = BMW_step(&walker)) { + BM_edge_select_set(em->bm, e, true); } } } @@ -2859,6 +2854,9 @@ static int edbm_select_non_manifold_exec(bContext *C, wmOperator *op) BMEdge *e; BMIter iter; + if (!RNA_boolean_get(op->ptr, "extend")) + EDBM_flag_disable_all(em, BM_ELEM_SELECT); + /* Selects isolated verts, and edges that do not have 2 neighboring * faces */ @@ -2898,6 +2896,9 @@ void MESH_OT_select_non_manifold(wmOperatorType *ot) /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + + /* props */ + RNA_def_boolean(ot->srna, "extend", true, "Extend", "Extend the selection"); } static int edbm_select_random_exec(bContext *C, wmOperator *op) @@ -2962,8 +2963,7 @@ void MESH_OT_select_random(wmOperatorType *ot) /* props */ RNA_def_float_percentage(ot->srna, "percent", 50.f, 0.0f, 100.0f, "Percent", "Percentage of elements to select randomly", 0.f, 100.0f); - RNA_def_boolean(ot->srna, "extend", 0, - "Extend Selection", "Extend selection instead of deselecting everything first"); + RNA_def_boolean(ot->srna, "extend", false, "Extend", "Extend the selection"); } static int edbm_select_next_loop_exec(bContext *C, wmOperator *UNUSED(op)) diff --git a/source/blender/editors/mesh/editmesh_slide.c b/source/blender/editors/mesh/editmesh_slide.c deleted file mode 100644 index eb0a21261ce..00000000000 --- a/source/blender/editors/mesh/editmesh_slide.c +++ /dev/null @@ -1,793 +0,0 @@ -/* - * ***** 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): Francisco De La Cruz - * - * ***** END GPL LICENSE BLOCK ***** - */ - -/** \file blender/editors/mesh/editmesh_slide.c - * \ingroup edmesh - */ - -/* Takes heavily from editmesh_loopcut.c */ - -#include "DNA_object_types.h" -#include "DNA_mesh_types.h" - -#include "MEM_guardedalloc.h" - -#include "BLI_array.h" -#include "BLI_math.h" - -#include "BLF_translation.h" - -#include "BKE_context.h" -#include "BKE_report.h" -#include "BKE_tessmesh.h" - -#include "BIF_gl.h" -#include "BIF_glutil.h" - -#include "ED_screen.h" -#include "ED_view3d.h" -#include "ED_mesh.h" -#include "ED_space_api.h" - -#include "UI_resources.h" - -#include "RNA_access.h" -#include "RNA_define.h" - -#include "WM_api.h" -#include "WM_types.h" - -#include "mesh_intern.h" - -#define VTX_SLIDE_SNAP_THRSH 15 - -/* Cusom VertexSlide Operator data */ -typedef struct VertexSlideOp { - /* Starting Vertex */ - BMVert *start_vtx; - BMEdge *sel_edge; - - ViewContext *view_context; - ARegion *active_region; - - /* Draw callback handle */ - void *draw_handle; - - /* Active Object */ - Object *obj; - - /* Are we in slide mode */ - int slide_mode; - int snap_n_merge; - int snap_to_end_vtx; - int snap_to_mid; - - /* Snap threshold */ - float snap_threshold; - - float distance; - float interp[3]; - - /* Edge Frame Count */ - int disk_edges; - - /* Edges */ - BMEdge **edge_frame; - - /* Slide Frame Endpoints */ - float (*vtx_frame)[3]; - - /* Mouse Click 2d pos */ - int m_co[2]; - -} VertexSlideOp; - -static void vtx_slide_draw(const bContext *C, ARegion *ar, void *arg); -static int edbm_vertex_slide_exec_ex(bContext *C, wmOperator *op, const int do_update); -static void vtx_slide_exit(const bContext *C, wmOperator *op); -static int vtx_slide_set_frame(VertexSlideOp *vso); - -static int vtx_slide_init(bContext *C, wmOperator *op) -{ - Object *obedit = CTX_data_edit_object(C); - BMEditMesh *em = BMEdit_FromObject(obedit); - BMEditSelection *ese; - - /* Custom data */ - VertexSlideOp *vso; - - const char *header_str = TIP_("Vertex Slide: Hover over an edge and left-click to select slide edge. " - "Left-Shift: Midpoint Snap, Left-Alt: Snap, Left-Ctrl: Snap & Merge"); - - if (!obedit) { - BKE_report(op->reports, RPT_ERROR, "Vertex slide error: no object in context"); - return FALSE; - } - - EDBM_selectmode_flush(em); - ese = em->bm->selected.last; - - /* Is there a starting vertex ? */ - if (ese == NULL || (ese->htype != BM_VERT && ese->htype != BM_EDGE)) { - BKE_report(op->reports, RPT_ERROR_INVALID_INPUT, "Vertex slide error: select a (single) vertex"); - return FALSE; - } - - vso = MEM_callocN(sizeof(VertexSlideOp), "Vertex Slide Operator"); - vso->view_context = MEM_callocN(sizeof(ViewContext), "Vertex Slide View Context"); - - op->customdata = vso; - - /* Set the start vertex */ - vso->start_vtx = (BMVert *)ese->ele; - - vso->sel_edge = NULL; - - /* Edges */ - vso->edge_frame = NULL; - - vso->vtx_frame = NULL; - - vso->disk_edges = 0; - - vso->slide_mode = FALSE; - - vso->snap_n_merge = FALSE; - - vso->snap_to_end_vtx = FALSE; - - vso->snap_to_mid = FALSE; - - vso->distance = 0.0f; - - vso->snap_threshold = 0.2f; - - /* Notify the viewport */ - view3d_operator_needs_opengl(C); - - /* Set the drawing region */ - vso->active_region = CTX_wm_region(C); - - /* Set the draw callback */ - vso->draw_handle = ED_region_draw_cb_activate(vso->active_region->type, vtx_slide_draw, vso, REGION_DRAW_POST_VIEW); - - ED_area_headerprint(CTX_wm_area(C), header_str); - - em_setup_viewcontext(C, vso->view_context); - - /* Set the object */ - vso->obj = obedit; - - /* Init frame */ - if (!vtx_slide_set_frame(vso)) { - BKE_report(op->reports, RPT_ERROR_INVALID_INPUT, "Vertex slide error: cannot find starting vertex!"); - vtx_slide_exit(C, op); - return FALSE; - } - - /* Add handler for the vertex sliding */ - WM_event_add_modal_handler(C, op); - - /* Tag for redraw */ - ED_region_tag_redraw(vso->active_region); - - return TRUE; -} - -static void vtx_slide_confirm(bContext *C, wmOperator *op) -{ - VertexSlideOp *vso = op->customdata; - BMEditMesh *em = BMEdit_FromObject(vso->obj); - BMesh *bm = em->bm; - BMVert *other = NULL; - - BMVert *mirr_vtx = NULL; - BMVert *mirr_vtx_other = NULL; - - /* Select new edge */ - BM_edge_select_set(bm, vso->sel_edge, TRUE); - - if (vso->snap_n_merge) { - other = BM_edge_other_vert(vso->sel_edge, vso->start_vtx); - } - - if (((Mesh *)em->ob->data)->editflag & ME_EDIT_MIRROR_X) { - EDBM_verts_mirror_cache_begin(em, TRUE); - - mirr_vtx = EDBM_verts_mirror_get(em, vso->start_vtx); - if (vso->snap_n_merge) { - mirr_vtx_other = EDBM_verts_mirror_get(em, other); - } - } - - /* Invoke operator - warning */ - edbm_vertex_slide_exec_ex(C, op, FALSE); - - if (mirr_vtx) { - mirr_vtx->co[0] = -vso->start_vtx->co[0]; - mirr_vtx->co[1] = vso->start_vtx->co[1]; - mirr_vtx->co[2] = vso->start_vtx->co[2]; - } - - if (vso->snap_n_merge) { - float other_d; - other_d = len_v3v3(vso->interp, other->co); - - /* Only snap if within threshold */ - if (other_d < vso->snap_threshold) { - BM_vert_select_set(bm, other, TRUE); - BM_vert_select_set(bm, vso->start_vtx, TRUE); - EDBM_op_callf(em, op, "pointmerge verts=%hv merge_co=%v", BM_ELEM_SELECT, other->co); - EDBM_flag_disable_all(em, BM_ELEM_SELECT); - - if (mirr_vtx_other) { - BM_vert_select_set(bm, mirr_vtx, TRUE); - BM_vert_select_set(bm, mirr_vtx_other, TRUE); - EDBM_op_callf(em, op, "pointmerge verts=%hv merge_co=%v", BM_ELEM_SELECT, mirr_vtx_other->co); - EDBM_flag_disable_all(em, BM_ELEM_SELECT); - } - } - else { - /* Store in historty if not merging */ - BM_select_history_store(em->bm, vso->start_vtx); - } - } - else { - /* Store edit selection of the active vertex, allows other - * ops to run without reselecting */ - BM_select_history_store(em->bm, vso->start_vtx); - } - - if (((Mesh *)em->ob->data)->editflag & ME_EDIT_MIRROR_X) { - EDBM_verts_mirror_cache_end(em); - } - - EDBM_selectmode_flush(em); - - /* NC_GEOM | ND_DATA & Retess */ - EDBM_update_generic(em, TRUE, FALSE); - - ED_region_tag_redraw(vso->active_region); -} - -static void vtx_slide_exit(const bContext *C, wmOperator *op) -{ - /* Fetch custom data */ - VertexSlideOp *vso = op->customdata; - - /* Clean-up the custom data */ - ED_region_draw_cb_exit(vso->active_region->type, vso->draw_handle); - - /* Free Custom Data - * - */ - MEM_freeN(vso->view_context); - - vso->view_context = NULL; - - if (vso->edge_frame) { - MEM_freeN(vso->edge_frame); - } - - if (vso->vtx_frame) { - MEM_freeN(vso->vtx_frame); - } - - vso->edge_frame = NULL; - - vso->vtx_frame = NULL; - - vso->slide_mode = FALSE; - - MEM_freeN(vso); - vso = NULL; - op->customdata = NULL; - - /* Clear the header */ - ED_area_headerprint(CTX_wm_area(C), NULL); -} - -static void vtx_slide_draw(const bContext *C, ARegion *UNUSED(ar), void *arg) -{ - VertexSlideOp *vso = arg; - - /* Have an edge to draw */ - if (vso && vso->sel_edge) { - /* Get 3d view */ - View3D *view3d = CTX_wm_view3d(C); - const float outline_w = UI_GetThemeValuef(TH_OUTLINE_WIDTH) + 0.8f; - const float pt_size = UI_GetThemeValuef(TH_FACEDOT_SIZE) + 1.5f; - - int i = 0; - - if (view3d && view3d->zbuf) - glDisable(GL_DEPTH_TEST); - - glPushAttrib(GL_CURRENT_BIT | GL_LINE_BIT | GL_POINT_BIT); - - glPushMatrix(); - glMultMatrixf(vso->obj->obmat); - - glEnable(GL_BLEND); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - - - if (vso->slide_mode && vso->disk_edges > 0) { - /* Draw intermediate edge frame */ - UI_ThemeColorShadeAlpha(TH_EDGE_SELECT, 50, -50); - - for (i = 0; i < vso->disk_edges; i++) { - glBegin(GL_LINES); - glVertex3fv(vso->vtx_frame[i]); - glVertex3fv(vso->interp); - glEnd(); - } - } - - /* Draw selected edge - * Add color offset and reduce alpha */ - UI_ThemeColorShadeAlpha(TH_EDGE_SELECT, 40, -50); - - glLineWidth(outline_w); - - glBegin(GL_LINES); - bglVertex3fv(vso->sel_edge->v1->co); - bglVertex3fv(vso->sel_edge->v2->co); - glEnd(); - - if (vso->slide_mode) { - /* Draw interpolated vertex */ - - UI_ThemeColorShadeAlpha(TH_FACE_DOT, -80, -50); - - glPointSize(pt_size); - - bglBegin(GL_POINTS); - bglVertex3fv(vso->interp); - bglEnd(); - } - - glDisable(GL_BLEND); - glPopMatrix(); - glPopAttrib(); - - if (view3d && view3d->zbuf) - glEnable(GL_DEPTH_TEST); - } -} - -static BMEdge *vtx_slide_nrst_in_frame(VertexSlideOp *vso, const float mval[2]) -{ - BMEdge *cl_edge = NULL; - if (vso->disk_edges > 0) { - int i = 0; - BMEdge *edge = NULL; - - float v1_proj[3], v2_proj[3]; - float min_dist = FLT_MAX; - - for (i = 0; i < vso->disk_edges; i++) { - edge = vso->edge_frame[i]; - - mul_v3_m4v3(v1_proj, vso->obj->obmat, edge->v1->co); - mul_v3_m4v3(v2_proj, vso->obj->obmat, edge->v2->co); - - /* we could use ED_view3d_project_float_object here, but for now dont since we dont have the context */ - if ((ED_view3d_project_float_global(vso->active_region, v1_proj, v1_proj, V3D_PROJ_TEST_NOP) == V3D_PROJ_RET_OK) && - (ED_view3d_project_float_global(vso->active_region, v2_proj, v2_proj, V3D_PROJ_TEST_NOP) == V3D_PROJ_RET_OK)) - { - const float dist = dist_to_line_segment_v2(mval, v1_proj, v2_proj); - if (dist < min_dist) { - min_dist = dist; - cl_edge = edge; - } - } - } - } - return cl_edge; -} - -static void vtx_slide_find_edge(VertexSlideOp *vso, wmEvent *event) -{ - /* Nearest edge */ - BMEdge *nst_edge = NULL; - - const float mval_float[2] = {(float)event->mval[0], - (float)event->mval[1]}; - - /* Set mouse coords */ - copy_v2_v2_int(vso->view_context->mval, event->mval); - - /* Find nearest edge */ - nst_edge = vtx_slide_nrst_in_frame(vso, mval_float); - - if (nst_edge) { - /* Find a connected edge */ - if (BM_vert_in_edge(nst_edge, vso->start_vtx)) { - - /* Save mouse coords */ - copy_v2_v2_int(vso->m_co, event->mval); - - /* Set edge */ - vso->sel_edge = nst_edge; - } - } -} - -/* Updates the status of the operator - Invoked on mouse movement */ -static void vtx_slide_update(VertexSlideOp *vso, wmEvent *event) -{ - BMEdge *edge; - - /* Find nearest edge */ - edge = vso->sel_edge; - - if (edge) { - float edge_other_proj[3]; - float start_vtx_proj[3]; - float edge_len; - BMVert *other; - - float interp[3]; - - /* Calculate interpolation value for preview */ - float t_val; - - float mval_float[2] = { (float)event->mval[0], (float)event->mval[1]}; - float closest_2d[2]; - - other = BM_edge_other_vert(edge, vso->start_vtx); - - /* Project points onto screen and do interpolation in 2D */ - mul_v3_m4v3(start_vtx_proj, vso->obj->obmat, vso->start_vtx->co); - mul_v3_m4v3(edge_other_proj, vso->obj->obmat, other->co); - - if ((ED_view3d_project_float_global(vso->active_region, edge_other_proj, edge_other_proj, V3D_PROJ_TEST_NOP) != V3D_PROJ_RET_OK) || - (ED_view3d_project_float_global(vso->active_region, start_vtx_proj, start_vtx_proj, V3D_PROJ_TEST_NOP) != V3D_PROJ_RET_OK)) - { - /* not much we can do here */ - return; - } - - closest_to_line_v2(closest_2d, mval_float, start_vtx_proj, edge_other_proj); - - t_val = line_point_factor_v2(closest_2d, start_vtx_proj, edge_other_proj); - - /* Set snap threshold to be proportional to edge length */ - edge_len = len_v3v3(start_vtx_proj, edge_other_proj); - - if (edge_len <= 0.0f) - edge_len = VTX_SLIDE_SNAP_THRSH; - - edge_len = (BM_edge_calc_length(edge) * VTX_SLIDE_SNAP_THRSH) / edge_len; - - vso->snap_threshold = edge_len; - - /* Snap to mid */ - if (vso->snap_to_mid) { - t_val = 0.5f; - } - - /* Interpolate preview vertex 3D */ - interp_v3_v3v3(interp, vso->start_vtx->co, other->co, t_val); - copy_v3_v3(vso->interp, interp); - - vso->distance = t_val; - - /* If snapping */ - if (vso->snap_to_end_vtx) { - int start_at_v1 = edge->v1 == vso->start_vtx; - float v1_d = len_v3v3(vso->interp, edge->v1->co); - float v2_d = len_v3v3(vso->interp, edge->v2->co); - - if (v1_d > v2_d && v2_d < vso->snap_threshold) { - copy_v3_v3(vso->interp, edge->v2->co); - - if (start_at_v1) - vso->distance = 1.0f; - else - vso->distance = 0.0f; - } - if (v2_d > v1_d && v1_d < vso->snap_threshold) { - copy_v3_v3(vso->interp, edge->v1->co); - if (start_at_v1) - vso->distance = 0.0f; - else - vso->distance = 1.0f; - } - } - } -} - -/* Sets the outline frame */ -static int vtx_slide_set_frame(VertexSlideOp *vso) -{ - BMEdge *edge; - float (*vtx_frame)[3] = NULL; - BMEdge **edge_frame = NULL; - BMVert *curr_vert = NULL; - BLI_array_declare(vtx_frame); - BLI_array_declare(edge_frame); - BMIter iter; - BMVert *sel_vtx = vso->start_vtx; - int idx = 0; - - vso->disk_edges = 0; - - if (vso->edge_frame) { - MEM_freeN(vso->edge_frame); - vso->edge_frame = NULL; - } - - if (vso->vtx_frame) { - MEM_freeN(vso->vtx_frame); - vso->vtx_frame = NULL; - } - - /* Iterate over edges of vertex and copy them */ - BM_ITER_ELEM_INDEX (edge, &iter, sel_vtx, BM_EDGES_OF_VERT, idx) { - curr_vert = BM_edge_other_vert(edge, sel_vtx); - if (curr_vert) { - BLI_array_grow_one(vtx_frame); - - copy_v3_v3(vtx_frame[idx], curr_vert->co); - - BLI_array_append(edge_frame, edge); - vso->disk_edges++; - } - } - - vso->edge_frame = edge_frame; - vso->vtx_frame = vtx_frame; - - /* Set the interp at starting vtx */ - copy_v3_v3(vso->interp, sel_vtx->co); - - return vso->disk_edges > 0; -} - -static int edbm_vertex_slide_modal(bContext *C, wmOperator *op, wmEvent *event) -{ - VertexSlideOp *vso = op->customdata; - char buff[128]; - - if (!vso) - return OPERATOR_CANCELLED; - - /* Notify the viewport */ - view3d_operator_needs_opengl(C); - - switch (event->type) { - case LEFTSHIFTKEY: - { - switch (event->val) { - case KM_PRESS: - vso->snap_to_mid = TRUE; - break; - case KM_RELEASE: - vso->snap_to_mid = FALSE; - break; - } - - break; - } - case LEFTCTRLKEY: - { - switch (event->val) { - case KM_PRESS: - vso->snap_n_merge = TRUE; - vso->snap_to_end_vtx = TRUE; - break; - case KM_RELEASE: - vso->snap_n_merge = FALSE; - vso->snap_to_end_vtx = FALSE; - break; - } - - break; - } - case LEFTALTKEY: - { - switch (event->val) { - case KM_PRESS: - vso->snap_to_end_vtx = TRUE; - break; - case KM_RELEASE: - vso->snap_to_end_vtx = FALSE; - break; - } - - break; - } - case RIGHTMOUSE: - case ESCKEY: - { - /* Enforce redraw */ - ED_region_tag_redraw(vso->active_region); - - /* Clean-up */ - vtx_slide_exit(C, op); - - return OPERATOR_CANCELLED; - } - case LEFTMOUSE: - { - if (event->val == KM_PRESS) { - /* Update mouse coords */ - copy_v2_v2_int(vso->m_co, event->mval); - - if (vso->slide_mode) { - vtx_slide_confirm(C, op); - /* Clean-up */ - vtx_slide_exit(C, op); - return OPERATOR_FINISHED; - } - else if (vso->sel_edge) { - vso->slide_mode = TRUE; - } - } - - ED_region_tag_redraw(vso->active_region); - break; - - } - case MOUSEMOVE: - { - sprintf(buff, "Vertex Slide: %f", vso->distance); - if (!vso->slide_mode) { - vtx_slide_find_edge(vso, event); - } - else { - vtx_slide_update(vso, event); - } - ED_area_headerprint(CTX_wm_area(C), buff); - ED_region_tag_redraw(vso->active_region); - break; - } - } - - return OPERATOR_RUNNING_MODAL; -} - -static int edbm_vertex_slide_cancel(bContext *C, wmOperator *op) -{ - /* Exit the modal */ - vtx_slide_exit(C, op); - - return OPERATOR_CANCELLED; -} - -static int edbm_vertex_slide_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event)) -{ - /* Initialize the operator */ - if (vtx_slide_init(C, op)) - return OPERATOR_RUNNING_MODAL; - else - return OPERATOR_CANCELLED; -} - -/* Vertex Slide */ -static int edbm_vertex_slide_exec_ex(bContext *C, wmOperator *op, const int do_update) -{ - Object *obedit = CTX_data_edit_object(C); - BMEditMesh *em = BMEdit_FromObject(obedit); - BMesh *bm = em->bm; - BMVert *start_vert; - BMOperator bmop; - BMEditSelection *ese = (BMEditSelection *)em->bm->selected.last; - - float factor = 0.0f; - - /* Invoked modally? */ - if (op->type->modal == edbm_vertex_slide_modal && op->customdata) { - VertexSlideOp *vso = (VertexSlideOp *)op->customdata; - - if (bm->totedgesel > 1) { - /* Reset selections */ - EDBM_flag_disable_all(em, BM_ELEM_SELECT); - BM_edge_select_set(bm, vso->sel_edge, TRUE); - BM_vert_select_set(bm, vso->start_vtx, TRUE); - - BM_select_history_store(em->bm, vso->sel_edge); - BM_select_history_store(em->bm, vso->start_vtx); - ese = (BMEditSelection *)em->bm->selected.last; - } - factor = vso->distance; - RNA_float_set(op->ptr, "factor", factor); - } - else { - /* Get Properties */ - factor = RNA_float_get(op->ptr, "factor"); - } - - /* Is there a starting vertex ? */ - if ((ese == NULL) || (ese->htype != BM_VERT && ese->htype != BM_EDGE)) { - BKE_report(op->reports, RPT_ERROR_INVALID_INPUT, "Vertex slide error: select a (single) vertex"); - return OPERATOR_CANCELLED; - } - - start_vert = (BMVert *)ese->ele; - - /* Prepare operator */ - if (!EDBM_op_init(em, &bmop, op, - "slide_vert vert=%e edges=%he factor=%f", - start_vert, BM_ELEM_SELECT, factor)) - { - return OPERATOR_CANCELLED; - } - /* Execute operator */ - BMO_op_exec(bm, &bmop); - - /* Deselect the input edges */ - BMO_slot_buffer_hflag_disable(bm, bmop.slots_in, "edges", BM_EDGE, BM_ELEM_SELECT, TRUE); - - /* Select the output vert */ - BMO_slot_buffer_hflag_enable(bm, bmop.slots_out, "verts.out", BM_VERT, BM_ELEM_SELECT, TRUE); - - /* Flush the select buffers */ - EDBM_selectmode_flush(em); - - if (!EDBM_op_finish(em, &bmop, op, TRUE)) { - return OPERATOR_CANCELLED; - } - - if (do_update) { - /* Update Geometry */ - EDBM_update_generic(em, TRUE, FALSE); - } - - return OPERATOR_FINISHED; -} - -#if 0 -static int edbm_vertex_slide_exec(bContext *C, wmOperator *op) -{ - return edbm_vertex_slide_exec_ex(C, op, TRUE); -} -#endif - -void MESH_OT_vert_slide(wmOperatorType *ot) -{ - PropertyRNA *prop; - - /* identifiers */ - ot->name = "Vertex Slide"; - ot->idname = "MESH_OT_vert_slide"; - ot->description = "Vertex slide"; - - /* api callback */ - ot->invoke = edbm_vertex_slide_invoke; - ot->modal = edbm_vertex_slide_modal; - ot->cancel = edbm_vertex_slide_cancel; - ot->poll = ED_operator_editmesh_region_view3d; - - /* ot->exec = edbm_vertex_slide_exec; - * ot->poll = ED_operator_editmesh; */ - - /* flags */ - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; - - /* Properties for vertex slide */ - prop = RNA_def_float(ot->srna, "factor", 0.0f, -FLT_MAX, FLT_MAX, "Distance", "Distance", -5.0f, 5.0f); - RNA_def_property_ui_range(prop, -5.0f, 5.0f, 0.1, 4); - RNA_def_property_flag(prop, PROP_SKIP_SAVE); -} diff --git a/source/blender/editors/mesh/editmesh_tools.c b/source/blender/editors/mesh/editmesh_tools.c index 27c68ce21bc..b411cd2bd27 100644 --- a/source/blender/editors/mesh/editmesh_tools.c +++ b/source/blender/editors/mesh/editmesh_tools.c @@ -387,7 +387,7 @@ static short edbm_extrude_edge(Object *obedit, BMEditMesh *em, const char hflag, if (ele->head.htype == BM_FACE) { f = (BMFace *)ele; add_normal_aligned(nor, f->no); - }; + } } normalize_v3(nor); @@ -3190,8 +3190,7 @@ static int mesh_separate_loose(Main *bmain, Scene *scene, Base *base_old, BMesh BMW_FLAG_NOP, BMW_NIL_LAY); - e = BMW_begin(&walker, v_seed); - for (; e; e = BMW_step(&walker)) { + for (e = BMW_begin(&walker, v_seed); e; e = BMW_step(&walker)) { if (!BM_elem_flag_test(e->v1, BM_ELEM_TAG)) { BM_elem_flag_enable(e->v1, BM_ELEM_TAG); tot++; } if (!BM_elem_flag_test(e->v2, BM_ELEM_TAG)) { BM_elem_flag_enable(e->v2, BM_ELEM_TAG); tot++; } } @@ -3838,6 +3837,9 @@ static int edbm_select_face_by_sides_exec(bContext *C, wmOperator *op) const int numverts = RNA_int_get(op->ptr, "number"); const int type = RNA_enum_get(op->ptr, "type"); + if (!RNA_boolean_get(op->ptr, "extend")) + EDBM_flag_disable_all(em, BM_ELEM_SELECT); + BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { int select; @@ -3897,9 +3899,10 @@ void MESH_OT_select_face_by_sides(wmOperatorType *ot) /* properties */ RNA_def_int(ot->srna, "number", 4, 3, INT_MAX, "Number of Vertices", "", 3, INT_MAX); RNA_def_enum(ot->srna, "type", type_items, 1, "Type", "Type of comparison to make"); + RNA_def_boolean(ot->srna, "extend", TRUE, "Extend", "Extend the selection"); } -static int edbm_select_loose_verts_exec(bContext *C, wmOperator *UNUSED(op)) +static int edbm_select_loose_verts_exec(bContext *C, wmOperator *op) { Object *obedit = CTX_data_edit_object(C); BMEditMesh *em = BMEdit_FromObject(obedit); @@ -3907,6 +3910,9 @@ static int edbm_select_loose_verts_exec(bContext *C, wmOperator *UNUSED(op)) BMEdge *eed; BMIter iter; + if (!RNA_boolean_get(op->ptr, "extend")) + EDBM_flag_disable_all(em, BM_ELEM_SELECT); + BM_ITER_MESH (eve, &iter, em->bm, BM_VERTS_OF_MESH) { if (!eve->e) { BM_vert_select_set(em->bm, eve, TRUE); @@ -3938,6 +3944,9 @@ void MESH_OT_select_loose_verts(wmOperatorType *ot) /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + + /* props */ + RNA_def_boolean(ot->srna, "extend", false, "Extend", "Extend the selection"); } static int edbm_select_mirror_exec(bContext *C, wmOperator *op) @@ -4593,7 +4602,7 @@ static int edbm_noise_exec(bContext *C, wmOperator *op) BM_ITER_MESH (eve, &iter, em->bm, BM_VERTS_OF_MESH) { if (BM_elem_flag_test(eve, BM_ELEM_SELECT)) { float tin, dum; - externtex(ma->mtex[0], eve->co, &tin, &dum, &dum, &dum, &dum, 0); + externtex(ma->mtex[0], eve->co, &tin, &dum, &dum, &dum, &dum, 0, NULL); eve->co[2] += fac * tin; } } diff --git a/source/blender/editors/mesh/editmesh_utils.c b/source/blender/editors/mesh/editmesh_utils.c index b95c8a05353..d62eba9728c 100644 --- a/source/blender/editors/mesh/editmesh_utils.c +++ b/source/blender/editors/mesh/editmesh_utils.c @@ -682,8 +682,10 @@ void undo_push_mesh(bContext *C, const char *name) undo_editmode_push(C, name, getEditMesh, free_undo, undoMesh_to_editbtMesh, editbtMesh_to_undoMesh, NULL); } -/* write comment here */ -UvVertMap *EDBM_uv_vert_map_create(BMEditMesh *em, int selected, const float limit[2]) +/** + * Return a new UVVertMap from the editmesh + */ +UvVertMap *EDBM_uv_vert_map_create(BMEditMesh *em, bool use_select, const float limit[2]) { BMVert *ev; BMFace *efa; @@ -696,6 +698,7 @@ UvVertMap *EDBM_uv_vert_map_create(BMEditMesh *em, int selected, const float lim MLoopUV *luv; unsigned int a; int totverts, i, totuv; + const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV); BM_mesh_elem_index_ensure(em->bm, BM_VERT | BM_FACE); @@ -704,8 +707,9 @@ UvVertMap *EDBM_uv_vert_map_create(BMEditMesh *em, int selected, const float lim /* generate UvMapVert array */ BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { - if (!selected || ((!BM_elem_flag_test(efa, BM_ELEM_HIDDEN)) && BM_elem_flag_test(efa, BM_ELEM_SELECT))) + if ((use_select == false) || BM_elem_flag_test(efa, BM_ELEM_SELECT)) { totuv += efa->len; + } } if (totuv == 0) { @@ -726,7 +730,7 @@ UvVertMap *EDBM_uv_vert_map_create(BMEditMesh *em, int selected, const float lim a = 0; BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { - if (!selected || ((!BM_elem_flag_test(efa, BM_ELEM_HIDDEN)) && BM_elem_flag_test(efa, BM_ELEM_SELECT))) { + if ((use_select == false) || BM_elem_flag_test(efa, BM_ELEM_SELECT)) { i = 0; BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { buf->tfindex = i; @@ -761,7 +765,7 @@ UvVertMap *EDBM_uv_vert_map_create(BMEditMesh *em, int selected, const float lim /* tf = CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY); */ /* UNUSED */ l = BM_iter_at_index(em->bm, BM_LOOPS_OF_FACE, efa, v->tfindex); - luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV); + luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); uv = luv->uv; lastv = NULL; @@ -773,7 +777,7 @@ UvVertMap *EDBM_uv_vert_map_create(BMEditMesh *em, int selected, const float lim /* tf = CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY); */ /* UNUSED */ l = BM_iter_at_index(em->bm, BM_LOOPS_OF_FACE, efa, iterv->tfindex); - luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV); + luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); uv2 = luv->uv; sub_v2_v2v2(uvdiff, uv2, uv); @@ -831,6 +835,8 @@ UvElementMap *EDBM_uv_element_map_create(BMEditMesh *em, int selected, int do_is BMFace **stack; int stacksize = 0; + const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV); + BM_mesh_elem_index_ensure(em->bm, BM_VERT | BM_FACE); totverts = em->bm->totvert; @@ -843,8 +849,9 @@ UvElementMap *EDBM_uv_element_map_create(BMEditMesh *em, int selected, int do_is /* generate UvElement array */ BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { - if (!selected || ((!BM_elem_flag_test(efa, BM_ELEM_HIDDEN)) && BM_elem_flag_test(efa, BM_ELEM_SELECT))) + if (!selected || BM_elem_flag_test(efa, BM_ELEM_SELECT)) { totuv += efa->len; + } } if (totuv == 0) { @@ -869,7 +876,7 @@ UvElementMap *EDBM_uv_element_map_create(BMEditMesh *em, int selected, int do_is j = 0; BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { island_number[j++] = INVALID_ISLAND; - if (!selected || ((!BM_elem_flag_test(efa, BM_ELEM_HIDDEN)) && BM_elem_flag_test(efa, BM_ELEM_SELECT))) { + if (!selected || BM_elem_flag_test(efa, BM_ELEM_SELECT)) { BM_ITER_ELEM_INDEX (l, &liter, efa, BM_LOOPS_OF_FACE, i) { buf->l = l; buf->separate = 0; @@ -898,7 +905,7 @@ UvElementMap *EDBM_uv_element_map_create(BMEditMesh *em, int selected, int do_is newvlist = v; l = v->l; - luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV); + luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); uv = luv->uv; lastv = NULL; @@ -908,7 +915,7 @@ UvElementMap *EDBM_uv_element_map_create(BMEditMesh *em, int selected, int do_is next = iterv->next; l = iterv->l; - luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV); + luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); uv2 = luv->uv; sub_v2_v2v2(uvdiff, uv2, uv); @@ -1339,7 +1346,7 @@ void EDBM_mesh_reveal(BMEditMesh *em) /* so many tools call these that we better make it a generic function. */ -void EDBM_update_generic(BMEditMesh *em, const short do_tessface, const short is_destructive) +void EDBM_update_generic(BMEditMesh *em, const bool do_tessface, const bool is_destructive) { Object *ob = em->ob; /* order of calling isn't important */ diff --git a/source/blender/editors/mesh/mesh_intern.h b/source/blender/editors/mesh/mesh_intern.h index 790a7eae487..fe4917acdac 100644 --- a/source/blender/editors/mesh/mesh_intern.h +++ b/source/blender/editors/mesh/mesh_intern.h @@ -216,7 +216,6 @@ void MESH_OT_bevel(struct wmOperatorType *ot); void MESH_OT_bridge_edge_loops(struct wmOperatorType *ot); void MESH_OT_inset(struct wmOperatorType *ot); void MESH_OT_wireframe(struct wmOperatorType *ot); -void MESH_OT_vert_slide(struct wmOperatorType *ot); void MESH_OT_convex_hull(struct wmOperatorType *ot); diff --git a/source/blender/editors/mesh/mesh_ops.c b/source/blender/editors/mesh/mesh_ops.c index 372d6feec0c..9403299b0cd 100644 --- a/source/blender/editors/mesh/mesh_ops.c +++ b/source/blender/editors/mesh/mesh_ops.c @@ -154,7 +154,6 @@ void ED_operatortypes_mesh(void) WM_operatortype_append(MESH_OT_solidify); WM_operatortype_append(MESH_OT_select_nth); WM_operatortype_append(MESH_OT_vert_connect); - WM_operatortype_append(MESH_OT_vert_slide); WM_operatortype_append(MESH_OT_knife_tool); WM_operatortype_append(MESH_OT_bevel); @@ -269,10 +268,14 @@ void ED_keymap_mesh(wmKeyConfig *keyconf) keymap = WM_keymap_find(keyconf, "Mesh", 0, 0); keymap->poll = ED_operator_editmesh; - WM_keymap_add_item(keymap, "MESH_OT_loopcut_slide", RKEY, KM_PRESS, KM_CTRL, 0); - WM_keymap_add_item(keymap, "MESH_OT_bevel", BKEY, KM_PRESS, KM_CTRL, 0); + WM_keymap_add_item(keymap, "MESH_OT_loopcut_slide", RKEY, KM_PRESS, KM_CTRL, 0); WM_keymap_add_item(keymap, "MESH_OT_inset", IKEY, KM_PRESS, 0, 0); + kmi = WM_keymap_add_item(keymap, "MESH_OT_bevel", BKEY, KM_PRESS, KM_CTRL, 0); + RNA_boolean_set(kmi->ptr, "vertex_only", FALSE); + kmi = WM_keymap_add_item(keymap, "MESH_OT_bevel", BKEY, KM_PRESS, KM_CTRL | KM_SHIFT, 0); + RNA_boolean_set(kmi->ptr, "vertex_only", TRUE); + /* selecting */ /* standard mouse selection goes via space_view3d */ kmi = WM_keymap_add_item(keymap, "MESH_OT_loop_select", SELECTMOUSE, KM_PRESS, KM_ALT, 0); @@ -366,7 +369,7 @@ void ED_keymap_mesh(wmKeyConfig *keyconf) WM_keymap_add_item(keymap, "MESH_OT_vert_connect", JKEY, KM_PRESS, 0, 0); /* Vertex Slide */ - WM_keymap_add_item(keymap, "MESH_OT_vert_slide", VKEY, KM_PRESS, KM_SHIFT, 0); + WM_keymap_add_item(keymap, "TRANSFORM_OT_vert_slide", VKEY, KM_PRESS, KM_SHIFT, 0); /* use KM_CLICK because same key is used for tweaks */ kmi = WM_keymap_add_item(keymap, "MESH_OT_dupli_extrude_cursor", ACTIONMOUSE, KM_CLICK, KM_CTRL, 0); RNA_boolean_set(kmi->ptr, "rotate_source", TRUE); diff --git a/source/blender/editors/object/object_add.c b/source/blender/editors/object/object_add.c index 4db416b6f72..8457b278c6c 100644 --- a/source/blender/editors/object/object_add.c +++ b/source/blender/editors/object/object_add.c @@ -941,7 +941,7 @@ static void object_delete_check_glsl_update(Object *ob) void ED_base_object_free_and_unlink(Main *bmain, Scene *scene, Base *base) { DAG_id_type_tag(bmain, ID_OB); - BLI_remlink(&scene->base, base); + BKE_scene_base_unlink(scene, base); object_delete_check_glsl_update(base->object); BKE_libblock_free_us(&bmain->object, base->object); if (scene->basact == base) scene->basact = NULL; @@ -1698,7 +1698,11 @@ static Base *object_add_duplicate_internal(Main *bmain, Scene *scene, Base *base BLI_addhead(&scene->base, basen); /* addhead: prevent eternal loop */ basen->object = obn; - if (basen->flag & OB_FROMGROUP) { + /* 1) duplis should end up in same group as the original + * 2) Rigid Body sim participants MUST always be part of a group... + */ + // XXX: is 2) really a good measure here? + if ((basen->flag & OB_FROMGROUP) || ob->rigidbody_object || ob->rigidbody_constraint) { Group *group; for (group = bmain->group.first; group; group = group->id.next) { if (object_in_group(ob, group)) diff --git a/source/blender/editors/object/object_bake.c b/source/blender/editors/object/object_bake.c index f36c6d79783..322ba99593e 100644 --- a/source/blender/editors/object/object_bake.c +++ b/source/blender/editors/object/object_bake.c @@ -610,7 +610,12 @@ static void finish_bake_internal(BakeRender *bkr) /* freed when baking is done, but if its canceled we need to free here */ if (ibuf) { if (ibuf->userdata) { - MEM_freeN(ibuf->userdata); + BakeImBufuserData *userdata = (BakeImBufuserData *) ibuf->userdata; + if (userdata->mask_buffer) + MEM_freeN(userdata->mask_buffer); + if (userdata->displacement_buffer) + MEM_freeN(userdata->displacement_buffer); + MEM_freeN(userdata); ibuf->userdata = NULL; } } diff --git a/source/blender/editors/object/object_edit.c b/source/blender/editors/object/object_edit.c index fcc3b5d012e..5e5e38c3e43 100644 --- a/source/blender/editors/object/object_edit.c +++ b/source/blender/editors/object/object_edit.c @@ -376,7 +376,7 @@ void ED_object_exit_editmode(bContext *C, int flag) scene->obedit = NULL; // XXX for context /* flag object caches as outdated */ - BKE_ptcache_ids_from_object(&pidlist, obedit, NULL, 0); + BKE_ptcache_ids_from_object(&pidlist, obedit, scene, 0); for (pid = pidlist.first; pid; pid = pid->next) { if (pid->type != PTCACHE_TYPE_PARTICLES) /* particles don't need reset on geometry change */ pid->cache->flag |= PTCACHE_OUTDATED; diff --git a/source/blender/editors/object/object_ops.c b/source/blender/editors/object/object_ops.c index 03b50c05071..5c65e543cc9 100644 --- a/source/blender/editors/object/object_ops.c +++ b/source/blender/editors/object/object_ops.c @@ -394,6 +394,12 @@ void ED_keymap_object(wmKeyConfig *keyconf) WM_keymap_verify_item(keymap, "GROUP_OT_objects_remove_all", GKEY, KM_PRESS, KM_SHIFT | KM_CTRL | KM_ALT, 0); WM_keymap_verify_item(keymap, "GROUP_OT_objects_add_active", GKEY, KM_PRESS, KM_SHIFT | KM_CTRL, 0); WM_keymap_verify_item(keymap, "GROUP_OT_objects_remove_active", GKEY, KM_PRESS, KM_SHIFT | KM_ALT, 0); + + kmi = WM_keymap_add_item(keymap, "RIGIDBODY_OT_objects_add", RKEY, KM_PRESS, KM_CTRL, 0); + RNA_enum_set(kmi->ptr, "type", 0); /* active */ + kmi = WM_keymap_add_item(keymap, "RIGIDBODY_OT_objects_add", RKEY, KM_PRESS, KM_CTRL | KM_SHIFT, 0); + RNA_enum_set(kmi->ptr, "type", 1); /* passive */ + kmi = WM_keymap_add_item(keymap, "RIGIDBODY_OT_objects_remove", RKEY, KM_PRESS, KM_CTRL | KM_ALT, 0); WM_keymap_add_menu(keymap, "VIEW3D_MT_object_specials", WKEY, KM_PRESS, 0, 0); diff --git a/source/blender/editors/object/object_relations.c b/source/blender/editors/object/object_relations.c index fa44d3d7fb4..9749494bc66 100644 --- a/source/blender/editors/object/object_relations.c +++ b/source/blender/editors/object/object_relations.c @@ -354,7 +354,7 @@ static int make_proxy_exec(bContext *C, wmOperator *op) /* remove base, leave user count of object, it gets linked in BKE_object_make_proxy */ if (gob == NULL) { - BLI_remlink(&scene->base, oldbase); + BKE_scene_base_unlink(scene, oldbase); MEM_freeN(oldbase); } diff --git a/source/blender/editors/object/object_vgroup.c b/source/blender/editors/object/object_vgroup.c index e7c619acb67..a1fb0eb98d2 100644 --- a/source/blender/editors/object/object_vgroup.c +++ b/source/blender/editors/object/object_vgroup.c @@ -82,6 +82,7 @@ static void vgroup_remap_update_users(Object *ob, int *map); static void vgroup_delete_edit_mode(Object *ob, bDeformGroup *defgroup); static void vgroup_delete_object_mode(Object *ob, bDeformGroup *dg); static void vgroup_delete_all(Object *ob); +static int ED_vgroup_give_parray(ID *id, MDeformVert ***dvert_arr, int *dvert_tot, const short use_vert_sel); static int vertex_group_use_vert_sel(Object *ob) { @@ -183,6 +184,29 @@ int ED_vgroup_data_create(ID *id) } } +/** + * Removes out of range MDeformWeights + */ +void ED_vgroup_data_clamp_range(ID *id, const int total) +{ + MDeformVert **dvert_arr; + int dvert_tot; + + if (ED_vgroup_give_parray(id, &dvert_arr, &dvert_tot, false)) { + int i; + for (i = 0; i < dvert_tot; i++) { + MDeformVert *dv = dvert_arr[i]; + int j; + for (j = 0; j < dv->totweight; j++) { + if (dv->dw[j].def_nr >= total) { + defvert_remove_group(dv, &dv->dw[j]); + j--; + } + } + } + } +} + static int ED_vgroup_give_parray(ID *id, MDeformVert ***dvert_arr, int *dvert_tot, const short use_vert_sel) { *dvert_tot = 0; @@ -2725,7 +2749,7 @@ void OBJECT_OT_vertex_group_remove_from(wmOperatorType *ot) /* identifiers */ ot->name = "Remove from Vertex Group"; ot->idname = "OBJECT_OT_vertex_group_remove_from"; - ot->description = "Remove the selected vertices from the active vertex group"; + ot->description = "Remove the selected vertices from active or all vertex group(s)"; /* api callbacks */ ot->poll = vertex_group_poll_edit_or_wpaint_vert_select; diff --git a/source/blender/editors/physics/CMakeLists.txt b/source/blender/editors/physics/CMakeLists.txt index da12a26e747..435327319aa 100644 --- a/source/blender/editors/physics/CMakeLists.txt +++ b/source/blender/editors/physics/CMakeLists.txt @@ -43,6 +43,9 @@ set(SRC physics_fluid.c physics_ops.c physics_pointcache.c + rigidbody_constraint.c + rigidbody_object.c + rigidbody_world.c physics_intern.h ) @@ -59,4 +62,11 @@ if(WITH_INTERNATIONAL) add_definitions(-DWITH_INTERNATIONAL) endif() +if(WITH_BULLET) + list(APPEND INC + ../../rigidbody + ) + add_definitions(-DWITH_BULLET) +endif() + blender_add_lib(bf_editor_physics "${SRC}" "${INC}" "${INC_SYS}") diff --git a/source/blender/editors/physics/SConscript b/source/blender/editors/physics/SConscript index 293f7769a6a..b68cc944925 100644 --- a/source/blender/editors/physics/SConscript +++ b/source/blender/editors/physics/SConscript @@ -33,6 +33,7 @@ incs = '../include ../../blenfont ../../blenlib ../../blenkernel ../../makesdna incs += ' ../../windowmanager #/intern/guardedalloc #/extern/glew/include' incs += ' ../../gpu ../../blenloader ../../bmesh' incs += ' ../../makesrna ../../render/extern/include #/intern/elbeem/extern' +incs += ' ../../rigidbody' defs = [] diff --git a/source/blender/editors/physics/particle_edit.c b/source/blender/editors/physics/particle_edit.c index 9dbc0f9a10c..deddc649956 100644 --- a/source/blender/editors/physics/particle_edit.c +++ b/source/blender/editors/physics/particle_edit.c @@ -2004,7 +2004,7 @@ static int rekey_exec(bContext *C, wmOperator *op) PE_set_data(C, &data); data.dval= 1.0f / (float)(data.totrekey-1); - data.totrekey= RNA_int_get(op->ptr, "keys"); + data.totrekey= RNA_int_get(op->ptr, "keys_number"); foreach_selected_point(&data, rekey_particle); @@ -2031,7 +2031,7 @@ void PARTICLE_OT_rekey(wmOperatorType *ot) ot->flag = OPTYPE_REGISTER|OPTYPE_UNDO; /* properties */ - RNA_def_int(ot->srna, "keys", 2, 2, INT_MAX, "Number of Keys", "", 2, 100); + RNA_def_int(ot->srna, "keys_number", 2, 2, INT_MAX, "Number of Keys", "", 2, 100); } static void rekey_particle_to_time(Scene *scene, Object *ob, int pa_index, float path_time) @@ -3254,7 +3254,7 @@ static int brush_add(PEData *data, short number) ParticleEditSettings *pset= PE_settings(scene); int i, k, n= 0, totpart= psys->totpart; float mco[2]; - short dmx= 0, dmy= 0; + float dmx, dmy; float co1[3], co2[3], min_d, imat[4][4]; float framestep, timestep; short size= pset->brush[PE_BRUSH_ADD].size; @@ -3282,12 +3282,19 @@ static int brush_add(PEData *data, short number) for (i=0; i<number; i++) { if (number>1) { - dmx=dmy=size; - while (dmx*dmx+dmy*dmy>size2) { - dmx=(short)((2.0f*BLI_frand()-1.0f)*size); - dmy=(short)((2.0f*BLI_frand()-1.0f)*size); + dmx = size; + dmy = size; + + /* rejection sampling to get points in circle */ + while (dmx*dmx + dmy*dmy > size2) { + dmx= (2.0f*BLI_frand() - 1.0f)*size; + dmy= (2.0f*BLI_frand() - 1.0f)*size; } } + else { + dmx = 0.0f; + dmy = 0.0f; + } mco[0] = data->mval[0] + dmx; mco[1] = data->mval[1] + dmy; @@ -3307,8 +3314,8 @@ static int brush_add(PEData *data, short number) int newtotpart=totpart+n; float hairmat[4][4], cur_co[3]; KDTree *tree=0; - ParticleData *pa, *new_pars= MEM_callocN(newtotpart*sizeof(ParticleData), "ParticleData new"); - PTCacheEditPoint *point, *new_points= MEM_callocN(newtotpart*sizeof(PTCacheEditPoint), "PTCacheEditPoint array new"); + ParticleData *pa, *new_pars = MEM_callocN(newtotpart*sizeof(ParticleData), "ParticleData new"); + PTCacheEditPoint *point, *new_points = MEM_callocN(newtotpart*sizeof(PTCacheEditPoint), "PTCacheEditPoint array new"); PTCacheEditKey *key; HairKey *hkey; @@ -3343,8 +3350,8 @@ static int brush_add(PEData *data, short number) edit->totpoint= psys->totpart= newtotpart; /* create new elements */ - pa= psys->particles + totpart; - point= edit->points + totpart; + pa = psys->particles + totpart; + point = edit->points + totpart; for (i=totpart; i<newtotpart; i++, pa++, point++) { memcpy(pa, add_pars + i - totpart, sizeof(ParticleData)); @@ -3390,8 +3397,14 @@ static int brush_add(PEData *data, short number) weight[w] = 0.0f; } - for (w=0; w<maxw; w++) - weight[w] /= totw; + if(totw > 0.0f) { + for (w=0; w<maxw; w++) + weight[w] /= totw; + } + else { + for (w=0; w<maxw; w++) + weight[w] = 1.0f/maxw; + } ppa= psys->particles+ptn[0].index; @@ -3403,7 +3416,7 @@ static int brush_add(PEData *data, short number) psys_get_particle_on_path(&sim, ptn[0].index, key3, 0); mul_v3_fl(key3[0].co, weight[0]); - /* TODO: interpolatint the weight would be nicer */ + /* TODO: interpolating the weight would be nicer */ thkey->weight= (ppa->hair+MIN2(k, ppa->totkey-1))->weight; if (maxw>1) { @@ -4147,8 +4160,8 @@ int PE_minmax(Scene *scene, float min[3], float max[3]) /* initialize needed data for bake edit */ static void PE_create_particle_edit(Scene *scene, Object *ob, PointCache *cache, ParticleSystem *psys) { - PTCacheEdit *edit= (psys)? psys->edit : cache->edit; - ParticleSystemModifierData *psmd= (psys)? psys_get_modifier(ob, psys): NULL; + PTCacheEdit *edit; + ParticleSystemModifierData *psmd = (psys) ? psys_get_modifier(ob, psys) : NULL; POINT_P; KEY_K; ParticleData *pa = NULL; HairKey *hkey; @@ -4164,6 +4177,8 @@ static void PE_create_particle_edit(Scene *scene, Object *ob, PointCache *cache, if (psys == NULL && (cache && cache->mem_cache.first == NULL)) return; + edit = (psys) ? psys->edit : cache->edit; + if (!edit) { totpoint = psys ? psys->totpart : (int)((PTCacheMem *)cache->mem_cache.first)->totpoint; diff --git a/source/blender/editors/physics/physics_intern.h b/source/blender/editors/physics/physics_intern.h index 75779cf6102..77ce5a334e6 100644 --- a/source/blender/editors/physics/physics_intern.h +++ b/source/blender/editors/physics/physics_intern.h @@ -105,5 +105,23 @@ void PTCACHE_OT_bake_from_cache(struct wmOperatorType *ot); void PTCACHE_OT_add(struct wmOperatorType *ot); void PTCACHE_OT_remove(struct wmOperatorType *ot); -#endif /* __PHYSICS_INTERN_H__ */ +/* rigidbody_object.c */ +void RIGIDBODY_OT_object_add(struct wmOperatorType *ot); +void RIGIDBODY_OT_object_remove(struct wmOperatorType *ot); + +void RIGIDBODY_OT_objects_add(struct wmOperatorType *ot); +void RIGIDBODY_OT_objects_remove(struct wmOperatorType *ot); + +void RIGIDBODY_OT_shape_change(struct wmOperatorType *ot); +void RIGIDBODY_OT_mass_calculate(struct wmOperatorType *ot); +/* rigidbody_constraint.c */ +void RIGIDBODY_OT_constraint_add(struct wmOperatorType *ot); +void RIGIDBODY_OT_constraint_remove(struct wmOperatorType *ot); + +/*rigidbody_world.c */ +void RIGIDBODY_OT_world_add(struct wmOperatorType *ot); +void RIGIDBODY_OT_world_remove(struct wmOperatorType *ot); +void RIGIDBODY_OT_world_export(struct wmOperatorType *ot); + +#endif /* __PHYSICS_INTERN_H__ */ diff --git a/source/blender/editors/physics/physics_ops.c b/source/blender/editors/physics/physics_ops.c index fb99d296a54..51a66886c6e 100644 --- a/source/blender/editors/physics/physics_ops.c +++ b/source/blender/editors/physics/physics_ops.c @@ -86,6 +86,22 @@ static void operatortypes_particle(void) WM_operatortype_append(PARTICLE_OT_dupliob_remove); WM_operatortype_append(PARTICLE_OT_dupliob_move_up); WM_operatortype_append(PARTICLE_OT_dupliob_move_down); + + WM_operatortype_append(RIGIDBODY_OT_object_add); + WM_operatortype_append(RIGIDBODY_OT_object_remove); + + WM_operatortype_append(RIGIDBODY_OT_objects_add); + WM_operatortype_append(RIGIDBODY_OT_objects_remove); + + WM_operatortype_append(RIGIDBODY_OT_shape_change); + WM_operatortype_append(RIGIDBODY_OT_mass_calculate); + + WM_operatortype_append(RIGIDBODY_OT_constraint_add); + WM_operatortype_append(RIGIDBODY_OT_constraint_remove); + + WM_operatortype_append(RIGIDBODY_OT_world_add); + WM_operatortype_append(RIGIDBODY_OT_world_remove); +// WM_operatortype_append(RIGIDBODY_OT_world_export); } static void keymap_particle(wmKeyConfig *keyconf) diff --git a/source/blender/editors/physics/rigidbody_constraint.c b/source/blender/editors/physics/rigidbody_constraint.c new file mode 100644 index 00000000000..fac835a414a --- /dev/null +++ b/source/blender/editors/physics/rigidbody_constraint.c @@ -0,0 +1,202 @@ +/* + * ***** 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) 2013 Blender Foundation + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): Sergej Reich + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file rigidbody_constraint.c + * \ingroup editor_physics + * \brief Rigid Body constraint editing operators + */ + +#include <stdlib.h> +#include <string.h> + +#include "MEM_guardedalloc.h" + +#include "DNA_group_types.h" +#include "DNA_object_types.h" +#include "DNA_rigidbody_types.h" +#include "DNA_scene_types.h" + +#include "BLI_blenlib.h" +#include "BLI_math.h" + +#include "BKE_context.h" +#include "BKE_depsgraph.h" +#include "BKE_group.h" +#include "BKE_object.h" +#include "BKE_report.h" +#include "BKE_rigidbody.h" + +#include "RNA_access.h" +#include "RNA_define.h" +#include "RNA_enum_types.h" + +#include "WM_api.h" +#include "WM_types.h" + +#include "ED_physics.h" +#include "ED_screen.h" + +#include "physics_intern.h" + +/* ********************************************** */ +/* Helper API's for RigidBody Constraint Editing */ + +static int ED_operator_rigidbody_con_active_poll(bContext *C) +{ + if (ED_operator_object_active_editable(C)) { + Object *ob = CTX_data_active_object(C); + return (ob && ob->rigidbody_constraint); + } + else + return 0; +} + + +void ED_rigidbody_con_add(wmOperator *op, Scene *scene, Object *ob, int type) +{ + RigidBodyWorld *rbw = BKE_rigidbody_get_world(scene); + + /* check that object doesn't already have a constraint */ + if (ob->rigidbody_constraint) { + BKE_reportf(op->reports, RPT_INFO, "Object '%s' already has a Rigid Body Constraint", ob->id.name + 2); + return; + } + /* create constraint group if it doesn't already exits */ + if (rbw->constraints == NULL) { + rbw->constraints = add_group("RigidBodyConstraints"); + } + /* make rigidbody constraint settings */ + ob->rigidbody_constraint = BKE_rigidbody_create_constraint(scene, ob, type); + ob->rigidbody_constraint->flag |= RBC_FLAG_NEEDS_VALIDATE; + + /* add constraint to rigid body constraint group */ + add_to_group(rbw->constraints, ob, scene, NULL); +} + +void ED_rigidbody_con_remove(Scene *scene, Object *ob) +{ + RigidBodyWorld *rbw = BKE_rigidbody_get_world(scene); + + BKE_rigidbody_remove_constraint(scene, ob); + if (rbw) + rem_from_group(rbw->constraints, ob, scene, NULL); + + DAG_id_tag_update(&ob->id, OB_RECALC_OB); +} + +/* ********************************************** */ +/* Active Object Add/Remove Operators */ + +/* ************ Add Rigid Body Constraint ************** */ + +static int rigidbody_con_add_exec(bContext *C, wmOperator *op) +{ + Scene *scene = CTX_data_scene(C); + RigidBodyWorld *rbw = BKE_rigidbody_get_world(scene); + Object *ob = (scene) ? OBACT : NULL; + int type = RNA_enum_get(op->ptr, "type"); + + /* sanity checks */ + if (ELEM(NULL, scene, rbw)) { + BKE_report(op->reports, RPT_ERROR, "No Rigid Body World to add Rigid Body Constraint to"); + return OPERATOR_CANCELLED; + } + /* apply to active object */ + ED_rigidbody_con_add(op, scene, ob, type); + + /* send updates */ + DAG_ids_flush_update(CTX_data_main(C), 0); + + WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, NULL); + WM_event_add_notifier(C, NC_GROUP | NA_EDITED, NULL); + + /* done */ + return OPERATOR_FINISHED; +} + +void RIGIDBODY_OT_constraint_add(wmOperatorType *ot) +{ + /* identifiers */ + ot->idname = "RIGIDBODY_OT_constraint_add"; + ot->name = "Add Rigid Body Constraint"; + ot->description = "Add Rigid Body Constraint to active object"; + + /* callbacks */ + ot->exec = rigidbody_con_add_exec; + ot->poll = ED_operator_object_active_editable; + + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + + /* properties */ + ot->prop = RNA_def_enum(ot->srna, "type", rigidbody_con_type_items, RBC_TYPE_FIXED, "Rigid Body Constraint Type", ""); +} + +/* ************ Remove Rigid Body Constraint ************** */ + +static int rigidbody_con_remove_exec(bContext *C, wmOperator *op) +{ + Scene *scene = CTX_data_scene(C); + Object *ob = (scene) ? OBACT : NULL; + + /* sanity checks */ + if (scene == NULL) + return OPERATOR_CANCELLED; + + /* apply to active object */ + if (ELEM(NULL, ob, ob->rigidbody_constraint)) { + BKE_report(op->reports, RPT_ERROR, "Object has no Rigid Body Constraint to remove"); + return OPERATOR_CANCELLED; + } + else { + ED_rigidbody_con_remove(scene, ob); + } + + /* send updates */ + DAG_ids_flush_update(CTX_data_main(C), 0); + + WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, NULL); + WM_event_add_notifier(C, NC_GROUP | NA_EDITED, NULL); + + /* done */ + return OPERATOR_FINISHED; +} + +void RIGIDBODY_OT_constraint_remove(wmOperatorType *ot) +{ + /* identifiers */ + ot->idname = "RIGIDBODY_OT_constraint_remove"; + ot->name = "Remove Rigid Body Constraint"; + ot->description = "Remove Rigid Body Constraint from Object"; + + /* callbacks */ + ot->exec = rigidbody_con_remove_exec; + ot->poll = ED_operator_rigidbody_con_active_poll; + + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; +} diff --git a/source/blender/editors/physics/rigidbody_object.c b/source/blender/editors/physics/rigidbody_object.c new file mode 100644 index 00000000000..fc1e24840a4 --- /dev/null +++ b/source/blender/editors/physics/rigidbody_object.c @@ -0,0 +1,628 @@ +/* + * ***** 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) 2013 Blender Foundation + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): Joshua Leung, Sergej Reich + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file rigidbody_object.c + * \ingroup editor_physics + * \brief Rigid Body object editing operators + */ + +#include <stdlib.h> +#include <string.h> + +#include "MEM_guardedalloc.h" + +#include "DNA_group_types.h" +#include "DNA_object_types.h" +#include "DNA_mesh_types.h" +#include "DNA_rigidbody_types.h" +#include "DNA_scene_types.h" + +#include "BLI_blenlib.h" +#include "BLI_math.h" + +#include "BKE_context.h" +#include "BKE_depsgraph.h" +#include "BKE_group.h" +#include "BKE_object.h" +#include "BKE_report.h" +#include "BKE_rigidbody.h" + +#include "RNA_access.h" +#include "RNA_define.h" +#include "RNA_enum_types.h" + +#include "WM_api.h" +#include "WM_types.h" + +#include "ED_physics.h" +#include "ED_screen.h" + +#include "physics_intern.h" + +/* ********************************************** */ +/* Helper API's for RigidBody Objects Editing */ + +static int ED_operator_rigidbody_active_poll(bContext *C) +{ + if (ED_operator_object_active_editable(C)) { + Object *ob = CTX_data_active_object(C); + return (ob && ob->rigidbody_object); + } + else + return 0; +} + +static int ED_operator_rigidbody_add_poll(bContext *C) +{ + if (ED_operator_object_active_editable(C)) { + Object *ob = CTX_data_active_object(C); + return (ob && ob->type == OB_MESH); + } + else + return 0; +} + +/* ----------------- */ + +void ED_rigidbody_ob_add(wmOperator *op, Scene *scene, Object *ob, int type) +{ + RigidBodyWorld *rbw = BKE_rigidbody_get_world(scene); + + /* check that object doesn't already belong to the current simulation */ + if (ob->rigidbody_object) { + BKE_reportf(op->reports, RPT_INFO, "Object '%s' already has a Rigid Body", ob->id.name + 2); + return; + } + if (ob->type != OB_MESH) { + BKE_report(op->reports, RPT_ERROR, "Can't add Rigid Body to non mesh object"); + return; + } + if (((Mesh *)ob->data)->totpoly == 0) { + BKE_report(op->reports, RPT_ERROR, "Can't create Rigid Body from mesh with no polygons"); + return; + } + + /* Add rigid body world and group if they don't exist for convenience */ + if (rbw == NULL) { + rbw = BKE_rigidbody_create_world(scene); + BKE_rigidbody_validate_sim_world(scene, rbw, false); + scene->rigidbody_world = rbw; + } + if (rbw->group == NULL) { + rbw->group = add_group("RigidBodyWorld"); + } + + /* make rigidbody object settings */ + ob->rigidbody_object = BKE_rigidbody_create_object(scene, ob, type); + ob->rigidbody_object->flag |= RBO_FLAG_NEEDS_VALIDATE; + + /* add object to rigid body group */ + add_to_group(rbw->group, ob, scene, NULL); +} + +void ED_rigidbody_ob_remove(Scene *scene, Object *ob) +{ + RigidBodyWorld *rbw = BKE_rigidbody_get_world(scene); + + BKE_rigidbody_remove_object(scene, ob); + if (rbw) + rem_from_group(rbw->group, ob, scene, NULL); + + DAG_id_tag_update(&ob->id, OB_RECALC_OB); +} + +/* ********************************************** */ +/* Active Object Add/Remove Operators */ + +/* ************ Add Rigid Body ************** */ + +static int rigidbody_ob_add_exec(bContext *C, wmOperator *op) +{ + Scene *scene = CTX_data_scene(C); + Object *ob = (scene) ? OBACT : NULL; + int type = RNA_enum_get(op->ptr, "type"); + + /* apply to active object */ + ED_rigidbody_ob_add(op, scene, ob, type); + + /* send updates */ + DAG_ids_flush_update(CTX_data_main(C), 0); + + WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, NULL); + WM_event_add_notifier(C, NC_GROUP | NA_EDITED, NULL); + + /* done */ + return OPERATOR_FINISHED; +} + +void RIGIDBODY_OT_object_add(wmOperatorType *ot) +{ + /* identifiers */ + ot->idname = "RIGIDBODY_OT_object_add"; + ot->name = "Add Rigid Body"; + ot->description = "Add active object as Rigid Body"; + + /* callbacks */ + ot->exec = rigidbody_ob_add_exec; + ot->poll = ED_operator_rigidbody_add_poll; + + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + + /* properties */ + ot->prop = RNA_def_enum(ot->srna, "type", rigidbody_ob_type_items, RBO_TYPE_ACTIVE, "Rigid Body Type", ""); +} + +/* ************ Remove Rigid Body ************** */ + +static int rigidbody_ob_remove_exec(bContext *C, wmOperator *op) +{ + Scene *scene = CTX_data_scene(C); + Object *ob = (scene) ? OBACT : NULL; + + /* sanity checks */ + if (scene == NULL) + return OPERATOR_CANCELLED; + + /* apply to active object */ + if (ELEM(NULL, ob, ob->rigidbody_object)) { + BKE_report(op->reports, RPT_ERROR, "Object has no Rigid Body settings to remove"); + return OPERATOR_CANCELLED; + } + else + ED_rigidbody_ob_remove(scene, ob); + + /* send updates */ + DAG_ids_flush_update(CTX_data_main(C), 0); + + WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, NULL); + WM_event_add_notifier(C, NC_GROUP | NA_EDITED, NULL); + + /* done */ + return OPERATOR_FINISHED; +} + +void RIGIDBODY_OT_object_remove(wmOperatorType *ot) +{ + /* identifiers */ + ot->idname = "RIGIDBODY_OT_object_remove"; + ot->name = "Remove Rigid Body"; + ot->description = "Remove Rigid Body settings from Object"; + + /* callbacks */ + ot->exec = rigidbody_ob_remove_exec; + ot->poll = ED_operator_rigidbody_active_poll; + + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; +} + +/* ********************************************** */ +/* Selected Object Add/Remove Operators */ + +/* ************ Add Rigid Bodies ************** */ + +static int rigidbody_obs_add_exec(bContext *C, wmOperator *op) +{ + Scene *scene = CTX_data_scene(C); + int type = RNA_enum_get(op->ptr, "type"); + + /* sanity check */ + if (scene == NULL) { + BKE_report(op->reports, RPT_ERROR, "No Scene to add Rigid Bodies to"); + return OPERATOR_CANCELLED; + } + /* create rigid body objects and add them to the world's group */ + CTX_DATA_BEGIN(C, Object *, ob, selected_objects) { + ED_rigidbody_ob_add(op, scene, ob, type); + } + CTX_DATA_END; + + /* send updates */ + DAG_ids_flush_update(CTX_data_main(C), 0); + + WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, NULL); + WM_event_add_notifier(C, NC_GROUP | NA_EDITED, NULL); + + /* done */ + return OPERATOR_FINISHED; +} + +void RIGIDBODY_OT_objects_add(wmOperatorType *ot) +{ + /* identifiers */ + ot->idname = "RIGIDBODY_OT_objects_add"; + ot->name = "Add Rigid Bodies"; + ot->description = "Add selected objects as Rigid Bodies"; + + /* callbacks */ + ot->exec = rigidbody_obs_add_exec; + ot->poll = ED_operator_rigidbody_add_poll; + + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + + /* properties */ + ot->prop = RNA_def_enum(ot->srna, "type", rigidbody_ob_type_items, RBO_TYPE_ACTIVE, "Rigid Body Type", ""); +} + +/* ************ Remove Rigid Bodies ************** */ + +static int rigidbody_obs_remove_exec(bContext *C, wmOperator *UNUSED(op)) +{ + Scene *scene = CTX_data_scene(C); + + /* sanity checks */ + if (scene == NULL) + return OPERATOR_CANCELLED; + + /* apply this to all selected objects... */ + CTX_DATA_BEGIN(C, Object *, ob, selected_objects) + { + if (ob->rigidbody_object) { + ED_rigidbody_ob_remove(scene, ob); + } + } + CTX_DATA_END; + + /* send updates */ + DAG_ids_flush_update(CTX_data_main(C), 0); + + WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, NULL); + WM_event_add_notifier(C, NC_GROUP | NA_EDITED, NULL); + + /* done */ + return OPERATOR_FINISHED; +} + +void RIGIDBODY_OT_objects_remove(wmOperatorType *ot) +{ + /* identifiers */ + ot->idname = "RIGIDBODY_OT_objects_remove"; + ot->name = "Remove Rigid Bodies"; + ot->description = "Remove selected objects from Rigid Body simulation"; + + /* callbacks */ + ot->exec = rigidbody_obs_remove_exec; + ot->poll = ED_operator_rigidbody_active_poll; + + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; +} + +/* ********************************************** */ +/* Utility Operators */ + +/* ************ Change Collision Shapes ************** */ + +static int rigidbody_obs_shape_change_exec(bContext *C, wmOperator *op) +{ + Scene *scene = CTX_data_scene(C); + int shape = RNA_enum_get(op->ptr, "type"); + + /* sanity checks */ + if (scene == NULL) + return OPERATOR_CANCELLED; + + /* apply this to all selected objects... */ + CTX_DATA_BEGIN(C, Object *, ob, selected_objects) + { + if (ob->rigidbody_object) { + PointerRNA ptr; + + /* use RNA-system to change the property and perform all necessary changes */ + RNA_pointer_create(&ob->id, &RNA_RigidBodyObject, ob->rigidbody_object, &ptr); + RNA_enum_set(&ptr, "collision_shape", shape); + } + } + CTX_DATA_END; + + /* send updates */ + WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, NULL); // XXX: wrong notifiers for now, but these also do the job... + + /* done */ + return OPERATOR_FINISHED; +} + +void RIGIDBODY_OT_shape_change(wmOperatorType *ot) +{ + /* identifiers */ + ot->idname = "RIGIDBODY_OT_shape_change"; + ot->name = "Change Collision Shape"; + ot->description = "Change collision shapes for selected Rigid Body Objects"; + + /* callbacks */ + ot->invoke = WM_menu_invoke; + ot->exec = rigidbody_obs_shape_change_exec; + ot->poll = ED_operator_rigidbody_active_poll; + + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + + /* properties */ + ot->prop = RNA_def_enum(ot->srna, "type", rigidbody_ob_shape_items, RB_SHAPE_TRIMESH, "Rigid Body Shape", ""); +} + +/* ************ Calculate Mass ************** */ + +/* Entry in material density table */ +typedef struct rbMaterialDensityItem { + const char *name; /* Name of material */ + float density; /* Density (kg/m^3) */ +} rbMaterialDensityItem; + +/* Preset density values for materials (kg/m^3) + * Selected values obtained from: + * 1) http://www.jaredzone.info/2010/09/densities.html + * 2) http://www.avlandesign.com/density_construction.htm + * 3) http://www.avlandesign.com/density_metal.htm + */ +static rbMaterialDensityItem RB_MATERIAL_DENSITY_TABLE[] = { + {"Air", 1.0f}, /* not quite; adapted from 1.43 for oxygen for use as default */ + {"Acrylic", 1400.0f}, + {"Asphalt (Crushed)", 721.0f}, + {"Bark", 240.0f}, + {"Beans (Cocoa)", 593.0f}, + {"Beans (Soy)", 721.0f}, + {"Brick (Pressed)", 2400.0f}, + {"Brick (Common)", 2000.0f}, + {"Brick (Soft)", 1600.0f}, + {"Brass", 8216.0f}, + {"Bronze", 8860.0f}, + {"Carbon (Solid)", 2146.0f}, + {"Cardboard", 689.0f}, + {"Cast Iron", 7150.0f}, + //{"Cement", 1442.0f}, + {"Chalk (Solid)", 2499.0f}, + //{"Coffee (Fresh/Roast)", ~500}, + {"Concrete", 2320.0f}, + {"Charcoal", 208.0f}, + {"Cork", 240.0f}, + {"Copper", 8933.0f}, + {"Garbage", 481.0f}, + {"Glass (Broken)", 1940.0f}, + {"Glass (Solid)", 2190.0f}, + {"Gold", 19282.0f}, + {"Granite (Broken)", 1650.0f}, + {"Granite (Solid)", 2691.0f}, + {"Gravel", 2780.0f}, + {"Ice (Crushed)", 593.0f}, + {"Ice (Solid)", 919.0f}, + {"Iron", 7874.0f}, + {"Lead", 11342.0f}, + {"Limestone (Broken)", 1554.0f}, + {"Limestone (Solid)", 2611.0f}, + {"Marble (Broken)", 1570.0f}, + {"Marble (Solid)", 2563.0f}, + {"Paper", 1201.0f}, + {"Peanuts (Shelled)", 641.0f}, + {"Peanuts (Not Shelled)", 272.0f}, + {"Plaster", 849.0f}, + {"Plastic", 1200.0f}, + {"Polystyrene", 1050.0f}, + {"Rubber", 1522.0f}, + {"Silver", 10501.0f}, + {"Steel", 7860.0f}, + {"Stone", 2515.0f}, + {"Stone (Crushed)", 1602.0f}, + {"Timber", 610.0f} +}; +static const int NUM_RB_MATERIAL_PRESETS = sizeof(RB_MATERIAL_DENSITY_TABLE) / sizeof(rbMaterialDensityItem); + + +/* dynamically generate list of items + * - Although there is a runtime cost, this has a lower maintenance cost + * in the long run than other two-list solutions... + */ +static EnumPropertyItem *rigidbody_materials_itemf(bContext *UNUSED(C), PointerRNA *UNUSED(ptr), PropertyRNA *UNUSED(prop), int *free) +{ + EnumPropertyItem item_tmp = {0}; + EnumPropertyItem *item = NULL; + int totitem = 0; + int i = 0; + + /* add each preset to the list */ + for (i = 0; i < NUM_RB_MATERIAL_PRESETS; i++) { + rbMaterialDensityItem *preset = &RB_MATERIAL_DENSITY_TABLE[i]; + + item_tmp.identifier = item_tmp.name = preset->name; + item_tmp.value = i; + RNA_enum_item_add(&item, &totitem, &item_tmp); + } + + /* add special "custom" entry to the end of the list */ + { + item_tmp.identifier = item_tmp.name = "Custom"; + item_tmp.value = -1; + RNA_enum_item_add(&item, &totitem, &item_tmp); + } + + RNA_enum_item_end(&item, &totitem); + *free = 1; + + return item; +} + +/* ------------------------------------------ */ + +/* helper function to calculate volume of rigidbody object */ +// TODO: allow a parameter to specify method used to calculate this? +static float calc_rigidbody_ob_volume(Object *ob) +{ + RigidBodyOb *rbo = ob->rigidbody_object; + + float size[3] = {1.0f, 1.0f, 1.0f}; + float radius = 1.0f; + float height = 1.0f; + + float volume = 0.0f; + + /* if automatically determining dimensions, use the Object's boundbox + * - assume that all quadrics are standing upright on local z-axis + * - assume even distribution of mass around the Object's pivot + * (i.e. Object pivot is centralised in boundbox) + * - boundbox gives full width + */ + // XXX: all dimensions are auto-determined now... later can add stored settings for this + BKE_object_dimensions_get(ob, size); + + if (ELEM3(rbo->shape, RB_SHAPE_CAPSULE, RB_SHAPE_CYLINDER, RB_SHAPE_CONE)) { + /* take radius as largest x/y dimension, and height as z-dimension */ + radius = MAX2(size[0], size[1]) * 0.5f; + height = size[2]; + } + else if (rbo->shape == RB_SHAPE_SPHERE) { + /* take radius to the the largest dimension to try and encompass everything */ + radius = max_fff(size[0], size[1], size[2]) * 0.5f; + } + + /* calculate volume as appropriate */ + switch (rbo->shape) { + case RB_SHAPE_BOX: + volume = size[0] * size[1] * size[2]; + break; + + case RB_SHAPE_SPHERE: + volume = 4.0f / 3.0f * (float)M_PI * radius * radius * radius; + break; + + /* for now, assume that capsule is close enough to a cylinder... */ + case RB_SHAPE_CAPSULE: + case RB_SHAPE_CYLINDER: + volume = (float)M_PI * radius * radius * height; + break; + + case RB_SHAPE_CONE: + volume = (float)M_PI / 3.0f * radius * radius * height; + break; + + /* for now, all mesh shapes are just treated as boxes... + * NOTE: this may overestimate the volume, but other methods are overkill + */ + case RB_SHAPE_CONVEXH: + case RB_SHAPE_TRIMESH: + volume = size[0] * size[1] * size[2]; + break; + +#if 0 // XXX: not defined yet + case RB_SHAPE_COMPOUND: + volume = 0.0f; + break; +#endif + } + + /* return the volume calculated */ + return volume; +} + +/* ------------------------------------------ */ + +static int rigidbody_obs_calc_mass_exec(bContext *C, wmOperator *op) +{ + Scene *scene = CTX_data_scene(C); + int material = RNA_enum_get(op->ptr, "material"); + float density; + + /* sanity checks */ + if (scene == NULL) + return OPERATOR_CANCELLED; + + /* get density (kg/m^3) to apply */ + if (material >= 0) { + /* get density from table, and store in props for later repeating */ + if (material >= NUM_RB_MATERIAL_PRESETS) + material = 0; + + density = RB_MATERIAL_DENSITY_TABLE[material].density; + RNA_float_set(op->ptr, "density", density); + } + else { + /* custom - grab from whatever value is set */ + density = RNA_float_get(op->ptr, "density"); + } + + /* apply this to all selected objects (with rigidbodies)... */ + CTX_DATA_BEGIN(C, Object *, ob, selected_objects) + { + if (ob->rigidbody_object) { + PointerRNA ptr; + + float volume; /* m^3 */ + float mass; /* kg */ + + /* mass is calculated from the approximate volume of the object, + * and the density of the material we're simulating + */ + volume = calc_rigidbody_ob_volume(ob); + mass = volume * density; + + /* use RNA-system to change the property and perform all necessary changes */ + RNA_pointer_create(&ob->id, &RNA_RigidBodyObject, ob->rigidbody_object, &ptr); + RNA_float_set(&ptr, "mass", mass); + } + } + CTX_DATA_END; + + /* send updates */ + WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, NULL); // XXX: wrong notifiers for now, but these also do the job... + + /* done */ + return OPERATOR_FINISHED; +} + +void RIGIDBODY_OT_mass_calculate(wmOperatorType *ot) +{ + PropertyRNA *prop; + + /* identifiers */ + ot->idname = "RIGIDBODY_OT_mass_calculate"; + ot->name = "Calculate Mass"; + ot->description = "Automatically calculate mass values for Rigid Body Objects based on volume"; + + /* callbacks */ + ot->invoke = WM_menu_invoke; // XXX + ot->exec = rigidbody_obs_calc_mass_exec; + ot->poll = ED_operator_rigidbody_active_poll; + + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + + /* properties */ + ot->prop = prop = RNA_def_enum(ot->srna, "material", + DummyRNA_DEFAULT_items, 0, + "Material Preset", + "Type of material that objects are made of. " + "Determines material density"); + RNA_def_enum_funcs(prop, rigidbody_materials_itemf); + + RNA_def_float(ot->srna, "density", 1.0, FLT_MIN, FLT_MAX, + "Density", + "Custom density value (kg/m^3) to use instead of material preset", + 1.0f, 2500.0f); +} + +/* ********************************************** */ diff --git a/source/blender/editors/physics/rigidbody_world.c b/source/blender/editors/physics/rigidbody_world.c new file mode 100644 index 00000000000..5ab8e7697c5 --- /dev/null +++ b/source/blender/editors/physics/rigidbody_world.c @@ -0,0 +1,213 @@ +/* + * ***** 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) 2013 Blender Foundation + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): Joshua Leung, Sergej Reich + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file rigidbody_world.c + * \ingroup editor_physics + * \brief Rigid Body world editing operators + */ + +#include <stdlib.h> +#include <string.h> + +#include "DNA_object_types.h" +#include "DNA_rigidbody_types.h" +#include "DNA_scene_types.h" + +#include "BLI_blenlib.h" +#include "BLI_math.h" + +#ifdef WITH_BULLET +# include "RBI_api.h" +#endif + +#include "BKE_context.h" +#include "BKE_depsgraph.h" +#include "BKE_group.h" +#include "BKE_global.h" +#include "BKE_main.h" +#include "BKE_report.h" +#include "BKE_rigidbody.h" +#include "BKE_utildefines.h" + +#include "RNA_access.h" +#include "RNA_define.h" +#include "RNA_enum_types.h" + +#include "WM_api.h" +#include "WM_types.h" + +#include "ED_physics.h" +#include "ED_screen.h" + +#include "physics_intern.h" + +/* ********************************************** */ +/* API */ + +/* check if there is an active rigid body world */ +static int ED_rigidbody_world_active_poll(bContext *C) +{ + Scene *scene = CTX_data_scene(C); + return (scene && scene->rigidbody_world); +} +static int ED_rigidbody_world_add_poll(bContext *C) +{ + Scene *scene = CTX_data_scene(C); + return (scene && scene->rigidbody_world == NULL); +} + +/* ********************************************** */ +/* OPERATORS - Management */ + +/* ********** Add RigidBody World **************** */ + +static int rigidbody_world_add_exec(bContext *C, wmOperator *UNUSED(op)) +{ + Scene *scene = CTX_data_scene(C); + RigidBodyWorld *rbw; + + rbw = BKE_rigidbody_create_world(scene); +// BKE_rigidbody_validate_sim_world(scene, rbw, false); + scene->rigidbody_world = rbw; + + return OPERATOR_FINISHED; +} + +void RIGIDBODY_OT_world_add(wmOperatorType *ot) +{ + /* identifiers */ + ot->idname = "RIGIDBODY_OT_world_add"; + ot->name = "Add Rigid Body World"; + ot->description = "Add Rigid Body simulation world to the current scene"; + + /* callbacks */ + ot->exec = rigidbody_world_add_exec; + ot->poll = ED_rigidbody_world_add_poll; + + /* flags */ + ot->flag = OPTYPE_REGISTER|OPTYPE_UNDO; +} + +/* ********** Remove RigidBody World ************* */ + +static int rigidbody_world_remove_exec(bContext *C, wmOperator *op) +{ + Scene *scene = CTX_data_scene(C); + RigidBodyWorld *rbw = scene->rigidbody_world; + + /* sanity checks */ + if (ELEM(NULL, scene, rbw)) { + BKE_report(op->reports, RPT_ERROR, "No Rigid Body World to remove"); + return OPERATOR_CANCELLED; + } + + BKE_rigidbody_free_world(rbw); + scene->rigidbody_world = NULL; + + /* send updates */ + WM_event_add_notifier(C, NC_GROUP | NA_EDITED, NULL); + + /* done */ + return OPERATOR_FINISHED; +} + +void RIGIDBODY_OT_world_remove(wmOperatorType *ot) +{ + /* identifiers */ + ot->idname = "RIGIDBODY_OT_world_remove"; + ot->name = "Remove Rigid Body World"; + ot->description = "Remove Rigid Body simulation world from the current scene"; + + /* callbacks */ + ot->exec = rigidbody_world_remove_exec; + ot->poll = ED_rigidbody_world_active_poll; + + /* flags */ + ot->flag = OPTYPE_REGISTER|OPTYPE_UNDO; +} + +/* ********************************************** */ +/* UTILITY OPERATORS */ + +/* ********** Export RigidBody World ************* */ + +static int rigidbody_world_export_exec(bContext *C, wmOperator *op) +{ + Scene *scene = CTX_data_scene(C); + RigidBodyWorld *rbw = scene->rigidbody_world; + char path[FILE_MAX]; + + /* sanity checks */ + if ELEM(NULL, scene, rbw) { + BKE_report(op->reports, RPT_ERROR, "No Rigid Body World to export"); + return OPERATOR_CANCELLED; + } + if (rbw->physics_world == NULL) { + BKE_report(op->reports, RPT_ERROR, "Rigid Body World has no associated physics data to export"); + return OPERATOR_CANCELLED; + } + + RNA_string_get(op->ptr, "filepath", path); +#ifdef WITH_BULLET + RB_dworld_export(rbw->physics_world, path); +#endif + return OPERATOR_FINISHED; +} + +static int rigidbody_world_export_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(evt)) +{ + if (!RNA_struct_property_is_set(op->ptr, "relative_path")) + RNA_boolean_set(op->ptr, "relative_path", (U.flag & USER_RELPATHS)); + + if (RNA_struct_property_is_set(op->ptr, "filepath")) + return rigidbody_world_export_exec(C, op); + + // TODO: use the actual rigidbody world's name + .bullet instead of this temp crap + RNA_string_set(op->ptr, "filepath", "rigidbodyworld_export.bullet"); + WM_event_add_fileselect(C, op); + + return OPERATOR_RUNNING_MODAL; +} + +void RIGIDBODY_OT_world_export(wmOperatorType *ot) +{ + /* identifiers */ + ot->idname = "RIGIDBODY_OT_world_export"; + ot->name = "Export Rigid Body World"; + ot->description = "Export Rigid Body world to simulator's own fileformat (i.e. '.bullet' for Bullet Physics)"; + + /* callbacks */ + ot->invoke = rigidbody_world_export_invoke; + ot->exec = rigidbody_world_export_exec; + ot->poll = ED_rigidbody_world_active_poll; + + /* flags */ + ot->flag = OPTYPE_REGISTER|OPTYPE_UNDO; + + /* properties */ + WM_operator_properties_filesel(ot, FOLDERFILE, FILE_SPECIAL, FILE_SAVE, FILE_RELPATH, FILE_DEFAULTDISPLAY); +} diff --git a/source/blender/editors/render/render_internal.c b/source/blender/editors/render/render_internal.c index f8154f4abda..deb6eaf2c22 100644 --- a/source/blender/editors/render/render_internal.c +++ b/source/blender/editors/render/render_internal.c @@ -73,6 +73,7 @@ #include "render_intern.h" /* Render Callbacks */ +static int render_break(void *rjv); /* called inside thread! */ void image_buffer_rect_update(Scene *scene, RenderResult *rr, ImBuf *ibuf, volatile rcti *renrect) @@ -210,7 +211,7 @@ static int screen_render_exec(bContext *C, wmOperator *op) lay = (v3d) ? v3d->lay : scene->lay; G.is_break = FALSE; - RE_test_break_cb(re, NULL, (int (*)(void *))blender_test_break); + RE_test_break_cb(re, NULL, render_break); ima = BKE_image_verify_viewer(IMA_TYPE_R_RESULT, "Render Result"); BKE_image_signal(ima, NULL, IMA_SIGNAL_FREE); @@ -443,6 +444,15 @@ static int render_breakjob(void *rjv) return 0; } +/* for exec() when there is no render job + * note: this wont check for the escape key being pressed, but doing so isnt threadsafe */ +static int render_break(void *UNUSED(rjv)) +{ + if (G.is_break) + return 1; + return 0; +} + /* runs in thread, no cursor setting here works. careful with notifiers too (malloc conflicts) */ /* maybe need a way to get job send notifer? */ static void render_drawlock(void *UNUSED(rjv), int lock) diff --git a/source/blender/editors/render/render_update.c b/source/blender/editors/render/render_update.c index 38535eca918..16d7923baff 100644 --- a/source/blender/editors/render/render_update.c +++ b/source/blender/editors/render/render_update.c @@ -394,7 +394,14 @@ static void texture_changed(Main *bmain, Tex *tex) if (dm && totmaterial && material) { for (a = 0; a < *totmaterial; a++) { - if (material_uses_texture((*material)[a], tex)) { + Material *ma; + + if (ob->matbits && ob->matbits[a]) + ma = ob->mat[a]; + else + ma = (*material)[a]; + + if (ma && material_uses_texture(ma, tex)) { GPU_drawobject_free(dm); break; } diff --git a/source/blender/editors/screen/area.c b/source/blender/editors/screen/area.c index cea7b12a27d..8afe07b4689 100644 --- a/source/blender/editors/screen/area.c +++ b/source/blender/editors/screen/area.c @@ -1864,15 +1864,11 @@ void ED_region_info_draw(ARegion *ar, const char *text, int block, float alpha) /* background box */ ED_region_visible_rect(ar, &rect); - rect.xmin = 0; rect.ymin = BLI_rcti_size_y(&ar->winrct) - header_height; - if (block) { - rect.xmax = BLI_rcti_size_x(&ar->winrct); - } - else { - rect.xmax = rect.xmin + BLF_width(fontid, text) + 24; - } + /* box fill entire width or just around text */ + if (!block) + rect.xmax = min_ii(rect.xmax, rect.xmin + BLF_width(fontid, text) + 1.2f * U.widget_unit); rect.ymax = BLI_rcti_size_y(&ar->winrct); @@ -1884,8 +1880,13 @@ void ED_region_info_draw(ARegion *ar, const char *text, int block, float alpha) /* text */ UI_ThemeColor(TH_TEXT_HI); - BLF_position(fontid, 12, rect.ymin + 5, 0.0f); + BLF_clipping(fontid, rect.xmin, rect.ymin, rect.xmax, rect.ymax); + BLF_enable(fontid, BLF_CLIPPING); + BLF_position(fontid, rect.xmin + 0.6f * U.widget_unit, rect.ymin + 0.3f * U.widget_unit, 0.0f); + BLF_draw(fontid, text, BLF_DRAW_STR_DUMMY_MAX); + + BLF_disable(fontid, BLF_CLIPPING); } void ED_region_grid_draw(ARegion *ar, float zoomx, float zoomy) diff --git a/source/blender/editors/screen/glutil.c b/source/blender/editors/screen/glutil.c index f073fdd5125..105c2dc88d1 100644 --- a/source/blender/editors/screen/glutil.c +++ b/source/blender/editors/screen/glutil.c @@ -38,13 +38,12 @@ #include "BLI_rect.h" #include "BLI_utildefines.h" +#include "BLI_math.h" +#include "BLI_threads.h" #include "BKE_blender.h" #include "BKE_colortools.h" -#include "BLI_math.h" -#include "BLI_threads.h" - #include "BIF_gl.h" #include "BIF_glutil.h" diff --git a/source/blender/editors/screen/screendump.c b/source/blender/editors/screen/screendump.c index 2982e1f21af..1763e62582a 100644 --- a/source/blender/editors/screen/screendump.c +++ b/source/blender/editors/screen/screendump.c @@ -86,8 +86,8 @@ static unsigned int *screenshot(bContext *C, int *dumpsx, int *dumpsy) x = 0; y = 0; - *dumpsx = win->sizex; - *dumpsy = win->sizey; + *dumpsx = WM_window_pixels_x(win); + *dumpsy = WM_window_pixels_y(win); if (*dumpsx && *dumpsy) { @@ -457,8 +457,8 @@ static int screencast_exec(bContext *C, wmOperator *op) wmWindow *win = CTX_wm_window(C); sj->x = 0; sj->y = 0; - sj->dumpsx = win->sizex; - sj->dumpsy = win->sizey; + sj->dumpsx = WM_window_pixels_x(win); + sj->dumpsy = WM_window_pixels_y(win); } else { ScrArea *curarea = CTX_wm_area(C); diff --git a/source/blender/editors/sculpt_paint/paint_cursor.c b/source/blender/editors/sculpt_paint/paint_cursor.c index 5e23a144408..ffea5af74a3 100644 --- a/source/blender/editors/sculpt_paint/paint_cursor.c +++ b/source/blender/editors/sculpt_paint/paint_cursor.c @@ -43,6 +43,7 @@ #include "BKE_brush.h" #include "BKE_context.h" +#include "BKE_image.h" #include "BKE_paint.h" #include "WM_api.h" @@ -116,7 +117,7 @@ static void make_snap(Snapshot *snap, Brush *brush, ViewContext *vc) snap->winy = vc->ar->winy; } -static int load_tex(Sculpt *sd, Brush *br, ViewContext *vc) +static int load_tex(Brush *br, ViewContext *vc) { static GLuint overlay_texture = 0; static int init = 0; @@ -130,10 +131,6 @@ static int load_tex(Sculpt *sd, Brush *br, ViewContext *vc) int size; int j; int refresh; - -#ifndef _OPENMP - (void)sd; /* quied unused warning */ -#endif if (br->mtex.brush_map_mode == MTEX_MAP_MODE_TILED && !br->mtex.tex) return 0; @@ -147,6 +144,8 @@ static int load_tex(Sculpt *sd, Brush *br, ViewContext *vc) !same_snap(&snap, br, vc); if (refresh) { + struct ImagePool *pool = NULL; + if (br->mtex.tex && br->mtex.tex->preview) tex_changed_timestamp = br->mtex.tex->preview->changed_timestamp[0]; @@ -186,7 +185,10 @@ static int load_tex(Sculpt *sd, Brush *br, ViewContext *vc) buffer = MEM_mallocN(sizeof(GLubyte) * size * size, "load_tex"); - #pragma omp parallel for schedule(static) if (sd->flags & SCULPT_USE_OPENMP) + if (br->mtex.tex) + pool = BKE_image_pool_new(); + + #pragma omp parallel for schedule(static) for (j = 0; j < size; j++) { int i; float y; @@ -236,7 +238,7 @@ static int load_tex(Sculpt *sd, Brush *br, ViewContext *vc) x += br->mtex.ofs[0]; y += br->mtex.ofs[1]; - avg = br->mtex.tex ? paint_get_tex_pixel(br, x, y) : 1; + avg = br->mtex.tex ? paint_get_tex_pixel(br, x, y, pool) : 1; avg += br->texture_sample_bias; @@ -251,6 +253,9 @@ static int load_tex(Sculpt *sd, Brush *br, ViewContext *vc) } } + if (pool) + BKE_image_pool_free(pool); + if (!overlay_texture) glGenTextures(1, &overlay_texture); } @@ -376,7 +381,7 @@ static int sculpt_get_brush_geometry(bContext *C, ViewContext *vc, /* Draw an overlay that shows what effect the brush's texture will * have on brush strength */ /* TODO: sculpt only for now */ -static void paint_draw_alpha_overlay(Sculpt *sd, Brush *brush, +static void paint_draw_alpha_overlay(UnifiedPaintSettings *ups, Brush *brush, ViewContext *vc, int x, int y) { rctf quad; @@ -401,7 +406,7 @@ static void paint_draw_alpha_overlay(Sculpt *sd, Brush *brush, GL_VIEWPORT_BIT | GL_TEXTURE_BIT); - if (load_tex(sd, brush, vc)) { + if (load_tex(brush, vc)) { glEnable(GL_BLEND); glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); @@ -416,24 +421,24 @@ static void paint_draw_alpha_overlay(Sculpt *sd, Brush *brush, /* brush rotation */ glTranslatef(0.5, 0.5, 0); glRotatef((double)RAD2DEGF((brush->flag & BRUSH_RAKE) ? - sd->last_angle : sd->special_rotation), + ups->last_angle : ups->special_rotation), 0.0, 0.0, 1.0); glTranslatef(-0.5f, -0.5f, 0); /* scale based on tablet pressure */ - if (sd->draw_pressure && BKE_brush_use_size_pressure(vc->scene, brush)) { + if (ups->draw_pressure && BKE_brush_use_size_pressure(vc->scene, brush)) { glTranslatef(0.5f, 0.5f, 0); - glScalef(1.0f / sd->pressure_value, 1.0f / sd->pressure_value, 1); + glScalef(1.0f / ups->pressure_value, 1.0f / ups->pressure_value, 1); glTranslatef(-0.5f, -0.5f, 0); } - if (sd->draw_anchored) { - const float *aim = sd->anchored_initial_mouse; + if (ups->draw_anchored) { + const float *aim = ups->anchored_initial_mouse; const rcti *win = &vc->ar->winrct; - quad.xmin = aim[0] - sd->anchored_size - win->xmin; - quad.ymin = aim[1] - sd->anchored_size - win->ymin; - quad.xmax = aim[0] + sd->anchored_size - win->xmin; - quad.ymax = aim[1] + sd->anchored_size - win->ymin; + quad.xmin = aim[0] - ups->anchored_size - win->xmin; + quad.ymin = aim[1] - ups->anchored_size - win->ymin; + quad.xmax = aim[0] + ups->anchored_size - win->xmin; + quad.ymax = aim[1] + ups->anchored_size - win->ymin; } else { const int radius = BKE_brush_size_get(vc->scene, brush); @@ -476,7 +481,7 @@ static void paint_draw_alpha_overlay(Sculpt *sd, Brush *brush, /* Special actions taken when paint cursor goes over mesh */ /* TODO: sculpt only for now */ -static void paint_cursor_on_hit(Sculpt *sd, Brush *brush, ViewContext *vc, +static void paint_cursor_on_hit(UnifiedPaintSettings *ups, Brush *brush, ViewContext *vc, const float location[3]) { float unprojected_radius, projected_radius; @@ -484,8 +489,8 @@ static void paint_cursor_on_hit(Sculpt *sd, Brush *brush, ViewContext *vc, /* update the brush's cached 3D radius */ if (!BKE_brush_use_locked_size(vc->scene, brush)) { /* get 2D brush radius */ - if (sd->draw_anchored) - projected_radius = sd->anchored_size; + if (ups->draw_anchored) + projected_radius = ups->anchored_size; else { if (brush->flag & BRUSH_ANCHORED) projected_radius = 8; @@ -498,8 +503,8 @@ static void paint_cursor_on_hit(Sculpt *sd, Brush *brush, ViewContext *vc, projected_radius); /* scale 3D brush radius by pressure */ - if (sd->draw_pressure && BKE_brush_use_size_pressure(vc->scene, brush)) - unprojected_radius *= sd->pressure_value; + if (ups->draw_pressure && BKE_brush_use_size_pressure(vc->scene, brush)) + unprojected_radius *= ups->pressure_value; /* set cached value in either Brush or UnifiedPaintSettings */ BKE_brush_unprojected_radius_set(vc->scene, brush, unprojected_radius); @@ -509,6 +514,7 @@ static void paint_cursor_on_hit(Sculpt *sd, Brush *brush, ViewContext *vc, static void paint_draw_cursor(bContext *C, int x, int y, void *UNUSED(unused)) { Scene *scene = CTX_data_scene(C); + UnifiedPaintSettings *ups = &scene->toolsettings->unified_paint_settings; Paint *paint = paint_get_active_from_context(C); Brush *brush = paint_brush(paint); ViewContext vc; @@ -534,7 +540,6 @@ static void paint_draw_cursor(bContext *C, int x, int y, void *UNUSED(unused)) /* TODO: as sculpt and other paint modes are unified, this * special mode of drawing will go away */ if (vc.obact->sculpt) { - Sculpt *sd = CTX_data_tool_settings(C)->sculpt; float location[3]; int pixel_radius, hit; @@ -547,14 +552,14 @@ static void paint_draw_cursor(bContext *C, int x, int y, void *UNUSED(unused)) const float v = 1 - u; const float r = 20; - const float dx = sd->last_x - x; - const float dy = sd->last_y - y; + const float dx = ups->last_x - x; + const float dy = ups->last_y - y; if (dx * dx + dy * dy >= r * r) { - sd->last_angle = atan2(dx, dy); + ups->last_angle = atan2(dx, dy); - sd->last_x = u * sd->last_x + v * x; - sd->last_y = u * sd->last_y + v * y; + ups->last_x = u * ups->last_x + v * x; + ups->last_y = u * ups->last_y + v * y; } } @@ -562,7 +567,7 @@ static void paint_draw_cursor(bContext *C, int x, int y, void *UNUSED(unused)) hit = sculpt_get_brush_geometry(C, &vc, x, y, &pixel_radius, location); /* draw overlay */ - paint_draw_alpha_overlay(sd, brush, &vc, x, y); + paint_draw_alpha_overlay(ups, brush, &vc, x, y); if (BKE_brush_use_locked_size(scene, brush)) BKE_brush_size_set(scene, brush, pixel_radius); @@ -581,12 +586,12 @@ static void paint_draw_cursor(bContext *C, int x, int y, void *UNUSED(unused)) /* only do if brush is over the mesh */ if (hit) - paint_cursor_on_hit(sd, brush, &vc, location); + paint_cursor_on_hit(ups, brush, &vc, location); - if (sd->draw_anchored) { - final_radius = sd->anchored_size; - translation[0] = sd->anchored_initial_mouse[0] - vc.ar->winrct.xmin; - translation[1] = sd->anchored_initial_mouse[1] - vc.ar->winrct.ymin; + if (ups->draw_anchored) { + final_radius = ups->anchored_size; + translation[0] = ups->anchored_initial_mouse[0] - vc.ar->winrct.xmin; + translation[1] = ups->anchored_initial_mouse[1] - vc.ar->winrct.ymin; } } @@ -599,6 +604,14 @@ static void paint_draw_cursor(bContext *C, int x, int y, void *UNUSED(unused)) /* draw brush outline */ glTranslatef(translation[0], translation[1], 0); + + /* draw an inner brush */ + if (ups->draw_pressure && BKE_brush_use_size_pressure(scene, brush)) { + /* inner at full alpha */ + glutil_draw_lined_arc(0.0, M_PI * 2.0, final_radius * ups->pressure_value, 40); + /* outer at half alpha */ + glColor4f(outline_col[0], outline_col[1], outline_col[2], outline_alpha * 0.5f); + } glutil_draw_lined_arc(0.0, M_PI * 2.0, final_radius, 40); glTranslatef(-translation[0], -translation[1], 0); diff --git a/source/blender/editors/sculpt_paint/paint_image.c b/source/blender/editors/sculpt_paint/paint_image.c index d0f8e36e17d..c60097e20eb 100644 --- a/source/blender/editors/sculpt_paint/paint_image.c +++ b/source/blender/editors/sculpt_paint/paint_image.c @@ -316,7 +316,7 @@ typedef struct ProjPaintState { float normal_angle_range; /* difference between normal_angle and normal_angle_inner, for easy access */ short is_ortho; - short is_airbrush; /* only to avoid using (ps.brush->flag & BRUSH_AIRBRUSH) */ + bool do_masking; /* use masking during painting. Some operations such as airbrush may disable */ short is_texbrush; /* only to avoid running */ #ifndef PROJ_DEBUG_NOSEAMBLEED float seam_bleed_px; @@ -355,7 +355,7 @@ typedef union pixelStore { typedef struct ProjPixel { float projCoSS[2]; /* the floating point screen projection of this pixel */ - + float worldCoSS[3]; /* Only used when the airbrush is disabled. * Store the max mask value to avoid painting over an area with a lower opacity * with an advantage that we can avoid touching the pixel at all, if the @@ -1526,6 +1526,7 @@ static int project_paint_pixel_sizeof(const short tool) } } + /* run this function when we know a bucket's, face's pixel can be initialized, * return the ProjPixel which is added to 'ps->bucketRect[bucket_index]' */ static ProjPixel *project_paint_uvpixel_init( @@ -1537,6 +1538,7 @@ static ProjPixel *project_paint_uvpixel_init( const int face_index, const int image_index, const float pixelScreenCo[4], + const float world_spaceCo[3], const int side, const float w[3]) { @@ -1565,6 +1567,10 @@ static ProjPixel *project_paint_uvpixel_init( } /* screenspace unclamped, we could keep its z and w values but don't need them at the moment */ + if (ps->brush->mtex.brush_map_mode == MTEX_MAP_MODE_3D) { + copy_v3_v3(projPixel->worldCoSS, world_spaceCo); + } + copy_v2_v2(projPixel->projCoSS, pixelScreenCo); projPixel->x_px = x_px; @@ -2374,6 +2380,7 @@ static void project_paint_face_init(const ProjPaintState *ps, const int thread_i float *uv1co, *uv2co, *uv3co; /* for convenience only, these will be assigned to tf->uv[0],1,2 or tf->uv[0],2,3 */ float pixelScreenCo[4]; + bool do_3d_mapping = ps->brush->mtex.brush_map_mode == MTEX_MAP_MODE_3D; rcti bounds_px; /* ispace bounds */ /* vars for getting uvspace bounds */ @@ -2449,7 +2456,7 @@ static void project_paint_face_init(const ProjPaintState *ps, const int thread_i v1coSS = ps->screenCoords[(*(&mf->v1 + i1))]; v2coSS = ps->screenCoords[(*(&mf->v1 + i2))]; v3coSS = ps->screenCoords[(*(&mf->v1 + i3))]; - + /* This funtion gives is a concave polyline in UV space from the clipped quad and tri*/ project_bucket_clip_face( is_ortho, bucket_bounds, @@ -2501,9 +2508,9 @@ static void project_paint_face_init(const ProjPaintState *ps, const int thread_i else screen_px_from_persp(uv, v1coSS, v2coSS, v3coSS, uv1co, uv2co, uv3co, pixelScreenCo, w); /* a pity we need to get the worldspace pixel location here */ - if (do_clip) { + if (do_clip || do_3d_mapping) { interp_v3_v3v3v3(wco, ps->dm_mvert[(*(&mf->v1 + i1))].co, ps->dm_mvert[(*(&mf->v1 + i2))].co, ps->dm_mvert[(*(&mf->v1 + i3))].co, w); - if (ED_view3d_clipping_test(ps->rv3d, wco, TRUE)) { + if (do_clip && ED_view3d_clipping_test(ps->rv3d, wco, TRUE)) { continue; /* Watch out that no code below this needs to run */ } } @@ -2514,13 +2521,13 @@ static void project_paint_face_init(const ProjPaintState *ps, const int thread_i if ((ps->do_occlude == FALSE) || !project_bucket_point_occluded(ps, bucketFaceNodes, face_index, pixelScreenCo)) { - mask = project_paint_uvpixel_mask(ps, face_index, side, w); - + if (mask > 0.0f) { BLI_linklist_prepend_arena( bucketPixelNodes, - project_paint_uvpixel_init(ps, arena, ibuf, x, y, mask, face_index, image_index, pixelScreenCo, side, w), + project_paint_uvpixel_init(ps, arena, ibuf, x, y, mask, face_index, + image_index, pixelScreenCo, wco, side, w), arena ); } @@ -2725,11 +2732,11 @@ static void project_paint_face_init(const ProjPaintState *ps, const int thread_i } /* a pity we need to get the worldspace pixel location here */ - if (do_clip) { + if (do_clip || do_3d_mapping) { if (side) interp_v3_v3v3v3(wco, ps->dm_mvert[mf->v1].co, ps->dm_mvert[mf->v3].co, ps->dm_mvert[mf->v4].co, w); else interp_v3_v3v3v3(wco, ps->dm_mvert[mf->v1].co, ps->dm_mvert[mf->v2].co, ps->dm_mvert[mf->v3].co, w); - if (ED_view3d_clipping_test(ps->rv3d, wco, TRUE)) { + if (do_clip && ED_view3d_clipping_test(ps->rv3d, wco, TRUE)) { continue; /* Watch out that no code below this needs to run */ } } @@ -2739,7 +2746,7 @@ static void project_paint_face_init(const ProjPaintState *ps, const int thread_i if (mask > 0.0f) { BLI_linklist_prepend_arena( bucketPixelNodes, - project_paint_uvpixel_init(ps, arena, ibuf, x, y, mask, face_index, image_index, pixelScreenCo, side, w), + project_paint_uvpixel_init(ps, arena, ibuf, x, y, mask, face_index, image_index, pixelScreenCo, wco, side, w), arena ); } @@ -3749,6 +3756,8 @@ typedef struct ProjectHandle { /* thread settings */ int thread_index; + + struct ImagePool *pool; } ProjectHandle; static void blend_color_mix(unsigned char cp[4], const unsigned char cp1[4], const unsigned char cp2[4], const int fac) @@ -3800,7 +3809,7 @@ static void blend_color_mix_accum_float(float cp[4], const float cp1[4], const u static void do_projectpaint_clone(ProjPaintState *ps, ProjPixel *projPixel, float alpha, float mask) { - if (ps->is_airbrush == 0 && mask < 1.0f) { + if (ps->do_masking && mask < 1.0f) { projPixel->newColor.uint = IMB_blend_color(projPixel->newColor.uint, ((ProjPixelClone *)projPixel)->clonepx.uint, (int)(alpha * 255), ps->blend); blend_color_mix(projPixel->pixel.ch_pt, projPixel->origColor.ch, projPixel->newColor.ch, (int)(mask * 255)); } @@ -3811,7 +3820,7 @@ static void do_projectpaint_clone(ProjPaintState *ps, ProjPixel *projPixel, floa static void do_projectpaint_clone_f(ProjPaintState *ps, ProjPixel *projPixel, float alpha, float mask) { - if (ps->is_airbrush == 0 && mask < 1.0f) { + if (ps->do_masking && mask < 1.0f) { IMB_blend_color_float(projPixel->newColor.f, projPixel->newColor.f, ((ProjPixelClone *)projPixel)->clonepx.f, alpha, ps->blend); blend_color_mix_float(projPixel->pixel.f_pt, projPixel->origColor.f, projPixel->newColor.f, mask); } @@ -3946,7 +3955,7 @@ static void do_projectpaint_draw(ProjPaintState *ps, ProjPixel *projPixel, const rgba_ub[3] = 255; } - if (ps->is_airbrush == 0 && mask < 1.0f) { + if (ps->do_masking && mask < 1.0f) { projPixel->newColor.uint = IMB_blend_color(projPixel->newColor.uint, *((unsigned int *)rgba_ub), (int)(alpha * 255), ps->blend); blend_color_mix(projPixel->pixel.ch_pt, projPixel->origColor.ch, projPixel->newColor.ch, (int)(mask * 255)); } @@ -3978,7 +3987,7 @@ static void do_projectpaint_draw_f(ProjPaintState *ps, ProjPixel *projPixel, flo rgba[3] = 1.0; } - if (ps->is_airbrush == 0 && mask < 1.0f) { + if (ps->do_masking && mask < 1.0f) { IMB_blend_color_float(projPixel->newColor.f, projPixel->newColor.f, rgba, alpha, ps->blend); blend_color_mix_float(projPixel->pixel.f_pt, projPixel->origColor.f, projPixel->newColor.f, mask); } @@ -3998,10 +4007,12 @@ static void *do_projectpaint_thread(void *ph_v) const float *lastpos = ((ProjectHandle *)ph_v)->prevmval; const float *pos = ((ProjectHandle *)ph_v)->mval; const int thread_index = ((ProjectHandle *)ph_v)->thread_index; + struct ImagePool *pool = ((ProjectHandle *)ph_v)->pool; /* Done with args from ProjectHandle */ LinkNode *node; ProjPixel *projPixel; + Brush *brush = ps->brush; int last_index = -1; ProjPaintImage *last_projIma = NULL; @@ -4021,10 +4032,10 @@ static void *do_projectpaint_thread(void *ph_v) float co[2]; float mask = 1.0f; /* airbrush wont use mask */ unsigned short mask_short; - const float radius = (float)BKE_brush_size_get(ps->scene, ps->brush); + const float radius = (float)BKE_brush_size_get(ps->scene, brush); const float radius_squared = radius * radius; /* avoid a square root with every dist comparison */ - short lock_alpha = ELEM(ps->brush->blend, IMB_BLEND_ERASE_ALPHA, IMB_BLEND_ADD_ALPHA) ? 0 : ps->brush->flag & BRUSH_LOCK_ALPHA; + short lock_alpha = ELEM(brush->blend, IMB_BLEND_ERASE_ALPHA, IMB_BLEND_ADD_ALPHA) ? 0 : brush->flag & BRUSH_LOCK_ALPHA; LinkNode *smearPixels = NULL; LinkNode *smearPixels_f = NULL; @@ -4105,23 +4116,36 @@ static void *do_projectpaint_thread(void *ph_v) /*if (dist < radius) {*/ /* correct but uses a sqrtf */ if (dist_nosqrt <= radius_squared) { + float samplecos[3]; dist = sqrtf(dist_nosqrt); falloff = BKE_brush_curve_strength_clamp(ps->brush, dist, radius); + if (ps->is_texbrush) { + MTex *mtex = &brush->mtex; + if (mtex->brush_map_mode == MTEX_MAP_MODE_VIEW) { + sub_v2_v2v2(samplecos, projPixel->projCoSS, pos); + } + /* taking 3d copy to account for 3D mapping too. It gets concatenated during sampling */ + else if (mtex->brush_map_mode == MTEX_MAP_MODE_3D) + copy_v3_v3(samplecos, projPixel->worldCoSS); + else + copy_v3_v3(samplecos, projPixel->projCoSS); + } + if (falloff > 0.0f) { if (ps->is_texbrush) { /* note, for clone and smear, we only use the alpha, could be a special function */ - BKE_brush_sample_tex(ps->scene, ps->brush, projPixel->projCoSS, rgba, thread_index); + BKE_brush_sample_tex(ps->scene, brush, samplecos, rgba, thread_index, pool); alpha = rgba[3]; } else { alpha = 1.0f; } - if (ps->is_airbrush) { + if (!ps->do_masking) { /* for an aurbrush there is no real mask, so just multiply the alpha by it */ - alpha *= falloff * BKE_brush_alpha_get(ps->scene, ps->brush); + alpha *= falloff * BKE_brush_alpha_get(ps->scene, brush); mask = ((float)projPixel->mask) / 65535.0f; } else { @@ -4129,7 +4153,7 @@ static void *do_projectpaint_thread(void *ph_v) falloff = 1.0f - falloff; falloff = 1.0f - (falloff * falloff); - mask_short = (unsigned short)(projPixel->mask * (BKE_brush_alpha_get(ps->scene, ps->brush) * falloff)); + mask_short = (unsigned short)(projPixel->mask * (BKE_brush_alpha_get(ps->scene, brush) * falloff)); if (mask_short > projPixel->mask_max) { mask = ((float)mask_short) / 65535.0f; projPixel->mask_max = mask_short; @@ -4248,6 +4272,8 @@ static int project_paint_op(void *state, ImBuf *UNUSED(ibufb), const float lastp ListBase threads; int a, i; + struct ImagePool *pool; + if (!project_bucket_iter_init(ps, pos)) { return 0; } @@ -4255,6 +4281,8 @@ static int project_paint_op(void *state, ImBuf *UNUSED(ibufb), const float lastp if (ps->thread_tot > 1) BLI_init_threads(&threads, do_projectpaint_thread, ps->thread_tot); + pool = BKE_image_pool_new(); + /* get the threads running */ for (a = 0; a < ps->thread_tot; a++) { @@ -4278,6 +4306,8 @@ static int project_paint_op(void *state, ImBuf *UNUSED(ibufb), const float lastp memcpy(handles[a].projImages[i].partRedrawRect, ps->projImages[i].partRedrawRect, sizeof(ImagePaintPartialRedraw) * PROJ_BOUNDBOX_SQUARED); } + handles[a].pool = pool; + if (ps->thread_tot > 1) BLI_insert_thread(&threads, &handles[a]); } @@ -4288,6 +4318,8 @@ static int project_paint_op(void *state, ImBuf *UNUSED(ibufb), const float lastp do_projectpaint_thread(&handles[0]); + BKE_image_pool_free(pool); + /* move threaded bounds back into ps->projectPartialRedraws */ for (i = 0; i < ps->image_tot; i++) { int touch = 0; @@ -4714,6 +4746,7 @@ static int imapaint_canvas_set(ImagePaintState *s, Image *ima) if (!ima || !ibuf || !(ibuf->rect || ibuf->rect_float)) { BKE_image_release_ibuf(ima, ibuf, NULL); + BKE_image_release_ibuf(s->image, s->canvas, NULL); return 0; } @@ -4955,7 +4988,6 @@ typedef struct PaintOperation { int first; int prevmouse[2]; - float prev_pressure; /* need this since we don't get tablet events for pressure change */ int orig_brush_size; double starttime; @@ -4998,7 +5030,9 @@ static void project_state_init(bContext *C, Object *ob, ProjPaintState *ps) ps->pixel_sizeof = project_paint_pixel_sizeof(ps->tool); BLI_assert(ps->pixel_sizeof >= sizeof(ProjPixel)); - ps->is_airbrush = (brush->flag & BRUSH_AIRBRUSH) ? 1 : 0; + /* disable for 3d mapping also because painting on mirrored mesh can create "stripes" */ + ps->do_masking = (brush->flag & BRUSH_AIRBRUSH || brush->mtex.brush_map_mode == MTEX_MAP_MODE_VIEW || + brush->mtex.brush_map_mode == MTEX_MAP_MODE_3D) ? false : true; ps->is_texbrush = (brush->mtex.tex) ? 1 : 0; @@ -5173,6 +5207,11 @@ static int texture_paint_init(bContext *C, wmOperator *op) /* create painter */ pop->painter = BKE_brush_painter_new(scene, pop->s.brush); + { + UnifiedPaintSettings *ups = &settings->unified_paint_settings; + ups->draw_pressure = true; + } + return 1; } @@ -5261,6 +5300,11 @@ static void paint_exit(bContext *C, wmOperator *op) BKE_reportf(op->reports, RPT_WARNING, "Packed MultiLayer files cannot be painted: %s", pop->s.warnpackedfile); MEM_freeN(pop); + + { + UnifiedPaintSettings *ups = &scene->toolsettings->unified_paint_settings; + ups->draw_pressure = false; + } } static int paint_exec(bContext *C, wmOperator *op) @@ -5285,7 +5329,6 @@ static void paint_apply_event(bContext *C, wmOperator *op, wmEvent *event) { const Scene *scene = CTX_data_scene(C); PaintOperation *pop = op->customdata; - wmTabletData *wmtab; PointerRNA itemptr; float pressure, mousef[2]; double time; @@ -5296,16 +5339,17 @@ static void paint_apply_event(bContext *C, wmOperator *op, wmEvent *event) tablet = 0; pop->s.blend = pop->s.brush->blend; - if (event->custom == EVT_DATA_TABLET) { - wmtab = event->customdata; + if (event->tablet_data) { + wmTabletData *wmtab = event->tablet_data; tablet = (wmtab->Active != EVT_TABLET_NONE); pressure = wmtab->Pressure; if (wmtab->Active == EVT_TABLET_ERASER) pop->s.blend = IMB_BLEND_ERASE_ALPHA; } - else { /* otherwise airbrush becomes 1.0 pressure instantly */ - pressure = pop->prev_pressure ? pop->prev_pressure : 1.0f; + else { + BLI_assert(fabsf(WM_cursor_pressure(CTX_wm_window(C))) == 1.0f); + pressure = 1.0f; } if (pop->first) { @@ -5338,7 +5382,10 @@ static void paint_apply_event(bContext *C, wmOperator *op, wmEvent *event) /* apply */ paint_apply(C, op, &itemptr); - pop->prev_pressure = pressure; + { + UnifiedPaintSettings *ups = &scene->toolsettings->unified_paint_settings; + ups->pressure_value = pressure; + } } static int paint_invoke(bContext *C, wmOperator *op, wmEvent *event) @@ -5349,7 +5396,7 @@ static int paint_invoke(bContext *C, wmOperator *op, wmEvent *event) MEM_freeN(op->customdata); return OPERATOR_CANCELLED; } - + paint_apply_event(C, op, event); pop = op->customdata; @@ -5479,6 +5526,16 @@ static void brush_drawcursor(bContext *C, int x, int y, void *UNUSED(customdata) glColor4f(brush->add_col[0], brush->add_col[1], brush->add_col[2], alpha); glEnable(GL_LINE_SMOOTH); glEnable(GL_BLEND); + { + UnifiedPaintSettings *ups = &scene->toolsettings->unified_paint_settings; + /* hrmf, duplicate paint_draw_cursor logic here */ + if (ups->draw_pressure && BKE_brush_use_size_pressure(scene, brush)) { + /* inner at full alpha */ + glutil_draw_lined_arc(0, (float)(M_PI * 2.0), size * ups->pressure_value, 40); + /* outer at half alpha */ + glColor4f(brush->add_col[0], brush->add_col[1], brush->add_col[2], alpha * 0.5f); + } + } glutil_draw_lined_arc(0, (float)(M_PI * 2.0), size, 40); glDisable(GL_BLEND); glDisable(GL_LINE_SMOOTH); @@ -5953,7 +6010,7 @@ static int texture_paint_camera_project_exec(bContext *C, wmOperator *op) /* override */ ps.is_texbrush = 0; - ps.is_airbrush = 1; + ps.do_masking = false; orig_brush_size = BKE_brush_size_get(scene, ps.brush); BKE_brush_size_set(scene, ps.brush, 32); /* cover the whole image */ diff --git a/source/blender/editors/sculpt_paint/paint_image_2d.c b/source/blender/editors/sculpt_paint/paint_image_2d.c index dd7412cf3d5..0b76c88df66 100644 --- a/source/blender/editors/sculpt_paint/paint_image_2d.c +++ b/source/blender/editors/sculpt_paint/paint_image_2d.c @@ -205,7 +205,7 @@ static void brush_painter_do_partial(BrushPainter *painter, ImBuf *oldtexibuf, xy[0] = x + xoff; xy[1] = y + yoff; - BKE_brush_sample_tex(scene, brush, xy, tf, 0); + BKE_brush_sample_tex_2D(scene, brush, xy, tf, 0); } bf[0] = tf[0] * mf[0]; @@ -236,7 +236,7 @@ static void brush_painter_do_partial(BrushPainter *painter, ImBuf *oldtexibuf, xy[0] = x + xoff; xy[1] = y + yoff; - BKE_brush_sample_tex(scene, brush, xy, rgba, 0); + BKE_brush_sample_tex_2D(scene, brush, xy, rgba, 0); rgba_float_to_uchar(t, rgba); } @@ -314,6 +314,7 @@ static void brush_painter_refresh_cache(BrushPainter *painter, const float pos[2 short flt; const int diameter = 2 * BKE_brush_size_get(scene, brush); const float alpha = BKE_brush_alpha_get(scene, brush); + const bool do_tiled = ELEM(brush->mtex.brush_map_mode, MTEX_MAP_MODE_TILED, MTEX_MAP_MODE_3D); if (diameter != cache->lastsize || alpha != cache->lastalpha || @@ -331,7 +332,7 @@ static void brush_painter_refresh_cache(BrushPainter *painter, const float pos[2 flt = cache->flt; size = (cache->size) ? cache->size : diameter; - if (brush->flag & BRUSH_FIXED_TEX) { + if (do_tiled) { BKE_brush_imbuf_new(scene, brush, flt, 3, size, &cache->maskibuf, use_color_correction); brush_painter_fixed_tex_partial_update(painter, pos); } @@ -342,7 +343,7 @@ static void brush_painter_refresh_cache(BrushPainter *painter, const float pos[2 cache->lastalpha = alpha; cache->lastjitter = brush->jitter; } - else if ((brush->flag & BRUSH_FIXED_TEX) && mtex && mtex->tex) { + else if (do_tiled && mtex && mtex->tex) { int dx = (int)painter->lastpaintpos[0] - (int)pos[0]; int dy = (int)painter->lastpaintpos[1] - (int)pos[1]; @@ -539,7 +540,7 @@ unsigned int *BKE_brush_gen_texture_cache(Brush *br, int half_side) co[2] = 0.0f; /* This is copied from displace modifier code */ - hasrgb = multitex_ext(mtex->tex, co, NULL, NULL, 0, &texres); + hasrgb = multitex_ext(mtex->tex, co, NULL, NULL, 0, &texres, NULL); /* if the texture gave an RGB value, we assume it didn't give a valid * intensity, so calculate one (formula from do_material_tex). diff --git a/source/blender/editors/sculpt_paint/paint_intern.h b/source/blender/editors/sculpt_paint/paint_intern.h index cf55c93efe4..faa9ce00da8 100644 --- a/source/blender/editors/sculpt_paint/paint_intern.h +++ b/source/blender/editors/sculpt_paint/paint_intern.h @@ -36,6 +36,7 @@ struct ARegion; struct bContext; struct bglMats; struct Brush; +struct ImagePool; struct ListBase; struct Mesh; struct Object; @@ -61,7 +62,8 @@ struct PaintStroke *paint_stroke_new(struct bContext *C, StrokeUpdateStep update_step, StrokeDone done, int event_type); void paint_stroke_data_free(struct wmOperator *op); -int paint_space_stroke_enabled(struct Brush *br); +bool paint_space_stroke_enabled(struct Brush *br); +bool paint_supports_dynamic_size(struct Brush *br); struct wmKeyMap *paint_stroke_modal_keymap(struct wmKeyConfig *keyconf); int paint_stroke_modal(struct bContext *C, struct wmOperator *op, struct wmEvent *event); @@ -139,7 +141,7 @@ void paint_calc_redraw_planes(float planes[4][4], void projectf(struct bglMats *mats, const float v[3], float p[2]); float paint_calc_object_space_radius(struct ViewContext *vc, const float center[3], float pixel_radius); -float paint_get_tex_pixel(struct Brush *br, float u, float v); +float paint_get_tex_pixel(struct Brush *br, float u, float v, struct ImagePool *pool); int imapaint_pick_face(struct ViewContext *vc, const int mval[2], unsigned int *index, unsigned int totface); void imapaint_pick_uv(struct Scene *scene, struct Object *ob, unsigned int faceindex, const int xy[2], float uv[2]); diff --git a/source/blender/editors/sculpt_paint/paint_ops.c b/source/blender/editors/sculpt_paint/paint_ops.c index e5d6a1820a2..618d545b084 100644 --- a/source/blender/editors/sculpt_paint/paint_ops.c +++ b/source/blender/editors/sculpt_paint/paint_ops.c @@ -681,6 +681,7 @@ void ED_keymap_paint(wmKeyConfig *keyconf) keymap_brush_select(keymap, OB_MODE_SCULPT, SCULPT_TOOL_FLATTEN, TKEY, KM_SHIFT); keymap_brush_select(keymap, OB_MODE_SCULPT, SCULPT_TOOL_CLAY, CKEY, 0); keymap_brush_select(keymap, OB_MODE_SCULPT, SCULPT_TOOL_CREASE, CKEY, KM_SHIFT); + keymap_brush_select(keymap, OB_MODE_SCULPT, SCULPT_TOOL_SNAKE_HOOK, KKEY, 0); kmi = keymap_brush_select(keymap, OB_MODE_SCULPT, SCULPT_TOOL_MASK, MKEY, 0); RNA_boolean_set(kmi->ptr, "toggle", 1); RNA_boolean_set(kmi->ptr, "create_missing", 1); diff --git a/source/blender/editors/sculpt_paint/paint_stroke.c b/source/blender/editors/sculpt_paint/paint_stroke.c index 2f4115dcd94..5d9313485d2 100644 --- a/source/blender/editors/sculpt_paint/paint_stroke.c +++ b/source/blender/editors/sculpt_paint/paint_stroke.c @@ -125,8 +125,8 @@ static float event_tablet_data(wmEvent *event, int *pen_flip) int erasor = 0; float pressure = 1; - if (event->custom == EVT_DATA_TABLET) { - wmTabletData *wmtab = event->customdata; + if (event->tablet_data) { + wmTabletData *wmtab = event->tablet_data; erasor = (wmtab->Active == EVT_TABLET_ERASER); pressure = (wmtab->Active != EVT_TABLET_NONE) ? wmtab->Pressure : 1; @@ -324,10 +324,15 @@ static void stroke_done(struct bContext *C, struct wmOperator *op) } /* Returns zero if the stroke dots should not be spaced, non-zero otherwise */ -int paint_space_stroke_enabled(Brush *br) +bool paint_space_stroke_enabled(Brush *br) { - return (br->flag & BRUSH_SPACE) && - !(br->flag & BRUSH_ANCHORED) && + return (br->flag & BRUSH_SPACE) && paint_supports_dynamic_size(br); +} + +/* return true if the brush size can change during paint (normally used for pressure) */ +bool paint_supports_dynamic_size(Brush *br) +{ + return !(br->flag & BRUSH_ANCHORED) && !ELEM4(br->sculpt_tool, SCULPT_TOOL_GRAB, SCULPT_TOOL_THUMB, SCULPT_TOOL_ROTATE, SCULPT_TOOL_SNAKE_HOOK); } diff --git a/source/blender/editors/sculpt_paint/paint_utils.c b/source/blender/editors/sculpt_paint/paint_utils.c index e7d13bd080d..4f156276aac 100644 --- a/source/blender/editors/sculpt_paint/paint_utils.c +++ b/source/blender/editors/sculpt_paint/paint_utils.c @@ -173,13 +173,13 @@ float paint_calc_object_space_radius(ViewContext *vc, const float center[3], return len_v3(delta) / scale; } -float paint_get_tex_pixel(Brush *br, float u, float v) +float paint_get_tex_pixel(Brush *br, float u, float v, struct ImagePool *pool) { TexResult texres = {0}; float co[3] = {u, v, 0.0f}; int hasrgb; - hasrgb = multitex_ext(br->mtex.tex, co, NULL, NULL, 0, &texres); + hasrgb = multitex_ext(br->mtex.tex, co, NULL, NULL, 0, &texres, pool); if (hasrgb & TEX_RGB) texres.tin = rgb_to_grayscale(&texres.tr) * texres.ta; diff --git a/source/blender/editors/sculpt_paint/paint_vertex.c b/source/blender/editors/sculpt_paint/paint_vertex.c index 08c26aaa755..5b04bdb8ee7 100644 --- a/source/blender/editors/sculpt_paint/paint_vertex.c +++ b/source/blender/editors/sculpt_paint/paint_vertex.c @@ -2172,6 +2172,11 @@ static int wpaint_stroke_test_start(bContext *C, wmOperator *op, const float UNU if (me->editflag & ME_EDIT_MIRROR_X) { wpd->vgroup_mirror = wpaint_mirror_vgroup_ensure(ob, wpd->vgroup_active); } + + { + UnifiedPaintSettings *ups = &ts->unified_paint_settings; + ups->draw_pressure = true; + } return TRUE; } @@ -2414,6 +2419,11 @@ static void wpaint_stroke_update_step(bContext *C, struct PaintStroke *stroke, P swap_m4m4(vc->rv3d->persmat, mat); + { + UnifiedPaintSettings *ups = &ts->unified_paint_settings; + ups->pressure_value = pressure; + } + DAG_id_tag_update(ob->data, 0); ED_region_tag_redraw(vc->ar); } @@ -2454,7 +2464,12 @@ static void wpaint_stroke_done(const bContext *C, struct PaintStroke *stroke) } } } - + + { + UnifiedPaintSettings *ups = &ts->unified_paint_settings; + ups->draw_pressure = false; + } + DAG_id_tag_update(ob->data, 0); WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob); @@ -2583,9 +2598,8 @@ static int set_vpaint(bContext *C, wmOperator *op) /* toggle */ BKE_paint_init(&vp->paint, PAINT_CURSOR_VERTEX_PAINT); } - if (me) - /* update modifier stack for mapping requirements */ - DAG_id_tag_update(&me->id, 0); + /* update modifier stack for mapping requirements */ + DAG_id_tag_update(&me->id, 0); WM_event_add_notifier(C, NC_SCENE | ND_MODE, scene); @@ -2735,6 +2749,11 @@ static int vpaint_stroke_test_start(bContext *C, struct wmOperator *op, const fl invert_m4_m4(imat, mat); copy_m3_m4(vpd->vpimat, imat); + { + UnifiedPaintSettings *ups = &ts->unified_paint_settings; + ups->draw_pressure = true; + } + return 1; } @@ -2889,6 +2908,11 @@ static void vpaint_stroke_update_step(bContext *C, struct PaintStroke *stroke, P do_shared_vertexcol(me, do_tessface); } + { + UnifiedPaintSettings *ups = &ts->unified_paint_settings; + ups->pressure_value = pressure; + } + ED_region_tag_redraw(vc->ar); if (vpd->use_fast_update == FALSE) { @@ -2920,6 +2944,11 @@ static void vpaint_stroke_done(const bContext *C, struct PaintStroke *stroke) BLI_memarena_free(vpd->polyfacemap_arena); } + { + UnifiedPaintSettings *ups = &ts->unified_paint_settings; + ups->draw_pressure = false; + } + WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob); MEM_freeN(vpd); diff --git a/source/blender/editors/sculpt_paint/sculpt.c b/source/blender/editors/sculpt_paint/sculpt.c index 2dc4176dde3..ce7d72f9787 100644 --- a/source/blender/editors/sculpt_paint/sculpt.c +++ b/source/blender/editors/sculpt_paint/sculpt.c @@ -56,6 +56,7 @@ #include "BKE_cdderivedmesh.h" #include "BKE_context.h" #include "BKE_depsgraph.h" +#include "BKE_image.h" #include "BKE_key.h" #include "BKE_library.h" #include "BKE_mesh.h" @@ -430,7 +431,11 @@ static void paint_mesh_restore_co(Sculpt *sd, Object *ob) BKE_pbvh_search_gather(ss->pbvh, NULL, NULL, &nodes, &totnode); - #pragma omp parallel for schedule(guided) if (sd->flags & SCULPT_USE_OPENMP) + /* Disable OpenMP when dynamic-topology is enabled. Otherwise, new + * entries might be inserted by sculpt_undo_push_node() into the + * GHash used internally by BM_log_original_vert_co() by a + * different thread. [#33787] */ + #pragma omp parallel for schedule(guided) if (sd->flags & SCULPT_USE_OPENMP && !ss->bm) for (n = 0; n < totnode; n++) { SculptUndoNode *unode; SculptUndoType type = (brush->sculpt_tool == SCULPT_TOOL_MASK ? @@ -893,7 +898,7 @@ static float tex_strength(SculptSession *ss, Brush *br, /* Get strength by feeding the vertex * location directly into a texture */ externtex(mtex, point, &avg, - &jnk, &jnk, &jnk, &jnk, 0); + &jnk, &jnk, &jnk, &jnk, 0, ss->tex_pool); } else if (ss->texcache) { float rotation = -mtex->rot; @@ -979,7 +984,7 @@ static float tex_strength(SculptSession *ss, Brush *br, x += br->mtex.ofs[0]; y += br->mtex.ofs[1]; - avg = paint_get_tex_pixel(br, x, y); + avg = paint_get_tex_pixel(br, x, y, ss->tex_pool); } avg += br->texture_sample_bias; @@ -3372,11 +3377,17 @@ static void sculpt_update_tex(const Scene *scene, Sculpt *sd, SculptSession *ss) ss->texcache = NULL; } + if (ss->tex_pool) { + BKE_image_pool_free(ss->tex_pool); + ss->tex_pool = NULL; + } + /* Need to allocate a bigger buffer for bigger brush size */ ss->texcache_side = 2 * radius; if (!ss->texcache || ss->texcache_side > ss->texcache_actual) { ss->texcache = BKE_brush_gen_texture_cache(brush, radius); ss->texcache_actual = ss->texcache_side; + ss->tex_pool = BKE_image_pool_new(); } } @@ -3654,6 +3665,7 @@ static void sculpt_omp_done(SculptSession *ss) static void sculpt_update_cache_invariants(bContext *C, Sculpt *sd, SculptSession *ss, wmOperator *op, const float mouse[2]) { StrokeCache *cache = MEM_callocN(sizeof(StrokeCache), "stroke cache"); + UnifiedPaintSettings *ups = &CTX_data_tool_settings(C)->unified_paint_settings; Brush *brush = paint_brush(&sd->paint); ViewContext *vc = paint_stroke_view_context(op->customdata); Object *ob = CTX_data_active_object(C); @@ -3762,7 +3774,7 @@ static void sculpt_update_cache_invariants(bContext *C, Sculpt *sd, SculptSessio } } - cache->special_rotation = (brush->flag & BRUSH_RAKE) ? sd->last_angle : 0; + cache->special_rotation = (brush->flag & BRUSH_RAKE) ? ups->last_angle : 0; cache->first_time = 1; @@ -3771,7 +3783,7 @@ static void sculpt_update_cache_invariants(bContext *C, Sculpt *sd, SculptSessio sculpt_omp_start(sd, ss); } -static void sculpt_update_brush_delta(Sculpt *sd, Object *ob, Brush *brush) +static void sculpt_update_brush_delta(UnifiedPaintSettings *ups, Object *ob, Brush *brush) { SculptSession *ss = ob->sculpt; StrokeCache *cache = ss->cache; @@ -3836,17 +3848,17 @@ static void sculpt_update_brush_delta(Sculpt *sd, Object *ob, Brush *brush) copy_v3_v3(cache->old_grab_location, grab_location); if (tool == SCULPT_TOOL_GRAB) - copy_v3_v3(sd->anchored_location, cache->true_location); + copy_v3_v3(ups->anchored_location, cache->true_location); else if (tool == SCULPT_TOOL_THUMB) - copy_v3_v3(sd->anchored_location, cache->orig_grab_location); + copy_v3_v3(ups->anchored_location, cache->orig_grab_location); if (ELEM(tool, SCULPT_TOOL_GRAB, SCULPT_TOOL_THUMB)) { /* location stays the same for finding vertices in brush radius */ copy_v3_v3(cache->true_location, cache->orig_grab_location); - sd->draw_anchored = 1; - copy_v2_v2(sd->anchored_initial_mouse, cache->initial_mouse); - sd->anchored_size = cache->pixel_radius; + ups->draw_anchored = 1; + copy_v2_v2(ups->anchored_initial_mouse, cache->initial_mouse); + ups->anchored_size = cache->pixel_radius; } } } @@ -3857,6 +3869,7 @@ static void sculpt_update_cache_variants(bContext *C, Sculpt *sd, Object *ob, PointerRNA *ptr) { Scene *scene = CTX_data_scene(C); + UnifiedPaintSettings *ups = &scene->toolsettings->unified_paint_settings; SculptSession *ss = ob->sculpt; StrokeCache *cache = ss->cache; Brush *brush = paint_brush(&sd->paint); @@ -3880,13 +3893,14 @@ static void sculpt_update_cache_variants(bContext *C, Sculpt *sd, Object *ob, * brush coord/pressure/etc. * It's more an events design issue, which doesn't split coordinate/pressure/angle * changing events. We should avoid this after events system re-design */ - if (paint_space_stroke_enabled(brush) || cache->first_time) + if (paint_supports_dynamic_size(brush) || cache->first_time) { cache->pressure = RNA_float_get(ptr, "pressure"); + } /* Truly temporary data that isn't stored in properties */ - sd->draw_pressure = 1; - sd->pressure_value = cache->pressure; + ups->draw_pressure = 1; + ups->pressure_value = cache->pressure; cache->previous_pixel_radius = cache->pixel_radius; cache->pixel_radius = BKE_brush_size_get(scene, brush); @@ -3903,12 +3917,13 @@ static void sculpt_update_cache_variants(bContext *C, Sculpt *sd, Object *ob, } } - if (BKE_brush_use_size_pressure(scene, brush)) { + if (BKE_brush_use_size_pressure(scene, brush) && paint_supports_dynamic_size(brush)) { cache->pixel_radius *= cache->pressure; cache->radius = cache->initial_radius * cache->pressure; } - else + else { cache->radius = cache->initial_radius; + } cache->radius_squared = cache->radius * cache->radius; @@ -3932,7 +3947,7 @@ static void sculpt_update_cache_variants(bContext *C, Sculpt *sd, Object *ob, const float dx = cache->mouse[0] - cache->initial_mouse[0]; const float dy = cache->mouse[1] - cache->initial_mouse[1]; - sd->anchored_size = cache->pixel_radius = sqrt(dx * dx + dy * dy); + ups->anchored_size = cache->pixel_radius = sqrt(dx * dx + dy * dy); cache->special_rotation = atan2(dx, dy) + M_PI; @@ -3944,27 +3959,27 @@ static void sculpt_update_cache_variants(bContext *C, Sculpt *sd, Object *ob, halfway[1] = dy * 0.5f + cache->initial_mouse[1]; if (sculpt_stroke_get_location(C, out, halfway)) { - copy_v3_v3(sd->anchored_location, out); - copy_v2_v2(sd->anchored_initial_mouse, halfway); + copy_v3_v3(ups->anchored_location, out); + copy_v2_v2(ups->anchored_initial_mouse, halfway); copy_v2_v2(cache->tex_mouse, halfway); - copy_v3_v3(cache->true_location, sd->anchored_location); - sd->anchored_size /= 2.0f; + copy_v3_v3(cache->true_location, ups->anchored_location); + ups->anchored_size /= 2.0f; cache->pixel_radius /= 2.0f; hit = 1; } } if (!hit) - copy_v2_v2(sd->anchored_initial_mouse, cache->initial_mouse); + copy_v2_v2(ups->anchored_initial_mouse, cache->initial_mouse); cache->radius = paint_calc_object_space_radius(paint_stroke_view_context(stroke), cache->true_location, cache->pixel_radius); cache->radius_squared = cache->radius * cache->radius; - copy_v3_v3(sd->anchored_location, cache->true_location); + copy_v3_v3(ups->anchored_location, cache->true_location); - sd->draw_anchored = 1; + ups->draw_anchored = 1; } else if (brush->flag & BRUSH_RAKE) { const float u = 0.5f; @@ -3985,7 +4000,7 @@ static void sculpt_update_cache_variants(bContext *C, Sculpt *sd, Object *ob, } } - sculpt_update_brush_delta(sd, ob, brush); + sculpt_update_brush_delta(ups, ob, brush); if (brush->sculpt_tool == SCULPT_TOOL_ROTATE) { const float dx = cache->mouse[0] - cache->initial_mouse[0]; @@ -3993,13 +4008,13 @@ static void sculpt_update_cache_variants(bContext *C, Sculpt *sd, Object *ob, cache->vertex_rotation = -atan2f(dx, dy) * cache->bstrength; - sd->draw_anchored = 1; - copy_v2_v2(sd->anchored_initial_mouse, cache->initial_mouse); - copy_v3_v3(sd->anchored_location, cache->true_location); - sd->anchored_size = cache->pixel_radius; + ups->draw_anchored = 1; + copy_v2_v2(ups->anchored_initial_mouse, cache->initial_mouse); + copy_v3_v3(ups->anchored_location, cache->true_location); + ups->anchored_size = cache->pixel_radius; } - sd->special_rotation = cache->special_rotation; + ups->special_rotation = cache->special_rotation; } /* Returns true iff any of the smoothing modes are active (currently @@ -4172,6 +4187,17 @@ static void sculpt_restore_mesh(Sculpt *sd, Object *ob) } } +/* Copy the PBVH bounding box into the object's bounding box */ +static void sculpt_update_object_bounding_box(Object *ob) +{ + if (ob->bb) { + float bb_min[3], bb_max[3]; + + BKE_pbvh_bounding_box(ob->sculpt->pbvh, bb_min, bb_max); + BKE_boundbox_init_from_minmax(ob->bb, bb_min, bb_max); + } +} + static void sculpt_flush_update(bContext *C) { Object *ob = CTX_data_active_object(C); @@ -4192,6 +4218,11 @@ static void sculpt_flush_update(bContext *C) rcti r; BKE_pbvh_update(ss->pbvh, PBVH_UpdateBB, NULL); + /* Update the object's bounding box too so that the object + * doesn't get incorrectly clipped during drawing in + * draw_mesh_object(). [#33790] */ + sculpt_update_object_bounding_box(ob); + if (sculpt_get_redraw_rect(ar, CTX_wm_region_view3d(C), ob, &r)) { if (ss->cache) ss->cache->previous_r = r; @@ -4289,6 +4320,7 @@ static void sculpt_brush_exit_tex(Sculpt *sd) static void sculpt_stroke_done(const bContext *C, struct PaintStroke *UNUSED(stroke)) { + UnifiedPaintSettings *ups = &CTX_data_tool_settings(C)->unified_paint_settings; Object *ob = CTX_data_active_object(C); SculptSession *ss = ob->sculpt; Sculpt *sd = CTX_data_tool_settings(C)->sculpt; @@ -4296,9 +4328,9 @@ static void sculpt_stroke_done(const bContext *C, struct PaintStroke *UNUSED(str sculpt_omp_done(ss); /* reset values used to draw brush after completing the stroke */ - sd->draw_anchored = 0; - sd->draw_pressure = 0; - sd->special_rotation = 0; + ups->draw_anchored = 0; + ups->draw_pressure = 0; + ups->special_rotation = 0; /* Finished */ if (ss->cache) { @@ -4869,6 +4901,12 @@ static int sculpt_toggle_mode(bContext *C, wmOperator *UNUSED(op)) /* Enter sculptmode */ ob->mode |= OB_MODE_SCULPT; + /* Remove dynamic-topology flag; this will be enabled if the + * file was saved with dynamic topology on, but we don't + * automatically re-enter dynamic-topology mode when loading a + * file. */ + me->flag &= ~ME_SCULPT_DYNAMIC_TOPOLOGY; + if (flush_recalc) DAG_id_tag_update(&ob->id, OB_RECALC_DATA); diff --git a/source/blender/editors/space_buttons/buttons_ops.c b/source/blender/editors/space_buttons/buttons_ops.c index d40426a5bc9..54261974993 100644 --- a/source/blender/editors/space_buttons/buttons_ops.c +++ b/source/blender/editors/space_buttons/buttons_ops.c @@ -112,14 +112,22 @@ static int file_browse_exec(bContext *C, wmOperator *op) /* add slash for directories, important for some properties */ if (RNA_property_subtype(fbo->prop) == PROP_DIRPATH) { char name[FILE_MAX]; - + int is_relative = RNA_boolean_get(op->ptr, "relative_path"); id = fbo->ptr.id.data; BLI_strncpy(path, str, FILE_MAX); BLI_path_abs(path, id ? ID_BLEND_PATH(G.main, id) : G.main->name); if (BLI_is_dir(path)) { - str = MEM_reallocN(str, strlen(str) + 2); + if (is_relative) { + BLI_strncpy(path, str, FILE_MAX); + BLI_path_rel(path, G.main->name); + str = MEM_reallocN(str, strlen(path) + 2); + BLI_strncpy(str, path, FILE_MAX); + } + else { + str = MEM_reallocN(str, strlen(str) + 2); + } BLI_add_slash(str); } else diff --git a/source/blender/editors/space_clip/clip_editor.c b/source/blender/editors/space_clip/clip_editor.c index 04154a27b74..927834a8924 100644 --- a/source/blender/editors/space_clip/clip_editor.c +++ b/source/blender/editors/space_clip/clip_editor.c @@ -33,13 +33,6 @@ #include "MEM_guardedalloc.h" -#include "BKE_main.h" -#include "BKE_mask.h" -#include "BKE_movieclip.h" -#include "BKE_context.h" -#include "BKE_tracking.h" -#include "BKE_library.h" - #include "DNA_mask_types.h" #include "DNA_object_types.h" /* SELECT */ @@ -48,6 +41,13 @@ #include "BLI_string.h" #include "BLI_rect.h" +#include "BKE_main.h" +#include "BKE_mask.h" +#include "BKE_movieclip.h" +#include "BKE_context.h" +#include "BKE_tracking.h" +#include "BKE_library.h" + #include "GPU_extensions.h" #include "IMB_imbuf_types.h" diff --git a/source/blender/editors/space_image/image_buttons.c b/source/blender/editors/space_image/image_buttons.c index 060a181612b..afae9535fee 100644 --- a/source/blender/editors/space_image/image_buttons.c +++ b/source/blender/editors/space_image/image_buttons.c @@ -784,6 +784,8 @@ void uiTemplateImageSettings(uiLayout *layout, PointerRNA *imfptr, int color_man R_IMF_CHAN_DEPTH_32)) == 0) { row = uiLayoutRow(col, FALSE); + + uiItemL(row, IFACE_("Color Depth:"), ICON_NONE); uiItemR(row, imfptr, "color_depth", UI_ITEM_R_EXPAND, NULL, ICON_NONE); } diff --git a/source/blender/editors/space_image/image_draw.c b/source/blender/editors/space_image/image_draw.c index 7b4814d1ab2..ba4f8287cd7 100644 --- a/source/blender/editors/space_image/image_draw.c +++ b/source/blender/editors/space_image/image_draw.c @@ -110,8 +110,8 @@ static void draw_render_info(Scene *scene, Image *ima, ARegion *ar, float zoomx, glScalef(zoomx, zoomy, 1.0f); if (scene->r.mode & R_BORDER) { - glTranslatef(-scene->r.border.xmin * scene->r.xsch * scene->r.size / 100.0f, - -scene->r.border.ymin * scene->r.ysch * scene->r.size / 100.0f, + glTranslatef((int)(-scene->r.border.xmin * scene->r.xsch * scene->r.size / 100.0f), + (int)(-scene->r.border.ymin * scene->r.ysch * scene->r.size / 100.0f), 0.0f); } @@ -834,7 +834,7 @@ void draw_image_main(const bContext *C, ARegion *ar) show_render = (show_viewer && ima->type == IMA_TYPE_R_RESULT); if (show_viewer) { - /* use locked draw for drawing viewer image buffer since the conpositor + /* use locked draw for drawing viewer image buffer since the compositor * is running in separated thread and compositor could free this buffers. * other images are not modifying in such a way so they does not require * lock (sergey) diff --git a/source/blender/editors/space_image/image_ops.c b/source/blender/editors/space_image/image_ops.c index eed15425441..23adf7eb575 100644 --- a/source/blender/editors/space_image/image_ops.c +++ b/source/blender/editors/space_image/image_ops.c @@ -1109,6 +1109,11 @@ static int image_replace_exec(bContext *C, wmOperator *op) /* we cant do much if the str is longer then FILE_MAX :/ */ BLI_strncpy(sima->image->name, str, sizeof(sima->image->name)); + if (sima->image->source == IMA_SRC_GENERATED) { + sima->image->source = IMA_SRC_FILE; + BKE_image_signal(sima->image, &sima->iuser, IMA_SIGNAL_SRC_CHANGE); + } + if (BLI_testextensie_array(str, imb_ext_movie)) sima->image->source = IMA_SRC_MOVIE; else diff --git a/source/blender/editors/space_image/space_image.c b/source/blender/editors/space_image/space_image.c index 9492e29734d..1c384ef38d7 100644 --- a/source/blender/editors/space_image/space_image.c +++ b/source/blender/editors/space_image/space_image.c @@ -38,6 +38,7 @@ #include "BLI_blenlib.h" #include "BLI_math.h" +#include "BLI_threads.h" #include "BKE_colortools.h" #include "BKE_context.h" @@ -692,10 +693,25 @@ static void image_main_area_draw(const bContext *C, ARegion *ar) } if (mask) { - int width, height; + Image *image = ED_space_image(sima); + int width, height, show_viewer; float aspx, aspy; + + show_viewer = (image && image->source == IMA_SRC_VIEWER); + + if (show_viewer) { + /* ED_space_image_get* will acquire image buffer which requires + * lock here by the same reason why lock is needed in draw_image_main + */ + BLI_lock_thread(LOCK_DRAW_IMAGE); + } + ED_space_image_get_size(sima, &width, &height); ED_space_image_get_aspect(sima, &aspx, &aspy); + + if (show_viewer) + BLI_unlock_thread(LOCK_DRAW_IMAGE); + ED_mask_draw_region(mask, ar, sima->mask_info.draw_flag, sima->mask_info.draw_type, width, height, diff --git a/source/blender/editors/space_logic/logic_ops.c b/source/blender/editors/space_logic/logic_ops.c index 74be7c46d26..f28757bb431 100644 --- a/source/blender/editors/space_logic/logic_ops.c +++ b/source/blender/editors/space_logic/logic_ops.c @@ -54,6 +54,8 @@ #include "WM_api.h" #include "WM_types.h" +#include "UI_view2d.h" + #include "logic_intern.h" // temporary new includes for texface functions @@ -421,6 +423,10 @@ static int controller_add_exec(bContext *C, wmOperator *op) ob->scaflag |= OB_SHOWCONT; WM_event_add_notifier(C, NC_LOGIC, NULL); + + /* prevent the operator to get stuck with the "object" of the previous call - + * it only happens when it's called from the "smart controller", see bug #54102 */ + RNA_string_set(op->ptr, "object", ""); return OPERATOR_FINISHED; } @@ -723,6 +729,39 @@ static void LOGIC_OT_texface_convert(wmOperatorType *ot) } +/* ************************ view ********************* */ + +static int logic_view_all_exec(bContext *C, wmOperator *UNUSED(op)) +{ + ARegion *ar = CTX_wm_region(C); + rctf cur_new = ar->v2d.tot; + float aspect = BLI_rctf_size_y(&ar->v2d.cur) / BLI_rctf_size_x(&ar->v2d.cur); + + /* force the view2d code to zoom to width, not height */ + cur_new.ymin = cur_new.ymax - BLI_rctf_size_x(&cur_new) * aspect; + + UI_view2d_smooth_view(C, ar, &cur_new); + + return OPERATOR_FINISHED; +} + +static void LOGIC_OT_view_all(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "View All"; + ot->idname = "LOGIC_OT_view_all"; + ot->description = "Resize view so you can see all logic bricks"; + + /* api callbacks */ + ot->exec = logic_view_all_exec; + ot->poll = ED_operator_logic_active; + + /* flags */ + ot->flag = 0; +} + +/* ************************* */ + void ED_operatortypes_logic(void) { WM_operatortype_append(LOGIC_OT_sensor_remove); @@ -735,4 +774,5 @@ void ED_operatortypes_logic(void) WM_operatortype_append(LOGIC_OT_actuator_add); WM_operatortype_append(LOGIC_OT_actuator_move); WM_operatortype_append(LOGIC_OT_texface_convert); + WM_operatortype_append(LOGIC_OT_view_all); } diff --git a/source/blender/editors/space_logic/logic_window.c b/source/blender/editors/space_logic/logic_window.c index a7599f21ad5..f46151fd33a 100644 --- a/source/blender/editors/space_logic/logic_window.c +++ b/source/blender/editors/space_logic/logic_window.c @@ -2226,6 +2226,7 @@ void logic_buttons(bContext *C, ARegion *ar) BLI_snprintf(uiblockstr, sizeof(uiblockstr), "buttonswin %p", (void *)ar); block= uiBeginBlock(C, ar, uiblockstr, UI_EMBOSS); uiBlockSetHandleFunc(block, do_logic_buts, NULL); + uiBoundsBlock(block, U.widget_unit/2); /* loop over all objects and set visible/linked flags for the logic bricks */ for (a=0; a<count; a++) { @@ -2516,7 +2517,7 @@ void logic_buttons(bContext *C, ARegion *ar) uiBlockLayoutResolve(block, NULL, &yco); /* stores final height in yco */ height = MIN2(height, yco); - UI_view2d_totRect_set(&ar->v2d, 57.5f * U.widget_unit, height); + UI_view2d_totRect_set(&ar->v2d, 57.5f * U.widget_unit, height - U.widget_unit); /* set the view */ UI_view2d_view_ortho(&ar->v2d); diff --git a/source/blender/editors/space_logic/space_logic.c b/source/blender/editors/space_logic/space_logic.c index 8795d655e77..3f3c81f2bfa 100644 --- a/source/blender/editors/space_logic/space_logic.c +++ b/source/blender/editors/space_logic/space_logic.c @@ -183,7 +183,7 @@ static void logic_keymap(struct wmKeyConfig *keyconf) WM_keymap_add_item(keymap, "LOGIC_OT_links_cut", LEFTMOUSE, KM_PRESS, KM_CTRL, 0); WM_keymap_add_menu(keymap, "LOGIC_MT_logicbricks_add", AKEY, KM_PRESS, KM_SHIFT, 0); - WM_keymap_add_item(keymap, "VIEW2D_OT_reset", HOMEKEY, KM_PRESS, 0, 0); + WM_keymap_add_item(keymap, "LOGIC_OT_view_all", HOMEKEY, KM_PRESS, 0, 0); } diff --git a/source/blender/editors/space_nla/nla_draw.c b/source/blender/editors/space_nla/nla_draw.c index 0c89e3ecbcf..acfb4a51b14 100644 --- a/source/blender/editors/space_nla/nla_draw.c +++ b/source/blender/editors/space_nla/nla_draw.c @@ -874,7 +874,7 @@ static void draw_nla_channel_list_gl(bAnimContext *ac, ListBase *anim_data, View glVertex2f((float)v2d->cur.xmax - offset - 1, y + 0.45f * U.widget_unit); glVertex2f((float)v2d->cur.xmax - 1, y + 0.45f * U.widget_unit); glVertex2f((float)v2d->cur.xmax - 1, y - 0.35f * U.widget_unit); - glEnd(); // GL_LINES + glEnd(); /* 'push down' icon for normal active-actions */ UI_icon_draw((float)v2d->cur.xmax - offset, ydatac, ICON_FREEZE); diff --git a/source/blender/editors/space_node/drawnode.c b/source/blender/editors/space_node/drawnode.c index 981a1775b51..cca1858f112 100644 --- a/source/blender/editors/space_node/drawnode.c +++ b/source/blender/editors/space_node/drawnode.c @@ -1121,8 +1121,10 @@ static void node_update_reroute(const bContext *UNUSED(C), bNodeTree *UNUSED(ntr static void node_draw_reroute(const bContext *C, ARegion *ar, SpaceNode *UNUSED(snode), bNodeTree *ntree, bNode *node) { bNodeSocket *sock; -#if 0 /* UNUSED */ + char showname[128]; /* 128 used below */ rctf *rct = &node->totr; + +#if 0 /* UNUSED */ float size = NODE_REROUTE_SIZE; #endif float socket_size = NODE_SOCKSIZE; @@ -1163,6 +1165,15 @@ static void node_draw_reroute(const bContext *C, ARegion *ar, SpaceNode *UNUSED( } #endif + if (node->label[0] != '\0') { + /* draw title (node label) */ + BLI_strncpy(showname, node->label, sizeof(showname)); + uiDefBut(node->block, LABEL, 0, showname, + (int)(rct->xmin - NODE_DYS), (int)(rct->ymax), + (short)512, (short)NODE_DY, + NULL, 0, 0, 0, 0, NULL); + } + /* only draw input socket. as they all are placed on the same position. * highlight also if node itself is selected, since we don't display the node body separately! */ diff --git a/source/blender/editors/space_node/node_draw.c b/source/blender/editors/space_node/node_draw.c index e1d5e4200b8..d5d2ace6fa7 100644 --- a/source/blender/editors/space_node/node_draw.c +++ b/source/blender/editors/space_node/node_draw.c @@ -454,8 +454,8 @@ static void node_update_hidden(bNode *node) for (nsock = node->outputs.first; nsock; nsock = nsock->next) { if (!nodeSocketIsHidden(nsock)) { - nsock->locx = node->totr.xmax - hiddenrad + (float)sin(rad) * hiddenrad; - nsock->locy = node->totr.ymin + hiddenrad + (float)cos(rad) * hiddenrad; + nsock->locx = node->totr.xmax - hiddenrad + sinf(rad) * hiddenrad; + nsock->locy = node->totr.ymin + hiddenrad + cosf(rad) * hiddenrad; rad += drad; } } @@ -465,8 +465,8 @@ static void node_update_hidden(bNode *node) for (nsock = node->inputs.first; nsock; nsock = nsock->next) { if (!nodeSocketIsHidden(nsock)) { - nsock->locx = node->totr.xmin + hiddenrad + (float)sin(rad) * hiddenrad; - nsock->locy = node->totr.ymin + hiddenrad + (float)cos(rad) * hiddenrad; + nsock->locx = node->totr.xmin + hiddenrad + sinf(rad) * hiddenrad; + nsock->locy = node->totr.ymin + hiddenrad + cosf(rad) * hiddenrad; rad += drad; } } @@ -501,21 +501,18 @@ int node_tweak_area_default(bNode *node, int x, int y) int node_get_colorid(bNode *node) { - if (node->typeinfo->nclass == NODE_CLASS_INPUT) - return TH_NODE_IN_OUT; - if (node->typeinfo->nclass == NODE_CLASS_OUTPUT) { - if (node->flag & NODE_DO_OUTPUT) - return TH_NODE_IN_OUT; - else - return TH_NODE; + switch (node->typeinfo->nclass) { + case NODE_CLASS_INPUT: return TH_NODE_IN_OUT; + case NODE_CLASS_OUTPUT: return (node->flag & NODE_DO_OUTPUT) ? TH_NODE_IN_OUT : TH_NODE; + case NODE_CLASS_CONVERTOR: return TH_NODE_CONVERTOR; + case NODE_CLASS_OP_COLOR: + case NODE_CLASS_OP_VECTOR: + case NODE_CLASS_OP_FILTER: return TH_NODE_OPERATOR; + case NODE_CLASS_GROUP: return TH_NODE_GROUP; + case NODE_CLASS_MATTE: return TH_NODE_MATTE; + case NODE_CLASS_DISTORT: return TH_NODE_DISTORT; + default: return TH_NODE; } - if (node->typeinfo->nclass == NODE_CLASS_CONVERTOR) - return TH_NODE_CONVERTOR; - if (ELEM3(node->typeinfo->nclass, NODE_CLASS_OP_COLOR, NODE_CLASS_OP_VECTOR, NODE_CLASS_OP_FILTER)) - return TH_NODE_OPERATOR; - if (node->typeinfo->nclass == NODE_CLASS_GROUP) - return TH_NODE_GROUP; - return TH_NODE; } /* note: in cmp_util.c is similar code, for node_compo_pass_on() @@ -704,6 +701,7 @@ static void node_draw_basis(const bContext *C, ARegion *ar, SpaceNode *snode, bN if (node->flag & NODE_MUTED) UI_ThemeColorBlend(color_id, TH_REDALERT, 0.5f); + #ifdef WITH_COMPOSITOR if (ntree->type == NTREE_COMPOSIT && (snode->flag & SNODE_SHOW_HIGHLIGHT)) { @@ -798,6 +796,7 @@ static void node_draw_basis(const bContext *C, ARegion *ar, SpaceNode *snode, bN /* outline active and selected emphasis */ if (node->flag & SELECT) { + glEnable(GL_BLEND); glEnable(GL_LINE_SMOOTH); @@ -805,6 +804,7 @@ static void node_draw_basis(const bContext *C, ARegion *ar, SpaceNode *snode, bN UI_ThemeColorShadeAlpha(TH_ACTIVE, 0, -40); else UI_ThemeColorShadeAlpha(TH_SELECT, 0, -40); + uiSetRoundBox(UI_CNR_ALL); uiDrawBox(GL_LINE_LOOP, rct->xmin, rct->ymin, rct->xmax, rct->ymax, BASIS_RAD); diff --git a/source/blender/editors/space_node/node_edit.c b/source/blender/editors/space_node/node_edit.c index ae95d9ae074..2fae92d674c 100644 --- a/source/blender/editors/space_node/node_edit.c +++ b/source/blender/editors/space_node/node_edit.c @@ -550,6 +550,12 @@ void snode_set_context(SpaceNode *snode, Scene *scene) snode->id = snode->from = NULL; if (snode->treetype == NTREE_SHADER) { + /* we use this to signal warnings, when node shaders are drawn in wrong render engine */ + if (BKE_scene_use_new_shading_nodes(scene)) + snode->flag |= SNODE_NEW_SHADERS; + else + snode->flag &= ~SNODE_NEW_SHADERS; + /* need active object, or we allow pinning... */ if (snode->shaderfrom == SNODE_SHADER_OBJECT) { if (ob) { diff --git a/source/blender/editors/space_node/node_select.c b/source/blender/editors/space_node/node_select.c index a3efa15c54a..7d2b80d50ba 100644 --- a/source/blender/editors/space_node/node_select.c +++ b/source/blender/editors/space_node/node_select.c @@ -30,14 +30,14 @@ #include "DNA_node_types.h" -#include "BKE_context.h" -#include "BKE_main.h" -#include "BKE_node.h" - #include "BLI_rect.h" #include "BLI_lasso.h" #include "BLI_utildefines.h" +#include "BKE_context.h" +#include "BKE_main.h" +#include "BKE_node.h" + #include "ED_node.h" /* own include */ #include "ED_screen.h" #include "ED_types.h" diff --git a/source/blender/editors/space_outliner/outliner_draw.c b/source/blender/editors/space_outliner/outliner_draw.c index 1a058104c78..b64019b01be 100644 --- a/source/blender/editors/space_outliner/outliner_draw.c +++ b/source/blender/editors/space_outliner/outliner_draw.c @@ -1066,7 +1066,8 @@ static void tselem_draw_icon(uiBlock *block, int xmax, float x, float y, TreeSto UI_icon_draw(x, y, ICON_MOD_SKIN); break; case eModifierType_Triangulate: UI_icon_draw(x, y, ICON_MOD_TRIANGULATE); break; - + case eModifierType_MeshCache: + UI_icon_draw(x, y, ICON_MOD_MESHDEFORM); break; /* XXX, needs own icon */ /* Default */ case eModifierType_None: case eModifierType_ShapeKey: diff --git a/source/blender/editors/space_text/CMakeLists.txt b/source/blender/editors/space_text/CMakeLists.txt index a33a9abada1..1a6b8eaa753 100644 --- a/source/blender/editors/space_text/CMakeLists.txt +++ b/source/blender/editors/space_text/CMakeLists.txt @@ -39,6 +39,7 @@ set(SRC text_autocomplete.c text_draw.c text_format.c + text_format_lua.c text_format_osl.c text_format_py.c text_header.c diff --git a/source/blender/editors/space_text/space_text.c b/source/blender/editors/space_text/space_text.c index fa3eefcc0f7..ff9d1329721 100644 --- a/source/blender/editors/space_text/space_text.c +++ b/source/blender/editors/space_text/space_text.c @@ -232,6 +232,12 @@ static void text_keymap(struct wmKeyConfig *keyconf) wmKeyMap *keymap; wmKeyMapItem *kmi; + keymap = WM_keymap_find(keyconf, "Text Generic", SPACE_TEXT, 0); + WM_keymap_add_item(keymap, "TEXT_OT_properties", FKEY, KM_PRESS, KM_CTRL, 0); +#ifdef __APPLE__ + WM_keymap_add_item(keymap, "TEXT_OT_properties", FKEY, KM_PRESS, KM_OSKEY, 0); +#endif + keymap = WM_keymap_find(keyconf, "Text", SPACE_TEXT, 0); #ifdef __APPLE__ @@ -256,7 +262,6 @@ static void text_keymap(struct wmKeyConfig *keyconf) WM_keymap_add_item(keymap, "TEXT_OT_cut", XKEY, KM_PRESS, KM_OSKEY, 0); WM_keymap_add_item(keymap, "TEXT_OT_copy", CKEY, KM_PRESS, KM_OSKEY, 0); WM_keymap_add_item(keymap, "TEXT_OT_paste", VKEY, KM_PRESS, KM_OSKEY, 0); - WM_keymap_add_item(keymap, "TEXT_OT_properties", FKEY, KM_PRESS, KM_OSKEY, 0); WM_keymap_add_item(keymap, "TEXT_OT_find_set_selected", EKEY, KM_PRESS, KM_OSKEY, 0); WM_keymap_add_item(keymap, "TEXT_OT_find", GKEY, KM_PRESS, KM_OSKEY, 0); WM_keymap_add_item(keymap, "TEXT_OT_select_all", AKEY, KM_PRESS, KM_OSKEY, 0); @@ -305,7 +310,6 @@ static void text_keymap(struct wmKeyConfig *keyconf) WM_keymap_add_item(keymap, "TEXT_OT_jump", JKEY, KM_PRESS, KM_CTRL, 0); WM_keymap_add_item(keymap, "TEXT_OT_find", GKEY, KM_PRESS, KM_CTRL, 0); - WM_keymap_add_item(keymap, "TEXT_OT_properties", FKEY, KM_PRESS, KM_CTRL, 0); WM_keymap_add_item(keymap, "TEXT_OT_replace", HKEY, KM_PRESS, KM_CTRL, 0); kmi = WM_keymap_add_item(keymap, "TEXT_OT_to_3d_object", MKEY, KM_PRESS, KM_ALT, 0); @@ -413,6 +417,8 @@ static void text_main_area_init(wmWindowManager *wm, ARegion *ar) UI_view2d_region_reinit(&ar->v2d, V2D_COMMONVIEW_STANDARD, ar->winx, ar->winy); /* own keymap */ + keymap = WM_keymap_find(wm->defaultconf, "Text Generic", SPACE_TEXT, 0); + WM_event_add_keymap_handler_bb(&ar->handlers, keymap, &ar->v2d.mask, &ar->winrct); keymap = WM_keymap_find(wm->defaultconf, "Text", SPACE_TEXT, 0); WM_event_add_keymap_handler_bb(&ar->handlers, keymap, &ar->v2d.mask, &ar->winrct); @@ -496,6 +502,11 @@ static void text_header_area_draw(const bContext *C, ARegion *ar) /* add handlers, stuff you only do once or on area/region changes */ static void text_properties_area_init(wmWindowManager *wm, ARegion *ar) { + wmKeyMap *keymap; + + keymap = WM_keymap_find(wm->defaultconf, "Text Generic", SPACE_TEXT, 0); + WM_event_add_keymap_handler_bb(&ar->handlers, keymap, &ar->v2d.mask, &ar->winrct); + ED_region_panels_init(wm, ar); } @@ -560,5 +571,6 @@ void ED_spacetype_text(void) /* register formatters */ ED_text_format_register_py(); ED_text_format_register_osl(); + ED_text_format_register_lua(); } diff --git a/source/blender/editors/space_text/text_autocomplete.c b/source/blender/editors/space_text/text_autocomplete.c index e406a1b7166..94977fc5f0f 100644 --- a/source/blender/editors/space_text/text_autocomplete.c +++ b/source/blender/editors/space_text/text_autocomplete.c @@ -167,7 +167,7 @@ static GHash *text_autocomplete_build(Text *text) while (i_start < linep->len) { /* seek identifier beginning */ - while (i_start < linep->len && !text_check_identifier(linep->line[i_start])) { + while (i_start < linep->len && !text_check_identifier_nodigit(linep->line[i_start])) { i_start++; } i_end = i_start; @@ -175,7 +175,11 @@ static GHash *text_autocomplete_build(Text *text) i_end++; } - if (i_start != i_end) { + if ((i_start != i_end) && + /* check we're at the beginning of a line or that the previous char is not an identifier + * this prevents digits from being added */ + ((i_start < 1) || !text_check_identifier(linep->line[i_start - 1]))) + { char *str_sub = &linep->line[i_start]; const int choice_len = i_end - i_start; diff --git a/source/blender/editors/space_text/text_format.c b/source/blender/editors/space_text/text_format.c index 294f94dd4b7..a8c2de193c4 100644 --- a/source/blender/editors/space_text/text_format.c +++ b/source/blender/editors/space_text/text_format.c @@ -140,6 +140,54 @@ int text_check_format_len(TextLine *line, unsigned int len) return 1; } +/** + * Fill the string with formatting constant, + * advancing \a str_p and \a fmt_p + * + * \param len length in bytes + */ +void text_format_fill(const char **str_p, char **fmt_p, const char type, const int len) +{ + const char *str = *str_p; + char *fmt = *fmt_p; + int i = 0; + + while (i < len) { + const int size = BLI_str_utf8_size_safe(str); + *fmt++ = type; + + str += size; + i += size; + } + + str--; + fmt--; + + BLI_assert(*str != '\0'); + + *str_p = str; + *fmt_p = fmt; +} +/** + * ascii version of #text_format_fill, + * use when we no the text being stepped over is ascii (as is the case for most keywords) + */ +void text_format_fill_ascii(const char **str_p, char **fmt_p, const char type, const int len) +{ + const char *str = *str_p; + char *fmt = *fmt_p; + + memset(fmt, type, len); + + str += len - 1; + fmt += len - 1; + + BLI_assert(*str != '\0'); + + *str_p = str; + *fmt_p = fmt; +} + /* *** Registration *** */ static ListBase tft_lb = {NULL, NULL}; void ED_text_format_register(TextFormatType *tft) @@ -149,14 +197,31 @@ void ED_text_format_register(TextFormatType *tft) TextFormatType *ED_text_format_get(Text *text) { - /* NOTE: once more types are added we'll need to return some type based on 'text' - * for now this function is more of a placeholder */ + TextFormatType *tft; + + if (text) { + const char *text_ext = strchr(text->id.name + 2, '.'); + if (text_ext) { + text_ext++; /* skip the '.' */ + /* Check all text formats in the static list */ + for (tft = tft_lb.first; tft; tft = tft->next) { + /* All formats should have an ext, but just in case */ + const char **ext; + for (ext = tft->ext; *ext; ext++) { + /* If extension matches text name, return the matching tft */ + if (BLI_strcasecmp(text_ext, *ext) == 0) { + return tft; + } + } + } + } - /* XXX, wrong, but OK for testing */ - if (text && BLI_testextensie(text->id.name + 2, ".osl")) { - return tft_lb.last; + /* If we make it here we never found an extension that worked - return + * the "default" text format */ + return tft_lb.first; } else { + /* Return the "default" text format */ return tft_lb.first; } } diff --git a/source/blender/editors/space_text/text_format.h b/source/blender/editors/space_text/text_format.h index e593e41d42c..808311cbb62 100644 --- a/source/blender/editors/space_text/text_format.h +++ b/source/blender/editors/space_text/text_format.h @@ -49,18 +49,18 @@ enum { FMT_CONT_TRIPLE = (1 << 2), /* triplets of quotes: """ or ''' */ FMT_CONT_QUOTESINGLE_TRIPLE = (FMT_CONT_TRIPLE | FMT_CONT_QUOTESINGLE), FMT_CONT_QUOTEDOUBLE_TRIPLE = (FMT_CONT_TRIPLE | FMT_CONT_QUOTEDOUBLE), - FMT_CONT_COMMENT_C = (1 << 3), /* multi-line comments, OSL only (C style) */ - FMT_CONT_COMMENT_CXX = (1 << 4), /* single-line comments, OSL only (C++ style) */ + FMT_CONT_COMMENT_C = (1 << 3) /* multi-line comments, OSL only (C style) */ }; #define FMT_CONT_ALL \ - (FMT_CONT_QUOTESINGLE | FMT_CONT_QUOTEDOUBLE | FMT_CONT_TRIPLE | FMT_CONT_COMMENT_C | FMT_CONT_COMMENT_CXX) + (FMT_CONT_QUOTESINGLE | FMT_CONT_QUOTEDOUBLE | FMT_CONT_TRIPLE | FMT_CONT_COMMENT_C) int flatten_string(struct SpaceText *st, FlattenString *fs, const char *in); void flatten_string_free(FlattenString *fs); int flatten_string_strlen(FlattenString *fs, const char *str); int text_check_format_len(TextLine *line, unsigned int len); - +void text_format_fill(const char **str_p, char **fmt_p, const char type, const int len); +void text_format_fill_ascii(const char **str_p, char **fmt_p, const char type, const int len); /* *** Generalize Formatting *** */ typedef struct TextFormatType { @@ -101,6 +101,7 @@ void ED_text_format_register(TextFormatType *tft); /* formatters */ void ED_text_format_register_py(void); void ED_text_format_register_osl(void); +void ED_text_format_register_lua(void); #define STR_LITERAL_STARTSWITH(str, str_literal, len_var) \ (strncmp(str, str_literal, len_var = (sizeof(str_literal) - 1)) == 0) diff --git a/source/blender/editors/space_text/text_format_lua.c b/source/blender/editors/space_text/text_format_lua.c new file mode 100644 index 00000000000..6c72e043930 --- /dev/null +++ b/source/blender/editors/space_text/text_format_lua.c @@ -0,0 +1,318 @@ +/* + * ***** 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 + * 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) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file blender/editors/space_text/text_format_lua.c + * \ingroup sptext + */ + +#include <string.h> + +#include "BLI_blenlib.h" + +#include "DNA_text_types.h" +#include "DNA_space_types.h" + +#include "BKE_text.h" + +#include "text_format.h" + +/* *** Lua Keywords (for format_line) *** */ + +/* Checks the specified source string for a Lua keyword (minus boolean & 'nil'). + * This name must start at the beginning of the source string and must be + * followed by a non-identifier (see text_check_identifier(char)) or null char. + * + * If a keyword is found, the length of the matching word is returned. + * Otherwise, -1 is returned. + * + * See: + * http://www.lua.org/manual/5.1/manual.html#2.1 + */ + +static int txtfmt_lua_find_keyword(const char *string) +{ + int i, len; + + if (STR_LITERAL_STARTSWITH(string, "and", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "break", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "do", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "else", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "elseif", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "end", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "for", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "function", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "if", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "in", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "local", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "not", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "or", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "repeat", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "return", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "then", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "until", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "while", len)) i = len; + else i = 0; + + /* If next source char is an identifier (eg. 'i' in "definate") no match */ + if (i == 0 || text_check_identifier(string[i])) + return -1; + return i; +} + +/* Checks the specified source string for a Lua special name/function. This + * name must start at the beginning of the source string and must be followed + * by a non-identifier (see text_check_identifier(char)) or null character. + * + * If a special name is found, the length of the matching name is returned. + * Otherwise, -1 is returned. + * + * See: + * http://www.lua.org/manual/5.1/manual.html#5.1 + */ + +static int txtfmt_lua_find_specialvar(const char *string) +{ + int i, len; + + if (STR_LITERAL_STARTSWITH(string, "assert", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "collectgarbage", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "dofile", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "error", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "_G", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "getfenv", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "getmetatable", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "__index", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "ipairs", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "load", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "loadfile", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "loadstring", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "next", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "pairs", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "pcall", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "print", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "rawequal", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "rawget", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "rawset", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "select", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "setfenv", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "setmetatable", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "tonumber", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "tostring", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "type", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "unpack", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "_VERSION", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "xpcall", len)) i = len; + else i = 0; + + /* If next source char is an identifier (eg. 'i' in "definate") no match */ + if (i == 0 || text_check_identifier(string[i])) + return -1; + return i; +} + +static int txtfmt_lua_find_bool(const char *string) +{ + int i, len; + + if (STR_LITERAL_STARTSWITH(string, "nil", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "true", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "false", len)) i = len; + else i = 0; + + /* If next source char is an identifier (eg. 'i' in "Nonetheless") no match */ + if (i == 0 || text_check_identifier(string[i])) + return -1; + return i; +} + +static char txtfmt_lua_format_identifier(const char *str) +{ + char fmt; + if ((txtfmt_lua_find_specialvar(str)) != -1) fmt = FMT_TYPE_SPECIAL; + else if ((txtfmt_lua_find_keyword(str)) != -1) fmt = FMT_TYPE_KEYWORD; + else fmt = FMT_TYPE_DEFAULT; + return fmt; +} + +static void txtfmt_lua_format_line(SpaceText *st, TextLine *line, const int do_next) +{ + FlattenString fs; + const char *str; + char *fmt; + char cont_orig, cont, find, prev = ' '; + int len, i; + + /* Get continuation from previous line */ + if (line->prev && line->prev->format != NULL) { + fmt = line->prev->format; + cont = fmt[strlen(fmt) + 1]; /* Just after the null-terminator */ + BLI_assert((FMT_CONT_ALL & cont) == cont); + } + else { + cont = FMT_CONT_NOP; + } + + /* Get original continuation from this line */ + if (line->format != NULL) { + fmt = line->format; + cont_orig = fmt[strlen(fmt) + 1]; /* Just after the null-terminator */ + BLI_assert((FMT_CONT_ALL & cont_orig) == cont_orig); + } + else { + cont_orig = 0xFF; + } + + len = flatten_string(st, &fs, line->line); + str = fs.buf; + if (!text_check_format_len(line, len)) { + flatten_string_free(&fs); + return; + } + fmt = line->format; + + while (*str) { + /* Handle escape sequences by skipping both \ and next char */ + if (*str == '\\') { + *fmt = prev; fmt++; str++; + if (*str == '\0') break; + *fmt = prev; fmt++; str += BLI_str_utf8_size_safe(str); + continue; + } + /* Handle continuations */ + else if (cont) { + /* Multi-line comments */ + if (cont & FMT_CONT_COMMENT_C) { + if (*str == ']' && *(str + 1) == ']') { + *fmt = FMT_TYPE_COMMENT; fmt++; str++; + *fmt = FMT_TYPE_COMMENT; + cont = FMT_CONT_NOP; + } + else { + *fmt = FMT_TYPE_COMMENT; + } + /* Handle other comments */ + } + else { + find = (cont & FMT_CONT_QUOTEDOUBLE) ? '"' : '\''; + if (*str == find) cont = 0; + *fmt = FMT_TYPE_STRING; + } + + str += BLI_str_utf8_size_safe(str) - 1; + } + /* Not in a string... */ + else { + /* Multi-line comments */ + if (*str == '-' && *(str + 1) == '-' && + *(str + 2) == '[' && *(str + 3) == '[') + { + cont = FMT_CONT_COMMENT_C; + *fmt = FMT_TYPE_COMMENT; fmt++; str++; + *fmt = FMT_TYPE_COMMENT; fmt++; str++; + *fmt = FMT_TYPE_COMMENT; fmt++; str++; + *fmt = FMT_TYPE_COMMENT; + } + /* Single line comment */ + else if (*str == '-' && *(str + 1) == '-') { + text_format_fill(&str, &fmt, FMT_TYPE_COMMENT, len - (int)(str - fs.buf)); + } + else if (*str == '"' || *str == '\'') { + /* Strings */ + find = *str; + cont = (*str == '"') ? FMT_CONT_QUOTEDOUBLE : FMT_CONT_QUOTESINGLE; + *fmt = FMT_TYPE_STRING; + } + /* Whitespace (all ws. has been converted to spaces) */ + else if (*str == ' ') { + *fmt = FMT_TYPE_WHITESPACE; + } + /* Numbers (digits not part of an identifier and periods followed by digits) */ + else if ((prev != FMT_TYPE_DEFAULT && text_check_digit(*str)) || + (*str == '.' && text_check_digit(*(str + 1)))) + { + *fmt = FMT_TYPE_NUMERAL; + } + /* Booleans */ + else if (prev != FMT_TYPE_DEFAULT && (i = txtfmt_lua_find_bool(str)) != -1) { + if (i > 0) { + text_format_fill_ascii(&str, &fmt, FMT_TYPE_NUMERAL, i); + } + else { + str += BLI_str_utf8_size_safe(str) - 1; + *fmt = FMT_TYPE_DEFAULT; + } + } + /* Punctuation */ + else if ((*str != '#') && text_check_delim(*str)) { + *fmt = FMT_TYPE_SYMBOL; + } + /* Identifiers and other text (no previous ws. or delims. so text continues) */ + else if (prev == FMT_TYPE_DEFAULT) { + str += BLI_str_utf8_size_safe(str) - 1; + *fmt = FMT_TYPE_DEFAULT; + } + /* Not ws, a digit, punct, or continuing text. Must be new, check for special words */ + else { + /* Special vars(v) or built-in keywords(b) */ + /* keep in sync with 'txtfmt_osl_format_identifier()' */ + if ((i = txtfmt_lua_find_specialvar(str)) != -1) prev = FMT_TYPE_SPECIAL; + else if ((i = txtfmt_lua_find_keyword(str)) != -1) prev = FMT_TYPE_KEYWORD; + + if (i > 0) { + text_format_fill_ascii(&str, &fmt, prev, i); + } + else { + str += BLI_str_utf8_size_safe(str) - 1; + *fmt = FMT_TYPE_DEFAULT; + } + } + } + prev = *fmt; fmt++; str++; + } + + /* Terminate and add continuation char */ + *fmt = '\0'; fmt++; + *fmt = cont; + + /* If continuation has changed and we're allowed, process the next line */ + if (cont != cont_orig && do_next && line->next) { + txtfmt_lua_format_line(st, line->next, do_next); + } + + flatten_string_free(&fs); +} + +void ED_text_format_register_lua(void) +{ + static TextFormatType tft = {0}; + static const char *ext[] = {"lua", NULL}; + + tft.format_identifier = txtfmt_lua_format_identifier; + tft.format_line = txtfmt_lua_format_line; + tft.ext = ext; + + ED_text_format_register(&tft); +} diff --git a/source/blender/editors/space_text/text_format_osl.c b/source/blender/editors/space_text/text_format_osl.c index 3120e88163e..7d493eb1f62 100644 --- a/source/blender/editors/space_text/text_format_osl.c +++ b/source/blender/editors/space_text/text_format_osl.c @@ -228,10 +228,7 @@ static void txtfmt_osl_format_line(SpaceText *st, TextLine *line, const int do_n /* Handle continuations */ else if (cont) { /* C-Style comments */ - if (cont & FMT_CONT_COMMENT_CXX) { - *fmt = FMT_TYPE_COMMENT; - } - else if (cont & FMT_CONT_COMMENT_C) { + if (cont & FMT_CONT_COMMENT_C) { if (*str == '*' && *(str + 1) == '/') { *fmt = FMT_TYPE_COMMENT; fmt++; str++; *fmt = FMT_TYPE_COMMENT; @@ -254,8 +251,8 @@ static void txtfmt_osl_format_line(SpaceText *st, TextLine *line, const int do_n else { /* Deal with comments first */ if (*str == '/' && *(str + 1) == '/') { - cont = FMT_CONT_COMMENT_CXX; - *fmt = FMT_TYPE_COMMENT; + /* fill the remaining line */ + text_format_fill(&str, &fmt, FMT_TYPE_COMMENT, len - (int)(str - fs.buf)); } /* C-Style (multi-line) comments */ else if (*str == '/' && *(str + 1) == '*') { @@ -298,8 +295,12 @@ static void txtfmt_osl_format_line(SpaceText *st, TextLine *line, const int do_n else if ((i = txtfmt_osl_find_preprocessor(str)) != -1) prev = FMT_TYPE_DIRECTIVE; if (i > 0) { - memset(fmt, prev, i); - i--; fmt += i; str += i; + if (prev == FMT_TYPE_DIRECTIVE) { /* can contain utf8 */ + text_format_fill(&str, &fmt, prev, i); + } + else { + text_format_fill_ascii(&str, &fmt, prev, i); + } } else { str += BLI_str_utf8_size_safe(str) - 1; diff --git a/source/blender/editors/space_text/text_format_py.c b/source/blender/editors/space_text/text_format_py.c index cbccc6a770f..902d60dcb3e 100644 --- a/source/blender/editors/space_text/text_format_py.c +++ b/source/blender/editors/space_text/text_format_py.c @@ -231,9 +231,9 @@ static void txtfmt_py_format_line(SpaceText *st, TextLine *line, const int do_ne /* Not in a string... */ else { /* Deal with comments first */ - if (prev == FMT_TYPE_COMMENT || *str == '#') { - *fmt = FMT_TYPE_COMMENT; - str += BLI_str_utf8_size_safe(str) - 1; + if (*str == '#') { + /* fill the remaining line */ + text_format_fill(&str, &fmt, FMT_TYPE_COMMENT, len - (int)(str - fs.buf)); } else if (*str == '"' || *str == '\'') { /* Strings */ @@ -259,8 +259,7 @@ static void txtfmt_py_format_line(SpaceText *st, TextLine *line, const int do_ne /* Booleans */ else if (prev != FMT_TYPE_DEFAULT && (i = txtfmt_py_find_bool(str)) != -1) { if (i > 0) { - memset(fmt, FMT_TYPE_NUMERAL, i); - i--; fmt += i; str += i; + text_format_fill_ascii(&str, &fmt, FMT_TYPE_NUMERAL, i); } else { str += BLI_str_utf8_size_safe(str) - 1; @@ -285,8 +284,12 @@ static void txtfmt_py_format_line(SpaceText *st, TextLine *line, const int do_ne else if ((i = txtfmt_py_find_decorator(str)) != -1) prev = FMT_TYPE_DIRECTIVE; if (i > 0) { - memset(fmt, prev, i); - i--; fmt += i; str += i; + if (prev == FMT_TYPE_DIRECTIVE) { /* can contain utf8 */ + text_format_fill(&str, &fmt, prev, i); + } + else { + text_format_fill_ascii(&str, &fmt, prev, i); + } } else { str += BLI_str_utf8_size_safe(str) - 1; diff --git a/source/blender/editors/space_time/space_time.c b/source/blender/editors/space_time/space_time.c index 13c1938d77c..e5bd9e62c74 100644 --- a/source/blender/editors/space_time/space_time.c +++ b/source/blender/editors/space_time/space_time.c @@ -92,7 +92,7 @@ static void time_draw_sfra_efra(Scene *scene, View2D *v2d) #define CACHE_DRAW_HEIGHT 3.0f -static void time_draw_cache(SpaceTime *stime, Object *ob) +static void time_draw_cache(SpaceTime *stime, Object *ob, Scene *scene) { PTCacheID *pid; ListBase pidlist; @@ -102,7 +102,7 @@ static void time_draw_cache(SpaceTime *stime, Object *ob) if (!(stime->cache_display & TIME_CACHE_DISPLAY) || (!ob)) return; - BKE_ptcache_ids_from_object(&pidlist, ob, NULL, 0); + BKE_ptcache_ids_from_object(&pidlist, ob, scene, 0); /* iterate over pointcaches on the active object, * add spacetimecache and vertex array for each */ @@ -128,6 +128,9 @@ static void time_draw_cache(SpaceTime *stime, Object *ob) case PTCACHE_TYPE_DYNAMICPAINT: if (!(stime->cache_display & TIME_CACHE_DYNAMICPAINT)) continue; break; + case PTCACHE_TYPE_RIGIDBODY: + if (!(stime->cache_display & TIME_CACHE_RIGIDBODY)) continue; + break; } if (pid->cache->cached_frames == NULL) @@ -193,6 +196,10 @@ static void time_draw_cache(SpaceTime *stime, Object *ob) col[0] = 1.0; col[1] = 0.1; col[2] = 0.75; col[3] = 0.1; break; + case PTCACHE_TYPE_RIGIDBODY: + col[0] = 1.0; col[1] = 0.6; col[2] = 0.0; + col[3] = 0.1; + break; default: BLI_assert(0); col[0] = 1.0; col[1] = 0.0; col[2] = 1.0; @@ -499,7 +506,7 @@ static void time_main_area_draw(const bContext *C, ARegion *ar) draw_markers_time(C, 0); /* caches */ - time_draw_cache(stime, obact); + time_draw_cache(stime, obact, scene); /* reset view matrix */ UI_view2d_view_restore(C); @@ -648,6 +655,7 @@ static void time_init(wmWindowManager *UNUSED(wm), ScrArea *sa) stime->cache_display |= TIME_CACHE_DISPLAY; stime->cache_display |= (TIME_CACHE_SOFTBODY | TIME_CACHE_PARTICLES); stime->cache_display |= (TIME_CACHE_CLOTH | TIME_CACHE_SMOKE | TIME_CACHE_DYNAMICPAINT); + stime->cache_display |= TIME_CACHE_RIGIDBODY; } static SpaceLink *time_duplicate(SpaceLink *sl) diff --git a/source/blender/editors/space_view3d/drawmesh.c b/source/blender/editors/space_view3d/drawmesh.c index fa72f28cc44..70e2e663b33 100644 --- a/source/blender/editors/space_view3d/drawmesh.c +++ b/source/blender/editors/space_view3d/drawmesh.c @@ -458,12 +458,15 @@ static DMDrawOption draw_mcol__set_draw_legacy(MTFace *UNUSED(tface), int has_mc return DM_DRAW_OPTION_NO_MCOL; } -static DMDrawOption draw_tface__set_draw(MTFace *UNUSED(tface), int UNUSED(has_mcol), int matnr) +static DMDrawOption draw_tface__set_draw(MTFace *tface, int UNUSED(has_mcol), int matnr) { Material *ma = give_current_material(Gtexdraw.ob, matnr + 1); if (ma && (ma->game.flag & GEMAT_INVISIBLE)) return 0; + if (tface) + set_draw_settings_cached(0, tface, ma, Gtexdraw); + /* always use color from mcol, as set in update_tface_color_layer */ return DM_DRAW_OPTION_NORMAL; } @@ -937,7 +940,8 @@ static int tex_mat_set_face_editmesh_cb(void *userData, int index) void draw_mesh_textured(Scene *scene, View3D *v3d, RegionView3D *rv3d, Object *ob, DerivedMesh *dm, const int draw_flags) { - if ((!BKE_scene_use_new_shading_nodes(scene)) || (draw_flags & DRAW_MODIFIERS_PREVIEW)) { + /* if not cycles, or preview-modifiers, or drawing matcaps */ + if ((!BKE_scene_use_new_shading_nodes(scene)) || (draw_flags & DRAW_MODIFIERS_PREVIEW) || (v3d->flag2 & V3D_SHOW_SOLID_MATCAP)) { draw_mesh_textured_old(scene, v3d, rv3d, ob, dm, draw_flags); return; } diff --git a/source/blender/editors/space_view3d/drawobject.c b/source/blender/editors/space_view3d/drawobject.c index 7ef8dc49a5d..fc8d5d26455 100644 --- a/source/blender/editors/space_view3d/drawobject.c +++ b/source/blender/editors/space_view3d/drawobject.c @@ -88,6 +88,7 @@ #include "ED_types.h" #include "UI_resources.h" +#include "UI_interface_icons.h" #include "WM_api.h" #include "BLF_api.h" @@ -172,17 +173,26 @@ static void ob_wire_color_blend_theme_id(const unsigned char ob_wire_col[4], con } /* this condition has been made more complex since editmode can draw textures */ -static int check_object_draw_texture(Scene *scene, View3D *v3d, int drawtype) +static bool check_object_draw_texture(Scene *scene, View3D *v3d, int drawtype) { /* texture and material draw modes */ - if (ELEM(v3d->drawtype, OB_TEXTURE, OB_MATERIAL) && drawtype > OB_SOLID) - return TRUE; + if (ELEM(v3d->drawtype, OB_TEXTURE, OB_MATERIAL) && drawtype > OB_SOLID) { + return true; + } /* textured solid */ - if (v3d->drawtype == OB_SOLID && (v3d->flag2 & V3D_SOLID_TEX) && !BKE_scene_use_new_shading_nodes(scene)) - return TRUE; + if ((v3d->drawtype == OB_SOLID) && + (v3d->flag2 & V3D_SOLID_TEX) && + (BKE_scene_use_new_shading_nodes(scene) == false)) + { + return true; + } - return FALSE; + if (v3d->flag2 & V3D_SHOW_SOLID_MATCAP) { + return true; + } + + return false; } static int check_ob_drawface_dot(Scene *sce, View3D *vd, char dt) @@ -210,7 +220,7 @@ static int check_ob_drawface_dot(Scene *sce, View3D *vd, char dt) /* check for glsl drawing */ -int draw_glsl_material(Scene *scene, Object *ob, View3D *v3d, const short dt) +int draw_glsl_material(Scene *scene, Object *ob, View3D *v3d, const char dt) { if (!GPU_glsl_support()) return 0; @@ -220,6 +230,10 @@ int draw_glsl_material(Scene *scene, Object *ob, View3D *v3d, const short dt) return 0; if (ob == OBACT && (ob && ob->mode & OB_MODE_WEIGHT_PAINT)) return 0; + + if (v3d->flag2 & V3D_SHOW_SOLID_MATCAP) + return 1; + if (BKE_scene_use_new_shading_nodes(scene)) return 0; @@ -1081,7 +1095,7 @@ static void draw_transp_spot_volume(Lamp *la, float x, float z) } static void drawlamp(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base, - const short dt, const short dflag, const unsigned char ob_wire_col[4]) + const char dt, const short dflag, const unsigned char ob_wire_col[4]) { Object *ob = base->object; const float pixsize = ED_view3d_pixel_size(rv3d, ob->obmat[3]); @@ -2677,16 +2691,21 @@ static void draw_em_measure_stats(View3D *v3d, Object *ob, BMEditMesh *em, UnitS BMFace *f; int n; -#define DRAW_EM_MEASURE_STATS_FACEAREA() \ - if (BM_elem_flag_test(f, BM_ELEM_SELECT)) { \ - mul_v3_fl(vmid, 1.0f / (float)n); \ - if (unit->system) \ - bUnit_AsString(numstr, sizeof(numstr), \ - (double)(area * unit->scale_length), \ - 3, unit->system, B_UNIT_LENGTH, do_split, FALSE); \ - else \ - BLI_snprintf(numstr, sizeof(numstr), conv_float, area); \ - view3d_cached_text_draw_add(vmid, numstr, 0, txt_flag, col); \ +#define DRAW_EM_MEASURE_STATS_FACEAREA() \ + if (BM_elem_flag_test(f, BM_ELEM_SELECT)) { \ + mul_v3_fl(vmid, 1.0f / (float)n); \ + if (unit->system) { \ + bUnit_AsString(numstr, sizeof(numstr), \ + (double)(area * unit->scale_length * unit->scale_length), \ + 3, unit->system, B_UNIT_AREA, do_split, FALSE); \ + view3d_cached_text_draw_add(vmid, numstr, 0, \ + /* Metric system uses unicode "squared" sign! */ \ + txt_flag ^ V3D_CACHE_TEXT_ASCII, col); \ + } \ + else { \ + BLI_snprintf(numstr, sizeof(numstr), conv_float, area); \ + view3d_cached_text_draw_add(vmid, numstr, 0, txt_flag, col); \ + } \ } (void)0 UI_GetThemeColor3ubv(TH_DRAWEXTRA_FACEAREA, col); @@ -2858,7 +2877,7 @@ static DMDrawOption draw_em_fancy__setGLSLFaceOpts(void *userData, int index) } static void draw_em_fancy(Scene *scene, View3D *v3d, RegionView3D *rv3d, - Object *ob, BMEditMesh *em, DerivedMesh *cageDM, DerivedMesh *finalDM, const short dt) + Object *ob, BMEditMesh *em, DerivedMesh *cageDM, DerivedMesh *finalDM, const char dt) { Mesh *me = ob->data; @@ -3094,7 +3113,7 @@ static void draw_mesh_object_outline(View3D *v3d, Object *ob, DerivedMesh *dm) } static void draw_mesh_fancy(Scene *scene, ARegion *ar, View3D *v3d, RegionView3D *rv3d, Base *base, - const short dt, const unsigned char ob_wire_col[4], const short dflag) + const char dt, const unsigned char ob_wire_col[4], const short dflag) { Object *ob = base->object; Mesh *me = ob->data; @@ -3303,7 +3322,7 @@ static void draw_mesh_fancy(Scene *scene, ARegion *ar, View3D *v3d, RegionView3D glDepthMask(0); /* disable write in zbuffer, selected edge wires show better */ } - dm->drawEdges(dm, (dt == OB_WIRE || totface == 0), me->drawflag & ME_ALLEDGES); + dm->drawEdges(dm, (dt == OB_WIRE || totface == 0), (ob->dtx & OB_DRAW_ALL_EDGES)); if (dt != OB_WIRE && (draw_wire == OBDRAW_WIRE_ON_DEPTH)) { glDepthMask(1); @@ -3329,7 +3348,7 @@ static void draw_mesh_fancy(Scene *scene, ARegion *ar, View3D *v3d, RegionView3D /* returns 1 if nothing was drawn, for detecting to draw an object center */ static int draw_mesh_object(Scene *scene, ARegion *ar, View3D *v3d, RegionView3D *rv3d, Base *base, - const short dt, const unsigned char ob_wire_col[4], const short dflag) + const char dt, const unsigned char ob_wire_col[4], const short dflag) { Object *ob = base->object; Object *obedit = scene->obedit; @@ -3651,7 +3670,7 @@ static void drawCurveDMWired(Object *ob) } /* return 1 when nothing was drawn */ -static int drawCurveDerivedMesh(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base, const short dt) +static int drawCurveDerivedMesh(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base, const char dt) { Object *ob = base->object; DerivedMesh *dm = ob->derivedFinal; @@ -3687,7 +3706,7 @@ static int drawCurveDerivedMesh(Scene *scene, View3D *v3d, RegionView3D *rv3d, B * \return 1 when nothing was drawn */ static int drawDispList_nobackface(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base, - const short dt, const short dflag, const unsigned char ob_wire_col[4]) + const char dt, const short dflag, const unsigned char ob_wire_col[4]) { Object *ob = base->object; ListBase *lb = NULL; @@ -3813,7 +3832,7 @@ static int drawDispList_nobackface(Scene *scene, View3D *v3d, RegionView3D *rv3d return FALSE; } static int drawDispList(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base, - const short dt, const short dflag, const unsigned char ob_wire_col[4]) + const char dt, const short dflag, const unsigned char ob_wire_col[4]) { int retval; @@ -4977,9 +4996,9 @@ static void ob_draw_RE_motion(float com[3], float rotscale[3][3], float itw, flo glEnd(); } -/*place to add drawers */ +/* place to add drawers */ -static void tekenhandlesN(Nurb *nu, short sel, short hide_handles) +static void drawhandlesN(Nurb *nu, short sel, short hide_handles) { BezTriple *bezt; float *fp; @@ -5039,7 +5058,7 @@ static void tekenhandlesN(Nurb *nu, short sel, short hide_handles) glEnd(); } -static void tekenhandlesN_active(Nurb *nu) +static void drawhandlesN_active(Nurb *nu) { BezTriple *bezt; float *fp; @@ -5074,7 +5093,7 @@ static void tekenhandlesN_active(Nurb *nu) glLineWidth(1); } -static void tekenvertsN(Nurb *nu, short sel, short hide_handles, void *lastsel) +static void drawvertsN(Nurb *nu, short sel, short hide_handles, void *lastsel) { BezTriple *bezt; BPoint *bp; @@ -5330,7 +5349,7 @@ static void draw_editnurb(Object *ob, Nurb *nurb, int sel) } static void drawnurb(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base, Nurb *nurb, - const short dt, const short dflag, const unsigned char ob_wire_col[4]) + const char dt, const short dflag, const unsigned char ob_wire_col[4]) { ToolSettings *ts = scene->toolsettings; Object *ob = base->object; @@ -5354,8 +5373,8 @@ static void drawnurb(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base, for (nu = nurb; nu; nu = nu->next) { if (nu->type == CU_BEZIER) { if (index == cu->actnu && !hide_handles) - tekenhandlesN_active(nu); - tekenhandlesN(nu, 0, hide_handles); + drawhandlesN_active(nu); + drawhandlesN(nu, 0, hide_handles); } index++; } @@ -5364,8 +5383,8 @@ static void drawnurb(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base, /* selected handles */ for (nu = nurb; nu; nu = nu->next) { if (nu->type == CU_BEZIER && (cu->drawflag & CU_HIDE_HANDLES) == 0) - tekenhandlesN(nu, 1, hide_handles); - tekenvertsN(nu, 0, hide_handles, NULL); + drawhandlesN(nu, 1, hide_handles); + drawvertsN(nu, 0, hide_handles, NULL); } if (v3d->zbuf) glEnable(GL_DEPTH_TEST); @@ -5416,7 +5435,7 @@ static void drawnurb(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base, if (v3d->zbuf) glDisable(GL_DEPTH_TEST); for (nu = nurb; nu; nu = nu->next) { - tekenvertsN(nu, 1, hide_handles, cu->lastsel); + drawvertsN(nu, 1, hide_handles, cu->lastsel); } if (v3d->zbuf) glEnable(GL_DEPTH_TEST); @@ -5478,39 +5497,6 @@ static void draw_empty_cone(float size) gluDeleteQuadric(qobj); } -/* draw points on curve speed handles */ -#if 0 /* XXX old animation system stuff */ -static void curve_draw_speed(Scene *scene, Object *ob) -{ - Curve *cu = ob->data; - IpoCurve *icu; - BezTriple *bezt; - float loc[4], dir[3]; - int a; - - if (cu->ipo == NULL) - return; - - icu = cu->ipo->curve.first; - if (icu == NULL || icu->totvert < 2) - return; - - glPointSize(UI_GetThemeValuef(TH_VERTEX_SIZE)); - bglBegin(GL_POINTS); - - for (a = 0, bezt = icu->bezt; a < icu->totvert; a++, bezt++) { - if (where_on_path(ob, bezt->vec[1][1], loc, dir)) { - UI_ThemeColor((bezt->f2 & SELECT) && ob == OBACT ? TH_VERTEX_SELECT : TH_VERTEX); - bglVertex3fv(loc); - } - } - - glPointSize(1.0); - bglEnd(); -} -#endif /* XXX old animation system stuff */ - - static void draw_textcurs(RegionView3D *rv3d, float textcurs[4][2]) { cpack(0); @@ -5614,7 +5600,7 @@ static void drawcircle_size(float size) } -/* needs fixing if non-identity matrice used */ +/* needs fixing if non-identity matrix used */ static void drawtube(const float vec[3], float radius, float height, float tmat[4][4]) { float cur[3]; @@ -5636,7 +5622,8 @@ static void drawtube(const float vec[3], float radius, float height, float tmat[ glVertex3f(cur[0], cur[1] - radius, cur[2]); glEnd(); } -/* needs fixing if non-identity matrice used */ + +/* needs fixing if non-identity matrix used */ static void drawcone(const float vec[3], float radius, float height, float tmat[4][4]) { float cur[3]; @@ -5657,9 +5644,10 @@ static void drawcone(const float vec[3], float radius, float height, float tmat[ glVertex3f(cur[0], cur[1] - radius, cur[2]); glEnd(); } + /* return TRUE if nothing was drawn */ static int drawmball(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base, - const short dt, const short dflag, const unsigned char ob_wire_col[4]) + const char dt, const short dflag, const unsigned char ob_wire_col[4]) { Object *ob = base->object; MetaBall *mb; @@ -5705,7 +5693,6 @@ static int drawmball(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base, } while (ml) { - /* draw radius */ if (mb->editelems) { if ((dflag & DRAW_CONSTCOLOR) == 0) { @@ -6292,6 +6279,34 @@ static void draw_object_wire_color(Scene *scene, Base *base, unsigned char r_ob_ r_ob_wire_col[3] = 255; } +static void draw_object_matcap_check(Scene *scene, View3D *v3d, Object *ob) +{ + /* fixed rule, active object draws as matcap */ + if (ob == OBACT) { + if (ob->mode & (OB_MODE_VERTEX_PAINT | OB_MODE_WEIGHT_PAINT | OB_MODE_TEXTURE_PAINT)) + return; + + if (v3d->defmaterial == NULL) { + extern Material defmaterial; + + v3d->defmaterial = MEM_mallocN(sizeof(Material), "matcap material"); + *(v3d->defmaterial) = defmaterial; + v3d->defmaterial->gpumaterial.first = v3d->defmaterial->gpumaterial.last = NULL; + v3d->defmaterial->preview = NULL; + } + /* first time users */ + if (v3d->matcap_icon == 0) + v3d->matcap_icon = ICON_MATCAP_01; + + if (v3d->defmaterial->preview == NULL) + v3d->defmaterial->preview = UI_icon_to_preview(v3d->matcap_icon); + + /* signal to all material checks, gets cleared below */ + v3d->flag2 |= V3D_SHOW_SOLID_MATCAP; + } + +} + /** * main object drawing function, draws in selection * \param dflag (draw flag) can be DRAW_PICKING and/or DRAW_CONSTCOLOR, DRAW_SCENESET @@ -6308,7 +6323,9 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, const short unsigned char _ob_wire_col[4]; /* dont initialize this */ unsigned char *ob_wire_col = NULL; /* dont initialize this, use NULL crashes as a way to find invalid use */ int i, selstart, selend, empty_object = 0; - short dt, dtx, zbufoff = 0; + short dtx; + char dt; + short zbufoff = 0; const short is_obact = (ob == OBACT); /* only once set now, will be removed too, should become a global standard */ @@ -6379,6 +6396,10 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, const short dt = MIN2(dt, ob->dt); if (v3d->zbuf == 0 && dt > OB_WIRE) dt = OB_WIRE; dtx = 0; + + /* matcap check */ + if (dt == OB_SOLID && (v3d->flag2 & V3D_SOLID_MATCAP)) + draw_object_matcap_check(scene, v3d, ob); /* faceselect exception: also draw solid when (dt == wire), except in editmode */ if (is_obact && (ob->mode & (OB_MODE_VERTEX_PAINT | OB_MODE_WEIGHT_PAINT | OB_MODE_TEXTURE_PAINT))) { @@ -6822,7 +6843,7 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, const short } if (ob->gameflag & OB_BOUNDS) { - if (ob->boundtype != ob->collision_boundtype || (dtx & OB_BOUNDBOX) == 0) { + if (ob->boundtype != ob->collision_boundtype || (dtx & OB_DRAWBOUNDOX) == 0) { setlinestyle(2); draw_bounding_volume(scene, ob, ob->collision_boundtype); @@ -6836,7 +6857,7 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, const short if (dtx & OB_AXIS) { drawaxes(1.0f, OB_ARROWS); } - if (dtx & OB_BOUNDBOX) { + if (dtx & OB_DRAWBOUNDOX) { draw_bounding_volume(scene, ob, ob->boundtype); } if (dtx & OB_TEXSPACE) { @@ -6879,7 +6900,9 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, const short /* return warning, this is cached text draw */ invert_m4_m4(ob->imat, ob->obmat); view3d_cached_text_draw_end(v3d, ar, 1, NULL); - + /* return warning, clear temp flag */ + v3d->flag2 &= ~V3D_SHOW_SOLID_MATCAP; + glLoadMatrixf(rv3d->viewmat); if (zbufoff) { @@ -7319,7 +7342,7 @@ static void draw_object_mesh_instance(Scene *scene, View3D *v3d, RegionView3D *r if (dm) dm->release(dm); } -void draw_object_instance(Scene *scene, View3D *v3d, RegionView3D *rv3d, Object *ob, const short dt, int outline) +void draw_object_instance(Scene *scene, View3D *v3d, RegionView3D *rv3d, Object *ob, const char dt, int outline) { if (ob == NULL) return; diff --git a/source/blender/editors/space_view3d/space_view3d.c b/source/blender/editors/space_view3d/space_view3d.c index 1d87895d64a..b2d58cf41de 100644 --- a/source/blender/editors/space_view3d/space_view3d.c +++ b/source/blender/editors/space_view3d/space_view3d.c @@ -32,6 +32,7 @@ #include <string.h> #include <stdio.h> +#include "DNA_material_types.h" #include "DNA_object_types.h" #include "DNA_scene_types.h" @@ -42,16 +43,18 @@ #include "BLI_rand.h" #include "BLI_utildefines.h" -#include "BKE_object.h" #include "BKE_context.h" +#include "BKE_icons.h" +#include "BKE_object.h" #include "BKE_screen.h" #include "ED_space_api.h" #include "ED_screen.h" #include "ED_object.h" -#include "BIF_gl.h" +#include "GPU_material.h" +#include "BIF_gl.h" #include "WM_api.h" #include "WM_types.h" @@ -335,6 +338,14 @@ static void view3d_free(SpaceLink *sl) if (vd->localvd) MEM_freeN(vd->localvd); if (vd->properties_storage) MEM_freeN(vd->properties_storage); + + /* matcap material, its preview rect gets freed via icons */ + if (vd->defmaterial) { + if (vd->defmaterial->gpumaterial.first) + GPU_material_free(vd->defmaterial); + BKE_previewimg_free(&vd->defmaterial->preview); + MEM_freeN(vd->defmaterial); + } } @@ -365,6 +376,8 @@ static SpaceLink *view3d_duplicate(SpaceLink *sl) /* copy or clear inside new stuff */ + v3dn->defmaterial = NULL; + BLI_duplicatelist(&v3dn->bgpicbase, &v3do->bgpicbase); v3dn->properties_storage = NULL; @@ -584,6 +597,9 @@ static void view3d_main_area_free(ARegion *ar) if (rv3d->depths->depths) MEM_freeN(rv3d->depths->depths); MEM_freeN(rv3d->depths); } + if (rv3d->sms) { + MEM_freeN(rv3d->sms); + } MEM_freeN(rv3d); ar->regiondata = NULL; } diff --git a/source/blender/editors/space_view3d/view3d_draw.c b/source/blender/editors/space_view3d/view3d_draw.c index 67344a9804b..ff63f16d125 100644 --- a/source/blender/editors/space_view3d/view3d_draw.c +++ b/source/blender/editors/space_view3d/view3d_draw.c @@ -1927,7 +1927,8 @@ static void draw_dupli_objects_color(Scene *scene, ARegion *ar, View3D *v3d, Bas BoundBox bb, *bb_tmp; /* use a copy because draw_object, calls clear_mesh_caches */ GLuint displist = 0; short transflag, use_displist = -1; /* -1 is initialize */ - char dt, dtx; + char dt; + short dtx; if (base->object->restrictflag & OB_RESTRICT_VIEW) return; @@ -2882,7 +2883,7 @@ static int view3d_main_area_draw_engine(const bContext *C, ARegion *ar, int draw if (!(type->view_update && type->view_draw)) return 0; - engine = RE_engine_create(type); + engine = RE_engine_create_ex(type, TRUE); engine->tile_x = scene->r.tilex; engine->tile_y = scene->r.tiley; @@ -3458,14 +3459,14 @@ static void bl_debug_draw(void) if (_bl_debug_draw_quads_tot) { int i; cpack(0x00FF0000); - glBegin(GL_LINE_LOOP); for (i = 0; i < _bl_debug_draw_quads_tot; i ++) { + glBegin(GL_LINE_LOOP); glVertex3fv(_bl_debug_draw_quads[i][0]); glVertex3fv(_bl_debug_draw_quads[i][1]); glVertex3fv(_bl_debug_draw_quads[i][2]); glVertex3fv(_bl_debug_draw_quads[i][3]); + glEnd(); } - glEnd(); } if (_bl_debug_draw_edges_tot) { int i; diff --git a/source/blender/editors/space_view3d/view3d_intern.h b/source/blender/editors/space_view3d/view3d_intern.h index a6daf610052..c8f0fe44433 100644 --- a/source/blender/editors/space_view3d/view3d_intern.h +++ b/source/blender/editors/space_view3d/view3d_intern.h @@ -119,8 +119,8 @@ void draw_motion_paths_cleanup(View3D *v3d); /* drawobject.c */ void draw_object(Scene *scene, struct ARegion *ar, View3D *v3d, Base *base, const short dflag); -int draw_glsl_material(Scene *scene, struct Object *ob, View3D *v3d, const short dt); -void draw_object_instance(Scene *scene, View3D *v3d, RegionView3D *rv3d, struct Object *ob, const short dt, int outline); +int draw_glsl_material(Scene *scene, struct Object *ob, View3D *v3d, const char dt); +void draw_object_instance(Scene *scene, View3D *v3d, RegionView3D *rv3d, struct Object *ob, const char dt, int outline); void draw_object_backbufsel(Scene *scene, View3D *v3d, RegionView3D *rv3d, struct Object *ob); void drawaxes(float size, char drawtype); diff --git a/source/blender/editors/space_view3d/view3d_ops.c b/source/blender/editors/space_view3d/view3d_ops.c index 615ae71cf9b..bf1c5404c0e 100644 --- a/source/blender/editors/space_view3d/view3d_ops.c +++ b/source/blender/editors/space_view3d/view3d_ops.c @@ -39,14 +39,14 @@ #include "DNA_space_types.h" #include "DNA_view3d_types.h" -#include "BKE_blender.h" -#include "BKE_context.h" -#include "BKE_main.h" - #include "BLI_math.h" #include "BLI_blenlib.h" #include "BLI_utildefines.h" +#include "BKE_blender.h" +#include "BKE_context.h" +#include "BKE_main.h" + #include "RNA_access.h" #include "WM_api.h" diff --git a/source/blender/editors/space_view3d/view3d_view.c b/source/blender/editors/space_view3d/view3d_view.c index 41d092ce2b1..fba1ce328ba 100644 --- a/source/blender/editors/space_view3d/view3d_view.c +++ b/source/blender/editors/space_view3d/view3d_view.c @@ -111,17 +111,43 @@ float *give_cursor(Scene *scene, View3D *v3d) /* ****************** smooth view operator ****************** */ /* This operator is one of the 'timer refresh' ones like animation playback */ +struct SmoothView3DState { + float dist; + float lens; + float quat[4]; + float ofs[3]; +}; + struct SmoothView3DStore { - float orig_dist, new_dist; - float orig_lens, new_lens; - float orig_quat[4], new_quat[4]; - float orig_ofs[3], new_ofs[3]; - - int to_camera, orig_view; - + /* source*/ + struct SmoothView3DState src; /* source */ + struct SmoothView3DState dst; /* destination */ + struct SmoothView3DState org; /* original */ + + bool to_camera; + char org_view; + double time_allowed; }; +static void view3d_smooth_view_state_backup(struct SmoothView3DState *sms_state, + const View3D *v3d, const RegionView3D *rv3d) +{ + copy_v3_v3(sms_state->ofs, rv3d->ofs); + copy_qt_qt(sms_state->quat, rv3d->viewquat); + sms_state->dist = rv3d->dist; + sms_state->lens = v3d->lens; +} + +static void view3d_smooth_view_state_restore(const struct SmoothView3DState *sms_state, + View3D *v3d, RegionView3D *rv3d) +{ + copy_v3_v3(rv3d->ofs, sms_state->ofs); + copy_qt_qt(rv3d->viewquat, sms_state->quat); + rv3d->dist = sms_state->dist; + v3d->lens = sms_state->lens; +} + /* will start timer if appropriate */ /* the arguments are the desired situation */ void view3d_smooth_view(bContext *C, View3D *v3d, ARegion *ar, Object *oldcamera, Object *camera, @@ -132,15 +158,22 @@ void view3d_smooth_view(bContext *C, View3D *v3d, ARegion *ar, Object *oldcamera ScrArea *sa = CTX_wm_area(C); RegionView3D *rv3d = ar->regiondata; - struct SmoothView3DStore sms = {0}; - short ok = FALSE; + struct SmoothView3DStore sms = {{0}}; + bool ok = false; /* initialize sms */ - copy_v3_v3(sms.new_ofs, rv3d->ofs); - copy_qt_qt(sms.new_quat, rv3d->viewquat); - sms.new_dist = rv3d->dist; - sms.new_lens = v3d->lens; - sms.to_camera = FALSE; + view3d_smooth_view_state_backup(&sms.dst, v3d, rv3d); + view3d_smooth_view_state_backup(&sms.src, v3d, rv3d); + /* if smoothview runs multiple times... */ + if (rv3d->sms == NULL) { + view3d_smooth_view_state_backup(&sms.org, v3d, rv3d); + sms.org_view = rv3d->view; + } + else { + sms.org = rv3d->sms->org; + sms.org_view = rv3d->sms->org_view; + } + /* sms.to_camera = false; */ /* initizlized to zero anyway */ /* note on camera locking, this is a little confusing but works ok. * we may be changing the view 'as if' there is no active camera, but in fact @@ -155,50 +188,43 @@ void view3d_smooth_view(bContext *C, View3D *v3d, ARegion *ar, Object *oldcamera } /* store the options we want to end with */ - if (ofs) copy_v3_v3(sms.new_ofs, ofs); - if (quat) copy_qt_qt(sms.new_quat, quat); - if (dist) sms.new_dist = *dist; - if (lens) sms.new_lens = *lens; + if (ofs) copy_v3_v3(sms.dst.ofs, ofs); + if (quat) copy_qt_qt(sms.dst.quat, quat); + if (dist) sms.dst.dist = *dist; + if (lens) sms.dst.lens = *lens; if (camera) { - sms.new_dist = ED_view3d_offset_distance(camera->obmat, ofs, VIEW3D_DIST_FALLBACK); - ED_view3d_from_object(camera, sms.new_ofs, sms.new_quat, &sms.new_dist, &sms.new_lens); - sms.to_camera = TRUE; /* restore view3d values in end */ + sms.dst.dist = ED_view3d_offset_distance(camera->obmat, ofs, VIEW3D_DIST_FALLBACK); + ED_view3d_from_object(camera, sms.dst.ofs, sms.dst.quat, &sms.dst.dist, &sms.dst.lens); + sms.to_camera = true; /* restore view3d values in end */ } if (C && U.smooth_viewtx) { - int changed = FALSE; /* zero means no difference */ + bool changed = false; /* zero means no difference */ if (oldcamera != camera) - changed = TRUE; - else if (sms.new_dist != rv3d->dist) - changed = TRUE; - else if (sms.new_lens != v3d->lens) - changed = TRUE; - else if (!equals_v3v3(sms.new_ofs, rv3d->ofs)) - changed = TRUE; - else if (!equals_v4v4(sms.new_quat, rv3d->viewquat)) - changed = TRUE; + changed = true; + else if (sms.dst.dist != rv3d->dist) + changed = true; + else if (sms.dst.lens != v3d->lens) + changed = true; + else if (!equals_v3v3(sms.dst.ofs, rv3d->ofs)) + changed = true; + else if (!equals_v4v4(sms.dst.quat, rv3d->viewquat)) + changed = true; /* The new view is different from the old one * so animate the view */ if (changed) { - /* original values */ if (oldcamera) { - sms.orig_dist = ED_view3d_offset_distance(oldcamera->obmat, rv3d->ofs, 0.0f); - ED_view3d_from_object(oldcamera, sms.orig_ofs, sms.orig_quat, &sms.orig_dist, &sms.orig_lens); - } - else { - copy_v3_v3(sms.orig_ofs, rv3d->ofs); - copy_qt_qt(sms.orig_quat, rv3d->viewquat); - sms.orig_dist = rv3d->dist; - sms.orig_lens = v3d->lens; + sms.src.dist = ED_view3d_offset_distance(oldcamera->obmat, rv3d->ofs, 0.0f); + /* this */ + ED_view3d_from_object(oldcamera, sms.src.ofs, sms.src.quat, &sms.src.dist, &sms.src.lens); } /* grid draw as floor */ if ((rv3d->viewlock & RV3D_LOCKED) == 0) { /* use existing if exists, means multiple calls to smooth view wont loose the original 'view' setting */ - sms.orig_view = rv3d->sms ? rv3d->sms->orig_view : rv3d->view; rv3d->view = RV3D_VIEW_USER; } @@ -212,8 +238,8 @@ void view3d_smooth_view(bContext *C, View3D *v3d, ARegion *ar, Object *oldcamera float vec1[3] = {0, 0, 1}, vec2[3] = {0, 0, 1}; float q1[4], q2[4]; - invert_qt_qt(q1, sms.new_quat); - invert_qt_qt(q2, sms.orig_quat); + invert_qt_qt(q1, sms.dst.quat); + invert_qt_qt(q2, sms.src.quat); mul_qt_v3(q1, vec1); mul_qt_v3(q2, vec2); @@ -223,36 +249,45 @@ void view3d_smooth_view(bContext *C, View3D *v3d, ARegion *ar, Object *oldcamera } /* ensure it shows correct */ - if (sms.to_camera) rv3d->persp = RV3D_PERSP; + if (sms.to_camera) { + rv3d->persp = RV3D_PERSP; + } rv3d->rflag |= RV3D_NAVIGATING; + /* not essential but in some cases the caller will tag the area for redraw, + * and in that case we can get a ficker of the 'org' user view but we want to see 'src' */ + view3d_smooth_view_state_restore(&sms.src, v3d, rv3d); + /* keep track of running timer! */ - if (rv3d->sms == NULL) + if (rv3d->sms == NULL) { rv3d->sms = MEM_mallocN(sizeof(struct SmoothView3DStore), "smoothview v3d"); + } *rv3d->sms = sms; - if (rv3d->smooth_timer) + if (rv3d->smooth_timer) { WM_event_remove_timer(wm, win, rv3d->smooth_timer); + } /* TIMER1 is hardcoded in keymap */ rv3d->smooth_timer = WM_event_add_timer(wm, win, TIMER1, 1.0 / 100.0); /* max 30 frs/sec */ - - ok = TRUE; + + ok = true; } } /* if we get here nothing happens */ - if (ok == FALSE) { - if (sms.to_camera == FALSE) { - copy_v3_v3(rv3d->ofs, sms.new_ofs); - copy_qt_qt(rv3d->viewquat, sms.new_quat); - rv3d->dist = sms.new_dist; - v3d->lens = sms.new_lens; + if (ok == false) { + if (sms.to_camera == false) { + copy_v3_v3(rv3d->ofs, sms.dst.ofs); + copy_qt_qt(rv3d->viewquat, sms.dst.quat); + rv3d->dist = sms.dst.dist; + v3d->lens = sms.dst.lens; ED_view3d_camera_lock_sync(v3d, rv3d); } - if (rv3d->viewlock & RV3D_BOXVIEW) + if (rv3d->viewlock & RV3D_BOXVIEW) { view3d_boxview_copy(sa, ar); + } ED_region_tag_redraw(ar); } @@ -281,22 +316,16 @@ static int view3d_smoothview_invoke(bContext *C, wmOperator *UNUSED(op), wmEvent /* if we went to camera, store the original */ if (sms->to_camera) { rv3d->persp = RV3D_CAMOB; - copy_v3_v3(rv3d->ofs, sms->orig_ofs); - copy_qt_qt(rv3d->viewquat, sms->orig_quat); - rv3d->dist = sms->orig_dist; - v3d->lens = sms->orig_lens; + view3d_smooth_view_state_restore(&sms->org, v3d, rv3d); } else { - copy_v3_v3(rv3d->ofs, sms->new_ofs); - copy_qt_qt(rv3d->viewquat, sms->new_quat); - rv3d->dist = sms->new_dist; - v3d->lens = sms->new_lens; + view3d_smooth_view_state_restore(&sms->dst, v3d, rv3d); ED_view3d_camera_lock_sync(v3d, rv3d); } if ((rv3d->viewlock & RV3D_LOCKED) == 0) { - rv3d->view = sms->orig_view; + rv3d->view = sms->org_view; } MEM_freeN(rv3d->sms); @@ -312,11 +341,11 @@ static int view3d_smoothview_invoke(bContext *C, wmOperator *UNUSED(op), wmEvent step_inv = 1.0f - step; - interp_v3_v3v3(rv3d->ofs, sms->orig_ofs, sms->new_ofs, step); - interp_qt_qtqt(rv3d->viewquat, sms->orig_quat, sms->new_quat, step); + interp_v3_v3v3(rv3d->ofs, sms->src.ofs, sms->dst.ofs, step); + interp_qt_qtqt(rv3d->viewquat, sms->src.quat, sms->dst.quat, step); - rv3d->dist = sms->new_dist * step + sms->orig_dist * step_inv; - v3d->lens = sms->new_lens * step + sms->orig_lens * step_inv; + rv3d->dist = sms->dst.dist * step + sms->src.dist * step_inv; + v3d->lens = sms->dst.lens * step + sms->src.lens * step_inv; ED_view3d_camera_lock_sync(v3d, rv3d); } @@ -325,12 +354,16 @@ static int view3d_smoothview_invoke(bContext *C, wmOperator *UNUSED(op), wmEvent view3d_boxview_copy(CTX_wm_area(C), CTX_wm_region(C)); /* note: this doesn't work right because the v3d->lens is now used in ortho mode r51636, - * when switching camera in quad-view the other ortho views would zoom & reset. */ -#if 0 - WM_event_add_notifier(C, NC_SPACE | ND_SPACE_VIEW3D, v3d); -#else - ED_region_tag_redraw(CTX_wm_region(C)); -#endif + * when switching camera in quad-view the other ortho views would zoom & reset. + * + * For now only redraw all regions when smoothview finishes. + */ + if (step >= 1.0f) { + WM_event_add_notifier(C, NC_SPACE | ND_SPACE_VIEW3D, v3d); + } + else { + ED_region_tag_redraw(CTX_wm_region(C)); + } return OPERATOR_FINISHED; } @@ -846,7 +879,8 @@ short view3d_opengl_select(ViewContext *vc, unsigned int *buffer, unsigned int b ARegion *ar = vc->ar; rctf rect; short code, hits; - char dt, dtx; + char dt; + short dtx; G.f |= G_PICKSEL; diff --git a/source/blender/editors/transform/transform.c b/source/blender/editors/transform/transform.c index 5b5e5206e9c..d29326db6b0 100644 --- a/source/blender/editors/transform/transform.c +++ b/source/blender/editors/transform/transform.c @@ -52,12 +52,14 @@ #include "DNA_movieclip_types.h" #include "DNA_scene_types.h" /* PET modes */ -#include "RNA_access.h" - -#include "BIF_gl.h" -#include "BIF_glutil.h" - -#include "BLF_api.h" +#include "BLI_utildefines.h" +#include "BLI_math.h" +#include "BLI_rect.h" +#include "BLI_listbase.h" +#include "BLI_string.h" +#include "BLI_ghash.h" +#include "BLI_linklist.h" +#include "BLI_smallhash.h" #include "BKE_nla.h" #include "BKE_bmesh.h" @@ -69,6 +71,9 @@ #include "BKE_unit.h" #include "BKE_mask.h" +#include "BIF_gl.h" +#include "BIF_glutil.h" + #include "ED_image.h" #include "ED_keyframing.h" #include "ED_screen.h" @@ -79,25 +84,25 @@ #include "ED_clip.h" #include "ED_mask.h" -#include "UI_view2d.h" #include "WM_types.h" #include "WM_api.h" -#include "BLI_math.h" -#include "BLI_blenlib.h" -#include "BLI_utildefines.h" -#include "BLI_ghash.h" -#include "BLI_linklist.h" -#include "BLI_smallhash.h" -#include "BLI_array.h" - +#include "UI_view2d.h" #include "UI_interface_icons.h" #include "UI_resources.h" +#include "RNA_access.h" + +#include "BLF_api.h" + #include "transform.h" static void drawTransformApply(const struct bContext *C, ARegion *ar, void *arg); static int doEdgeSlide(TransInfo *t, float perc); +static int doVertSlide(TransInfo *t, float perc); + +static void drawEdgeSlide(const struct bContext *C, TransInfo *t); +static void drawVertSlide(const struct bContext *C, TransInfo *t); /* ************************** SPACE DEPENDANT CODE **************************** */ @@ -875,19 +880,52 @@ int transformEvent(TransInfo *t, wmEvent *event) break; case TFM_MODAL_TRANSLATE: /* only switch when... */ - if (ELEM3(t->mode, TFM_ROTATION, TFM_RESIZE, TFM_TRACKBALL) ) { + if (ELEM5(t->mode, TFM_ROTATION, TFM_RESIZE, TFM_TRACKBALL, TFM_EDGE_SLIDE, TFM_VERT_SLIDE)) { + if (t->mode == TFM_EDGE_SLIDE) { + freeEdgeSlideVerts(t); + } + else if (t->mode == TFM_VERT_SLIDE) { + freeVertSlideVerts(t); + } resetTransRestrictions(t); restoreTransObjects(t); initTranslation(t); initSnapping(t, NULL); // need to reinit after mode change t->redraw |= TREDRAW_HARD; + WM_event_add_mousemove(t->context); } - else if (t->mode == TFM_TRANSLATION) { - if (t->options & (CTX_MOVIECLIP | CTX_MASK)) { - restoreTransObjects(t); + else { + if (t->obedit && t->obedit->type == OB_MESH) { + if ((t->mode == TFM_TRANSLATION) && (t->spacetype == SPACE_VIEW3D)) { + resetTransRestrictions(t); + restoreTransObjects(t); - t->flag ^= T_ALT_TRANSFORM; - t->redraw |= TREDRAW_HARD; + /* first try edge slide */ + initEdgeSlide(t); + /* if that fails, do vertex slide */ + if (t->state == TRANS_CANCEL) { + t->state = TRANS_STARTING; + initVertSlide(t); + } + /* vert slide can fail on unconnected vertices (rare but possible) */ + if (t->state == TRANS_CANCEL) { + t->state = TRANS_STARTING; + resetTransRestrictions(t); + restoreTransObjects(t); + initTranslation(t); + } + initSnapping(t, NULL); // need to reinit after mode change + t->redraw |= TREDRAW_HARD; + WM_event_add_mousemove(t->context); + } + } + else if (t->options & (CTX_MOVIECLIP | CTX_MASK)) { + if (t->mode == TFM_TRANSLATION) { + restoreTransObjects(t); + + t->flag ^= T_ALT_TRANSFORM; + t->redraw |= TREDRAW_HARD; + } } } break; @@ -1600,7 +1638,10 @@ static void drawTransformView(const struct bContext *C, ARegion *UNUSED(ar), voi drawConstraint(t); drawPropCircle(C, t); drawSnapping(C, t); - drawNonPropEdge(C, t); + + /* edge slide, vert slide */ + drawEdgeSlide(C, t); + drawVertSlide(C, t); } /* just draw a little warning message in the top-right corner of the viewport to warn that autokeying is enabled */ @@ -1949,6 +1990,9 @@ int initTransform(bContext *C, TransInfo *t, wmOperator *op, wmEvent *event, int case TFM_EDGE_SLIDE: initEdgeSlide(t); break; + case TFM_VERT_SLIDE: + initVertSlide(t); + break; case TFM_BONE_ROLL: initBoneRoll(t); break; @@ -2080,12 +2124,6 @@ void transformApply(bContext *C, TransInfo *t) t->state = TRANS_CONFIRM; } - if (BKE_ptcache_get_continue_physics()) { - // TRANSFORM_FIX_ME - //do_screenhandlers(G.curscreen); - t->redraw |= TREDRAW_HARD; - } - t->context = NULL; } @@ -4902,29 +4940,43 @@ static BMLoop *get_next_loop(BMVert *v, BMLoop *l, return NULL; } -static void calcNonProportionalEdgeSlide(TransInfo *t, SlideData *sld, const float mval[2]) +static void calcNonProportionalEdgeSlide(TransInfo *t, EdgeSlideData *sld, const float mval[2]) { - TransDataSlideVert *sv = sld->sv; + TransDataEdgeSlideVert *sv = sld->sv; if (sld->totsv > 0) { + ARegion *ar = t->ar; + RegionView3D *rv3d = NULL; + float projectMat[4][4]; + int i = 0; - float v_proj[3]; + float v_proj[2]; float dist = 0; float min_dist = FLT_MAX; + if (t->spacetype == SPACE_VIEW3D) { + /* background mode support */ + rv3d = t->ar ? t->ar->regiondata : NULL; + } + + if (!rv3d) { + /* ok, let's try to survive this */ + unit_m4(projectMat); + } + else { + ED_view3d_ob_project_mat_get(rv3d, t->obedit, projectMat); + } + for (i = 0; i < sld->totsv; i++, sv++) { /* Set length */ sv->edge_len = len_v3v3(sv->upvec, sv->downvec); - mul_v3_m4v3(v_proj, t->obedit->obmat, sv->v->co); - /* allow points behind the view [#33643] */ - if (ED_view3d_project_float_global(t->ar, v_proj, v_proj, V3D_PROJ_TEST_NOP) == V3D_PROJ_RET_OK) { - dist = len_squared_v2v2(mval, v_proj); - if (dist < min_dist) { - min_dist = dist; - sld->curr_sv_index = i; - } + ED_view3d_project_float_v2_m4(ar, sv->v->co, v_proj, projectMat); + dist = len_squared_v2v2(mval, v_proj); + if (dist < min_dist) { + min_dist = dist; + sld->curr_sv_index = i; } } } @@ -4933,17 +4985,17 @@ static void calcNonProportionalEdgeSlide(TransInfo *t, SlideData *sld, const flo } } -static int createSlideVerts(TransInfo *t) +static int createEdgeSlideVerts(TransInfo *t) { BMEditMesh *em = BMEdit_FromObject(t->obedit); BMesh *bm = em->bm; BMIter iter; BMEdge *e, *e1; BMVert *v, *v2, *first; - TransDataSlideVert *sv_array; + TransDataEdgeSlideVert *sv_array; BMBVHTree *btree; SmallHash table; - SlideData *sld = MEM_callocN(sizeof(*sld), "sld"); + EdgeSlideData *sld = MEM_callocN(sizeof(*sld), "sld"); View3D *v3d = NULL; RegionView3D *rv3d = NULL; ARegion *ar = t->ar; @@ -5040,7 +5092,7 @@ static int createSlideVerts(TransInfo *t) return 0; } - sv_array = MEM_callocN(sizeof(TransDataSlideVert) * j, "sv_array"); + sv_array = MEM_callocN(sizeof(TransDataEdgeSlideVert) * j, "sv_array"); loop_nr = 0; j = 0; @@ -5102,7 +5154,7 @@ static int createSlideVerts(TransInfo *t) /*iterate over the loop*/ first = v; do { - TransDataSlideVert *sv = sv_array + j; + TransDataEdgeSlideVert *sv = sv_array + j; sv->v = v; sv->origvert = *v; @@ -5272,7 +5324,7 @@ static int createSlideVerts(TransInfo *t) if (rv3d) calcNonProportionalEdgeSlide(t, sld, mval); - sld->origfaces_init = TRUE; + sld->origfaces_init = true; sld->em = em; /*zero out start*/ @@ -5305,10 +5357,10 @@ static int createSlideVerts(TransInfo *t) return 1; } -void projectSVData(TransInfo *t, int final) +void projectEdgeSlideData(TransInfo *t, bool is_final) { - SlideData *sld = t->customData; - TransDataSlideVert *sv; + EdgeSlideData *sld = t->customData; + TransDataEdgeSlideVert *sv; BMEditMesh *em = sld->em; SmallHash visit; int i; @@ -5435,7 +5487,7 @@ void projectSVData(TransInfo *t, int final) * and we do not want to mess up other shape keys */ BM_loop_interp_from_face(em->bm, l, f_copy_flip, FALSE, FALSE); - if (final) { + if (is_final) { BM_loop_interp_multires(em->bm, l, f_copy_flip); if (f_copy != f_copy_flip) { BM_loop_interp_multires(em->bm, l, f_copy); @@ -5459,7 +5511,7 @@ void projectSVData(TransInfo *t, int final) BLI_smallhash_release(&visit); } -void freeSlideTempFaces(SlideData *sld) +void freeEdgeSlideTempFaces(EdgeSlideData *sld) { if (sld->origfaces_init) { SmallHashIter hiter; @@ -5472,7 +5524,7 @@ void freeSlideTempFaces(SlideData *sld) BLI_smallhash_release(&sld->origfaces); - sld->origfaces_init = FALSE; + sld->origfaces_init = false; /* arrays are dirty from removing faces: EDBM_index_arrays_free */ EDBM_update_generic(sld->em, FALSE, TRUE); @@ -5480,13 +5532,13 @@ void freeSlideTempFaces(SlideData *sld) } -void freeSlideVerts(TransInfo *t) +void freeEdgeSlideVerts(TransInfo *t) { - SlideData *sld = t->customData; + EdgeSlideData *sld = t->customData; #if 0 /*BMESH_TODO*/ if (me->drawflag & ME_DRAWEXTRA_EDGELEN) { - TransDataSlideVert *sv; + TransDataEdgeSlideVert *sv; LinkNode *look = sld->vertlist; GHash *vertgh = sld->vhash; while (look) { @@ -5503,7 +5555,7 @@ void freeSlideVerts(TransInfo *t) if (!sld) return; - freeSlideTempFaces(sld); + freeEdgeSlideTempFaces(sld); bmesh_edit_end(sld->em->bm, BMO_OP_FLAG_UNTAN_MULTIRES); @@ -5519,13 +5571,13 @@ void freeSlideVerts(TransInfo *t) void initEdgeSlide(TransInfo *t) { - SlideData *sld; + EdgeSlideData *sld; t->mode = TFM_EDGE_SLIDE; t->transform = EdgeSlide; t->handleEvent = handleEventEdgeSlide; - if (!createSlideVerts(t)) { + if (!createEdgeSlideVerts(t)) { t->state = TRANS_CANCEL; return; } @@ -5535,7 +5587,7 @@ void initEdgeSlide(TransInfo *t) if (!sld) return; - t->customFree = freeSlideVerts; + t->customFree = freeEdgeSlideVerts; /* set custom point first if you want value to be initialized by init */ setCustomPoints(t, &t->mouse, sld->end, sld->start); @@ -5555,7 +5607,7 @@ void initEdgeSlide(TransInfo *t) int handleEventEdgeSlide(struct TransInfo *t, struct wmEvent *event) { if (t->mode == TFM_EDGE_SLIDE) { - SlideData *sld = t->customData; + EdgeSlideData *sld = t->customData; if (sld) { switch (event->type) { @@ -5598,17 +5650,17 @@ int handleEventEdgeSlide(struct TransInfo *t, struct wmEvent *event) return 0; } -void drawNonPropEdge(const struct bContext *C, TransInfo *t) +void drawEdgeSlide(const struct bContext *C, TransInfo *t) { if (t->mode == TFM_EDGE_SLIDE) { - SlideData *sld = (SlideData *)t->customData; + EdgeSlideData *sld = (EdgeSlideData *)t->customData; /* Non-Prop mode */ if (sld && sld->is_proportional == FALSE) { View3D *v3d = CTX_wm_view3d(C); float marker[3]; float v1[3], v2[3]; float interp_v; - TransDataSlideVert *curr_sv = &sld->sv[sld->curr_sv_index]; + TransDataEdgeSlideVert *curr_sv = &sld->sv[sld->curr_sv_index]; const float ctrl_size = UI_GetThemeValuef(TH_FACEDOT_SIZE) + 1.5f; const float guide_size = ctrl_size - 0.5f; const float line_size = UI_GetThemeValuef(TH_OUTLINE_WIDTH) + 0.5f; @@ -5674,8 +5726,8 @@ void drawNonPropEdge(const struct bContext *C, TransInfo *t) static int doEdgeSlide(TransInfo *t, float perc) { - SlideData *sld = t->customData; - TransDataSlideVert *svlist = sld->sv, *sv; + EdgeSlideData *sld = t->customData; + TransDataEdgeSlideVert *svlist = sld->sv, *sv; int i; sld->perc = perc; @@ -5705,7 +5757,7 @@ static int doEdgeSlide(TransInfo *t, float perc) * \note len_v3v3(curr_sv->upvec, curr_sv->downvec) * is the same as the distance between the original vert locations, same goes for the lines below. */ - TransDataSlideVert *curr_sv = &sld->sv[sld->curr_sv_index]; + TransDataEdgeSlideVert *curr_sv = &sld->sv[sld->curr_sv_index]; const float curr_length_perc = curr_sv->edge_len * (((sld->flipped_vtx ? perc : -perc) + 1.0f) / 2.0f); float down_co[3]; @@ -5728,7 +5780,7 @@ static int doEdgeSlide(TransInfo *t, float perc) } } - projectSVData(t, 0); + projectEdgeSlideData(t, 0); return 1; } @@ -5737,9 +5789,9 @@ int EdgeSlide(TransInfo *t, const int UNUSED(mval[2])) { char str[128]; float final; - SlideData *sld = t->customData; - int flipped = sld->flipped_vtx; - int is_proportional = sld->is_proportional; + EdgeSlideData *sld = t->customData; + bool flipped = sld->flipped_vtx; + bool is_proportional = sld->is_proportional; final = t->values[0]; @@ -5782,6 +5834,498 @@ int EdgeSlide(TransInfo *t, const int UNUSED(mval[2])) return 1; } + +/* ******************** Vert Slide *************** */ +static void calcVertSlideCustomPoints(struct TransInfo *t) +{ + VertSlideData *sld = t->customData; + TransDataVertSlideVert *sv = &sld->sv[sld->curr_sv_index]; + float *co_orig = sv->co_orig_2d; + float *co_curr = sv->co_link_orig_2d[sv->co_link_curr]; + float co_curr_flip[2]; + + flip_v2_v2v2(co_curr_flip, co_orig, co_curr); + + { + const int start[2] = {co_orig[0], co_orig[1]}; + const int end[2] = {co_curr_flip[0], co_curr_flip[1]}; + if (!sld->flipped_vtx) { + setCustomPoints(t, &t->mouse, end, start); + } + else { + setCustomPoints(t, &t->mouse, start, end); + } + } +} + +/** + * Run once when initializing vert slide to find the reference edge + */ +static void calcVertSlideMouseActiveVert(struct TransInfo *t, const int mval[2]) +{ + VertSlideData *sld = t->customData; + float mval_fl[2] = {UNPACK2(mval)}; + TransDataVertSlideVert *sv; + + /* set the vertex to use as a reference for the mouse direction 'curr_sv_index' */ + float dist = 0.0f; + float min_dist = FLT_MAX; + int i; + + for (i = 0, sv = sld->sv; i < sld->totsv; i++, sv++) { + dist = len_squared_v2v2(mval_fl, sv->co_orig_2d); + if (dist < min_dist) { + min_dist = dist; + sld->curr_sv_index = i; + } + } +} +/** + * Run while moving the mouse to slide along the edge matching the mouse direction + */ +static void calcVertSlideMouseActiveEdges(struct TransInfo *t, const int mval[2]) +{ + VertSlideData *sld = t->customData; + float mval_fl[2] = {UNPACK2(mval)}; + + float dir[2]; + TransDataVertSlideVert *sv; + int i; + + /* first get the direction of the original vertex */ + sub_v2_v2v2(dir, sld->sv[sld->curr_sv_index].co_orig_2d, mval_fl); + normalize_v2(dir); + + for (i = 0, sv = sld->sv; i < sld->totsv; i++, sv++) { + if (sv->co_link_tot > 1) { + float dir_dot_best = -FLT_MAX; + int co_link_curr_best = -1; + int j; + + for (j = 0; j < sv->co_link_tot; j++) { + float tdir[2]; + float dir_dot; + sub_v2_v2v2(tdir, sv->co_orig_2d, sv->co_link_orig_2d[j]); + normalize_v2(tdir); + dir_dot = dot_v2v2(dir, tdir); + if (dir_dot > dir_dot_best) { + dir_dot_best = dir_dot; + co_link_curr_best = j; + } + } + + if (co_link_curr_best != -1) { + sv->co_link_curr = co_link_curr_best; + } + } + } +} + +static int createVertSlideVerts(TransInfo *t) +{ + BMEditMesh *em = BMEdit_FromObject(t->obedit); + BMesh *bm = em->bm; + BMIter iter; + BMIter eiter; + BMEdge *e; + BMVert *v; + TransDataVertSlideVert *sv_array; + VertSlideData *sld = MEM_callocN(sizeof(*sld), "sld"); +// View3D *v3d = NULL; + RegionView3D *rv3d = NULL; + ARegion *ar = t->ar; + float projectMat[4][4]; + int j; + + if (t->spacetype == SPACE_VIEW3D) { + /* background mode support */ +// v3d = t->sa ? t->sa->spacedata.first : NULL; + rv3d = t->ar ? t->ar->regiondata : NULL; + } + + sld->is_proportional = true; + sld->curr_sv_index = 0; + sld->flipped_vtx = false; + + if (!rv3d) { + /* ok, let's try to survive this */ + unit_m4(projectMat); + } + else { + ED_view3d_ob_project_mat_get(rv3d, t->obedit, projectMat); + } + + j = 0; + BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) { + bool ok = false; + if (BM_elem_flag_test(v, BM_ELEM_SELECT) && v->e) { + BM_ITER_ELEM (e, &eiter, v, BM_EDGES_OF_VERT) { + if (!BM_elem_flag_test(e, BM_ELEM_HIDDEN)) { + ok = true; + break; + } + } + } + + if (ok) { + BM_elem_flag_enable(v, BM_ELEM_TAG); + j += 1; + } + else { + BM_elem_flag_disable(v, BM_ELEM_TAG); + } + } + + if (!j) { + MEM_freeN(sld); + return 0; + } + + sv_array = MEM_callocN(sizeof(TransDataVertSlideVert) * j, "sv_array"); + + j = 0; + BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) { + if (BM_elem_flag_test(v, BM_ELEM_TAG)) { + int k; + sv_array[j].v = v; + copy_v3_v3(sv_array[j].co_orig_3d, v->co); + + k = 0; + BM_ITER_ELEM (e, &eiter, v, BM_EDGES_OF_VERT) { + if (!BM_elem_flag_test(e, BM_ELEM_HIDDEN)) { + k++; + } + } + + sv_array[j].co_link_orig_3d = MEM_mallocN(sizeof(*sv_array[j].co_link_orig_3d) * k, __func__); + sv_array[j].co_link_orig_2d = MEM_mallocN(sizeof(*sv_array[j].co_link_orig_2d) * k, __func__); + sv_array[j].co_link_tot = k; + + k = 0; + BM_ITER_ELEM (e, &eiter, v, BM_EDGES_OF_VERT) { + if (!BM_elem_flag_test(e, BM_ELEM_HIDDEN)) { + BMVert *v_other = BM_edge_other_vert(e, v); + copy_v3_v3(sv_array[j].co_link_orig_3d[k], v_other->co); + ED_view3d_project_float_v2_m4(ar, + sv_array[j].co_link_orig_3d[k], + sv_array[j].co_link_orig_2d[k], + projectMat); + k++; + } + } + + ED_view3d_project_float_v2_m4(ar, + sv_array[j].co_orig_3d, + sv_array[j].co_orig_2d, + projectMat); + + j++; + } + } + + sld->sv = sv_array; + sld->totsv = j; + + sld->em = em; + + sld->perc = 0.0f; + + t->customData = sld; + + if (rv3d) { + calcVertSlideMouseActiveVert(t, t->mval); + calcVertSlideMouseActiveEdges(t, t->mval); + } + + return 1; +} + +void freeVertSlideVerts(TransInfo *t) +{ + VertSlideData *sld = t->customData; + + if (!sld) + return; + + + if (sld->totsv > 0) { + TransDataVertSlideVert *sv = sld->sv; + int i = 0; + for (i = 0; i < sld->totsv; i++, sv++) { + MEM_freeN(sv->co_link_orig_2d); + MEM_freeN(sv->co_link_orig_3d); + } + } + + MEM_freeN(sld->sv); + MEM_freeN(sld); + + t->customData = NULL; + + recalcData(t); +} + +void initVertSlide(TransInfo *t) +{ + VertSlideData *sld; + + t->mode = TFM_VERT_SLIDE; + t->transform = VertSlide; + t->handleEvent = handleEventVertSlide; + + if (!createVertSlideVerts(t)) { + t->state = TRANS_CANCEL; + return; + } + + sld = t->customData; + + if (!sld) + return; + + t->customFree = freeVertSlideVerts; + + /* set custom point first if you want value to be initialized by init */ + calcVertSlideCustomPoints(t); + initMouseInputMode(t, &t->mouse, INPUT_CUSTOM_RATIO); + + t->idx_max = 0; + t->num.idx_max = 0; + t->snap[0] = 0.0f; + t->snap[1] = 0.1f; + t->snap[2] = t->snap[1] * 0.1f; + + t->num.increment = t->snap[1]; + + t->flag |= T_NO_CONSTRAINT | T_NO_PROJECT; +} + +int handleEventVertSlide(struct TransInfo *t, struct wmEvent *event) +{ + if (t->mode == TFM_VERT_SLIDE) { + VertSlideData *sld = t->customData; + + if (sld) { + switch (event->type) { + case EKEY: + if (event->val == KM_PRESS) { + sld->is_proportional = !sld->is_proportional; + return 1; + } + break; + case FKEY: + { + if (event->val == KM_PRESS) { + if (sld->is_proportional == FALSE) { + sld->flipped_vtx = !sld->flipped_vtx; + calcVertSlideCustomPoints(t); + } + return 1; + } + break; + } +#if 0 + case EVT_MODAL_MAP: + { + switch (event->val) { + case TFM_MODAL_EDGESLIDE_DOWN: + { + sld->curr_sv_index = ((sld->curr_sv_index - 1) + sld->totsv) % sld->totsv; + break; + } + case TFM_MODAL_EDGESLIDE_UP: + { + sld->curr_sv_index = (sld->curr_sv_index + 1) % sld->totsv; + break; + } + } + } +#endif + case MOUSEMOVE: + { + /* don't recalculat the best edge */ + if (!(t->flag & T_ALT_TRANSFORM)) { + calcVertSlideMouseActiveEdges(t, event->mval); + } + calcVertSlideCustomPoints(t); + } + default: + break; + } + } + } + return 0; +} + +static void drawVertSlide(const struct bContext *C, TransInfo *t) +{ + if (t->mode == TFM_VERT_SLIDE) { + VertSlideData *sld = (VertSlideData *)t->customData; + /* Non-Prop mode */ + if (sld) { + View3D *v3d = CTX_wm_view3d(C); + TransDataVertSlideVert *curr_sv = &sld->sv[sld->curr_sv_index]; + TransDataVertSlideVert *sv; + const float ctrl_size = UI_GetThemeValuef(TH_FACEDOT_SIZE) + 1.5f; + const float line_size = UI_GetThemeValuef(TH_OUTLINE_WIDTH) + 0.5f; + const int alpha_shade = -30; + int i; + bool is_constrained = !(t->flag & T_ALT_TRANSFORM); + + if (v3d && v3d->zbuf) + glDisable(GL_DEPTH_TEST); + + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + + glPushAttrib(GL_CURRENT_BIT | GL_LINE_BIT | GL_POINT_BIT); + glPushMatrix(); + + glMultMatrixf(t->obedit->obmat); + + glLineWidth(line_size); + UI_ThemeColorShadeAlpha(TH_EDGE_SELECT, 80, alpha_shade); + glBegin(GL_LINES); + if (is_constrained) { + sv = sld->sv; + for (i = 0; i < sld->totsv; i++, sv++) { + glVertex3fv(sv->co_orig_3d); + glVertex3fv(sv->co_link_orig_3d[sv->co_link_curr]); + } + } + else { + sv = sld->sv; + for (i = 0; i < sld->totsv; i++, sv++) { + float a[3], b[3]; + sub_v3_v3v3(a, sv->co_link_orig_3d[sv->co_link_curr], sv->co_orig_3d); + mul_v3_fl(a, 100.0f); + negate_v3_v3(b, a); + add_v3_v3(a, sv->co_orig_3d); + add_v3_v3(b, sv->co_orig_3d); + + glVertex3fv(a); + glVertex3fv(b); + } + } + bglEnd(); + + glPointSize(ctrl_size); + + bglBegin(GL_POINTS); + bglVertex3fv((sld->flipped_vtx && sld->is_proportional == FALSE) ? + curr_sv->co_link_orig_3d[curr_sv->co_link_curr] : + curr_sv->co_orig_3d); + bglEnd(); + + glPopMatrix(); + glPopAttrib(); + + glDisable(GL_BLEND); + + if (v3d && v3d->zbuf) + glEnable(GL_DEPTH_TEST); + } + } +} + +static int doVertSlide(TransInfo *t, float perc) +{ + VertSlideData *sld = t->customData; + TransDataVertSlideVert *svlist = sld->sv, *sv; + int i; + + sld->perc = perc; + sv = svlist; + + if (sld->is_proportional == TRUE) { + for (i = 0; i < sld->totsv; i++, sv++) { + interp_v3_v3v3(sv->v->co, sv->co_orig_3d, sv->co_link_orig_3d[sv->co_link_curr], perc); + } + } + else { + TransDataVertSlideVert *sv_curr = &sld->sv[sld->curr_sv_index]; + const float edge_len_curr = len_v3v3(sv_curr->co_orig_3d, sv_curr->co_link_orig_3d[sv_curr->co_link_curr]); + const float tperc = perc * edge_len_curr; + + for (i = 0; i < sld->totsv; i++, sv++) { + float edge_len; + float dir[3]; + + sub_v3_v3v3(dir, sv->co_link_orig_3d[sv->co_link_curr], sv->co_orig_3d); + edge_len = normalize_v3(dir); + + if (edge_len > FLT_EPSILON) { + if (sld->flipped_vtx) { + madd_v3_v3v3fl(sv->v->co, sv->co_link_orig_3d[sv->co_link_curr], dir, -tperc); + } + else { + madd_v3_v3v3fl(sv->v->co, sv->co_orig_3d, dir, tperc); + } + } + else { + copy_v3_v3(sv->v->co, sv->co_orig_3d); + } + } + } + + return 1; +} + +int VertSlide(TransInfo *t, const int UNUSED(mval[2])) +{ + char str[128]; + float final; + VertSlideData *sld = t->customData; + const bool flipped = sld->flipped_vtx; + const bool is_proportional = sld->is_proportional; + const bool is_constrained = !((t->flag & T_ALT_TRANSFORM) || hasNumInput(&t->num)); + + final = t->values[0]; + + snapGrid(t, &final); + + /* only do this so out of range values are not displayed */ + if (is_constrained) { + CLAMP(final, 0.0f, 1.0f); + } + + if (hasNumInput(&t->num)) { + char c[NUM_STR_REP_LEN]; + + applyNumInput(&t->num, &final); + + outputNumInput(&(t->num), c); + + BLI_snprintf(str, sizeof(str), "Vert Slide: %s (E)ven: %s, (F)lipped: %s, Alt Hold: %s", + &c[0], !is_proportional ? "ON" : "OFF", flipped ? "ON" : "OFF", (t->flag & T_ALT_TRANSFORM) ? "ON" : "OFF"); + } + else { + BLI_snprintf(str, sizeof(str), "Vert Slide: %.2f (E)ven: %s, (F)lipped: %s, Alt Hold: %s", + final, !is_proportional ? "ON" : "OFF", flipped ? "ON" : "OFF", (t->flag & T_ALT_TRANSFORM) ? "ON" : "OFF"); + } + + if (is_constrained) { + CLAMP(final, 0.0f, 1.0f); + } + + t->values[0] = final; + + /*do stuff here*/ + if (t->customData) + doVertSlide(t, final); + else { + strcpy(str, "Invalid Vert Selection"); + t->state = TRANS_CANCEL; + } + + recalcData(t); + + ED_area_headerprint(t->sa, str); + + return 1; +} + + /* ******************** EditBone roll *************** */ void initBoneRoll(TransInfo *t) diff --git a/source/blender/editors/transform/transform.h b/source/blender/editors/transform/transform.h index 08fe1e7676b..c72c6a83d82 100644 --- a/source/blender/editors/transform/transform.h +++ b/source/blender/editors/transform/transform.h @@ -52,12 +52,7 @@ struct Object; struct View3D; struct ScrArea; struct Scene; -struct bPose; struct bConstraint; -struct BezTriple; -struct wmOperatorType; -struct wmOperator; -struct wmWindowManager; struct wmKeyMap; struct wmKeyConfig; struct bContext; @@ -65,7 +60,6 @@ struct wmEvent; struct wmTimer; struct ARegion; struct ReportList; -struct SmallHash; typedef struct TransSnapPoint { struct TransSnapPoint *next, *prev; @@ -108,15 +102,15 @@ typedef struct TransCon { int imval[2]; /* initial mouse value for visual calculation */ /* the one in TransInfo is not garanty to stay the same (Rotates change it) */ int mode; /* Mode flags of the Constraint */ - void (*drawExtra)(struct TransInfo *); + void (*drawExtra)(struct TransInfo *t); /* For constraints that needs to draw differently from the other * uses this instead of the generic draw function */ - void (*applyVec)(struct TransInfo *, struct TransData *, float *, float *, float *); + void (*applyVec)(struct TransInfo *t, struct TransData *td, const float in[3], float out[3], float pvec[3]); /* Apply function pointer for linear vectorial transformation */ /* The last three parameters are pointers to the in/out/printable vectors */ - void (*applySize)(struct TransInfo *, struct TransData *, float [3][3]); + void (*applySize)(struct TransInfo *t, struct TransData *td, float smat[3][3]); /* Apply function pointer for size transformation */ - void (*applyRot)(struct TransInfo *, struct TransData *, float [3], float *); + void (*applyRot)(struct TransInfo *t, struct TransData *td, float vec[3], float *angle); /* Apply function pointer for rotation transformation */ } TransCon; @@ -143,6 +137,7 @@ typedef struct TransDataExtension { * namely when a bone is in "NoLocal" or "Hinge" mode)... */ float r_smtx[3][3]; /* Invers of previous one. */ int rotOrder; /* rotation mode, as defined in eRotationModes (DNA_action_types.h) */ + float oloc[3], orot[3], oquat[4], orotAxis[3], orotAngle; /* Original object transformation used for rigid bodies */ } TransDataExtension; typedef struct TransData2D { @@ -188,7 +183,7 @@ typedef struct TransDataNla { struct LinkNode; struct GHash; -typedef struct TransDataSlideVert { +typedef struct TransDataEdgeSlideVert { struct BMVert vup, vdown; struct BMVert origvert; @@ -201,10 +196,10 @@ typedef struct TransDataSlideVert { float upvec[3], downvec[3]; int loop_nr; -} TransDataSlideVert; +} TransDataEdgeSlideVert; -typedef struct SlideData { - TransDataSlideVert *sv; +typedef struct EdgeSlideData { + TransDataEdgeSlideVert *sv; int totsv; struct SmallHash vhash; @@ -214,15 +209,40 @@ typedef struct SlideData { struct BMEditMesh *em; /* flag that is set when origfaces is initialized */ - int origfaces_init; + bool origfaces_init; float perc; - int is_proportional; - int flipped_vtx; + bool is_proportional; + bool flipped_vtx; int curr_sv_index; -} SlideData; +} EdgeSlideData; + + +typedef struct TransDataVertSlideVert { + BMVert *v; + float co_orig_3d[3]; + float co_orig_2d[2]; + float (*co_link_orig_3d)[3]; + float (*co_link_orig_2d)[2]; + int co_link_tot; + int co_link_curr; +} TransDataVertSlideVert; + +typedef struct VertSlideData { + TransDataVertSlideVert *sv; + int totsv; + + struct BMEditMesh *em; + + float perc; + + bool is_proportional; + bool flipped_vtx; + + int curr_sv_index; +} VertSlideData; typedef struct TransData { float dist; /* Distance needed to affect element (for Proportionnal Editing) */ @@ -246,8 +266,8 @@ typedef struct TransData { } TransData; typedef struct MouseInput { - void (*apply)(struct TransInfo *, struct MouseInput *, const int [2], float [3]); - void (*post)(struct TransInfo *, float [3]); + void (*apply)(struct TransInfo *t, struct MouseInput *mi, const int mval[2], float output[3]); + void (*post)(struct TransInfo *t, float values[3]); int imval[2]; /* initial mouse position */ char precision; @@ -530,6 +550,10 @@ void initEdgeSlide(TransInfo *t); int handleEventEdgeSlide(TransInfo *t, struct wmEvent *event); int EdgeSlide(TransInfo *t, const int mval[2]); +void initVertSlide(TransInfo *t); +int handleEventVertSlide(TransInfo *t, struct wmEvent *event); +int VertSlide(TransInfo *t, const int mval[2]); + void initTimeTranslate(TransInfo *t); int TimeTranslate(TransInfo *t, const int mval[2]); @@ -656,13 +680,13 @@ typedef enum { INPUT_CUSTOM_RATIO } MouseInputMode; -void initMouseInput(TransInfo *t, MouseInput *mi, int center[2], int mval[2]); +void initMouseInput(TransInfo *t, MouseInput *mi, const int center[2], const int mval[2]); void initMouseInputMode(TransInfo *t, MouseInput *mi, MouseInputMode mode); int handleMouseInput(struct TransInfo *t, struct MouseInput *mi, struct wmEvent *event); void applyMouseInput(struct TransInfo *t, struct MouseInput *mi, const int mval[2], float output[3]); -void setCustomPoints(TransInfo *t, MouseInput *mi, int start[2], int end[2]); -void setInputPostFct(MouseInput *mi, void (*post)(struct TransInfo *, float [3])); +void setCustomPoints(TransInfo *t, MouseInput *mi, const int start[2], const int end[2]); +void setInputPostFct(MouseInput *mi, void (*post)(struct TransInfo *t, float values[3])); /*********************** Generics ********************************/ @@ -672,8 +696,6 @@ void resetTransRestrictions(TransInfo *t); void drawLine(TransInfo *t, const float center[3], const float dir[3], char axis, short options); -void drawNonPropEdge(const struct bContext *C, TransInfo *t); - /* DRAWLINE options flags */ #define DRAWLIGHT 1 @@ -715,8 +737,10 @@ void applyTransformOrientation(const struct bContext *C, float mat[3][3], char * int getTransformOrientation(const struct bContext *C, float normal[3], float plane[3], int activeOnly); -void freeSlideTempFaces(SlideData *sld); -void freeSlideVerts(TransInfo *t); -void projectSVData(TransInfo *t, int final); +void freeEdgeSlideTempFaces(EdgeSlideData *sld); +void freeEdgeSlideVerts(TransInfo *t); +void projectEdgeSlideData(TransInfo *t, bool is_final); + +void freeVertSlideVerts(TransInfo *t); #endif diff --git a/source/blender/editors/transform/transform_constraints.c b/source/blender/editors/transform/transform_constraints.c index 947bdf53bee..097e4592933 100644 --- a/source/blender/editors/transform/transform_constraints.c +++ b/source/blender/editors/transform/transform_constraints.c @@ -200,13 +200,14 @@ static void viewAxisCorrectCenter(TransInfo *t, float t_con_center[3]) } } -static void axisProjection(TransInfo *t, float axis[3], float in[3], float out[3]) +static void axisProjection(TransInfo *t, const float axis[3], const float in[3], float out[3]) { float norm[3], vec[3], factor, angle; float t_con_center[3]; - if (in[0] == 0.0f && in[1] == 0.0f && in[2] == 0.0f) + if (is_zero_v3(in)) { return; + } copy_v3_v3(t_con_center, t->con.center); @@ -278,7 +279,7 @@ static void axisProjection(TransInfo *t, float axis[3], float in[3], float out[3 } } -static void planeProjection(TransInfo *t, float in[3], float out[3]) +static void planeProjection(TransInfo *t, const float in[3], float out[3]) { float vec[3], factor, norm[3]; @@ -308,7 +309,7 @@ static void planeProjection(TransInfo *t, float in[3], float out[3]) * */ -static void applyAxisConstraintVec(TransInfo *t, TransData *td, float in[3], float out[3], float pvec[3]) +static void applyAxisConstraintVec(TransInfo *t, TransData *td, const float in[3], float out[3], float pvec[3]) { copy_v3_v3(out, in); if (!td && t->con.mode & CON_APPLY) { @@ -351,7 +352,7 @@ static void applyAxisConstraintVec(TransInfo *t, TransData *td, float in[3], flo * Further down, that vector is mapped to each data's space. */ -static void applyObjectConstraintVec(TransInfo *t, TransData *td, float in[3], float out[3], float pvec[3]) +static void applyObjectConstraintVec(TransInfo *t, TransData *td, const float in[3], float out[3], float pvec[3]) { copy_v3_v3(out, in); if (t->con.mode & CON_APPLY) { diff --git a/source/blender/editors/transform/transform_conversions.c b/source/blender/editors/transform/transform_conversions.c index d38bdb178fb..39c51ff456e 100644 --- a/source/blender/editors/transform/transform_conversions.c +++ b/source/blender/editors/transform/transform_conversions.c @@ -85,6 +85,7 @@ #include "BKE_particle.h" #include "BKE_pointcache.h" #include "BKE_report.h" +#include "BKE_rigidbody.h" #include "BKE_scene.h" #include "BKE_sequencer.h" #include "BKE_tessmesh.h" @@ -4541,6 +4542,27 @@ static void ObjectToTransData(TransInfo *t, TransData *td, Object *ob) short constinv; short skip_invert = 0; + if (ob->rigidbody_object) { + float rot[3][3], scale[3]; + + /* save original object transform */ + copy_v3_v3(td->ext->oloc, ob->loc); + + if (ob->rotmode > 0) { + copy_v3_v3(td->ext->orot, ob->rot); + } + else if (ob->rotmode == ROT_MODE_AXISANGLE) { + td->ext->orotAngle = ob->rotAngle; + copy_v3_v3(td->ext->orotAxis, ob->rotAxis); + } + else { + copy_qt_qt(td->ext->oquat, ob->quat); + } + /* update object's loc/rot to get current rigid body transform */ + mat4_to_loc_rot_size(ob->loc, rot, scale, ob->obmat); + BKE_object_mat3_to_rot(ob, rot, FALSE); + } + /* axismtx has the real orientation */ copy_m3_m4(td->axismtx, ob->obmat); normalize_m3(td->axismtx); @@ -5094,25 +5116,25 @@ void special_aftertrans_update(bContext *C, TransInfo *t) if (canceled == 0) { /* we need to delete the temporary faces before automerging */ if (t->mode == TFM_EDGE_SLIDE) { - SlideData *sld = t->customData; + EdgeSlideData *sld = t->customData; /* handle multires re-projection, done * on transform completion since it's * really slow -joeedh */ - projectSVData(t, TRUE); + projectEdgeSlideData(t, TRUE); /* free temporary faces to avoid automerging and deleting * during cleanup - psy-fi */ - freeSlideTempFaces(sld); + freeEdgeSlideTempFaces(sld); } EDBM_automerge(t->scene, t->obedit, TRUE); } else { if (t->mode == TFM_EDGE_SLIDE) { - SlideData *sld = t->customData; + EdgeSlideData *sld = t->customData; sld->perc = 0.0; - projectSVData(t, FALSE); + projectEdgeSlideData(t, FALSE); } } } @@ -5494,6 +5516,9 @@ void special_aftertrans_update(bContext *C, TransInfo *t) if (ob->avs.path_bakeflag & MOTIONPATH_BAKE_HAS_PATHS) recalcObPaths = 1; } + /* restore rigid body transform */ + if (ob->rigidbody_object && canceled) + BKE_rigidbody_aftertrans_update(ob, td->ext->oloc, td->ext->orot, td->ext->oquat, td->ext->orotAxis, td->ext->orotAngle); } /* recalculate motion paths for objects (if necessary) diff --git a/source/blender/editors/transform/transform_generics.c b/source/blender/editors/transform/transform_generics.c index 2591c61c5ab..ef775ae3128 100644 --- a/source/blender/editors/transform/transform_generics.c +++ b/source/blender/editors/transform/transform_generics.c @@ -550,13 +550,20 @@ static void recalcData_nla(TransInfo *t) break; } - /* use RNA to write the values... */ - // TODO: do we need to write in 2 passes to make sure that no truncation goes on? + /* Use RNA to write the values to ensure that constraints on these are obeyed + * (e.g. for transition strips, the values are taken from the neighbours) + * + * NOTE: we write these twice to avoid truncation errors which can arise when + * moving the strips a large distance using numeric input [#33852] + */ RNA_pointer_create(NULL, &RNA_NlaStrip, strip, &strip_ptr); RNA_float_set(&strip_ptr, "frame_start", tdn->h1[0]); RNA_float_set(&strip_ptr, "frame_end", tdn->h2[0]); + RNA_float_set(&strip_ptr, "frame_start", tdn->h1[0]); + RNA_float_set(&strip_ptr, "frame_end", tdn->h2[0]); + /* flush transforms to child strips (since this should be a meta) */ BKE_nlameta_flush_transforms(strip); @@ -812,7 +819,7 @@ static void recalcData_view3d(TransInfo *t) mul_m3_v3(t->mat, up_axis); } - ebo->roll = ED_rollBoneToVector(ebo, up_axis, FALSE); + ebo->roll = ED_rollBoneToVector(ebo, up_axis, TRUE); } } } diff --git a/source/blender/editors/transform/transform_input.c b/source/blender/editors/transform/transform_input.c index 69569251d01..c805dfe1b41 100644 --- a/source/blender/editors/transform/transform_input.c +++ b/source/blender/editors/transform/transform_input.c @@ -164,7 +164,7 @@ static void InputVerticalAbsolute(TransInfo *t, MouseInput *mi, const int mval[2 output[0] = dot_v3v3(t->viewinv[1], vec) * 2.0f; } -void setCustomPoints(TransInfo *UNUSED(t), MouseInput *mi, int start[2], int end[2]) +void setCustomPoints(TransInfo *UNUSED(t), MouseInput *mi, const int start[2], const int end[2]) { int *data; @@ -275,7 +275,7 @@ static void InputAngle(TransInfo *UNUSED(t), MouseInput *mi, const int mval[2], output[0] = *angle; } -void initMouseInput(TransInfo *UNUSED(t), MouseInput *mi, int center[2], int mval[2]) +void initMouseInput(TransInfo *UNUSED(t), MouseInput *mi, const int center[2], const int mval[2]) { mi->factor = 0; mi->precision = 0; @@ -368,7 +368,7 @@ void initMouseInputMode(TransInfo *t, MouseInput *mi, MouseInputMode mode) applyMouseInput(t, mi, mi->imval, t->values); } -void setInputPostFct(MouseInput *mi, void (*post)(struct TransInfo *, float[3])) +void setInputPostFct(MouseInput *mi, void (*post)(struct TransInfo *t, float values[3])) { mi->post = post; } diff --git a/source/blender/editors/transform/transform_manipulator.c b/source/blender/editors/transform/transform_manipulator.c index 6b016bf4303..cd6035a232b 100644 --- a/source/blender/editors/transform/transform_manipulator.c +++ b/source/blender/editors/transform/transform_manipulator.c @@ -734,8 +734,8 @@ static void partial_doughnut(float radring, float radhole, int start, int end, i float cos_phi, sin_phi, dist; phi += side_delta; - cos_phi = (float)cos(phi); - sin_phi = (float)sin(phi); + cos_phi = cosf(phi); + sin_phi = sinf(phi); dist = radhole + radring * cos_phi; glVertex3f(cos_theta1 * dist, -sin_theta1 * dist, radring * sin_phi); @@ -749,8 +749,8 @@ static void partial_doughnut(float radring, float radhole, int start, int end, i float cos_phi, sin_phi, dist; phi += side_delta; - cos_phi = (float)cos(phi); - sin_phi = (float)sin(phi); + cos_phi = cosf(phi); + sin_phi = sinf(phi); dist = radhole + radring * cos_phi; glVertex3f(cos_theta1 * dist, -sin_theta1 * dist, radring * sin_phi); diff --git a/source/blender/editors/transform/transform_ops.c b/source/blender/editors/transform/transform_ops.c index 916cf540589..32dc31954f2 100644 --- a/source/blender/editors/transform/transform_ops.c +++ b/source/blender/editors/transform/transform_ops.c @@ -73,6 +73,7 @@ static char OP_TILT[] = "TRANSFORM_OT_tilt"; static char OP_TRACKBALL[] = "TRANSFORM_OT_trackball"; static char OP_MIRROR[] = "TRANSFORM_OT_mirror"; static char OP_EDGE_SLIDE[] = "TRANSFORM_OT_edge_slide"; +static char OP_VERT_SLIDE[] = "TRANSFORM_OT_vert_slide"; static char OP_EDGE_CREASE[] = "TRANSFORM_OT_edge_crease"; static char OP_EDGE_BWEIGHT[] = "TRANSFORM_OT_edge_bevelweight"; static char OP_SEQ_SLIDE[] = "TRANSFORM_OT_seq_slide"; @@ -90,6 +91,7 @@ static void TRANSFORM_OT_tilt(struct wmOperatorType *ot); static void TRANSFORM_OT_trackball(struct wmOperatorType *ot); static void TRANSFORM_OT_mirror(struct wmOperatorType *ot); static void TRANSFORM_OT_edge_slide(struct wmOperatorType *ot); +static void TRANSFORM_OT_vert_slide(struct wmOperatorType *ot); static void TRANSFORM_OT_edge_crease(struct wmOperatorType *ot); static void TRANSFORM_OT_edge_bevelweight(struct wmOperatorType *ot); static void TRANSFORM_OT_seq_slide(struct wmOperatorType *ot); @@ -109,6 +111,7 @@ static TransformModeItem transform_modes[] = {OP_TRACKBALL, TFM_TRACKBALL, TRANSFORM_OT_trackball}, {OP_MIRROR, TFM_MIRROR, TRANSFORM_OT_mirror}, {OP_EDGE_SLIDE, TFM_EDGE_SLIDE, TRANSFORM_OT_edge_slide}, + {OP_VERT_SLIDE, TFM_VERT_SLIDE, TRANSFORM_OT_vert_slide}, {OP_EDGE_CREASE, TFM_CREASE, TRANSFORM_OT_edge_crease}, {OP_EDGE_BWEIGHT, TFM_BWEIGHT, TRANSFORM_OT_edge_bevelweight}, {OP_SEQ_SLIDE, TFM_SEQ_SLIDE, TRANSFORM_OT_seq_slide}, @@ -150,38 +153,6 @@ EnumPropertyItem transform_mode_types[] = {0, NULL, 0, NULL, NULL} }; -static int snap_type_exec(bContext *C, wmOperator *op) -{ - ToolSettings *ts = CTX_data_tool_settings(C); - - ts->snap_mode = RNA_enum_get(op->ptr, "type"); - - WM_event_add_notifier(C, NC_SCENE | ND_TOOLSETTINGS, NULL); /* header redraw */ - - return OPERATOR_FINISHED; -} - -static void TRANSFORM_OT_snap_type(wmOperatorType *ot) -{ - /* identifiers */ - ot->name = "Snap Type"; - ot->description = "Set the snap element type"; - ot->idname = "TRANSFORM_OT_snap_type"; - - /* api callbacks */ - ot->invoke = WM_menu_invoke; - ot->exec = snap_type_exec; - - ot->poll = ED_operator_areaactive; - - /* flags */ - ot->flag = OPTYPE_UNDO; - - /* props */ - ot->prop = RNA_def_enum(ot->srna, "type", snap_element_items, 0, "Type", "Set the snap element type"); - -} - static int select_orientation_exec(bContext *C, wmOperator *op) { int orientation = RNA_enum_get(op->ptr, "orientation"); @@ -793,6 +764,26 @@ static void TRANSFORM_OT_edge_slide(struct wmOperatorType *ot) Transform_Properties(ot, P_MIRROR | P_SNAP | P_CORRECT_UV); } +static void TRANSFORM_OT_vert_slide(struct wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Vertex Slide"; + ot->description = "Slide a vertex along a mesh"; + ot->idname = OP_VERT_SLIDE; + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_BLOCKING; + + /* api callbacks */ + ot->invoke = transform_invoke; + ot->exec = transform_exec; + ot->modal = transform_modal; + ot->cancel = transform_cancel; + ot->poll = ED_operator_editmesh; + + RNA_def_float_factor(ot->srna, "value", 0, -10.0f, 10.0f, "Factor", "", -1.0f, 1.0f); + + Transform_Properties(ot, P_MIRROR | P_SNAP); +} + static void TRANSFORM_OT_edge_crease(struct wmOperatorType *ot) { /* identifiers */ @@ -891,8 +882,6 @@ void transform_operatortypes(void) WM_operatortype_append(TRANSFORM_OT_select_orientation); WM_operatortype_append(TRANSFORM_OT_create_orientation); WM_operatortype_append(TRANSFORM_OT_delete_orientation); - - WM_operatortype_append(TRANSFORM_OT_snap_type); } void transform_keymap_for_space(wmKeyConfig *keyconf, wmKeyMap *keymap, int spaceid) @@ -939,7 +928,9 @@ void transform_keymap_for_space(wmKeyConfig *keyconf, wmKeyMap *keymap, int spac kmi = WM_keymap_add_item(keymap, "WM_OT_context_toggle", TABKEY, KM_PRESS, KM_SHIFT, 0); RNA_string_set(kmi->ptr, "data_path", "tool_settings.use_snap"); - WM_keymap_add_item(keymap, "TRANSFORM_OT_snap_type", TABKEY, KM_PRESS, KM_SHIFT | KM_CTRL, 0); + kmi = WM_keymap_add_item(keymap, "WM_OT_context_menu_enum", TABKEY, KM_PRESS, KM_SHIFT | KM_CTRL, 0); + RNA_string_set(kmi->ptr, "data_path", "tool_settings.snap_element"); + kmi = WM_keymap_add_item(keymap, OP_TRANSLATION, TKEY, KM_PRESS, KM_SHIFT, 0); RNA_boolean_set(kmi->ptr, "texture_space", TRUE); @@ -1032,6 +1023,9 @@ void transform_keymap_for_space(wmKeyConfig *keyconf, wmKeyMap *keymap, int spac kmi = WM_keymap_add_item(keymap, "WM_OT_context_toggle", TABKEY, KM_PRESS, KM_SHIFT, 0); RNA_string_set(kmi->ptr, "data_path", "tool_settings.use_snap"); + + kmi = WM_keymap_add_item(keymap, "WM_OT_context_menu_enum", TABKEY, KM_PRESS, KM_SHIFT | KM_CTRL, 0); + RNA_string_set(kmi->ptr, "data_path", "tool_settings.snap_uv_element"); break; case SPACE_CLIP: WM_keymap_add_item(keymap, OP_TRANSLATION, GKEY, KM_PRESS, 0, 0); diff --git a/source/blender/editors/uvedit/uvedit_draw.c b/source/blender/editors/uvedit/uvedit_draw.c index 023f281aea9..ea7e17af086 100644 --- a/source/blender/editors/uvedit/uvedit_draw.c +++ b/source/blender/editors/uvedit/uvedit_draw.c @@ -134,14 +134,15 @@ static void draw_uvs_shadow(Object *obedit) BMIter iter, liter; MLoopUV *luv; + const int cd_loop_uv_offset = CustomData_get_offset(&bm->ldata, CD_MLOOPUV); + /* draws the gray mesh when painting */ glColor3ub(112, 112, 112); BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) { glBegin(GL_LINE_LOOP); BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { - luv = CustomData_bmesh_get(&bm->ldata, l->head.data, CD_MLOOPUV); - + luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); glVertex2fv(luv->uv); } glEnd(); @@ -173,6 +174,9 @@ static void draw_uvs_stretch(SpaceImage *sima, Scene *scene, BMEditMesh *em, MTe float aspx, aspy, col[4]; int i; + const int cd_loop_uv_offset = CustomData_get_offset(&bm->ldata, CD_MLOOPUV); + const int cd_poly_tex_offset = CustomData_get_offset(&bm->pdata, CD_MTEXPOLY); + ED_space_image_get_uv_aspect(sima, &aspx, &aspy); switch (sima->dt_uvstretch) { @@ -184,10 +188,10 @@ static void draw_uvs_stretch(SpaceImage *sima, Scene *scene, BMEditMesh *em, MTe const int efa_len = efa->len; float (*tf_uv)[2] = BLI_array_alloca(tf_uv, efa_len); float (*tf_uvorig)[2] = BLI_array_alloca(tf_uvorig, efa_len); - tf = CustomData_bmesh_get(&bm->pdata, efa->head.data, CD_MTEXPOLY); + tf = BM_ELEM_CD_GET_VOID_P(efa, cd_poly_tex_offset); BM_ITER_ELEM_INDEX (l, &liter, efa, BM_LOOPS_OF_FACE, i) { - luv = CustomData_bmesh_get(&bm->ldata, l->head.data, CD_MLOOPUV); + luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); copy_v2_v2(tf_uvorig[i], luv->uv); } @@ -214,7 +218,7 @@ static void draw_uvs_stretch(SpaceImage *sima, Scene *scene, BMEditMesh *em, MTe if (BM_elem_flag_test(efa, BM_ELEM_TAG)) { glBegin(GL_POLYGON); BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { - luv = CustomData_bmesh_get(&bm->ldata, l->head.data, CD_MLOOPUV); + luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); glVertex2fv(luv->uv); } glEnd(); @@ -231,7 +235,7 @@ static void draw_uvs_stretch(SpaceImage *sima, Scene *scene, BMEditMesh *em, MTe area = BM_face_calc_area(efa) / totarea; BM_ITER_ELEM_INDEX (l, &liter, efa, BM_LOOPS_OF_FACE, i) { - luv = CustomData_bmesh_get(&bm->ldata, l->head.data, CD_MLOOPUV); + luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); copy_v2_v2(tf_uvorig[i], luv->uv); } @@ -251,7 +255,7 @@ static void draw_uvs_stretch(SpaceImage *sima, Scene *scene, BMEditMesh *em, MTe glBegin(GL_POLYGON); BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { - luv = CustomData_bmesh_get(&bm->ldata, l->head.data, CD_MLOOPUV); + luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); glVertex2fv(luv->uv); } glEnd(); @@ -269,7 +273,7 @@ static void draw_uvs_stretch(SpaceImage *sima, Scene *scene, BMEditMesh *em, MTe glShadeModel(GL_SMOOTH); BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) { - tf = CustomData_bmesh_get(&bm->pdata, efa->head.data, CD_MTEXPOLY); + tf = BM_ELEM_CD_GET_VOID_P(efa, cd_poly_tex_offset); if (uvedit_face_visible_test(scene, ima, efa, tf)) { const int efa_len = efa->len; @@ -284,7 +288,7 @@ static void draw_uvs_stretch(SpaceImage *sima, Scene *scene, BMEditMesh *em, MTe BM_elem_flag_enable(efa, BM_ELEM_TAG); BM_ITER_ELEM_INDEX (l, &liter, efa, BM_LOOPS_OF_FACE, i) { - luv = CustomData_bmesh_get(&bm->ldata, l->head.data, CD_MLOOPUV); + luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); copy_v2_v2(tf_uvorig[i], luv->uv); } @@ -310,7 +314,7 @@ static void draw_uvs_stretch(SpaceImage *sima, Scene *scene, BMEditMesh *em, MTe glBegin(GL_POLYGON); BM_ITER_ELEM_INDEX (l, &liter, efa, BM_LOOPS_OF_FACE, i) { - luv = CustomData_bmesh_get(&bm->ldata, l->head.data, CD_MLOOPUV); + luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); a = fabsf(uvang[i] - ang[i]) / (float)M_PI; weight_to_rgb(col, 1.0f - powf((1.0f - a), 2.0f)); glColor3fv(col); @@ -418,6 +422,9 @@ static void draw_uvs(SpaceImage *sima, Scene *scene, Object *obedit) int drawfaces, interpedges; Image *ima = sima->image; + const int cd_loop_uv_offset = CustomData_get_offset(&bm->ldata, CD_MLOOPUV); + const int cd_poly_tex_offset = CustomData_get_offset(&bm->pdata, CD_MTEXPOLY); + activetf = EDBM_mtexpoly_active_get(em, &efa_act, FALSE, FALSE); /* will be set to NULL if hidden */ activef = BM_active_face_get(bm, FALSE, FALSE); ts = scene->toolsettings; @@ -467,7 +474,7 @@ static void draw_uvs(SpaceImage *sima, Scene *scene, Object *obedit) glEnable(GL_BLEND); BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) { - tf = CustomData_bmesh_get(&bm->pdata, efa->head.data, CD_MTEXPOLY); + tf = BM_ELEM_CD_GET_VOID_P(efa, cd_poly_tex_offset); if (uvedit_face_visible_test(scene, ima, efa, tf)) { BM_elem_flag_enable(efa, BM_ELEM_TAG); @@ -480,7 +487,7 @@ static void draw_uvs(SpaceImage *sima, Scene *scene, Object *obedit) glBegin(GL_POLYGON); BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { - luv = CustomData_bmesh_get(&bm->ldata, l->head.data, CD_MLOOPUV); + luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); glVertex2fv(luv->uv); } glEnd(); @@ -497,7 +504,7 @@ static void draw_uvs(SpaceImage *sima, Scene *scene, Object *obedit) /* would be nice to do this within a draw loop but most below are optional, so it would involve too many checks */ BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) { - tf = CustomData_bmesh_get(&bm->pdata, efa->head.data, CD_MTEXPOLY); + tf = BM_ELEM_CD_GET_VOID_P(efa, cd_poly_tex_offset); if (uvedit_face_visible_test(scene, ima, efa, tf)) { BM_elem_flag_enable(efa, BM_ELEM_TAG); @@ -514,7 +521,7 @@ static void draw_uvs(SpaceImage *sima, Scene *scene, Object *obedit) /* 3. draw active face stippled */ if (activef) { - tf = CustomData_bmesh_get(&bm->pdata, activef->head.data, CD_MTEXPOLY); + tf = BM_ELEM_CD_GET_VOID_P(activef, cd_poly_tex_offset); if (uvedit_face_visible_test(scene, ima, activef, tf)) { glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); @@ -525,7 +532,7 @@ static void draw_uvs(SpaceImage *sima, Scene *scene, Object *obedit) glBegin(GL_POLYGON); BM_ITER_ELEM (l, &liter, activef, BM_LOOPS_OF_FACE) { - luv = CustomData_bmesh_get(&bm->ldata, l->head.data, CD_MLOOPUV); + luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); glVertex2fv(luv->uv); } glEnd(); @@ -548,14 +555,14 @@ static void draw_uvs(SpaceImage *sima, Scene *scene, Object *obedit) BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) { if (!BM_elem_flag_test(efa, BM_ELEM_TAG)) continue; - tf = CustomData_bmesh_get(&bm->pdata, efa->head.data, CD_MTEXPOLY); + tf = BM_ELEM_CD_GET_VOID_P(efa, cd_poly_tex_offset); if (tf) { cpack(0x111111); glBegin(GL_LINE_LOOP); BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { - luv = CustomData_bmesh_get(&bm->ldata, l->head.data, CD_MLOOPUV); + luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); glVertex2fv(luv->uv); } glEnd(); @@ -565,20 +572,11 @@ static void draw_uvs(SpaceImage *sima, Scene *scene, Object *obedit) glBegin(GL_LINE_LOOP); BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { - luv = CustomData_bmesh_get(&bm->ldata, l->head.data, CD_MLOOPUV); + luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); glVertex2fv(luv->uv); } glEnd(); -#if 0 - glBegin(GL_LINE_STRIP); - luv = CustomData_bmesh_get(&bm->ldata, efa->lbase->head.data, CD_MLOOPUV); - glVertex2fv(luv->uv); - luv = CustomData_bmesh_get(&bm->ldata, efa->lbase->next->head.data, CD_MLOOPUV); - glVertex2fv(luv->uv); - glEnd(); -#endif - setlinestyle(0); } } @@ -594,7 +592,7 @@ static void draw_uvs(SpaceImage *sima, Scene *scene, Object *obedit) glBegin(GL_LINE_LOOP); BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { - luv = CustomData_bmesh_get(&bm->ldata, l->head.data, CD_MLOOPUV); + luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); glVertex2fv(luv->uv); } glEnd(); @@ -610,7 +608,7 @@ static void draw_uvs(SpaceImage *sima, Scene *scene, Object *obedit) glBegin(GL_LINE_LOOP); BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { - luv = CustomData_bmesh_get(&bm->ldata, l->head.data, CD_MLOOPUV); + luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); glVertex2fv(luv->uv); } glEnd(); @@ -636,7 +634,7 @@ static void draw_uvs(SpaceImage *sima, Scene *scene, Object *obedit) sel = (uvedit_uv_select_test(em, scene, l) ? 1 : 0); glColor4ubv(sel ? (GLubyte *)col1 : (GLubyte *)col2); - luv = CustomData_bmesh_get(&bm->ldata, l->head.data, CD_MLOOPUV); + luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); glVertex2fv(luv->uv); } glEnd(); @@ -656,9 +654,9 @@ static void draw_uvs(SpaceImage *sima, Scene *scene, Object *obedit) glColor4ubv(sel ? (GLubyte *)col1 : (GLubyte *)col2); lastsel = sel; } - luv = CustomData_bmesh_get(&bm->ldata, l->head.data, CD_MLOOPUV); + luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); glVertex2fv(luv->uv); - luv = CustomData_bmesh_get(&bm->ldata, l->next->head.data, CD_MLOOPUV); + luv = BM_ELEM_CD_GET_VOID_P(l->next, cd_loop_uv_offset); glVertex2fv(luv->uv); } glEnd(); @@ -673,7 +671,7 @@ static void draw_uvs(SpaceImage *sima, Scene *scene, Object *obedit) glBegin(GL_LINE_LOOP); BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { - luv = CustomData_bmesh_get(&bm->ldata, l->head.data, CD_MLOOPUV); + luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); glVertex2fv(luv->uv); } glEnd(); @@ -741,7 +739,7 @@ static void draw_uvs(SpaceImage *sima, Scene *scene, Object *obedit) continue; BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { - luv = CustomData_bmesh_get(&bm->ldata, l->head.data, CD_MLOOPUV); + luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); if (!uvedit_uv_select_test(em, scene, l)) bglVertex2fv(luv->uv); } @@ -759,7 +757,7 @@ static void draw_uvs(SpaceImage *sima, Scene *scene, Object *obedit) continue; BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { - luv = CustomData_bmesh_get(&bm->ldata, l->head.data, CD_MLOOPUV); + luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); if (luv->flag & MLOOPUV_PINNED) bglVertex2fv(luv->uv); @@ -777,7 +775,7 @@ static void draw_uvs(SpaceImage *sima, Scene *scene, Object *obedit) continue; BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { - luv = CustomData_bmesh_get(&bm->ldata, l->head.data, CD_MLOOPUV); + luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); if (uvedit_uv_select_test(em, scene, l)) bglVertex2fv(luv->uv); diff --git a/source/blender/editors/uvedit/uvedit_intern.h b/source/blender/editors/uvedit/uvedit_intern.h index b6d82451d2f..7faec33ca98 100644 --- a/source/blender/editors/uvedit/uvedit_intern.h +++ b/source/blender/editors/uvedit/uvedit_intern.h @@ -59,7 +59,7 @@ typedef struct NearestHit { struct BMFace *efa; struct MTexPoly *tf; struct BMLoop *l, *nextl; - struct MLoopUV *luv, *nextluv; + struct MLoopUV *luv, *luv_next; int lindex; //index of loop within face int vert1, vert2; //index in mesh of edge vertices } NearestHit; diff --git a/source/blender/editors/uvedit/uvedit_ops.c b/source/blender/editors/uvedit/uvedit_ops.c index 2194ce28353..e158f8843b7 100644 --- a/source/blender/editors/uvedit/uvedit_ops.c +++ b/source/blender/editors/uvedit/uvedit_ops.c @@ -199,6 +199,8 @@ void ED_uvedit_assign_image(Main *bmain, Scene *scene, Object *obedit, Image *im else { BMFace *efa; + int cd_poly_tex_offset; + /* old shading system, assign image to selected faces */ #ifdef USE_SWITCH_ASPECT float prev_aspect[2], fprev_aspect; @@ -220,9 +222,11 @@ void ED_uvedit_assign_image(Main *bmain, Scene *scene, Object *obedit, Image *im update = 1; } + cd_poly_tex_offset = CustomData_get_offset(&em->bm->pdata, CD_MTEXPOLY); + /* now assign to all visible faces */ BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { - tf = CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY); + tf = BM_ELEM_CD_GET_VOID_P(efa, cd_poly_tex_offset); if (uvedit_face_visible_test(scene, previma, efa, tf) && (selected == TRUE || uvedit_face_select_test(scene, em, efa))) @@ -243,7 +247,7 @@ void ED_uvedit_assign_image(Main *bmain, Scene *scene, Object *obedit, Image *im BMLoop *l; BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { - MLoopUV *luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV); + MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); luv->uv[0] *= fprev_aspect; luv->uv[0] /= faspect; @@ -274,6 +278,7 @@ static int uvedit_set_tile(Object *obedit, Image *ima, int curtile) BMFace *efa; BMIter iter; MTexPoly *tf; + int cd_poly_tex_offset; /* verify if we have something to do */ if (!ima || !ED_uvedit_test(obedit)) @@ -288,10 +293,12 @@ static int uvedit_set_tile(Object *obedit, Image *ima, int curtile) em = BMEdit_FromObject(obedit); + cd_poly_tex_offset = CustomData_get_offset(&em->bm->pdata, CD_MTEXPOLY); + BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { - tf = CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY); + tf = BM_ELEM_CD_GET_VOID_P(efa, cd_poly_tex_offset); - if (!BM_elem_flag_test(efa, BM_ELEM_HIDDEN) && BM_elem_flag_test(efa, BM_ELEM_SELECT)) + if (BM_elem_flag_test(efa, BM_ELEM_SELECT)) tf->tile = curtile; /* set tile index */ } @@ -344,15 +351,18 @@ int uvedit_face_select_test(Scene *scene, BMEditMesh *em, BMFace *efa) { ToolSettings *ts = scene->toolsettings; - if (ts->uv_flag & UV_SYNC_SELECTION) + if (ts->uv_flag & UV_SYNC_SELECTION) { return (BM_elem_flag_test(efa, BM_ELEM_SELECT)); + } else { BMLoop *l; MLoopUV *luv; BMIter liter; + const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV); /* TODO, pass this on */ + BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { - luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV); + luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); if (!(luv->flag & MLOOPUV_VERTSEL)) return 0; } @@ -376,8 +386,10 @@ int uvedit_face_select_enable(Scene *scene, BMEditMesh *em, BMFace *efa, const s MLoopUV *luv; BMIter liter; + const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV); /* TODO, pass this on */ + BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { - luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV); + luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); luv->flag |= MLOOPUV_VERTSEL; } @@ -399,8 +411,10 @@ int uvedit_face_select_disable(Scene *scene, BMEditMesh *em, BMFace *efa) MLoopUV *luv; BMIter liter; + const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV); /* TODO, pass this on */ + BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { - luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV); + luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); luv->flag &= ~MLOOPUV_VERTSEL; } @@ -503,7 +517,9 @@ int uvedit_uv_select_test(BMEditMesh *em, Scene *scene, BMLoop *l) return BM_elem_flag_test(l->v, BM_ELEM_SELECT); } else { - MLoopUV *luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV); + const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV); /* TODO, pass this on */ + + MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); return luv->flag & MLOOPUV_VERTSEL; } @@ -524,7 +540,8 @@ void uvedit_uv_select_enable(BMEditMesh *em, Scene *scene, BMLoop *l, const shor } } else { - MLoopUV *luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV); + const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV); /* TODO, pass this on */ + MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); luv->flag |= MLOOPUV_VERTSEL; } @@ -541,7 +558,8 @@ void uvedit_uv_select_disable(BMEditMesh *em, Scene *scene, BMLoop *l) BM_vert_select_set(em->bm, l->v, FALSE); } else { - MLoopUV *luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV); + const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV); /* TODO, pass this on */ + MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); luv->flag &= ~MLOOPUV_VERTSEL; } @@ -565,10 +583,12 @@ void uv_poly_center(BMEditMesh *em, BMFace *f, float r_cent[2]) MLoopUV *luv; BMIter liter; + const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV); /* TODO, pass this on */ + zero_v2(r_cent); BM_ITER_ELEM (l, &liter, f, BM_LOOPS_OF_FACE) { - luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV); + luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); add_v2_v2(r_cent, luv->uv); } @@ -594,17 +614,20 @@ int ED_uvedit_minmax(Scene *scene, Image *ima, Object *obedit, float r_min[2], f MLoopUV *luv; int sel; + const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV); + const int cd_poly_tex_offset = CustomData_get_offset(&em->bm->pdata, CD_MTEXPOLY); + INIT_MINMAX2(r_min, r_max); sel = 0; BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { - tf = CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY); + tf = BM_ELEM_CD_GET_VOID_P(efa, cd_poly_tex_offset); if (!uvedit_face_visible_test(scene, ima, efa, tf)) continue; BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { if (uvedit_uv_select_test(em, scene, l)) { - luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV); + luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); minmax_v2v2_v2(r_min, r_max, luv->uv); sel = 1; } @@ -624,14 +647,17 @@ static int ED_uvedit_median(Scene *scene, Image *ima, Object *obedit, float co[2 MLoopUV *luv; unsigned int sel = 0; + const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV); + const int cd_poly_tex_offset = CustomData_get_offset(&em->bm->pdata, CD_MTEXPOLY); + zero_v2(co); BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { - tf = CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY); + tf = BM_ELEM_CD_GET_VOID_P(efa, cd_poly_tex_offset); if (!uvedit_face_visible_test(scene, ima, efa, tf)) continue; BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { - luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV); + luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); if (uvedit_uv_select_test(em, scene, l)) { add_v2_v2(co, luv->uv); sel++; @@ -672,26 +698,29 @@ void uv_find_nearest_edge(Scene *scene, Image *ima, BMEditMesh *em, const float BMFace *efa; BMLoop *l; BMIter iter, liter; - MLoopUV *luv, *nextluv; + MLoopUV *luv, *luv_next; float mindist_squared, dist_squared; int i; + const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV); + const int cd_poly_tex_offset = CustomData_get_offset(&em->bm->pdata, CD_MTEXPOLY); + mindist_squared = 1e10f; memset(hit, 0, sizeof(*hit)); BM_mesh_elem_index_ensure(em->bm, BM_VERT); BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { - tf = CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY); + tf = BM_ELEM_CD_GET_VOID_P(efa, cd_poly_tex_offset); if (!uvedit_face_visible_test(scene, ima, efa, tf)) continue; i = 0; BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { - luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV); - nextluv = CustomData_bmesh_get(&em->bm->ldata, l->next->head.data, CD_MLOOPUV); + luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); + luv_next = BM_ELEM_CD_GET_VOID_P(l->next, cd_loop_uv_offset); - dist_squared = dist_squared_to_line_segment_v2(co, luv->uv, nextluv->uv); + dist_squared = dist_squared_to_line_segment_v2(co, luv->uv, luv_next->uv); if (dist_squared < mindist_squared) { hit->tf = tf; @@ -700,7 +729,7 @@ void uv_find_nearest_edge(Scene *scene, Image *ima, BMEditMesh *em, const float hit->l = l; hit->nextl = l->next; hit->luv = luv; - hit->nextluv = nextluv; + hit->luv_next = luv_next; hit->lindex = i; hit->vert1 = BM_elem_index_get(hit->l->v); hit->vert2 = BM_elem_index_get(hit->l->next->v); @@ -720,16 +749,18 @@ static void find_nearest_uv_face(Scene *scene, Image *ima, BMEditMesh *em, const BMIter iter; float mindist, dist, cent[2]; + const int cd_poly_tex_offset = CustomData_get_offset(&em->bm->pdata, CD_MTEXPOLY); + mindist = 1e10f; memset(hit, 0, sizeof(*hit)); /*this will fill in hit.vert1 and hit.vert2*/ uv_find_nearest_edge(scene, ima, em, co, hit); hit->l = hit->nextl = NULL; - hit->luv = hit->nextluv = NULL; + hit->luv = hit->luv_next = NULL; BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { - tf = CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY); + tf = BM_ELEM_CD_GET_VOID_P(efa, cd_poly_tex_offset); if (!uvedit_face_visible_test(scene, ima, efa, tf)) continue; @@ -753,6 +784,7 @@ static int nearest_uv_between(BMEditMesh *em, BMFace *efa, int UNUSED(nverts), i BMIter iter; float m[2], v1[2], v2[2], c1, c2, *uv1 = NULL, /* *uv2, */ /* UNUSED */ *uv3 = NULL; int id1, id2, i; + const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV); id1 = (id + efa->len - 1) % efa->len; id2 = (id + efa->len + 1) % efa->len; @@ -761,7 +793,7 @@ static int nearest_uv_between(BMEditMesh *em, BMFace *efa, int UNUSED(nverts), i i = 0; BM_ITER_ELEM (l, &iter, efa, BM_LOOPS_OF_FACE) { - luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV); + luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); if (i == id1) { uv1 = luv->uv; @@ -803,10 +835,13 @@ void uv_find_nearest_vert(Scene *scene, Image *ima, BMEditMesh *em, float mindist, dist; int i; + const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV); + const int cd_poly_tex_offset = CustomData_get_offset(&em->bm->pdata, CD_MTEXPOLY); + /*this will fill in hit.vert1 and hit.vert2*/ uv_find_nearest_edge(scene, ima, em, co, hit); hit->l = hit->nextl = NULL; - hit->luv = hit->nextluv = NULL; + hit->luv = hit->luv_next = NULL; mindist = 1e10f; memset(hit, 0, sizeof(*hit)); @@ -814,13 +849,13 @@ void uv_find_nearest_vert(Scene *scene, Image *ima, BMEditMesh *em, BM_mesh_elem_index_ensure(em->bm, BM_VERT); BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { - tf = CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY); + tf = BM_ELEM_CD_GET_VOID_P(efa, cd_poly_tex_offset); if (!uvedit_face_visible_test(scene, ima, efa, tf)) continue; i = 0; BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { - luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV); + luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); if (penalty && uvedit_uv_select_test(em, scene, l)) dist = fabsf(co[0] - luv->uv[0]) + penalty[0] + fabsf(co[1] - luv->uv[1]) + penalty[1]; @@ -839,7 +874,7 @@ void uv_find_nearest_vert(Scene *scene, Image *ima, BMEditMesh *em, hit->l = l; hit->nextl = l->next; hit->luv = luv; - hit->nextluv = CustomData_bmesh_get(&em->bm->ldata, l->next->head.data, CD_MLOOPUV); + hit->luv_next = BM_ELEM_CD_GET_VOID_P(l->next, cd_loop_uv_offset); hit->tf = tf; hit->efa = efa; hit->lindex = i; @@ -862,16 +897,19 @@ int ED_uvedit_nearest_uv(Scene *scene, Object *obedit, Image *ima, const float c float mindist, dist; int found = FALSE; + const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV); + const int cd_poly_tex_offset = CustomData_get_offset(&em->bm->pdata, CD_MTEXPOLY); + mindist = 1e10f; copy_v2_v2(r_uv, co); BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { - tf = CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY); + tf = BM_ELEM_CD_GET_VOID_P(efa, cd_poly_tex_offset); if (!uvedit_face_visible_test(scene, ima, efa, tf)) continue; BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { - luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV); + luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); dist = fabsf(co[0] - luv->uv[0]) + fabsf(co[1] - luv->uv[1]); if (dist <= mindist) { @@ -985,6 +1023,8 @@ static int select_edgeloop(Scene *scene, Image *ima, BMEditMesh *em, NearestHit UvMapVert *iterv1, *iterv2; int a, looking, nverts, starttotf, select; + const int cd_poly_tex_offset = CustomData_get_offset(&em->bm->pdata, CD_MTEXPOLY); + /* setup */ EDBM_index_arrays_ensure(em, BM_FACE); vmap = EDBM_uv_vert_map_create(em, 0, limit); @@ -1018,7 +1058,7 @@ static int select_edgeloop(Scene *scene, Image *ima, BMEditMesh *em, NearestHit /* find correct valence edges which are not tagged yet, but connect to tagged one */ BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { - tf = CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY); + tf = BM_ELEM_CD_GET_VOID_P(efa, cd_poly_tex_offset); if (!BM_elem_flag_test(efa, BM_ELEM_TAG) && uvedit_face_visible_test(scene, ima, efa, tf)) { nverts = efa->len; @@ -1097,6 +1137,9 @@ static void select_linked(Scene *scene, Image *ima, BMEditMesh *em, const float unsigned int a; char *flag; + const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV); + const int cd_poly_tex_offset = CustomData_get_offset(&em->bm->pdata, CD_MTEXPOLY); + EDBM_index_arrays_ensure(em, BM_FACE); /* we can use this too */ vmap = EDBM_uv_vert_map_create(em, 1, limit); @@ -1108,11 +1151,11 @@ static void select_linked(Scene *scene, Image *ima, BMEditMesh *em, const float if (!hit) { BM_ITER_MESH_INDEX (efa, &iter, em->bm, BM_FACES_OF_MESH, a) { - tf = CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY); + tf = BM_ELEM_CD_GET_VOID_P(efa, cd_poly_tex_offset); if (uvedit_face_visible_test(scene, ima, efa, tf)) { BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { - luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV); + luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); if (luv->flag & MLOOPUV_VERTSEL) { stack[stacksize] = a; @@ -1186,7 +1229,7 @@ static void select_linked(Scene *scene, Image *ima, BMEditMesh *em, const float a = 0; BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { - luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV); + luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); if (flag[a]) luv->flag |= MLOOPUV_VERTSEL; @@ -1205,7 +1248,7 @@ static void select_linked(Scene *scene, Image *ima, BMEditMesh *em, const float } BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { - luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV); + luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); if (luv->flag & MLOOPUV_VERTSEL) break; @@ -1226,7 +1269,7 @@ static void select_linked(Scene *scene, Image *ima, BMEditMesh *em, const float } BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { - luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV); + luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); luv->flag &= ~MLOOPUV_VERTSEL; } @@ -1243,7 +1286,7 @@ static void select_linked(Scene *scene, Image *ima, BMEditMesh *em, const float } BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { - luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV); + luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); luv->flag |= MLOOPUV_VERTSEL; } @@ -1265,14 +1308,17 @@ static float *uv_sel_co_from_eve(Scene *scene, Image *ima, BMEditMesh *em, BMVer BMIter liter; BMLoop *l; + const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV); + const int cd_poly_tex_offset = CustomData_get_offset(&em->bm->pdata, CD_MTEXPOLY); + BM_ITER_ELEM (l, &liter, eve, BM_LOOPS_OF_VERT) { - MTexPoly *tf = CustomData_bmesh_get(&em->bm->pdata, l->f->head.data, CD_MTEXPOLY); + MTexPoly *tf = BM_ELEM_CD_GET_VOID_P(l->f, cd_poly_tex_offset); if (!uvedit_face_visible_test(scene, ima, l->f, tf)) continue; if (uvedit_uv_select_test(em, scene, l)) { - MLoopUV *luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV); + MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); return luv->uv; } } @@ -1284,17 +1330,18 @@ static float *uv_sel_co_from_eve(Scene *scene, Image *ima, BMEditMesh *em, BMVer static void weld_align_uv(bContext *C, int tool) { + Object *obedit = CTX_data_edit_object(C); + BMEditMesh *em = BMEdit_FromObject(obedit); SpaceImage *sima; Scene *scene; - Object *obedit; Image *ima; - BMEditMesh *em; MTexPoly *tf; float cent[2], min[2], max[2]; - + + const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV); + const int cd_poly_tex_offset = CustomData_get_offset(&em->bm->pdata, CD_MTEXPOLY); + scene = CTX_data_scene(C); - obedit = CTX_data_edit_object(C); - em = BMEdit_FromObject(obedit); ima = CTX_data_edit_image(C); sima = CTX_wm_space_image(C); @@ -1306,14 +1353,14 @@ static void weld_align_uv(bContext *C, int tool) BMLoop *l; BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { - tf = CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY); + tf = BM_ELEM_CD_GET_VOID_P(efa, cd_poly_tex_offset); if (!uvedit_face_visible_test(scene, ima, efa, tf)) continue; BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { if (uvedit_uv_select_test(em, scene, l)) { - MLoopUV *luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV); + MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); minmax_v2v2_v2(min, max, luv->uv); } } @@ -1330,13 +1377,13 @@ static void weld_align_uv(bContext *C, int tool) BMLoop *l; BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { - tf = CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY); + tf = BM_ELEM_CD_GET_VOID_P(efa, cd_poly_tex_offset); if (!uvedit_face_visible_test(scene, ima, efa, tf)) continue; BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { if (uvedit_uv_select_test(em, scene, l)) { - MLoopUV *luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV); + MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); luv->uv[0] = cent[0]; } @@ -1350,13 +1397,13 @@ static void weld_align_uv(bContext *C, int tool) BMLoop *l; BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { - tf = CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY); + tf = BM_ELEM_CD_GET_VOID_P(efa, cd_poly_tex_offset); if (!uvedit_face_visible_test(scene, ima, efa, tf)) continue; BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { if (uvedit_uv_select_test(em, scene, l)) { - MLoopUV *luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV); + MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); luv->uv[1] = cent[1]; } @@ -1379,7 +1426,7 @@ static void weld_align_uv(bContext *C, int tool) /* tag verts with a selected UV */ BM_ITER_MESH (eve, &iter, em->bm, BM_VERTS_OF_MESH) { BM_ITER_ELEM (l, &liter, eve, BM_LOOPS_OF_VERT) { - tf = CustomData_bmesh_get(&em->bm->pdata, l->f->head.data, CD_MTEXPOLY); + tf = BM_ELEM_CD_GET_VOID_P(l->f, cd_poly_tex_offset); if (!uvedit_face_visible_test(scene, ima, l->f, tf)) continue; @@ -1469,13 +1516,13 @@ static void weld_align_uv(bContext *C, int tool) /* go over all verts except for endpoints */ for (i = 0; i < BLI_array_count(eve_line); i++) { BM_ITER_ELEM (l, &liter, eve_line[i], BM_LOOPS_OF_VERT) { - tf = CustomData_bmesh_get(&em->bm->pdata, l->f->head.data, CD_MTEXPOLY); + tf = BM_ELEM_CD_GET_VOID_P(l->f, cd_poly_tex_offset); if (!uvedit_face_visible_test(scene, ima, l->f, tf)) continue; if (uvedit_uv_select_test(em, scene, l)) { - MLoopUV *luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV); + MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); /* Projection of point (x, y) over line (x1, y1, x2, y2) along X axis: * new_y = (y2 - y1) / (x2 - x1) * (x - x1) + y1 * Maybe this should be a BLI func? Or is it already existing? @@ -1554,9 +1601,9 @@ static int remove_doubles_exec(bContext *C, wmOperator *op) SpaceImage *sima; Scene *scene; - Object *obedit; + Object *obedit = CTX_data_edit_object(C); + BMEditMesh *em = BMEdit_FromObject(obedit); Image *ima; - BMEditMesh *em; MTexPoly *tf; int uv_a_index; int uv_b_index; @@ -1567,10 +1614,11 @@ static int remove_doubles_exec(bContext *C, wmOperator *op) BMFace *efa; BMLoop *l; + const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV); + const int cd_poly_tex_offset = CustomData_get_offset(&em->bm->pdata, CD_MTEXPOLY); + sima = CTX_wm_space_image(C); scene = CTX_data_scene(C); - obedit = CTX_data_edit_object(C); - em = BMEdit_FromObject(obedit); ima = CTX_data_edit_image(C); if (use_unselected == FALSE) { @@ -1581,13 +1629,13 @@ static int remove_doubles_exec(bContext *C, wmOperator *op) /* TODO, use qsort as with MESH_OT_remove_doubles, this isn't optimal */ BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { - tf = CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY); + tf = BM_ELEM_CD_GET_VOID_P(efa, cd_poly_tex_offset); if (!uvedit_face_visible_test(scene, ima, efa, tf)) continue; BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { if (uvedit_uv_select_test(em, scene, l)) { - MLoopUV *luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV); + MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); UVvert vert; vert.uv_loop = luv; vert.weld = FALSE; @@ -1644,12 +1692,12 @@ static int remove_doubles_exec(bContext *C, wmOperator *op) BLI_array_declare(loop_arr_unselected); BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { - tf = CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY); + tf = BM_ELEM_CD_GET_VOID_P(efa, cd_poly_tex_offset); if (!uvedit_face_visible_test(scene, ima, efa, tf)) continue; BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { - MLoopUV *luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV); + MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); if (uvedit_uv_select_test(em, scene, l)) { BLI_array_append(loop_arr, luv); } @@ -1738,6 +1786,9 @@ static void select_all_perform(Scene *scene, Image *ima, BMEditMesh *em, int act MTexPoly *tf; MLoopUV *luv; + const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV); + const int cd_poly_tex_offset = CustomData_get_offset(&em->bm->pdata, CD_MTEXPOLY); + if (ts->uv_flag & UV_SYNC_SELECTION) { switch (action) { @@ -1760,13 +1811,13 @@ static void select_all_perform(Scene *scene, Image *ima, BMEditMesh *em, int act if (action == SEL_TOGGLE) { action = SEL_SELECT; BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { - tf = CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY); + tf = BM_ELEM_CD_GET_VOID_P(efa, cd_poly_tex_offset); if (!uvedit_face_visible_test(scene, ima, efa, tf)) continue; BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { - luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV); + luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); if (luv->flag & MLOOPUV_VERTSEL) { action = SEL_DESELECT; @@ -1778,13 +1829,13 @@ static void select_all_perform(Scene *scene, Image *ima, BMEditMesh *em, int act BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { - tf = CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY); + tf = BM_ELEM_CD_GET_VOID_P(efa, cd_poly_tex_offset); if (!uvedit_face_visible_test(scene, ima, efa, tf)) continue; BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { - luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV); + luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); switch (action) { case SEL_SELECT: @@ -1879,6 +1930,9 @@ static int mouse_select(bContext *C, const float co[2], int extend, int loop) BLI_array_declare(hituv); float penalty[2]; + const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV); + const int cd_poly_tex_offset = CustomData_get_offset(&em->bm->pdata, CD_MTEXPOLY); + /* notice 'limit' is the same no matter the zoom level, since this is like * remove doubles and could annoying if it joined points when zoomed out. * 'penalty' is in screen pixel space otherwise zooming in on a uv-vert and @@ -1957,7 +2011,7 @@ static int mouse_select(bContext *C, const float co[2], int extend, int loop) hitv[hit.lindex] = hit.vert1; hitv[(hit.lindex + 1) % hit.efa->len] = hit.vert2; hituv[hit.lindex] = hit.luv->uv; - hituv[(hit.lindex + 1) % hit.efa->len] = hit.nextluv->uv; + hituv[(hit.lindex + 1) % hit.efa->len] = hit.luv_next->uv; hitlen = hit.efa->len; } @@ -1979,7 +2033,7 @@ static int mouse_select(bContext *C, const float co[2], int extend, int loop) BLI_array_grow_items(hituv, hit.efa->len); i = 0; BM_ITER_ELEM (l, &liter, hit.efa, BM_LOOPS_OF_FACE) { - luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV); + luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); hituv[i] = luv->uv; hitv[i] = BM_elem_index_get(l->v); i++; @@ -2065,12 +2119,12 @@ static int mouse_select(bContext *C, const float co[2], int extend, int loop) /* deselect */ if (select == 0) { BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { - tf = CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY); + tf = BM_ELEM_CD_GET_VOID_P(efa, cd_poly_tex_offset); if (!uvedit_face_visible_test(scene, ima, efa, tf)) continue; BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { - luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV); + luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); if (sticky_select(limit, hitv, BM_elem_index_get(l->v), hituv, luv->uv, sticky, hitlen)) uvedit_uv_select_disable(em, scene, l); } @@ -2080,12 +2134,12 @@ static int mouse_select(bContext *C, const float co[2], int extend, int loop) /* select */ else { BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { - tf = CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY); + tf = BM_ELEM_CD_GET_VOID_P(efa, cd_poly_tex_offset); if (!uvedit_face_visible_test(scene, ima, efa, tf)) continue; BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { - luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV); + luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); if (sticky_select(limit, hitv, BM_elem_index_get(l->v), hituv, luv->uv, sticky, hitlen)) uvedit_uv_select_enable(em, scene, l, FALSE); } @@ -2117,13 +2171,13 @@ static int mouse_select(bContext *C, const float co[2], int extend, int loop) /* select sticky uvs */ if (sticky != SI_STICKY_DISABLE) { BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { - tf = CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY); + tf = BM_ELEM_CD_GET_VOID_P(efa, cd_poly_tex_offset); if (!uvedit_face_visible_test(scene, ima, efa, tf)) continue; BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { if (sticky == SI_STICKY_DISABLE) continue; - luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV); + luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); if (sticky_select(limit, hitv, BM_elem_index_get(l->v), hituv, luv->uv, sticky, hitlen)) uvedit_uv_select_enable(em, scene, l, FALSE); @@ -2380,23 +2434,27 @@ static int select_split_exec(bContext *C, wmOperator *op) MLoopUV *luv; short change = FALSE; + const int cd_loop_uv_offset = CustomData_get_offset(&bm->ldata, CD_MLOOPUV); + const int cd_poly_tex_offset = CustomData_get_offset(&bm->pdata, CD_MTEXPOLY); + if (ts->uv_flag & UV_SYNC_SELECTION) { BKE_report(op->reports, RPT_ERROR, "Cannot split selection when sync selection is enabled"); return OPERATOR_CANCELLED; } + BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) { int is_sel = FALSE; int is_unsel = FALSE; - tf = CustomData_bmesh_get(&bm->pdata, efa->head.data, CD_MTEXPOLY); + tf = BM_ELEM_CD_GET_VOID_P(efa, cd_poly_tex_offset); if (!uvedit_face_visible_test(scene, ima, efa, tf)) continue; /* are we all selected? */ BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { - luv = CustomData_bmesh_get(&bm->ldata, l->head.data, CD_MLOOPUV); + luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); if (luv->flag & MLOOPUV_VERTSEL) { is_sel = TRUE; @@ -2413,7 +2471,7 @@ static int select_split_exec(bContext *C, wmOperator *op) if (is_sel && is_unsel) { BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { - luv = CustomData_bmesh_get(&bm->ldata, l->head.data, CD_MLOOPUV); + luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); luv->flag &= ~MLOOPUV_VERTSEL; } @@ -2459,6 +2517,9 @@ static int unlink_selection_exec(bContext *C, wmOperator *op) MTexPoly *tf; MLoopUV *luv; + const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV); + const int cd_poly_tex_offset = CustomData_get_offset(&em->bm->pdata, CD_MTEXPOLY); + if (ts->uv_flag & UV_SYNC_SELECTION) { BKE_report(op->reports, RPT_ERROR, "Cannot unlink selection when sync selection is enabled"); return OPERATOR_CANCELLED; @@ -2467,12 +2528,12 @@ static int unlink_selection_exec(bContext *C, wmOperator *op) BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { int desel = 0; - tf = CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY); + tf = BM_ELEM_CD_GET_VOID_P(efa, cd_poly_tex_offset); if (!uvedit_face_visible_test(scene, ima, efa, tf)) continue; BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { - luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV); + luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); if (!(luv->flag & MLOOPUV_VERTSEL)) { desel = 1; @@ -2482,7 +2543,7 @@ static int unlink_selection_exec(bContext *C, wmOperator *op) if (desel) { BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { - luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV); + luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); luv->flag &= ~MLOOPUV_VERTSEL; } } @@ -2569,7 +2630,7 @@ static void uv_faces_do_sticky(SpaceImage *sima, Scene *scene, Object *obedit, s /* now select tagged verts */ BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { - /* tf = CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY); */ /* UNUSED */ + /* tf = BM_ELEM_CD_GET_VOID_P(efa, cd_poly_tex_offset); */ /* UNUSED */ BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { if (BM_elem_flag_test(l->v, BM_ELEM_TAG)) { @@ -2604,7 +2665,7 @@ static void uv_faces_do_sticky(SpaceImage *sima, Scene *scene, Object *obedit, s efa = BM_iter_new(&iter, em->bm, BM_FACES_OF_MESH, NULL); for (efa_index = 0; efa; efa = BM_iter_step(&iter), efa_index++) { if (BM_elem_flag_test(efa, BM_ELEM_TAG)) { - /* tf = CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY); */ /* UNUSED */ + /* tf = BM_ELEM_CD_GET_VOID_P(efa, cd_poly_tex_offset); */ /* UNUSED */ BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { if (select) @@ -2633,7 +2694,7 @@ static void uv_faces_do_sticky(SpaceImage *sima, Scene *scene, Object *obedit, s if (efa_index != vlist_iter->f) { BMLoop *l_other; efa_vlist = EDBM_face_at_index(em, vlist_iter->f); - /* tf_vlist = CustomData_bmesh_get(&em->bm->pdata, efa_vlist->head.data, CD_MTEXPOLY); */ /* UNUSED */ + /* tf_vlist = BM_ELEM_CD_GET_VOID_P(efa_vlist, cd_poly_tex_offset); */ /* UNUSED */ l_other = BM_iter_at_index(em->bm, BM_LOOPS_OF_FACE, efa_vlist, vlist_iter->tfindex); @@ -2685,6 +2746,9 @@ static int border_select_exec(bContext *C, wmOperator *op) (ts->selectmode == SCE_SELECT_FACE) : (ts->uv_selectmode == UV_SELECT_FACE); + const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV); + const int cd_poly_tex_offset = CustomData_get_offset(&em->bm->pdata, CD_MTEXPOLY); + /* get rectangle from operator */ WM_operator_properties_border_to_rcti(op, &rect); @@ -2710,7 +2774,7 @@ static int border_select_exec(bContext *C, wmOperator *op) /* assume not touched */ BM_elem_flag_disable(efa, BM_ELEM_TAG); - tf = CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY); + tf = BM_ELEM_CD_GET_VOID_P(efa, cd_poly_tex_offset); if (uvedit_face_visible_test(scene, ima, efa, tf)) { uv_poly_center(em, efa, cent); if (BLI_rctf_isect_pt_v(&rectf, cent)) { @@ -2730,11 +2794,11 @@ static int border_select_exec(bContext *C, wmOperator *op) change = 1; BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { - tf = CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY); + tf = BM_ELEM_CD_GET_VOID_P(efa, cd_poly_tex_offset); if (!uvedit_face_visible_test(scene, ima, efa, tf)) continue; BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { - luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV); + luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); if (!pinned || (ts->uv_flag & UV_SYNC_SELECTION) ) { @@ -2834,6 +2898,8 @@ static int circle_select_exec(bContext *C, wmOperator *op) (ts->selectmode == SCE_SELECT_FACE) : (ts->uv_selectmode == UV_SELECT_FACE); + const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV); + /* get operator properties */ select = (gesture_mode == GESTURE_MODAL_SELECT); x = RNA_int_get(op->ptr, "x"); @@ -2874,7 +2940,7 @@ static int circle_select_exec(bContext *C, wmOperator *op) else { BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { - luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV); + luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); change |= select_uv_inside_ellipse(em, scene, select, offset, ellipse, l, luv); } } @@ -2929,6 +2995,9 @@ static int do_lasso_select_mesh_uv(bContext *C, const int mcords[][2], short mov (ts->selectmode == SCE_SELECT_FACE) : (ts->uv_selectmode == UV_SELECT_FACE); + const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV); + const int cd_poly_tex_offset = CustomData_get_offset(&em->bm->pdata, CD_MTEXPOLY); + BMIter iter, liter; BMFace *efa; @@ -2964,11 +3033,11 @@ static int do_lasso_select_mesh_uv(bContext *C, const int mcords[][2], short mov } else { /* Vert Sel */ BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { - tf = CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY); + tf = BM_ELEM_CD_GET_VOID_P(efa, cd_poly_tex_offset); if (uvedit_face_visible_test(scene, ima, efa, tf)) { BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { if ((select) != (uvedit_uv_select_test(em, scene, l))) { - MLoopUV *luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV); + MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); UI_view2d_view_to_region(&ar->v2d, luv->uv[0], luv->uv[1], &screen_uv[0], &screen_uv[1]); if (BLI_rcti_isect_pt_v(&rect, screen_uv) && BLI_lasso_is_point_inside(mcords, moves, screen_uv[0], screen_uv[1], V2D_IS_CLIPPED)) @@ -3119,14 +3188,17 @@ static int snap_uvs_to_cursor(Scene *scene, Image *ima, Object *obedit, SpaceIma MLoopUV *luv; short change = 0; + const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV); + const int cd_poly_tex_offset = CustomData_get_offset(&em->bm->pdata, CD_MTEXPOLY); + BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { - tface = CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY); + tface = BM_ELEM_CD_GET_VOID_P(efa, cd_poly_tex_offset); if (!uvedit_face_visible_test(scene, ima, efa, tface)) continue; BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { if (uvedit_uv_select_test(em, scene, l)) { - luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV); + luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); copy_v2_v2(luv->uv, sima->cursor); change = 1; } @@ -3146,11 +3218,13 @@ static int snap_uvs_to_adjacent_unselected(Scene *scene, Image *ima, Object *obe MTexPoly *tface; MLoopUV *luv; short change = FALSE; + const int cd_loop_uv_offset = CustomData_get_offset(&bm->ldata, CD_MLOOPUV); + const int cd_poly_tex_offset = CustomData_get_offset(&bm->pdata, CD_MTEXPOLY); /* index every vert that has a selected UV using it, but only once so as to * get unique indices and to count how much to malloc */ BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) { - tface = CustomData_bmesh_get(&bm->pdata, f->head.data, CD_MTEXPOLY); + tface = BM_ELEM_CD_GET_VOID_P(f, cd_poly_tex_offset); if (uvedit_face_visible_test(scene, ima, f, tface)) { BM_elem_flag_enable(f, BM_ELEM_TAG); BM_ITER_ELEM (l, &liter, f, BM_LOOPS_OF_FACE) { @@ -3173,15 +3247,14 @@ static int snap_uvs_to_adjacent_unselected(Scene *scene, Image *ima, Object *obe if (BM_elem_flag_test(lsub->f, BM_ELEM_TAG) && /* face: visible */ !BM_elem_flag_test(lsub, BM_ELEM_TAG)) /* loop: unselected */ { - - luv = CustomData_bmesh_get(&bm->ldata, lsub->head.data, CD_MLOOPUV); + luv = BM_ELEM_CD_GET_VOID_P(lsub, cd_loop_uv_offset); add_v2_v2(uv, luv->uv); uv_tot++; } } if (uv_tot) { - luv = CustomData_bmesh_get(&bm->ldata, l->head.data, CD_MLOOPUV); + luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); mul_v2_v2fl(luv->uv, uv, 1.0f / (float)uv_tot); change = TRUE; } @@ -3206,18 +3279,21 @@ static int snap_uvs_to_pixels(SpaceImage *sima, Scene *scene, Object *obedit) float w, h; short change = 0; + const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV); + const int cd_poly_tex_offset = CustomData_get_offset(&em->bm->pdata, CD_MTEXPOLY); + ED_space_image_get_size(sima, &width, &height); w = (float)width; h = (float)height; BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { - tface = CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY); + tface = BM_ELEM_CD_GET_VOID_P(efa, cd_poly_tex_offset); if (!uvedit_face_visible_test(scene, ima, efa, tface)) continue; BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { if (uvedit_uv_select_test(em, scene, l)) { - luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV); + luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); snap_uv_to_pixel(luv->uv, w, h); } } @@ -3295,13 +3371,16 @@ static int pin_exec(bContext *C, wmOperator *op) MLoopUV *luv; int clear = RNA_boolean_get(op->ptr, "clear"); + const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV); + const int cd_poly_tex_offset = CustomData_get_offset(&em->bm->pdata, CD_MTEXPOLY); + BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { - tface = CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY); + tface = BM_ELEM_CD_GET_VOID_P(efa, cd_poly_tex_offset); if (!uvedit_face_visible_test(scene, ima, efa, tface)) continue; BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { - luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV); + luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); if (!clear) { if (uvedit_uv_select_test(em, scene, l)) @@ -3349,13 +3428,16 @@ static int select_pinned_exec(bContext *C, wmOperator *UNUSED(op)) MTexPoly *tface; MLoopUV *luv; + const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV); + const int cd_poly_tex_offset = CustomData_get_offset(&em->bm->pdata, CD_MTEXPOLY); + BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { - tface = CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY); + tface = BM_ELEM_CD_GET_VOID_P(efa, cd_poly_tex_offset); if (!uvedit_face_visible_test(scene, ima, efa, tface)) continue; BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { - luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV); + luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); if (luv->flag & MLOOPUV_PINNED) uvedit_uv_select_enable(em, scene, l, FALSE); @@ -3387,15 +3469,17 @@ static void UV_OT_select_pinned(wmOperatorType *ot) #define UV_SEL_TEST(luv, bool_test) ((((luv)->flag & MLOOPUV_VERTSEL) == MLOOPUV_VERTSEL) == bool_test) /* is every UV vert selected or unselected depending on bool_test */ -static int bm_face_is_all_uv_sel(BMesh *bm, BMFace *f, int bool_test) +static int bm_face_is_all_uv_sel(BMFace *f, bool select_test, + const int cd_loop_uv_offset) { BMLoop *l_iter; BMLoop *l_first; l_iter = l_first = BM_FACE_FIRST_LOOP(f); do { - MLoopUV *luv = CustomData_bmesh_get(&bm->ldata, l_iter->head.data, CD_MLOOPUV); - if (!UV_SEL_TEST(luv, bool_test)) { + + MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(l_iter, cd_loop_uv_offset); + if (!UV_SEL_TEST(luv, select_test)) { return FALSE; } } while ((l_iter = l_iter->next) != l_first); @@ -3419,6 +3503,9 @@ static int hide_exec(bContext *C, wmOperator *op) Image *ima = sima ? sima->image : NULL; const int use_face_center = (ts->uv_selectmode == UV_SELECT_FACE); + const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV); + const int cd_poly_tex_offset = CustomData_get_offset(&em->bm->pdata, CD_MTEXPOLY); + if (ts->uv_flag & UV_SYNC_SELECTION) { EDBM_mesh_hide(em, swap); WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data); @@ -3429,14 +3516,14 @@ static int hide_exec(bContext *C, wmOperator *op) BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { int hide = 0; - tf = CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY); + tf = BM_ELEM_CD_GET_VOID_P(efa, cd_poly_tex_offset); if (!uvedit_face_visible_test(scene, ima, efa, tf)) { continue; } BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { - luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV); + luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); if (UV_SEL_TEST(luv, !swap)) { hide = 1; @@ -3450,15 +3537,15 @@ static int hide_exec(bContext *C, wmOperator *op) if (use_face_center) { if (em->selectmode == SCE_SELECT_FACE) { /* check that every UV is selected */ - if (bm_face_is_all_uv_sel(em->bm, efa, TRUE) == !swap) { + if (bm_face_is_all_uv_sel(efa, true, cd_loop_uv_offset) == !swap) { BM_face_select_set(em->bm, efa, FALSE); } uvedit_face_select_disable(scene, em, efa); } else { - if (bm_face_is_all_uv_sel(em->bm, efa, TRUE) == !swap) { + if (bm_face_is_all_uv_sel(efa, true, cd_loop_uv_offset) == !swap) { BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { - luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV); + luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); if (UV_SEL_TEST(luv, !swap)) { BM_vert_select_set(em->bm, l->v, FALSE); } @@ -3469,14 +3556,14 @@ static int hide_exec(bContext *C, wmOperator *op) } else if (em->selectmode == SCE_SELECT_FACE) { /* check if a UV is de-selected */ - if (bm_face_is_all_uv_sel(em->bm, efa, FALSE) != !swap) { + if (bm_face_is_all_uv_sel(efa, false, cd_loop_uv_offset) != !swap) { BM_face_select_set(em->bm, efa, FALSE); uvedit_face_select_disable(scene, em, efa); } } else { BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { - luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV); + luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); if (UV_SEL_TEST(luv, !swap)) { BM_vert_select_set(em->bm, l->v, FALSE); if (!swap) luv->flag &= ~MLOOPUV_VERTSEL; @@ -3530,6 +3617,8 @@ static int reveal_exec(bContext *C, wmOperator *UNUSED(op)) const int use_face_center = (ts->uv_selectmode == UV_SELECT_FACE); const int stickymode = sima ? (sima->sticky != SI_STICKY_DISABLE) : 1; + const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV); + /* note on tagging, selecting faces needs to be delayed so it doesn't select the verts and * confuse our checks on selected verts. */ @@ -3546,7 +3635,7 @@ static int reveal_exec(bContext *C, wmOperator *UNUSED(op)) BM_elem_flag_disable(efa, BM_ELEM_TAG); if (!BM_elem_flag_test(efa, BM_ELEM_HIDDEN) && !BM_elem_flag_test(efa, BM_ELEM_SELECT)) { BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { - luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV); + luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); luv->flag |= MLOOPUV_VERTSEL; } /* BM_face_select_set(em->bm, efa, TRUE); */ @@ -3567,7 +3656,7 @@ static int reveal_exec(bContext *C, wmOperator *UNUSED(op)) if (!totsel) { BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { - luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV); + luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); luv->flag |= MLOOPUV_VERTSEL; } /* BM_face_select_set(em->bm, efa, TRUE); */ @@ -3582,7 +3671,7 @@ static int reveal_exec(bContext *C, wmOperator *UNUSED(op)) if (!BM_elem_flag_test(efa, BM_ELEM_HIDDEN) && !BM_elem_flag_test(efa, BM_ELEM_SELECT)) { BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { if (BM_elem_flag_test(l->v, BM_ELEM_SELECT) == 0) { - luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV); + luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); luv->flag |= MLOOPUV_VERTSEL; } } @@ -3598,7 +3687,7 @@ static int reveal_exec(bContext *C, wmOperator *UNUSED(op)) BM_elem_flag_disable(efa, BM_ELEM_TAG); if (!BM_elem_flag_test(efa, BM_ELEM_HIDDEN) && !BM_elem_flag_test(efa, BM_ELEM_SELECT)) { BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { - luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV); + luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); luv->flag |= MLOOPUV_VERTSEL; } /* BM_face_select_set(em->bm, efa, TRUE); */ @@ -3612,7 +3701,7 @@ static int reveal_exec(bContext *C, wmOperator *UNUSED(op)) if (!BM_elem_flag_test(efa, BM_ELEM_HIDDEN) && !BM_elem_flag_test(efa, BM_ELEM_SELECT)) { BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { if (BM_elem_flag_test(l->v, BM_ELEM_SELECT) == 0) { - luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV); + luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); luv->flag |= MLOOPUV_VERTSEL; } } diff --git a/source/blender/editors/uvedit/uvedit_unwrap_ops.c b/source/blender/editors/uvedit/uvedit_unwrap_ops.c index 81f548b2b5d..00b82e26a05 100644 --- a/source/blender/editors/uvedit/uvedit_unwrap_ops.c +++ b/source/blender/editors/uvedit/uvedit_unwrap_ops.c @@ -161,13 +161,16 @@ static int ED_uvedit_ensure_uvs(bContext *C, Scene *scene, Object *obedit) /****************** Parametrizer Conversion ***************/ -static int uvedit_have_selection(Scene *scene, BMEditMesh *em, short implicit) +static bool uvedit_have_selection(Scene *scene, BMEditMesh *em, bool implicit) { BMFace *efa; BMLoop *l; BMIter iter, liter; - MLoopUV *luv; + if (!CustomData_has_layer(&em->bm->ldata, CD_MLOOPUV)) { + return (em->bm->totfacesel != 0); + } + /* verify if we have any selected uv's before unwrapping, * so we can cancel the operator early */ BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { @@ -175,14 +178,10 @@ static int uvedit_have_selection(Scene *scene, BMEditMesh *em, short implicit) if (BM_elem_flag_test(efa, BM_ELEM_HIDDEN)) continue; } - else if (BM_elem_flag_test(efa, BM_ELEM_HIDDEN) || !BM_elem_flag_test(efa, BM_ELEM_SELECT)) + else if (!BM_elem_flag_test(efa, BM_ELEM_SELECT)) continue; BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { - luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV); - if (!luv) - return 1; - if (uvedit_uv_select_test(em, scene, l)) break; } @@ -190,10 +189,10 @@ static int uvedit_have_selection(Scene *scene, BMEditMesh *em, short implicit) if (implicit && !l) continue; - return 1; + return true; } - return 0; + return false; } void uvedit_get_aspect(Scene *scene, Object *ob, BMEditMesh *em, float *aspx, float *aspy) @@ -226,6 +225,7 @@ static ParamHandle *construct_param_handle(Scene *scene, Object *ob, BMEditMesh short implicit, short fill, short sel, short correct_aspect) { + BMesh *bm = em->bm; ScanFillContext sf_ctx; ParamHandle *handle; BMFace *efa; @@ -233,8 +233,11 @@ static ParamHandle *construct_param_handle(Scene *scene, Object *ob, BMEditMesh BMEdge *eed; BMIter iter, liter; + const int cd_loop_uv_offset = CustomData_get_offset(&bm->ldata, CD_MLOOPUV); + handle = param_construct_begin(); + if (correct_aspect) { float aspx, aspy; @@ -284,7 +287,7 @@ static ParamHandle *construct_param_handle(Scene *scene, Object *ob, BMEditMesh * about which split is best for unwrapping than scanfill */ i = 0; BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { - MLoopUV *luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV); + MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); vkeys[i] = (ParamKey)BM_elem_index_get(l->v); co[i] = l->v->co; uv[i] = luv->uv; @@ -332,7 +335,7 @@ static ParamHandle *construct_param_handle(Scene *scene, Object *ob, BMEditMesh ls[2] = sf_tri->v3->tmp.p; for (i = 0; i < 3; i++) { - MLoopUV *luv = CustomData_bmesh_get(&em->bm->ldata, ls[i]->head.data, CD_MLOOPUV); + MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(ls[i], cd_loop_uv_offset); vkeys[i] = (ParamKey)BM_elem_index_get(ls[i]->v); co[i] = ls[i]->v->co; uv[i] = luv->uv; @@ -364,7 +367,8 @@ static ParamHandle *construct_param_handle(Scene *scene, Object *ob, BMEditMesh } -static void texface_from_original_index(BMFace *efa, int index, float **uv, ParamBool *pin, ParamBool *select, Scene *scene, BMEditMesh *em) +static void texface_from_original_index(BMFace *efa, int index, float **uv, ParamBool *pin, ParamBool *select, + Scene *scene, BMEditMesh *em, const int cd_loop_uv_offset) { BMLoop *l; BMIter liter; @@ -379,10 +383,11 @@ static void texface_from_original_index(BMFace *efa, int index, float **uv, Para BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { if (BM_elem_index_get(l->v) == index) { - luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV); + luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); *uv = luv->uv; *pin = (luv->flag & MLOOPUV_PINNED) ? 1 : 0; *select = (uvedit_uv_select_test(em, scene, l) != 0); + break; } } } @@ -418,6 +423,8 @@ static ParamHandle *construct_param_handle_subsurfed(Scene *scene, Object *ob, B /* similar to the above, we need a way to map edges to their original ones */ BMEdge **edgeMap; + const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV); + handle = param_construct_begin(); if (correct_aspect) { @@ -506,10 +513,10 @@ static ParamHandle *construct_param_handle_subsurfed(Scene *scene, Object *ob, B /* This is where all the magic is done. If the vertex exists in the, we pass the original uv pointer to the solver, thus * flushing the solution to the edit mesh. */ - texface_from_original_index(origFace, origVertIndices[face->v1], &uv[0], &pin[0], &select[0], scene, em); - texface_from_original_index(origFace, origVertIndices[face->v2], &uv[1], &pin[1], &select[1], scene, em); - texface_from_original_index(origFace, origVertIndices[face->v3], &uv[2], &pin[2], &select[2], scene, em); - texface_from_original_index(origFace, origVertIndices[face->v4], &uv[3], &pin[3], &select[3], scene, em); + texface_from_original_index(origFace, origVertIndices[face->v1], &uv[0], &pin[0], &select[0], scene, em, cd_loop_uv_offset); + texface_from_original_index(origFace, origVertIndices[face->v2], &uv[1], &pin[1], &select[1], scene, em, cd_loop_uv_offset); + texface_from_original_index(origFace, origVertIndices[face->v3], &uv[2], &pin[2], &select[2], scene, em, cd_loop_uv_offset); + texface_from_original_index(origFace, origVertIndices[face->v4], &uv[3], &pin[3], &select[3], scene, em, cd_loop_uv_offset); param_face_add(handle, key, 4, vkeys, co, uv, pin, select); } @@ -547,17 +554,17 @@ typedef struct MinStretch { wmTimer *timer; } MinStretch; -static int minimize_stretch_init(bContext *C, wmOperator *op) +static bool minimize_stretch_init(bContext *C, wmOperator *op) { Scene *scene = CTX_data_scene(C); Object *obedit = CTX_data_edit_object(C); BMEditMesh *em = BMEdit_FromObject(obedit); MinStretch *ms; int fill_holes = RNA_boolean_get(op->ptr, "fill_holes"); - short implicit = 1; + bool implicit = true; if (!uvedit_have_selection(scene, em, implicit)) { - return 0; + return false; } ms = MEM_callocN(sizeof(MinStretch), "MinStretch"); @@ -576,7 +583,7 @@ static int minimize_stretch_init(bContext *C, wmOperator *op) op->customdata = ms; - return 1; + return true; } static void minimize_stretch_iteration(bContext *C, wmOperator *op, int interactive) @@ -596,7 +603,7 @@ static void minimize_stretch_iteration(bContext *C, wmOperator *op, int interact param_flush(ms->handle); if (sa) { - BLI_snprintf(str, sizeof(str), "Minimize Stretch. Blend %.2f", ms->blend); + BLI_snprintf(str, sizeof(str), "Minimize Stretch. Blend %.2f (Press + and -, or scroll wheel to set)", ms->blend); ED_area_headerprint(sa, str); } @@ -679,20 +686,24 @@ static int minimize_stretch_modal(bContext *C, wmOperator *op, wmEvent *event) return OPERATOR_FINISHED; case PADPLUSKEY: case WHEELUPMOUSE: - if (ms->blend < 0.95f) { - ms->blend += 0.1f; - ms->lasttime = 0.0f; - RNA_float_set(op->ptr, "blend", ms->blend); - minimize_stretch_iteration(C, op, 1); + if (event->val == KM_PRESS) { + if (ms->blend < 0.95f) { + ms->blend += 0.1f; + ms->lasttime = 0.0f; + RNA_float_set(op->ptr, "blend", ms->blend); + minimize_stretch_iteration(C, op, 1); + } } break; case PADMINUS: case WHEELDOWNMOUSE: - if (ms->blend > 0.05f) { - ms->blend -= 0.1f; - ms->lasttime = 0.0f; - RNA_float_set(op->ptr, "blend", ms->blend); - minimize_stretch_iteration(C, op, 1); + if (event->val == KM_PRESS) { + if (ms->blend > 0.05f) { + ms->blend -= 0.1f; + ms->lasttime = 0.0f; + RNA_float_set(op->ptr, "blend", ms->blend); + minimize_stretch_iteration(C, op, 1); + } } break; case TIMER: @@ -750,7 +761,7 @@ static int pack_islands_exec(bContext *C, wmOperator *op) Object *obedit = CTX_data_edit_object(C); BMEditMesh *em = BMEdit_FromObject(obedit); ParamHandle *handle; - short implicit = 1; + bool implicit = true; if (!uvedit_have_selection(scene, em, implicit)) { return OPERATOR_CANCELLED; @@ -797,7 +808,7 @@ static int average_islands_scale_exec(bContext *C, wmOperator *UNUSED(op)) Object *obedit = CTX_data_edit_object(C); BMEditMesh *em = BMEdit_FromObject(obedit); ParamHandle *handle; - short implicit = 1; + bool implicit = true; if (!uvedit_have_selection(scene, em, implicit)) { return OPERATOR_CANCELLED; @@ -965,18 +976,18 @@ static void uv_map_rotation_matrix(float result[4][4], RegionView3D *rv3d, Objec /* this is "kanonen gegen spatzen", a few plus minus 1 will do here */ /* i wanted to keep the reason here, so we're rotating*/ sideangle = (float)M_PI * (sideangledeg + 180.0f) / 180.0f; - rotside[0][0] = (float)cos(sideangle); - rotside[0][1] = -(float)sin(sideangle); - rotside[1][0] = (float)sin(sideangle); - rotside[1][1] = (float)cos(sideangle); - rotside[2][2] = 1.0f; + rotside[0][0] = cosf(sideangle); + rotside[0][1] = -sinf(sideangle); + rotside[1][0] = sinf(sideangle); + rotside[1][1] = cosf(sideangle); + rotside[2][2] = 1.0f; upangle = (float)M_PI * upangledeg / 180.0f; - rotup[1][1] = (float)cos(upangle) / radius; - rotup[1][2] = -(float)sin(upangle) / radius; - rotup[2][1] = (float)sin(upangle) / radius; - rotup[2][2] = (float)cos(upangle) / radius; - rotup[0][0] = (float)1.0f / radius; + rotup[1][1] = cosf(upangle) / radius; + rotup[1][2] = -sinf(upangle) / radius; + rotup[2][1] = sinf(upangle) / radius; + rotup[2][2] = cosf(upangle) / radius; + rotup[0][0] = 1.0f / radius; /* calculate transforms*/ mul_serie_m4(result, rotup, rotside, viewmatrix, rotobj, NULL, NULL, NULL, NULL); @@ -1047,6 +1058,8 @@ static void correct_uv_aspect(Scene *scene, Object *ob, BMEditMesh *em) BMFace *efa; float scale, aspx, aspy; + const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV); + uvedit_get_aspect(scene, ob, em, &aspx, &aspy); if (aspx == aspy) @@ -1056,11 +1069,11 @@ static void correct_uv_aspect(Scene *scene, Object *ob, BMEditMesh *em) scale = aspy / aspx; BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { - if (!BM_elem_flag_test(efa, BM_ELEM_SELECT) || BM_elem_flag_test(efa, BM_ELEM_HIDDEN)) + if (!BM_elem_flag_test(efa, BM_ELEM_SELECT)) continue; BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { - luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV); + luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); luv->uv[0] = ((luv->uv[0] - 0.5f) * scale) + 0.5f; } } @@ -1069,11 +1082,11 @@ static void correct_uv_aspect(Scene *scene, Object *ob, BMEditMesh *em) scale = aspx / aspy; BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { - if (!BM_elem_flag_test(efa, BM_ELEM_SELECT) || BM_elem_flag_test(efa, BM_ELEM_HIDDEN)) + if (!BM_elem_flag_test(efa, BM_ELEM_SELECT)) continue; BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { - luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV); + luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); luv->uv[1] = ((luv->uv[1] - 0.5f) * scale) + 0.5f; } } @@ -1103,6 +1116,8 @@ static void uv_map_clip_correct(Scene *scene, Object *ob, BMEditMesh *em, wmOper int clip_to_bounds = RNA_boolean_get(op->ptr, "clip_to_bounds"); int scale_to_bounds = RNA_boolean_get(op->ptr, "scale_to_bounds"); + const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV); + /* correct for image aspect ratio */ if (correct_aspect) correct_uv_aspect(scene, ob, em); @@ -1115,7 +1130,7 @@ static void uv_map_clip_correct(Scene *scene, Object *ob, BMEditMesh *em, wmOper continue; BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { - luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV); + luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); minmax_v2v2_v2(min, max, luv->uv); } } @@ -1134,7 +1149,7 @@ static void uv_map_clip_correct(Scene *scene, Object *ob, BMEditMesh *em, wmOper continue; BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { - luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV); + luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); luv->uv[0] = (luv->uv[0] - min[0]) * dx; luv->uv[1] = (luv->uv[1] - min[1]) * dy; @@ -1148,7 +1163,7 @@ static void uv_map_clip_correct(Scene *scene, Object *ob, BMEditMesh *em, wmOper continue; BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { - luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV); + luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); CLAMP(luv->uv[0], 0.0f, 1.0f); CLAMP(luv->uv[1], 0.0f, 1.0f); } @@ -1198,7 +1213,7 @@ static int unwrap_exec(bContext *C, wmOperator *op) int use_subsurf = RNA_boolean_get(op->ptr, "use_subsurf_data"); short use_subsurf_final; float obsize[3]; - short implicit = 0; + bool implicit = false; if (!uvedit_have_selection(scene, em, implicit)) { return OPERATOR_CANCELLED; @@ -1296,11 +1311,15 @@ static int uv_from_view_exec(bContext *C, wmOperator *op) MLoopUV *luv; float rotmat[4][4]; + int cd_loop_uv_offset; + /* add uvs if they don't exist yet */ if (!ED_uvedit_ensure_uvs(C, scene, obedit)) { return OPERATOR_CANCELLED; } + cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV); + /* establish the camera object, so we can default to view mapping if anything is wrong with it */ if ((rv3d->persp == RV3D_CAMOB) && (v3d->camera) && (v3d->camera->type == OB_CAMERA)) { camera = v3d->camera->data; @@ -1314,7 +1333,7 @@ static int uv_from_view_exec(bContext *C, wmOperator *op) continue; BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { - luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV); + luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); BLI_uvproject_from_view_ortho(luv->uv, l->v->co, rotmat); } } @@ -1328,7 +1347,7 @@ static int uv_from_view_exec(bContext *C, wmOperator *op) continue; BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { - luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV); + luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); BLI_uvproject_from_camera(luv->uv, l->v->co, uci); } } @@ -1344,7 +1363,7 @@ static int uv_from_view_exec(bContext *C, wmOperator *op) continue; BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { - luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV); + luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); BLI_uvproject_from_view(luv->uv, l->v->co, rv3d->persmat, rotmat, ar->winx, ar->winy); } } @@ -1448,11 +1467,11 @@ static void uv_map_mirror(BMEditMesh *em, BMFace *efa, MTexPoly *UNUSED(tf)) float dx; int i, mi; - i = 0; - BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { - luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV); + const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV); + + BM_ITER_ELEM_INDEX (l, &liter, efa, BM_LOOPS_OF_FACE, i) { + luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); uvs[i] = luv->uv; - i++; } mi = 0; @@ -1480,11 +1499,15 @@ static int sphere_project_exec(bContext *C, wmOperator *op) MLoopUV *luv; float center[3], rotmat[4][4]; + int cd_loop_uv_offset; + /* add uvs if they don't exist yet */ if (!ED_uvedit_ensure_uvs(C, scene, obedit)) { return OPERATOR_CANCELLED; } + cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV); + uv_map_transform(C, op, center, rotmat); BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { @@ -1492,7 +1515,7 @@ static int sphere_project_exec(bContext *C, wmOperator *op) continue; BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { - luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV); + luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); uv_sphere_project(luv->uv, l->v->co, center, rotmat); } @@ -1555,11 +1578,15 @@ static int cylinder_project_exec(bContext *C, wmOperator *op) MLoopUV *luv; float center[3], rotmat[4][4]; + int cd_loop_uv_offset; + /* add uvs if they don't exist yet */ if (!ED_uvedit_ensure_uvs(C, scene, obedit)) { return OPERATOR_CANCELLED; } + cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV); + uv_map_transform(C, op, center, rotmat); BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { @@ -1567,7 +1594,7 @@ static int cylinder_project_exec(bContext *C, wmOperator *op) continue; BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { - luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV); + luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); uv_cylinder_project(luv->uv, l->v->co, center, rotmat); } @@ -1617,11 +1644,15 @@ static int cube_project_exec(bContext *C, wmOperator *op) float cube_size, *loc, dx, dy; int cox, coy; + int cd_loop_uv_offset; + /* add uvs if they don't exist yet */ if (!ED_uvedit_ensure_uvs(C, scene, obedit)) { return OPERATOR_CANCELLED; } + cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV); + loc = obedit->obmat[3]; cube_size = RNA_float_get(op->ptr, "cube_size"); @@ -1639,7 +1670,7 @@ static int cube_project_exec(bContext *C, wmOperator *op) dx = dy = 0; BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { - luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV); + luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); luv->uv[0] = 0.5f + 0.5f * cube_size * (loc[cox] + l->v->co[cox]); luv->uv[1] = 0.5f + 0.5f * cube_size * (loc[coy] + l->v->co[coy]); |