diff options
Diffstat (limited to 'source/blender/editors')
90 files changed, 1370 insertions, 1154 deletions
diff --git a/source/blender/editors/animation/anim_draw.c b/source/blender/editors/animation/anim_draw.c index 4203c2677b7..a2a1f7eb1d2 100644 --- a/source/blender/editors/animation/anim_draw.c +++ b/source/blender/editors/animation/anim_draw.c @@ -62,67 +62,6 @@ /* *************************************************** */ /* CURRENT FRAME DRAWING */ -/* Draw current frame number in a little green box beside the current frame indicator */ -void ANIM_draw_cfra_number(const bContext *C, View2D *v2d, short flag) -{ - Scene *scene = CTX_data_scene(C); - const float time = scene->r.cfra + scene->r.subframe; - const float cfra = (float)(time * scene->r.framelen); - const bool show_time = (flag & DRAWCFRA_UNIT_SECONDS) != 0; - - const uiFontStyle *fstyle = UI_FSTYLE_WIDGET; - uchar col[4]; - float color[4]; - float xscale, x, y; - char numstr[32] = " t "; /* t is the character to start replacing from */ - float hlen; - int slen; - - /* because the frame number text is subject to the same scaling as the contents of the view */ - UI_view2d_scale_get(v2d, &xscale, NULL); - GPU_matrix_push(); - GPU_matrix_scale_2f(1.0f / xscale, 1.0f); - - /* get timecode string - * - padding on str-buf passed so that it doesn't sit on the frame indicator - */ - if (show_time) { - BLI_timecode_string_from_time( - &numstr[2], sizeof(numstr) - 2, 0, FRA2TIME(cfra), FPS, U.timecode_style); - } - else { - BLI_timecode_string_from_time_seconds(&numstr[2], sizeof(numstr) - 2, 1, cfra); - } - - slen = UI_fontstyle_string_width(fstyle, numstr) - 1; - hlen = slen * 0.5f; - - /* get starting coordinates for drawing */ - x = cfra * xscale; - y = -0.1f * U.widget_unit; - - /* draw green box around/behind text */ - UI_GetThemeColor4fv(TH_CFRAME, color); - color[3] = 3.0f; - - UI_draw_roundbox_corner_set(UI_CNR_ALL); - UI_draw_roundbox_aa(true, - x - hlen - 0.1f * U.widget_unit, - y + 3.0f, - x + hlen + 0.1f * U.widget_unit, - y - 3.0f + U.widget_unit, - 0.1f * U.widget_unit, - color); - - /* draw current frame number */ - UI_GetThemeColor4ubv(TH_TEXT_HI, col); - UI_fontstyle_draw_simple( - fstyle, x - hlen - 0.15f * U.widget_unit, y + 0.28f * U.widget_unit, numstr, col); - - /* restore view transform */ - GPU_matrix_pop(); -} - /* General call for drawing current frame indicator in animation editor */ void ANIM_draw_cfra(const bContext *C, View2D *v2d, short flag) { diff --git a/source/blender/editors/animation/keyframing.c b/source/blender/editors/animation/keyframing.c index 04061ceea51..0e9b870df88 100644 --- a/source/blender/editors/animation/keyframing.c +++ b/source/blender/editors/animation/keyframing.c @@ -1827,7 +1827,7 @@ static int insert_key_exec(bContext *C, wmOperator *op) * updated since the last switching to the edit mode will be keyframed correctly */ if (obedit && ANIM_keyingset_find_id(ks, (ID *)obedit->data)) { - ED_object_mode_toggle(C, OB_MODE_EDIT); + ED_object_mode_set(C, OB_MODE_OBJECT); ob_edit_mode = true; } @@ -1843,7 +1843,7 @@ static int insert_key_exec(bContext *C, wmOperator *op) /* restore the edit mode if necessary */ if (ob_edit_mode) { - ED_object_mode_toggle(C, OB_MODE_EDIT); + ED_object_mode_set(C, OB_MODE_EDIT); } /* report failure or do updates? */ diff --git a/source/blender/editors/curve/editfont_undo.c b/source/blender/editors/curve/editfont_undo.c index af591e0c7c5..ef9bb7e0c88 100644 --- a/source/blender/editors/curve/editfont_undo.c +++ b/source/blender/editors/curve/editfont_undo.c @@ -359,7 +359,7 @@ static void font_undosys_step_decode( struct bContext *C, struct Main *bmain, UndoStep *us_p, int UNUSED(dir), bool UNUSED(is_final)) { /* TODO(campbell): undo_system: use low-level API to set mode. */ - ED_object_mode_set(C, OB_MODE_EDIT); + ED_object_mode_set_ex(C, OB_MODE_EDIT, false, NULL); BLI_assert(font_undosys_poll(C)); FontUndoStep *us = (FontUndoStep *)us_p; diff --git a/source/blender/editors/gizmo_library/gizmo_types/snap3d_gizmo.c b/source/blender/editors/gizmo_library/gizmo_types/snap3d_gizmo.c index 1fdf1160d09..a3921791427 100644 --- a/source/blender/editors/gizmo_library/gizmo_types/snap3d_gizmo.c +++ b/source/blender/editors/gizmo_library/gizmo_types/snap3d_gizmo.c @@ -67,7 +67,6 @@ typedef struct SnapGizmo3D { /* We could have other snap contexts, for now only support 3D view. */ SnapObjectContext *snap_context_v3d; int mval[2]; - short snap_elem; #ifdef USE_SNAP_DETECT_FROM_KEYMAP_HACK wmKeyMap *keymap; @@ -75,6 +74,7 @@ typedef struct SnapGizmo3D { bool invert_snap; #endif int use_snap_override; + short snap_elem; } SnapGizmo3D; #ifdef USE_SNAP_DETECT_FROM_KEYMAP_HACK @@ -82,11 +82,8 @@ static bool invert_snap(const wmGizmo *gz, const wmWindowManager *wm, const wmEv { SnapGizmo3D *gizmo_snap = (SnapGizmo3D *)gz; wmKeyMap *keymap = WM_keymap_active(wm, gizmo_snap->keymap); - if (!keymap) { - return false; - } - int snap_on = gizmo_snap->snap_on; + const int snap_on = gizmo_snap->snap_on; for (wmKeyMapItem *kmi = keymap->items.first; kmi; kmi = kmi->next) { if (kmi->flag & KMI_INACTIVE) { continue; @@ -408,14 +405,21 @@ static void gizmo_snap_draw(const bContext *C, wmGizmo *gz) static int gizmo_snap_test_select(bContext *C, wmGizmo *gz, const int mval[2]) { SnapGizmo3D *gizmo_snap = (SnapGizmo3D *)gz; + #ifdef USE_SNAP_DETECT_FROM_KEYMAP_HACK wmWindowManager *wm = CTX_wm_manager(C); - const bool invert = invert_snap(gz, wm, wm->winactive->eventstate); + if (gizmo_snap->keymap == NULL) { + gizmo_snap->keymap = WM_modalkeymap_find(wm->defaultconf, "Generic Gizmo Tweak Modal Map"); + RNA_enum_value_from_id(gizmo_snap->keymap->modal_items, "SNAP_ON", &gizmo_snap->snap_on); + } + + const bool invert = wm->winactive ? invert_snap(gz, wm, wm->winactive->eventstate) : false; if (gizmo_snap->invert_snap == invert && gizmo_snap->mval[0] == mval[0] && gizmo_snap->mval[1] == mval[1]) { /* Performance, do not update. */ return gizmo_snap->snap_elem ? 0 : -1; } + gizmo_snap->invert_snap = invert; #else if (gizmo_snap->mval[0] == mval[0] && gizmo_snap->mval[1] == mval[1]) { @@ -425,14 +429,6 @@ static int gizmo_snap_test_select(bContext *C, wmGizmo *gz, const int mval[2]) #endif copy_v2_v2_int(gizmo_snap->mval, mval); -#ifdef USE_SNAP_DETECT_FROM_KEYMAP_HACK - if (gizmo_snap->keymap == NULL) { - gizmo_snap->keymap = WM_modalkeymap_find(wm->defaultconf, "Generic Gizmo Tweak Modal Map"); - gizmo_snap->snap_on = -1; - RNA_enum_value_from_id(gizmo_snap->keymap->modal_items, "SNAP_ON", &gizmo_snap->snap_on); - } -#endif - ARegion *region = CTX_wm_region(C); View3D *v3d = CTX_wm_view3d(C); const float mval_fl[2] = {UNPACK2(mval)}; diff --git a/source/blender/editors/gpencil/annotate_paint.c b/source/blender/editors/gpencil/annotate_paint.c index c53b90fbfee..723c7d214e3 100644 --- a/source/blender/editors/gpencil/annotate_paint.c +++ b/source/blender/editors/gpencil/annotate_paint.c @@ -1729,17 +1729,16 @@ static void gpencil_draw_eraser(bContext *UNUSED(C), int x, int y, void *p_ptr) } /* Turn brush cursor in 3D view on/off */ -static void gpencil_draw_toggle_eraser_cursor(bContext *C, tGPsdata *p, short enable) +static void gpencil_draw_toggle_eraser_cursor(tGPsdata *p, short enable) { if (p->erasercursor && !enable) { /* clear cursor */ - WM_paint_cursor_end(CTX_wm_manager(C), p->erasercursor); + WM_paint_cursor_end(p->erasercursor); p->erasercursor = NULL; } else if (enable && !p->erasercursor) { /* enable cursor */ - p->erasercursor = WM_paint_cursor_activate(CTX_wm_manager(C), - SPACE_TYPE_ANY, + p->erasercursor = WM_paint_cursor_activate(SPACE_TYPE_ANY, RGN_TYPE_ANY, NULL, /* XXX */ gpencil_draw_eraser, @@ -1794,17 +1793,17 @@ static void gpencil_draw_stabilizer(bContext *C, int x, int y, void *p_ptr) } /* Turn *stabilizer* brush cursor in 3D view on/off */ -static void gpencil_draw_toggle_stabilizer_cursor(bContext *C, tGPsdata *p, short enable) +static void gpencil_draw_toggle_stabilizer_cursor(tGPsdata *p, short enable) { if (p->stabilizer_cursor && !enable) { /* clear cursor */ - WM_paint_cursor_end(CTX_wm_manager(C), p->stabilizer_cursor); + WM_paint_cursor_end(p->stabilizer_cursor); p->stabilizer_cursor = NULL; } else if (enable && !p->stabilizer_cursor) { /* enable cursor */ p->stabilizer_cursor = WM_paint_cursor_activate( - CTX_wm_manager(C), SPACE_TYPE_ANY, RGN_TYPE_ANY, NULL, gpencil_draw_stabilizer, p); + SPACE_TYPE_ANY, RGN_TYPE_ANY, NULL, gpencil_draw_stabilizer, p); } } @@ -1828,10 +1827,10 @@ static void gpencil_draw_exit(bContext *C, wmOperator *op) /* check size of buffer before cleanup, to determine if anything happened here */ if (p->paintmode == GP_PAINTMODE_ERASER) { /* turn off radial brush cursor */ - gpencil_draw_toggle_eraser_cursor(C, p, false); + gpencil_draw_toggle_eraser_cursor(p, false); } else if (p->paintmode == GP_PAINTMODE_DRAW) { - gpencil_draw_toggle_stabilizer_cursor(C, p, false); + gpencil_draw_toggle_stabilizer_cursor(p, false); } /* always store the new eraser size to be used again next time @@ -2039,7 +2038,7 @@ static void gpencil_draw_apply(wmOperator *op, tGPsdata *p, Depsgraph *depsgraph /* handle draw event */ static void annotation_draw_apply_event( - bContext *C, wmOperator *op, const wmEvent *event, Depsgraph *depsgraph, float x, float y) + wmOperator *op, const wmEvent *event, Depsgraph *depsgraph, float x, float y) { tGPsdata *p = op->customdata; PointerRNA itemptr; @@ -2056,14 +2055,14 @@ static void annotation_draw_apply_event( /* Using permanent stabilization, shift will deactivate the flag. */ if (p->flags & (GP_PAINTFLAG_USE_STABILIZER)) { if (p->flags & GP_PAINTFLAG_USE_STABILIZER_TEMP) { - gpencil_draw_toggle_stabilizer_cursor(C, p, false); + gpencil_draw_toggle_stabilizer_cursor(p, false); p->flags &= ~GP_PAINTFLAG_USE_STABILIZER_TEMP; } } /* Not using any stabilization flag. Activate temporal one. */ else if ((p->flags & GP_PAINTFLAG_USE_STABILIZER_TEMP) == 0) { p->flags |= GP_PAINTFLAG_USE_STABILIZER_TEMP; - gpencil_draw_toggle_stabilizer_cursor(C, p, true); + gpencil_draw_toggle_stabilizer_cursor(p, true); } } /* verify key status for straight lines */ @@ -2092,7 +2091,7 @@ static void annotation_draw_apply_event( so activate the temp flag back again. */ if (p->flags & GP_PAINTFLAG_USE_STABILIZER) { if ((p->flags & GP_PAINTFLAG_USE_STABILIZER_TEMP) == 0) { - gpencil_draw_toggle_stabilizer_cursor(C, p, true); + gpencil_draw_toggle_stabilizer_cursor(p, true); p->flags |= GP_PAINTFLAG_USE_STABILIZER_TEMP; } } @@ -2102,7 +2101,7 @@ static void annotation_draw_apply_event( else if (p->flags & GP_PAINTFLAG_USE_STABILIZER_TEMP) { /* Reset temporal stabilizer flag and remove cursor. */ p->flags &= ~GP_PAINTFLAG_USE_STABILIZER_TEMP; - gpencil_draw_toggle_stabilizer_cursor(C, p, false); + gpencil_draw_toggle_stabilizer_cursor(p, false); } } @@ -2296,7 +2295,7 @@ static int gpencil_draw_invoke(bContext *C, wmOperator *op, const wmEvent *event /* if eraser is on, draw radial aid */ if (p->paintmode == GP_PAINTMODE_ERASER) { - gpencil_draw_toggle_eraser_cursor(C, p, true); + gpencil_draw_toggle_eraser_cursor(p, true); } else if (p->paintmode == GP_PAINTMODE_DRAW_STRAIGHT) { if (RNA_enum_get(op->ptr, "arrowstyle_start") != GP_STROKE_ARROWSTYLE_NONE) { @@ -2313,11 +2312,11 @@ static int gpencil_draw_invoke(bContext *C, wmOperator *op, const wmEvent *event p->stabilizer_radius = RNA_int_get(op->ptr, "stabilizer_radius"); if (RNA_boolean_get(op->ptr, "use_stabilizer")) { p->flags |= GP_PAINTFLAG_USE_STABILIZER | GP_PAINTFLAG_USE_STABILIZER_TEMP; - gpencil_draw_toggle_stabilizer_cursor(C, p, true); + gpencil_draw_toggle_stabilizer_cursor(p, true); } else if (event->shift > 0) { p->flags |= GP_PAINTFLAG_USE_STABILIZER_TEMP; - gpencil_draw_toggle_stabilizer_cursor(C, p, true); + gpencil_draw_toggle_stabilizer_cursor(p, true); } } /* set cursor @@ -2333,7 +2332,7 @@ static int gpencil_draw_invoke(bContext *C, wmOperator *op, const wmEvent *event p->status = GP_STATUS_PAINTING; /* handle the initial drawing - i.e. for just doing a simple dot */ - annotation_draw_apply_event(C, op, event, CTX_data_ensure_evaluated_depsgraph(C), 0.0f, 0.0f); + annotation_draw_apply_event(op, event, CTX_data_ensure_evaluated_depsgraph(C), 0.0f, 0.0f); op->flag |= OP_IS_MODAL_CURSOR_REGION; } else { @@ -2425,7 +2424,7 @@ static void annotation_add_missing_events(bContext *C, interp_v2_v2v2(pt, a, b, 0.5f); sub_v2_v2v2(pt, b, pt); /* create fake event */ - annotation_draw_apply_event(C, op, event, depsgraph, pt[0], pt[1]); + annotation_draw_apply_event(op, event, depsgraph, pt[0], pt[1]); } else if (dist >= factor) { int slices = 2 + (int)((dist - 1.0) / factor); @@ -2434,7 +2433,7 @@ static void annotation_add_missing_events(bContext *C, interp_v2_v2v2(pt, a, b, n * i); sub_v2_v2v2(pt, b, pt); /* create fake event */ - annotation_draw_apply_event(C, op, event, depsgraph, pt[0], pt[1]); + annotation_draw_apply_event(op, event, depsgraph, pt[0], pt[1]); } } } @@ -2562,7 +2561,7 @@ static int gpencil_draw_modal(bContext *C, wmOperator *op, const wmEvent *event) * Just hiding this makes it seem like * you can paint again... */ - gpencil_draw_toggle_eraser_cursor(C, p, false); + gpencil_draw_toggle_eraser_cursor(p, false); } } @@ -2647,7 +2646,7 @@ static int gpencil_draw_modal(bContext *C, wmOperator *op, const wmEvent *event) p->paintmode = RNA_enum_get(op->ptr, "mode"); } - gpencil_draw_toggle_eraser_cursor(C, p, p->paintmode == GP_PAINTMODE_ERASER); + gpencil_draw_toggle_eraser_cursor(p, p->paintmode == GP_PAINTMODE_ERASER); /* not painting, so start stroke (this should be mouse-button down) */ p = gpencil_stroke_begin(C, op); @@ -2681,8 +2680,7 @@ static int gpencil_draw_modal(bContext *C, wmOperator *op, const wmEvent *event) } /* TODO(sergey): Possibly evaluating dependency graph from modal operator? */ - annotation_draw_apply_event( - C, op, event, CTX_data_ensure_evaluated_depsgraph(C), 0.0f, 0.0f); + annotation_draw_apply_event(op, event, CTX_data_ensure_evaluated_depsgraph(C), 0.0f, 0.0f); /* finish painting operation if anything went wrong just now */ if (p->status == GP_STATUS_ERROR) { diff --git a/source/blender/editors/gpencil/gpencil_edit.c b/source/blender/editors/gpencil/gpencil_edit.c index 4330a07057e..8771fcb0c8d 100644 --- a/source/blender/editors/gpencil/gpencil_edit.c +++ b/source/blender/editors/gpencil/gpencil_edit.c @@ -370,7 +370,7 @@ static int gpencil_paintmode_toggle_exec(bContext *C, wmOperator *op) if (mode == OB_MODE_PAINT_GPENCIL) { /* Be sure we have brushes and Paint settings. - * Need Draw and Vertex (used fro Tint). */ + * Need Draw and Vertex (used for Tint). */ BKE_paint_ensure(ts, (Paint **)&ts->gp_paint); BKE_paint_ensure(ts, (Paint **)&ts->gp_vertexpaint); @@ -485,11 +485,13 @@ static int gpencil_sculptmode_toggle_exec(bContext *C, wmOperator *op) } if (mode == OB_MODE_SCULPT_GPENCIL) { - /* be sure we have brushes */ + /* Be sure we have brushes. */ BKE_paint_ensure(ts, (Paint **)&ts->gp_sculptpaint); - BKE_paint_toolslots_brush_validate(bmain, &ts->gp_sculptpaint->paint); - BKE_brush_gpencil_sculpt_presets(bmain, ts, false); + const bool reset_mode = (ts->gp_sculptpaint->paint.brush == NULL); + BKE_brush_gpencil_sculpt_presets(bmain, ts, reset_mode); + + BKE_paint_toolslots_brush_validate(bmain, &ts->gp_sculptpaint->paint); } /* setup other modes */ @@ -592,11 +594,13 @@ static int gpencil_weightmode_toggle_exec(bContext *C, wmOperator *op) } if (mode == OB_MODE_WEIGHT_GPENCIL) { - /* be sure we have brushes */ + /* Be sure we have brushes. */ BKE_paint_ensure(ts, (Paint **)&ts->gp_weightpaint); - BKE_paint_toolslots_brush_validate(bmain, &ts->gp_weightpaint->paint); - BKE_brush_gpencil_weight_presets(bmain, ts, false); + const bool reset_mode = (ts->gp_weightpaint->paint.brush == NULL); + BKE_brush_gpencil_weight_presets(bmain, ts, reset_mode); + + BKE_paint_toolslots_brush_validate(bmain, &ts->gp_weightpaint->paint); } /* setup other modes */ @@ -696,11 +700,13 @@ static int gpencil_vertexmode_toggle_exec(bContext *C, wmOperator *op) } if (mode == OB_MODE_VERTEX_GPENCIL) { - /* be sure we have brushes */ + /* Be sure we have brushes. */ BKE_paint_ensure(ts, (Paint **)&ts->gp_vertexpaint); - BKE_paint_toolslots_brush_validate(bmain, &ts->gp_vertexpaint->paint); - BKE_brush_gpencil_vertex_presets(bmain, ts, false); + const bool reset_mode = (ts->gp_vertexpaint->paint.brush == NULL); + BKE_brush_gpencil_vertex_presets(bmain, ts, reset_mode); + + BKE_paint_toolslots_brush_validate(bmain, &ts->gp_vertexpaint->paint); /* Ensure Palette by default. */ BKE_gpencil_palette_ensure(bmain, CTX_data_scene(C)); diff --git a/source/blender/editors/gpencil/gpencil_paint.c b/source/blender/editors/gpencil/gpencil_paint.c index 4e83c4fb11c..06079c34d12 100644 --- a/source/blender/editors/gpencil/gpencil_paint.c +++ b/source/blender/editors/gpencil/gpencil_paint.c @@ -2299,18 +2299,17 @@ static void gpencil_draw_eraser(bContext *UNUSED(C), int x, int y, void *p_ptr) } /* Turn brush cursor in 3D view on/off */ -static void gpencil_draw_toggle_eraser_cursor(bContext *C, tGPsdata *p, short enable) +static void gpencil_draw_toggle_eraser_cursor(tGPsdata *p, short enable) { if (p->erasercursor && !enable) { /* clear cursor */ - WM_paint_cursor_end(CTX_wm_manager(C), p->erasercursor); + WM_paint_cursor_end(p->erasercursor); p->erasercursor = NULL; } else if (enable && !p->erasercursor) { ED_gpencil_toggle_brush_cursor(p->C, false, NULL); /* enable cursor */ - p->erasercursor = WM_paint_cursor_activate(CTX_wm_manager(C), - SPACE_TYPE_ANY, + p->erasercursor = WM_paint_cursor_activate(SPACE_TYPE_ANY, RGN_TYPE_ANY, NULL, /* XXX */ gpencil_draw_eraser, @@ -2335,7 +2334,7 @@ static void gpencil_draw_exit(bContext *C, wmOperator *op) /* check size of buffer before cleanup, to determine if anything happened here */ if (p->paintmode == GP_PAINTMODE_ERASER) { /* turn off radial brush cursor */ - gpencil_draw_toggle_eraser_cursor(C, p, false); + gpencil_draw_toggle_eraser_cursor(p, false); } /* always store the new eraser size to be used again next time @@ -3154,7 +3153,7 @@ static int gpencil_draw_invoke(bContext *C, wmOperator *op, const wmEvent *event /* TODO: set any additional settings that we can take from the events? * if eraser is on, draw radial aid */ if (p->paintmode == GP_PAINTMODE_ERASER) { - gpencil_draw_toggle_eraser_cursor(C, p, true); + gpencil_draw_toggle_eraser_cursor(p, true); } else { ED_gpencil_toggle_brush_cursor(C, true, NULL); @@ -3700,7 +3699,7 @@ static int gpencil_draw_modal(bContext *C, wmOperator *op, const wmEvent *event) p->paintmode = RNA_enum_get(op->ptr, "mode"); } - gpencil_draw_toggle_eraser_cursor(C, p, p->paintmode == GP_PAINTMODE_ERASER); + gpencil_draw_toggle_eraser_cursor(p, p->paintmode == GP_PAINTMODE_ERASER); /* not painting, so start stroke (this should be mouse-button down) */ p = gpencil_stroke_begin(C, op); diff --git a/source/blender/editors/gpencil/gpencil_select.c b/source/blender/editors/gpencil/gpencil_select.c index 69d22b52ded..7accf48832a 100644 --- a/source/blender/editors/gpencil/gpencil_select.c +++ b/source/blender/editors/gpencil/gpencil_select.c @@ -43,6 +43,7 @@ #include "BKE_context.h" #include "BKE_gpencil.h" +#include "BKE_material.h" #include "BKE_report.h" #include "UI_interface.h" @@ -67,6 +68,45 @@ /** \name Shared Utilities * \{ */ +/* Check if mouse inside stroke. */ +static bool gpencil_point_inside_stroke(bGPDstroke *gps, + GP_SpaceConversion *gsc, + int mouse[2], + const float diff_mat[4][4]) +{ + bool hit = false; + if (gps->totpoints == 0) { + return hit; + } + + int(*mcoords)[2] = NULL; + int len = gps->totpoints; + mcoords = MEM_mallocN(sizeof(int) * 2 * len, __func__); + + /* Convert stroke to 2D array of points. */ + bGPDspoint *pt; + int i; + for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) { + bGPDspoint pt2; + gp_point_to_parent_space(pt, diff_mat, &pt2); + gp_point_to_xy(gsc, gps, &pt2, &mcoords[i][0], &mcoords[i][1]); + } + + /* Compute boundbox of lasso (for faster testing later). */ + rcti rect; + BLI_lasso_boundbox(&rect, mcoords, len); + + /* Test if point inside stroke. */ + hit = ((!ELEM(V2D_IS_CLIPPED, mouse[0], mouse[1])) && + BLI_rcti_isect_pt(&rect, mouse[0], mouse[1]) && + BLI_lasso_is_point_inside(mcoords, len, mouse[0], mouse[1], INT_MAX)); + + /* Free memory. */ + MEM_SAFE_FREE(mcoords); + + return hit; +} + /* Convert sculpt mask mode to Select mode */ static int gpencil_select_mode_from_sculpt(eGP_Sculpt_SelectMaskFlag mode) { @@ -1118,10 +1158,8 @@ typedef bool (*GPencilTestFn)(bGPDstroke *gps, const float diff_mat[4][4], void *user_data); -static int gpencil_generic_select_exec(bContext *C, - wmOperator *op, - GPencilTestFn is_inside_fn, - void *user_data) +static int gpencil_generic_select_exec( + bContext *C, wmOperator *op, GPencilTestFn is_inside_fn, rcti box, void *user_data) { Object *ob = CTX_data_active_object(C); bGPdata *gpd = ED_gpencil_data_get_active(C); @@ -1143,7 +1181,6 @@ static int gpencil_generic_select_exec(bContext *C, ((gpd->flag & GP_DATA_STROKE_PAINTMODE) == 0)); const bool segmentmode = ((selectmode == GP_SELECTMODE_SEGMENT) && ((gpd->flag & GP_DATA_STROKE_PAINTMODE) == 0)); - const bool is_multiedit = (bool)GPENCIL_MULTIEDIT_SESSIONS_ON(gpd); const eSelectOp sel_op = RNA_enum_get(op->ptr, "mode"); const float scale = ts->gp_sculpt.isect_threshold; @@ -1180,15 +1217,13 @@ static int gpencil_generic_select_exec(bContext *C, /* select/deselect points */ GP_EVALUATED_STROKES_BEGIN (gpstroke_iter, C, gpl, gps) { bGPDstroke *gps_active = (gps->runtime.gps_orig) ? gps->runtime.gps_orig : gps; + bool whole = false; bGPDspoint *pt; int i; bool hit = false; for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) { - if (pt->runtime.pt_orig == NULL) { - continue; - } - bGPDspoint *pt_active = pt->runtime.pt_orig; + bGPDspoint *pt_active = (pt->runtime.pt_orig) ? pt->runtime.pt_orig : pt; /* convert point coords to screenspace */ const bool is_inside = is_inside_fn(gps, pt, &gsc, gpstroke_iter.diff_mat, user_data); @@ -1198,9 +1233,10 @@ static int gpencil_generic_select_exec(bContext *C, if (sel_op_result != -1) { SET_FLAG_FROM_TEST(pt_active->flag, sel_op_result, GP_SPOINT_SELECT); changed = true; + hit = true; - /* expand selection to segment */ - if ((sel_op_result != -1) && (segmentmode)) { + /* Expand selection to segment. */ + if (segmentmode) { bool hit_select = (bool)(pt_active->flag & GP_SPOINT_SELECT); float r_hita[3], r_hitb[3]; ED_gpencil_select_stroke_segment( @@ -1216,16 +1252,28 @@ static int gpencil_generic_select_exec(bContext *C, } } - /* if stroke mode expand selection */ - if (strokemode) { - const bool is_select = BKE_gpencil_stroke_select_check(gps_active); - const bool is_inside = hit; + /* If nothing hit, check if the mouse is inside a filled stroke using the center or + * Box or lasso area. */ + if (!hit) { + /* Only check filled strokes. */ + MaterialGPencilStyle *gp_style = BKE_gpencil_material_settings(ob, gps->mat_nr + 1); + if ((gp_style->flag & GP_MATERIAL_FILL_SHOW) == 0) { + continue; + } + int mval[2]; + mval[0] = (box.xmax + box.xmin) / 2; + mval[1] = (box.ymax + box.ymin) / 2; + + whole = gpencil_point_inside_stroke(gps_active, &gsc, mval, gpstroke_iter.diff_mat); + } + + /* if stroke mode expand selection. */ + if ((strokemode) || (whole)) { + const bool is_select = BKE_gpencil_stroke_select_check(gps_active) || whole; + const bool is_inside = hit || whole; const int sel_op_result = ED_select_op_action_deselected(sel_op, is_select, is_inside); if (sel_op_result != -1) { for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) { - if ((!is_multiedit) && (pt->runtime.pt_orig == NULL)) { - continue; - } bGPDspoint *pt_active = (pt->runtime.pt_orig) ? pt->runtime.pt_orig : pt; if (sel_op_result) { @@ -1261,7 +1309,6 @@ static int gpencil_generic_select_exec(bContext *C, WM_event_add_notifier(C, NC_GPENCIL | NA_SELECTED, NULL); WM_event_add_notifier(C, NC_GEOM | ND_SELECT, NULL); } - return OPERATOR_FINISHED; } @@ -1293,7 +1340,8 @@ static int gpencil_box_select_exec(bContext *C, wmOperator *op) { struct GP_SelectBoxUserData data = {0}; WM_operator_properties_border_to_rcti(op, &data.rect); - return gpencil_generic_select_exec(C, op, gpencil_test_box, &data); + rcti rect = data.rect; + return gpencil_generic_select_exec(C, op, gpencil_test_box, rect, &data); } void GPENCIL_OT_select_box(wmOperatorType *ot) @@ -1360,7 +1408,8 @@ static int gpencil_lasso_select_exec(bContext *C, wmOperator *op) /* Compute boundbox of lasso (for faster testing later). */ BLI_lasso_boundbox(&data.rect, data.mcoords, data.mcoords_len); - int ret = gpencil_generic_select_exec(C, op, gpencil_test_lasso, &data); + rcti rect = data.rect; + int ret = gpencil_generic_select_exec(C, op, gpencil_test_lasso, rect, &data); MEM_freeN((void *)data.mcoords); @@ -1424,7 +1473,7 @@ static int gpencil_select_exec(bContext *C, wmOperator *op) const bool is_multiedit = (bool)GPENCIL_MULTIEDIT_SESSIONS_ON(gpd); /* "radius" is simply a threshold (screen space) to make it easier to test with a tolerance */ - const float radius = 0.50f * U.widget_unit; + const float radius = 0.4f * U.widget_unit; const int radius_squared = (int)(radius * radius); const bool use_shift_extend = RNA_boolean_get(op->ptr, "use_shift_extend"); @@ -1469,12 +1518,19 @@ static int gpencil_select_exec(bContext *C, wmOperator *op) RNA_int_get_array(op->ptr, "location", mval); /* First Pass: Find stroke point which gets hit */ - /* XXX: maybe we should go from the top of the stack down instead... */ GP_EVALUATED_STROKES_BEGIN (gpstroke_iter, C, gpl, gps) { bGPDstroke *gps_active = (gps->runtime.gps_orig) ? gps->runtime.gps_orig : gps; bGPDspoint *pt; int i; + /* Check boundbox to speedup. */ + float fmval[2]; + copy_v2fl_v2i(fmval, mval); + if (!ED_gpencil_stroke_check_collision( + &gsc, gps_active, fmval, radius, gpstroke_iter.diff_mat)) { + continue; + } + /* firstly, check for hit-point */ for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) { int xy[2]; @@ -1502,11 +1558,27 @@ static int gpencil_select_exec(bContext *C, wmOperator *op) } } } + if (ELEM(NULL, hit_stroke, hit_point)) { + /* If nothing hit, check if the mouse is inside any filled stroke. + * Only check filling materials. */ + MaterialGPencilStyle *gp_style = BKE_gpencil_material_settings(ob, gps->mat_nr + 1); + if ((gp_style->flag & GP_MATERIAL_FILL_SHOW) == 0) { + continue; + } + bool hit_fill = gpencil_point_inside_stroke(gps, &gsc, mval, gpstroke_iter.diff_mat); + if (hit_fill) { + hit_stroke = gps_active; + hit_point = &gps_active->points[0]; + /* Extend selection to all stroke. */ + whole = true; + } + } } GP_EVALUATED_STROKES_END(gpstroke_iter); /* Abort if nothing hit... */ if (ELEM(NULL, hit_stroke, hit_point)) { + if (deselect_all) { /* since left mouse select change, deselect all if click outside any hit */ deselect_all_selected(C); diff --git a/source/blender/editors/gpencil/gpencil_utils.c b/source/blender/editors/gpencil/gpencil_utils.c index 3cab26eab44..1962eba5017 100644 --- a/source/blender/editors/gpencil/gpencil_utils.c +++ b/source/blender/editors/gpencil/gpencil_utils.c @@ -1871,19 +1871,18 @@ void ED_gpencil_toggle_brush_cursor(bContext *C, bool enable, void *customdata) if (gset->paintcursor && !enable) { /* clear cursor */ - WM_paint_cursor_end(CTX_wm_manager(C), gset->paintcursor); + WM_paint_cursor_end(gset->paintcursor); gset->paintcursor = NULL; } else if (enable) { /* in some situations cursor could be duplicated, so it is better disable first if exist */ if (gset->paintcursor) { /* clear cursor */ - WM_paint_cursor_end(CTX_wm_manager(C), gset->paintcursor); + WM_paint_cursor_end(gset->paintcursor); gset->paintcursor = NULL; } /* enable cursor */ - gset->paintcursor = WM_paint_cursor_activate(CTX_wm_manager(C), - SPACE_TYPE_ANY, + gset->paintcursor = WM_paint_cursor_activate(SPACE_TYPE_ANY, RGN_TYPE_ANY, gp_brush_cursor_poll, gp_brush_cursor_draw, diff --git a/source/blender/editors/include/ED_anim_api.h b/source/blender/editors/include/ED_anim_api.h index 7d38792f332..426a470b128 100644 --- a/source/blender/editors/include/ED_anim_api.h +++ b/source/blender/editors/include/ED_anim_api.h @@ -652,9 +652,6 @@ enum eAnimEditDraw_CurrentFrame { /* main call to draw current-frame indicator in an Animation Editor */ void ANIM_draw_cfra(const struct bContext *C, struct View2D *v2d, short flag); -/* main call to draw "number box" in scrollbar for current frame indicator */ -void ANIM_draw_cfra_number(const struct bContext *C, struct View2D *v2d, short flag); - /* ------------- Preview Range Drawing -------------- */ /* main call to draw preview range curtains */ diff --git a/source/blender/editors/include/ED_object.h b/source/blender/editors/include/ED_object.h index 5adc99a8ae0..a2a8fbab6b3 100644 --- a/source/blender/editors/include/ED_object.h +++ b/source/blender/editors/include/ED_object.h @@ -212,13 +212,11 @@ bool ED_object_editmode_load(struct Main *bmain, struct Object *obedit); void ED_object_vpaintmode_enter_ex(struct Main *bmain, struct Depsgraph *depsgraph, - struct wmWindowManager *wm, struct Scene *scene, struct Object *ob); void ED_object_vpaintmode_enter(struct bContext *C, struct Depsgraph *depsgraph); void ED_object_wpaintmode_enter_ex(struct Main *bmain, struct Depsgraph *depsgraph, - struct wmWindowManager *wm, struct Scene *scene, struct Object *ob); void ED_object_wpaintmode_enter(struct bContext *C, struct Depsgraph *depsgraph); @@ -329,11 +327,12 @@ bool ED_object_mode_compat_set(struct bContext *C, struct Object *ob, eObjectMode mode, struct ReportList *reports); -void ED_object_mode_toggle(struct bContext *C, eObjectMode mode); -void ED_object_mode_set(struct bContext *C, eObjectMode mode); -void ED_object_mode_exit(struct bContext *C, struct Depsgraph *depsgraph); +bool ED_object_mode_set_ex(struct bContext *C, + eObjectMode mode, + bool use_undo, + struct ReportList *reports); +bool ED_object_mode_set(struct bContext *C, eObjectMode mode); -bool ED_object_mode_generic_enter(struct bContext *C, eObjectMode object_mode); void ED_object_mode_generic_exit(struct Main *bmain, struct Depsgraph *depsgraph, struct Scene *scene, diff --git a/source/blender/editors/include/ED_transform.h b/source/blender/editors/include/ED_transform.h index 9969acd04b7..a62deb9d69f 100644 --- a/source/blender/editors/include/ED_transform.h +++ b/source/blender/editors/include/ED_transform.h @@ -162,6 +162,19 @@ int BIF_countTransformOrientation(const struct bContext *C); void Transform_Properties(struct wmOperatorType *ot, int flags); +/* *** transform_orientations.c *** */ +void ED_transform_calc_orientation_from_type(const struct bContext *C, float r_mat[3][3]); +short ED_transform_calc_orientation_from_type_ex(const struct bContext *C, + float r_mat[3][3], + /* extra args */ + struct Scene *scene, + struct RegionView3D *rv3d, + struct Object *ob, + struct Object *obedit, + const short orientation_type, + int orientation_index_custom, + const int pivot_point); + /* transform gizmos */ void VIEW3D_GGT_xform_gizmo(struct wmGizmoGroupType *gzgt); @@ -180,18 +193,6 @@ void ED_widgetgroup_gizmo2d_rotate_callbacks_set(struct wmGizmoGroupType *gzgt); #define SNAP_INCREMENTAL_ANGLE DEG2RAD(5.0) -void ED_transform_calc_orientation_from_type(const struct bContext *C, float r_mat[3][3]); -void ED_transform_calc_orientation_from_type_ex(const struct bContext *C, - float r_mat[3][3], - /* extra args */ - struct Scene *scene, - struct RegionView3D *rv3d, - struct Object *ob, - struct Object *obedit, - const short orientation_type, - int orientation_index_custom, - const int pivot_point); - struct TransformBounds { float center[3]; /* Center for transform widget. */ float min[3], max[3]; /* Boundbox of selection for transform widget. */ diff --git a/source/blender/editors/include/UI_interface.h b/source/blender/editors/include/UI_interface.h index c95f517b155..01bc59f71e7 100644 --- a/source/blender/editors/include/UI_interface.h +++ b/source/blender/editors/include/UI_interface.h @@ -1938,7 +1938,7 @@ uiLayout *uiLayoutRadial(uiLayout *layout); /* templates */ void uiTemplateHeader(uiLayout *layout, struct bContext *C); void uiTemplateID(uiLayout *layout, - struct bContext *C, + const struct bContext *C, struct PointerRNA *ptr, const char *propname, const char *newop, @@ -2111,7 +2111,7 @@ void uiTemplateComponentMenu(uiLayout *layout, const char *name); void uiTemplateNodeSocket(uiLayout *layout, struct bContext *C, float *color); void uiTemplateCacheFile(uiLayout *layout, - struct bContext *C, + const struct bContext *C, struct PointerRNA *ptr, const char *propname); @@ -2144,7 +2144,7 @@ void uiTemplateNodeView(uiLayout *layout, struct bNodeSocket *input); void uiTemplateTextureUser(uiLayout *layout, struct bContext *C); void uiTemplateTextureShow(uiLayout *layout, - struct bContext *C, + const struct bContext *C, struct PointerRNA *ptr, struct PropertyRNA *prop); diff --git a/source/blender/editors/interface/interface_eyedropper_color.c b/source/blender/editors/interface/interface_eyedropper_color.c index ace367fd513..c917ffb3f3e 100644 --- a/source/blender/editors/interface/interface_eyedropper_color.c +++ b/source/blender/editors/interface/interface_eyedropper_color.c @@ -138,11 +138,26 @@ void eyedropper_color_sample_fl(bContext *C, int mx, int my, float r_col[3]) { /* we could use some clever */ Main *bmain = CTX_data_main(C); - bScreen *screen = CTX_wm_screen(C); - ScrArea *area = BKE_screen_find_area_xy(screen, SPACE_TYPE_ANY, mx, my); + wmWindowManager *wm = CTX_wm_manager(C); const char *display_device = CTX_data_scene(C)->display_settings.display_device; struct ColorManagedDisplay *display = IMB_colormanagement_display_get_named(display_device); + wmWindow *win = CTX_wm_window(C); + bScreen *screen = CTX_wm_screen(C); + ScrArea *area = BKE_screen_find_area_xy(screen, SPACE_TYPE_ANY, mx, my); + if (area == NULL) { + int mval[2] = {mx, my}; + if (WM_window_find_under_cursor(wm, NULL, win, mval, &win, mval)) { + mx = mval[0]; + my = mval[1]; + screen = WM_window_get_active_screen(win); + area = BKE_screen_find_area_xy(screen, SPACE_TYPE_ANY, mx, my); + } + else { + win = NULL; + } + } + if (area) { if (area->spacetype == SPACE_IMAGE) { ARegion *region = BKE_area_find_region_xy(area, RGN_TYPE_WINDOW, mx, my); @@ -179,12 +194,15 @@ void eyedropper_color_sample_fl(bContext *C, int mx, int my, float r_col[3]) } } - /* fallback to simple opengl picker */ - glReadBuffer(GL_FRONT); - glReadPixels(mx, my, 1, 1, GL_RGB, GL_FLOAT, r_col); - glReadBuffer(GL_BACK); - - IMB_colormanagement_display_to_scene_linear_v3(r_col, display); + if (win) { + /* Fallback to simple opengl picker. */ + int mval[2] = {mx, my}; + WM_window_pixel_sample_read(wm, win, mval, r_col); + IMB_colormanagement_display_to_scene_linear_v3(r_col, display); + } + else { + zero_v3(r_col); + } } /* sets the sample color RGB, maintaining A */ diff --git a/source/blender/editors/interface/interface_icons.c b/source/blender/editors/interface/interface_icons.c index c94a95890c0..deea3028354 100644 --- a/source/blender/editors/interface/interface_icons.c +++ b/source/blender/editors/interface/interface_icons.c @@ -1603,8 +1603,8 @@ static void icon_draw_cache_texture_flush_ex(GLuint texture, GPUShader *shader = GPU_shader_get_builtin_shader(GPU_SHADER_2D_IMAGE_MULTI_RECT_COLOR); GPU_shader_bind(shader); - int img_loc = GPU_shader_get_uniform_ensure(shader, "image"); - int data_loc = GPU_shader_get_uniform_ensure(shader, "calls_data[0]"); + int img_loc = GPU_shader_get_uniform(shader, "image"); + int data_loc = GPU_shader_get_uniform(shader, "calls_data"); glUniform1i(img_loc, 0); glUniform4fv(data_loc, ICON_DRAW_CACHE_SIZE * 3, (float *)texture_draw_calls->drawcall_cache); @@ -1750,9 +1750,9 @@ static void icon_draw_texture(float x, GPU_shader_get_builtin_uniform(shader, GPU_UNIFORM_COLOR), alpha, alpha, alpha, alpha); } - glUniform1i(GPU_shader_get_uniform_ensure(shader, "image"), 0); - glUniform4f(GPU_shader_get_uniform_ensure(shader, "rect_icon"), x1, y1, x2, y2); - glUniform4f(GPU_shader_get_uniform_ensure(shader, "rect_geom"), x, y, x + w, y + h); + glUniform1i(GPU_shader_get_uniform(shader, "image"), 0); + glUniform4f(GPU_shader_get_uniform(shader, "rect_icon"), x1, y1, x2, y2); + glUniform4f(GPU_shader_get_uniform(shader, "rect_geom"), x, y, x + w, y + h); GPU_draw_primitive(GPU_PRIM_TRI_STRIP, 4); diff --git a/source/blender/editors/interface/interface_templates.c b/source/blender/editors/interface/interface_templates.c index 9b59e4419c4..6bf2c721c20 100644 --- a/source/blender/editors/interface/interface_templates.c +++ b/source/blender/editors/interface/interface_templates.c @@ -799,7 +799,7 @@ static uiBut *template_id_def_new_but(uiBlock *block, return but; } -static void template_ID(bContext *C, +static void template_ID(const bContext *C, uiLayout *layout, TemplateID *template_ui, StructRNA *type, @@ -1140,7 +1140,7 @@ ID *UI_context_active_but_get_tab_ID(bContext *C) } } -static void template_ID_tabs(bContext *C, +static void template_ID_tabs(const bContext *C, uiLayout *layout, TemplateID *template, StructRNA *type, @@ -1214,7 +1214,7 @@ static void template_ID_tabs(bContext *C, } static void ui_template_id(uiLayout *layout, - bContext *C, + const bContext *C, PointerRNA *ptr, const char *propname, const char *newop, @@ -1298,7 +1298,7 @@ static void ui_template_id(uiLayout *layout, } void uiTemplateID(uiLayout *layout, - bContext *C, + const bContext *C, PointerRNA *ptr, const char *propname, const char *newop, @@ -7523,7 +7523,10 @@ void uiTemplateNodeSocket(uiLayout *layout, bContext *UNUSED(C), float *color) /** \name Cache File Template * \{ */ -void uiTemplateCacheFile(uiLayout *layout, bContext *C, PointerRNA *ptr, const char *propname) +void uiTemplateCacheFile(uiLayout *layout, + const bContext *C, + PointerRNA *ptr, + const char *propname) { if (!ptr->data) { return; diff --git a/source/blender/editors/io/io_alembic.c b/source/blender/editors/io/io_alembic.c index 551f7989d53..dc8ad858a9f 100644 --- a/source/blender/editors/io/io_alembic.c +++ b/source/blender/editors/io/io_alembic.c @@ -663,7 +663,7 @@ static int wm_alembic_import_exec(bContext *C, wmOperator *op) /* Switch out of edit mode to avoid being stuck in it (T54326). */ Object *obedit = CTX_data_edit_object(C); if (obedit) { - ED_object_mode_toggle(C, OB_MODE_EDIT); + ED_object_mode_set(C, OB_MODE_OBJECT); } bool ok = ABC_import(C, diff --git a/source/blender/editors/mask/mask_draw.c b/source/blender/editors/mask/mask_draw.c index bea44ee89f8..3786ed2789c 100644 --- a/source/blender/editors/mask/mask_draw.c +++ b/source/blender/editors/mask/mask_draw.c @@ -752,7 +752,7 @@ void ED_mask_draw_region( } IMMDrawPixelsTexState state = immDrawPixelsTexSetup(GPU_SHADER_2D_IMAGE_SHUFFLE_COLOR); GPU_shader_uniform_vector( - state.shader, GPU_shader_get_uniform_ensure(state.shader, "shuffle"), 4, 1, red); + state.shader, GPU_shader_get_uniform(state.shader, "shuffle"), 4, 1, red); immDrawPixelsTex( &state, 0.0f, 0.0f, width, height, GL_RED, GL_FLOAT, GL_NEAREST, buffer, 1.0f, 1.0f, NULL); diff --git a/source/blender/editors/mesh/editmesh_knife.c b/source/blender/editors/mesh/editmesh_knife.c index f94cd778e13..5f5599b53df 100644 --- a/source/blender/editors/mesh/editmesh_knife.c +++ b/source/blender/editors/mesh/editmesh_knife.c @@ -2998,6 +2998,7 @@ static int knifetool_modal(bContext *C, wmOperator *op, const wmEvent *event) case MOUSEROTATE: case WHEELUPMOUSE: case WHEELDOWNMOUSE: + case NDOF_MOTION: return OPERATOR_PASS_THROUGH; case MOUSEMOVE: /* mouse moved somewhere to select another loop */ if (kcd->mode != MODE_PANNING) { diff --git a/source/blender/editors/mesh/editmesh_loopcut.c b/source/blender/editors/mesh/editmesh_loopcut.c index 3861676c2cf..0f52911c603 100644 --- a/source/blender/editors/mesh/editmesh_loopcut.c +++ b/source/blender/editors/mesh/editmesh_loopcut.c @@ -515,6 +515,10 @@ static int loopcut_finish(RingSelOpData *lcd, bContext *C, wmOperator *op) static int loopcut_modal(bContext *C, wmOperator *op, const wmEvent *event) { + if (event->type == NDOF_MOTION) { + return OPERATOR_PASS_THROUGH; + } + RingSelOpData *lcd = op->customdata; float cuts = lcd->cuts; float smoothness = lcd->smoothness; @@ -606,7 +610,8 @@ static int loopcut_modal(bContext *C, wmOperator *op, const wmEvent *event) } handled = true; break; - case MOUSEMOVE: /* mouse moved somewhere to select another loop */ + case MOUSEMOVE: { + /* mouse moved somewhere to select another loop */ /* This is normally disabled for all modal operators. * This is an exception since mouse movement doesn't relate to numeric input. @@ -615,14 +620,16 @@ static int loopcut_modal(bContext *C, wmOperator *op, const wmEvent *event) #if 0 if (!has_numinput) #endif - { - lcd->vc.mval[0] = event->mval[0]; - lcd->vc.mval[1] = event->mval[1]; - loopcut_mouse_move(lcd, (int)lcd->cuts); + { + lcd->vc.mval[0] = event->mval[0]; + lcd->vc.mval[1] = event->mval[1]; + loopcut_mouse_move(lcd, (int)lcd->cuts); - ED_region_tag_redraw(lcd->region); - handled = true; - } break; + ED_region_tag_redraw(lcd->region); + handled = true; + } + break; + } } /* Modal numinput inactive, try to handle numeric inputs last... */ diff --git a/source/blender/editors/object/object_edit.c b/source/blender/editors/object/object_edit.c index 53a557c5871..d522dcabae3 100644 --- a/source/blender/editors/object/object_edit.c +++ b/source/blender/editors/object/object_edit.c @@ -1475,10 +1475,9 @@ static bool object_mode_set_poll(bContext *C) static int object_mode_set_exec(bContext *C, wmOperator *op) { - bool use_submode = STREQ(op->idname, "OBJECT_OT_mode_set_with_submode"); + const bool use_submode = STREQ(op->idname, "OBJECT_OT_mode_set_with_submode"); Object *ob = CTX_data_active_object(C); eObjectMode mode = RNA_enum_get(op->ptr, "mode"); - eObjectMode restore_mode = ob->mode; const bool toggle = RNA_boolean_get(op->ptr, "toggle"); /* by default the operator assume is a mesh, but if gp object change mode */ @@ -1490,43 +1489,63 @@ static int object_mode_set_exec(bContext *C, wmOperator *op) return OPERATOR_PASS_THROUGH; } + /** + * Mode Switching Logic (internal details). + * + * Notes: + * - Code below avoids calling mode switching functions more than once, + * as this causes unnecessary calculations and undo steps to be added. + * - The previous mode (#Object.restore_mode) is object mode by default. + * + * Supported Cases: + * - Setting the mode (when the 'toggle' setting is off). + * - Toggle the mode: + * - Toggle between object mode and non-object mode property. + * - Toggle between the previous mode (#Object.restore_mode) and the mode property. + * - Toggle object mode. + * While this is similar to regular toggle, + * this operator depends on there being a previous mode set + * (this isn't bound to a key with the default key-map). + */ if (toggle == false) { if (ob->mode != mode) { - if (mode != OB_MODE_OBJECT) { - /* Enter new mode. */ - ED_object_mode_toggle(C, mode); - } - else { - ED_object_mode_compat_set(C, ob, mode, op->reports); - } + ED_object_mode_set_ex(C, mode, true, op->reports); } } else { - /* Exit current mode if it's not the mode we're setting */ - if (mode != OB_MODE_OBJECT) { - /* Enter new mode. */ - ED_object_mode_toggle(C, mode); - } - - /* Special case for Object mode! */ - if ((mode == OB_MODE_OBJECT) && (restore_mode == OB_MODE_OBJECT) && - (ob->restore_mode != OB_MODE_OBJECT)) { - ED_object_mode_toggle(C, ob->restore_mode); - } - else if (ob->mode == mode) { - /* For toggling, store old mode so we know what to go back to */ - ob->restore_mode = restore_mode; - } - else if ((ob->restore_mode != OB_MODE_OBJECT) && (ob->restore_mode != mode)) { - ED_object_mode_toggle(C, ob->restore_mode); + const eObjectMode mode_prev = ob->mode; + /* When toggling object mode, we always use the restore mode, + * otherwise there is nothing to do. */ + if (mode == OB_MODE_OBJECT) { + if (ob->mode != OB_MODE_OBJECT) { + if (ED_object_mode_set_ex(C, OB_MODE_OBJECT, true, op->reports)) { + /* Store old mode so we know what to go back to. */ + ob->restore_mode = mode_prev; + } + } + else { + if (ob->restore_mode != OB_MODE_OBJECT) { + ED_object_mode_set_ex(C, ob->restore_mode, true, op->reports); + } + } } - } - - /* if type is OB_GPENCIL, set cursor mode */ - if (ob->type == OB_GPENCIL) { - if (ob->data) { - bGPdata *gpd = (bGPdata *)ob->data; - ED_gpencil_setup_modes(C, gpd, ob->mode); + else { + /* Non-object modes, enter the 'mode' unless it's already set, + * in that case use restore mode. */ + if (ob->mode != mode) { + if (ED_object_mode_set_ex(C, mode, true, op->reports)) { + /* Store old mode so we know what to go back to. */ + ob->restore_mode = mode_prev; + } + } + else { + if (ob->restore_mode != OB_MODE_OBJECT) { + ED_object_mode_set_ex(C, ob->restore_mode, true, op->reports); + } + else { + ED_object_mode_set_ex(C, OB_MODE_OBJECT, true, op->reports); + } + } } } diff --git a/source/blender/editors/object/object_modes.c b/source/blender/editors/object/object_modes.c index f06b6a4db2a..fbd935c2e55 100644 --- a/source/blender/editors/object/object_modes.c +++ b/source/blender/editors/object/object_modes.c @@ -167,41 +167,6 @@ bool ED_object_mode_compat_set(bContext *C, Object *ob, eObjectMode mode, Report return ok; } -void ED_object_mode_toggle(bContext *C, eObjectMode mode) -{ - if (mode != OB_MODE_OBJECT) { - const char *opstring = object_mode_op_string(mode); - - if (opstring) { - wmOperatorType *ot = WM_operatortype_find(opstring, false); - WM_operator_name_call_ptr(C, ot, WM_OP_EXEC_REGION_WIN, NULL); - } - } -} - -/* Wrapper for operator */ -void ED_object_mode_set(bContext *C, eObjectMode mode) -{ - wmWindowManager *wm = CTX_wm_manager(C); - wm->op_undo_depth++; - /* needed so we don't do undo pushes. */ - ED_object_mode_generic_enter(C, mode); - wm->op_undo_depth--; -} - -void ED_object_mode_exit(bContext *C, Depsgraph *depsgraph) -{ - struct Main *bmain = CTX_data_main(C); - Scene *scene = CTX_data_scene(C); - ViewLayer *view_layer = CTX_data_view_layer(C); - FOREACH_OBJECT_BEGIN (view_layer, ob) { - if (ob->mode & OB_MODE_ALL_MODE_DATA) { - ED_object_mode_generic_exit(bmain, depsgraph, scene, ob); - } - } - FOREACH_OBJECT_END; -} - /** \} */ /* -------------------------------------------------------------------- */ @@ -212,23 +177,50 @@ void ED_object_mode_exit(bContext *C, Depsgraph *depsgraph) * * \{ */ -bool ED_object_mode_generic_enter(struct bContext *C, eObjectMode object_mode) +bool ED_object_mode_set_ex(bContext *C, eObjectMode mode, bool use_undo, ReportList *reports) { + wmWindowManager *wm = CTX_wm_manager(C); ViewLayer *view_layer = CTX_data_view_layer(C); Object *ob = OBACT(view_layer); if (ob == NULL) { - return (object_mode == OB_MODE_OBJECT); + return (mode == OB_MODE_OBJECT); + } + + if ((ob->type == OB_GPENCIL) && (mode == OB_MODE_EDIT)) { + mode = OB_MODE_EDIT_GPENCIL; } - if (ob->mode == object_mode) { + + if (ob->mode == mode) { return true; } - wmOperatorType *ot = WM_operatortype_find("OBJECT_OT_mode_set", false); - PointerRNA ptr; - WM_operator_properties_create_ptr(&ptr, ot); - RNA_enum_set(&ptr, "mode", object_mode); - WM_operator_name_call_ptr(C, ot, WM_OP_INVOKE_DEFAULT, &ptr); - WM_operator_properties_free(&ptr); - return (ob->mode == object_mode); + + if (!ED_object_mode_compat_test(ob, mode)) { + return false; + } + + const char *opstring = object_mode_op_string((mode == OB_MODE_OBJECT) ? ob->mode : mode); + wmOperatorType *ot = WM_operatortype_find(opstring, false); + + if (!use_undo) { + wm->op_undo_depth++; + } + WM_operator_name_call_ptr(C, ot, WM_OP_EXEC_REGION_WIN, NULL); + if (!use_undo) { + wm->op_undo_depth--; + } + + if (ob->mode != mode) { + BKE_reportf(reports, RPT_ERROR, "Unable to execute '%s', error changing modes", ot->name); + return false; + } + + return true; +} + +bool ED_object_mode_set(bContext *C, eObjectMode mode) +{ + /* Don't do undo push by default, since this may be called by lower level code. */ + return ED_object_mode_set_ex(C, mode, true, NULL); } /** diff --git a/source/blender/editors/object/object_relations.c b/source/blender/editors/object/object_relations.c index 11e9c396552..ca3a559ca1d 100644 --- a/source/blender/editors/object/object_relations.c +++ b/source/blender/editors/object/object_relations.c @@ -2516,7 +2516,8 @@ static int make_override_library_exec(bContext *C, wmOperator *op) ViewLayer *view_layer = CTX_data_view_layer(C); Collection *new_collection = (Collection *)collection->id.newid; - BKE_collection_child_add(bmain, scene->master_collection, new_collection); + BKE_collection_add_from_object(bmain, scene, obcollection, new_collection); + FOREACH_COLLECTION_OBJECT_RECURSIVE_BEGIN (new_collection, new_ob) { if (new_ob != NULL && new_ob->id.override_library != NULL) { if ((base = BKE_view_layer_base_find(view_layer, new_ob)) == NULL) { @@ -2524,14 +2525,7 @@ static int make_override_library_exec(bContext *C, wmOperator *op) base = BKE_view_layer_base_find(view_layer, new_ob); DEG_id_tag_update_ex(bmain, &new_ob->id, ID_RECALC_TRANSFORM | ID_RECALC_BASE_FLAGS); } - /* parent to 'collection' empty */ - /* Disabled for now, according to some artist this is probably not really useful anyway. - * And it breaks things like objects parented to bones - * (most likely due to missing proper setting of inverse parent matrix?)... */ - /* Note: we might even actually want to get rid of that instantiating empty... */ - if (0 && new_ob->parent == NULL) { - new_ob->parent = obcollection; - } + if (new_ob == (Object *)obact->id.newid) { /* TODO: is setting active needed? */ BKE_view_layer_base_select_and_set_active(view_layer, base); @@ -2546,9 +2540,9 @@ static int make_override_library_exec(bContext *C, wmOperator *op) } FOREACH_COLLECTION_OBJECT_RECURSIVE_END; - /* obcollection is no more duplicollection-ing, - * it merely parents whole collection of overriding instantiated objects. */ - obcollection->instance_collection = NULL; + /* Remove the instance empty from this scene, the items now have an overriden collection + * instead. */ + ED_object_base_free_and_unlink(bmain, scene, obcollection); /* Also, we'd likely want to lock by default things like * transformations of implicitly overridden objects? */ diff --git a/source/blender/editors/physics/particle_edit.c b/source/blender/editors/physics/particle_edit.c index 306adb36c52..3639cd64b7c 100644 --- a/source/blender/editors/physics/particle_edit.c +++ b/source/blender/editors/physics/particle_edit.c @@ -3235,12 +3235,12 @@ static void toggle_particle_cursor(bContext *C, int enable) ParticleEditSettings *pset = PE_settings(CTX_data_scene(C)); if (pset->paintcursor && !enable) { - WM_paint_cursor_end(CTX_wm_manager(C), pset->paintcursor); + WM_paint_cursor_end(pset->paintcursor); pset->paintcursor = NULL; } else if (enable) { pset->paintcursor = WM_paint_cursor_activate( - CTX_wm_manager(C), SPACE_VIEW3D, RGN_TYPE_WINDOW, PE_poll_view3d, brush_drawcursor, NULL); + SPACE_VIEW3D, RGN_TYPE_WINDOW, PE_poll_view3d, brush_drawcursor, NULL); } } diff --git a/source/blender/editors/physics/particle_edit_undo.c b/source/blender/editors/physics/particle_edit_undo.c index 5b363bdca78..205c04f54a9 100644 --- a/source/blender/editors/physics/particle_edit_undo.c +++ b/source/blender/editors/physics/particle_edit_undo.c @@ -253,7 +253,7 @@ static void particle_undosys_step_decode(struct bContext *C, { Depsgraph *depsgraph = CTX_data_depsgraph_pointer(C); /* TODO(campbell): undo_system: use low-level API to set mode. */ - ED_object_mode_set(C, OB_MODE_PARTICLE_EDIT); + ED_object_mode_set_ex(C, OB_MODE_PARTICLE_EDIT, false, NULL); BLI_assert(particle_undosys_poll(C)); ParticleUndoStep *us = (ParticleUndoStep *)us_p; diff --git a/source/blender/editors/screen/glutil.c b/source/blender/editors/screen/glutil.c index ddb345ab65e..a9380debbdc 100644 --- a/source/blender/editors/screen/glutil.c +++ b/source/blender/editors/screen/glutil.c @@ -83,7 +83,7 @@ static void immDrawPixelsTexSetupAttributes(IMMDrawPixelsTexState *state) /* To be used before calling immDrawPixelsTex * Default shader is GPU_SHADER_2D_IMAGE_COLOR * You can still set uniforms with : - * GPU_shader_uniform_int(shader, GPU_shader_get_uniform_ensure(shader, "name"), 0); + * GPU_shader_uniform_int(shader, GPU_shader_get_uniform(shader, "name"), 0); * */ IMMDrawPixelsTexState immDrawPixelsTexSetup(int builtin) { @@ -191,7 +191,7 @@ void immDrawPixelsTexScaled_clipping(IMMDrawPixelsTexState *state, /* NOTE: Shader could be null for GLSL OCIO drawing, it is fine, since * it does not need color. */ - if (state->shader != NULL && GPU_shader_get_uniform_ensure(state->shader, "color") != -1) { + if (state->shader != NULL && GPU_shader_get_uniform(state->shader, "color") != -1) { immUniformColor4fv((color) ? color : white); } diff --git a/source/blender/editors/screen/workspace_edit.c b/source/blender/editors/screen/workspace_edit.c index 3edc51b038b..478a0adfd9a 100644 --- a/source/blender/editors/screen/workspace_edit.c +++ b/source/blender/editors/screen/workspace_edit.c @@ -83,8 +83,7 @@ static void workspace_change_update(WorkSpace *workspace_new, eObjectMode mode_new = workspace_new->object_mode; if (mode_old != mode_new) { - ED_object_mode_compat_set(C, ob_act, mode_new, &wm->reports); - ED_object_mode_toggle(C, mode_new); + ED_object_mode_set(C, mode_new); } #endif } @@ -175,7 +174,7 @@ bool ED_workspace_change(WorkSpace *workspace_new, bContext *C, wmWindowManager /* Automatic mode switching. */ if (workspace_new->object_mode != workspace_old->object_mode) { - ED_object_mode_generic_enter(C, workspace_new->object_mode); + ED_object_mode_set(C, workspace_new->object_mode); } return true; diff --git a/source/blender/editors/sculpt_paint/paint_cursor.c b/source/blender/editors/sculpt_paint/paint_cursor.c index 191a064a95c..4222a466a7b 100644 --- a/source/blender/editors/sculpt_paint/paint_cursor.c +++ b/source/blender/editors/sculpt_paint/paint_cursor.c @@ -1674,23 +1674,13 @@ static void paint_draw_cursor(bContext *C, int x, int y, void *UNUSED(unused)) /* Public API */ -void paint_cursor_start(bContext *C, bool (*poll)(bContext *C)) +void paint_cursor_start(Paint *p, bool (*poll)(bContext *C)) { - Paint *p = BKE_paint_get_active_from_context(C); - if (p && !p->paint_cursor) { p->paint_cursor = WM_paint_cursor_activate( - CTX_wm_manager(C), SPACE_TYPE_ANY, RGN_TYPE_ANY, poll, paint_draw_cursor, NULL); + SPACE_TYPE_ANY, RGN_TYPE_ANY, poll, paint_draw_cursor, NULL); } /* Invalidate the paint cursors. */ BKE_paint_invalidate_overlay_all(); } - -void paint_cursor_start_explicit(Paint *p, wmWindowManager *wm, bool (*poll)(bContext *C)) -{ - if (p && !p->paint_cursor) { - p->paint_cursor = WM_paint_cursor_activate( - wm, SPACE_TYPE_ANY, RGN_TYPE_ANY, poll, paint_draw_cursor, NULL); - } -} diff --git a/source/blender/editors/sculpt_paint/paint_image.c b/source/blender/editors/sculpt_paint/paint_image.c index fd5018f76ff..6ad4d1e650a 100644 --- a/source/blender/editors/sculpt_paint/paint_image.c +++ b/source/blender/editors/sculpt_paint/paint_image.c @@ -511,12 +511,8 @@ static PaintOperation *texture_paint_init(bContext *C, wmOperator *op, const flo } if ((brush->imagepaint_tool == PAINT_TOOL_FILL) && (brush->flag & BRUSH_USE_GRADIENT)) { - pop->cursor = WM_paint_cursor_activate(CTX_wm_manager(C), - SPACE_TYPE_ANY, - RGN_TYPE_ANY, - image_paint_poll, - gradient_draw_line, - pop); + pop->cursor = WM_paint_cursor_activate( + SPACE_TYPE_ANY, RGN_TYPE_ANY, image_paint_poll, gradient_draw_line, pop); } settings->imapaint.flag |= IMAGEPAINT_DRAWING; @@ -655,7 +651,7 @@ static void paint_stroke_done(const bContext *C, struct PaintStroke *stroke) } if (pop->cursor) { - WM_paint_cursor_end(CTX_wm_manager(C), pop->cursor); + WM_paint_cursor_end(pop->cursor); } ED_image_undo_push_end(); @@ -787,17 +783,17 @@ bool get_imapaint_zoom(bContext *C, float *zoomx, float *zoomy) static void toggle_paint_cursor(bContext *C, int enable) { - wmWindowManager *wm = CTX_wm_manager(C); Scene *scene = CTX_data_scene(C); ToolSettings *settings = scene->toolsettings; + Paint *p = &settings->imapaint.paint; - if (settings->imapaint.paintcursor && !enable) { - WM_paint_cursor_end(wm, settings->imapaint.paintcursor); - settings->imapaint.paintcursor = NULL; + if (p->paint_cursor && !enable) { + WM_paint_cursor_end(p->paint_cursor); + p->paint_cursor = NULL; paint_cursor_delete_textures(); } else if (enable) { - paint_cursor_start(C, image_paint_poll); + paint_cursor_start(p, image_paint_poll); } } @@ -827,7 +823,7 @@ void ED_space_image_paint_update(Main *bmain, wmWindowManager *wm, Scene *scene) if (enabled) { BKE_paint_init(bmain, scene, PAINT_MODE_TEXTURE_2D, PAINT_CURSOR_TEXTURE_PAINT); - paint_cursor_start_explicit(&imapaint->paint, wm, image_paint_poll); + paint_cursor_start(&imapaint->paint, image_paint_poll); } else { paint_cursor_delete_textures(); diff --git a/source/blender/editors/sculpt_paint/paint_intern.h b/source/blender/editors/sculpt_paint/paint_intern.h index 018d7f72bb6..0d4e957c77b 100644 --- a/source/blender/editors/sculpt_paint/paint_intern.h +++ b/source/blender/editors/sculpt_paint/paint_intern.h @@ -90,10 +90,7 @@ void *paint_stroke_mode_data(struct PaintStroke *stroke); float paint_stroke_distance_get(struct PaintStroke *stroke); void paint_stroke_set_mode_data(struct PaintStroke *stroke, void *mode_data); bool paint_poll(struct bContext *C); -void paint_cursor_start(struct bContext *C, bool (*poll)(struct bContext *C)); -void paint_cursor_start_explicit(struct Paint *p, - struct wmWindowManager *wm, - bool (*poll)(struct bContext *C)); +void paint_cursor_start(struct Paint *p, bool (*poll)(struct bContext *C)); void paint_cursor_delete_textures(void); /* paint_vertex.c */ diff --git a/source/blender/editors/sculpt_paint/paint_stroke.c b/source/blender/editors/sculpt_paint/paint_stroke.c index 723ac58bc6e..2c6f708d82a 100644 --- a/source/blender/editors/sculpt_paint/paint_stroke.c +++ b/source/blender/editors/sculpt_paint/paint_stroke.c @@ -962,7 +962,7 @@ void paint_stroke_free(bContext *C, wmOperator *op) } if (stroke->stroke_cursor) { - WM_paint_cursor_end(CTX_wm_manager(C), stroke->stroke_cursor); + WM_paint_cursor_end(stroke->stroke_cursor); } BLI_freelistN(&stroke->line); @@ -1385,12 +1385,8 @@ int paint_stroke_modal(bContext *C, wmOperator *op, const wmEvent *event) } if (paint_supports_smooth_stroke(br, mode)) { - stroke->stroke_cursor = WM_paint_cursor_activate(CTX_wm_manager(C), - SPACE_TYPE_ANY, - RGN_TYPE_ANY, - paint_poll, - paint_draw_smooth_cursor, - stroke); + stroke->stroke_cursor = WM_paint_cursor_activate( + SPACE_TYPE_ANY, RGN_TYPE_ANY, paint_poll, paint_draw_smooth_cursor, stroke); } stroke->stroke_init = true; @@ -1416,12 +1412,8 @@ int paint_stroke_modal(bContext *C, wmOperator *op, const wmEvent *event) } if (br->flag & BRUSH_LINE) { - stroke->stroke_cursor = WM_paint_cursor_activate(CTX_wm_manager(C), - SPACE_TYPE_ANY, - RGN_TYPE_ANY, - paint_poll, - paint_draw_line_cursor, - stroke); + stroke->stroke_cursor = WM_paint_cursor_activate( + SPACE_TYPE_ANY, RGN_TYPE_ANY, paint_poll, paint_draw_line_cursor, stroke); } first_dab = true; diff --git a/source/blender/editors/sculpt_paint/paint_vertex.c b/source/blender/editors/sculpt_paint/paint_vertex.c index 6172b77de07..6de54b3ae6a 100644 --- a/source/blender/editors/sculpt_paint/paint_vertex.c +++ b/source/blender/editors/sculpt_paint/paint_vertex.c @@ -1193,12 +1193,8 @@ static void vertex_paint_init_session_data(const ToolSettings *ts, Object *ob) /** \name Enter Vertex/Weight Paint Mode * \{ */ -static void ed_vwpaintmode_enter_generic(Main *bmain, - Depsgraph *depsgraph, - wmWindowManager *wm, - Scene *scene, - Object *ob, - const eObjectMode mode_flag) +static void ed_vwpaintmode_enter_generic( + Main *bmain, Depsgraph *depsgraph, Scene *scene, Object *ob, const eObjectMode mode_flag) { ob->mode |= mode_flag; Mesh *me = BKE_mesh_from_object(ob); @@ -1214,7 +1210,7 @@ static void ed_vwpaintmode_enter_generic(Main *bmain, BKE_paint_ensure(scene->toolsettings, (Paint **)&scene->toolsettings->vpaint); Paint *paint = BKE_paint_get_active_from_paintmode(scene, paint_mode); - paint_cursor_start_explicit(paint, wm, vertex_paint_poll); + paint_cursor_start(paint, vertex_paint_poll); BKE_paint_init(bmain, scene, paint_mode, PAINT_CURSOR_VERTEX_PAINT); } else if (mode_flag == OB_MODE_WEIGHT_PAINT) { @@ -1222,7 +1218,7 @@ static void ed_vwpaintmode_enter_generic(Main *bmain, BKE_paint_ensure(scene->toolsettings, (Paint **)&scene->toolsettings->wpaint); Paint *paint = BKE_paint_get_active_from_paintmode(scene, paint_mode); - paint_cursor_start_explicit(paint, wm, weight_paint_poll); + paint_cursor_start(paint, weight_paint_poll); BKE_paint_init(bmain, scene, paint_mode, PAINT_CURSOR_WEIGHT_PAINT); /* weight paint specific */ @@ -1248,32 +1244,28 @@ static void ed_vwpaintmode_enter_generic(Main *bmain, DEG_id_tag_update(&ob->id, ID_RECALC_COPY_ON_WRITE); } -void ED_object_vpaintmode_enter_ex( - Main *bmain, Depsgraph *depsgraph, wmWindowManager *wm, Scene *scene, Object *ob) +void ED_object_vpaintmode_enter_ex(Main *bmain, Depsgraph *depsgraph, Scene *scene, Object *ob) { - ed_vwpaintmode_enter_generic(bmain, depsgraph, wm, scene, ob, OB_MODE_VERTEX_PAINT); + ed_vwpaintmode_enter_generic(bmain, depsgraph, scene, ob, OB_MODE_VERTEX_PAINT); } void ED_object_vpaintmode_enter(struct bContext *C, Depsgraph *depsgraph) { Main *bmain = CTX_data_main(C); - wmWindowManager *wm = CTX_wm_manager(C); Scene *scene = CTX_data_scene(C); Object *ob = CTX_data_active_object(C); - ED_object_vpaintmode_enter_ex(bmain, depsgraph, wm, scene, ob); + ED_object_vpaintmode_enter_ex(bmain, depsgraph, scene, ob); } -void ED_object_wpaintmode_enter_ex( - Main *bmain, Depsgraph *depsgraph, wmWindowManager *wm, Scene *scene, Object *ob) +void ED_object_wpaintmode_enter_ex(Main *bmain, Depsgraph *depsgraph, Scene *scene, Object *ob) { - ed_vwpaintmode_enter_generic(bmain, depsgraph, wm, scene, ob, OB_MODE_WEIGHT_PAINT); + ed_vwpaintmode_enter_generic(bmain, depsgraph, scene, ob, OB_MODE_WEIGHT_PAINT); } void ED_object_wpaintmode_enter(struct bContext *C, Depsgraph *depsgraph) { Main *bmain = CTX_data_main(C); - wmWindowManager *wm = CTX_wm_manager(C); Scene *scene = CTX_data_scene(C); Object *ob = CTX_data_active_object(C); - ED_object_wpaintmode_enter_ex(bmain, depsgraph, wm, scene, ob); + ED_object_wpaintmode_enter_ex(bmain, depsgraph, scene, ob); } /** \} */ @@ -1384,8 +1376,7 @@ static int wpaint_mode_toggle_exec(bContext *C, wmOperator *op) if (depsgraph) { depsgraph = CTX_data_ensure_evaluated_depsgraph(C); } - wmWindowManager *wm = CTX_wm_manager(C); - ED_object_wpaintmode_enter_ex(bmain, depsgraph, wm, scene, ob); + ED_object_wpaintmode_enter_ex(bmain, depsgraph, scene, ob); BKE_paint_toolslots_brush_validate(bmain, &ts->wpaint->paint); } @@ -2651,8 +2642,7 @@ static int vpaint_mode_toggle_exec(bContext *C, wmOperator *op) if (depsgraph) { depsgraph = CTX_data_ensure_evaluated_depsgraph(C); } - wmWindowManager *wm = CTX_wm_manager(C); - ED_object_vpaintmode_enter_ex(bmain, depsgraph, wm, scene, ob); + ED_object_vpaintmode_enter_ex(bmain, depsgraph, scene, ob); BKE_paint_toolslots_brush_validate(bmain, &ts->vpaint->paint); } diff --git a/source/blender/editors/sculpt_paint/sculpt.c b/source/blender/editors/sculpt_paint/sculpt.c index 4ad6bcc5d0f..b742ce91dd9 100644 --- a/source/blender/editors/sculpt_paint/sculpt.c +++ b/source/blender/editors/sculpt_paint/sculpt.c @@ -261,8 +261,15 @@ bool SCULPT_vertex_visible_get(SculptSession *ss, int index) return !(ss->mvert[index].flag & ME_HIDE); case PBVH_BMESH: return !BM_elem_flag_test(BM_vert_at_index(ss->bm, index), BM_ELEM_HIDDEN); - case PBVH_GRIDS: - return true; + case PBVH_GRIDS: { + const CCGKey *key = BKE_pbvh_get_grid_key(ss->pbvh); + const int grid_index = index / key->grid_area; + const int vertex_index = index - grid_index * key->grid_area; + BLI_bitmap **grid_hidden = BKE_pbvh_get_grid_visibility(ss->pbvh); + if (grid_hidden && grid_hidden[grid_index]) { + return !BLI_BITMAP_TEST(grid_hidden[grid_index], vertex_index); + } + } } return true; } @@ -7628,7 +7635,7 @@ void ED_object_sculptmode_enter_ex(Main *bmain, Paint *paint = BKE_paint_get_active_from_paintmode(scene, PAINT_MODE_SCULPT); BKE_paint_init(bmain, scene, PAINT_MODE_SCULPT, PAINT_CURSOR_SCULPT); - paint_cursor_start_explicit(paint, bmain->wm.first, SCULPT_poll_view3d); + paint_cursor_start(paint, SCULPT_poll_view3d); /* Check dynamic-topology flag; re-enter dynamic-topology mode when changing modes, * As long as no data was added that is not supported. */ @@ -7898,4 +7905,5 @@ void ED_operatortypes_sculpt(void) WM_operatortype_append(SCULPT_OT_face_sets_change_visibility); WM_operatortype_append(SCULPT_OT_face_sets_randomize_colors); WM_operatortype_append(SCULPT_OT_face_sets_init); + WM_operatortype_append(SCULPT_OT_cloth_filter); } diff --git a/source/blender/editors/sculpt_paint/sculpt_automasking.c b/source/blender/editors/sculpt_paint/sculpt_automasking.c index f0f6478d3a6..bfa657147fd 100644 --- a/source/blender/editors/sculpt_paint/sculpt_automasking.c +++ b/source/blender/editors/sculpt_paint/sculpt_automasking.c @@ -91,7 +91,7 @@ bool SCULPT_is_automasking_enabled(const Sculpt *sd, const SculptSession *ss, co float SCULPT_automasking_factor_get(SculptSession *ss, int vert) { - if (ss->cache->automask) { + if (ss->cache && ss->cache->automask) { return ss->cache->automask[vert]; } else { diff --git a/source/blender/editors/sculpt_paint/sculpt_cloth.c b/source/blender/editors/sculpt_paint/sculpt_cloth.c index 6dac2b51645..3203282c30c 100644 --- a/source/blender/editors/sculpt_paint/sculpt_cloth.c +++ b/source/blender/editors/sculpt_paint/sculpt_cloth.c @@ -106,9 +106,11 @@ #define CLOTH_MAX_CONSTRAINTS_PER_VERTEX 1024 #define CLOTH_SIMULATION_TIME_STEP 0.01f -static void cloth_brush_add_length_constraint(SculptSession *ss, const int v1, const int v2) +static void cloth_brush_add_length_constraint(SculptSession *ss, + SculptClothSimulation *cloth_sim, + const int v1, + const int v2) { - SculptClothSimulation *cloth_sim = ss->cache->cloth_sim; cloth_sim->length_constraints[cloth_sim->tot_length_constraints].v1 = v1; cloth_sim->length_constraints[cloth_sim->tot_length_constraints].v2 = v2; cloth_sim->length_constraints[cloth_sim->tot_length_constraints].length = len_v3v3( @@ -133,12 +135,11 @@ static void do_cloth_brush_build_constraints_task_cb_ex( SculptSession *ss = data->ob->sculpt; PBVHVertexIter vd; - const float radius = ss->cache->initial_radius; - const float limit = radius + (radius * data->brush->cloth_sim_limit); BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) { - if (len_squared_v3v3(vd.co, ss->cache->initial_location) < limit * limit) { + if (len_squared_v3v3(vd.co, data->cloth_sim_initial_location) < + data->cloth_sim_radius * data->cloth_sim_radius) { SculptVertexNeighborIter ni; int build_indices[CLOTH_MAX_CONSTRAINTS_PER_VERTEX]; @@ -159,7 +160,8 @@ static void do_cloth_brush_build_constraints_task_cb_ex( for (int c_i = 0; c_i < tot_indices; c_i++) { for (int c_j = 0; c_j < tot_indices; c_j++) { if (c_i != c_j) { - cloth_brush_add_length_constraint(ss, build_indices[c_i], build_indices[c_j]); + cloth_brush_add_length_constraint( + ss, data->cloth_sim, build_indices[c_i], build_indices[c_j]); } } } @@ -192,11 +194,11 @@ static float cloth_brush_simulation_falloff_get(const Brush *brush, } } -static void cloth_brush_apply_force_to_vertex(SculptSession *ss, +static void cloth_brush_apply_force_to_vertex(SculptSession *UNUSED(ss), + SculptClothSimulation *cloth_sim, const float force[3], const int vertex_index) { - SculptClothSimulation *cloth_sim = ss->cache->cloth_sim; madd_v3_v3fl(cloth_sim->acceleration[vertex_index], force, 1.0f / cloth_sim->mass); } @@ -290,7 +292,6 @@ static void do_cloth_brush_apply_forces_task_cb_ex(void *__restrict userdata, float brush_disp[3]; float normal[3]; - if (vd.no) { normal_short_to_float_v3(normal, vd.no); } @@ -348,13 +349,15 @@ static void do_cloth_brush_apply_forces_task_cb_ex(void *__restrict userdata, madd_v3_v3fl(force, gravity, fade); - cloth_brush_apply_force_to_vertex(ss, force, vd.index); + cloth_brush_apply_force_to_vertex(ss, ss->cache->cloth_sim, force, vd.index); } } BKE_pbvh_vertex_iter_end; } -static SculptClothSimulation *cloth_brush_simulation_create(SculptSession *ss, Brush *brush) +static SculptClothSimulation *cloth_brush_simulation_create(SculptSession *ss, + const float cloth_mass, + const float cloth_damping) { const int totverts = SCULPT_vertex_count_get(ss); SculptClothSimulation *cloth_sim; @@ -373,8 +376,8 @@ static SculptClothSimulation *cloth_brush_simulation_create(SculptSession *ss, B cloth_sim->length_constraint_tweak = MEM_callocN(sizeof(float) * totverts, "cloth sim length tweak"); - cloth_sim->mass = brush->cloth_mass; - cloth_sim->damping = brush->cloth_damping; + cloth_sim->mass = cloth_mass; + cloth_sim->damping = cloth_damping; return cloth_sim; } @@ -386,12 +389,16 @@ static void do_cloth_brush_solve_simulation_task_cb_ex( SculptSession *ss = data->ob->sculpt; const Brush *brush = data->brush; PBVHVertexIter vd; - SculptClothSimulation *cloth_sim = ss->cache->cloth_sim; + SculptClothSimulation *cloth_sim = data->cloth_sim; const float time_step = data->cloth_time_step; BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) { - const float sim_factor = cloth_brush_simulation_falloff_get( - brush, ss->cache->radius, ss->cache->initial_location, cloth_sim->init_pos[vd.index]); + const float sim_factor = ss->cache ? cloth_brush_simulation_falloff_get( + brush, + ss->cache->radius, + ss->cache->initial_location, + cloth_sim->init_pos[vd.index]) : + 1.0f; if (sim_factor > 0.0f) { int i = vd.index; float temp[3]; @@ -412,7 +419,7 @@ static void do_cloth_brush_solve_simulation_task_cb_ex( copy_v3_fl(cloth_sim->acceleration[i], 0.0f); - copy_v3_v3(vd.co, ss->cache->cloth_sim->pos[vd.index]); + copy_v3_v3(vd.co, cloth_sim->pos[vd.index]); if (vd.mvert) { vd.mvert->flag |= ME_VERT_PBVH_UPDATE; } @@ -424,7 +431,10 @@ static void do_cloth_brush_solve_simulation_task_cb_ex( static void cloth_brush_build_nodes_constraints(Sculpt *sd, Object *ob, PBVHNode **nodes, - int totnode) + int totnode, + SculptClothSimulation *cloth_sim, + float initial_location[3], + const float radius) { Brush *brush = BKE_paint_brush(&sd->paint); @@ -440,6 +450,9 @@ static void cloth_brush_build_nodes_constraints(Sculpt *sd, .ob = ob, .brush = brush, .nodes = nodes, + .cloth_sim = cloth_sim, + .cloth_sim_initial_location = initial_location, + .cloth_sim_radius = radius, }; BLI_task_parallel_range( 0, totnode, &build_constraints_data, do_cloth_brush_build_constraints_task_cb_ex, &settings); @@ -480,10 +493,18 @@ static void cloth_brush_satisfy_constraints(SculptSession *ss, const float mask_v2 = (1.0f - SCULPT_vertex_mask_get(ss, v2)) * SCULPT_automasking_factor_get(ss, v2); - const float sim_factor_v1 = cloth_brush_simulation_falloff_get( - brush, ss->cache->radius, ss->cache->initial_location, cloth_sim->init_pos[v1]); - const float sim_factor_v2 = cloth_brush_simulation_falloff_get( - brush, ss->cache->radius, ss->cache->initial_location, cloth_sim->init_pos[v2]); + const float sim_factor_v1 = ss->cache ? cloth_brush_simulation_falloff_get( + brush, + ss->cache->radius, + ss->cache->initial_location, + cloth_sim->init_pos[v1]) : + 1.0f; + const float sim_factor_v2 = ss->cache ? cloth_brush_simulation_falloff_get( + brush, + ss->cache->radius, + ss->cache->initial_location, + cloth_sim->init_pos[v2]) : + 1.0f; madd_v3_v3fl(cloth_sim->pos[v1], correction_vector_half, 1.0f * mask_v1 * sim_factor_v1); madd_v3_v3fl(cloth_sim->pos[v2], correction_vector_half, -1.0f * mask_v2 * sim_factor_v2); @@ -491,13 +512,12 @@ static void cloth_brush_satisfy_constraints(SculptSession *ss, } } -static void cloth_brush_do_simulation_step(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode) +static void cloth_brush_do_simulation_step( + Sculpt *sd, Object *ob, SculptClothSimulation *cloth_sim, PBVHNode **nodes, int totnode) { SculptSession *ss = ob->sculpt; Brush *brush = BKE_paint_brush(&sd->paint); - SculptClothSimulation *cloth_sim = ss->cache->cloth_sim; - /* Update the constraints. */ cloth_brush_satisfy_constraints(ss, brush, cloth_sim); @@ -508,6 +528,7 @@ static void cloth_brush_do_simulation_step(Sculpt *sd, Object *ob, PBVHNode **no .brush = brush, .nodes = nodes, .cloth_time_step = CLOTH_SIMULATION_TIME_STEP, + .cloth_sim = cloth_sim, }; TaskParallelSettings settings; @@ -608,7 +629,8 @@ void SCULPT_do_cloth_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode /* The simulation structure only needs to be created on the first symmetry pass. */ if (ss->cache->mirror_symmetry_pass == 0) { - ss->cache->cloth_sim = cloth_brush_simulation_create(ss, brush); + ss->cache->cloth_sim = cloth_brush_simulation_create( + ss, brush->cloth_mass, brush->cloth_damping); for (int i = 0; i < totverts; i++) { copy_v3_v3(ss->cache->cloth_sim->prev_pos[i], SCULPT_vertex_co_get(ss, i)); copy_v3_v3(ss->cache->cloth_sim->init_pos[i], SCULPT_vertex_co_get(ss, i)); @@ -616,7 +638,10 @@ void SCULPT_do_cloth_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode } /* Build the constraints. */ - cloth_brush_build_nodes_constraints(sd, ob, nodes, totnode); + const float radius = ss->cache->initial_radius; + const float limit = radius + (radius * brush->cloth_sim_limit); + cloth_brush_build_nodes_constraints( + sd, ob, nodes, totnode, ss->cache->cloth_sim, ss->cache->location, limit); return; } @@ -630,7 +655,7 @@ void SCULPT_do_cloth_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode cloth_brush_apply_brush_foces(sd, ob, nodes, totnode); /* Update and write the simulation to the nodes. */ - cloth_brush_do_simulation_step(sd, ob, nodes, totnode); + cloth_brush_do_simulation_step(sd, ob, ss->cache->cloth_sim, nodes, totnode); return; } @@ -706,3 +731,246 @@ void SCULPT_cloth_plane_falloff_preview_draw(const uint gpuattr, immEnd(); } + +/* Cloth Filter. */ + +typedef enum eSculpClothFilterType { + CLOTH_FILTER_GRAVITY, + CLOTH_FILTER_INFLATE, + CLOTH_FILTER_EXPAND, + CLOTH_FILTER_PINCH, +} eSculptClothFilterType; + +static EnumPropertyItem prop_cloth_filter_type[] = { + {CLOTH_FILTER_GRAVITY, "GRAVITY", 0, "Gravity", "Applies gravity to the simulation"}, + {CLOTH_FILTER_INFLATE, "INFLATE", 0, "Inflate", "Inflates the cloth"}, + {CLOTH_FILTER_EXPAND, "EXPAND", 0, "Expand", "Expands the cloth's dimensions"}, + {CLOTH_FILTER_PINCH, + "PINCH", + 0, + "Pinch", + "Pinches the cloth to the point were the cursor was when the filter started"}, + {0, NULL, 0, NULL, NULL}, +}; + +static void cloth_filter_apply_forces_task_cb(void *__restrict userdata, + const int i, + const TaskParallelTLS *__restrict UNUSED(tls)) +{ + SculptThreadedTaskData *data = userdata; + Sculpt *sd = data->sd; + SculptSession *ss = data->ob->sculpt; + PBVHNode *node = data->nodes[i]; + + SculptClothSimulation *cloth_sim = ss->filter_cache->cloth_sim; + const int filter_type = data->filter_type; + + float sculpt_gravity[3] = {0.0f}; + if (sd->gravity_object) { + copy_v3_v3(sculpt_gravity, sd->gravity_object->obmat[2]); + } + else { + sculpt_gravity[2] = -1.0f; + } + mul_v3_fl(sculpt_gravity, sd->gravity_factor * data->filter_strength); + + PBVHVertexIter vd; + BKE_pbvh_vertex_iter_begin(ss->pbvh, node, vd, PBVH_ITER_UNIQUE) + { + float fade = vd.mask ? *vd.mask : 0.0f; + fade = 1.0f - fade; + float force[3] = {0.0f, 0.0f, 0.0f}; + + if (ss->filter_cache->active_face_set != SCULPT_FACE_SET_NONE) { + if (!SCULPT_vertex_has_face_set(ss, vd.index, ss->filter_cache->active_face_set)) { + continue; + } + } + + switch (filter_type) { + case CLOTH_FILTER_GRAVITY: + force[2] = -data->filter_strength * fade; + break; + case CLOTH_FILTER_INFLATE: { + float normal[3]; + SCULPT_vertex_normal_get(ss, vd.index, normal); + mul_v3_v3fl(force, normal, fade * data->filter_strength); + } break; + case CLOTH_FILTER_EXPAND: + cloth_sim->length_constraint_tweak[vd.index] += fade * data->filter_strength * 0.01f; + zero_v3(force); + break; + case CLOTH_FILTER_PINCH: + sub_v3_v3v3(force, ss->filter_cache->cloth_sim_pinch_point, vd.co); + normalize_v3(force); + mul_v3_fl(force, fade * data->filter_strength); + break; + } + + add_v3_v3(force, sculpt_gravity); + + cloth_brush_apply_force_to_vertex(ss, cloth_sim, force, vd.index); + } + BKE_pbvh_vertex_iter_end; + + BKE_pbvh_node_mark_update(node); +} + +static int sculpt_cloth_filter_modal(bContext *C, wmOperator *op, const wmEvent *event) +{ + Object *ob = CTX_data_active_object(C); + Depsgraph *depsgraph = CTX_data_depsgraph_pointer(C); + SculptSession *ss = ob->sculpt; + Sculpt *sd = CTX_data_tool_settings(C)->sculpt; + int filter_type = RNA_enum_get(op->ptr, "type"); + float filter_strength = RNA_float_get(op->ptr, "strength"); + + if (event->type == LEFTMOUSE && event->val == KM_RELEASE) { + SCULPT_filter_cache_free(ss); + SCULPT_undo_push_end(); + SCULPT_flush_update_done(C, ob, SCULPT_UPDATE_COORDS); + return OPERATOR_FINISHED; + } + + if (event->type != MOUSEMOVE) { + return OPERATOR_RUNNING_MODAL; + } + + float len = event->prevclickx - event->mval[0]; + filter_strength = filter_strength * -len * 0.001f * UI_DPI_FAC; + + SCULPT_vertex_random_access_init(ss); + + BKE_sculpt_update_object_for_edit(depsgraph, ob, true, true); + + const int totverts = SCULPT_vertex_count_get(ss); + for (int i = 0; i < totverts; i++) { + copy_v3_v3(ss->filter_cache->cloth_sim->pos[i], SCULPT_vertex_co_get(ss, i)); + } + + SculptThreadedTaskData data = { + .sd = sd, + .ob = ob, + .nodes = ss->filter_cache->nodes, + .filter_type = filter_type, + .filter_strength = filter_strength, + }; + + TaskParallelSettings settings; + BKE_pbvh_parallel_range_settings( + &settings, (sd->flags & SCULPT_USE_OPENMP), ss->filter_cache->totnode); + BLI_task_parallel_range( + 0, ss->filter_cache->totnode, &data, cloth_filter_apply_forces_task_cb, &settings); + + /* Update and write the simulation to the nodes. */ + cloth_brush_do_simulation_step( + sd, ob, ss->filter_cache->cloth_sim, ss->filter_cache->nodes, ss->filter_cache->totnode); + + if (ss->deform_modifiers_active || ss->shapekey_active) { + SCULPT_flush_stroke_deform(sd, ob, true); + } + SCULPT_flush_update_step(C, SCULPT_UPDATE_COORDS); + return OPERATOR_RUNNING_MODAL; +} + +static int sculpt_cloth_filter_invoke(bContext *C, wmOperator *op, const wmEvent *event) +{ + Object *ob = CTX_data_active_object(C); + Depsgraph *depsgraph = CTX_data_depsgraph_pointer(C); + Sculpt *sd = CTX_data_tool_settings(C)->sculpt; + SculptSession *ss = ob->sculpt; + + /* Update the active vertex */ + float mouse[2]; + SculptCursorGeometryInfo sgi; + mouse[0] = event->mval[0]; + mouse[1] = event->mval[1]; + SCULPT_cursor_geometry_info_update(C, &sgi, mouse, false); + + SCULPT_vertex_random_access_init(ss); + + /* Needs mask data to be available as it is used when solving the constraints. */ + BKE_sculpt_update_object_for_edit(depsgraph, ob, true, true); + + SCULPT_undo_push_begin("Cloth filter"); + SCULPT_filter_cache_init(ob, sd); + + const float cloth_mass = RNA_float_get(op->ptr, "cloth_mass"); + const float cloth_damping = RNA_float_get(op->ptr, "cloth_damping"); + ss->filter_cache->cloth_sim = cloth_brush_simulation_create(ss, cloth_mass, cloth_damping); + copy_v3_v3(ss->filter_cache->cloth_sim_pinch_point, SCULPT_active_vertex_co_get(ss)); + + const int totverts = SCULPT_vertex_count_get(ss); + for (int i = 0; i < totverts; i++) { + copy_v3_v3(ss->filter_cache->cloth_sim->prev_pos[i], SCULPT_vertex_co_get(ss, i)); + copy_v3_v3(ss->filter_cache->cloth_sim->init_pos[i], SCULPT_vertex_co_get(ss, i)); + } + + float origin[3] = {0.0f, 0.0f, 0.0f}; + cloth_brush_build_nodes_constraints(sd, + ob, + ss->filter_cache->nodes, + ss->filter_cache->totnode, + ss->filter_cache->cloth_sim, + origin, + FLT_MAX); + + const bool use_face_sets = RNA_boolean_get(op->ptr, "use_face_sets"); + if (use_face_sets) { + ss->filter_cache->active_face_set = SCULPT_active_face_set_get(ss); + } + else { + ss->filter_cache->active_face_set = SCULPT_FACE_SET_NONE; + } + + WM_event_add_modal_handler(C, op); + return OPERATOR_RUNNING_MODAL; +} + +void SCULPT_OT_cloth_filter(struct wmOperatorType *ot) +{ + /* Identifiers. */ + ot->name = "Filter cloth"; + ot->idname = "SCULPT_OT_cloth_filter"; + ot->description = "Applies a cloth simulation deformation to the entire mesh"; + + /* API callbacks. */ + ot->invoke = sculpt_cloth_filter_invoke; + ot->modal = sculpt_cloth_filter_modal; + ot->poll = SCULPT_mode_poll; + + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + + /* RNA. */ + RNA_def_enum(ot->srna, + "type", + prop_cloth_filter_type, + CLOTH_FILTER_GRAVITY, + "Filter type", + "Operation that is going to be applied to the mesh"); + RNA_def_float( + ot->srna, "strength", 1.0f, -10.0f, 10.0f, "Strength", "Filter Strength", -10.0f, 10.0f); + RNA_def_float(ot->srna, + "cloth_mass", + 1.0f, + 0.0f, + 2.0f, + "Cloth Mass", + "Mass of each simulation particle", + 0.0f, + 1.0f); + RNA_def_float(ot->srna, + "cloth_damping", + 0.0f, + 0.0f, + 1.0f, + "Cloth Damping", + "How much the applied forces are propagated through the cloth", + 0.0f, + 1.0f); + ot->prop = RNA_def_boolean(ot->srna, + "use_face_sets", + false, + "Use Face Sets", + "Apply the filter only to the Face Set under the cursor"); +} diff --git a/source/blender/editors/sculpt_paint/sculpt_filter_mesh.c b/source/blender/editors/sculpt_paint/sculpt_filter_mesh.c index 7c438e9245b..58c9e1a569e 100644 --- a/source/blender/editors/sculpt_paint/sculpt_filter_mesh.c +++ b/source/blender/editors/sculpt_paint/sculpt_filter_mesh.c @@ -121,6 +121,9 @@ void SCULPT_filter_cache_init(Object *ob, Sculpt *sd) void SCULPT_filter_cache_free(SculptSession *ss) { + if (ss->filter_cache->cloth_sim) { + SCULPT_cloth_simulation_free(ss->filter_cache->cloth_sim); + } MEM_SAFE_FREE(ss->filter_cache->nodes); MEM_SAFE_FREE(ss->filter_cache->mask_update_it); MEM_SAFE_FREE(ss->filter_cache->prev_mask); @@ -565,8 +568,7 @@ static int sculpt_mesh_filter_invoke(bContext *C, wmOperator *op, const wmEvent SCULPT_filter_cache_init(ob, sd); if (use_face_sets) { - ss->filter_cache->active_face_set = SCULPT_vertex_face_set_get(ss, - SCULPT_active_vertex_get(ss)); + ss->filter_cache->active_face_set = SCULPT_active_face_set_get(ss); } else { ss->filter_cache->active_face_set = SCULPT_FACE_SET_NONE; diff --git a/source/blender/editors/sculpt_paint/sculpt_intern.h b/source/blender/editors/sculpt_paint/sculpt_intern.h index 6c217f66940..d7b221ae947 100644 --- a/source/blender/editors/sculpt_paint/sculpt_intern.h +++ b/source/blender/editors/sculpt_paint/sculpt_intern.h @@ -592,6 +592,9 @@ typedef struct SculptThreadedTaskData { float transform_mats[8][4][4]; float cloth_time_step; + SculptClothSimulation *cloth_sim; + float *cloth_sim_initial_location; + float cloth_sim_radius; float dirty_mask_min; float dirty_mask_max; @@ -837,6 +840,10 @@ typedef struct FilterCache { PBVHNode **nodes; int totnode; + /* Cloth filter. */ + SculptClothSimulation *cloth_sim; + float cloth_sim_pinch_point[3]; + /* mask expand iteration caches */ int mask_update_current_it; int mask_update_last_it; @@ -891,6 +898,9 @@ void SCULPT_OT_set_pivot_position(struct wmOperatorType *ot); /* Mesh Filter. */ void SCULPT_OT_mesh_filter(struct wmOperatorType *ot); +/* Cloth Filter. */ +void SCULPT_OT_cloth_filter(struct wmOperatorType *ot); + /* Mask filter and Dirty Mask. */ void SCULPT_OT_mask_filter(struct wmOperatorType *ot); void SCULPT_OT_dirty_mask(struct wmOperatorType *ot); diff --git a/source/blender/editors/sculpt_paint/sculpt_pose.c b/source/blender/editors/sculpt_paint/sculpt_pose.c index 35f4870fa12..56ba15bef70 100644 --- a/source/blender/editors/sculpt_paint/sculpt_pose.c +++ b/source/blender/editors/sculpt_paint/sculpt_pose.c @@ -401,6 +401,14 @@ typedef struct PoseFloodFillData { * that have the current face set. */ float fallback_origin[3]; int fallback_count; + + /* Face Set FK mode. */ + int *floodfill_it; + float *fk_weights; + int initial_face_set; + int masked_face_set_it; + int masked_face_set; + int target_face_set; } PoseFloodFillData; static bool pose_topology_floodfill_cb( @@ -806,6 +814,119 @@ static SculptPoseIKChain *pose_ik_chain_init_face_sets( return ik_chain; } +static bool pose_face_sets_fk_find_masked_floodfill_cb( + SculptSession *ss, int from_v, int to_v, bool is_duplicate, void *userdata) +{ + PoseFloodFillData *data = userdata; + + if (!is_duplicate) { + data->floodfill_it[to_v] = data->floodfill_it[from_v] + 1; + } + else { + data->floodfill_it[to_v] = data->floodfill_it[from_v]; + } + + const int to_face_set = SCULPT_vertex_face_set_get(ss, to_v); + if (SCULPT_vertex_has_unique_face_set(ss, to_v) && + !SCULPT_vertex_has_unique_face_set(ss, from_v) && + SCULPT_vertex_has_face_set(ss, from_v, to_face_set)) { + + if (data->floodfill_it[to_v] > data->masked_face_set_it) { + data->masked_face_set = to_face_set; + data->masked_face_set_it = data->floodfill_it[to_v]; + } + + if (data->target_face_set == SCULPT_FACE_SET_NONE) { + data->target_face_set = to_face_set; + } + } + + return SCULPT_vertex_has_face_set(ss, to_v, data->initial_face_set); +} + +static bool pose_face_sets_fk_set_weights_floodfill_cb( + SculptSession *ss, int UNUSED(from_v), int to_v, bool UNUSED(is_duplicate), void *userdata) +{ + PoseFloodFillData *data = userdata; + data->fk_weights[to_v] = 1.0f; + return !SCULPT_vertex_has_face_set(ss, to_v, data->masked_face_set); +} + +static SculptPoseIKChain *pose_ik_chain_init_face_sets_fk( + Sculpt *sd, Object *ob, SculptSession *ss, const float radius, const float *initial_location) +{ + const int totvert = SCULPT_vertex_count_get(ss); + + SculptPoseIKChain *ik_chain = pose_ik_chain_new(1, totvert); + + const int active_vertex = SCULPT_active_vertex_get(ss); + const int active_face_set = SCULPT_active_face_set_get(ss); + + SculptFloodFill flood; + SCULPT_floodfill_init(ss, &flood); + SCULPT_floodfill_add_initial(&flood, active_vertex); + PoseFloodFillData fdata; + fdata.floodfill_it = MEM_calloc_arrayN(totvert, sizeof(int), "floodfill iteration"); + fdata.floodfill_it[active_vertex] = 1; + fdata.initial_face_set = active_face_set; + fdata.masked_face_set = SCULPT_FACE_SET_NONE; + fdata.target_face_set = SCULPT_FACE_SET_NONE; + fdata.masked_face_set_it = 0; + SCULPT_floodfill_execute(ss, &flood, pose_face_sets_fk_find_masked_floodfill_cb, &fdata); + SCULPT_floodfill_free(&flood); + + int origin_count = 0; + float origin_acc[3] = {0.0f}; + for (int i = 0; i < totvert; i++) { + if (fdata.floodfill_it[i] != 0 && SCULPT_vertex_has_face_set(ss, i, fdata.initial_face_set) && + SCULPT_vertex_has_face_set(ss, i, fdata.masked_face_set)) { + add_v3_v3(origin_acc, SCULPT_vertex_co_get(ss, i)); + origin_count++; + } + } + + int target_count = 0; + float target_acc[3] = {0.0f}; + if (fdata.target_face_set != fdata.masked_face_set) { + for (int i = 0; i < totvert; i++) { + if (fdata.floodfill_it[i] != 0 && + SCULPT_vertex_has_face_set(ss, i, fdata.initial_face_set) && + SCULPT_vertex_has_face_set(ss, i, fdata.target_face_set)) { + add_v3_v3(target_acc, SCULPT_vertex_co_get(ss, i)); + target_count++; + } + } + } + + MEM_freeN(fdata.floodfill_it); + + if (origin_count > 0) { + copy_v3_v3(ik_chain->segments[0].orig, origin_acc); + mul_v3_fl(ik_chain->segments[0].orig, 1.0f / origin_count); + } + else { + zero_v3(ik_chain->segments[0].orig); + } + + if (target_count > 0) { + copy_v3_v3(ik_chain->segments[0].head, target_acc); + mul_v3_fl(ik_chain->segments[0].head, 1.0f / target_count); + sub_v3_v3v3(ik_chain->grab_delta_offset, ik_chain->segments[0].head, initial_location); + } + else { + copy_v3_v3(ik_chain->segments[0].head, initial_location); + } + + SCULPT_floodfill_init(ss, &flood); + SCULPT_floodfill_add_active(sd, ob, ss, &flood, radius); + fdata.fk_weights = ik_chain->segments[0].weights; + SCULPT_floodfill_execute(ss, &flood, pose_face_sets_fk_set_weights_floodfill_cb, &fdata); + SCULPT_floodfill_free(&flood); + + pose_ik_chain_origin_heads_init(ik_chain, ik_chain->segments[0].head); + return ik_chain; +} + SculptPoseIKChain *SCULPT_pose_ik_chain_init(Sculpt *sd, Object *ob, SculptSession *ss, @@ -820,6 +941,9 @@ SculptPoseIKChain *SCULPT_pose_ik_chain_init(Sculpt *sd, case BRUSH_POSE_ORIGIN_FACE_SETS: return pose_ik_chain_init_face_sets(sd, ob, ss, br, radius); break; + case BRUSH_POSE_ORIGIN_FACE_SETS_FK: + return pose_ik_chain_init_face_sets_fk(sd, ob, ss, radius, initial_location); + break; } return NULL; } @@ -905,6 +1029,7 @@ static void sculpt_pose_do_rotate_deform(SculptSession *ss, Brush *brush) /* Calculate the IK target. */ copy_v3_v3(ik_target, ss->cache->true_location); add_v3_v3(ik_target, ss->cache->grab_delta); + add_v3_v3(ik_target, ik_chain->grab_delta_offset); /* Solve the IK positions. */ pose_solve_ik_chain(ik_chain, ik_target, brush->flag2 & BRUSH_POSE_IK_ANCHORED); @@ -935,7 +1060,6 @@ void SCULPT_do_pose_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode) { SculptSession *ss = ob->sculpt; Brush *brush = BKE_paint_brush(&sd->paint); - float grab_delta[3]; const ePaintSymmetryFlags symm = sd->paint.symmetry_flags & PAINT_SYMM_AXIS_ALL; /* The pose brush applies all enabled symmetry axis in a single iteration, so the rest can be @@ -945,7 +1069,6 @@ void SCULPT_do_pose_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode) } SculptPoseIKChain *ik_chain = ss->cache->pose_ik_chain; - copy_v3_v3(grab_delta, ss->cache->grab_delta); switch (brush->pose_deform_type) { case BRUSH_POSE_DEFORM_ROTATE_TWIST: @@ -999,7 +1122,6 @@ void SCULPT_do_pose_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode) .ob = ob, .brush = brush, .nodes = nodes, - .grab_delta = grab_delta, }; TaskParallelSettings settings; diff --git a/source/blender/editors/space_action/action_edit.c b/source/blender/editors/space_action/action_edit.c index e90122f2585..576b52a5cdd 100644 --- a/source/blender/editors/space_action/action_edit.c +++ b/source/blender/editors/space_action/action_edit.c @@ -490,7 +490,7 @@ void ACTION_OT_view_frame(wmOperatorType *ot) /* identifiers */ ot->name = "Go to Current Frame"; ot->idname = "ACTION_OT_view_frame"; - ot->description = "Move the view to the playhead"; + ot->description = "Move the view to the current frame"; /* api callbacks */ ot->exec = actkeys_view_frame_exec; diff --git a/source/blender/editors/space_buttons/buttons_texture.c b/source/blender/editors/space_buttons/buttons_texture.c index 5bf431be9f8..3dc5eca8a8b 100644 --- a/source/blender/editors/space_buttons/buttons_texture.c +++ b/source/blender/editors/space_buttons/buttons_texture.c @@ -545,7 +545,7 @@ static void template_texture_show(bContext *C, void *data_p, void *prop_p) } } -void uiTemplateTextureShow(uiLayout *layout, bContext *C, PointerRNA *ptr, PropertyRNA *prop) +void uiTemplateTextureShow(uiLayout *layout, const bContext *C, PointerRNA *ptr, PropertyRNA *prop) { /* button to quickly show texture in texture tab */ SpaceProperties *sbuts = CTX_wm_space_properties(C); diff --git a/source/blender/editors/space_graph/graph_edit.c b/source/blender/editors/space_graph/graph_edit.c index 8ffd2844f1a..a974ec612a9 100644 --- a/source/blender/editors/space_graph/graph_edit.c +++ b/source/blender/editors/space_graph/graph_edit.c @@ -385,7 +385,7 @@ void GRAPH_OT_view_frame(wmOperatorType *ot) /* identifiers */ ot->name = "Go to Current Frame"; ot->idname = "GRAPH_OT_view_frame"; - ot->description = "Move the view to the playhead"; + ot->description = "Move the view to the current frame"; /* api callbacks */ ot->exec = graphkeys_view_frame_exec; diff --git a/source/blender/editors/space_image/image_draw.c b/source/blender/editors/space_image/image_draw.c index 6037c1d2ec8..9040ca5e79c 100644 --- a/source/blender/editors/space_image/image_draw.c +++ b/source/blender/editors/space_image/image_draw.c @@ -476,7 +476,7 @@ static void sima_draw_zbuf_pixels( IMMDrawPixelsTexState state = immDrawPixelsTexSetup(GPU_SHADER_2D_IMAGE_SHUFFLE_COLOR); GPU_shader_uniform_vector( - state.shader, GPU_shader_get_uniform_ensure(state.shader, "shuffle"), 4, 1, red); + state.shader, GPU_shader_get_uniform(state.shader, "shuffle"), 4, 1, red); immDrawPixelsTex( &state, x1, y1, rectx, recty, GL_RED, GL_INT, GL_NEAREST, recti, zoomx, zoomy, NULL); @@ -524,7 +524,7 @@ static void sima_draw_zbuffloat_pixels(Scene *scene, IMMDrawPixelsTexState state = immDrawPixelsTexSetup(GPU_SHADER_2D_IMAGE_SHUFFLE_COLOR); GPU_shader_uniform_vector( - state.shader, GPU_shader_get_uniform_ensure(state.shader, "shuffle"), 4, 1, red); + state.shader, GPU_shader_get_uniform(state.shader, "shuffle"), 4, 1, red); immDrawPixelsTex( &state, x1, y1, rectx, recty, GL_RED, GL_FLOAT, GL_NEAREST, rectf, zoomx, zoomy, NULL); @@ -637,7 +637,7 @@ static void draw_image_buffer(const bContext *C, IMMDrawPixelsTexState state = immDrawPixelsTexSetup(GPU_SHADER_2D_IMAGE_SHUFFLE_COLOR); GPU_shader_uniform_vector( - state.shader, GPU_shader_get_uniform_ensure(state.shader, "shuffle"), 4, 1, shuffle); + state.shader, GPU_shader_get_uniform(state.shader, "shuffle"), 4, 1, shuffle); IMB_colormanagement_display_settings_from_ctx(C, &view_settings, &display_settings); display_buffer = IMB_display_buffer_acquire( diff --git a/source/blender/editors/space_image/image_undo.c b/source/blender/editors/space_image/image_undo.c index 5668b88826e..e0c44c3a0ba 100644 --- a/source/blender/editors/space_image/image_undo.c +++ b/source/blender/editors/space_image/image_undo.c @@ -958,7 +958,7 @@ static void image_undosys_step_decode( } if (us->paint_mode == PAINT_MODE_TEXTURE_3D) { - ED_object_mode_set(C, OB_MODE_TEXTURE_PAINT); + ED_object_mode_set_ex(C, OB_MODE_TEXTURE_PAINT, false, NULL); } /* Refresh texture slots. */ diff --git a/source/blender/editors/space_nla/nla_edit.c b/source/blender/editors/space_nla/nla_edit.c index f68896e21d6..dec7a0fd93c 100644 --- a/source/blender/editors/space_nla/nla_edit.c +++ b/source/blender/editors/space_nla/nla_edit.c @@ -567,7 +567,7 @@ void NLA_OT_view_frame(wmOperatorType *ot) /* identifiers */ ot->name = "Go to Current Frame"; ot->idname = "NLA_OT_view_frame"; - ot->description = "Move the view to the playhead"; + ot->description = "Move the view to the current frame"; /* api callbacks */ ot->exec = nlaedit_viewframe_exec; diff --git a/source/blender/editors/space_node/drawnode.c b/source/blender/editors/space_node/drawnode.c index 44003a5b9bc..01ac3a80871 100644 --- a/source/blender/editors/space_node/drawnode.c +++ b/source/blender/editors/space_node/drawnode.c @@ -3638,7 +3638,7 @@ void draw_nodespace_back_pix(const bContext *C, IMMDrawPixelsTexState state = immDrawPixelsTexSetup(GPU_SHADER_2D_IMAGE_SHUFFLE_COLOR); GPU_shader_uniform_vector( - state.shader, GPU_shader_get_uniform_ensure(state.shader, "shuffle"), 4, 1, shuffle); + state.shader, GPU_shader_get_uniform(state.shader, "shuffle"), 4, 1, shuffle); immDrawPixelsTex(&state, x, diff --git a/source/blender/editors/space_outliner/outliner_tree.c b/source/blender/editors/space_outliner/outliner_tree.c index 7bb62b0d1e2..d6efe683673 100644 --- a/source/blender/editors/space_outliner/outliner_tree.c +++ b/source/blender/editors/space_outliner/outliner_tree.c @@ -1427,9 +1427,9 @@ static void outliner_add_layer_collections_recursive(SpaceOutliner *soops, ten->name = id->name + 2; ten->directdata = lc; - /* Open by default. */ + /* Open by default, except linked collections, which may contain many elements. */ TreeStoreElem *tselem = TREESTORE(ten); - if (!tselem->used) { + if (!(tselem->used || ID_IS_LINKED(id) || ID_IS_OVERRIDE_LIBRARY(id))) { tselem->flag &= ~TSE_CLOSED; } diff --git a/source/blender/editors/space_sequencer/sequencer_draw.c b/source/blender/editors/space_sequencer/sequencer_draw.c index 5d8851d5e3d..1f06ab68516 100644 --- a/source/blender/editors/space_sequencer/sequencer_draw.c +++ b/source/blender/editors/space_sequencer/sequencer_draw.c @@ -2299,10 +2299,10 @@ void draw_timeline_seq(const bContext *C, ARegion *region) cfra_flag |= DRAWCFRA_UNIT_SECONDS; } - /* Draw playhead. */ + /* Draw the current frame indicator. */ ANIM_draw_cfra(C, v2d, cfra_flag); - /* Draw overlap playhead. */ + /* Draw overlap frame frame indicator. */ if (scene->ed && scene->ed->over_flag & SEQ_EDIT_OVERLAY_SHOW) { int cfra_over = (scene->ed->over_flag & SEQ_EDIT_OVERLAY_ABS) ? scene->ed->over_cfra : diff --git a/source/blender/editors/space_sequencer/sequencer_edit.c b/source/blender/editors/space_sequencer/sequencer_edit.c index 232bb1d66e8..ea0d5785d22 100644 --- a/source/blender/editors/space_sequencer/sequencer_edit.c +++ b/source/blender/editors/space_sequencer/sequencer_edit.c @@ -214,20 +214,41 @@ static void seq_proxy_build_job(const bContext *C, ReportList *reports) } file_list = BLI_gset_new(BLI_ghashutil_strhash_p, BLI_ghashutil_strcmp, "file list"); + bool selected = false; /* Check for no selected strips */ + SEQP_BEGIN (ed, seq) { - if ((seq->flag & SELECT)) { - bool success = BKE_sequencer_proxy_rebuild_context( - pj->main, pj->depsgraph, pj->scene, seq, file_list, &pj->queue); - if (!success) { - BKE_reportf(reports, RPT_ERROR, "Could not build proxy for strip %s", seq->name); - } + if (!ELEM(seq->type, SEQ_TYPE_MOVIE, SEQ_TYPE_IMAGE, SEQ_TYPE_META) || + (seq->flag & SELECT) == 0) { + continue; + } + + selected = true; + if (!(seq->flag & SEQ_USE_PROXY)) { + BKE_reportf(reports, RPT_WARNING, "Proxy is not enabled for %s, skipping.", seq->name); + continue; + } + else if (seq->strip->proxy->build_size_flags == 0) { + BKE_reportf(reports, RPT_WARNING, "Resolution is not selected for %s, skipping.", seq->name); + continue; + } + + bool success = BKE_sequencer_proxy_rebuild_context( + pj->main, pj->depsgraph, pj->scene, seq, file_list, &pj->queue); + + if (!success && (seq->strip->proxy->build_flags & SEQ_PROXY_SKIP_EXISTING) != 0) { + BKE_reportf(reports, RPT_WARNING, "Overwrite is not checked for %s, skipping.", seq->name); } } SEQ_END; + if (!selected) { + BKE_reportf(reports, RPT_WARNING, "Select movie or image strips."); + return; + } + BLI_gset_free(file_list, MEM_freeN); - if (!WM_jobs_is_running(wm_job)) { + if (selected && !WM_jobs_is_running(wm_job)) { G.is_break = false; WM_jobs_start(CTX_wm_manager(C), wm_job); } @@ -290,7 +311,7 @@ static int mouse_frame_side(View2D *v2d, short mouse_x, int frame) mval[0] = mouse_x; mval[1] = 0; - /* Choose the side based on which side of the playhead the mouse is on. */ + /* Choose the side based on which side of the current frame the mouse is on. */ UI_view2d_region_to_view(v2d, mval[0], mval[1], &mouseloc[0], &mouseloc[1]); return mouseloc[0] > frame ? SEQ_SIDE_RIGHT : SEQ_SIDE_LEFT; @@ -1355,7 +1376,7 @@ static int sequencer_snap_invoke(bContext *C, wmOperator *op, const wmEvent *UNU void SEQUENCER_OT_snap(struct wmOperatorType *ot) { /* Identifiers. */ - ot->name = "Snap Strips to Playhead"; + ot->name = "Snap Strips to the Current Frame"; ot->idname = "SEQUENCER_OT_snap"; ot->description = "Frame where selected strips will be snapped"; @@ -1706,7 +1727,7 @@ static int sequencer_slip_modal(bContext *C, wmOperator *op, const wmEvent *even mouse_x = event->mval[0]; } - /* Choose the side based on which side of the playhead the mouse is. */ + /* Choose the side based on which side of the current frame the mouse is. */ UI_view2d_region_to_view(v2d, mouse_x, 0, &mouseloc[0], &mouseloc[1]); offset = mouseloc[0] - data->init_mouseloc[0]; @@ -2353,7 +2374,7 @@ void SEQUENCER_OT_split(struct wmOperatorType *ot) "use_cursor_position", 0, "Use Cursor Position", - "Split at position of the cursor instead of playhead"); + "Split at position of the cursor instead of current frame"); prop = RNA_def_enum(ot->srna, "side", @@ -2955,7 +2976,7 @@ void SEQUENCER_OT_view_frame(wmOperatorType *ot) /* Identifiers. */ ot->name = "Go to Current Frame"; ot->idname = "SEQUENCER_OT_view_frame"; - ot->description = "Move the view to the playhead"; + ot->description = "Move the view to the current frame"; /* Api callbacks. */ ot->exec = sequencer_view_frame_exec; @@ -3757,12 +3778,7 @@ static int sequencer_enable_proxies_exec(bContext *C, wmOperator *op) SEQP_BEGIN (ed, seq) { if ((seq->flag & SELECT)) { - if (ELEM(seq->type, - SEQ_TYPE_MOVIE, - SEQ_TYPE_IMAGE, - SEQ_TYPE_META, - SEQ_TYPE_SCENE, - SEQ_TYPE_MULTICAM)) { + if (ELEM(seq->type, SEQ_TYPE_MOVIE, SEQ_TYPE_IMAGE, SEQ_TYPE_META)) { BKE_sequencer_proxy_set(seq, turnon); if (seq->strip->proxy == NULL) { continue; diff --git a/source/blender/editors/space_sequencer/sequencer_intern.h b/source/blender/editors/space_sequencer/sequencer_intern.h index 708682cd04f..0e7e691c748 100644 --- a/source/blender/editors/space_sequencer/sequencer_intern.h +++ b/source/blender/editors/space_sequencer/sequencer_intern.h @@ -191,6 +191,7 @@ enum { SEQ_SELECT_LR_MOUSE, SEQ_SELECT_LR_LEFT, SEQ_SELECT_LR_RIGHT, + SEQ_SELECT_LR_OVERLAP, }; /* Defines used internally. */ diff --git a/source/blender/editors/space_sequencer/sequencer_select.c b/source/blender/editors/space_sequencer/sequencer_select.c index c5472ed88e5..2e6cd7f7442 100644 --- a/source/blender/editors/space_sequencer/sequencer_select.c +++ b/source/blender/editors/space_sequencer/sequencer_select.c @@ -412,6 +412,7 @@ static int sequencer_select_exec(bContext *C, wmOperator *op) ret_value = OPERATOR_FINISHED; } + /* Select left, right or overlapping the current frame. */ else if (left_right != SEQ_SELECT_LR_NONE) { /* Use different logic for this. */ float x; @@ -420,20 +421,35 @@ static int sequencer_select_exec(bContext *C, wmOperator *op) } switch (left_right) { - case SEQ_SELECT_LR_MOUSE: + case SEQ_SELECT_LR_MOUSE: { + /* 10px margin around current frame to select under the current frame with mouse. */ + float margin = BLI_rctf_size_x(&v2d->cur) / BLI_rcti_size_x(&v2d->mask) * 10; x = UI_view2d_region_to_view_x(v2d, mval[0]); + if (x >= CFRA - margin && x <= CFRA + margin) { + x = CFRA; + } break; + } case SEQ_SELECT_LR_LEFT: x = CFRA - 1.0f; break; case SEQ_SELECT_LR_RIGHT: + x = CFRA + 1.0f; + break; + case SEQ_SELECT_LR_OVERLAP: default: x = CFRA; break; } SEQP_BEGIN (ed, seq) { - if (((x < CFRA) && (seq->enddisp <= CFRA)) || ((x >= CFRA) && (seq->startdisp >= CFRA))) { + /* Select overlapping the current frame. */ + if ((x == CFRA) && (seq->startdisp <= CFRA) && (seq->enddisp >= CFRA)) { + seq->flag = SELECT; + recurs_sel_seq(seq); + } + /* Select left or right. */ + else if ((x < CFRA && seq->enddisp <= CFRA) || (x > CFRA && seq->startdisp >= CFRA)) { seq->flag |= SELECT; recurs_sel_seq(seq); } @@ -627,8 +643,9 @@ void SEQUENCER_OT_select(wmOperatorType *ot) static const EnumPropertyItem sequencer_select_left_right_types[] = { {SEQ_SELECT_LR_NONE, "NONE", 0, "None", "Don't do left-right selection"}, {SEQ_SELECT_LR_MOUSE, "MOUSE", 0, "Mouse", "Use mouse position for selection"}, - {SEQ_SELECT_LR_LEFT, "LEFT", 0, "Left", "Select left"}, - {SEQ_SELECT_LR_RIGHT, "RIGHT", 0, "Right", "Select right"}, + {SEQ_SELECT_LR_LEFT, "LEFT", 0, "Left", "Select to the left of the current frame"}, + {SEQ_SELECT_LR_RIGHT, "RIGHT", 0, "Right", "Select to the right of the current frame"}, + {SEQ_SELECT_LR_OVERLAP, "OVERLAP", 0, "Overlap", "Select overlapping the current frame"}, {0, NULL, 0, NULL, NULL}, }; PropertyRNA *prop; diff --git a/source/blender/editors/space_userpref/userpref_ops.c b/source/blender/editors/space_userpref/userpref_ops.c index 1ec459ccfca..d823530fd89 100644 --- a/source/blender/editors/space_userpref/userpref_ops.c +++ b/source/blender/editors/space_userpref/userpref_ops.c @@ -25,11 +25,15 @@ #include "DNA_screen_types.h" +#include "BLI_listbase.h" + #include "BKE_context.h" #include "BKE_global.h" #include "BKE_main.h" #include "BKE_report.h" +#include "RNA_access.h" +#include "RNA_define.h" #include "RNA_types.h" #include "UI_interface.h" @@ -41,11 +45,13 @@ #include "ED_userpref.h" +#include "MEM_guardedalloc.h" + /* -------------------------------------------------------------------- */ -/** \name Reset Default Theme +/** \name Reset Default Theme Operator * \{ */ -static int reset_default_theme_exec(bContext *C, wmOperator *UNUSED(op)) +static int preferences_reset_default_theme_exec(bContext *C, wmOperator *UNUSED(op)) { Main *bmain = CTX_data_main(C); UI_theme_init_default(); @@ -64,7 +70,7 @@ static void PREFERENCES_OT_reset_default_theme(wmOperatorType *ot) ot->description = "Reset to the default theme colors"; /* callbacks */ - ot->exec = reset_default_theme_exec; + ot->exec = preferences_reset_default_theme_exec; /* flags */ ot->flag = OPTYPE_REGISTER; @@ -72,7 +78,64 @@ static void PREFERENCES_OT_reset_default_theme(wmOperatorType *ot) /** \} */ +/* -------------------------------------------------------------------- */ +/** \name Add Auto-Execution Path Operator + * \{ */ + +static int preferences_autoexec_add_exec(bContext *UNUSED(C), wmOperator *UNUSED(op)) +{ + bPathCompare *path_cmp = MEM_callocN(sizeof(bPathCompare), "bPathCompare"); + BLI_addtail(&U.autoexec_paths, path_cmp); + U.runtime.is_dirty = true; + return OPERATOR_FINISHED; +} + +static void PREFERENCES_OT_autoexec_path_add(wmOperatorType *ot) +{ + ot->name = "Add Autoexec Path"; + ot->idname = "PREFERENCES_OT_autoexec_path_add"; + ot->description = "Add path to exclude from auto-execution"; + + ot->exec = preferences_autoexec_add_exec; + + ot->flag = OPTYPE_INTERNAL; +} + +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Remove Auto-Execution Path Operator + * \{ */ + +static int preferences_autoexec_remove_exec(bContext *UNUSED(C), wmOperator *op) +{ + const int index = RNA_int_get(op->ptr, "index"); + bPathCompare *path_cmp = BLI_findlink(&U.autoexec_paths, index); + if (path_cmp) { + BLI_freelinkN(&U.autoexec_paths, path_cmp); + U.runtime.is_dirty = true; + } + return OPERATOR_FINISHED; +} + +static void PREFERENCES_OT_autoexec_path_remove(wmOperatorType *ot) +{ + ot->name = "Remove Autoexec Path"; + ot->idname = "PREFERENCES_OT_autoexec_path_remove"; + ot->description = "Remove path to exclude from auto-execution"; + + ot->exec = preferences_autoexec_remove_exec; + + ot->flag = OPTYPE_INTERNAL; + + RNA_def_int(ot->srna, "index", 0, 0, INT_MAX, "Index", "", 0, 1000); +} + +/** \} */ + void ED_operatortypes_userpref(void) { WM_operatortype_append(PREFERENCES_OT_reset_default_theme); + WM_operatortype_append(PREFERENCES_OT_autoexec_path_add); + WM_operatortype_append(PREFERENCES_OT_autoexec_path_remove); } diff --git a/source/blender/editors/space_view3d/view3d_buttons.c b/source/blender/editors/space_view3d/view3d_buttons.c index f81b4bb09e2..cb87ddafea1 100644 --- a/source/blender/editors/space_view3d/view3d_buttons.c +++ b/source/blender/editors/space_view3d/view3d_buttons.c @@ -1642,7 +1642,7 @@ static int view3d_object_mode_menu(bContext *C, wmOperator *op) return OPERATOR_CANCELLED; } else if (((ob->mode & OB_MODE_EDIT) == 0) && (ELEM(ob->type, OB_ARMATURE))) { - ED_object_mode_toggle(C, OB_MODE_POSE); + ED_object_mode_set(C, (ob->mode == OB_MODE_OBJECT) ? OB_MODE_POSE : OB_MODE_OBJECT); return OPERATOR_CANCELLED; } else { diff --git a/source/blender/editors/space_view3d/view3d_edit.c b/source/blender/editors/space_view3d/view3d_edit.c index 25678820050..edd75d8e561 100644 --- a/source/blender/editors/space_view3d/view3d_edit.c +++ b/source/blender/editors/space_view3d/view3d_edit.c @@ -3349,7 +3349,7 @@ void VIEW3D_OT_view_center_pick(wmOperatorType *ot) /** \} */ /* -------------------------------------------------------------------- */ -/** \name View Camera Center Operator +/** \name Frame Camera Bounds Operator * \{ */ static int view3d_center_camera_exec(bContext *C, wmOperator *UNUSED(op)) @@ -3386,8 +3386,8 @@ static int view3d_center_camera_exec(bContext *C, wmOperator *UNUSED(op)) void VIEW3D_OT_view_center_camera(wmOperatorType *ot) { /* identifiers */ - ot->name = "View Camera Center"; - ot->description = "Center the camera view"; + ot->name = "Frame Camera Bounds"; + ot->description = "Center the camera view, resizing the view to fit its bounds"; ot->idname = "VIEW3D_OT_view_center_camera"; /* api callbacks */ diff --git a/source/blender/editors/transform/transform.c b/source/blender/editors/transform/transform.c index 5fc65522fe6..79090bd633e 100644 --- a/source/blender/editors/transform/transform.c +++ b/source/blender/editors/transform/transform.c @@ -49,6 +49,7 @@ #include "ED_space_api.h" #include "WM_api.h" +#include "WM_message.h" #include "WM_types.h" #include "UI_interface_icons.h" @@ -1195,7 +1196,7 @@ int transformEvent(TransInfo *t, const wmEvent *event) stopConstraint(t); } else { - initSelectConstraint(t, event->shift); + initSelectConstraint(t); postSelectConstraint(t); } } @@ -1672,11 +1673,14 @@ void saveTransform(bContext *C, TransInfo *t, wmOperator *op) if (t->flag & T_MODAL) { /* do we check for parameter? */ if (transformModeUseSnap(t)) { - if (t->modifiers & MOD_SNAP) { - ts->snap_flag |= SCE_SNAP; - } - else { - ts->snap_flag &= ~SCE_SNAP; + if (!(t->modifiers & MOD_SNAP) != !(ts->snap_flag & SCE_SNAP)) { + if (t->modifiers & MOD_SNAP) { + ts->snap_flag |= SCE_SNAP; + } + else { + ts->snap_flag &= ~SCE_SNAP; + } + WM_msg_publish_rna_prop(t->mbus, &t->scene->id, ts, ToolSettings, use_snap); } } } @@ -1884,62 +1888,38 @@ bool initTransform(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *eve t->region->type, drawTransformView, t, REGION_DRAW_POST_VIEW); t->draw_handle_pixel = ED_region_draw_cb_activate( t->region->type, drawTransformPixel, t, REGION_DRAW_POST_PIXEL); - t->draw_handle_cursor = WM_paint_cursor_activate(CTX_wm_manager(C), - SPACE_TYPE_ANY, - RGN_TYPE_ANY, - transform_draw_cursor_poll, - transform_draw_cursor_draw, - t); + t->draw_handle_cursor = WM_paint_cursor_activate( + SPACE_TYPE_ANY, RGN_TYPE_ANY, transform_draw_cursor_poll, transform_draw_cursor_draw, t); } else if (t->spacetype == SPACE_IMAGE) { t->draw_handle_view = ED_region_draw_cb_activate( t->region->type, drawTransformView, t, REGION_DRAW_POST_VIEW); - t->draw_handle_cursor = WM_paint_cursor_activate(CTX_wm_manager(C), - SPACE_TYPE_ANY, - RGN_TYPE_ANY, - transform_draw_cursor_poll, - transform_draw_cursor_draw, - t); + t->draw_handle_cursor = WM_paint_cursor_activate( + SPACE_TYPE_ANY, RGN_TYPE_ANY, transform_draw_cursor_poll, transform_draw_cursor_draw, t); } else if (t->spacetype == SPACE_CLIP) { t->draw_handle_view = ED_region_draw_cb_activate( t->region->type, drawTransformView, t, REGION_DRAW_POST_VIEW); - t->draw_handle_cursor = WM_paint_cursor_activate(CTX_wm_manager(C), - SPACE_TYPE_ANY, - RGN_TYPE_ANY, - transform_draw_cursor_poll, - transform_draw_cursor_draw, - t); + t->draw_handle_cursor = WM_paint_cursor_activate( + SPACE_TYPE_ANY, RGN_TYPE_ANY, transform_draw_cursor_poll, transform_draw_cursor_draw, t); } else if (t->spacetype == SPACE_NODE) { t->draw_handle_view = ED_region_draw_cb_activate( t->region->type, drawTransformView, t, REGION_DRAW_POST_VIEW); - t->draw_handle_cursor = WM_paint_cursor_activate(CTX_wm_manager(C), - SPACE_TYPE_ANY, - RGN_TYPE_ANY, - transform_draw_cursor_poll, - transform_draw_cursor_draw, - t); + t->draw_handle_cursor = WM_paint_cursor_activate( + SPACE_TYPE_ANY, RGN_TYPE_ANY, transform_draw_cursor_poll, transform_draw_cursor_draw, t); } else if (t->spacetype == SPACE_GRAPH) { t->draw_handle_view = ED_region_draw_cb_activate( t->region->type, drawTransformView, t, REGION_DRAW_POST_VIEW); - t->draw_handle_cursor = WM_paint_cursor_activate(CTX_wm_manager(C), - SPACE_TYPE_ANY, - RGN_TYPE_ANY, - transform_draw_cursor_poll, - transform_draw_cursor_draw, - t); + t->draw_handle_cursor = WM_paint_cursor_activate( + SPACE_TYPE_ANY, RGN_TYPE_ANY, transform_draw_cursor_poll, transform_draw_cursor_draw, t); } else if (t->spacetype == SPACE_ACTION) { t->draw_handle_view = ED_region_draw_cb_activate( t->region->type, drawTransformView, t, REGION_DRAW_POST_VIEW); - t->draw_handle_cursor = WM_paint_cursor_activate(CTX_wm_manager(C), - SPACE_TYPE_ANY, - RGN_TYPE_ANY, - transform_draw_cursor_poll, - transform_draw_cursor_draw, - t); + t->draw_handle_cursor = WM_paint_cursor_activate( + SPACE_TYPE_ANY, RGN_TYPE_ANY, transform_draw_cursor_poll, transform_draw_cursor_draw, t); } createTransData(C, t); // make TransData structs from selection diff --git a/source/blender/editors/transform/transform.h b/source/blender/editors/transform/transform.h index 7720660e2e8..192728f63d2 100644 --- a/source/blender/editors/transform/transform.h +++ b/source/blender/editors/transform/transform.h @@ -560,6 +560,7 @@ typedef struct TransInfo { void *view; /** Only valid (non null) during an operator called function. */ struct bContext *context; + struct wmMsgBus *mbus; struct ScrArea *area; struct ARegion *region; struct Depsgraph *depsgraph; @@ -610,56 +611,53 @@ enum { T_CURSOR = 1 << 5, /** Transform points, having no rotation/scale. */ T_POINTS = 1 << 6, - - /* empty slot - (1 << 7) */ - /** restrictions flags */ - T_NO_CONSTRAINT = 1 << 8, - T_NULL_ONE = 1 << 9, - T_NO_ZERO = 1 << 10, + T_NO_CONSTRAINT = 1 << 7, + T_NULL_ONE = 1 << 8, + T_NO_ZERO = 1 << 9, T_ALL_RESTRICTIONS = T_NO_CONSTRAINT | T_NULL_ONE | T_NO_ZERO, - T_PROP_EDIT = 1 << 11, - T_PROP_CONNECTED = 1 << 12, - T_PROP_PROJECTED = 1 << 13, + T_PROP_EDIT = 1 << 10, + T_PROP_CONNECTED = 1 << 11, + T_PROP_PROJECTED = 1 << 12, T_PROP_EDIT_ALL = T_PROP_EDIT | T_PROP_CONNECTED | T_PROP_PROJECTED, - T_V3D_ALIGN = 1 << 14, + T_V3D_ALIGN = 1 << 13, /** For 2d views like uv or fcurve. */ - T_2D_EDIT = 1 << 15, - T_CLIP_UV = 1 << 16, + T_2D_EDIT = 1 << 14, + T_CLIP_UV = 1 << 15, /** Auto-ik is on. */ - T_AUTOIK = 1 << 18, + T_AUTOIK = 1 << 16, /** Don't use mirror even if the data-block option is set. */ - T_NO_MIRROR = 1 << 19, + T_NO_MIRROR = 1 << 17, /** To indicate that the value set in the `value` parameter is the final * value of the transformation, modified only by the constrain. */ - T_INPUT_IS_VALUES_FINAL = 1 << 20, + T_INPUT_IS_VALUES_FINAL = 1 << 18, /** To specify if we save back settings at the end. */ - T_MODAL = 1 << 21, + T_MODAL = 1 << 19, /** No retopo. */ - T_NO_PROJECT = 1 << 22, + T_NO_PROJECT = 1 << 20, - T_RELEASE_CONFIRM = 1 << 23, + T_RELEASE_CONFIRM = 1 << 21, /** Alternative transformation. used to add offset to tracking markers. */ - T_ALT_TRANSFORM = 1 << 24, + T_ALT_TRANSFORM = 1 << 22, /** #TransInfo.center has been set, don't change it. */ - T_OVERRIDE_CENTER = 1 << 25, + T_OVERRIDE_CENTER = 1 << 23, - T_MODAL_CURSOR_SET = 1 << 26, + T_MODAL_CURSOR_SET = 1 << 24, - T_CLNOR_REBUILD = 1 << 27, + T_CLNOR_REBUILD = 1 << 25, /* Special Aftertrans. */ - T_AUTOMERGE = 1 << 28, - T_AUTOSPLIT = 1 << 29, + T_AUTOMERGE = 1 << 26, + T_AUTOSPLIT = 1 << 27, }; /** #TransInfo.modifiers */ @@ -706,40 +704,39 @@ enum { /** #TransData.flag */ enum { TD_SELECTED = 1 << 0, - TD_NOACTION = 1 << 2, - TD_USEQUAT = 1 << 3, - TD_NOTCONNECTED = 1 << 4, + TD_USEQUAT = 1 << 1, + TD_NOTCONNECTED = 1 << 2, /** Used for scaling of #MetaElem.rad */ - TD_SINGLESIZE = 1 << 5, + TD_SINGLESIZE = 1 << 3, /** Scale relative to individual element center */ - TD_INDIVIDUAL_SCALE = 1 << 8, - TD_NOCENTER = 1 << 9, + TD_INDIVIDUAL_SCALE = 1 << 4, + TD_NOCENTER = 1 << 5, /** #TransData.ext abused for particle key timing. */ - TD_NO_EXT = 1 << 10, + TD_NO_EXT = 1 << 6, /** don't transform this data */ - TD_SKIP = 1 << 11, + TD_SKIP = 1 << 7, /** if this is a bez triple, we need to restore the handles, * if this is set #TransData.hdata needs freeing */ - TD_BEZTRIPLE = 1 << 12, + TD_BEZTRIPLE = 1 << 8, /** when this is set, don't apply translation changes to this element */ - TD_NO_LOC = 1 << 13, + TD_NO_LOC = 1 << 9, /** For Graph Editor autosnap, indicates that point should not undergo autosnapping */ - TD_NOTIMESNAP = 1 << 14, + TD_NOTIMESNAP = 1 << 10, /** For Graph Editor - curves that can only have int-values * need their keyframes tagged with this. */ - TD_INTVALUES = 1 << 15, + TD_INTVALUES = 1 << 11, /** For editmode mirror, clamp axis to 0 */ - TD_MIRROR_EDGE_X = 1 << 16, - TD_MIRROR_EDGE_Y = 1 << 17, - TD_MIRROR_EDGE_Z = 1 << 18, + TD_MIRROR_EDGE_X = 1 << 12, + TD_MIRROR_EDGE_Y = 1 << 13, + TD_MIRROR_EDGE_Z = 1 << 14, /** For fcurve handles, move them along with their keyframes */ - TD_MOVEHANDLE1 = 1 << 19, - TD_MOVEHANDLE2 = 1 << 20, + TD_MOVEHANDLE1 = 1 << 15, + TD_MOVEHANDLE2 = 1 << 16, /** Exceptional case with pose bone rotating when a parent bone has 'Local Location' * option enabled and rotating also transforms it. */ - TD_PBONE_LOCAL_MTX_P = 1 << 21, + TD_PBONE_LOCAL_MTX_P = 1 << 17, /** Same as above but for a child bone. */ - TD_PBONE_LOCAL_MTX_C = 1 << 22, + TD_PBONE_LOCAL_MTX_C = 1 << 18, }; /** #TransSnap.status */ @@ -920,7 +917,7 @@ struct TransformOrientation *addMatrixSpace(struct bContext *C, float mat[3][3], const char *name, const bool overwrite); -bool applyTransformOrientation(const struct TransformOrientation *ts, +void applyTransformOrientation(const struct TransformOrientation *ts, float r_mat[3][3], char r_name[64]); diff --git a/source/blender/editors/transform/transform_constraints.c b/source/blender/editors/transform/transform_constraints.c index 0a6e0d6b7f5..0347522b8e8 100644 --- a/source/blender/editors/transform/transform_constraints.c +++ b/source/blender/editors/transform/transform_constraints.c @@ -829,11 +829,7 @@ static void drawObjectConstraint(TransInfo *t) } } - if (t->flag & T_OBJECT) { - copy_v3_v3(co, td->ob->obmat[3]); - axismtx = td->axismtx; - } - else if (t->flag & T_EDIT) { + if (t->flag & T_EDIT) { mul_v3_m4v3(co, tc->mat, td->center); mul_m3_m3m3(tmp_axismtx, tc->mat3_unit, td->axismtx); @@ -880,21 +876,15 @@ void stopConstraint(TransInfo *t) /*------------------------- MMB Select -------------------------------*/ -void initSelectConstraint(TransInfo *t, bool force_global) +void initSelectConstraint(TransInfo *t) { - short orientation; - if (force_global) { - orientation = V3D_ORIENT_GLOBAL; - } - else { - if (t->orient_curr == 0) { - t->orient_curr = 1; - transform_orientations_current_set(t, t->orient_curr); - } - orientation = t->orient[t->orient_curr].type; + if (t->orient_curr == 0) { + t->orient_curr = 1; + transform_orientations_current_set(t, t->orient_curr); } - setUserConstraint(t, orientation, CON_APPLY | CON_SELECT, ""); + short orientation = t->orient[t->orient_curr].type; + setUserConstraint(t, orientation, CON_APPLY | CON_SELECT, "%s"); setNearestAxis(t); } diff --git a/source/blender/editors/transform/transform_constraints.h b/source/blender/editors/transform/transform_constraints.h index b57a7599321..c41b9361ca4 100644 --- a/source/blender/editors/transform/transform_constraints.h +++ b/source/blender/editors/transform/transform_constraints.h @@ -35,7 +35,7 @@ void drawConstraint(TransInfo *t); void drawPropCircle(const struct bContext *C, TransInfo *t); void startConstraint(TransInfo *t); void stopConstraint(TransInfo *t); -void initSelectConstraint(TransInfo *t, bool force_global); +void initSelectConstraint(TransInfo *t); void selectConstraint(TransInfo *t); void postSelectConstraint(TransInfo *t); void setNearestAxis(TransInfo *t); diff --git a/source/blender/editors/transform/transform_convert.c b/source/blender/editors/transform/transform_convert.c index b91542a80fc..ac69c2a60fe 100644 --- a/source/blender/editors/transform/transform_convert.c +++ b/source/blender/editors/transform/transform_convert.c @@ -827,10 +827,6 @@ void clipUVData(TransInfo *t) FOREACH_TRANS_DATA_CONTAINER (t, tc) { TransData *td = tc->data; for (int a = 0; a < tc->data_len; a++, td++) { - if (td->flag & TD_NOACTION) { - break; - } - if ((td->flag & TD_SKIP) || (!td->loc)) { continue; } @@ -2390,10 +2386,6 @@ void special_aftertrans_update(bContext *C, TransInfo *t) PTCacheID *pid; ob = td->ob; - if (td->flag & TD_NOACTION) { - break; - } - if (td->flag & TD_SKIP) { continue; } diff --git a/source/blender/editors/transform/transform_generics.c b/source/blender/editors/transform/transform_generics.c index b1e69dde0ac..6de962a3ed1 100644 --- a/source/blender/editors/transform/transform_generics.c +++ b/source/blender/editors/transform/transform_generics.c @@ -174,9 +174,6 @@ static void clipMirrorModifier(TransInfo *t) int clip; float loc[3], iloc[3]; - if (td->flag & TD_NOACTION) { - break; - } if (td->loc == NULL) { break; } @@ -1068,11 +1065,6 @@ static void recalcData_objects(TransInfo *t) for (int i = 0; i < tc->data_len; i++, td++) { Object *ob = td->ob; - - if (td->flag & TD_NOACTION) { - break; - } - if (td->flag & TD_SKIP) { continue; } @@ -1379,6 +1371,7 @@ void initTransInfo(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *eve bGPdata *gpd = CTX_data_gpencil_data(C); PropertyRNA *prop; + t->mbus = CTX_wm_message_bus(C); t->depsgraph = CTX_data_depsgraph_pointer(C); t->scene = sce; t->view_layer = view_layer; @@ -1649,13 +1642,17 @@ void initTransInfo(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *eve } { - TransformOrientationSlot *orient_slot = &t->scene->orientation_slots[SCE_ORIENT_DEFAULT]; short orient_type_set = -1; short orient_type_matrix_set = -1; - short orient_type_scene = orient_slot->type; - if (orient_type_scene == V3D_ORIENT_CUSTOM) { - const int index_custom = orient_slot->index_custom; - orient_type_scene += index_custom; + short orient_type_scene = V3D_ORIENT_GLOBAL; + + if ((t->spacetype == SPACE_VIEW3D) && (t->region->regiontype == RGN_TYPE_WINDOW)) { + TransformOrientationSlot *orient_slot = &t->scene->orientation_slots[SCE_ORIENT_DEFAULT]; + orient_type_scene = orient_slot->type; + if (orient_type_scene == V3D_ORIENT_CUSTOM) { + const int index_custom = orient_slot->index_custom; + orient_type_scene += index_custom; + } } short orient_types[3]; @@ -1929,7 +1926,7 @@ void postTrans(bContext *C, TransInfo *t) ED_region_draw_cb_exit(t->region->type, t->draw_handle_pixel); } if (t->draw_handle_cursor) { - WM_paint_cursor_end(CTX_wm_manager(C), t->draw_handle_cursor); + WM_paint_cursor_end(t->draw_handle_cursor); } if (t->flag & T_MODAL_CURSOR_SET) { @@ -2408,19 +2405,11 @@ void calculatePropRatio(TransInfo *t) } else if ((connected && (td->flag & TD_NOTCONNECTED || td->dist > t->prop_size)) || (connected == 0 && td->rdist > t->prop_size)) { - /* - * The elements are sorted according to their dist member in the array, - * that means we can stop when it finds one element outside of the propsize. - * do not set 'td->flag |= TD_NOACTION', the prop circle is being changed. - */ - td->factor = 0.0f; restoreElement(td); } else { /* Use rdist for falloff calculations, it is the real distance */ - td->flag &= ~TD_NOACTION; - if (connected) { dist = (t->prop_size - td->dist) / t->prop_size; } diff --git a/source/blender/editors/transform/transform_gizmo_3d.c b/source/blender/editors/transform/transform_gizmo_3d.c index 04be7048791..ebc021cd983 100644 --- a/source/blender/editors/transform/transform_gizmo_3d.c +++ b/source/blender/editors/transform/transform_gizmo_3d.c @@ -635,101 +635,6 @@ bool gimbal_axis(Object *ob, float gmat[3][3]) return 0; } -void ED_transform_calc_orientation_from_type(const bContext *C, float r_mat[3][3]) -{ - ARegion *region = CTX_wm_region(C); - Scene *scene = CTX_data_scene(C); - ViewLayer *view_layer = CTX_data_view_layer(C); - Object *obedit = CTX_data_edit_object(C); - RegionView3D *rv3d = region->regiondata; - Object *ob = OBACT(view_layer); - const short orientation_type = scene->orientation_slots[SCE_ORIENT_DEFAULT].type; - const short orientation_index_custom = scene->orientation_slots[SCE_ORIENT_DEFAULT].index_custom; - const int pivot_point = scene->toolsettings->transform_pivot_point; - - ED_transform_calc_orientation_from_type_ex( - C, r_mat, scene, rv3d, ob, obedit, orientation_type, orientation_index_custom, pivot_point); -} - -void ED_transform_calc_orientation_from_type_ex(const bContext *C, - float r_mat[3][3], - /* extra args (can be accessed from context) */ - Scene *scene, - RegionView3D *rv3d, - Object *ob, - Object *obedit, - const short orientation_type, - int orientation_index_custom, - const int pivot_point) -{ - bool ok = false; - - switch (orientation_type) { - case V3D_ORIENT_GLOBAL: { - break; /* nothing to do */ - } - case V3D_ORIENT_GIMBAL: { - if (gimbal_axis(ob, r_mat)) { - ok = true; - break; - } - /* if not gimbal, fall through to normal */ - ATTR_FALLTHROUGH; - } - case V3D_ORIENT_NORMAL: { - if (obedit || ob->mode & OB_MODE_POSE) { - ED_getTransformOrientationMatrix(C, r_mat, pivot_point); - ok = true; - break; - } - /* no break we define 'normal' as 'local' in Object mode */ - ATTR_FALLTHROUGH; - } - case V3D_ORIENT_LOCAL: { - if (ob->mode & OB_MODE_POSE) { - /* each bone moves on its own local axis, but to avoid confusion, - * use the active pones axis for display [#33575], this works as expected on a single bone - * and users who select many bones will understand what's going on and what local means - * when they start transforming */ - ED_getTransformOrientationMatrix(C, r_mat, pivot_point); - ok = true; - break; - } - copy_m3_m4(r_mat, ob->obmat); - normalize_m3(r_mat); - ok = true; - break; - } - case V3D_ORIENT_VIEW: { - if (rv3d != NULL) { - copy_m3_m4(r_mat, rv3d->viewinv); - normalize_m3(r_mat); - ok = true; - } - break; - } - case V3D_ORIENT_CURSOR: { - BKE_scene_cursor_rot_to_mat3(&scene->cursor, r_mat); - ok = true; - break; - } - case V3D_ORIENT_CUSTOM: - default: { - BLI_assert(orientation_type >= V3D_ORIENT_CUSTOM); - TransformOrientation *custom_orientation = BKE_scene_transform_orientation_find( - scene, orientation_index_custom); - if (applyTransformOrientation(custom_orientation, r_mat, NULL)) { - ok = true; - } - break; - } - } - - if (!ok) { - unit_m3(r_mat); - } -} - /* centroid, boundbox, of selection */ /* returns total items selected */ int ED_transform_calc_gizmo_stats(const bContext *C, diff --git a/source/blender/editors/transform/transform_mode_align.c b/source/blender/editors/transform/transform_mode_align.c index 9bce793809b..4fd4599b940 100644 --- a/source/blender/editors/transform/transform_mode_align.c +++ b/source/blender/editors/transform/transform_mode_align.c @@ -52,10 +52,6 @@ static void applyAlign(TransInfo *t, const int UNUSED(mval[2])) for (i = 0; i < tc->data_len; i++, td++) { float mat[3][3], invmat[3][3]; - if (td->flag & TD_NOACTION) { - break; - } - if (td->flag & TD_SKIP) { continue; } diff --git a/source/blender/editors/transform/transform_mode_baketime.c b/source/blender/editors/transform/transform_mode_baketime.c index bb8fd0df13d..4e7fc3578ce 100644 --- a/source/blender/editors/transform/transform_mode_baketime.c +++ b/source/blender/editors/transform/transform_mode_baketime.c @@ -97,10 +97,6 @@ static void applyBakeTime(TransInfo *t, const int mval[2]) FOREACH_TRANS_DATA_CONTAINER (t, tc) { TransData *td = tc->data; for (i = 0; i < tc->data_len; i++, td++) { - if (td->flag & TD_NOACTION) { - break; - } - if (td->flag & TD_SKIP) { continue; } diff --git a/source/blender/editors/transform/transform_mode_bbone_resize.c b/source/blender/editors/transform/transform_mode_bbone_resize.c index c81049ac379..77850e74785 100644 --- a/source/blender/editors/transform/transform_mode_bbone_resize.c +++ b/source/blender/editors/transform/transform_mode_bbone_resize.c @@ -141,10 +141,6 @@ static void applyBoneSize(TransInfo *t, const int UNUSED(mval[2])) FOREACH_TRANS_DATA_CONTAINER (t, tc) { TransData *td = tc->data; for (i = 0; i < tc->data_len; i++, td++) { - if (td->flag & TD_NOACTION) { - break; - } - if (td->flag & TD_SKIP) { continue; } diff --git a/source/blender/editors/transform/transform_mode_bend.c b/source/blender/editors/transform/transform_mode_bend.c index 721d226050a..3b51626b170 100644 --- a/source/blender/editors/transform/transform_mode_bend.c +++ b/source/blender/editors/transform/transform_mode_bend.c @@ -186,10 +186,6 @@ static void Bend(TransInfo *t, const int UNUSED(mval[2])) float delta[3]; float fac, fac_scaled; - if (td->flag & TD_NOACTION) { - break; - } - if (td->flag & TD_SKIP) { continue; } diff --git a/source/blender/editors/transform/transform_mode_boneenvelope.c b/source/blender/editors/transform/transform_mode_boneenvelope.c index aa20a5ade95..7045d190478 100644 --- a/source/blender/editors/transform/transform_mode_boneenvelope.c +++ b/source/blender/editors/transform/transform_mode_boneenvelope.c @@ -73,10 +73,6 @@ static void applyBoneEnvelope(TransInfo *t, const int UNUSED(mval[2])) FOREACH_TRANS_DATA_CONTAINER (t, tc) { TransData *td = tc->data; for (i = 0; i < tc->data_len; i++, td++) { - if (td->flag & TD_NOACTION) { - break; - } - if (td->flag & TD_SKIP) { continue; } diff --git a/source/blender/editors/transform/transform_mode_boneroll.c b/source/blender/editors/transform/transform_mode_boneroll.c index 0564a946148..1503519c519 100644 --- a/source/blender/editors/transform/transform_mode_boneroll.c +++ b/source/blender/editors/transform/transform_mode_boneroll.c @@ -75,10 +75,6 @@ static void applyBoneRoll(TransInfo *t, const int UNUSED(mval[2])) FOREACH_TRANS_DATA_CONTAINER (t, tc) { TransData *td = tc->data; for (i = 0; i < tc->data_len; i++, td++) { - if (td->flag & TD_NOACTION) { - break; - } - if (td->flag & TD_SKIP) { continue; } diff --git a/source/blender/editors/transform/transform_mode_curveshrinkfatten.c b/source/blender/editors/transform/transform_mode_curveshrinkfatten.c index 057f13ac068..84e4e950804 100644 --- a/source/blender/editors/transform/transform_mode_curveshrinkfatten.c +++ b/source/blender/editors/transform/transform_mode_curveshrinkfatten.c @@ -73,10 +73,6 @@ static void applyCurveShrinkFatten(TransInfo *t, const int UNUSED(mval[2])) FOREACH_TRANS_DATA_CONTAINER (t, tc) { TransData *td = tc->data; for (i = 0; i < tc->data_len; i++, td++) { - if (td->flag & TD_NOACTION) { - break; - } - if (td->flag & TD_SKIP) { continue; } diff --git a/source/blender/editors/transform/transform_mode_edge_bevelweight.c b/source/blender/editors/transform/transform_mode_edge_bevelweight.c index 5db7895232c..399cec2d62c 100644 --- a/source/blender/editors/transform/transform_mode_edge_bevelweight.c +++ b/source/blender/editors/transform/transform_mode_edge_bevelweight.c @@ -87,10 +87,6 @@ static void applyBevelWeight(TransInfo *t, const int UNUSED(mval[2])) FOREACH_TRANS_DATA_CONTAINER (t, tc) { TransData *td = tc->data; for (i = 0; i < tc->data_len; i++, td++) { - if (td->flag & TD_NOACTION) { - break; - } - if (td->val) { *td->val = td->ival + weight * td->factor; if (*td->val < 0.0f) { diff --git a/source/blender/editors/transform/transform_mode_edge_crease.c b/source/blender/editors/transform/transform_mode_edge_crease.c index 4a92a57fef6..53c948c742b 100644 --- a/source/blender/editors/transform/transform_mode_edge_crease.c +++ b/source/blender/editors/transform/transform_mode_edge_crease.c @@ -87,10 +87,6 @@ static void applyCrease(TransInfo *t, const int UNUSED(mval[2])) FOREACH_TRANS_DATA_CONTAINER (t, tc) { TransData *td = tc->data; for (i = 0; i < tc->data_len; i++, td++) { - if (td->flag & TD_NOACTION) { - break; - } - if (td->flag & TD_SKIP) { continue; } diff --git a/source/blender/editors/transform/transform_mode_edge_seq_slide.c b/source/blender/editors/transform/transform_mode_edge_seq_slide.c index 8690cd54a3b..c1cb4325c09 100644 --- a/source/blender/editors/transform/transform_mode_edge_seq_slide.c +++ b/source/blender/editors/transform/transform_mode_edge_seq_slide.c @@ -81,10 +81,6 @@ static void applySeqSlideValue(TransInfo *t, const float val[2]) FOREACH_TRANS_DATA_CONTAINER (t, tc) { TransData *td = tc->data; for (i = 0; i < tc->data_len; i++, td++) { - if (td->flag & TD_NOACTION) { - break; - } - if (td->flag & TD_SKIP) { continue; } diff --git a/source/blender/editors/transform/transform_mode_gpopacity.c b/source/blender/editors/transform/transform_mode_gpopacity.c index 267d297a31c..4712fb7ba01 100644 --- a/source/blender/editors/transform/transform_mode_gpopacity.c +++ b/source/blender/editors/transform/transform_mode_gpopacity.c @@ -73,10 +73,6 @@ static void applyGPOpacity(TransInfo *t, const int UNUSED(mval[2])) FOREACH_TRANS_DATA_CONTAINER (t, tc) { TransData *td = tc->data; for (i = 0; i < tc->data_len; i++, td++) { - if (td->flag & TD_NOACTION) { - break; - } - if (td->flag & TD_SKIP) { continue; } diff --git a/source/blender/editors/transform/transform_mode_gpshrinkfatten.c b/source/blender/editors/transform/transform_mode_gpshrinkfatten.c index 7c49d107703..ab9a0aa79ed 100644 --- a/source/blender/editors/transform/transform_mode_gpshrinkfatten.c +++ b/source/blender/editors/transform/transform_mode_gpshrinkfatten.c @@ -73,10 +73,6 @@ static void applyGPShrinkFatten(TransInfo *t, const int UNUSED(mval[2])) FOREACH_TRANS_DATA_CONTAINER (t, tc) { TransData *td = tc->data; for (i = 0; i < tc->data_len; i++, td++) { - if (td->flag & TD_NOACTION) { - break; - } - if (td->flag & TD_SKIP) { continue; } diff --git a/source/blender/editors/transform/transform_mode_maskshrinkfatten.c b/source/blender/editors/transform/transform_mode_maskshrinkfatten.c index e42439920db..68f3abda85b 100644 --- a/source/blender/editors/transform/transform_mode_maskshrinkfatten.c +++ b/source/blender/editors/transform/transform_mode_maskshrinkfatten.c @@ -78,10 +78,6 @@ static void applyMaskShrinkFatten(TransInfo *t, const int UNUSED(mval[2])) FOREACH_TRANS_DATA_CONTAINER (t, tc) { TransData *td = tc->data; for (i = 0; i < tc->data_len; i++, td++) { - if (td->flag & TD_NOACTION) { - break; - } - if (td->flag & TD_SKIP) { continue; } @@ -97,10 +93,6 @@ static void applyMaskShrinkFatten(TransInfo *t, const int UNUSED(mval[2])) FOREACH_TRANS_DATA_CONTAINER (t, tc) { TransData *td = tc->data; for (td = tc->data, i = 0; i < tc->data_len; i++, td++) { - if (td->flag & TD_NOACTION) { - break; - } - if (td->flag & TD_SKIP) { continue; } diff --git a/source/blender/editors/transform/transform_mode_mirror.c b/source/blender/editors/transform/transform_mode_mirror.c index dae17374481..8d953610eb8 100644 --- a/source/blender/editors/transform/transform_mode_mirror.c +++ b/source/blender/editors/transform/transform_mode_mirror.c @@ -69,10 +69,6 @@ static void applyMirror(TransInfo *t, const int UNUSED(mval[2])) FOREACH_TRANS_DATA_CONTAINER (t, tc) { TransData *td = tc->data; for (i = 0; i < tc->data_len; i++, td++) { - if (td->flag & TD_NOACTION) { - break; - } - if (td->flag & TD_SKIP) { continue; } @@ -93,10 +89,6 @@ static void applyMirror(TransInfo *t, const int UNUSED(mval[2])) FOREACH_TRANS_DATA_CONTAINER (t, tc) { TransData *td = tc->data; for (i = 0; i < tc->data_len; i++, td++) { - if (td->flag & TD_NOACTION) { - break; - } - if (td->flag & TD_SKIP) { continue; } diff --git a/source/blender/editors/transform/transform_mode_push_pull.c b/source/blender/editors/transform/transform_mode_push_pull.c index 6eb038ea9b0..4a2f979ec38 100644 --- a/source/blender/editors/transform/transform_mode_push_pull.c +++ b/source/blender/editors/transform/transform_mode_push_pull.c @@ -82,10 +82,6 @@ static void applyPushPull(TransInfo *t, const int UNUSED(mval[2])) FOREACH_TRANS_DATA_CONTAINER (t, tc) { TransData *td = tc->data; for (i = 0; i < tc->data_len; i++, td++) { - if (td->flag & TD_NOACTION) { - break; - } - if (td->flag & TD_SKIP) { continue; } diff --git a/source/blender/editors/transform/transform_mode_resize.c b/source/blender/editors/transform/transform_mode_resize.c index 00644b9bfdc..d919d5c889d 100644 --- a/source/blender/editors/transform/transform_mode_resize.c +++ b/source/blender/editors/transform/transform_mode_resize.c @@ -93,10 +93,6 @@ static void applyResize(TransInfo *t, const int UNUSED(mval[2])) FOREACH_TRANS_DATA_CONTAINER (t, tc) { TransData *td = tc->data; for (i = 0; i < tc->data_len; i++, td++) { - if (td->flag & TD_NOACTION) { - break; - } - if (td->flag & TD_SKIP) { continue; } diff --git a/source/blender/editors/transform/transform_mode_rotate.c b/source/blender/editors/transform/transform_mode_rotate.c index 55c97630487..6480cb6c30e 100644 --- a/source/blender/editors/transform/transform_mode_rotate.c +++ b/source/blender/editors/transform/transform_mode_rotate.c @@ -82,10 +82,6 @@ static void applyRotationValue(TransInfo *t, FOREACH_TRANS_DATA_CONTAINER (t, tc) { TransData *td = tc->data; for (i = 0; i < tc->data_len; i++, td++) { - if (td->flag & TD_NOACTION) { - break; - } - if (td->flag & TD_SKIP) { continue; } diff --git a/source/blender/editors/transform/transform_mode_shear.c b/source/blender/editors/transform/transform_mode_shear.c index 3eeb8a1e758..fa33c1550e7 100644 --- a/source/blender/editors/transform/transform_mode_shear.c +++ b/source/blender/editors/transform/transform_mode_shear.c @@ -165,11 +165,6 @@ static void applyShear(TransInfo *t, const int UNUSED(mval[2])) TransData *td = tc->data; for (i = 0; i < tc->data_len; i++, td++) { const float *center, *co; - - if (td->flag & TD_NOACTION) { - break; - } - if (td->flag & TD_SKIP) { continue; } diff --git a/source/blender/editors/transform/transform_mode_shrink_fatten.c b/source/blender/editors/transform/transform_mode_shrink_fatten.c index ed082e86b6d..78d3efa0d69 100644 --- a/source/blender/editors/transform/transform_mode_shrink_fatten.c +++ b/source/blender/editors/transform/transform_mode_shrink_fatten.c @@ -95,10 +95,6 @@ static void applyShrinkFatten(TransInfo *t, const int UNUSED(mval[2])) TransData *td = tc->data; for (i = 0; i < tc->data_len; i++, td++) { float tdistance; /* temp dist */ - if (td->flag & TD_NOACTION) { - break; - } - if (td->flag & TD_SKIP) { continue; } diff --git a/source/blender/editors/transform/transform_mode_skin_resize.c b/source/blender/editors/transform/transform_mode_skin_resize.c index b53dbb55c62..23d83050613 100644 --- a/source/blender/editors/transform/transform_mode_skin_resize.c +++ b/source/blender/editors/transform/transform_mode_skin_resize.c @@ -73,11 +73,6 @@ static void applySkinResize(TransInfo *t, const int UNUSED(mval[2])) for (i = 0; i < tc->data_len; i++, td++) { float tmat[3][3], smat[3][3]; float fsize[3]; - - if (td->flag & TD_NOACTION) { - break; - } - if (td->flag & TD_SKIP) { continue; } diff --git a/source/blender/editors/transform/transform_mode_tilt.c b/source/blender/editors/transform/transform_mode_tilt.c index 2f56f4bd162..ca0a8818477 100644 --- a/source/blender/editors/transform/transform_mode_tilt.c +++ b/source/blender/editors/transform/transform_mode_tilt.c @@ -77,10 +77,6 @@ static void applyTilt(TransInfo *t, const int UNUSED(mval[2])) FOREACH_TRANS_DATA_CONTAINER (t, tc) { TransData *td = tc->data; for (i = 0; i < tc->data_len; i++, td++) { - if (td->flag & TD_NOACTION) { - break; - } - if (td->flag & TD_SKIP) { continue; } diff --git a/source/blender/editors/transform/transform_mode_tosphere.c b/source/blender/editors/transform/transform_mode_tosphere.c index 841ccf41365..f6c5448a906 100644 --- a/source/blender/editors/transform/transform_mode_tosphere.c +++ b/source/blender/editors/transform/transform_mode_tosphere.c @@ -79,10 +79,6 @@ static void applyToSphere(TransInfo *t, const int UNUSED(mval[2])) TransData *td = tc->data; for (i = 0; i < tc->data_len; i++, td++) { float tratio; - if (td->flag & TD_NOACTION) { - break; - } - if (td->flag & TD_SKIP) { continue; } diff --git a/source/blender/editors/transform/transform_mode_trackball.c b/source/blender/editors/transform/transform_mode_trackball.c index c6e0b205204..ca5a749b275 100644 --- a/source/blender/editors/transform/transform_mode_trackball.c +++ b/source/blender/editors/transform/transform_mode_trackball.c @@ -63,10 +63,6 @@ static void applyTrackballValue(TransInfo *t, FOREACH_TRANS_DATA_CONTAINER (t, tc) { TransData *td = tc->data; for (i = 0; i < tc->data_len; i++, td++) { - if (td->flag & TD_NOACTION) { - break; - } - if (td->flag & TD_SKIP) { continue; } diff --git a/source/blender/editors/transform/transform_mode_translate.c b/source/blender/editors/transform/transform_mode_translate.c index 69552eda5bf..96820ca6385 100644 --- a/source/blender/editors/transform/transform_mode_translate.c +++ b/source/blender/editors/transform/transform_mode_translate.c @@ -236,10 +236,6 @@ static void applyTranslationValue(TransInfo *t, const float vec[3]) TransData *td = tc->data; for (int i = 0; i < tc->data_len; i++, td++) { - if (td->flag & TD_NOACTION) { - break; - } - if (td->flag & TD_SKIP) { continue; } diff --git a/source/blender/editors/transform/transform_orientations.c b/source/blender/editors/transform/transform_orientations.c index 32269e1bacc..cd170b144d8 100644 --- a/source/blender/editors/transform/transform_orientations.c +++ b/source/blender/editors/transform/transform_orientations.c @@ -397,14 +397,12 @@ int BIF_countTransformOrientation(const bContext *C) return BLI_listbase_count(transform_orientations); } -bool applyTransformOrientation(const TransformOrientation *ts, float r_mat[3][3], char *r_name) +void applyTransformOrientation(const TransformOrientation *ts, float r_mat[3][3], char *r_name) { if (r_name) { BLI_strncpy(r_name, ts->name, MAX_NAME); } copy_m3_m3(r_mat, ts->mat); - - return true; } /* Updates all `BONE_TRANSFORM` flags. @@ -438,82 +436,141 @@ static int armature_bone_transflags_update_recursive(bArmature *arm, return total; } -/* Sets the matrix of the specified space orientation. - * If the matrix cannot be obtained, an orientation different from the one - * informed is returned */ -short transform_orientation_matrix_get(bContext *C, - TransInfo *t, - const short orientation, - const float custom[3][3], - float r_spacemtx[3][3]) +void ED_transform_calc_orientation_from_type(const bContext *C, float r_mat[3][3]) { - Object *ob = CTX_data_active_object(C); - Object *obedit = CTX_data_active_object(C); + ARegion *region = CTX_wm_region(C); + Scene *scene = CTX_data_scene(C); + ViewLayer *view_layer = CTX_data_view_layer(C); + Object *obedit = CTX_data_edit_object(C); + RegionView3D *rv3d = region->regiondata; + Object *ob = OBACT(view_layer); + const short orientation_type = scene->orientation_slots[SCE_ORIENT_DEFAULT].type; + const short orientation_index_custom = scene->orientation_slots[SCE_ORIENT_DEFAULT].index_custom; + const int pivot_point = scene->toolsettings->transform_pivot_point; - switch (orientation) { - case V3D_ORIENT_GLOBAL: - unit_m3(r_spacemtx); - return V3D_ORIENT_GLOBAL; + ED_transform_calc_orientation_from_type_ex( + C, r_mat, scene, rv3d, ob, obedit, orientation_type, orientation_index_custom, pivot_point); +} - case V3D_ORIENT_GIMBAL: - unit_m3(r_spacemtx); - if (ob && gimbal_axis(ob, r_spacemtx)) { +short ED_transform_calc_orientation_from_type_ex(const bContext *C, + float r_mat[3][3], + /* extra args (can be accessed from context) */ + Scene *scene, + RegionView3D *rv3d, + Object *ob, + Object *obedit, + const short orientation_type, + int orientation_index_custom, + const int pivot_point) +{ + switch (orientation_type) { + case V3D_ORIENT_GLOBAL: { + unit_m3(r_mat); + return V3D_ORIENT_GLOBAL; + } + case V3D_ORIENT_GIMBAL: { + if (gimbal_axis(ob, r_mat)) { return V3D_ORIENT_GIMBAL; } - ATTR_FALLTHROUGH; /* no gimbal fallthrough to normal */ - - case V3D_ORIENT_NORMAL: - if (obedit || (ob && ob->mode & OB_MODE_POSE)) { - ED_getTransformOrientationMatrix(C, r_spacemtx, t->around); + /* if not gimbal, fall through to normal */ + ATTR_FALLTHROUGH; + } + case V3D_ORIENT_NORMAL: { + if (obedit || ob->mode & OB_MODE_POSE) { + ED_getTransformOrientationMatrix(C, r_mat, pivot_point); return V3D_ORIENT_NORMAL; } - ATTR_FALLTHROUGH; /* we define 'normal' as 'local' in Object mode */ - - case V3D_ORIENT_LOCAL: + /* no break we define 'normal' as 'local' in Object mode */ + ATTR_FALLTHROUGH; + } + case V3D_ORIENT_LOCAL: { if (ob) { - copy_m3_m4(r_spacemtx, ob->obmat); - normalize_m3(r_spacemtx); + if (ob->mode & OB_MODE_POSE) { + /* each bone moves on its own local axis, but to avoid confusion, + * use the active pones axis for display [#33575], this works as expected on a single + * bone and users who select many bones will understand what's going on and what local + * means when they start transforming */ + ED_getTransformOrientationMatrix(C, r_mat, pivot_point); + } + else { + copy_m3_m4(r_mat, ob->obmat); + normalize_m3(r_mat); + } return V3D_ORIENT_LOCAL; } - unit_m3(r_spacemtx); + unit_m3(r_mat); return V3D_ORIENT_GLOBAL; - + } case V3D_ORIENT_VIEW: { - float mat[3][3]; - if ((t->spacetype == SPACE_VIEW3D) && (t->region->regiontype == RGN_TYPE_WINDOW)) { - RegionView3D *rv3d = t->region->regiondata; - copy_m3_m4(mat, rv3d->viewinv); - normalize_m3(mat); + if (rv3d != NULL) { + copy_m3_m4(r_mat, rv3d->viewinv); + normalize_m3(r_mat); } else { - unit_m3(mat); + unit_m3(r_mat); } - copy_m3_m3(r_spacemtx, mat); return V3D_ORIENT_VIEW; } - case V3D_ORIENT_CURSOR: - BKE_scene_cursor_rot_to_mat3(&t->scene->cursor, r_spacemtx); + case V3D_ORIENT_CURSOR: { + BKE_scene_cursor_rot_to_mat3(&scene->cursor, r_mat); return V3D_ORIENT_CURSOR; - - case V3D_ORIENT_CUSTOM_MATRIX: - copy_m3_m3(r_spacemtx, custom); - return V3D_ORIENT_CUSTOM_MATRIX; - + } + case V3D_ORIENT_CUSTOM_MATRIX: { + /* Do nothing. */; + break; + } case V3D_ORIENT_CUSTOM: - default: - BLI_assert(orientation >= V3D_ORIENT_CUSTOM); - TransformOrientation *ts = BKE_scene_transform_orientation_find( - t->scene, orientation - V3D_ORIENT_CUSTOM); - if (applyTransformOrientation(ts, r_spacemtx, t->spacename)) { - /* pass */ - } - else { - unit_m3(r_spacemtx); - } + default: { + BLI_assert(orientation_type >= V3D_ORIENT_CUSTOM); + TransformOrientation *custom_orientation = BKE_scene_transform_orientation_find( + scene, orientation_index_custom); + applyTransformOrientation(custom_orientation, r_mat, NULL); break; + } } - return orientation; + return orientation_type; +} + +/* Sets the matrix of the specified space orientation. + * If the matrix cannot be obtained, an orientation different from the one + * informed is returned */ +short transform_orientation_matrix_get(bContext *C, + TransInfo *t, + const short orientation, + const float custom[3][3], + float r_spacemtx[3][3]) +{ + if (orientation == V3D_ORIENT_CUSTOM_MATRIX) { + copy_m3_m3(r_spacemtx, custom); + return V3D_ORIENT_CUSTOM_MATRIX; + } + + if ((t->spacetype == SPACE_VIEW3D) && (t->region->regiontype == RGN_TYPE_WINDOW)) { + Object *ob = CTX_data_active_object(C); + Object *obedit = CTX_data_active_object(C); + RegionView3D *rv3d = t->region->regiondata; + int orientation_index_custom = 0; + + if (orientation >= V3D_ORIENT_CUSTOM) { + orientation_index_custom = orientation - V3D_ORIENT_CUSTOM; + } + + return ED_transform_calc_orientation_from_type_ex( + C, + r_spacemtx, + /* extra args (can be accessed from context) */ + t->scene, + rv3d, + ob, + obedit, + orientation, + orientation_index_custom, + t->around); + } + + unit_m3(r_spacemtx); + return V3D_ORIENT_GLOBAL; } const char *transform_orientations_spacename_get(TransInfo *t, const short orient_type) @@ -545,37 +602,7 @@ const char *transform_orientations_spacename_get(TransInfo *t, const short orien void transform_orientations_current_set(TransInfo *t, const short orient_index) { const short orientation = t->orient[orient_index].type; - const char *spacename; - switch (orientation) { - case V3D_ORIENT_GLOBAL: - spacename = TIP_("global"); - break; - case V3D_ORIENT_GIMBAL: - spacename = TIP_("gimbal"); - break; - case V3D_ORIENT_NORMAL: - spacename = TIP_("normal"); - break; - case V3D_ORIENT_LOCAL: - spacename = TIP_("local"); - break; - case V3D_ORIENT_VIEW: - spacename = TIP_("view"); - break; - case V3D_ORIENT_CURSOR: - spacename = TIP_("cursor"); - break; - case V3D_ORIENT_CUSTOM_MATRIX: - spacename = TIP_("custom"); - break; - case V3D_ORIENT_CUSTOM: - default: - BLI_assert(orientation >= V3D_ORIENT_CUSTOM); - TransformOrientation *ts = BKE_scene_transform_orientation_find( - t->scene, orientation - V3D_ORIENT_CUSTOM); - spacename = ts->name; - break; - } + const char *spacename = transform_orientations_spacename_get(t, orientation); BLI_strncpy(t->spacename, spacename, sizeof(t->spacename)); copy_m3_m3(t->spacemtx, t->orient[orient_index].matrix); diff --git a/source/blender/editors/transform/transform_snap.c b/source/blender/editors/transform/transform_snap.c index 50f525a324b..82602e7d828 100644 --- a/source/blender/editors/transform/transform_snap.c +++ b/source/blender/editors/transform/transform_snap.c @@ -306,11 +306,6 @@ void applyProject(TransInfo *t) for (i = 0; i < tc->data_len; i++, td++) { float iloc[3], loc[3], no[3]; float mval_fl[2]; - - if (td->flag & TD_NOACTION) { - break; - } - if (td->flag & TD_SKIP) { continue; } @@ -417,11 +412,6 @@ void applyGridAbsolute(TransInfo *t) for (i = 0, td = tc->data; i < tc->data_len; i++, td++) { float iloc[3], loc[3], tvec[3]; - - if (td->flag & TD_NOACTION) { - break; - } - if (td->flag & TD_SKIP) { continue; } diff --git a/source/blender/editors/transform/transform_snap_object.c b/source/blender/editors/transform/transform_snap_object.c index 77bb0c1c785..c30b8d59dc0 100644 --- a/source/blender/editors/transform/transform_snap_object.c +++ b/source/blender/editors/transform/transform_snap_object.c @@ -104,7 +104,7 @@ typedef struct SnapObjectData { /* SNAP_EDIT_MESH */ BVHTreeFromEditMesh treedata_editmesh; float min[3], max[3]; - struct LinkNode **bvh_cache_p; + struct Mesh_Runtime *mesh_runtime; }; }; } SnapObjectData; @@ -144,6 +144,17 @@ struct SnapObjectContext { /** \} */ /* -------------------------------------------------------------------- */ +/** \name Utilities + * \{ */ + +static bool editmesh_eval_final_is_bmesh(const BMEditMesh *em) +{ + return (em->mesh_eval_final->runtime.wrapper_type == ME_WRAPPER_TYPE_BMESH); +} + +/** \} */ + +/* -------------------------------------------------------------------- */ /** \name Snap Object Data * \{ */ @@ -244,17 +255,17 @@ static SnapObjectData *snap_object_data_mesh_get(SnapObjectContext *sctx, Object return sod; } -static struct LinkNode **snap_object_data_editmesh_bvh_cache_get(Object *ob) +static struct Mesh_Runtime *snap_object_data_editmesh_runtime_get(Object *ob) { BMEditMesh *em = BKE_editmesh_from_object(ob); if (em->mesh_eval_final) { - return &em->mesh_eval_final->runtime.bvh_cache; + return &em->mesh_eval_final->runtime; } if (em->mesh_eval_cage) { - return &em->mesh_eval_cage->runtime.bvh_cache; + return &em->mesh_eval_cage->runtime; } - return &((Mesh *)ob->data)->runtime.bvh_cache; + return &((Mesh *)ob->data)->runtime; } static SnapObjectData *snap_object_data_editmesh_get(SnapObjectContext *sctx, @@ -291,23 +302,23 @@ static SnapObjectData *snap_object_data_editmesh_get(SnapObjectContext *sctx, clear_cache = true; init = true; } - else if (sod->bvh_cache_p) { - if (sod->bvh_cache_p != snap_object_data_editmesh_bvh_cache_get(ob)) { + else if (sod->mesh_runtime) { + if (sod->mesh_runtime != snap_object_data_editmesh_runtime_get(ob)) { clear_cache = true; init = true; } else if (sod->treedata_editmesh.tree && sod->treedata_editmesh.cached && - !bvhcache_has_tree(*sod->bvh_cache_p, sod->treedata_editmesh.tree)) { + !bvhcache_has_tree(sod->mesh_runtime->bvh_cache, sod->treedata_editmesh.tree)) { /* The tree is owned by the EditMesh and may have been freed since we last used! */ clear = true; } else if (sod->bvhtree[0] && sod->cached[0] && - !bvhcache_has_tree(*sod->bvh_cache_p, sod->bvhtree[0])) { + !bvhcache_has_tree(sod->mesh_runtime->bvh_cache, sod->bvhtree[0])) { /* The tree is owned by the EditMesh and may have been freed since we last used! */ clear = true; } else if (sod->bvhtree[1] && sod->cached[1] && - !bvhcache_has_tree(*sod->bvh_cache_p, sod->bvhtree[1])) { + !bvhcache_has_tree(sod->mesh_runtime->bvh_cache, sod->bvhtree[1])) { /* The tree is owned by the EditMesh and may have been freed since we last used! */ clear = true; } @@ -346,7 +357,7 @@ static SnapObjectData *snap_object_data_editmesh_get(SnapObjectContext *sctx, bm_mesh_minmax(em->bm, sod->min, sod->max); } - sod->bvh_cache_p = snap_object_data_editmesh_bvh_cache_get(ob); + sod->mesh_runtime = snap_object_data_editmesh_runtime_get(ob); } return sod; @@ -359,7 +370,7 @@ static SnapObjectData *snap_object_data_editmesh_get(SnapObjectContext *sctx, * \{ */ typedef void (*IterSnapObjsCallback)(SnapObjectContext *sctx, - bool is_obedit, + bool use_obedit, bool use_backface_culling, Object *ob, float obmat[4][4], @@ -835,14 +846,19 @@ static bool raycastEditMesh(SnapObjectContext *sctx, sctx->callbacks.edit_mesh.user_data); bvhtree_from_editmesh_looptri_ex( - treedata, em, elem_mask, looptri_num_active, 0.0f, 4, 6, 0, NULL); + treedata, em, elem_mask, looptri_num_active, 0.0f, 4, 6, 0, NULL, NULL); MEM_freeN(elem_mask); } else { /* Only cache if bvhtree is created without a mask. * This helps keep a standardized bvhtree in cache. */ - BKE_bvhtree_from_editmesh_get(treedata, em, 4, BVHTREE_FROM_EM_LOOPTRI, sod->bvh_cache_p); + BKE_bvhtree_from_editmesh_get(treedata, + em, + 4, + BVHTREE_FROM_EM_LOOPTRI, + &sod->mesh_runtime->bvh_cache, + sod->mesh_runtime->eval_mutex); } if (treedata->tree == NULL) { @@ -920,41 +936,52 @@ static bool raycastEditMesh(SnapObjectContext *sctx, return retval; } +struct RaycastObjUserData { + const float *ray_start; + const float *ray_dir; + uint ob_index; + /* read/write args */ + float *ray_depth; + /* return args */ + float *r_loc; + float *r_no; + int *r_index; + Object **r_ob; + float (*r_obmat)[4]; + ListBase *r_hit_list; + bool use_occlusion_test; + bool ret; +}; + /** * \param use_obedit: Uses the coordinates of BMesh (if any) to do the snapping; * * \note Duplicate args here are documented at #snapObjectsRay */ -static bool raycastObj(SnapObjectContext *sctx, - const float ray_start[3], - const float ray_dir[3], - Object *ob, - const float obmat[4][4], - const uint ob_index, - bool use_obedit, - bool use_occlusion_test, - bool use_backface_culling, - /* read/write args */ - float *ray_depth, - /* return args */ - float r_loc[3], - float r_no[3], - int *r_index, - Object **r_ob, - float r_obmat[4][4], - ListBase *r_hit_list) +static void raycast_obj_fn(SnapObjectContext *sctx, + bool use_obedit, + bool use_backface_culling, + Object *ob, + float obmat[4][4], + void *data) { + struct RaycastObjUserData *dt = data; + const uint ob_index = dt->ob_index++; + bool use_occlusion_test = dt->use_occlusion_test; + /* read/write args */ + float *ray_depth = dt->ray_depth; + bool retval = false; if (use_occlusion_test) { if (use_obedit && sctx->use_v3d && XRAY_FLAG_ENABLED(sctx->v3d_data.v3d)) { /* Use of occlude geometry in editing mode disabled. */ - return false; + return; } if (ELEM(ob->dt, OB_BOUNDBOX, OB_WIRE)) { /* Do not hit objects that are in wire or bounding box * display mode. */ - return false; + return; } } @@ -963,22 +990,22 @@ static bool raycastObj(SnapObjectContext *sctx, Mesh *me = ob->data; bool use_hide = false; if (BKE_object_is_in_editmode(ob)) { - if (use_obedit) { + if (use_obedit || editmesh_eval_final_is_bmesh(me->edit_mesh)) { /* Operators only update the editmesh looptris of the original mesh. */ BMEditMesh *em_orig = BKE_editmesh_from_object(DEG_get_original_object(ob)); retval = raycastEditMesh(sctx, - ray_start, - ray_dir, + dt->ray_start, + dt->ray_dir, ob, em_orig, obmat, ob_index, use_backface_culling, ray_depth, - r_loc, - r_no, - r_index, - r_hit_list); + dt->r_loc, + dt->r_no, + dt->r_index, + dt->r_hit_list); break; } else { @@ -990,8 +1017,8 @@ static bool raycastObj(SnapObjectContext *sctx, } } retval = raycastMesh(sctx, - ray_start, - ray_dir, + dt->ray_start, + dt->ray_dir, ob, me, obmat, @@ -999,10 +1026,10 @@ static bool raycastObj(SnapObjectContext *sctx, use_hide, use_backface_culling, ray_depth, - r_loc, - r_no, - r_index, - r_hit_list); + dt->r_loc, + dt->r_no, + dt->r_index, + dt->r_hit_list); break; } case OB_CURVE: @@ -1011,8 +1038,8 @@ static bool raycastObj(SnapObjectContext *sctx, Mesh *mesh_eval = BKE_object_get_evaluated_mesh(ob); if (mesh_eval) { retval = raycastMesh(sctx, - ray_start, - ray_dir, + dt->ray_start, + dt->ray_dir, ob, mesh_eval, obmat, @@ -1020,70 +1047,24 @@ static bool raycastObj(SnapObjectContext *sctx, false, use_backface_culling, ray_depth, - r_loc, - r_no, - r_index, - r_hit_list); + dt->r_loc, + dt->r_no, + dt->r_index, + dt->r_hit_list); break; } } } if (retval) { - if (r_ob) { - *r_ob = ob; + if (dt->r_ob) { + *dt->r_ob = ob; } - if (r_obmat) { - copy_m4_m4(r_obmat, obmat); + if (dt->r_obmat) { + copy_m4_m4(dt->r_obmat, obmat); } - return true; + dt->ret = true; } - - return false; -} - -struct RaycastObjUserData { - const float *ray_start; - const float *ray_dir; - uint ob_index; - /* read/write args */ - float *ray_depth; - /* return args */ - float *r_loc; - float *r_no; - int *r_index; - Object **r_ob; - float (*r_obmat)[4]; - ListBase *r_hit_list; - bool use_occlusion_test; - bool ret; -}; - -static void raycast_obj_cb(SnapObjectContext *sctx, - bool use_obedit, - bool use_backface_culling, - Object *ob, - float obmat[4][4], - void *data) -{ - struct RaycastObjUserData *dt = data; - - dt->ret |= raycastObj(sctx, - dt->ray_start, - dt->ray_dir, - ob, - obmat, - dt->ob_index++, - use_obedit, - dt->use_occlusion_test, - use_backface_culling, - dt->ray_depth, - dt->r_loc, - dt->r_no, - dt->r_index, - dt->r_ob, - dt->r_obmat, - dt->r_hit_list); } /** @@ -1144,7 +1125,7 @@ static bool raycastObjects(SnapObjectContext *sctx, .ret = false, }; - iter_snap_objects(sctx, depsgraph, params, raycast_obj_cb, &data); + iter_snap_objects(sctx, depsgraph, params, raycast_obj_fn, &data); return data.ret; } @@ -2524,11 +2505,16 @@ static short snapEditMesh(SnapObjectContext *sctx, sctx->callbacks.edit_mesh.user_data); bvhtree_from_editmesh_verts_ex( - &treedata, em, verts_mask, verts_num_active, 0.0f, 2, 6, 0, NULL); + &treedata, em, verts_mask, verts_num_active, 0.0f, 2, 6, 0, NULL, NULL); MEM_freeN(verts_mask); } else { - BKE_bvhtree_from_editmesh_get(&treedata, em, 2, BVHTREE_FROM_EM_VERTS, sod->bvh_cache_p); + BKE_bvhtree_from_editmesh_get(&treedata, + em, + 2, + BVHTREE_FROM_EM_VERTS, + &sod->mesh_runtime->bvh_cache, + (ThreadMutex *)sod->mesh_runtime->eval_mutex); } sod->bvhtree[0] = treedata.tree; sod->cached[0] = treedata.cached; @@ -2551,11 +2537,16 @@ static short snapEditMesh(SnapObjectContext *sctx, sctx->callbacks.edit_mesh.user_data); bvhtree_from_editmesh_edges_ex( - &treedata, em, edges_mask, edges_num_active, 0.0f, 2, 6, 0, NULL); + &treedata, em, edges_mask, edges_num_active, 0.0f, 2, 6, 0, NULL, NULL); MEM_freeN(edges_mask); } else { - BKE_bvhtree_from_editmesh_get(&treedata, em, 2, BVHTREE_FROM_EM_EDGES, sod->bvh_cache_p); + BKE_bvhtree_from_editmesh_get(&treedata, + em, + 2, + BVHTREE_FROM_EM_EDGES, + &sod->mesh_runtime->bvh_cache, + sod->mesh_runtime->eval_mutex); } sod->bvhtree[1] = treedata.tree; sod->cached[1] = treedata.cached; @@ -2644,45 +2635,51 @@ static short snapEditMesh(SnapObjectContext *sctx, return 0; } +struct SnapObjUserData { + SnapData *snapdata; + /* read/write args */ + float *dist_px; + /* return args */ + float *r_loc; + float *r_no; + int *r_index; + Object **r_ob; + float (*r_obmat)[4]; + short ret; +}; + /** * \param use_obedit: Uses the coordinates of BMesh (if any) to do the snapping; * * \note Duplicate args here are documented at #snapObjectsRay */ -static short snapObject(SnapObjectContext *sctx, - SnapData *snapdata, - Object *ob, - float obmat[4][4], +static void sanp_obj_fn(SnapObjectContext *sctx, bool use_obedit, bool use_backface_culling, - /* read/write args */ - float *dist_px, - /* return args */ - float r_loc[3], - float r_no[3], - int *r_index, - Object **r_ob, - float r_obmat[4][4]) + Object *ob, + float obmat[4][4], + void *data) { + struct SnapObjUserData *dt = data; short retval = 0; switch (ob->type) { case OB_MESH: { Mesh *me = ob->data; if (BKE_object_is_in_editmode(ob)) { - if (use_obedit) { + if (use_obedit || editmesh_eval_final_is_bmesh(me->edit_mesh)) { /* Operators only update the editmesh looptris of the original mesh. */ BMEditMesh *em_orig = BKE_editmesh_from_object(DEG_get_original_object(ob)); retval = snapEditMesh(sctx, - snapdata, + dt->snapdata, ob, em_orig, obmat, use_backface_culling, - dist_px, - r_loc, - r_no, - r_index); + dt->dist_px, + dt->r_loc, + dt->r_no, + dt->r_index); break; } else { @@ -2694,99 +2691,66 @@ static short snapObject(SnapObjectContext *sctx, } else if (ob->dt == OB_BOUNDBOX) { /* Do not snap to objects that are in bounding box display mode */ - return 0; + return; } - retval = snapMesh( - sctx, snapdata, ob, me, obmat, use_backface_culling, dist_px, r_loc, r_no, r_index); + retval = snapMesh(sctx, + dt->snapdata, + ob, + me, + obmat, + use_backface_culling, + dt->dist_px, + dt->r_loc, + dt->r_no, + dt->r_index); break; } case OB_ARMATURE: - retval = snapArmature(snapdata, ob, obmat, use_obedit, dist_px, r_loc, r_no, r_index); + retval = snapArmature( + dt->snapdata, ob, obmat, use_obedit, dt->dist_px, dt->r_loc, dt->r_no, dt->r_index); break; case OB_CURVE: - retval = snapCurve(snapdata, ob, obmat, use_obedit, dist_px, r_loc, r_no, r_index); + retval = snapCurve( + dt->snapdata, ob, obmat, use_obedit, dt->dist_px, dt->r_loc, dt->r_no, dt->r_index); break; /* Use ATTR_FALLTHROUGH if we want to snap to the generated mesh. */ case OB_SURF: case OB_FONT: { Mesh *mesh_eval = BKE_object_get_evaluated_mesh(ob); if (mesh_eval) { retval |= snapMesh(sctx, - snapdata, + dt->snapdata, ob, mesh_eval, obmat, use_backface_culling, - dist_px, - r_loc, - r_no, - r_index); + dt->dist_px, + dt->r_loc, + dt->r_no, + dt->r_index); } break; } case OB_EMPTY: - retval = snapEmpty(snapdata, ob, obmat, dist_px, r_loc, r_no, r_index); + retval = snapEmpty(dt->snapdata, ob, obmat, dt->dist_px, dt->r_loc, dt->r_no, dt->r_index); break; case OB_GPENCIL: - retval = snapEmpty(snapdata, ob, obmat, dist_px, r_loc, r_no, r_index); + retval = snapEmpty(dt->snapdata, ob, obmat, dt->dist_px, dt->r_loc, dt->r_no, dt->r_index); break; case OB_CAMERA: - retval = snapCamera(sctx, snapdata, ob, obmat, dist_px, r_loc, r_no, r_index); + retval = snapCamera( + sctx, dt->snapdata, ob, obmat, dt->dist_px, dt->r_loc, dt->r_no, dt->r_index); break; } if (retval) { - if (r_ob) { - *r_ob = ob; + if (dt->r_ob) { + *dt->r_ob = ob; } - if (r_obmat) { - copy_m4_m4(r_obmat, obmat); + if (dt->r_obmat) { + copy_m4_m4(dt->r_obmat, obmat); } - return retval; - } - - return 0; -} - -struct SnapObjUserData { - SnapData *snapdata; - /* read/write args */ - float *dist_px; - /* return args */ - float *r_loc; - float *r_no; - int *r_index; - Object **r_ob; - float (*r_obmat)[4]; - short ret; -}; - -static void sanp_obj_cb(SnapObjectContext *sctx, - bool is_obedit, - bool use_backface_culling, - Object *ob, - float obmat[4][4], - void *data) -{ - struct SnapObjUserData *dt = data; - - short elem = snapObject(sctx, - dt->snapdata, - ob, - obmat, - is_obedit, - use_backface_culling, - /* read/write args */ - dt->dist_px, - /* return args */ - dt->r_loc, - dt->r_no, - dt->r_index, - dt->r_ob, - dt->r_obmat); - - if (elem) { - dt->ret = elem; + dt->ret = retval; } } @@ -2839,7 +2803,7 @@ static short snapObjectsRay(SnapObjectContext *sctx, .ret = 0, }; - iter_snap_objects(sctx, depsgraph, params, sanp_obj_cb, &data); + iter_snap_objects(sctx, depsgraph, params, sanp_obj_fn, &data); return data.ret; } diff --git a/source/blender/editors/util/ed_util.c b/source/blender/editors/util/ed_util.c index f8e19b742e4..af387e4f7c2 100644 --- a/source/blender/editors/util/ed_util.c +++ b/source/blender/editors/util/ed_util.c @@ -153,10 +153,10 @@ void ED_editors_init(bContext *C) ED_object_sculptmode_enter_ex(bmain, depsgraph, scene, ob, true, reports); } else if (mode == OB_MODE_VERTEX_PAINT) { - ED_object_vpaintmode_enter_ex(bmain, depsgraph, wm, scene, ob); + ED_object_vpaintmode_enter_ex(bmain, depsgraph, scene, ob); } else if (mode == OB_MODE_WEIGHT_PAINT) { - ED_object_wpaintmode_enter_ex(bmain, depsgraph, wm, scene, ob); + ED_object_wpaintmode_enter_ex(bmain, depsgraph, scene, ob); } else { BLI_assert(0); @@ -174,7 +174,7 @@ void ED_editors_init(bContext *C) else { /* TODO(campbell): avoid operator calls. */ if (obact == ob) { - ED_object_mode_toggle(C, mode); + ED_object_mode_set(C, mode); } } } diff --git a/source/blender/editors/uvedit/uvedit_draw.c b/source/blender/editors/uvedit/uvedit_draw.c index f8cef95c776..897e2f13774 100644 --- a/source/blender/editors/uvedit/uvedit_draw.c +++ b/source/blender/editors/uvedit/uvedit_draw.c @@ -39,6 +39,7 @@ #include "../../draw/intern/draw_cache_impl.h" #include "BLI_math.h" +#include "BLI_task.h" #include "BLI_utildefines.h" #include "BKE_deform.h" @@ -206,8 +207,10 @@ static void uvedit_get_batches(Object *ob, else { batches->faces = NULL; } - - DRW_mesh_batch_cache_create_requested(ob, ob->data, scene, false, false); + struct TaskGraph *task_graph = BLI_task_graph_create(); + DRW_mesh_batch_cache_create_requested(task_graph, ob, ob->data, scene, false, false); + BLI_task_graph_work_and_wait(task_graph); + BLI_task_graph_free(task_graph); if (draw_stretch && (sima->dt_uvstretch == SI_UVDT_STRETCH_AREA)) { /* after create_requested we can load the actual areas */ @@ -229,7 +232,11 @@ static void draw_uvs_shadow(SpaceImage *sima, DRW_mesh_batch_cache_validate(me); GPUBatch *edges = DRW_mesh_batch_cache_get_uv_edges(me); - DRW_mesh_batch_cache_create_requested(ob_eval, me, scene, false, false); + + struct TaskGraph *task_graph = BLI_task_graph_create(); + DRW_mesh_batch_cache_create_requested(task_graph, ob_eval, me, scene, false, false); + BLI_task_graph_work_and_wait(task_graph); + BLI_task_graph_free(task_graph); if (edges) { if (sima->flag & SI_SMOOTH_UV) { @@ -269,7 +276,10 @@ static void draw_uvs_texpaint(const Scene *scene, Object *ob, Depsgraph *depsgra DRW_mesh_batch_cache_validate(me); GPUBatch *geom = DRW_mesh_batch_cache_get_uv_edges(me); - DRW_mesh_batch_cache_create_requested(ob_eval, me, scene, false, false); + struct TaskGraph *task_graph = BLI_task_graph_create(); + DRW_mesh_batch_cache_create_requested(task_graph, ob_eval, me, scene, false, false); + BLI_task_graph_work_and_wait(task_graph); + BLI_task_graph_free(task_graph); GPU_batch_program_set_builtin(geom, GPU_SHADER_2D_UV_UNIFORM_COLOR); GPU_batch_uniform_4fv(geom, "color", col); diff --git a/source/blender/editors/uvedit/uvedit_ops.c b/source/blender/editors/uvedit/uvedit_ops.c index 78b6cfc44ac..22b51937083 100644 --- a/source/blender/editors/uvedit/uvedit_ops.c +++ b/source/blender/editors/uvedit/uvedit_ops.c @@ -71,6 +71,7 @@ #include "UI_resources.h" #include "UI_view2d.h" +#include "intern/math_base_inline.c" #include "uvedit_intern.h" /* -------------------------------------------------------------------- */ @@ -1843,11 +1844,12 @@ static void UV_OT_cursor_set(wmOperatorType *ot) static int uv_seams_from_islands_exec(bContext *C, wmOperator *op) { + Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); - int ret = OPERATOR_CANCELLED; const float limit[2] = {STD_UV_CONNECT_LIMIT, STD_UV_CONNECT_LIMIT}; const bool mark_seams = RNA_boolean_get(op->ptr, "mark_seams"); const bool mark_sharp = RNA_boolean_get(op->ptr, "mark_sharp"); + bool changed_multi = false; uint objects_len = 0; Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data_with_uvs( @@ -1858,111 +1860,76 @@ static int uv_seams_from_islands_exec(bContext *C, wmOperator *op) Mesh *me = (Mesh *)ob->data; BMEditMesh *em = me->edit_mesh; BMesh *bm = em->bm; - - UvVertMap *vmap; - BMEdge *editedge; BMIter iter; if (!EDBM_uv_check(em)) { continue; } - ret = OPERATOR_FINISHED; - - /* This code sets editvert->tmp.l to the index. This will be useful later on. */ - BM_mesh_elem_table_ensure(bm, BM_FACE); - vmap = BM_uv_vert_map_create(bm, limit, false, false); - - BM_ITER_MESH (editedge, &iter, bm, BM_EDGES_OF_MESH) { - /* flags to determine if we uv is separated from first editface match */ - char separated1 = 0, separated2; - /* set to denote edge must be flagged as seam */ - char faces_separated = 0; - /* flag to keep track if uv1 is disconnected from first editface match */ - char v1coincident = 1; - /* For use with v1coincident. v1coincident will change only if we've had commonFaces */ - int commonFaces = 0; - - BMFace *efa1, *efa2; - - UvMapVert *mv1, *mvinit1, *mv2, *mvinit2, *mviter; - /* mv2cache stores the first of the list of coincident uv's for later comparison - * mv2sep holds the last separator and is copied to mv2cache - * when a hit is first found */ - UvMapVert *mv2cache = NULL, *mv2sep = NULL; - - mvinit1 = vmap->vert[BM_elem_index_get(editedge->v1)]; - if (mark_seams) { - BM_elem_flag_disable(editedge, BM_ELEM_SEAM); + + const int cd_loop_uv_offset = CustomData_get_offset(&bm->ldata, CD_MLOOPUV); + bool changed = false; + + BMFace *f; + BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) { + if (!uvedit_face_visible_test(scene, f)) { + continue; } - for (mv1 = mvinit1; mv1 && !faces_separated; mv1 = mv1->next) { - if (mv1->separate && commonFaces) { - v1coincident = 0; + BMLoop *l_iter; + BMLoop *l_first; + + l_iter = l_first = BM_FACE_FIRST_LOOP(f); + do { + if (l_iter == l_iter->radial_next) { + continue; + } + if (!uvedit_edge_select_test(scene, l_iter, cd_loop_uv_offset)) { + continue; } - separated2 = 0; - efa1 = BM_face_at_index(bm, mv1->poly_index); - mvinit2 = vmap->vert[BM_elem_index_get(editedge->v2)]; + const MLoopUV *luv_curr = BM_ELEM_CD_GET_VOID_P(l_iter, cd_loop_uv_offset); + const MLoopUV *luv_next = BM_ELEM_CD_GET_VOID_P(l_iter->next, cd_loop_uv_offset); - for (mv2 = mvinit2; mv2; mv2 = mv2->next) { - if (mv2->separate) { - mv2sep = mv2; + bool mark = false; + BMLoop *l_other = l_iter->radial_next; + do { + const MLoopUV *luv_other_curr = BM_ELEM_CD_GET_VOID_P(l_other, cd_loop_uv_offset); + const MLoopUV *luv_other_next = BM_ELEM_CD_GET_VOID_P(l_other->next, cd_loop_uv_offset); + if (l_iter->v != l_other->v) { + SWAP(const MLoopUV *, luv_other_curr, luv_other_next); } - efa2 = BM_face_at_index(bm, mv2->poly_index); - if (efa1 == efa2) { - /* if v1 is not coincident no point in comparing */ - if (v1coincident) { - /* have we found previously anything? */ - if (mv2cache) { - /* flag seam unless proved to be coincident with previous hit */ - separated2 = 1; - for (mviter = mv2cache; mviter; mviter = mviter->next) { - if (mviter->separate && mviter != mv2cache) { - break; - } - /* coincident with previous hit, do not flag seam */ - if (mviter == mv2) { - separated2 = 0; - } - } - } - /* First hit case, store the hit in the cache */ - else { - mv2cache = mv2sep; - commonFaces = 1; - } - } - else { - separated1 = 1; - } + if (!compare_ff(luv_curr->uv[0], luv_other_curr->uv[0], limit[0]) || + !compare_ff(luv_curr->uv[1], luv_other_curr->uv[1], limit[1]) || - if (separated1 || separated2) { - faces_separated = 1; - break; - } + !compare_ff(luv_next->uv[0], luv_other_next->uv[0], limit[0]) || + !compare_ff(luv_next->uv[1], luv_other_next->uv[1], limit[1])) { + mark = true; + break; } - } - } + } while ((l_other = l_other->radial_next) != l_iter); - if (faces_separated) { - if (mark_seams) { - BM_elem_flag_enable(editedge, BM_ELEM_SEAM); - } - if (mark_sharp) { - BM_elem_flag_disable(editedge, BM_ELEM_SMOOTH); + if (mark) { + if (mark_seams) { + BM_elem_flag_enable(l_iter->e, BM_ELEM_SEAM); + } + if (mark_sharp) { + BM_elem_flag_disable(l_iter->e, BM_ELEM_SMOOTH); + } + changed = true; } - } + } while ((l_iter = l_iter->next) != l_first); } - BM_uv_vert_map_free(vmap); - - DEG_id_tag_update(&me->id, 0); - WM_event_add_notifier(C, NC_GEOM | ND_DATA, me); + if (changed) { + changed_multi = true; + DEG_id_tag_update(&me->id, 0); + WM_event_add_notifier(C, NC_GEOM | ND_DATA, me); + } } MEM_freeN(objects); - return ret; + return changed_multi ? OPERATOR_FINISHED : OPERATOR_CANCELLED; } static void UV_OT_seams_from_islands(wmOperatorType *ot) |