diff options
author | YimingWu <xp8110@outlook.com> | 2019-05-28 10:39:42 +0300 |
---|---|---|
committer | YimingWu <xp8110@outlook.com> | 2019-05-28 10:39:42 +0300 |
commit | f37533fc44cfb8a7eec919df0dae38998de10e2f (patch) | |
tree | 264074656a88f96bdc3a4dbf53340277d45dc86a /source/blender/editors | |
parent | a640228d92273154acc644d525b095b5318c248b (diff) | |
parent | 1008d9c73567780ec22bea6a0b27f57e60ea403d (diff) |
Merge branch 'master' into soc-2019-npr
Diffstat (limited to 'source/blender/editors')
102 files changed, 2352 insertions, 1687 deletions
diff --git a/source/blender/editors/animation/anim_markers.c b/source/blender/editors/animation/anim_markers.c index 876bc9ae3e4..90632da8a7c 100644 --- a/source/blender/editors/animation/anim_markers.c +++ b/source/blender/editors/animation/anim_markers.c @@ -482,7 +482,7 @@ static void draw_markers_background(rctf *rect) immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); unsigned char shade[4]; - UI_GetThemeColor4ubv(TH_SCRUBBING_BACKGROUND, shade); + UI_GetThemeColor4ubv(TH_TIME_SCRUB_BACKGROUND, shade); immUniformColor4ubv(shade); diff --git a/source/blender/editors/animation/time_scrub_ui.c b/source/blender/editors/animation/time_scrub_ui.c index 37e7eab74d4..70a9b7ba1fa 100644 --- a/source/blender/editors/animation/time_scrub_ui.c +++ b/source/blender/editors/animation/time_scrub_ui.c @@ -46,12 +46,12 @@ #include "RNA_access.h" -static void get_scrubbing_region_rect(const ARegion *ar, rcti *rect) +static void get_time_scrub_region_rect(const ARegion *ar, rcti *rect) { rect->xmin = 0; rect->xmax = ar->winx; rect->ymax = ar->winy; - rect->ymin = rect->ymax - UI_SCRUBBING_MARGIN_Y; + rect->ymin = rect->ymax - UI_TIME_SCRUB_MARGIN_Y; } static int get_centered_text_y(const rcti *rect) @@ -64,7 +64,7 @@ static void draw_background(const rcti *rect) uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); - immUniformThemeColor(TH_SCRUBBING_BACKGROUND); + immUniformThemeColor(TH_TIME_SCRUB_BACKGROUND); GPU_blend(true); GPU_blend_set_func_separate( @@ -91,7 +91,7 @@ static void get_current_time_str( static void draw_current_frame(const Scene *scene, bool display_seconds, const View2D *v2d, - const rcti *scrubbing_region_rect, + const rcti *scrub_region_rect, int current_frame) { const uiFontStyle *fstyle = UI_FSTYLE_WIDGET; @@ -111,9 +111,9 @@ static void draw_current_frame(const Scene *scene, UI_draw_roundbox_3fvAlpha(true, frame_x - box_width / 2 + U.pixelsize / 2, - scrubbing_region_rect->ymin + box_padding, + scrub_region_rect->ymin + box_padding, frame_x + box_width / 2 + U.pixelsize / 2, - scrubbing_region_rect->ymax - box_padding, + scrub_region_rect->ymax - box_padding, 4 * UI_DPI_FAC, bg_color, 1.0f); @@ -121,36 +121,36 @@ static void draw_current_frame(const Scene *scene, UI_GetThemeColorShade4fv(TH_CFRAME, 5, bg_color); UI_draw_roundbox_aa(false, frame_x - box_width / 2 + U.pixelsize / 2, - scrubbing_region_rect->ymin + box_padding, + scrub_region_rect->ymin + box_padding, frame_x + box_width / 2 + U.pixelsize / 2, - scrubbing_region_rect->ymax - box_padding, + scrub_region_rect->ymax - box_padding, 4 * UI_DPI_FAC, bg_color); UI_fontstyle_draw_simple(fstyle, frame_x - text_width / 2 + U.pixelsize / 2, - get_centered_text_y(scrubbing_region_rect), + get_centered_text_y(scrub_region_rect), frame_str, color); } -void ED_scrubbing_draw(const ARegion *ar, - const Scene *scene, - bool display_seconds, - bool discrete_frames) +void ED_time_scrub_draw(const ARegion *ar, + const Scene *scene, + bool display_seconds, + bool discrete_frames) { const View2D *v2d = &ar->v2d; GPU_matrix_push_projection(); wmOrtho2_region_pixelspace(ar); - rcti scrubbing_region_rect; - get_scrubbing_region_rect(ar, &scrubbing_region_rect); + rcti scrub_region_rect; + get_time_scrub_region_rect(ar, &scrub_region_rect); - draw_background(&scrubbing_region_rect); + draw_background(&scrub_region_rect); - rcti numbers_rect = scrubbing_region_rect; - numbers_rect.ymin = get_centered_text_y(&scrubbing_region_rect) - 4 * UI_DPI_FAC; + rcti numbers_rect = scrub_region_rect; + numbers_rect.ymin = get_centered_text_y(&scrub_region_rect) - 4 * UI_DPI_FAC; if (discrete_frames) { UI_view2d_draw_scale_x__discrete_frames_or_seconds( ar, v2d, &numbers_rect, scene, display_seconds, TH_TEXT); @@ -160,19 +160,19 @@ void ED_scrubbing_draw(const ARegion *ar, ar, v2d, &numbers_rect, scene, display_seconds, TH_TEXT); } - draw_current_frame(scene, display_seconds, v2d, &scrubbing_region_rect, scene->r.cfra); + draw_current_frame(scene, display_seconds, v2d, &scrub_region_rect, scene->r.cfra); GPU_matrix_pop_projection(); } -bool ED_event_in_scrubbing_region(const ARegion *ar, const wmEvent *event) +bool ED_time_scrub_event_in_region(const ARegion *ar, const wmEvent *event) { rcti rect = ar->winrct; - rect.ymin = rect.ymax - UI_SCRUBBING_MARGIN_Y; + rect.ymin = rect.ymax - UI_TIME_SCRUB_MARGIN_Y; return BLI_rcti_isect_pt(&rect, event->x, event->y); } -void ED_channel_search_draw(const bContext *C, ARegion *ar, bDopeSheet *dopesheet) +void ED_time_scrub_channel_search_draw(const bContext *C, ARegion *ar, bDopeSheet *dopesheet) { GPU_matrix_push_projection(); wmOrtho2_region_pixelspace(ar); @@ -180,7 +180,7 @@ void ED_channel_search_draw(const bContext *C, ARegion *ar, bDopeSheet *dopeshee rcti rect; rect.xmin = 0; rect.xmax = ceilf(ar->sizex * UI_DPI_FAC); - rect.ymin = ar->sizey * UI_DPI_FAC - UI_SCRUBBING_MARGIN_Y; + rect.ymin = ar->sizey * UI_DPI_FAC - UI_TIME_SCRUB_MARGIN_Y; rect.ymax = ceilf(ar->sizey * UI_DPI_FAC); uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); diff --git a/source/blender/editors/curve/editcurve.c b/source/blender/editors/curve/editcurve.c index 65f502d5cd2..8d131ee28ba 100644 --- a/source/blender/editors/curve/editcurve.c +++ b/source/blender/editors/curve/editcurve.c @@ -2584,33 +2584,42 @@ void CURVE_OT_switch_direction(wmOperatorType *ot) static int set_goal_weight_exec(bContext *C, wmOperator *op) { - Object *obedit = CTX_data_edit_object(C); - ListBase *editnurb = object_editcurve_get(obedit); - Nurb *nu; - BezTriple *bezt; - BPoint *bp; - float weight = RNA_float_get(op->ptr, "weight"); - int a; + ViewLayer *view_layer = CTX_data_view_layer(C); + uint objects_len; + Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data( + view_layer, CTX_wm_view3d(C), &objects_len); - for (nu = editnurb->first; nu; nu = nu->next) { - if (nu->bezt) { - for (bezt = nu->bezt, a = 0; a < nu->pntsu; a++, bezt++) { - if (bezt->f2 & SELECT) { - bezt->weight = weight; + for (uint ob_index = 0; ob_index < objects_len; ob_index++) { + Object *obedit = objects[ob_index]; + ListBase *editnurb = object_editcurve_get(obedit); + Nurb *nu; + BezTriple *bezt; + BPoint *bp; + float weight = RNA_float_get(op->ptr, "weight"); + int a; + + for (nu = editnurb->first; nu; nu = nu->next) { + if (nu->bezt) { + for (bezt = nu->bezt, a = 0; a < nu->pntsu; a++, bezt++) { + if (bezt->f2 & SELECT) { + bezt->weight = weight; + } } } - } - else if (nu->bp) { - for (bp = nu->bp, a = 0; a < nu->pntsu * nu->pntsv; a++, bp++) { - if (bp->f1 & SELECT) { - bp->weight = weight; + else if (nu->bp) { + for (bp = nu->bp, a = 0; a < nu->pntsu * nu->pntsv; a++, bp++) { + if (bp->f1 & SELECT) { + bp->weight = weight; + } } } } + + DEG_id_tag_update(obedit->data, 0); + WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data); } - DEG_id_tag_update(obedit->data, 0); - WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data); + MEM_freeN(objects); return OPERATOR_FINISHED; } @@ -2638,33 +2647,42 @@ void CURVE_OT_spline_weight_set(wmOperatorType *ot) static int set_radius_exec(bContext *C, wmOperator *op) { - Object *obedit = CTX_data_edit_object(C); - ListBase *editnurb = object_editcurve_get(obedit); - Nurb *nu; - BezTriple *bezt; - BPoint *bp; - float radius = RNA_float_get(op->ptr, "radius"); - int a; + ViewLayer *view_layer = CTX_data_view_layer(C); + uint objects_len; + Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data( + view_layer, CTX_wm_view3d(C), &objects_len); - for (nu = editnurb->first; nu; nu = nu->next) { - if (nu->bezt) { - for (bezt = nu->bezt, a = 0; a < nu->pntsu; a++, bezt++) { - if (bezt->f2 & SELECT) { - bezt->radius = radius; + for (uint ob_index = 0; ob_index < objects_len; ob_index++) { + Object *obedit = objects[ob_index]; + ListBase *editnurb = object_editcurve_get(obedit); + Nurb *nu; + BezTriple *bezt; + BPoint *bp; + float radius = RNA_float_get(op->ptr, "radius"); + int a; + + for (nu = editnurb->first; nu; nu = nu->next) { + if (nu->bezt) { + for (bezt = nu->bezt, a = 0; a < nu->pntsu; a++, bezt++) { + if (bezt->f2 & SELECT) { + bezt->radius = radius; + } } } - } - else if (nu->bp) { - for (bp = nu->bp, a = 0; a < nu->pntsu * nu->pntsv; a++, bp++) { - if (bp->f1 & SELECT) { - bp->radius = radius; + else if (nu->bp) { + for (bp = nu->bp, a = 0; a < nu->pntsu * nu->pntsv; a++, bp++) { + if (bp->f1 & SELECT) { + bp->radius = radius; + } } } } + + WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data); + DEG_id_tag_update(obedit->data, 0); } - WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data); - DEG_id_tag_update(obedit->data, 0); + MEM_freeN(objects); return OPERATOR_FINISHED; } @@ -2743,81 +2761,90 @@ static void smooth_single_bp(BPoint *bp, static int smooth_exec(bContext *C, wmOperator *UNUSED(op)) { const float factor = 1.0f / 6.0f; - Object *obedit = CTX_data_edit_object(C); - ListBase *editnurb = object_editcurve_get(obedit); - Nurb *nu; + ViewLayer *view_layer = CTX_data_view_layer(C); + uint objects_len; + Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data( + view_layer, CTX_wm_view3d(C), &objects_len); - int a, a_end; - bool changed = false; + for (uint ob_index = 0; ob_index < objects_len; ob_index++) { + Object *obedit = objects[ob_index]; + ListBase *editnurb = object_editcurve_get(obedit); + Nurb *nu; - for (nu = editnurb->first; nu; nu = nu->next) { - if (nu->bezt) { - /* duplicate the curve to use in weight calculation */ - const BezTriple *bezt_orig = MEM_dupallocN(nu->bezt); - BezTriple *bezt; - changed = false; + int a, a_end; + bool changed = false; - /* check whether its cyclic or not, and set initial & final conditions */ - if (nu->flagu & CU_NURB_CYCLIC) { - a = 0; - a_end = nu->pntsu; - } - else { - a = 1; - a_end = nu->pntsu - 1; - } + for (nu = editnurb->first; nu; nu = nu->next) { + if (nu->bezt) { + /* duplicate the curve to use in weight calculation */ + const BezTriple *bezt_orig = MEM_dupallocN(nu->bezt); + BezTriple *bezt; + changed = false; + + /* check whether its cyclic or not, and set initial & final conditions */ + if (nu->flagu & CU_NURB_CYCLIC) { + a = 0; + a_end = nu->pntsu; + } + else { + a = 1; + a_end = nu->pntsu - 1; + } - /* for all the curve points */ - for (; a < a_end; a++) { - /* respect selection */ - bezt = &nu->bezt[a]; - if (bezt->f2 & SELECT) { - const BezTriple *bezt_orig_prev, *bezt_orig_next; + /* for all the curve points */ + for (; a < a_end; a++) { + /* respect selection */ + bezt = &nu->bezt[a]; + if (bezt->f2 & SELECT) { + const BezTriple *bezt_orig_prev, *bezt_orig_next; - bezt_orig_prev = &bezt_orig[mod_i(a - 1, nu->pntsu)]; - bezt_orig_next = &bezt_orig[mod_i(a + 1, nu->pntsu)]; + bezt_orig_prev = &bezt_orig[mod_i(a - 1, nu->pntsu)]; + bezt_orig_next = &bezt_orig[mod_i(a + 1, nu->pntsu)]; - smooth_single_bezt(bezt, bezt_orig_prev, bezt_orig_next, factor); + smooth_single_bezt(bezt, bezt_orig_prev, bezt_orig_next, factor); - changed = true; + changed = true; + } + } + MEM_freeN((void *)bezt_orig); + if (changed) { + BKE_nurb_handles_calc(nu); } } - MEM_freeN((void *)bezt_orig); - if (changed) { - BKE_nurb_handles_calc(nu); - } - } - else if (nu->bp) { - /* Same as above, keep these the same! */ - const BPoint *bp_orig = MEM_dupallocN(nu->bp); - BPoint *bp; + else if (nu->bp) { + /* Same as above, keep these the same! */ + const BPoint *bp_orig = MEM_dupallocN(nu->bp); + BPoint *bp; - if (nu->flagu & CU_NURB_CYCLIC) { - a = 0; - a_end = nu->pntsu; - } - else { - a = 1; - a_end = nu->pntsu - 1; - } + if (nu->flagu & CU_NURB_CYCLIC) { + a = 0; + a_end = nu->pntsu; + } + else { + a = 1; + a_end = nu->pntsu - 1; + } - for (; a < a_end; a++) { - bp = &nu->bp[a]; - if (bp->f1 & SELECT) { - const BPoint *bp_orig_prev, *bp_orig_next; + for (; a < a_end; a++) { + bp = &nu->bp[a]; + if (bp->f1 & SELECT) { + const BPoint *bp_orig_prev, *bp_orig_next; - bp_orig_prev = &bp_orig[mod_i(a - 1, nu->pntsu)]; - bp_orig_next = &bp_orig[mod_i(a + 1, nu->pntsu)]; + bp_orig_prev = &bp_orig[mod_i(a - 1, nu->pntsu)]; + bp_orig_next = &bp_orig[mod_i(a + 1, nu->pntsu)]; - smooth_single_bp(bp, bp_orig_prev, bp_orig_next, factor); + smooth_single_bp(bp, bp_orig_prev, bp_orig_next, factor); + } } + MEM_freeN((void *)bp_orig); } - MEM_freeN((void *)bp_orig); } + + WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data); + DEG_id_tag_update(obedit->data, 0); } - WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data); - DEG_id_tag_update(obedit->data, 0); + MEM_freeN(objects); return OPERATOR_FINISHED; } @@ -3023,13 +3050,22 @@ static void curve_smooth_value(ListBase *editnurb, const int bezt_offsetof, cons static int curve_smooth_weight_exec(bContext *C, wmOperator *UNUSED(op)) { - Object *obedit = CTX_data_edit_object(C); - ListBase *editnurb = object_editcurve_get(obedit); + ViewLayer *view_layer = CTX_data_view_layer(C); + uint objects_len; + Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data( + view_layer, CTX_wm_view3d(C), &objects_len); + + for (uint ob_index = 0; ob_index < objects_len; ob_index++) { + Object *obedit = objects[ob_index]; + ListBase *editnurb = object_editcurve_get(obedit); + + curve_smooth_value(editnurb, offsetof(BezTriple, weight), offsetof(BPoint, weight)); - curve_smooth_value(editnurb, offsetof(BezTriple, weight), offsetof(BPoint, weight)); + WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data); + DEG_id_tag_update(obedit->data, 0); + } - WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data); - DEG_id_tag_update(obedit->data, 0); + MEM_freeN(objects); return OPERATOR_FINISHED; } @@ -3051,13 +3087,22 @@ void CURVE_OT_smooth_weight(wmOperatorType *ot) static int curve_smooth_radius_exec(bContext *C, wmOperator *UNUSED(op)) { - Object *obedit = CTX_data_edit_object(C); - ListBase *editnurb = object_editcurve_get(obedit); + ViewLayer *view_layer = CTX_data_view_layer(C); + uint objects_len; + Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data( + view_layer, CTX_wm_view3d(C), &objects_len); - curve_smooth_value(editnurb, offsetof(BezTriple, radius), offsetof(BPoint, radius)); + for (uint ob_index = 0; ob_index < objects_len; ob_index++) { + Object *obedit = objects[ob_index]; + ListBase *editnurb = object_editcurve_get(obedit); - WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data); - DEG_id_tag_update(obedit->data, 0); + curve_smooth_value(editnurb, offsetof(BezTriple, radius), offsetof(BPoint, radius)); + + WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data); + DEG_id_tag_update(obedit->data, 0); + } + + MEM_freeN(objects); return OPERATOR_FINISHED; } @@ -3079,13 +3124,22 @@ void CURVE_OT_smooth_radius(wmOperatorType *ot) static int curve_smooth_tilt_exec(bContext *C, wmOperator *UNUSED(op)) { - Object *obedit = CTX_data_edit_object(C); - ListBase *editnurb = object_editcurve_get(obedit); + ViewLayer *view_layer = CTX_data_view_layer(C); + uint objects_len; + Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data( + view_layer, CTX_wm_view3d(C), &objects_len); + + for (uint ob_index = 0; ob_index < objects_len; ob_index++) { + Object *obedit = objects[ob_index]; + ListBase *editnurb = object_editcurve_get(obedit); - curve_smooth_value(editnurb, offsetof(BezTriple, tilt), offsetof(BPoint, tilt)); + curve_smooth_value(editnurb, offsetof(BezTriple, tilt), offsetof(BPoint, tilt)); + + WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data); + DEG_id_tag_update(obedit->data, 0); + } - WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data); - DEG_id_tag_update(obedit->data, 0); + MEM_freeN(objects); return OPERATOR_FINISHED; } @@ -3253,7 +3307,8 @@ static int reveal_exec(bContext *C, wmOperator *op) } if (changed) { - DEG_id_tag_update(obedit->data, ID_RECALC_COPY_ON_WRITE | ID_RECALC_SELECT); + DEG_id_tag_update(obedit->data, + ID_RECALC_COPY_ON_WRITE | ID_RECALC_SELECT | ID_RECALC_GEOMETRY); WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data); changed_multi = true; } @@ -3909,54 +3964,63 @@ static void findselectedNurbvert( static int set_spline_type_exec(bContext *C, wmOperator *op) { - Main *bmain = CTX_data_main(C); - Object *obedit = CTX_data_edit_object(C); - View3D *v3d = CTX_wm_view3d(C); - ListBase *editnurb = object_editcurve_get(obedit); - Nurb *nu; - bool changed = false; - bool changed_size = false; - const bool use_handles = RNA_boolean_get(op->ptr, "use_handles"); - const int type = RNA_enum_get(op->ptr, "type"); + ViewLayer *view_layer = CTX_data_view_layer(C); + uint objects_len; + Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data( + view_layer, CTX_wm_view3d(C), &objects_len); + int ret_value = OPERATOR_CANCELLED; - if (type == CU_CARDINAL || type == CU_BSPLINE) { - BKE_report(op->reports, RPT_ERROR, "Not yet implemented"); - return OPERATOR_CANCELLED; - } + for (uint ob_index = 0; ob_index < objects_len; ob_index++) { + Object *obedit = objects[ob_index]; + Main *bmain = CTX_data_main(C); + View3D *v3d = CTX_wm_view3d(C); + ListBase *editnurb = object_editcurve_get(obedit); + Nurb *nu; + bool changed = false; + bool changed_size = false; + const bool use_handles = RNA_boolean_get(op->ptr, "use_handles"); + const int type = RNA_enum_get(op->ptr, "type"); - for (nu = editnurb->first; nu; nu = nu->next) { - if (ED_curve_nurb_select_check(v3d, nu)) { - const int pntsu_prev = nu->pntsu; - if (BKE_nurb_type_convert(nu, type, use_handles)) { - changed = true; - if (pntsu_prev != nu->pntsu) { - changed_size = true; + if (type == CU_CARDINAL || type == CU_BSPLINE) { + BKE_report(op->reports, RPT_ERROR, "Not yet implemented"); + continue; + } + + for (nu = editnurb->first; nu; nu = nu->next) { + if (ED_curve_nurb_select_check(v3d, nu)) { + const int pntsu_prev = nu->pntsu; + if (BKE_nurb_type_convert(nu, type, use_handles)) { + changed = true; + if (pntsu_prev != nu->pntsu) { + changed_size = true; + } + } + else { + BKE_report(op->reports, RPT_ERROR, "No conversion possible"); } - } - else { - BKE_report(op->reports, RPT_ERROR, "No conversion possible"); } } - } - if (changed) { - if (ED_curve_updateAnimPaths(bmain, obedit->data)) { - WM_event_add_notifier(C, NC_OBJECT | ND_KEYS, obedit); - } + if (changed) { + if (ED_curve_updateAnimPaths(bmain, obedit->data)) { + WM_event_add_notifier(C, NC_OBJECT | ND_KEYS, obedit); + } - DEG_id_tag_update(obedit->data, 0); - WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data); + DEG_id_tag_update(obedit->data, 0); + WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data); - if (changed_size) { - Curve *cu = obedit->data; - cu->actvert = CU_ACT_NONE; - } + if (changed_size) { + Curve *cu = obedit->data; + cu->actvert = CU_ACT_NONE; + } - return OPERATOR_FINISHED; - } - else { - return OPERATOR_CANCELLED; + ret_value = OPERATOR_FINISHED; + } } + + MEM_freeN(objects); + + return ret_value; } void CURVE_OT_spline_type_set(wmOperatorType *ot) @@ -6747,31 +6811,41 @@ void CURVE_OT_decimate(wmOperatorType *ot) static int shade_smooth_exec(bContext *C, wmOperator *op) { - Object *obedit = CTX_data_edit_object(C); View3D *v3d = CTX_wm_view3d(C); - ListBase *editnurb = object_editcurve_get(obedit); - Nurb *nu; + ViewLayer *view_layer = CTX_data_view_layer(C); int clear = (STREQ(op->idname, "CURVE_OT_shade_flat")); + uint objects_len; + Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data( + view_layer, CTX_wm_view3d(C), &objects_len); + int ret_value = OPERATOR_CANCELLED; - if (obedit->type != OB_CURVE) { - return OPERATOR_CANCELLED; - } + for (uint ob_index = 0; ob_index < objects_len; ob_index++) { + Object *obedit = objects[ob_index]; + ListBase *editnurb = object_editcurve_get(obedit); - for (nu = editnurb->first; nu; nu = nu->next) { - if (ED_curve_nurb_select_check(v3d, nu)) { - if (!clear) { - nu->flag |= CU_SMOOTH; - } - else { - nu->flag &= ~CU_SMOOTH; + if (obedit->type != OB_CURVE) { + continue; + } + + for (Nurb *nu = editnurb->first; nu; nu = nu->next) { + if (ED_curve_nurb_select_check(v3d, nu)) { + if (!clear) { + nu->flag |= CU_SMOOTH; + } + else { + nu->flag &= ~CU_SMOOTH; + } } } + + WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data); + DEG_id_tag_update(obedit->data, 0); + ret_value = OPERATOR_FINISHED; } - WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data); - DEG_id_tag_update(obedit->data, 0); + MEM_freeN(objects); - return OPERATOR_FINISHED; + return ret_value; } void CURVE_OT_shade_smooth(wmOperatorType *ot) @@ -7026,7 +7100,7 @@ static int match_texture_space_exec(bContext *C, wmOperator *UNUSED(op)) int a; if (object->runtime.curve_cache == NULL) { - BKE_displist_make_curveTypes(depsgraph, scene, object, false, false, NULL); + BKE_displist_make_curveTypes(depsgraph, scene, object, false, false); } INIT_MINMAX(min, max); diff --git a/source/blender/editors/curve/editfont.c b/source/blender/editors/curve/editfont.c index 0759b64d14a..ffbfb692ca9 100644 --- a/source/blender/editors/curve/editfont.c +++ b/source/blender/editors/curve/editfont.c @@ -2007,7 +2007,7 @@ static int font_open_exec(bContext *C, wmOperator *op) id_us_min(&font->id); RNA_id_pointer_create(&font->id, &idptr); - RNA_property_pointer_set(NULL, &pprop->ptr, pprop->prop, idptr); + RNA_property_pointer_set(&pprop->ptr, pprop->prop, idptr, NULL); RNA_property_update(C, &pprop->ptr, pprop->prop); } @@ -2090,7 +2090,7 @@ static int font_unlink_exec(bContext *C, wmOperator *op) builtin_font = BKE_vfont_builtin_get(); RNA_id_pointer_create(&builtin_font->id, &idptr); - RNA_property_pointer_set(NULL, &pprop.ptr, pprop.prop, idptr); + RNA_property_pointer_set(&pprop.ptr, pprop.prop, idptr, NULL); RNA_property_update(C, &pprop.ptr, pprop.prop); return OPERATOR_FINISHED; diff --git a/source/blender/editors/datafiles/CMakeLists.txt b/source/blender/editors/datafiles/CMakeLists.txt index 316ad3f91d6..d2d0095bdb2 100644 --- a/source/blender/editors/datafiles/CMakeLists.txt +++ b/source/blender/editors/datafiles/CMakeLists.txt @@ -569,9 +569,9 @@ set(ICON_NAMES loop_forwards back forward + file_cache file_volume - alembic - volume + file_3d file_hidden file_backup disk_drive diff --git a/source/blender/editors/gpencil/gpencil_fill.c b/source/blender/editors/gpencil/gpencil_fill.c index 96f405fab2f..bf15b846bb6 100644 --- a/source/blender/editors/gpencil/gpencil_fill.c +++ b/source/blender/editors/gpencil/gpencil_fill.c @@ -401,7 +401,8 @@ static bool gp_render_offscreen(tGPDfill *tgpf) glClearColor(0.0f, 0.0f, 0.0f, 0.0f); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - ED_view3d_update_viewmat(tgpf->depsgraph, tgpf->scene, tgpf->v3d, tgpf->ar, NULL, winmat, NULL); + ED_view3d_update_viewmat( + tgpf->depsgraph, tgpf->scene, tgpf->v3d, tgpf->ar, NULL, winmat, NULL, true); /* set for opengl */ GPU_matrix_projection_set(tgpf->rv3d->winmat); GPU_matrix_set(tgpf->rv3d->viewmat); diff --git a/source/blender/editors/include/ED_anim_api.h b/source/blender/editors/include/ED_anim_api.h index cd68981dee3..7a29e6b5e66 100644 --- a/source/blender/editors/include/ED_anim_api.h +++ b/source/blender/editors/include/ED_anim_api.h @@ -404,7 +404,7 @@ typedef enum eAnimFilter_Flags { /* channel heights */ #define ACHANNEL_FIRST_TOP(ac) \ - (UI_view2d_scale_get_y(&(ac)->ar->v2d) * -UI_SCRUBBING_MARGIN_Y - ACHANNEL_SKIP) + (UI_view2d_scale_get_y(&(ac)->ar->v2d) * -UI_TIME_SCRUB_MARGIN_Y - ACHANNEL_SKIP) #define ACHANNEL_HEIGHT(ac) (0.8f * (ac)->yscale_fac * U.widget_unit) #define ACHANNEL_SKIP (0.1f * U.widget_unit) #define ACHANNEL_STEP(ac) (ACHANNEL_HEIGHT(ac) + ACHANNEL_SKIP) @@ -422,7 +422,7 @@ typedef enum eAnimFilter_Flags { /* NLA channel heights */ #define NLACHANNEL_FIRST_TOP(ac) \ - (UI_view2d_scale_get_y(&(ac)->ar->v2d) * -UI_SCRUBBING_MARGIN_Y - NLACHANNEL_SKIP) + (UI_view2d_scale_get_y(&(ac)->ar->v2d) * -UI_TIME_SCRUB_MARGIN_Y - NLACHANNEL_SKIP) #define NLACHANNEL_HEIGHT(snla) \ ((snla && (snla->flag & SNLA_NOSTRIPCURVES)) ? (0.8f * U.widget_unit) : (1.2f * U.widget_unit)) #define NLACHANNEL_SKIP (0.1f * U.widget_unit) diff --git a/source/blender/editors/include/ED_mask.h b/source/blender/editors/include/ED_mask.h index c3883de0722..3322cf0a863 100644 --- a/source/blender/editors/include/ED_mask.h +++ b/source/blender/editors/include/ED_mask.h @@ -24,6 +24,7 @@ #ifndef __ED_MASK_H__ #define __ED_MASK_H__ +struct Depsgraph; struct KeyframeEditData; struct MaskLayer; struct MaskLayerShape; @@ -55,7 +56,8 @@ void ED_operatormacros_mask(void); /* mask_draw.c */ void ED_mask_draw(const struct bContext *C, const char draw_flag, const char draw_type); -void ED_mask_draw_region(struct Mask *mask, +void ED_mask_draw_region(struct Depsgraph *depsgraph, + struct Mask *mask, struct ARegion *ar, const char draw_flag, const char draw_type, diff --git a/source/blender/editors/include/ED_mesh.h b/source/blender/editors/include/ED_mesh.h index 4e6bf7d4df5..0a8304f3f8a 100644 --- a/source/blender/editors/include/ED_mesh.h +++ b/source/blender/editors/include/ED_mesh.h @@ -152,24 +152,16 @@ struct BMElem *EDBM_select_id_bm_elem_get(struct EDBMSelectID_Context *sel_id_ct const uint sel_id, uint *r_base_index); +uint EDBM_select_id_context_offset_for_object_elem(const struct EDBMSelectID_Context *sel_id_ctx, + int base_index, + char htype); + +uint EDBM_select_id_context_elem_len(const struct EDBMSelectID_Context *sel_id_ctx); + void EDBM_select_mirrored( struct BMEditMesh *em, const int axis, const bool extend, int *r_totmirr, int *r_totfail); void EDBM_automerge(struct Scene *scene, struct Object *ob, bool update, const char hflag); -bool EDBM_backbuf_border_init( - struct ViewContext *vc, short xmin, short ymin, short xmax, short ymax); -bool EDBM_backbuf_check(unsigned int index); -void EDBM_backbuf_free(void); - -bool EDBM_backbuf_border_mask_init(struct ViewContext *vc, - const int mcords[][2], - short tot, - short xmin, - short ymin, - short xmax, - short ymax); -bool EDBM_backbuf_circle_init(struct ViewContext *vc, short xs, short ys, short rads); - struct BMVert *EDBM_vert_find_nearest_ex(struct ViewContext *vc, float *r_dist, const bool use_select_bias, @@ -249,9 +241,6 @@ void em_setup_viewcontext(struct bContext *C, struct ViewContext *vc); /* rename bool EDBM_mesh_deselect_all_multi_ex(struct Base **bases, const uint bases_len); bool EDBM_mesh_deselect_all_multi(struct bContext *C); -/* Only use for modes that don't support multi-edit-modes (painting). */ -extern unsigned int bm_vertoffs, bm_solidoffs, bm_wireoffs; - /* editmesh_preselect_edgering.c */ struct EditMesh_PreSelEdgeRing; struct EditMesh_PreSelEdgeRing *EDBM_preselect_edgering_create(void); @@ -291,7 +280,6 @@ bool paintface_mouse_select(struct bContext *C, bool extend, bool deselect, bool toggle); -bool do_paintface_box_select(struct ViewContext *vc, const struct rcti *rect, int sel_op); bool paintface_deselect_all_visible(struct bContext *C, struct Object *ob, int action, diff --git a/source/blender/editors/include/ED_select_buffer_utils.h b/source/blender/editors/include/ED_select_buffer_utils.h new file mode 100644 index 00000000000..af745cee676 --- /dev/null +++ b/source/blender/editors/include/ED_select_buffer_utils.h @@ -0,0 +1,43 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +/** \file + * \ingroup editors + */ + +#ifndef __ED_SELECT_BUFFER_UTILS_H__ +#define __ED_SELECT_BUFFER_UTILS_H__ + +struct rcti; + +/* Boolean array from selection ID's. */ +uint *ED_select_buffer_bitmap_from_rect(const uint bitmap_len, const struct rcti *rect); +uint *ED_select_buffer_bitmap_from_circle(const uint bitmap_len, + const int center[2], + const int radius); +uint *ED_select_buffer_bitmap_from_poly(const uint bitmap_len, + const int poly[][2], + const int poly_len, + const rcti *rect); + +/* Single result from selection ID's. */ +uint ED_select_buffer_sample_point(const int center[2]); +uint ED_select_buffer_find_nearest_to_point(const int center[2], + const uint id_min, + const uint id_max, + uint *dist); + +#endif /* __ED_SELECT_BUFFER_UTILS_H__ */ diff --git a/source/blender/editors/include/ED_time_scrub_ui.h b/source/blender/editors/include/ED_time_scrub_ui.h index a2e3098e949..b43e674224c 100644 --- a/source/blender/editors/include/ED_time_scrub_ui.h +++ b/source/blender/editors/include/ED_time_scrub_ui.h @@ -21,23 +21,23 @@ * \ingroup editors */ -#ifndef __ED_SCRUBBING_H__ -#define __ED_SCRUBBING_H__ +#ifndef __ED_TIME_SCRUB_UI_H__ +#define __ED_TIME_SCRUB_UI_H__ struct View2DGrid; struct bContext; struct bDopeSheet; struct wmEvent; -void ED_scrubbing_draw(const struct ARegion *ar, - const struct Scene *scene, - bool display_seconds, - bool discrete_frames); +void ED_time_scrub_draw(const struct ARegion *ar, + const struct Scene *scene, + bool display_seconds, + bool discrete_frames); -bool ED_event_in_scrubbing_region(const struct ARegion *ar, const struct wmEvent *event); +bool ED_time_scrub_event_in_region(const struct ARegion *ar, const struct wmEvent *event); -void ED_channel_search_draw(const struct bContext *C, - struct ARegion *ar, - struct bDopeSheet *dopesheet); +void ED_time_scrub_channel_search_draw(const struct bContext *C, + struct ARegion *ar, + struct bDopeSheet *dopesheet); -#endif /* __ED_SCRUBBING_H__ */ +#endif /* __ED_TIME_SCRUB_UI_H__ */ diff --git a/source/blender/editors/include/ED_view3d.h b/source/blender/editors/include/ED_view3d.h index cd4cefe8891..5ce9133a531 100644 --- a/source/blender/editors/include/ED_view3d.h +++ b/source/blender/editors/include/ED_view3d.h @@ -42,6 +42,7 @@ struct GPUFX; struct GPUFXSettings; struct GPUOffScreen; struct GPUViewport; +struct ID; struct ImBuf; struct MVert; struct Main; @@ -449,16 +450,9 @@ void ED_view3d_backbuf_depth_validate(struct ViewContext *vc); int ED_view3d_backbuf_sample_size_clamp(struct ARegion *ar, const float dist); void ED_view3d_select_id_validate(struct ViewContext *vc); -void ED_view3d_select_id_validate_with_select_mode(struct ViewContext *vc, short select_mode); -uint ED_view3d_select_id_sample(struct ViewContext *vc, int x, int y); -uint *ED_view3d_select_id_read( - struct ViewContext *vc, int xmin, int ymin, int xmax, int ymax, uint *r_buf_len); -uint *ED_view3d_select_id_read_rect(struct ViewContext *vc, - const struct rcti *rect, - uint *r_buf_len); -uint ED_view3d_select_id_read_nearest( - struct ViewContext *vc, const int mval[2], const uint min, const uint max, uint *r_dist); +uint *ED_view3d_select_id_read(int xmin, int ymin, int xmax, int ymax, uint *r_buf_len); +uint *ED_view3d_select_id_read_rect(const struct rcti *rect, uint *r_buf_len); bool ED_view3d_autodist(struct Depsgraph *depsgraph, struct ARegion *ar, @@ -590,7 +584,6 @@ struct ImBuf *ED_view3d_draw_offscreen_imbuf(struct Depsgraph *depsgraph, int sizex, int sizey, unsigned int flag, - unsigned int draw_flags, int alpha_mode, int samples, const char *viewname, @@ -621,7 +614,8 @@ void ED_view3d_update_viewmat(struct Depsgraph *depsgraph, struct ARegion *ar, float viewmat[4][4], float winmat[4][4], - const struct rcti *rect); + const struct rcti *rect, + bool offscreen); bool ED_view3d_quat_from_axis_view(const char view, float quat[4]); char ED_view3d_quat_to_axis_view(const float quat[4], const float epsilon); char ED_view3d_lock_view_from_index(int index); diff --git a/source/blender/editors/include/UI_icons.h b/source/blender/editors/include/UI_icons.h index f54e4d1c61b..048f30bdf26 100644 --- a/source/blender/editors/include/UI_icons.h +++ b/source/blender/editors/include/UI_icons.h @@ -96,8 +96,8 @@ DEF_ICON(PINNED) DEF_ICON(SCREEN_BACK) DEF_ICON(RIGHTARROW) DEF_ICON(DOWNARROW_HLT) -DEF_ICON_BLANK(103) -DEF_ICON_BLANK(104) +DEF_ICON(FCURVE_SNAPSHOT) +DEF_ICON(OBJECT_HIDDEN) DEF_ICON_BLANK(105) DEF_ICON_BLANK(106) DEF_ICON(PLUGIN) @@ -699,8 +699,8 @@ DEF_ICON(VIS_SEL_10) DEF_ICON(VIS_SEL_01) DEF_ICON(VIS_SEL_00) DEF_ICON_BLANK(231) -DEF_ICON(AUTOMERGE_ON) DEF_ICON(AUTOMERGE_OFF) +DEF_ICON(AUTOMERGE_ON) DEF_ICON_BLANK(234) DEF_ICON(UV_VERTEXSEL) DEF_ICON(UV_EDGESEL) @@ -821,9 +821,9 @@ DEF_ICON(FORWARD) DEF_ICON_BLANK(825) DEF_ICON_BLANK(826) DEF_ICON_BLANK(827) +DEF_ICON(FILE_CACHE) DEF_ICON(FILE_VOLUME) -DEF_ICON(ALEMBIC) -DEF_ICON(VOLUME) +DEF_ICON(FILE_3D) DEF_ICON(FILE_HIDDEN) DEF_ICON(FILE_BACKUP) DEF_ICON(DISK_DRIVE) diff --git a/source/blender/editors/include/UI_interface.h b/source/blender/editors/include/UI_interface.h index 14d681ee817..bf728ec7772 100644 --- a/source/blender/editors/include/UI_interface.h +++ b/source/blender/editors/include/UI_interface.h @@ -281,6 +281,9 @@ enum { /** Value is animated, but the current value differs from the animated one. */ UI_BUT_ANIMATED_CHANGED = 1 << 25, + + /* Draw the checkbox buttons inverted. */ + UI_BUT_CHECKBOX_INVERT = 1 << 26, }; /* scale fixed button widths by this to account for DPI */ @@ -1627,7 +1630,7 @@ struct Panel *UI_panel_begin(struct ScrArea *sa, struct PanelType *pt, struct Panel *pa, bool *r_open); -void UI_panel_end(uiBlock *block, int width, int height); +void UI_panel_end(uiBlock *block, int width, int height, bool open); void UI_panels_scale(struct ARegion *ar, float new_width); void UI_panel_label_offset(struct uiBlock *block, int *r_x, int *r_y); int UI_panel_size_y(const struct Panel *pa); @@ -1638,6 +1641,7 @@ struct PanelCategoryDyn *UI_panel_category_find(struct ARegion *ar, const char * struct PanelCategoryStack *UI_panel_category_active_find(struct ARegion *ar, const char *idname); const char *UI_panel_category_active_get(struct ARegion *ar, bool set_fallback); void UI_panel_category_active_set(struct ARegion *ar, const char *idname); +void UI_panel_category_active_set_default(struct ARegion *ar, const char *idname); struct PanelCategoryDyn *UI_panel_category_find_mouse_over_ex(struct ARegion *ar, const int x, const int y); @@ -1711,14 +1715,28 @@ enum { UI_ITEM_O_RETURN_PROPS = 1 << 0, UI_ITEM_R_EXPAND = 1 << 1, UI_ITEM_R_SLIDER = 1 << 2, + /** + * Use for booleans, causes the button to draw with an outline (emboss), + * instead of text with a checkbox. + * This is implied when toggle buttons have an icon + * unless #UI_ITEM_R_ICON_NEVER flag is set. + */ UI_ITEM_R_TOGGLE = 1 << 3, - UI_ITEM_R_ICON_ONLY = 1 << 4, - UI_ITEM_R_EVENT = 1 << 5, - UI_ITEM_R_FULL_EVENT = 1 << 6, - UI_ITEM_R_NO_BG = 1 << 7, - UI_ITEM_R_IMMEDIATE = 1 << 8, - UI_ITEM_O_DEPRESS = 1 << 9, - UI_ITEM_R_COMPACT = 1 << 10, + /** + * Don't attempt to use an icon when the icon is set to #ICON_NONE. + * + * Use for boolean's, causes the buttons to always show as a checkbox + * even when there is an icon (which would normally show the button as a toggle). + */ + UI_ITEM_R_ICON_NEVER = 1 << 4, + UI_ITEM_R_ICON_ONLY = 1 << 5, + UI_ITEM_R_EVENT = 1 << 6, + UI_ITEM_R_FULL_EVENT = 1 << 7, + UI_ITEM_R_NO_BG = 1 << 8, + UI_ITEM_R_IMMEDIATE = 1 << 9, + UI_ITEM_O_DEPRESS = 1 << 10, + UI_ITEM_R_COMPACT = 1 << 11, + UI_ITEM_R_CHECKBOX_INVERT = 1 << 12, }; #define UI_HEADER_OFFSET ((void)0, 0.4f * UI_UNIT_X) @@ -2233,6 +2251,7 @@ void uiItemL(uiLayout *layout, const char *name, int icon); /* label */ /* label icon for dragging */ void uiItemLDrag(uiLayout *layout, struct PointerRNA *ptr, const char *name, int icon); /* menu */ +void uiItemM_ptr(uiLayout *layout, struct MenuType *mt, const char *name, int icon); void uiItemM(uiLayout *layout, const char *menuname, const char *name, int icon); /* menu contents */ void uiItemMContents(uiLayout *layout, const char *menuname); diff --git a/source/blender/editors/include/UI_resources.h b/source/blender/editors/include/UI_resources.h index 6dc632921ad..db6bb35560d 100644 --- a/source/blender/editors/include/UI_resources.h +++ b/source/blender/editors/include/UI_resources.h @@ -105,7 +105,7 @@ typedef enum ThemeColorID { TH_FACE_DOT, TH_FACEDOT_SIZE, TH_CFRAME, - TH_SCRUBBING_BACKGROUND, + TH_TIME_SCRUB_BACKGROUND, TH_TIME_KEYFRAME, TH_TIME_GP_KEYFRAME, TH_NURB_ULINE, diff --git a/source/blender/editors/include/UI_view2d.h b/source/blender/editors/include/UI_view2d.h index d03d4b1b4f5..42ac3bb30d8 100644 --- a/source/blender/editors/include/UI_view2d.h +++ b/source/blender/editors/include/UI_view2d.h @@ -260,6 +260,6 @@ void UI_view2d_smooth_view(struct bContext *C, const int smooth_viewtx); #define UI_MARKER_MARGIN_Y (42 * UI_DPI_FAC) -#define UI_SCRUBBING_MARGIN_Y (23 * UI_DPI_FAC) +#define UI_TIME_SCRUB_MARGIN_Y (23 * UI_DPI_FAC) #endif /* __UI_VIEW2D_H__ */ diff --git a/source/blender/editors/interface/interface.c b/source/blender/editors/interface/interface.c index f1724d92402..931a4faa1c0 100644 --- a/source/blender/editors/interface/interface.c +++ b/source/blender/editors/interface/interface.c @@ -1845,6 +1845,9 @@ int ui_but_is_pushed_ex(uiBut *but, double *value) } } + if ((but->drawflag & UI_BUT_CHECKBOX_INVERT) && (is_push != -1)) { + is_push = !((bool)is_push); + } return is_push; } int ui_but_is_pushed(uiBut *but) @@ -2772,7 +2775,7 @@ bool ui_but_string_set(bContext *C, uiBut *but, const char *str) } else if (type == PROP_POINTER) { if (str[0] == '\0') { - RNA_property_pointer_set(NULL, &but->rnapoin, but->rnaprop, PointerRNA_NULL); + RNA_property_pointer_set(&but->rnapoin, but->rnaprop, PointerRNA_NULL, NULL); return true; } else { @@ -2788,14 +2791,14 @@ bool ui_but_string_set(bContext *C, uiBut *but, const char *str) * Fact remains, using editstr as main 'reference' over whole search button thingy * is utterly weak and should be redesigned imho, but that's not a simple task. */ if (prop && RNA_property_collection_lookup_string(&ptr, prop, str, &rptr)) { - RNA_property_pointer_set(NULL, &but->rnapoin, but->rnaprop, rptr); + RNA_property_pointer_set(&but->rnapoin, but->rnaprop, rptr, NULL); } else if (but->func_arg2 != NULL) { RNA_pointer_create(NULL, RNA_property_pointer_type(&but->rnapoin, but->rnaprop), but->func_arg2, &rptr); - RNA_property_pointer_set(NULL, &but->rnapoin, but->rnaprop, rptr); + RNA_property_pointer_set(&but->rnapoin, but->rnaprop, rptr, NULL); } return true; @@ -3735,6 +3738,16 @@ void ui_def_but_icon(uiBut *but, const int icon, const int flag) } } +/** + * Avoid using this where possible since it's better not to ask for an icon in the first place. + */ +void ui_def_but_icon_clear(uiBut *but) +{ + but->icon = ICON_NONE; + but->flag &= ~UI_HAS_ICON; + but->drawflag &= ~UI_BUT_ICON_LEFT; +} + static void ui_def_but_rna__disable(uiBut *but, const char *info) { but->flag |= UI_BUT_DISABLED; diff --git a/source/blender/editors/interface/interface_context_menu.c b/source/blender/editors/interface/interface_context_menu.c index 9ef98db49f5..ca35689112f 100644 --- a/source/blender/editors/interface/interface_context_menu.c +++ b/source/blender/editors/interface/interface_context_menu.c @@ -47,6 +47,8 @@ #include "RNA_access.h" +#include "BPY_extern.h" + #include "WM_api.h" #include "WM_types.h" @@ -92,7 +94,7 @@ static const char *shortcut_get_operator_property(bContext *C, uiBut *but, IDPro { if (but->optype) { /* Operator */ - *prop = (but->opptr) ? IDP_CopyProperty(but->opptr->data) : NULL; + *prop = (but->opptr && but->opptr->data) ? IDP_CopyProperty(but->opptr->data) : NULL; return but->optype->idname; } else if (but->rnaprop) { @@ -358,7 +360,31 @@ static void ui_but_user_menu_add(bContext *C, uiBut *but, bUserMenu *um) if (drawstr[0] == '\0') { /* Hard code overrides for generic operators. */ if (UI_but_is_tool(but)) { - RNA_string_get(but->opptr, "name", drawstr); + char idname[64]; + RNA_string_get(but->opptr, "name", idname); +#ifdef WITH_PYTHON + { + const char *expr_imports[] = {"bpy", "bl_ui", NULL}; + char expr[256]; + SNPRINTF(expr, + "bl_ui.space_toolsystem_common.item_from_id(" + "bpy.context, " + "bpy.context.space_data.type, " + "'%s').label", + idname); + char *expr_result = NULL; + if (BPY_execute_string_as_string(C, expr_imports, expr, true, &expr_result)) { + STRNCPY(drawstr, expr_result); + MEM_freeN(expr_result); + } + else { + BLI_assert(0); + STRNCPY(drawstr, idname); + } + } +#else + STRNCPY(drawstr, idname); +#endif } } ED_screen_user_menu_item_add_operator( diff --git a/source/blender/editors/interface/interface_eyedropper_datablock.c b/source/blender/editors/interface/interface_eyedropper_datablock.c index 4a2d59c05de..658aa4f67f9 100644 --- a/source/blender/editors/interface/interface_eyedropper_datablock.c +++ b/source/blender/editors/interface/interface_eyedropper_datablock.c @@ -207,7 +207,7 @@ static bool datadropper_id_set(bContext *C, DataDropper *ddr, ID *id) RNA_id_pointer_create(id, &ptr_value); - RNA_property_pointer_set(NULL, &ddr->ptr, ddr->prop, ptr_value); + RNA_property_pointer_set(&ddr->ptr, ddr->prop, ptr_value, NULL); RNA_property_update(C, &ddr->ptr, ddr->prop); diff --git a/source/blender/editors/interface/interface_handlers.c b/source/blender/editors/interface/interface_handlers.c index a3b438ece42..b8e97f58c2f 100644 --- a/source/blender/editors/interface/interface_handlers.c +++ b/source/blender/editors/interface/interface_handlers.c @@ -556,18 +556,9 @@ static void ui_but_update_preferences_dirty(uiBut *but) /* Not very elegant, but ensures preference changes force re-save. */ bool tag = false; if (but->rnaprop) { - if (but->rnapoin.data == &U) { - /* Exclude navigation from setting dirty. */ - extern PropertyRNA rna_Preferences_active_section; - if (!ELEM(but->rnaprop, &rna_Preferences_active_section)) { - tag = true; - } - } - else { - StructRNA *base = RNA_struct_base(but->rnapoin.type); - if (ELEM(base, &RNA_AddonPreferences, &RNA_KeyConfigPreferences)) { - tag = true; - } + StructRNA *base = RNA_struct_base(but->rnapoin.type); + if (ELEM(base, &RNA_AddonPreferences, &RNA_KeyConfigPreferences, &RNA_KeyMapItem)) { + tag = true; } } @@ -1744,7 +1735,7 @@ static void ui_selectcontext_apply(bContext *C, } else if (rna_type == PROP_POINTER) { const PointerRNA other_value = delta.p; - RNA_property_pointer_set(NULL, &lptr, lprop, other_value); + RNA_property_pointer_set(&lptr, lprop, other_value, NULL); } RNA_property_update(C, &lptr, prop); @@ -5572,9 +5563,7 @@ static int ui_do_but_COLOR(bContext *C, uiBut *but, uiHandleButtonData *data, co if ((int)(but->a1) == UI_PALETTE_COLOR) { if (!event->ctrl) { float color[3]; - Scene *scene = CTX_data_scene(C); - ViewLayer *view_layer = CTX_data_view_layer(C); - Paint *paint = BKE_paint_get_active(scene, view_layer); + Paint *paint = BKE_paint_get_active_from_context(C); Brush *brush = BKE_paint_brush(paint); if (brush->flag & BRUSH_USE_GRADIENT) { @@ -5589,6 +5578,8 @@ static int ui_do_but_COLOR(bContext *C, uiBut *but, uiHandleButtonData *data, co } } else { + Scene *scene = CTX_data_scene(C); + if (but->rnaprop && RNA_property_subtype(but->rnaprop) == PROP_COLOR_GAMMA) { RNA_property_float_get_array(&but->rnapoin, but->rnaprop, color); BKE_brush_color_set(scene, brush, color); @@ -6530,7 +6521,7 @@ static int ui_do_but_CURVE( CurveMap *cuma = cumap->cm + cumap->cur; CurveMapPoint *cmp; const float m_xy[2] = {mx, my}; - float dist_min_sq = SQUARE(14.0f); /* 14 pixels radius */ + float dist_min_sq = SQUARE(U.dpi_fac * 14.0f); /* 14 pixels radius */ int sel = -1; if (event->ctrl) { @@ -6565,7 +6556,7 @@ static int ui_do_but_CURVE( BLI_rctf_transform_pt_v(&but->rect, &cumap->curr, f_xy, &cmp[0].x); /* with 160px height 8px should translate to the old 0.05 coefficient at no zoom */ - dist_min_sq = SQUARE(8.0f); + dist_min_sq = SQUARE(U.dpi_fac * 8.0f); /* loop through the curve segment table and find what's near the mouse. */ for (i = 1; i <= CM_TABLE; i++) { diff --git a/source/blender/editors/interface/interface_icons.c b/source/blender/editors/interface/interface_icons.c index e53e9694617..fa3605269ff 100644 --- a/source/blender/editors/interface/interface_icons.c +++ b/source/blender/editors/interface/interface_icons.c @@ -1086,6 +1086,12 @@ static void free_iconfile_list(struct ListBase *list) } } +#else + +void UI_icons_reload_internal_textures(void) +{ +} + #endif /* WITH_HEADLESS */ int UI_iconfile_get_index(const char *filename) diff --git a/source/blender/editors/interface/interface_intern.h b/source/blender/editors/interface/interface_intern.h index 33288df15ba..8a2b28ee2d4 100644 --- a/source/blender/editors/interface/interface_intern.h +++ b/source/blender/editors/interface/interface_intern.h @@ -500,6 +500,7 @@ extern int ui_but_string_get_max_length(uiBut *but); extern uiBut *ui_but_drag_multi_edit_get(uiBut *but); void ui_def_but_icon(uiBut *but, const int icon, const int flag); +void ui_def_but_icon_clear(uiBut *but); extern uiButExtraIconType ui_but_icon_extra_get(uiBut *but); extern void ui_but_default_set(struct bContext *C, const bool all, const bool use_afterfunc); diff --git a/source/blender/editors/interface/interface_layout.c b/source/blender/editors/interface/interface_layout.c index dc57be4f07f..b89767171ab 100644 --- a/source/blender/editors/interface/interface_layout.c +++ b/source/blender/editors/interface/interface_layout.c @@ -484,7 +484,7 @@ static void ui_item_array(uiLayout *layout, int UNUSED(h), bool expand, bool slider, - bool toggle, + int toggle, bool icon_only, bool compact, bool show_text) @@ -691,7 +691,7 @@ static void ui_item_array(uiLayout *layout, if (slider && but->type == UI_BTYPE_NUM) { but->type = UI_BTYPE_NUM_SLIDER; } - if (toggle && but->type == UI_BTYPE_CHECKBOX) { + if ((toggle == 1) && but->type == UI_BTYPE_CHECKBOX) { but->type = UI_BTYPE_TOGGLE; } if ((a == 0) && (subtype == PROP_AXISANGLE)) { @@ -1858,12 +1858,7 @@ void uiItemFullR(uiLayout *layout, int icon) { uiBlock *block = layout->root->block; - uiBut *but = NULL; - PropertyType type; char namestr[UI_MAX_NAME_STR]; - int len, w, h; - bool slider, toggle, expand, icon_only, no_bg, compact; - bool is_array; const bool use_prop_sep = ((layout->item.flag & UI_ITEM_PROP_SEP) != 0); /* By default 'use_prop_sep' uses a separate column for labels. @@ -1888,11 +1883,15 @@ void uiItemFullR(uiLayout *layout, UI_block_layout_set_current(block, layout); /* retrieve info */ - type = RNA_property_type(prop); - is_array = RNA_property_array_check(prop); - len = (is_array) ? RNA_property_array_length(ptr, prop) : 0; + const PropertyType type = RNA_property_type(prop); + const bool is_array = RNA_property_array_check(prop); + const int len = (is_array) ? RNA_property_array_length(ptr, prop) : 0; + + const bool icon_only = (flag & UI_ITEM_R_ICON_ONLY) != 0; - icon_only = (flag & UI_ITEM_R_ICON_ONLY) != 0; + /* Boolean with -1 to signify that the value depends on the presence of an icon. */ + const int toggle = ((flag & UI_ITEM_R_TOGGLE) ? 1 : ((flag & UI_ITEM_R_ICON_NEVER) ? 0 : -1)); + const bool no_icon = (toggle == 0); /* set name and icon */ if (!name) { @@ -1904,8 +1903,8 @@ void uiItemFullR(uiLayout *layout, } } - if (icon == ICON_NONE) { - icon = RNA_property_ui_icon(prop); + if (type != PROP_BOOLEAN) { + flag &= ~UI_ITEM_R_CHECKBOX_INVERT; } if (flag & UI_ITEM_R_ICON_ONLY) { @@ -1932,56 +1931,66 @@ void uiItemFullR(uiLayout *layout, } } -#ifdef UI_PROP_SEP_ICON_WIDTH_EXCEPTION - if (use_prop_sep) { - if (type == PROP_BOOLEAN && (icon == ICON_NONE) && !icon_only) { - use_prop_sep_split_label = false; + if (no_icon == false) { + if (icon == ICON_NONE) { + icon = RNA_property_ui_icon(prop); } - } -#endif - /* menus and pie-menus don't show checkbox without this */ - if ((layout->root->type == UI_LAYOUT_MENU) || - /* use checkboxes only as a fallback in pie-menu's, when no icon is defined */ - ((layout->root->type == UI_LAYOUT_PIEMENU) && (icon == ICON_NONE))) { - int prop_flag = RNA_property_flag(prop); - if (type == PROP_BOOLEAN && ((is_array == false) || (index != RNA_NO_INDEX))) { - if (prop_flag & PROP_ICONS_CONSECUTIVE) { - icon = ICON_CHECKBOX_DEHLT; /* but->iconadd will set to correct icon */ - } - else if (is_array) { - icon = (RNA_property_boolean_get_index(ptr, prop, index)) ? ICON_CHECKBOX_HLT : - ICON_CHECKBOX_DEHLT; + /* Menus and pie-menus don't show checkbox without this. */ + if ((layout->root->type == UI_LAYOUT_MENU) || + /* Use checkboxes only as a fallback in pie-menu's, when no icon is defined. */ + ((layout->root->type == UI_LAYOUT_PIEMENU) && (icon == ICON_NONE))) { + int prop_flag = RNA_property_flag(prop); + if (type == PROP_BOOLEAN) { + if ((is_array == false) || (index != RNA_NO_INDEX)) { + if (prop_flag & PROP_ICONS_CONSECUTIVE) { + icon = ICON_CHECKBOX_DEHLT; /* but->iconadd will set to correct icon */ + } + else if (is_array) { + icon = (RNA_property_boolean_get_index(ptr, prop, index)) ? ICON_CHECKBOX_HLT : + ICON_CHECKBOX_DEHLT; + } + else { + icon = (RNA_property_boolean_get(ptr, prop)) ? ICON_CHECKBOX_HLT : ICON_CHECKBOX_DEHLT; + } + } } - else { - icon = (RNA_property_boolean_get(ptr, prop)) ? ICON_CHECKBOX_HLT : ICON_CHECKBOX_DEHLT; + else if (type == PROP_ENUM) { + if (index == RNA_ENUM_VALUE) { + int enum_value = RNA_property_enum_get(ptr, prop); + if (prop_flag & PROP_ICONS_CONSECUTIVE) { + icon = ICON_CHECKBOX_DEHLT; /* but->iconadd will set to correct icon */ + } + else if (prop_flag & PROP_ENUM_FLAG) { + icon = (enum_value & value) ? ICON_CHECKBOX_HLT : ICON_CHECKBOX_DEHLT; + } + else { + icon = (enum_value == value) ? ICON_CHECKBOX_HLT : ICON_CHECKBOX_DEHLT; + } + } } } - else if (type == PROP_ENUM && index == RNA_ENUM_VALUE) { - int enum_value = RNA_property_enum_get(ptr, prop); - if (prop_flag & PROP_ICONS_CONSECUTIVE) { - icon = ICON_CHECKBOX_DEHLT; /* but->iconadd will set to correct icon */ - } - else if (prop_flag & PROP_ENUM_FLAG) { - icon = (enum_value & value) ? ICON_CHECKBOX_HLT : ICON_CHECKBOX_DEHLT; - } - else { - icon = (enum_value == value) ? ICON_CHECKBOX_HLT : ICON_CHECKBOX_DEHLT; - } + } + +#ifdef UI_PROP_SEP_ICON_WIDTH_EXCEPTION + if (use_prop_sep) { + if (type == PROP_BOOLEAN && (icon == ICON_NONE) && !icon_only) { + use_prop_sep_split_label = false; } } +#endif if ((type == PROP_ENUM) && (RNA_property_flag(prop) & PROP_ENUM_FLAG)) { flag |= UI_ITEM_R_EXPAND; } - slider = (flag & UI_ITEM_R_SLIDER) != 0; - toggle = (flag & UI_ITEM_R_TOGGLE) != 0; - expand = (flag & UI_ITEM_R_EXPAND) != 0; - no_bg = (flag & UI_ITEM_R_NO_BG) != 0; - compact = (flag & UI_ITEM_R_COMPACT) != 0; + const bool slider = (flag & UI_ITEM_R_SLIDER) != 0; + const bool expand = (flag & UI_ITEM_R_EXPAND) != 0; + const bool no_bg = (flag & UI_ITEM_R_NO_BG) != 0; + const bool compact = (flag & UI_ITEM_R_COMPACT) != 0; /* get size */ + int w, h; ui_item_rna_size(layout, name, icon, ptr, prop, index, icon_only, compact, &w, &h); int prev_emboss = layout->emboss; @@ -1989,6 +1998,8 @@ void uiItemFullR(uiLayout *layout, layout->emboss = UI_EMBOSS_NONE; } + uiBut *but = NULL; + /* Split the label / property. */ uiLayout *layout_parent = layout; if (use_prop_sep) { @@ -2156,7 +2167,13 @@ void uiItemFullR(uiLayout *layout, but->type = UI_BTYPE_NUM_SLIDER; } - if (toggle && but->type == UI_BTYPE_CHECKBOX) { + if (flag & UI_ITEM_R_CHECKBOX_INVERT) { + if (ELEM(but->type, UI_BTYPE_CHECKBOX, UI_BTYPE_CHECKBOX_N)) { + but->drawflag |= UI_BUT_CHECKBOX_INVERT; + } + } + + if ((toggle == 1) && but->type == UI_BTYPE_CHECKBOX) { but->type = UI_BTYPE_TOGGLE; } @@ -2175,6 +2192,18 @@ void uiItemFullR(uiLayout *layout, } } + /* The resulting button may have the icon set since boolean button drawing + * is being 'helpful' and adding an icon for us. + * In this case we want the ability not to have an icon. + * + * We could pass an argument not to set the icon to begin with however this is the one case + * the functionality is needed. */ + if (but && no_icon) { + if ((icon == ICON_NONE) && (but->icon != ICON_NONE)) { + ui_def_but_icon_clear(but); + } + } + /* Mark non-embossed textfields inside a listbox. */ if (but && (block->flag & UI_BLOCK_LIST_ITEM) && (but->type == UI_BTYPE_TEXT) && (but->dt & UI_EMBOSS_NONE)) { @@ -2744,14 +2773,8 @@ static uiBut *ui_item_menu(uiLayout *layout, return but; } -void uiItemM(uiLayout *layout, const char *menuname, const char *name, int icon) +void uiItemM_ptr(uiLayout *layout, MenuType *mt, const char *name, int icon) { - MenuType *mt = WM_menutype_find(menuname, false); - if (mt == NULL) { - RNA_warning("not found %s", menuname); - return; - } - if (!name) { name = CTX_IFACE_(mt->translation_context, mt->label); } @@ -2770,6 +2793,16 @@ void uiItemM(uiLayout *layout, const char *menuname, const char *name, int icon) false); } +void uiItemM(uiLayout *layout, const char *menuname, const char *name, int icon) +{ + MenuType *mt = WM_menutype_find(menuname, false); + if (mt == NULL) { + RNA_warning("not found %s", menuname); + return; + } + uiItemM_ptr(layout, mt, name, icon); +} + void uiItemMContents(uiLayout *layout, const char *menuname) { MenuType *mt = WM_menutype_find(menuname, false); diff --git a/source/blender/editors/interface/interface_panel.c b/source/blender/editors/interface/interface_panel.c index aa7ff015bad..9c5ce0c9d2c 100644 --- a/source/blender/editors/interface/interface_panel.c +++ b/source/blender/editors/interface/interface_panel.c @@ -367,7 +367,7 @@ Panel *UI_panel_begin( return pa; } -void UI_panel_end(uiBlock *block, int width, int height) +void UI_panel_end(uiBlock *block, int width, int height, bool open) { Panel *pa = block->panel; @@ -390,21 +390,21 @@ void UI_panel_end(uiBlock *block, int width, int height) pa->sizey = height; } else { - /* check if we need to do an animation */ - if (!ELEM(width, 0, pa->sizex) || !ELEM(height, 0, pa->sizey)) { - pa->runtime_flag |= PNL_ANIM_ALIGN; - if (height != 0) { - pa->ofsy += pa->sizey - height; - } - } + int old_sizex = pa->sizex, old_sizey = pa->sizey; /* update width/height if non-zero */ if (width != 0) { pa->sizex = width; } - if (height != 0) { + if (height != 0 || open) { pa->sizey = height; } + + /* check if we need to do an animation */ + if (pa->sizex != old_sizex || pa->sizey != old_sizey) { + pa->runtime_flag |= PNL_ANIM_ALIGN; + pa->ofsy += old_sizey - pa->sizey; + } } } @@ -1676,28 +1676,7 @@ PanelCategoryStack *UI_panel_category_active_find(ARegion *ar, const char *idnam return BLI_findstring(&ar->panels_category_active, idname, offsetof(PanelCategoryStack, idname)); } -const char *UI_panel_category_active_get(ARegion *ar, bool set_fallback) -{ - PanelCategoryStack *pc_act; - - for (pc_act = ar->panels_category_active.first; pc_act; pc_act = pc_act->next) { - if (UI_panel_category_find(ar, pc_act->idname)) { - return pc_act->idname; - } - } - - if (set_fallback) { - PanelCategoryDyn *pc_dyn = ar->panels_category.first; - if (pc_dyn) { - UI_panel_category_active_set(ar, pc_dyn->idname); - return pc_dyn->idname; - } - } - - return NULL; -} - -void UI_panel_category_active_set(ARegion *ar, const char *idname) +static void ui_panel_category_active_set(ARegion *ar, const char *idname, bool fallback) { ListBase *lb = &ar->panels_category_active; PanelCategoryStack *pc_act = UI_panel_category_active_find(ar, idname); @@ -1710,7 +1689,13 @@ void UI_panel_category_active_set(ARegion *ar, const char *idname) BLI_strncpy(pc_act->idname, idname, sizeof(pc_act->idname)); } - BLI_addhead(lb, pc_act); + if (fallback) { + /* For fallbacks, add at the end so explicitly chosen categories have priority. */ + BLI_addtail(lb, pc_act); + } + else { + BLI_addhead(lb, pc_act); + } /* validate all active panels, we could do this on load, * they are harmless - but we should remove somewhere. @@ -1729,6 +1714,39 @@ void UI_panel_category_active_set(ARegion *ar, const char *idname) } } +void UI_panel_category_active_set(ARegion *ar, const char *idname) +{ + ui_panel_category_active_set(ar, idname, false); +} + +void UI_panel_category_active_set_default(ARegion *ar, const char *idname) +{ + if (!UI_panel_category_active_find(ar, idname)) { + ui_panel_category_active_set(ar, idname, true); + } +} + +const char *UI_panel_category_active_get(ARegion *ar, bool set_fallback) +{ + PanelCategoryStack *pc_act; + + for (pc_act = ar->panels_category_active.first; pc_act; pc_act = pc_act->next) { + if (UI_panel_category_find(ar, pc_act->idname)) { + return pc_act->idname; + } + } + + if (set_fallback) { + PanelCategoryDyn *pc_dyn = ar->panels_category.first; + if (pc_dyn) { + ui_panel_category_active_set(ar, pc_dyn->idname, true); + return pc_dyn->idname; + } + } + + return NULL; +} + PanelCategoryDyn *UI_panel_category_find_mouse_over_ex(ARegion *ar, const int x, const int y) { PanelCategoryDyn *ptd; diff --git a/source/blender/editors/interface/interface_region_tooltip.c b/source/blender/editors/interface/interface_region_tooltip.c index 5b205de21b8..6c780482777 100644 --- a/source/blender/editors/interface/interface_region_tooltip.c +++ b/source/blender/editors/interface/interface_region_tooltip.c @@ -883,8 +883,7 @@ static uiTooltipData *ui_tooltip_data_from_gizmo(bContext *C, wmGizmo *gz) /* Operator Actions */ { - bool use_drag = gz->drag_part != -1 && gz->highlight_part != gz->drag_part; - + const bool use_drag = gz->drag_part != -1 && gz->highlight_part != gz->drag_part; const struct { int part; const char *prefix; diff --git a/source/blender/editors/interface/interface_templates.c b/source/blender/editors/interface/interface_templates.c index 3dbfd3d2f6a..33602818fd4 100644 --- a/source/blender/editors/interface/interface_templates.c +++ b/source/blender/editors/interface/interface_templates.c @@ -298,7 +298,7 @@ static void template_ID_set_property_cb(bContext *C, void *arg_template, void *i PointerRNA idptr; RNA_id_pointer_create(item, &idptr); - RNA_property_pointer_set(NULL, &template_ui->ptr, template_ui->prop, idptr); + RNA_property_pointer_set(&template_ui->ptr, template_ui->prop, idptr, NULL); RNA_property_update(C, &template_ui->ptr, template_ui->prop); } } @@ -489,7 +489,7 @@ static void template_id_cb(bContext *C, void *arg_litem, void *arg_event) break; case UI_ID_DELETE: memset(&idptr, 0, sizeof(idptr)); - RNA_property_pointer_set(NULL, &template_ui->ptr, template_ui->prop, idptr); + RNA_property_pointer_set(&template_ui->ptr, template_ui->prop, idptr, NULL); RNA_property_update(C, &template_ui->ptr, template_ui->prop); if (id && CTX_wm_window(C)->eventstate->shift) { @@ -532,7 +532,7 @@ static void template_id_cb(bContext *C, void *arg_litem, void *arg_event) idptr = RNA_property_pointer_get(&template_ui->ptr, template_ui->prop); } } - RNA_property_pointer_set(NULL, &template_ui->ptr, template_ui->prop, idptr); + RNA_property_pointer_set(&template_ui->ptr, template_ui->prop, idptr, NULL); RNA_property_update(C, &template_ui->ptr, template_ui->prop); } break; @@ -541,7 +541,7 @@ static void template_id_cb(bContext *C, void *arg_litem, void *arg_event) BKE_override_static_free(&id->override_static); /* reassign to get get proper updates/notifiers */ idptr = RNA_property_pointer_get(&template_ui->ptr, template_ui->prop); - RNA_property_pointer_set(NULL, &template_ui->ptr, template_ui->prop, idptr); + RNA_property_pointer_set(&template_ui->ptr, template_ui->prop, idptr, NULL); RNA_property_update(C, &template_ui->ptr, template_ui->prop); } break; @@ -1455,7 +1455,7 @@ static void template_search_handle_cb(bContext *C, void *arg_template, void *ite PointerRNA item_ptr; RNA_pointer_create(NULL, type, item, &item_ptr); - RNA_property_pointer_set(NULL, &coll_search->target_ptr, coll_search->target_prop, item_ptr); + RNA_property_pointer_set(&coll_search->target_ptr, coll_search->target_prop, item_ptr, NULL); RNA_property_update(C, &coll_search->target_ptr, coll_search->target_prop); } diff --git a/source/blender/editors/interface/interface_widgets.c b/source/blender/editors/interface/interface_widgets.c index 594793371ae..71629d6297c 100644 --- a/source/blender/editors/interface/interface_widgets.c +++ b/source/blender/editors/interface/interface_widgets.c @@ -1261,7 +1261,9 @@ void UI_widgetbase_draw_cache_flush(void) (float *)g_widget_base_batch.params); GPU_batch_uniform_3fv(batch, "checkerColorAndSize", checker_params); GPU_matrix_bind(batch->interface); - GPU_batch_draw_range_ex(batch, 0, g_widget_base_batch.count, true); + GPU_batch_bind(batch); + GPU_batch_draw_advanced(batch, 0, 0, 0, g_widget_base_batch.count); + GPU_batch_program_use_end(batch); } g_widget_base_batch.count = 0; @@ -1946,9 +1948,9 @@ static void ui_text_clip_right_label(const uiFontStyle *fstyle, uiBut *but, cons } #ifdef WITH_INPUT_IME -static void widget_draw_text_ime_underline(uiFontStyle *fstyle, - uiWidgetColors *wcol, - uiBut *but, +static void widget_draw_text_ime_underline(const uiFontStyle *fstyle, + const uiWidgetColors *wcol, + const uiBut *but, const rcti *rect, const wmIMEData *ime_data, const char *drawstr) @@ -2183,7 +2185,7 @@ static void widget_draw_text(const uiFontStyle *fstyle, ELEM(but->type, UI_BTYPE_NUM, UI_BTYPE_NUM_SLIDER) && /* if we're editing or multi-drag (fake editing), then use left alignment */ (but->editstr == NULL) && (drawstr == but->drawstr)) { - drawstr_right = strchr(drawstr + but->ofs, ':'); + drawstr_right = strrchr(drawstr + but->ofs, ':'); if (drawstr_right) { drawstr_right++; drawstr_left_len = (drawstr_right - drawstr); diff --git a/source/blender/editors/interface/resources.c b/source/blender/editors/interface/resources.c index 06acf59e07c..26beb08dd28 100644 --- a/source/blender/editors/interface/resources.c +++ b/source/blender/editors/interface/resources.c @@ -309,8 +309,8 @@ const uchar *UI_ThemeGetColorPtr(bTheme *btheme, int spacetype, int colorid) case TH_GRID: cp = ts->grid; break; - case TH_SCRUBBING_BACKGROUND: - cp = ts->scrubbing_background; + case TH_TIME_SCRUB_BACKGROUND: + cp = ts->time_scrub_background; break; case TH_VIEW_OVERLAY: cp = ts->view_overlay; diff --git a/source/blender/editors/interface/view2d.c b/source/blender/editors/interface/view2d.c index f2d4faff479..36b984e229b 100644 --- a/source/blender/editors/interface/view2d.c +++ b/source/blender/editors/interface/view2d.c @@ -190,7 +190,7 @@ static void view2d_masks(View2D *v2d, bool check_scrollers, const rcti *mask_scr * also have the scrubbing area at the top. * So the scrollbar has to move down a bit. */ if (scroll & V2D_SCROLL_VERTICAL_HANDLES) { - v2d->vert.ymax -= UI_SCRUBBING_MARGIN_Y; + v2d->vert.ymax -= UI_TIME_SCRUB_MARGIN_Y; } /* horizontal scroller */ diff --git a/source/blender/editors/interface/view2d_draw.c b/source/blender/editors/interface/view2d_draw.c index 2568193ee23..43b49825219 100644 --- a/source/blender/editors/interface/view2d_draw.c +++ b/source/blender/editors/interface/view2d_draw.c @@ -53,7 +53,7 @@ /* Compute display grid resolution ********************************************************/ -#define MIN_MAJOR_LINE_DISTANCE (UI_DPI_FAC * 50) +#define MIN_MAJOR_LINE_DISTANCE (U.v2d_min_gridsize * UI_DPI_FAC) static float select_major_distance(const float *possible_distances, uint amount, @@ -267,6 +267,10 @@ static void draw_horizontal_scale_indicators(const ARegion *ar, void *to_string_data, int colorid) { + if (UI_view2d_scale_get_x(v2d) <= 0.0f) { + return; + } + GPU_matrix_push_projection(); wmOrtho2_region_pixelspace(ar); @@ -318,6 +322,10 @@ static void draw_vertical_scale_indicators(const ARegion *ar, void *to_string_data, int colorid) { + if (UI_view2d_scale_get_y(v2d) <= 0.0f) { + return; + } + GPU_matrix_push_projection(); wmOrtho2_region_pixelspace(ar); diff --git a/source/blender/editors/io/io_cache.c b/source/blender/editors/io/io_cache.c index e2b3b6aa8c6..9fdcec71cfd 100644 --- a/source/blender/editors/io/io_cache.c +++ b/source/blender/editors/io/io_cache.c @@ -108,7 +108,7 @@ static int cachefile_open_exec(bContext *C, wmOperator *op) PointerRNA idptr; RNA_id_pointer_create(&cache_file->id, &idptr); - RNA_property_pointer_set(NULL, &pprop->ptr, pprop->prop, idptr); + RNA_property_pointer_set(&pprop->ptr, pprop->prop, idptr, NULL); RNA_property_update(C, &pprop->ptr, pprop->prop); } diff --git a/source/blender/editors/io/io_collada.c b/source/blender/editors/io/io_collada.c index 9796bf89cf3..1f844961d19 100644 --- a/source/blender/editors/io/io_collada.c +++ b/source/blender/editors/io/io_collada.c @@ -81,6 +81,9 @@ static int wm_collada_export_exec(bContext *C, wmOperator *op) { char filepath[FILE_MAX]; int apply_modifiers; + int global_forward; + int global_up; + int apply_global_orientation; int export_mesh_type; int selected; int include_children; @@ -103,7 +106,8 @@ static int wm_collada_export_exec(bContext *C, wmOperator *op) int use_object_instantiation; int use_blender_profile; int sort_by_name; - int export_transformation_type; + int export_object_transformation_type; + int export_animation_transformation_type; int open_sim; int limit_precision; @@ -140,6 +144,10 @@ static int wm_collada_export_exec(bContext *C, wmOperator *op) /* Options panel */ apply_modifiers = RNA_boolean_get(op->ptr, "apply_modifiers"); export_mesh_type = RNA_enum_get(op->ptr, "export_mesh_type_selection"); + global_forward = RNA_enum_get(op->ptr, "export_global_forward_selection"); + global_up = RNA_enum_get(op->ptr, "export_global_up_selection"); + apply_global_orientation = RNA_boolean_get(op->ptr, "apply_global_orientation"); + selected = RNA_boolean_get(op->ptr, "selected"); include_children = RNA_boolean_get(op->ptr, "include_children"); include_armatures = RNA_boolean_get(op->ptr, "include_armatures"); @@ -163,9 +171,13 @@ static int wm_collada_export_exec(bContext *C, wmOperator *op) use_object_instantiation = RNA_boolean_get(op->ptr, "use_object_instantiation"); use_blender_profile = RNA_boolean_get(op->ptr, "use_blender_profile"); sort_by_name = RNA_boolean_get(op->ptr, "sort_by_name"); - export_transformation_type = RNA_enum_get(op->ptr, "export_transformation_type_selection"); - open_sim = RNA_boolean_get(op->ptr, "open_sim"); + export_object_transformation_type = RNA_enum_get(op->ptr, + "export_object_transformation_type_selection"); + export_animation_transformation_type = RNA_enum_get( + op->ptr, "export_animation_transformation_type_selection"); + + open_sim = RNA_boolean_get(op->ptr, "open_sim"); limit_precision = RNA_boolean_get(op->ptr, "limit_precision"); keep_bind_info = RNA_boolean_get(op->ptr, "keep_bind_info"); @@ -181,6 +193,10 @@ static int wm_collada_export_exec(bContext *C, wmOperator *op) export_settings.filepath = filepath; export_settings.apply_modifiers = apply_modifiers != 0; + export_settings.global_forward = global_forward; + export_settings.global_up = global_up; + export_settings.apply_global_orientation = apply_global_orientation != 0; + export_settings.export_mesh_type = export_mesh_type; export_settings.selected = selected != 0; export_settings.include_children = include_children != 0; @@ -201,23 +217,24 @@ static int wm_collada_export_exec(bContext *C, wmOperator *op) export_settings.use_object_instantiation = use_object_instantiation != 0; export_settings.use_blender_profile = use_blender_profile != 0; export_settings.sort_by_name = sort_by_name != 0; + export_settings.object_transformation_type = export_object_transformation_type; + export_settings.animation_transformation_type = export_animation_transformation_type; + export_settings.keep_smooth_curves = keep_smooth_curves != 0; - if (export_animation_type == BC_ANIMATION_EXPORT_SAMPLES) { - export_settings.export_transformation_type = export_transformation_type; - } - else { + if (export_animation_type != BC_ANIMATION_EXPORT_SAMPLES) { // When curves are exported then we can not export as matrix - export_settings.export_transformation_type = BC_TRANSFORMATION_TYPE_TRANSROTLOC; + export_settings.animation_transformation_type = BC_TRANSFORMATION_TYPE_DECOMPOSED; } - if (export_settings.export_transformation_type == BC_TRANSFORMATION_TYPE_TRANSROTLOC) { - export_settings.keep_smooth_curves = keep_smooth_curves != 0; - } - else { + if (export_settings.animation_transformation_type != BC_TRANSFORMATION_TYPE_DECOMPOSED) { // Can not export smooth curves when Matrix export is enabled. export_settings.keep_smooth_curves = false; } + if (include_animations) { + export_settings.object_transformation_type = export_settings.animation_transformation_type; + } + export_settings.open_sim = open_sim != 0; export_settings.limit_precision = limit_precision != 0; export_settings.keep_bind_info = keep_bind_info != 0; @@ -250,14 +267,15 @@ static int wm_collada_export_exec(bContext *C, wmOperator *op) static void uiCollada_exportSettings(uiLayout *layout, PointerRNA *imfptr) { - uiLayout *box, *row, *col, *split; + uiLayout *bbox, *box, *row, *col, *split; bool include_animations = RNA_boolean_get(imfptr, "include_animations"); int ui_section = RNA_enum_get(imfptr, "prop_bc_export_ui_section"); BC_export_animation_type animation_type = RNA_enum_get(imfptr, "export_animation_type_selection"); - BC_export_transformation_type transformation_type = RNA_enum_get( - imfptr, "export_transformation_type_selection"); + + BC_export_transformation_type animation_transformation_type = RNA_enum_get( + imfptr, "export_animation_transformation_type_selection"); bool sampling = animation_type == BC_ANIMATION_EXPORT_SAMPLES; @@ -272,6 +290,18 @@ static void uiCollada_exportSettings(uiLayout *layout, PointerRNA *imfptr) /* Export Data options */ /* =================== */ + bbox = uiLayoutBox(layout); + row = uiLayoutRow(bbox, false); + uiItemL(row, IFACE_("Global Orientation:"), ICON_ORIENTATION_GLOBAL); + row = uiLayoutRow(bbox, false); + uiItemR(row, imfptr, "export_global_forward_selection", 0, "", ICON_NONE); + + row = uiLayoutRow(bbox, false); + uiItemR(row, imfptr, "export_global_up_selection", 0, "", ICON_NONE); + + row = uiLayoutRow(bbox, false); + uiItemR(row, imfptr, "apply_global_orientation", 0, NULL, ICON_NONE); + row = uiLayoutRow(box, false); uiItemR(row, imfptr, "selected", 0, NULL, ICON_NONE); @@ -287,6 +317,8 @@ static void uiCollada_exportSettings(uiLayout *layout, PointerRNA *imfptr) uiItemR(row, imfptr, "include_shapekeys", 0, NULL, ICON_NONE); uiLayoutSetEnabled(row, RNA_boolean_get(imfptr, "selected")); + row = uiLayoutRow(box, false); + /* Texture options */ box = uiLayoutBox(layout); row = uiLayoutRow(box, false); @@ -304,13 +336,26 @@ static void uiCollada_exportSettings(uiLayout *layout, PointerRNA *imfptr) row = uiLayoutRow(box, false); split = uiLayoutSplit(row, 0.6f, UI_LAYOUT_ALIGN_RIGHT); + col = uiLayoutColumn(split, false); uiItemR(col, imfptr, "apply_modifiers", 0, NULL, ICON_NONE); + col = uiLayoutColumn(split, false); uiItemR(col, imfptr, "export_mesh_type_selection", 0, "", ICON_NONE); uiLayoutSetEnabled(col, RNA_boolean_get(imfptr, "apply_modifiers")); + + col = uiLayoutColumn(box, false); + uiItemR(col, imfptr, "triangulate", 1, NULL, ICON_NONE); + row = uiLayoutRow(box, false); - uiItemR(row, imfptr, "triangulate", 1, NULL, ICON_NONE); + split = uiLayoutSplit(row, 0.6f, UI_LAYOUT_ALIGN_RIGHT); + uiItemL(split, IFACE_("Transformation Type"), ICON_NONE); + if (RNA_boolean_get(imfptr, "include_animations")) { + uiItemR(split, imfptr, "export_animation_transformation_type_selection", 0, "", ICON_NONE); + } + else { + uiItemR(split, imfptr, "export_object_transformation_type_selection", 0, "", ICON_NONE); + } } else if (ui_section == BC_UI_SECTION_ARMATURE) { /* Armature options */ @@ -335,18 +380,24 @@ static void uiCollada_exportSettings(uiLayout *layout, PointerRNA *imfptr) row = uiLayoutRow(box, false); uiItemR(row, imfptr, "export_animation_type_selection", UI_ITEM_R_EXPAND, NULL, ICON_NONE); + uiLayoutSetEnabled(row, include_animations); row = uiLayoutRow(box, false); split = uiLayoutSplit(row, 0.6f, UI_LAYOUT_ALIGN_RIGHT); uiItemL(split, IFACE_("Transformation Type"), ICON_NONE); - uiItemR(split, imfptr, "export_transformation_type_selection", 0, "", ICON_NONE); - uiLayoutSetEnabled(row, animation_type == BC_ANIMATION_EXPORT_SAMPLES); + if (RNA_boolean_get(imfptr, "include_animations")) { + uiItemR(split, imfptr, "export_animation_transformation_type_selection", 0, "", ICON_NONE); + } + else { + uiItemR(split, imfptr, "export_object_transformation_type_selection", 0, "", ICON_NONE); + } + uiLayoutSetEnabled(row, include_animations && animation_type == BC_ANIMATION_EXPORT_SAMPLES); row = uiLayoutColumn(box, false); uiItemR(row, imfptr, "keep_smooth_curves", 0, NULL, ICON_NONE); uiLayoutSetEnabled(row, include_animations && - (transformation_type == BC_TRANSFORMATION_TYPE_TRANSROTLOC || + (animation_transformation_type == BC_TRANSFORMATION_TYPE_DECOMPOSED || animation_type == BC_ANIMATION_EXPORT_KEYS)); row = uiLayoutColumn(box, false); @@ -359,6 +410,7 @@ static void uiCollada_exportSettings(uiLayout *layout, PointerRNA *imfptr) row = uiLayoutColumn(box, false); uiItemR(row, imfptr, "keep_flat_curves", 0, NULL, ICON_NONE); + uiLayoutSetEnabled(row, include_animations); row = uiLayoutRow(box, false); uiItemR(row, imfptr, "include_all_actions", 0, NULL, ICON_NONE); @@ -418,17 +470,37 @@ void WM_OT_collada_export(wmOperatorType *ot) {0, NULL, 0, NULL, NULL}, }; + static const EnumPropertyItem prop_bc_export_global_forward[] = { + {BC_GLOBAL_FORWARD_X, "X", 0, "X Forward", "Global Forward is positive X Axis"}, + {BC_GLOBAL_FORWARD_Y, "Y", 0, "Y Forward", "Global Forward is positive Y Axis"}, + {BC_GLOBAL_FORWARD_Z, "Z", 0, "Z Forward", "Global Forward is positive Z Axis"}, + {BC_GLOBAL_FORWARD_MINUS_X, "-X", 0, "-X Forward", "Global Forward is negative X Axis"}, + {BC_GLOBAL_FORWARD_MINUS_Y, "-Y", 0, "-Y Forward", "Global Forward is negative Y Axis"}, + {BC_GLOBAL_FORWARD_MINUS_Z, "-Z", 0, "-Z Forward", "Global Forward is negative Z Axis"}, + {0, NULL, 0, NULL, NULL}, + }; + + static const EnumPropertyItem prop_bc_export_global_up[] = { + {BC_GLOBAL_UP_X, "X", 0, "X Up", "Global UP is positive X Axis"}, + {BC_GLOBAL_UP_Y, "Y", 0, "Y Up", "Global UP is positive Y Axis"}, + {BC_GLOBAL_UP_Z, "Z", 0, "Z Up", "Global UP is positive Z Axis"}, + {BC_GLOBAL_UP_MINUS_X, "-X", 0, "-X Up", "Global UP is negative X Axis"}, + {BC_GLOBAL_UP_MINUS_Y, "-Y", 0, "-Y Up", "Global UP is negative Y Axis"}, + {BC_GLOBAL_UP_MINUS_Z, "-Z", 0, "-Z Up", "Global UP is negative Z Axis"}, + {0, NULL, 0, NULL, NULL}, + }; + static const EnumPropertyItem prop_bc_export_transformation_type[] = { {BC_TRANSFORMATION_TYPE_MATRIX, "matrix", 0, "Matrix", - "Use <matrix> to specify transformations"}, - {BC_TRANSFORMATION_TYPE_TRANSROTLOC, - "transrotloc", + "Use <matrix> representation for exported transformations"}, + {BC_TRANSFORMATION_TYPE_DECOMPOSED, + "decomposed", 0, - "TransRotLoc", - "Use <translate>, <rotate>, <scale> to specify transformations"}, + "Decomposed", + "Use <rotate>, <translate> and <scale> representation for exported transformations"}, {0, NULL, 0, NULL, NULL}}; static const EnumPropertyItem prop_bc_export_animation_type[] = { @@ -503,6 +575,27 @@ void WM_OT_collada_export(wmOperatorType *ot) "Resolution", "Modifier resolution for export"); + RNA_def_enum(func, + "export_global_forward_selection", + prop_bc_export_global_forward, + BC_DEFAULT_FORWARD, + "Global Forward Axis", + "Global Forward axis for export"); + + RNA_def_enum(func, + "export_global_up_selection", + prop_bc_export_global_up, + BC_DEFAULT_UP, + "Global Up Axis", + "Global Up axis for export"); + + RNA_def_boolean(func, + "apply_global_orientation", + false, + "Apply Global Orientation", + "enabled: Rotate all root objects to match the global orientation " + "settings.\ndisabled: set global orientation in Collada assets"); + RNA_def_boolean(func, "selected", false, "Selection Only", "Export only selected elements"); RNA_def_boolean(func, @@ -611,21 +704,42 @@ void WM_OT_collada_export(wmOperatorType *ot) func, "sort_by_name", 0, "Sort by Object name", "Sort exported data by Object name"); RNA_def_int(func, - "export_transformation_type", + "export_object_transformation_type", + 0, + INT_MIN, + INT_MAX, + "Transform", + "Object Transformation type for translation, scale and rotation", + INT_MIN, + INT_MAX); + + RNA_def_enum(func, + "export_object_transformation_type_selection", + prop_bc_export_transformation_type, + 0, + "Transform", + "Object Transformation type for translation, scale and rotation"); + + RNA_def_int(func, + "export_animation_transformation_type", 0, INT_MIN, INT_MAX, "Transform", - "Transformation type for translation, scale and rotation", + "Transformation type for translation, scale and rotation\n" + "Note: The Animation transformation type in the Anim Tab\n" + "is always equal to the Object transformation type in the Geom tab", INT_MIN, INT_MAX); RNA_def_enum(func, - "export_transformation_type_selection", + "export_animation_transformation_type_selection", prop_bc_export_transformation_type, 0, "Transform", - "Transformation type for translation, scale and rotation"); + "Transformation type for translation, scale and rotation\n" + "Note: The Animation transformation type in the Anim Tab\n" + "is always equal to the Object transformation type in the Geom tab"); RNA_def_boolean(func, "open_sim", diff --git a/source/blender/editors/mask/mask_add.c b/source/blender/editors/mask/mask_add.c index 3c456f9e2e2..fc85eab6e66 100644 --- a/source/blender/editors/mask/mask_add.c +++ b/source/blender/editors/mask/mask_add.c @@ -29,6 +29,7 @@ #include "BKE_mask.h" #include "DEG_depsgraph.h" +#include "DEG_depsgraph_query.h" #include "DNA_scene_types.h" #include "DNA_screen_types.h" @@ -47,7 +48,7 @@ #include "mask_intern.h" /* own include */ bool ED_mask_find_nearest_diff_point(const bContext *C, - struct Mask *mask, + struct Mask *mask_orig, const float normal_co[2], int threshold, bool feather, @@ -63,7 +64,7 @@ bool ED_mask_find_nearest_diff_point(const bContext *C, ScrArea *sa = CTX_wm_area(C); ARegion *ar = CTX_wm_region(C); - MaskLayer *masklay, *point_masklay; + MaskLayer *point_masklay; MaskSpline *point_spline; MaskSplinePoint *point = NULL; float dist_best_sq = FLT_MAX, co[2]; @@ -71,31 +72,36 @@ bool ED_mask_find_nearest_diff_point(const bContext *C, float u = 0.0f; float scalex, scaley; + Depsgraph *depsgraph = CTX_data_evaluated_depsgraph(C); + Mask *mask_eval = (Mask *)DEG_get_evaluated_id(depsgraph, &mask_orig->id); + ED_mask_get_size(sa, &width, &height); ED_mask_pixelspace_factor(sa, ar, &scalex, &scaley); co[0] = normal_co[0] * scalex; co[1] = normal_co[1] * scaley; - for (masklay = mask->masklayers.first; masklay; masklay = masklay->next) { - MaskSpline *spline; - - if (masklay->restrictflag & (MASK_RESTRICT_VIEW | MASK_RESTRICT_SELECT)) { + for (MaskLayer *masklay_orig = mask_orig->masklayers.first, + *masklay_eval = mask_eval->masklayers.first; + masklay_orig != NULL; + masklay_orig = masklay_orig->next, masklay_eval = masklay_eval->next) { + if (masklay_orig->restrictflag & (MASK_RESTRICT_VIEW | MASK_RESTRICT_SELECT)) { continue; } - for (spline = masklay->splines.first; spline; spline = spline->next) { + for (MaskSpline *spline_orig = masklay_orig->splines.first, + *spline_eval = masklay_eval->splines.first; + spline_orig != NULL; + spline_orig = spline_orig->next, spline_eval = spline_eval->next) { int i; - MaskSplinePoint *cur_point; + MaskSplinePoint *cur_point_eval; - for (i = 0, cur_point = use_deform ? spline->points_deform : spline->points; - i < spline->tot_point; - i++, cur_point++) { - float *diff_points; + for (i = 0, cur_point_eval = use_deform ? spline_eval->points_deform : spline_eval->points; + i < spline_eval->tot_point; + i++, cur_point_eval++) { unsigned int tot_diff_point; - - diff_points = BKE_mask_point_segment_diff( - spline, cur_point, width, height, &tot_diff_point); + float *diff_points = BKE_mask_point_segment_diff( + spline_eval, cur_point_eval, width, height, &tot_diff_point); if (diff_points) { int j, tot_point; @@ -104,7 +110,7 @@ bool ED_mask_find_nearest_diff_point(const bContext *C, if (feather) { feather_points = BKE_mask_point_segment_feather_diff( - spline, cur_point, width, height, &tot_feather_point); + spline_eval, cur_point_eval, width, height, &tot_feather_point); points = feather_points; tot_point = tot_feather_point; @@ -130,19 +136,19 @@ bool ED_mask_find_nearest_diff_point(const bContext *C, sub_v2_v2v2(tangent, &diff_points[2 * j + 2], &diff_points[2 * j]); } - point_masklay = masklay; - point_spline = spline; - point = use_deform ? &spline->points[(cur_point - spline->points_deform)] : - cur_point; + point_masklay = masklay_orig; + point_spline = spline_orig; + point = use_deform ? + &spline_orig->points[(cur_point_eval - spline_eval->points_deform)] : + &spline_orig->points[(cur_point_eval - spline_eval->points)]; dist_best_sq = dist_sq; u = (float)j / tot_point; } } - if (feather_points) { + if (feather_points != NULL) { MEM_freeN(feather_points); } - MEM_freeN(diff_points); } } @@ -580,7 +586,6 @@ static bool add_vertex_new(const bContext *C, Mask *mask, MaskLayer *masklay, co static int add_vertex_exec(bContext *C, wmOperator *op) { - Scene *scene = CTX_data_scene(C); Mask *mask = CTX_data_edit_mask(C); MaskLayer *masklay; @@ -626,8 +631,7 @@ static int add_vertex_exec(bContext *C, wmOperator *op) BKE_mask_calc_handle_point_auto(spline, point, false); BKE_mask_calc_handle_point_auto(spline, point_other, false); - /* TODO: only update this spline */ - BKE_mask_update_display(mask, CFRA); + DEG_id_tag_update(&mask->id, ID_RECALC_GEOMETRY); WM_event_add_notifier(C, NC_MASK | NA_EDITED, mask); return OPERATOR_FINISHED; @@ -648,8 +652,7 @@ static int add_vertex_exec(bContext *C, wmOperator *op) } } - /* TODO: only update this spline */ - BKE_mask_update_display(mask, CFRA); + DEG_id_tag_update(&mask->id, ID_RECALC_GEOMETRY); return OPERATOR_FINISHED; } @@ -716,7 +719,6 @@ static int add_feather_vertex_exec(bContext *C, wmOperator *op) if (ED_mask_find_nearest_diff_point( C, mask, co, threshold, true, NULL, true, true, &masklay, &spline, &point, &u, NULL)) { - Scene *scene = CTX_data_scene(C); float w = BKE_mask_point_weight(spline, point, u); float weight_scalar = BKE_mask_point_weight_scalar(spline, point, u); @@ -726,12 +728,10 @@ static int add_feather_vertex_exec(bContext *C, wmOperator *op) BKE_mask_point_add_uw(point, u, w); - BKE_mask_update_display(mask, scene->r.cfra); + DEG_id_tag_update(&mask->id, ID_RECALC_GEOMETRY); WM_event_add_notifier(C, NC_MASK | NA_EDITED, mask); - DEG_id_tag_update(&mask->id, 0); - return OPERATOR_FINISHED; } @@ -786,7 +786,6 @@ static int create_primitive_from_points( bContext *C, wmOperator *op, const float (*points)[2], int num_points, char handle_type) { ScrArea *sa = CTX_wm_area(C); - Scene *scene = CTX_data_scene(C); Mask *mask; MaskLayer *mask_layer; MaskSpline *new_spline; @@ -848,8 +847,7 @@ static int create_primitive_from_points( } WM_event_add_notifier(C, NC_MASK | NA_EDITED, mask); - /* TODO: only update this spline */ - BKE_mask_update_display(mask, CFRA); + DEG_id_tag_update(&mask->id, ID_RECALC_GEOMETRY); return OPERATOR_FINISHED; } diff --git a/source/blender/editors/mask/mask_draw.c b/source/blender/editors/mask/mask_draw.c index 305e3a328ab..33e89b1a7c5 100644 --- a/source/blender/editors/mask/mask_draw.c +++ b/source/blender/editors/mask/mask_draw.c @@ -52,6 +52,8 @@ #include "UI_resources.h" #include "UI_view2d.h" +#include "DEG_depsgraph_query.h" + #include "mask_intern.h" /* own include */ static void mask_spline_color_get(MaskLayer *masklay, @@ -672,7 +674,8 @@ static float *mask_rasterize(Mask *mask, const int width, const int height) /* sets up the opengl context. * width, height are to match the values from ED_mask_get_size() */ void ED_mask_draw_region( - Mask *mask, + Depsgraph *depsgraph, + Mask *mask_, ARegion *ar, const char draw_flag, const char draw_type, @@ -690,6 +693,7 @@ void ED_mask_draw_region( const bContext *C) { struct View2D *v2d = &ar->v2d; + Mask *mask_eval = (Mask *)DEG_get_evaluated_id(depsgraph, &mask_->id); /* aspect always scales vertically in movie and image spaces */ const float width = width_i, height = (float)height_i * (aspy / aspx); @@ -735,7 +739,7 @@ void ED_mask_draw_region( if (draw_flag & MASK_DRAWFLAG_OVERLAY) { float red[4] = {1.0f, 0.0f, 0.0f, 0.0f}; - float *buffer = mask_rasterize(mask, width, height); + float *buffer = mask_rasterize(mask_eval, width, height); if (overlay_mode != MASK_OVERLAY_ALPHACHANNEL) { /* More blending types could be supported in the future. */ @@ -779,7 +783,7 @@ void ED_mask_draw_region( } /* draw! */ - draw_masklays(C, mask, draw_flag, draw_type, width, height); + draw_masklays(C, mask_eval, draw_flag, draw_type, width, height); if (do_draw_cb) { ED_region_draw_cb_draw(C, ar, REGION_DRAW_POST_VIEW); diff --git a/source/blender/editors/mask/mask_ops.c b/source/blender/editors/mask/mask_ops.c index 1f825c0bb31..5a7a84dbbc8 100644 --- a/source/blender/editors/mask/mask_ops.c +++ b/source/blender/editors/mask/mask_ops.c @@ -31,6 +31,7 @@ #include "BKE_mask.h" #include "DEG_depsgraph.h" +#include "DEG_depsgraph_query.h" #include "DNA_scene_types.h" #include "DNA_mask_types.h" @@ -65,7 +66,7 @@ static void mask_point_scaled_handle(/*const*/ MaskSplinePoint *point, } MaskSplinePoint *ED_mask_point_find_nearest(const bContext *C, - Mask *mask, + Mask *mask_orig, const float normal_co[2], const float threshold, MaskLayer **masklay_r, @@ -76,7 +77,6 @@ MaskSplinePoint *ED_mask_point_find_nearest(const bContext *C, ScrArea *sa = CTX_wm_area(C); ARegion *ar = CTX_wm_region(C); - MaskLayer *masklay; MaskLayer *point_masklay = NULL; MaskSpline *point_spline = NULL; MaskSplinePoint *point = NULL; @@ -86,29 +86,35 @@ MaskSplinePoint *ED_mask_point_find_nearest(const bContext *C, eMaskWhichHandle which_handle = MASK_WHICH_HANDLE_NONE; int width, height; + Depsgraph *depsgraph = CTX_data_evaluated_depsgraph(C); + Mask *mask_eval = (Mask *)DEG_get_evaluated_id(depsgraph, &mask_orig->id); + ED_mask_get_size(sa, &width, &height); ED_mask_pixelspace_factor(sa, ar, &scalex, &scaley); co[0] = normal_co[0] * scalex; co[1] = normal_co[1] * scaley; - for (masklay = mask->masklayers.first; masklay; masklay = masklay->next) { - MaskSpline *spline; + for (MaskLayer *masklay_orig = mask_orig->masklayers.first, + *masklay_eval = mask_eval->masklayers.first; + masklay_orig != NULL; + masklay_orig = masklay_orig->next, masklay_eval = masklay_eval->next) { - if (masklay->restrictflag & (MASK_RESTRICT_VIEW | MASK_RESTRICT_SELECT)) { + if (masklay_orig->restrictflag & (MASK_RESTRICT_VIEW | MASK_RESTRICT_SELECT)) { continue; } - for (spline = masklay->splines.first; spline; spline = spline->next) { - MaskSplinePoint *points_array = BKE_mask_spline_point_array(spline); - - int i; + for (MaskSpline *spline_orig = masklay_orig->splines.first, + *spline_eval = masklay_eval->splines.first; + spline_orig != NULL; + spline_orig = spline_orig->next, spline_eval = spline_eval->next) { + MaskSplinePoint *points_array = BKE_mask_spline_point_array(spline_eval); - for (i = 0; i < spline->tot_point; i++) { - MaskSplinePoint *cur_point = &spline->points[i]; - MaskSplinePoint *cur_point_deform = &points_array[i]; + for (int i = 0; i < spline_orig->tot_point; i++) { + MaskSplinePoint *cur_point_orig = &spline_orig->points[i]; + MaskSplinePoint *cur_point_deform_eval = &points_array[i]; eMaskWhichHandle cur_which_handle = MASK_WHICH_HANDLE_NONE; - BezTriple *bezt = &cur_point_deform->bezt; + BezTriple *bezt = &cur_point_deform_eval->bezt; float cur_len_sq, vec[2]; vec[0] = bezt->vec[1][0] * scalex; @@ -117,17 +123,17 @@ MaskSplinePoint *ED_mask_point_find_nearest(const bContext *C, cur_len_sq = len_squared_v2v2(co, vec); if (cur_len_sq < len_sq) { - point_spline = spline; - point_masklay = masklay; - point = cur_point; + point_spline = spline_orig; + point_masklay = masklay_orig; + point = cur_point_orig; len_sq = cur_len_sq; which_handle = MASK_WHICH_HANDLE_NONE; } - if (BKE_mask_point_handles_mode_get(cur_point_deform) == MASK_HANDLE_MODE_STICK) { + if (BKE_mask_point_handles_mode_get(cur_point_deform_eval) == MASK_HANDLE_MODE_STICK) { float handle[2]; mask_point_scaled_handle( - cur_point_deform, MASK_WHICH_HANDLE_STICK, scalex, scaley, handle); + cur_point_deform_eval, MASK_WHICH_HANDLE_STICK, scalex, scaley, handle); cur_len_sq = len_squared_v2v2(co, handle); cur_which_handle = MASK_WHICH_HANDLE_STICK; } @@ -135,9 +141,9 @@ MaskSplinePoint *ED_mask_point_find_nearest(const bContext *C, float handle_left[2], handle_right[2]; float len_left_sq, len_right_sq; mask_point_scaled_handle( - cur_point_deform, MASK_WHICH_HANDLE_LEFT, scalex, scaley, handle_left); + cur_point_deform_eval, MASK_WHICH_HANDLE_LEFT, scalex, scaley, handle_left); mask_point_scaled_handle( - cur_point_deform, MASK_WHICH_HANDLE_RIGHT, scalex, scaley, handle_right); + cur_point_deform_eval, MASK_WHICH_HANDLE_RIGHT, scalex, scaley, handle_right); len_left_sq = len_squared_v2v2(co, handle_left); len_right_sq = len_squared_v2v2(co, handle_right); @@ -168,9 +174,9 @@ MaskSplinePoint *ED_mask_point_find_nearest(const bContext *C, } if (cur_len_sq <= len_sq && cur_which_handle != MASK_WHICH_HANDLE_NONE) { - point_masklay = masklay; - point_spline = spline; - point = cur_point; + point_masklay = masklay_orig; + point_spline = spline_orig; + point = cur_point_orig; len_sq = cur_len_sq; which_handle = cur_which_handle; } @@ -214,7 +220,7 @@ MaskSplinePoint *ED_mask_point_find_nearest(const bContext *C, } bool ED_mask_feather_find_nearest(const bContext *C, - Mask *mask, + Mask *mask_orig, const float normal_co[2], const float threshold, MaskLayer **masklay_r, @@ -226,7 +232,7 @@ bool ED_mask_feather_find_nearest(const bContext *C, ScrArea *sa = CTX_wm_area(C); ARegion *ar = CTX_wm_region(C); - MaskLayer *masklay, *point_masklay = NULL; + MaskLayer *point_masklay = NULL; MaskSpline *point_spline = NULL; MaskSplinePoint *point = NULL; MaskSplinePointUW *uw = NULL; @@ -235,32 +241,41 @@ bool ED_mask_feather_find_nearest(const bContext *C, float scalex, scaley; int width, height; + Depsgraph *depsgraph = CTX_data_evaluated_depsgraph(C); + Mask *mask_eval = (Mask *)DEG_get_evaluated_id(depsgraph, &mask_orig->id); + ED_mask_get_size(sa, &width, &height); ED_mask_pixelspace_factor(sa, ar, &scalex, &scaley); co[0] = normal_co[0] * scalex; co[1] = normal_co[1] * scaley; - for (masklay = mask->masklayers.first; masklay; masklay = masklay->next) { - MaskSpline *spline; + for (MaskLayer *masklay_orig = mask_orig->masklayers.first, + *masklay_eval = mask_eval->masklayers.first; + masklay_orig != NULL; + masklay_orig = masklay_orig->next, masklay_eval = masklay_eval->next) { - for (spline = masklay->splines.first; spline; spline = spline->next) { + for (MaskSpline *spline_orig = masklay_orig->splines.first, + *spline_eval = masklay_eval->splines.first; + spline_orig != NULL; + spline_orig = spline_orig->next, spline_eval = spline_eval->next) { // MaskSplinePoint *points_array = BKE_mask_spline_point_array(spline); int i, tot_feather_point; float(*feather_points)[2], (*fp)[2]; - if (masklay->restrictflag & (MASK_RESTRICT_VIEW | MASK_RESTRICT_SELECT)) { + if (masklay_orig->restrictflag & (MASK_RESTRICT_VIEW | MASK_RESTRICT_SELECT)) { continue; } - feather_points = fp = BKE_mask_spline_feather_points(spline, &tot_feather_point); + feather_points = fp = BKE_mask_spline_feather_points(spline_eval, &tot_feather_point); - for (i = 0; i < spline->tot_point; i++) { + for (i = 0; i < spline_orig->tot_point; i++) { int j; - MaskSplinePoint *cur_point = &spline->points[i]; + MaskSplinePoint *cur_point_orig = &spline_orig->points[i]; + MaskSplinePoint *cur_point_eval = &spline_eval->points[i]; - for (j = 0; j <= cur_point->tot_uw; j++) { + for (j = 0; j <= cur_point_eval->tot_uw; j++) { float cur_len_sq, vec[2]; vec[0] = (*fp)[0] * scalex; @@ -273,12 +288,12 @@ bool ED_mask_feather_find_nearest(const bContext *C, uw = NULL; } else { - uw = &cur_point->uw[j - 1]; + uw = &cur_point_eval->uw[j - 1]; } - point_masklay = masklay; - point_spline = spline; - point = cur_point; + point_masklay = masklay_orig; + point_spline = spline_orig; + point = cur_point_orig; len = cur_len_sq; } @@ -1648,7 +1663,6 @@ static void delete_feather_points(MaskSplinePoint *point) static int delete_exec(bContext *C, wmOperator *UNUSED(op)) { - Scene *scene = CTX_data_scene(C); Mask *mask = CTX_data_edit_mask(C); MaskLayer *masklay; bool changed = false; @@ -1743,8 +1757,7 @@ static int delete_exec(bContext *C, wmOperator *UNUSED(op)) return OPERATOR_CANCELLED; } - /* TODO: only update edited splines */ - BKE_mask_update_display(mask, CFRA); + DEG_id_tag_update(&mask->id, ID_RECALC_GEOMETRY); WM_event_add_notifier(C, NC_MASK | NA_EDITED, mask); @@ -1801,8 +1814,7 @@ static int mask_switch_direction_exec(bContext *C, wmOperator *UNUSED(op)) } if (changed) { - /* TODO: only update this spline */ - BKE_mask_update_display(mask, CFRA); + DEG_id_tag_update(&mask->id, ID_RECALC_GEOMETRY); WM_event_add_notifier(C, NC_MASK | ND_SELECT, mask); WM_event_add_notifier(C, NC_MASK | NA_EDITED, mask); @@ -1867,8 +1879,7 @@ static int mask_normals_make_consistent_exec(bContext *C, wmOperator *UNUSED(op) } if (changed) { - /* TODO: only update this spline */ - BKE_mask_update_display(mask, CFRA); + DEG_id_tag_update(&mask->id, ID_RECALC_GEOMETRY); WM_event_add_notifier(C, NC_MASK | ND_SELECT, mask); WM_event_add_notifier(C, NC_MASK | NA_EDITED, mask); @@ -2094,7 +2105,6 @@ void MASK_OT_hide_view_set(wmOperatorType *ot) static int mask_feather_weight_clear_exec(bContext *C, wmOperator *UNUSED(op)) { - Scene *scene = CTX_data_scene(C); Mask *mask = CTX_data_edit_mask(C); MaskLayer *masklay; bool changed = false; @@ -2121,8 +2131,7 @@ static int mask_feather_weight_clear_exec(bContext *C, wmOperator *UNUSED(op)) } if (changed) { - /* TODO: only update edited splines */ - BKE_mask_update_display(mask, CFRA); + DEG_id_tag_update(&mask->id, ID_RECALC_GEOMETRY); WM_event_add_notifier(C, NC_MASK | ND_DRAW, mask); DEG_id_tag_update(&mask->id, 0); @@ -2234,7 +2243,6 @@ void MASK_OT_layer_move(wmOperatorType *ot) static int mask_duplicate_exec(bContext *C, wmOperator *UNUSED(op)) { - Scene *scene = CTX_data_scene(C); Mask *mask = CTX_data_edit_mask(C); MaskLayer *mask_layer; @@ -2324,8 +2332,7 @@ static int mask_duplicate_exec(bContext *C, wmOperator *UNUSED(op)) } } - /* TODO: only update edited splines */ - BKE_mask_update_display(mask, CFRA); + DEG_id_tag_update(&mask->id, ID_RECALC_GEOMETRY); WM_event_add_notifier(C, NC_MASK | NA_EDITED, mask); @@ -2391,7 +2398,6 @@ static bool paste_splines_poll(bContext *C) static int paste_splines_exec(bContext *C, wmOperator *UNUSED(op)) { - Scene *scene = CTX_data_scene(C); Mask *mask = CTX_data_edit_mask(C); MaskLayer *mask_layer = BKE_mask_layer_active(mask); @@ -2401,8 +2407,7 @@ static int paste_splines_exec(bContext *C, wmOperator *UNUSED(op)) BKE_mask_clipboard_paste_to_layer(CTX_data_main(C), mask_layer); - /* TODO: only update edited splines */ - BKE_mask_update_display(mask, CFRA); + DEG_id_tag_update(&mask->id, ID_RECALC_GEOMETRY); WM_event_add_notifier(C, NC_MASK | NA_EDITED, mask); diff --git a/source/blender/editors/mask/mask_select.c b/source/blender/editors/mask/mask_select.c index a592f39d24b..717ce9fd72e 100644 --- a/source/blender/editors/mask/mask_select.c +++ b/source/blender/editors/mask/mask_select.c @@ -43,6 +43,8 @@ #include "RNA_access.h" #include "RNA_define.h" +#include "DEG_depsgraph.h" + #include "mask_intern.h" /* own include */ /* -------------------------------------------------------------------- */ @@ -223,6 +225,7 @@ static int select_all_exec(bContext *C, wmOperator *op) ED_mask_select_toggle_all(mask, action); ED_mask_select_flush_all(mask); + DEG_id_tag_update(&mask->id, ID_RECALC_SELECT); WM_event_add_notifier(C, NC_MASK | ND_SELECT, mask); return OPERATOR_FINISHED; @@ -326,6 +329,7 @@ static int select_exec(bContext *C, wmOperator *op) ED_mask_select_flush_all(mask); + DEG_id_tag_update(&mask->id, ID_RECALC_SELECT); WM_event_add_notifier(C, NC_MASK | ND_SELECT, mask); return OPERATOR_FINISHED; @@ -365,6 +369,7 @@ static int select_exec(bContext *C, wmOperator *op) ED_mask_select_flush_all(mask); + DEG_id_tag_update(&mask->id, ID_RECALC_SELECT); WM_event_add_notifier(C, NC_MASK | ND_SELECT, mask); return OPERATOR_FINISHED; @@ -374,6 +379,7 @@ static int select_exec(bContext *C, wmOperator *op) ED_mask_select_flush_all(mask); + DEG_id_tag_update(&mask->id, ID_RECALC_SELECT); WM_event_add_notifier(C, NC_MASK | ND_SELECT, mask); return OPERATOR_FINISHED; @@ -488,6 +494,7 @@ static int box_select_exec(bContext *C, wmOperator *op) if (changed) { ED_mask_select_flush_all(mask); + DEG_id_tag_update(&mask->id, ID_RECALC_SELECT); WM_event_add_notifier(C, NC_MASK | ND_SELECT, mask); return OPERATOR_FINISHED; @@ -592,6 +599,7 @@ static bool do_lasso_select_mask(bContext *C, if (changed) { ED_mask_select_flush_all(mask); + DEG_id_tag_update(&mask->id, ID_RECALC_SELECT); WM_event_add_notifier(C, NC_MASK | ND_SELECT, mask); } @@ -719,6 +727,7 @@ static int circle_select_exec(bContext *C, wmOperator *op) if (changed) { ED_mask_select_flush_all(mask); + DEG_id_tag_update(&mask->id, ID_RECALC_SELECT); WM_event_add_notifier(C, NC_MASK | ND_SELECT, mask); return OPERATOR_FINISHED; @@ -783,6 +792,7 @@ static int mask_select_linked_pick_invoke(bContext *C, wmOperator *op, const wmE if (changed) { ED_mask_select_flush_all(mask); + DEG_id_tag_update(&mask->id, ID_RECALC_SELECT); WM_event_add_notifier(C, NC_MASK | ND_SELECT, mask); return OPERATOR_FINISHED; @@ -840,6 +850,7 @@ static int mask_select_linked_exec(bContext *C, wmOperator *UNUSED(op)) if (changed) { ED_mask_select_flush_all(mask); + DEG_id_tag_update(&mask->id, ID_RECALC_SELECT); WM_event_add_notifier(C, NC_MASK | ND_SELECT, mask); return OPERATOR_FINISHED; @@ -940,6 +951,7 @@ static int mask_select_more_less(bContext *C, bool more) } } + DEG_id_tag_update(&mask->id, ID_RECALC_SELECT); WM_event_add_notifier(C, NC_MASK | ND_SELECT, mask); return OPERATOR_FINISHED; diff --git a/source/blender/editors/mesh/editface.c b/source/blender/editors/mesh/editface.c index fdbcc3449b2..d61c340f7a2 100644 --- a/source/blender/editors/mesh/editface.c +++ b/source/blender/editors/mesh/editface.c @@ -441,74 +441,6 @@ bool paintface_mouse_select( return true; } -bool do_paintface_box_select(ViewContext *vc, const rcti *rect, int sel_op) -{ - Object *ob = vc->obact; - Mesh *me; - - me = BKE_mesh_from_object(ob); - if ((me == NULL) || (me->totpoly == 0)) { - return false; - } - - bool changed = false; - if (SEL_OP_USE_PRE_DESELECT(sel_op)) { - changed |= paintface_deselect_all_visible(vc->C, vc->obact, SEL_DESELECT, false); - } - - if (BLI_rcti_is_empty(rect)) { - /* pass */ - } - else { - MPoly *mpoly; - uint *rt, *buf, buf_len; - int a, index; - - char *selar = MEM_callocN(me->totpoly + 1, "selar"); - - ED_view3d_select_id_validate(vc); - buf = ED_view3d_select_id_read_rect(vc, rect, &buf_len); - - rt = buf; - - a = buf_len; - while (a--) { - if (*rt) { - index = *rt; - if (index <= me->totpoly) { - selar[index] = 1; - } - } - rt++; - } - - mpoly = me->mpoly; - for (a = 1; a <= me->totpoly; a++, mpoly++) { - if ((mpoly->flag & ME_HIDE) == 0) { - const bool is_select = mpoly->flag & ME_FACE_SEL; - const bool is_inside = (selar[a] != 0); - const int sel_op_result = ED_select_op_action_deselected(sel_op, is_select, is_inside); - if (sel_op_result != -1) { - SET_FLAG_FROM_TEST(mpoly->flag, sel_op_result, ME_FACE_SEL); - changed = true; - } - } - } - - MEM_freeN(buf); - MEM_freeN(selar); - -#ifdef __APPLE__ - glReadBuffer(GL_BACK); -#endif - } - - if (changed) { - paintface_flush_flags(vc->C, vc->obact, SELECT); - } - return changed; -} - /* (similar to void paintface_flush_flags(Object *ob)) * copy the vertex flags, most importantly selection from the mesh to the final derived mesh, * use in object mode when selecting vertices (while painting) */ diff --git a/source/blender/editors/mesh/editmesh_bisect.c b/source/blender/editors/mesh/editmesh_bisect.c index bc60ff9274f..1d173d8e396 100644 --- a/source/blender/editors/mesh/editmesh_bisect.c +++ b/source/blender/editors/mesh/editmesh_bisect.c @@ -148,7 +148,7 @@ static int mesh_bisect_invoke(bContext *C, wmOperator *op, const wmEvent *event) BisectData *opdata; opdata = MEM_mallocN(sizeof(BisectData), "inset_operator_data"); - gesture->userdata = opdata; + gesture->user_data.data = opdata; opdata->backup_len = objects_len; opdata->backup = MEM_callocN(sizeof(*opdata->backup) * objects_len, __func__); @@ -193,7 +193,7 @@ static void edbm_bisect_exit(bContext *C, BisectData *opdata) static int mesh_bisect_modal(bContext *C, wmOperator *op, const wmEvent *event) { wmGesture *gesture = op->customdata; - BisectData *opdata = gesture->userdata; + BisectData *opdata = gesture->user_data.data; BisectData opdata_back = *opdata; /* annoyance, WM_gesture_straightline_modal, frees */ int ret; @@ -276,7 +276,7 @@ static int mesh_bisect_exec(bContext *C, wmOperator *op) } wmGesture *gesture = op->customdata; - BisectData *opdata = (gesture != NULL) ? gesture->userdata : NULL; + BisectData *opdata = (gesture != NULL) ? gesture->user_data.data : NULL; /* -------------------------------------------------------------------- */ /* Modal support */ diff --git a/source/blender/editors/mesh/editmesh_extrude_spin_gizmo.c b/source/blender/editors/mesh/editmesh_extrude_spin_gizmo.c index 269ead7b23f..74700e59e99 100644 --- a/source/blender/editors/mesh/editmesh_extrude_spin_gizmo.c +++ b/source/blender/editors/mesh/editmesh_extrude_spin_gizmo.c @@ -295,7 +295,8 @@ static void gizmo_mesh_spin_init_draw_prepare(const bContext *C, wmGizmoGroup *g static void gizmo_mesh_spin_init_invoke_prepare(const bContext *UNUSED(C), wmGizmoGroup *gzgroup, - wmGizmo *gz) + wmGizmo *gz, + const wmEvent *UNUSED(event)) { /* Set the initial ortho axis. */ GizmoGroupData_SpinInit *ggd = gzgroup->customdata; diff --git a/source/blender/editors/mesh/editmesh_knife.c b/source/blender/editors/mesh/editmesh_knife.c index e45c15b3e53..976dbe01a22 100644 --- a/source/blender/editors/mesh/editmesh_knife.c +++ b/source/blender/editors/mesh/editmesh_knife.c @@ -1156,19 +1156,20 @@ static void knifetool_draw(const bContext *UNUSED(C), ARegion *UNUSED(ar), void GPUBatch *batch = GPU_batch_create_ex(GPU_PRIM_POINTS, vert, NULL, GPU_BATCH_OWNS_VBO); GPU_batch_program_set_builtin(batch, GPU_SHADER_3D_UNIFORM_COLOR); + GPU_batch_bind(batch); /* draw any snapped verts first */ rgba_uchar_to_float(fcol, kcd->colors.point_a); GPU_batch_uniform_4fv(batch, "color", fcol); GPU_matrix_bind(batch->interface); GPU_point_size(11); - GPU_batch_draw_range_ex(batch, 0, v - 1, false); + GPU_batch_draw_advanced(batch, 0, v - 1, 0, 0); /* now draw the rest */ rgba_uchar_to_float(fcol, kcd->colors.curpoint_a); GPU_batch_uniform_4fv(batch, "color", fcol); GPU_point_size(7); - GPU_batch_draw_range_ex(batch, vs + 1, kcd->totlinehit - (vs + 1), false); + GPU_batch_draw_advanced(batch, vs + 1, kcd->totlinehit - (vs + 1), 0, 0); GPU_batch_program_use_end(batch); GPU_batch_discard(batch); diff --git a/source/blender/editors/mesh/editmesh_path.c b/source/blender/editors/mesh/editmesh_path.c index f8ec4334427..6fd0ee83b6c 100644 --- a/source/blender/editors/mesh/editmesh_path.c +++ b/source/blender/editors/mesh/editmesh_path.c @@ -63,6 +63,15 @@ /** \name Path Select Struct & Properties * \{ */ +enum { + EDGE_MODE_SELECT = 0, + EDGE_MODE_TAG_SEAM = 1, + EDGE_MODE_TAG_SHARP = 2, + EDGE_MODE_TAG_CREASE = 3, + EDGE_MODE_TAG_BEVEL = 4, + EDGE_MODE_TAG_FREESTYLE = 5, +}; + struct PathSelectParams { /** ensure the active element is the last selected item (handy for picking) */ bool track_active; @@ -75,6 +84,23 @@ struct PathSelectParams { static void path_select_properties(wmOperatorType *ot) { + static const EnumPropertyItem edge_tag_items[] = { + {EDGE_MODE_SELECT, "SELECT", 0, "Select", ""}, + {EDGE_MODE_TAG_SEAM, "SEAM", 0, "Tag Seam", ""}, + {EDGE_MODE_TAG_SHARP, "SHARP", 0, "Tag Sharp", ""}, + {EDGE_MODE_TAG_CREASE, "CREASE", 0, "Tag Crease", ""}, + {EDGE_MODE_TAG_BEVEL, "BEVEL", 0, "Tag Bevel", ""}, + {EDGE_MODE_TAG_FREESTYLE, "FREESTYLE", 0, "Tag Freestyle Edge Mark", ""}, + {0, NULL, 0, NULL, NULL}, + }; + + RNA_def_enum(ot->srna, + "edge_mode", + edge_tag_items, + EDGE_MODE_SELECT, + "Edge Tag", + "The edge flag to tag when selecting the shortest path"); + RNA_def_boolean(ot->srna, "use_face_step", false, @@ -93,9 +119,24 @@ static void path_select_properties(wmOperatorType *ot) WM_operator_properties_checker_interval(ot, true); } -static void path_select_params_from_op(wmOperator *op, struct PathSelectParams *op_params) +static void path_select_params_from_op(wmOperator *op, + ToolSettings *ts, + struct PathSelectParams *op_params) { - op_params->edge_mode = EDGE_MODE_SELECT; + { + PropertyRNA *prop = RNA_struct_find_property(op->ptr, "edge_mode"); + if (RNA_property_is_set(op->ptr, prop)) { + op_params->edge_mode = RNA_property_enum_get(op->ptr, prop); + if (op->flag & OP_IS_INVOKE) { + ts->edge_mode = op_params->edge_mode; + } + } + else { + op_params->edge_mode = ts->edge_mode; + RNA_property_enum_set(op->ptr, prop, op_params->edge_mode); + } + } + op_params->track_active = false; op_params->use_face_step = RNA_boolean_get(op->ptr, "use_face_step"); op_params->use_fill = RNA_boolean_get(op->ptr, "use_fill"); @@ -103,6 +144,21 @@ static void path_select_params_from_op(wmOperator *op, struct PathSelectParams * WM_operator_properties_checker_interval_from_op(op, &op_params->interval_params); } +static bool path_select_poll_property(const bContext *C, + wmOperator *UNUSED(op), + const PropertyRNA *prop) +{ + const char *prop_id = RNA_property_identifier(prop); + if (STREQ(prop_id, "edge_mode")) { + const Scene *scene = CTX_data_scene(C); + ToolSettings *ts = scene->toolsettings; + if ((ts->selectmode & SCE_SELECT_EDGE) == 0) { + return false; + } + } + return true; +} + struct UserData { BMesh *bm; Mesh *me; @@ -319,7 +375,7 @@ static void edgetag_ensure_cd_flag(Mesh *me, const char edge_mode) /* mesh shortest path select, uses prev-selected edge */ /* since you want to create paths with multiple selects, it doesn't have extend option */ -static void mouse_mesh_shortest_path_edge(Scene *UNUSED(scene), +static void mouse_mesh_shortest_path_edge(Scene *scene, Object *obedit, const struct PathSelectParams *op_params, BMEdge *e_act, @@ -421,6 +477,10 @@ static void mouse_mesh_shortest_path_edge(Scene *UNUSED(scene), } EDBM_update_generic(em, false, false); + + if (op_params->edge_mode == EDGE_MODE_TAG_SEAM) { + ED_uvedit_live_unwrap(scene, &obedit, 1); + } } /** \} */ @@ -649,12 +709,14 @@ static int edbm_shortest_path_pick_invoke(bContext *C, wmOperator *op, const wmE return OPERATOR_FINISHED; } + struct PathSelectParams op_params; + path_select_params_from_op(op, vc.scene->toolsettings, &op_params); + BMElem *ele_src, *ele_dst; if (!(ele_src = edbm_elem_active_elem_or_face_get(em->bm)) || !(ele_dst = edbm_elem_find_nearest(&vc, ele_src->head.htype))) { /* special case, toggle edge tags even when we don't have a path */ - if (((em->selectmode & SCE_SELECT_EDGE) && - (vc.scene->toolsettings->edge_mode != EDGE_MODE_SELECT)) && + if (((em->selectmode & SCE_SELECT_EDGE) && (op_params.edge_mode != EDGE_MODE_SELECT)) && /* check if we only have a destination edge */ ((ele_src == NULL) && (ele_dst = edbm_elem_find_nearest(&vc, BM_EDGE)))) { ele_src = ele_dst; @@ -665,11 +727,7 @@ static int edbm_shortest_path_pick_invoke(bContext *C, wmOperator *op, const wmE } } - struct PathSelectParams op_params; - - path_select_params_from_op(op, &op_params); op_params.track_active = track_active; - op_params.edge_mode = vc.scene->toolsettings->edge_mode; if (!edbm_shortest_path_pick_ex(vc.scene, vc.obedit, &op_params, ele_src, ele_dst)) { return OPERATOR_PASS_THROUGH; @@ -707,9 +765,8 @@ static int edbm_shortest_path_pick_exec(bContext *C, wmOperator *op) } struct PathSelectParams op_params; - path_select_params_from_op(op, &op_params); + path_select_params_from_op(op, scene->toolsettings, &op_params); op_params.track_active = true; - op_params.edge_mode = scene->toolsettings->edge_mode; if (!edbm_shortest_path_pick_ex(scene, obedit, &op_params, ele_src, ele_dst)) { return OPERATOR_CANCELLED; @@ -731,6 +788,7 @@ void MESH_OT_shortest_path_pick(wmOperatorType *ot) ot->invoke = edbm_shortest_path_pick_invoke; ot->exec = edbm_shortest_path_pick_exec; ot->poll = ED_operator_editmesh_region_view3d; + ot->poll_property = path_select_poll_property; /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; @@ -832,7 +890,7 @@ static int edbm_shortest_path_select_exec(bContext *C, wmOperator *op) if (ele_src && ele_dst) { struct PathSelectParams op_params; - path_select_params_from_op(op, &op_params); + path_select_params_from_op(op, scene->toolsettings, &op_params); edbm_shortest_path_pick_ex(scene, obedit, &op_params, ele_src, ele_dst); @@ -860,6 +918,7 @@ void MESH_OT_shortest_path_select(wmOperatorType *ot) /* api callbacks */ ot->exec = edbm_shortest_path_select_exec; ot->poll = ED_operator_editmesh; + ot->poll_property = path_select_poll_property; /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; diff --git a/source/blender/editors/mesh/editmesh_select.c b/source/blender/editors/mesh/editmesh_select.c index 485d855e18e..6a91fcb8327 100644 --- a/source/blender/editors/mesh/editmesh_select.c +++ b/source/blender/editors/mesh/editmesh_select.c @@ -53,6 +53,7 @@ #include "ED_mesh.h" #include "ED_screen.h" #include "ED_transform.h" +#include "ED_select_buffer_utils.h" #include "ED_select_utils.h" #include "ED_view3d.h" @@ -199,8 +200,19 @@ void EDBM_automerge(Scene *scene, Object *obedit, bool update, const char hflag) * \{ */ struct EDBMBaseOffset { - uint face; - uint edge; + /* For convenience only. */ + union { + uint offset; + uint face_start; + }; + union { + uint face; + uint edge_start; + }; + union { + uint edge; + uint vert_start; + }; uint vert; }; @@ -209,18 +221,21 @@ struct EDBMSelectID_Context { /** Borrow from caller (not freed). */ struct Base **bases; uint bases_len; + /** Total number of items `base_array_index_offsets[bases_len - 1].vert`. */ + uint base_array_index_len; }; static bool check_ob_drawface_dot(short select_mode, const View3D *v3d, char dt) { if (select_mode & SCE_SELECT_FACE) { - if (dt < OB_SOLID) { + if ((dt < OB_SOLID) || XRAY_FLAG_ENABLED(v3d)) { return true; } if (v3d->overlay.edit_flag & V3D_OVERLAY_EDIT_FACE_DOT) { return true; } - if (XRAY_FLAG_ENABLED(v3d)) { + if ((v3d->overlay.edit_flag & V3D_OVERLAY_EDIT_EDGES) == 0) { + /* Since we can't deduce face selection when edges aren't visible - show dots. */ return true; } } @@ -234,7 +249,7 @@ static void edbm_select_pick_draw_bases(struct EDBMSelectID_Context *sel_id_ctx, Scene *scene_eval = (Scene *)DEG_get_evaluated_id(vc->depsgraph, &vc->scene->id); DRW_framebuffer_select_id_setup(vc->ar, true); - uint offset = 0; + uint offset = 1; for (uint base_index = 0; base_index < sel_id_ctx->bases_len; base_index++) { Object *ob_eval = DEG_get_evaluated_object(vc->depsgraph, sel_id_ctx->bases[base_index]->object); @@ -252,9 +267,12 @@ static void edbm_select_pick_draw_bases(struct EDBMSelectID_Context *sel_id_ctx, &base_ofs->edge, &base_ofs->face); + base_ofs->offset = offset; offset = base_ofs->vert; } + sel_id_ctx->base_array_index_len = offset; + DRW_framebuffer_select_id_release(vc->ar); } @@ -262,28 +280,26 @@ BMElem *EDBM_select_id_bm_elem_get(struct EDBMSelectID_Context *sel_id_ctx, const uint sel_id, uint *r_base_index) { - char elem_type; + char elem_type = 0; uint elem_id; - uint prev_offs = 0; uint base_index = 0; for (; base_index < sel_id_ctx->bases_len; base_index++) { struct EDBMBaseOffset *base_ofs = &sel_id_ctx->base_array_index_offsets[base_index]; if (base_ofs->face > sel_id) { - elem_id = sel_id - (prev_offs + 1); + elem_id = sel_id - base_ofs->face_start; elem_type = BM_FACE; break; } if (base_ofs->edge > sel_id) { - elem_id = sel_id - base_ofs->face; + elem_id = sel_id - base_ofs->edge_start; elem_type = BM_EDGE; break; } if (base_ofs->vert > sel_id) { - elem_id = sel_id - base_ofs->edge; + elem_id = sel_id - base_ofs->vert_start; elem_type = BM_VERT; break; } - prev_offs = base_ofs->vert; } if (r_base_index) { @@ -306,9 +322,32 @@ BMElem *EDBM_select_id_bm_elem_get(struct EDBMSelectID_Context *sel_id_ctx, } } +uint EDBM_select_id_context_offset_for_object_elem(const struct EDBMSelectID_Context *sel_id_ctx, + int base_index, + char htype) +{ + struct EDBMBaseOffset *base_ofs = &sel_id_ctx->base_array_index_offsets[base_index]; + if (htype == BM_VERT) { + return base_ofs->vert_start - 1; + } + if (htype == BM_EDGE) { + return base_ofs->edge_start - 1; + } + if (htype == BM_FACE) { + return base_ofs->face_start - 1; + } + BLI_assert(0); + return 0; +} + +uint EDBM_select_id_context_elem_len(const struct EDBMSelectID_Context *sel_id_ctx) +{ + return sel_id_ctx->base_array_index_len; +} + struct EDBMSelectID_Context *EDBM_select_id_context_create(ViewContext *vc, Base **bases, - uint bases_len, + const uint bases_len, short select_mode) { struct EDBMSelectID_Context *sel_id_ctx = MEM_mallocN(sizeof(*sel_id_ctx), __func__); @@ -328,192 +367,6 @@ void EDBM_select_id_context_destroy(struct EDBMSelectID_Context *sel_id_ctx) MEM_freeN(sel_id_ctx); } -/* set in view3d_draw_legacy.c ... for colorindices */ -unsigned int bm_solidoffs = 0, bm_wireoffs = 0, bm_vertoffs = 0; - -/* facilities for box select and circle select */ -static BLI_bitmap *selbuf = NULL; - -static BLI_bitmap *edbm_backbuf_alloc(const int size) -{ - return BLI_BITMAP_NEW(size, "selbuf"); -} - -/* reads rect, and builds selection array for quick lookup */ -/* returns if all is OK */ -bool EDBM_backbuf_border_init(ViewContext *vc, short xmin, short ymin, short xmax, short ymax) -{ - uint *buf, *dr, buf_len; - - if (vc->obedit == NULL || XRAY_FLAG_ENABLED(vc->v3d)) { - return false; - } - - ED_view3d_select_id_validate(vc); - buf = ED_view3d_select_id_read(vc, xmin, ymin, xmax, ymax, &buf_len); - if ((buf == NULL) || (bm_vertoffs == 0)) { - return false; - } - - dr = buf; - - /* build selection lookup */ - selbuf = edbm_backbuf_alloc(bm_vertoffs + 1); - - while (buf_len--) { - if (*dr > 0 && *dr <= bm_vertoffs) { - BLI_BITMAP_ENABLE(selbuf, *dr); - } - dr++; - } - MEM_freeN(buf); - return true; -} - -bool EDBM_backbuf_check(unsigned int index) -{ - /* odd logic, if selbuf is NULL we assume no zbuf-selection is enabled - * and just ignore the depth buffer, this is error prone since its possible - * code doesn't set the depth buffer by accident, but leave for now. - Campbell */ - if (selbuf == NULL) { - return true; - } - - if (index > 0 && index <= bm_vertoffs) { - return BLI_BITMAP_TEST_BOOL(selbuf, index); - } - - return false; -} - -void EDBM_backbuf_free(void) -{ - if (selbuf) { - MEM_freeN(selbuf); - } - selbuf = NULL; -} - -struct LassoMaskData { - unsigned int *px; - int width; -}; - -static void edbm_mask_lasso_px_cb(int x, int x_end, int y, void *user_data) -{ - struct LassoMaskData *data = user_data; - unsigned int *px = &data->px[(y * data->width) + x]; - do { - *px = true; - px++; - } while (++x != x_end); -} - -/* mcords is a polygon mask - * - grab backbuffer, - * - draw with black in backbuffer, - * - grab again and compare - * returns 'OK' - */ -bool EDBM_backbuf_border_mask_init(ViewContext *vc, - const int mcords[][2], - short tot, - short xmin, - short ymin, - short xmax, - short ymax) -{ - uint *buf, *dr, *dr_mask, *dr_mask_arr, buf_len; - struct LassoMaskData lasso_mask_data; - - /* method in use for face selecting too */ - if (vc->obedit == NULL) { - if (!BKE_paint_select_elem_test(vc->obact)) { - return false; - } - } - else if (XRAY_FLAG_ENABLED(vc->v3d)) { - return false; - } - - ED_view3d_select_id_validate(vc); - buf = ED_view3d_select_id_read(vc, xmin, ymin, xmax, ymax, &buf_len); - if ((buf == NULL) || (bm_vertoffs == 0)) { - return false; - } - - dr = buf; - - dr_mask = dr_mask_arr = MEM_callocN(sizeof(*dr_mask) * buf_len, __func__); - lasso_mask_data.px = dr_mask; - lasso_mask_data.width = (xmax - xmin) + 1; - - BLI_bitmap_draw_2d_poly_v2i_n( - xmin, ymin, xmax + 1, ymax + 1, mcords, tot, edbm_mask_lasso_px_cb, &lasso_mask_data); - - /* build selection lookup */ - selbuf = edbm_backbuf_alloc(bm_vertoffs + 1); - - while (buf_len--) { - if (*dr > 0 && *dr <= bm_vertoffs && *dr_mask == true) { - BLI_BITMAP_ENABLE(selbuf, *dr); - } - dr++; - dr_mask++; - } - MEM_freeN(buf); - MEM_freeN(dr_mask_arr); - - return true; -} - -/* circle shaped sample area */ -bool EDBM_backbuf_circle_init(ViewContext *vc, short xs, short ys, short rads) -{ - uint *buf, *dr; - short xmin, ymin, xmax, ymax, xc, yc; - int radsq; - - /* method in use for face selecting too */ - if (vc->obedit == NULL) { - if (!BKE_paint_select_elem_test(vc->obact)) { - return false; - } - } - else if (XRAY_FLAG_ENABLED(vc->v3d)) { - return false; - } - - xmin = xs - rads; - xmax = xs + rads; - ymin = ys - rads; - ymax = ys + rads; - - ED_view3d_select_id_validate(vc); - buf = ED_view3d_select_id_read(vc, xmin, ymin, xmax, ymax, NULL); - if ((buf == NULL) || (bm_vertoffs == 0)) { - return false; - } - - dr = buf; - - /* build selection lookup */ - selbuf = edbm_backbuf_alloc(bm_vertoffs + 1); - radsq = rads * rads; - for (yc = -rads; yc <= rads; yc++) { - for (xc = -rads; xc <= rads; xc++, dr++) { - if (xc * xc + yc * yc < radsq) { - if (*dr > 0 && *dr <= bm_vertoffs) { - BLI_BITMAP_ENABLE(selbuf, *dr); - } - } - } - } - - MEM_freeN(buf); - return true; -} - /** \} */ /* -------------------------------------------------------------------- */ @@ -625,7 +478,7 @@ BMVert *EDBM_vert_find_nearest_ex(ViewContext *vc, struct EDBMSelectID_Context *sel_id_ctx = EDBM_select_id_context_create( vc, bases, bases_len, select_mode); - index = ED_view3d_select_id_read_nearest(vc, vc->mval, 1, UINT_MAX, &dist_px); + index = ED_select_buffer_find_nearest_to_point(vc->mval, 1, UINT_MAX, &dist_px); if (index) { eve = (BMVert *)EDBM_select_id_bm_elem_get(sel_id_ctx, index, &base_index); @@ -652,7 +505,7 @@ BMVert *EDBM_vert_find_nearest_ex(ViewContext *vc, } else { struct NearestVertUserData data = {{0}}; - const struct NearestVertUserData_Hit *hit; + const struct NearestVertUserData_Hit *hit = NULL; const eV3DProjTest clip_flag = V3D_PROJ_TEST_CLIP_DEFAULT; BMesh *prev_select_bm = NULL; @@ -697,6 +550,10 @@ BMVert *EDBM_vert_find_nearest_ex(ViewContext *vc, } } + if (hit == NULL) { + return NULL; + } + prev_select.index = hit->index; prev_select.elem = hit->vert; prev_select.bm = prev_select_bm; @@ -850,7 +707,7 @@ BMEdge *EDBM_edge_find_nearest_ex(ViewContext *vc, struct EDBMSelectID_Context *sel_id_ctx = EDBM_select_id_context_create( vc, bases, bases_len, select_mode); - index = ED_view3d_select_id_read_nearest(vc, vc->mval, 1, UINT_MAX, &dist_px); + index = ED_select_buffer_find_nearest_to_point(vc->mval, 1, UINT_MAX, &dist_px); if (index) { eed = (BMEdge *)EDBM_select_id_bm_elem_get(sel_id_ctx, index, &base_index); @@ -899,7 +756,7 @@ BMEdge *EDBM_edge_find_nearest_ex(ViewContext *vc, } else { struct NearestEdgeUserData data = {{0}}; - const struct NearestEdgeUserData_Hit *hit; + const struct NearestEdgeUserData_Hit *hit = NULL; /* interpolate along the edge before doing a clipping plane test */ const eV3DProjTest clip_flag = V3D_PROJ_TEST_CLIP_DEFAULT & ~V3D_PROJ_TEST_CLIP_BB; BMesh *prev_select_bm = NULL; @@ -946,6 +803,10 @@ BMEdge *EDBM_edge_find_nearest_ex(ViewContext *vc, } } + if (hit == NULL) { + return NULL; + } + if (r_dist_center) { *r_dist_center = hit->dist_center; } @@ -1059,7 +920,7 @@ BMFace *EDBM_face_find_nearest_ex(ViewContext *vc, struct EDBMSelectID_Context *sel_id_ctx = EDBM_select_id_context_create( vc, bases, bases_len, select_mode); - index = ED_view3d_select_id_sample(vc, vc->mval[0], vc->mval[1]); + index = ED_select_buffer_sample_point(vc->mval); if (index) { efa = (BMFace *)EDBM_select_id_bm_elem_get(sel_id_ctx, index, &base_index); @@ -1108,7 +969,7 @@ BMFace *EDBM_face_find_nearest_ex(ViewContext *vc, } else { struct NearestFaceUserData data = {{0}}; - const struct NearestFaceUserData_Hit *hit; + const struct NearestFaceUserData_Hit *hit = NULL; const eV3DProjTest clip_flag = V3D_PROJ_TEST_CLIP_DEFAULT; BMesh *prev_select_bm = NULL; @@ -1153,6 +1014,10 @@ BMFace *EDBM_face_find_nearest_ex(ViewContext *vc, } } + if (hit == NULL) { + return NULL; + } + if (r_dist_center) { *r_dist_center = hit->dist; } diff --git a/source/blender/editors/mesh/editmesh_tools.c b/source/blender/editors/mesh/editmesh_tools.c index 331be744932..60c6994eb2e 100644 --- a/source/blender/editors/mesh/editmesh_tools.c +++ b/source/blender/editors/mesh/editmesh_tools.c @@ -7688,6 +7688,7 @@ static int point_normals_init(bContext *C, wmOperator *op, const wmEvent *UNUSED BMEditMesh *em = BKE_editmesh_from_object(obedit); BMesh *bm = em->bm; + BKE_editmesh_ensure_autosmooth(em); BKE_editmesh_lnorspace_update(em); BMLoopNorEditDataArray *lnors_ed_arr = BM_loop_normal_editdata_array_init(bm); @@ -8077,7 +8078,7 @@ void MESH_OT_point_normals(struct wmOperatorType *ot) ot->exec = edbm_point_normals_exec; ot->invoke = edbm_point_normals_invoke; ot->modal = edbm_point_normals_modal; - ot->poll = ED_operator_editmesh_auto_smooth; + ot->poll = ED_operator_editmesh; ot->ui = edbm_point_normals_ui; ot->cancel = point_normals_free; @@ -8243,6 +8244,7 @@ static int normals_split_merge(bContext *C, const bool do_merge) BMEdge *e; BMIter eiter; + BKE_editmesh_ensure_autosmooth(em); BKE_editmesh_lnorspace_update(em); BMLoopNorEditDataArray *lnors_ed_arr = do_merge ? BM_loop_normal_editdata_array_init(bm) : NULL; @@ -8288,7 +8290,7 @@ void MESH_OT_merge_normals(struct wmOperatorType *ot) /* api callbacks */ ot->exec = edbm_merge_normals_exec; - ot->poll = ED_operator_editmesh_auto_smooth; + ot->poll = ED_operator_editmesh; /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; @@ -8308,7 +8310,7 @@ void MESH_OT_split_normals(struct wmOperatorType *ot) /* api callbacks */ ot->exec = edbm_split_normals_exec; - ot->poll = ED_operator_editmesh_auto_smooth; + ot->poll = ED_operator_editmesh; /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; @@ -8346,6 +8348,7 @@ static int edbm_average_normals_exec(bContext *C, wmOperator *op) BMLoop *l, *l_curr, *l_first; BMIter fiter; + BKE_editmesh_ensure_autosmooth(em); bm->spacearr_dirty |= BM_SPACEARR_DIRTY_ALL; BKE_editmesh_lnorspace_update(em); @@ -8506,7 +8509,7 @@ void MESH_OT_average_normals(struct wmOperatorType *ot) /* api callbacks */ ot->exec = edbm_average_normals_exec; - ot->poll = ED_operator_editmesh_auto_smooth; + ot->poll = ED_operator_editmesh; ot->ui = edbm_average_normals_ui; /* flags */ @@ -8569,6 +8572,7 @@ static int edbm_normals_tools_exec(bContext *C, wmOperator *op) const int mode = RNA_enum_get(op->ptr, "mode"); const bool absolute = RNA_boolean_get(op->ptr, "absolute"); + BKE_editmesh_ensure_autosmooth(em); BKE_editmesh_lnorspace_update(em); BMLoopNorEditDataArray *lnors_ed_arr = BM_loop_normal_editdata_array_init(bm); BMLoopNorEditData *lnor_ed = lnors_ed_arr->lnor_editdata; @@ -8725,7 +8729,7 @@ void MESH_OT_normals_tools(struct wmOperatorType *ot) /* api callbacks */ ot->exec = edbm_normals_tools_exec; - ot->poll = ED_operator_editmesh_auto_smooth; + ot->poll = ED_operator_editmesh; ot->ui = edbm_normals_tools_ui; /* flags */ @@ -8765,6 +8769,7 @@ static int edbm_set_normals_from_faces_exec(bContext *C, wmOperator *op) const bool keep_sharp = RNA_boolean_get(op->ptr, "keep_sharp"); + BKE_editmesh_ensure_autosmooth(em); BKE_editmesh_lnorspace_update(em); float(*vnors)[3] = MEM_callocN(sizeof(*vnors) * bm->totvert, __func__); @@ -8830,6 +8835,7 @@ static int edbm_set_normals_from_faces_exec(bContext *C, wmOperator *op) MEM_freeN(vnors); EDBM_update_generic(em, true, false); } + MEM_freeN(objects); return OPERATOR_FINISHED; } @@ -8843,7 +8849,7 @@ void MESH_OT_set_normals_from_faces(struct wmOperatorType *ot) /* api callbacks */ ot->exec = edbm_set_normals_from_faces_exec; - ot->poll = ED_operator_editmesh_auto_smooth; + ot->poll = ED_operator_editmesh; /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; @@ -8860,6 +8866,7 @@ static int edbm_smoothen_normals_exec(bContext *C, wmOperator *op) BMLoop *l; BMIter fiter, liter; + BKE_editmesh_ensure_autosmooth(em); BKE_editmesh_lnorspace_update(em); BMLoopNorEditDataArray *lnors_ed_arr = BM_loop_normal_editdata_array_init(bm); @@ -8935,7 +8942,7 @@ void MESH_OT_smoothen_normals(struct wmOperatorType *ot) /* api callbacks */ ot->exec = edbm_smoothen_normals_exec; - ot->poll = ED_operator_editmesh_auto_smooth; + ot->poll = ED_operator_editmesh; /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; @@ -9018,7 +9025,7 @@ void MESH_OT_mod_weighted_strength(struct wmOperatorType *ot) /* api callbacks */ ot->exec = edbm_mod_weighted_strength_exec; - ot->poll = ED_operator_editmesh_auto_smooth; + ot->poll = ED_operator_editmesh; /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; diff --git a/source/blender/editors/mesh/meshtools.c b/source/blender/editors/mesh/meshtools.c index e29cfa6b6e0..41736fb9a14 100644 --- a/source/blender/editors/mesh/meshtools.c +++ b/source/blender/editors/mesh/meshtools.c @@ -61,6 +61,7 @@ #include "DEG_depsgraph_query.h" #include "ED_mesh.h" +#include "ED_select_buffer_utils.h" #include "ED_object.h" #include "ED_view3d.h" @@ -1114,11 +1115,11 @@ bool ED_mesh_pick_face(bContext *C, Object *ob, const int mval[2], uint dist_px, if (dist_px) { /* sample rect to increase chances of selecting, so that when clicking * on an edge in the backbuf, we can still select a face */ - *r_index = ED_view3d_select_id_read_nearest(&vc, mval, 1, me->totpoly + 1, &dist_px); + *r_index = ED_select_buffer_find_nearest_to_point(mval, 1, me->totpoly + 1, &dist_px); } else { /* sample only on the exact position */ - *r_index = ED_view3d_select_id_sample(&vc, mval[0], mval[1]); + *r_index = ED_select_buffer_sample_point(mval); } if ((*r_index) == 0 || (*r_index) > (unsigned int)me->totpoly) { @@ -1295,11 +1296,11 @@ bool ED_mesh_pick_vert( if (dist_px > 0) { /* sample rect to increase chances of selecting, so that when clicking * on an face in the backbuf, we can still select a vert */ - *r_index = ED_view3d_select_id_read_nearest(&vc, mval, 1, me->totvert + 1, &dist_px); + *r_index = ED_select_buffer_find_nearest_to_point(mval, 1, me->totvert + 1, &dist_px); } else { /* sample only on the exact position */ - *r_index = ED_view3d_select_id_sample(&vc, mval[0], mval[1]); + *r_index = ED_select_buffer_sample_point(mval); } if ((*r_index) == 0 || (*r_index) > (uint)me->totvert) { diff --git a/source/blender/editors/object/object_add.c b/source/blender/editors/object/object_add.c index 293b3a57fdb..dc2a353bd86 100644 --- a/source/blender/editors/object/object_add.c +++ b/source/blender/editors/object/object_add.c @@ -1962,7 +1962,7 @@ static void convert_ensure_curve_cache(Depsgraph *depsgraph, Scene *scene, Objec if (ELEM(ob->type, OB_SURF, OB_CURVE, OB_FONT)) { /* We need 'for render' ON here, to enable computing bevel dipslist if needed. * Also makes sense anyway, we would not want e.g. to loose hidden parts etc. */ - BKE_displist_make_curveTypes(depsgraph, scene, ob, true, false, NULL); + BKE_displist_make_curveTypes(depsgraph, scene, ob, true, false); } else if (ob->type == OB_MBALL) { BKE_displist_make_mball(depsgraph, scene, ob); @@ -1970,13 +1970,30 @@ static void convert_ensure_curve_cache(Depsgraph *depsgraph, Scene *scene, Objec } } -static void curvetomesh(Main *bmain, Depsgraph *depsgraph, Scene *scene, Object *ob) +static void curvetomesh(Main *bmain, Depsgraph *depsgraph, Object *ob) { - convert_ensure_curve_cache(depsgraph, scene, ob); - BKE_mesh_from_nurbs(bmain, ob); /* also does users */ + Object *object_eval = DEG_get_evaluated_object(depsgraph, ob); + Curve *curve = ob->data; + Mesh *mesh = BKE_mesh_new_from_object_to_bmain(bmain, depsgraph, object_eval, true); + BKE_object_free_modifiers(ob, 0); + /* Replace curve used by the object itself. */ + ob->data = mesh; + ob->type = OB_MESH; + id_us_min(&curve->id); + id_us_plus(&mesh->id); + /* Change objects which are using same curve. + * A bit annoying, but: + * - It's possible to have multiple curve objects selected which are sharing the same curve + * datablock. We don't want mesh to be created for every of those objects. + * - This is how conversion worked for a long long time. */ + LISTBASE_FOREACH (Object *, other_object, &bmain->objects) { + if (other_object->data == curve) { + other_object->type = OB_MESH; - if (ob->type == OB_MESH) { - BKE_object_free_modifiers(ob, 0); + id_us_min((ID *)other_object->data); + other_object->data = ob->data; + id_us_plus((ID *)other_object->data); + } } } @@ -2052,7 +2069,8 @@ static int convert_exec(bContext *C, wmOperator *op) FOREACH_SCENE_OBJECT_END; } - ListBase selected_editable_bases = CTX_data_collection_get(C, "selected_editable_bases"); + ListBase selected_editable_bases; + CTX_data_selected_editable_bases(C, &selected_editable_bases); /* Ensure we get all meshes calculated with a sufficient data-mask, * needed since re-evaluating single modifiers causes bugs if they depend @@ -2232,7 +2250,7 @@ static int convert_exec(bContext *C, wmOperator *op) BKE_curve_curve_dimension_update(cu); if (target == OB_MESH) { - curvetomesh(bmain, depsgraph, scene, newob); + curvetomesh(bmain, depsgraph, newob); /* meshes doesn't use displist */ BKE_object_free_curve_cache(newob); @@ -2256,7 +2274,7 @@ static int convert_exec(bContext *C, wmOperator *op) newob = ob; } - curvetomesh(bmain, depsgraph, scene, newob); + curvetomesh(bmain, depsgraph, newob); /* meshes doesn't use displist */ BKE_object_free_curve_cache(newob); diff --git a/source/blender/editors/object/object_bake_api.c b/source/blender/editors/object/object_bake_api.c index f87342a14ad..2f5a4b44412 100644 --- a/source/blender/editors/object/object_bake_api.c +++ b/source/blender/editors/object/object_bake_api.c @@ -707,7 +707,7 @@ static size_t initialize_internal_images(BakeImages *bake_images, ReportList *re /* create new mesh with edit mode changes and modifiers applied */ static Mesh *bake_mesh_new_from_object(Object *object) { - Mesh *me = BKE_object_to_mesh(object); + Mesh *me = BKE_object_to_mesh(NULL, object, false); if (me->flag & ME_AUTOSMOOTH) { BKE_mesh_split_faces(me, true); @@ -946,7 +946,7 @@ static int bake(Render *re, md = md_next; } - me_cage = BKE_object_to_mesh(ob_low_eval); + me_cage = BKE_object_to_mesh(NULL, ob_low_eval, false); RE_bake_pixels_populate(me_cage, pixel_array_low, num_pixels, &bake_images, uv_layer); } @@ -965,7 +965,7 @@ static int bake(Render *re, highpoly[i].ob_eval = DEG_get_evaluated_object(depsgraph, ob_iter); highpoly[i].ob_eval->restrictflag &= ~OB_RESTRICT_RENDER; highpoly[i].ob_eval->base_flag |= (BASE_VISIBLE | BASE_ENABLED_RENDER); - highpoly[i].me = BKE_object_to_mesh(highpoly[i].ob_eval); + highpoly[i].me = BKE_object_to_mesh(NULL, highpoly[i].ob_eval, false); /* lowpoly to highpoly transformation matrix */ copy_m4_m4(highpoly[i].obmat, highpoly[i].ob->obmat); @@ -1088,7 +1088,7 @@ static int bake(Render *re, } /* Evaluate modifiers again. */ - me_nores = BKE_object_to_mesh(ob_low_eval); + me_nores = BKE_object_to_mesh(NULL, ob_low_eval, false); RE_bake_pixels_populate(me_nores, pixel_array_low, num_pixels, &bake_images, uv_layer); RE_bake_normal_world_to_tangent(pixel_array_low, diff --git a/source/blender/editors/object/object_modifier.c b/source/blender/editors/object/object_modifier.c index e555f0d940d..8d3a636671a 100644 --- a/source/blender/editors/object/object_modifier.c +++ b/source/blender/editors/object/object_modifier.c @@ -108,7 +108,7 @@ static void object_force_modifier_update_for_bind(Depsgraph *depsgraph, Object * BKE_displist_make_mball(depsgraph, scene_eval, ob_eval); } else if (ELEM(ob->type, OB_CURVE, OB_SURF, OB_FONT)) { - BKE_displist_make_curveTypes(depsgraph, scene_eval, ob_eval, false, false, NULL); + BKE_displist_make_curveTypes(depsgraph, scene_eval, ob_eval, false, false); } } diff --git a/source/blender/editors/object/object_relations.c b/source/blender/editors/object/object_relations.c index e15d85a7953..6df012cdc80 100644 --- a/source/blender/editors/object/object_relations.c +++ b/source/blender/editors/object/object_relations.c @@ -697,7 +697,7 @@ bool ED_object_parent_set(ReportList *reports, cu->flag |= CU_PATH | CU_FOLLOW; cu_eval->flag |= CU_PATH | CU_FOLLOW; /* force creation of path data */ - BKE_displist_make_curveTypes(depsgraph, scene, par, false, false, NULL); + BKE_displist_make_curveTypes(depsgraph, scene, par, false, false); } else { cu->flag |= CU_FOLLOW; diff --git a/source/blender/editors/object/object_transform.c b/source/blender/editors/object/object_transform.c index 8836d913475..00f5dffb3cc 100644 --- a/source/blender/editors/object/object_transform.c +++ b/source/blender/editors/object/object_transform.c @@ -1335,6 +1335,11 @@ static int object_origin_set_exec(bContext *C, wmOperator *op) BKE_object_batch_cache_dirty_tag(tob); DEG_id_tag_update(&tob->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY); } + /* special support for dupligroups */ + else if (tob->instance_collection && tob->instance_collection->id.tag & LIB_TAG_DOIT) { + DEG_id_tag_update(&tob->id, ID_RECALC_TRANSFORM); + DEG_id_tag_update(&tob->instance_collection->id, ID_RECALC_COPY_ON_WRITE); + } } if (tot_change) { diff --git a/source/blender/editors/render/render_opengl.c b/source/blender/editors/render/render_opengl.c index 342c6269419..20229b63258 100644 --- a/source/blender/editors/render/render_opengl.c +++ b/source/blender/editors/render/render_opengl.c @@ -114,7 +114,6 @@ typedef struct OGLRender { GPUOffScreen *ofs; int ofs_samples; - bool ofs_full_samples; int sizex, sizey; int write_still; @@ -356,9 +355,6 @@ static void screen_opengl_render_doit(const bContext *C, OGLRender *oglrender, R ImBuf *ibuf_view; const int alpha_mode = (draw_sky) ? R_ADDSKY : R_ALPHAPREMUL; - unsigned int draw_flags = V3D_OFSDRAW_NONE; - draw_flags |= (oglrender->ofs_full_samples) ? V3D_OFSDRAW_USE_FULL_SAMPLE : 0; - if (view_context) { ibuf_view = ED_view3d_draw_offscreen_imbuf(depsgraph, scene, @@ -368,7 +364,6 @@ static void screen_opengl_render_doit(const bContext *C, OGLRender *oglrender, R sizex, sizey, IB_rectfloat, - draw_flags, alpha_mode, oglrender->ofs_samples, viewname, @@ -381,7 +376,6 @@ static void screen_opengl_render_doit(const bContext *C, OGLRender *oglrender, R } } else { - draw_flags |= V3D_OFSDRAW_SHOW_ANNOTATION; ibuf_view = ED_view3d_draw_offscreen_imbuf_simple(depsgraph, scene, NULL, @@ -390,7 +384,7 @@ static void screen_opengl_render_doit(const bContext *C, OGLRender *oglrender, R oglrender->sizex, oglrender->sizey, IB_rectfloat, - draw_flags, + V3D_OFSDRAW_SHOW_ANNOTATION, alpha_mode, oglrender->ofs_samples, viewname, @@ -532,6 +526,7 @@ static bool screen_opengl_render_init(bContext *C, wmOperator *op) const bool is_animation = RNA_boolean_get(op->ptr, "animation"); const bool is_sequencer = RNA_boolean_get(op->ptr, "sequencer"); const bool is_write_still = RNA_boolean_get(op->ptr, "write_still"); + const int samples = U.ogl_multisamples; char err_out[256] = "unknown"; if (G.background) { @@ -576,7 +571,7 @@ static bool screen_opengl_render_init(bContext *C, wmOperator *op) /* corrects render size with actual size, not every card supports non-power-of-two dimensions */ DRW_opengl_context_enable(); /* Offscreen creation needs to be done in DRW context. */ - ofs = GPU_offscreen_create(sizex, sizey, 0, true, true, err_out); + ofs = GPU_offscreen_create(sizex, sizey, samples, true, true, err_out); DRW_opengl_context_disable(); if (!ofs) { @@ -597,6 +592,7 @@ static bool screen_opengl_render_init(bContext *C, wmOperator *op) oglrender->view_layer = CTX_data_view_layer(C); oglrender->depsgraph = CTX_data_depsgraph(C); oglrender->cfrao = scene->r.cfra; + oglrender->ofs_samples = samples; oglrender->write_still = is_write_still && !is_animation; oglrender->is_animation = is_animation; diff --git a/source/blender/editors/render/render_shading.c b/source/blender/editors/render/render_shading.c index 8819b7a541d..f7a1d7187f1 100644 --- a/source/blender/editors/render/render_shading.c +++ b/source/blender/editors/render/render_shading.c @@ -595,7 +595,7 @@ static int new_material_exec(bContext *C, wmOperator *UNUSED(op)) id_us_min(&ma->id); RNA_id_pointer_create(&ma->id, &idptr); - RNA_property_pointer_set(NULL, &ptr, prop, idptr); + RNA_property_pointer_set(&ptr, prop, idptr, NULL); RNA_property_update(C, &ptr, prop); } @@ -644,7 +644,7 @@ static int new_texture_exec(bContext *C, wmOperator *UNUSED(op)) id_us_min(&tex->id); RNA_id_pointer_create(&tex->id, &idptr); - RNA_property_pointer_set(NULL, &ptr, prop, idptr); + RNA_property_pointer_set(&ptr, prop, idptr, NULL); RNA_property_update(C, &ptr, prop); } @@ -695,7 +695,7 @@ static int new_world_exec(bContext *C, wmOperator *UNUSED(op)) id_us_min(&wo->id); RNA_id_pointer_create(&wo->id, &idptr); - RNA_property_pointer_set(NULL, &ptr, prop, idptr); + RNA_property_pointer_set(&ptr, prop, idptr, NULL); RNA_property_update(C, &ptr, prop); } diff --git a/source/blender/editors/screen/area.c b/source/blender/editors/screen/area.c index c2f9beb5d78..83058f2bc95 100644 --- a/source/blender/editors/screen/area.c +++ b/source/blender/editors/screen/area.c @@ -1612,9 +1612,9 @@ static void ed_default_handlers( keymap = WM_keymap_ensure(wm->defaultconf, "Markers", 0, 0); WM_event_add_keymap_handler_poll(handlers, keymap, event_in_markers_region); - /* time-scrubbing */ - keymap = WM_keymap_ensure(wm->defaultconf, "Scrubbing", 0, 0); - WM_event_add_keymap_handler_poll(handlers, keymap, ED_event_in_scrubbing_region); + /* time-scrub */ + keymap = WM_keymap_ensure(wm->defaultconf, "Time Scrub", 0, 0); + WM_event_add_keymap_handler_poll(handlers, keymap, ED_time_scrub_event_in_region); /* frame changing and timeline operators (for time spaces) */ keymap = WM_keymap_ensure(wm->defaultconf, "Animation", 0, 0); @@ -2292,7 +2292,7 @@ static void ed_panel_draw(const bContext *C, } } - UI_panel_end(block, w, h); + UI_panel_end(block, w, h, open); } /** diff --git a/source/blender/editors/screen/screen_context.c b/source/blender/editors/screen/screen_context.c index c60469e092f..6a5df8a3776 100644 --- a/source/blender/editors/screen/screen_context.c +++ b/source/blender/editors/screen/screen_context.c @@ -69,15 +69,10 @@ const char *screen_context_dir[] = { "scene", "view_layer", "visible_objects", - "visible_bases", "selectable_objects", - "selectable_bases", "selected_objects", - "selected_bases", "editable_objects", - "editable_bases", "selected_editable_objects", - "selected_editable_bases", "objects_in_mode", "objects_in_mode_unique_data", "visible_bones", @@ -89,7 +84,6 @@ const char *screen_context_dir[] = { "selected_pose_bones_from_active_object", "active_bone", "active_pose_bone", - "active_base", "active_object", "object", "edit_object", @@ -179,52 +173,6 @@ int ed_screen_context(const bContext *C, const char *member, bContextDataResult CTX_data_type_set(result, CTX_DATA_TYPE_COLLECTION); return 1; } - else if (CTX_data_equals(member, "visible_bases")) { - for (Base *base = view_layer->object_bases.first; base; base = base->next) { - if (BASE_VISIBLE(v3d, base)) { - CTX_data_list_add(result, &scene->id, &RNA_ObjectBase, base); - } - } - CTX_data_type_set(result, CTX_DATA_TYPE_COLLECTION); - return 1; - } - else if (CTX_data_equals(member, "selectable_bases")) { - for (Base *base = view_layer->object_bases.first; base; base = base->next) { - if (BASE_SELECTABLE(v3d, base)) { - CTX_data_list_add(result, &scene->id, &RNA_ObjectBase, base); - } - } - CTX_data_type_set(result, CTX_DATA_TYPE_COLLECTION); - return 1; - } - else if (CTX_data_equals(member, "selected_bases")) { - for (Base *base = view_layer->object_bases.first; base; base = base->next) { - if (BASE_SELECTED(v3d, base)) { - CTX_data_list_add(result, &scene->id, &RNA_ObjectBase, base); - } - } - CTX_data_type_set(result, CTX_DATA_TYPE_COLLECTION); - return 1; - } - else if (CTX_data_equals(member, "selected_editable_bases")) { - for (Base *base = view_layer->object_bases.first; base; base = base->next) { - if (BASE_SELECTED_EDITABLE(v3d, base)) { - CTX_data_list_add(result, &scene->id, &RNA_ObjectBase, base); - } - } - CTX_data_type_set(result, CTX_DATA_TYPE_COLLECTION); - return 1; - } - else if (CTX_data_equals(member, "editable_bases")) { - /* Visible + Editable, but not necessarily selected */ - for (Base *base = view_layer->object_bases.first; base; base = base->next) { - if (BASE_EDITABLE(v3d, base)) { - CTX_data_list_add(result, &scene->id, &RNA_ObjectBase, base); - } - } - CTX_data_type_set(result, CTX_DATA_TYPE_COLLECTION); - return 1; - } else if (CTX_data_equals(member, "objects_in_mode")) { if (obact && (obact->mode != OB_MODE_OBJECT)) { FOREACH_OBJECT_IN_MODE_BEGIN (view_layer, v3d, obact->type, obact->mode, ob_iter) { @@ -455,13 +403,6 @@ int ed_screen_context(const bContext *C, const char *member, bContextDataResult return 1; } } - else if (CTX_data_equals(member, "active_base")) { - if (view_layer->basact) { - CTX_data_pointer_set(result, &scene->id, &RNA_ObjectBase, view_layer->basact); - } - - return 1; - } else if (CTX_data_equals(member, "active_object")) { if (obact) { CTX_data_id_pointer_set(result, &obact->id); diff --git a/source/blender/editors/screen/screen_edit.c b/source/blender/editors/screen/screen_edit.c index 07a87982890..3a90532aa56 100644 --- a/source/blender/editors/screen/screen_edit.c +++ b/source/blender/editors/screen/screen_edit.c @@ -675,6 +675,12 @@ void ED_screen_set_active_region(bContext *C, wmWindow *win, const int xy[2]) bool do_draw = false; for (ar = area_iter->regionbase.first; ar; ar = ar->next) { + + /* call old area's deactivate if assigned */ + if (ar == old_ar && area_iter->type->deactivate) { + area_iter->type->deactivate(area_iter); + } + if (ar == old_ar || ar == scr->active_region) { do_draw = true; } diff --git a/source/blender/editors/screen/screen_user_menu.c b/source/blender/editors/screen/screen_user_menu.c index 0ec989db12b..08b9d010f79 100644 --- a/source/blender/editors/screen/screen_user_menu.c +++ b/source/blender/editors/screen/screen_user_menu.c @@ -194,6 +194,10 @@ void ED_screen_user_menu_item_remove(ListBase *lb, bUserMenuItem *umi) static void screen_user_menu_draw(const bContext *C, Menu *menu) { + /* Enable when we have the ability to edit menus. */ + const bool show_missing = false; + char label[512]; + uint um_array_len; bUserMenu **um_array = ED_screen_user_menus_find(C, &um_array_len); bool is_empty = true; @@ -206,15 +210,32 @@ static void screen_user_menu_draw(const bContext *C, Menu *menu) const char *ui_name = umi->ui_name[0] ? umi->ui_name : NULL; if (umi->type == USER_MENU_TYPE_OPERATOR) { bUserMenuItem_Op *umi_op = (bUserMenuItem_Op *)umi; - IDProperty *prop = umi_op->prop ? IDP_CopyProperty(umi_op->prop) : NULL; - uiItemFullO( - menu->layout, umi_op->op_idname, ui_name, ICON_NONE, prop, umi_op->opcontext, 0, NULL); - is_empty = false; + wmOperatorType *ot = WM_operatortype_find(umi_op->op_idname, false); + if (ot != NULL) { + IDProperty *prop = umi_op->prop ? IDP_CopyProperty(umi_op->prop) : NULL; + uiItemFullO_ptr(menu->layout, ot, ui_name, ICON_NONE, prop, umi_op->opcontext, 0, NULL); + is_empty = false; + } + else { + if (show_missing) { + SNPRINTF(label, "Missing: %s", umi_op->op_idname); + uiItemL(menu->layout, label, ICON_NONE); + } + } } else if (umi->type == USER_MENU_TYPE_MENU) { bUserMenuItem_Menu *umi_mt = (bUserMenuItem_Menu *)umi; - uiItemM(menu->layout, umi_mt->mt_idname, ui_name, ICON_NONE); - is_empty = false; + MenuType *mt = WM_menutype_find(umi_mt->mt_idname, false); + if (mt != NULL) { + uiItemM_ptr(menu->layout, mt, ui_name, ICON_NONE); + is_empty = false; + } + else { + if (show_missing) { + SNPRINTF(label, "Missing: %s", umi_mt->mt_idname); + uiItemL(menu->layout, label, ICON_NONE); + } + } } else if (umi->type == USER_MENU_TYPE_PROP) { bUserMenuItem_Prop *umi_pr = (bUserMenuItem_Prop *)umi; @@ -252,9 +273,10 @@ static void screen_user_menu_draw(const bContext *C, Menu *menu) } } if (!ok) { - char label[512]; - SNPRINTF(label, "Missing: %s.%s", umi_pr->context_data_path, umi_pr->prop_id); - uiItemL(menu->layout, label, ICON_NONE); + if (show_missing) { + SNPRINTF(label, "Missing: %s.%s", umi_pr->context_data_path, umi_pr->prop_id); + uiItemL(menu->layout, label, ICON_NONE); + } } } else if (umi->type == USER_MENU_TYPE_SEP) { diff --git a/source/blender/editors/sculpt_paint/paint_image_proj.c b/source/blender/editors/sculpt_paint/paint_image_proj.c index d7553d18d3b..303c3fac363 100644 --- a/source/blender/editors/sculpt_paint/paint_image_proj.c +++ b/source/blender/editors/sculpt_paint/paint_image_proj.c @@ -6188,7 +6188,6 @@ static int texture_paint_image_from_view_exec(bContext *C, wmOperator *op) w, h, IB_rect, - V3D_OFSDRAW_NONE, R_ALPHAPREMUL, 0, NULL, diff --git a/source/blender/editors/sculpt_paint/paint_utils.c b/source/blender/editors/sculpt_paint/paint_utils.c index 84b4a130183..c8ad1b5781d 100644 --- a/source/blender/editors/sculpt_paint/paint_utils.c +++ b/source/blender/editors/sculpt_paint/paint_utils.c @@ -71,6 +71,7 @@ #include "BLI_sys_types.h" #include "ED_mesh.h" /* for face mask functions */ +#include "ED_select_buffer_utils.h" #include "WM_api.h" #include "WM_types.h" @@ -390,7 +391,7 @@ static int imapaint_pick_face(ViewContext *vc, /* sample only on the exact position */ ED_view3d_select_id_validate(vc); - *r_index = ED_view3d_select_id_sample(vc, mval[0], mval[1]); + *r_index = ED_select_buffer_sample_point(mval); if ((*r_index) == 0 || (*r_index) > (unsigned int)totpoly) { return 0; diff --git a/source/blender/editors/sculpt_paint/paint_vertex_weight_ops.c b/source/blender/editors/sculpt_paint/paint_vertex_weight_ops.c index c904bf2005b..b6a6c897606 100644 --- a/source/blender/editors/sculpt_paint/paint_vertex_weight_ops.c +++ b/source/blender/editors/sculpt_paint/paint_vertex_weight_ops.c @@ -695,7 +695,7 @@ static void gradientVertInit__mapFunc(void *userData, static int paint_weight_gradient_modal(bContext *C, wmOperator *op, const wmEvent *event) { wmGesture *gesture = op->customdata; - WPGradient_vertStoreBase *vert_cache = gesture->userdata; + WPGradient_vertStoreBase *vert_cache = gesture->user_data.data; int ret = WM_gesture_straightline_modal(C, op, event); if (ret & OPERATOR_RUNNING_MODAL) { @@ -751,15 +751,15 @@ static int paint_weight_gradient_exec(bContext *C, wmOperator *op) WPGradient_userData data = {NULL}; if (is_interactive) { - if (gesture->userdata == NULL) { - gesture->userdata = MEM_mallocN(sizeof(WPGradient_vertStoreBase) + - (sizeof(WPGradient_vertStore) * me->totvert), - __func__); - gesture->userdata_free = false; + if (gesture->user_data.data == NULL) { + gesture->user_data.data = MEM_mallocN(sizeof(WPGradient_vertStoreBase) + + (sizeof(WPGradient_vertStore) * me->totvert), + __func__); + gesture->user_data.use_free = false; data.is_init = true; wpaint_prev_create( - &((WPGradient_vertStoreBase *)gesture->userdata)->wpp, me->dvert, me->totvert); + &((WPGradient_vertStoreBase *)gesture->user_data.data)->wpp, me->dvert, me->totvert); /* on init only, convert face -> vert sel */ if (me->editflag & ME_EDIT_PAINT_FACE_SEL) { @@ -767,7 +767,7 @@ static int paint_weight_gradient_exec(bContext *C, wmOperator *op) } } - vert_cache = gesture->userdata; + vert_cache = gesture->user_data.data; } else { if (ED_wpaint_ensure_data(C, op->reports, 0, NULL) == false) { diff --git a/source/blender/editors/sound/sound_ops.c b/source/blender/editors/sound/sound_ops.c index 692681cecb7..381173999c4 100644 --- a/source/blender/editors/sound/sound_ops.c +++ b/source/blender/editors/sound/sound_ops.c @@ -136,7 +136,7 @@ static int sound_open_exec(bContext *C, wmOperator *op) id_us_min(&sound->id); RNA_id_pointer_create(&sound->id, &idptr); - RNA_property_pointer_set(NULL, &pprop->ptr, pprop->prop, idptr); + RNA_property_pointer_set(&pprop->ptr, pprop->prop, idptr, NULL); RNA_property_update(C, &pprop->ptr, pprop->prop); } diff --git a/source/blender/editors/space_action/action_data.c b/source/blender/editors/space_action/action_data.c index d3e5c011579..bc7f8a0f79d 100644 --- a/source/blender/editors/space_action/action_data.c +++ b/source/blender/editors/space_action/action_data.c @@ -155,7 +155,7 @@ static void actedit_change_action(bContext *C, bAction *act) RNA_id_pointer_create((ID *)act, &idptr); /* set the new pointer, and force a refresh */ - RNA_property_pointer_set(NULL, &ptr, prop, idptr); + RNA_property_pointer_set(&ptr, prop, idptr, NULL); RNA_property_update(C, &ptr, prop); } @@ -261,7 +261,7 @@ static int action_new_exec(bContext *C, wmOperator *UNUSED(op)) * NOTE: we can't use actedit_change_action, as this function is also called from the NLA */ RNA_id_pointer_create(&action->id, &idptr); - RNA_property_pointer_set(NULL, &ptr, prop, idptr); + RNA_property_pointer_set(&ptr, prop, idptr, NULL); RNA_property_update(C, &ptr, prop); } @@ -619,7 +619,7 @@ void ED_animedit_unlink_action( prop = RNA_struct_find_property(&ptr, "action"); /* clear... */ - RNA_property_pointer_set(NULL, &ptr, prop, PointerRNA_NULL); + RNA_property_pointer_set(&ptr, prop, PointerRNA_NULL, NULL); RNA_property_update(C, &ptr, prop); } } diff --git a/source/blender/editors/space_action/space_action.c b/source/blender/editors/space_action/space_action.c index 972f19bb643..3c879b03126 100644 --- a/source/blender/editors/space_action/space_action.c +++ b/source/blender/editors/space_action/space_action.c @@ -237,7 +237,7 @@ static void action_main_region_draw(const bContext *C, ARegion *ar) UI_view2d_view_restore(C); /* scrubbing region */ - ED_scrubbing_draw(ar, scene, saction->flag & SACTION_DRAWTIME, true); + ED_time_scrub_draw(ar, scene, saction->flag & SACTION_DRAWTIME, true); /* scrollers */ scrollers = UI_view2d_scrollers_calc(v2d, NULL); @@ -281,7 +281,7 @@ static void action_channel_region_draw(const bContext *C, ARegion *ar) } /* channel filter next to scrubbing area */ - ED_channel_search_draw(C, ar, ac.ads); + ED_time_scrub_channel_search_draw(C, ar, ac.ads); /* reset view matrix */ UI_view2d_view_restore(C); diff --git a/source/blender/editors/space_clip/clip_buttons.c b/source/blender/editors/space_clip/clip_buttons.c index c985d61a8b8..2496b16ffae 100644 --- a/source/blender/editors/space_clip/clip_buttons.c +++ b/source/blender/editors/space_clip/clip_buttons.c @@ -808,12 +808,13 @@ void uiTemplateMovieclipInformation(uiLayout *layout, user = userptr->data; col = uiLayoutColumn(layout, false); + uiLayoutSetAlignment(col, UI_LAYOUT_ALIGN_RIGHT); ibuf = BKE_movieclip_get_ibuf_flag(clip, user, clip->flag, MOVIECLIP_CACHE_SKIP); /* Display frame dimensions, channels number and byffer type. */ BKE_movieclip_get_size(clip, user, &width, &height); - ofs += BLI_snprintf(str + ofs, sizeof(str) - ofs, IFACE_("Size %d x %d"), width, height); + ofs += BLI_snprintf(str + ofs, sizeof(str) - ofs, IFACE_("%d x %d"), width, height); if (ibuf) { if (ibuf->rect_float) { diff --git a/source/blender/editors/space_clip/clip_intern.h b/source/blender/editors/space_clip/clip_intern.h index 081515ca4bc..7683823a79f 100644 --- a/source/blender/editors/space_clip/clip_intern.h +++ b/source/blender/editors/space_clip/clip_intern.h @@ -35,7 +35,7 @@ struct bContext; struct wmOperatorType; /* channel heights */ -#define CHANNEL_FIRST (-UI_SCRUBBING_MARGIN_Y - CHANNEL_HEIGHT_HALF - CHANNEL_SKIP) +#define CHANNEL_FIRST (-UI_TIME_SCRUB_MARGIN_Y - CHANNEL_HEIGHT_HALF - CHANNEL_SKIP) #define CHANNEL_HEIGHT (0.8f * U.widget_unit) #define CHANNEL_HEIGHT_HALF (0.4f * U.widget_unit) #define CHANNEL_SKIP (0.1f * U.widget_unit) diff --git a/source/blender/editors/space_clip/clip_ops.c b/source/blender/editors/space_clip/clip_ops.c index e5698ede59a..710a46fdd51 100644 --- a/source/blender/editors/space_clip/clip_ops.c +++ b/source/blender/editors/space_clip/clip_ops.c @@ -245,7 +245,7 @@ static int open_exec(bContext *C, wmOperator *op) id_us_min(&clip->id); RNA_id_pointer_create(&clip->id, &idptr); - RNA_property_pointer_set(NULL, &pprop->ptr, pprop->prop, idptr); + RNA_property_pointer_set(&pprop->ptr, pprop->prop, idptr, NULL); RNA_property_update(C, &pprop->ptr, pprop->prop); } else if (sc) { diff --git a/source/blender/editors/space_clip/space_clip.c b/source/blender/editors/space_clip/space_clip.c index 13d190e6861..4df435270ce 100644 --- a/source/blender/editors/space_clip/space_clip.c +++ b/source/blender/editors/space_clip/space_clip.c @@ -926,7 +926,8 @@ static void clip_main_region_draw(const bContext *C, ARegion *ar) ScrArea *sa = CTX_wm_area(C); int mask_width, mask_height; ED_mask_get_size(sa, &mask_width, &mask_height); - ED_mask_draw_region(mask, + ED_mask_draw_region(CTX_data_depsgraph(C), + mask, ar, sc->mask_info.draw_flag, sc->mask_info.draw_type, @@ -1006,8 +1007,8 @@ static void clip_preview_region_init(wmWindowManager *wm, ARegion *ar) keymap = WM_keymap_ensure(wm->defaultconf, "Clip", SPACE_CLIP, 0); WM_event_add_keymap_handler_v2d_mask(&ar->handlers, keymap); - keymap = WM_keymap_ensure(wm->defaultconf, "Clip Scrubbing", SPACE_CLIP, RGN_TYPE_PREVIEW); - WM_event_add_keymap_handler_poll(&ar->handlers, keymap, ED_event_in_scrubbing_region); + keymap = WM_keymap_ensure(wm->defaultconf, "Clip Time Scrub", SPACE_CLIP, RGN_TYPE_PREVIEW); + WM_event_add_keymap_handler_poll(&ar->handlers, keymap, ED_time_scrub_event_in_region); keymap = WM_keymap_ensure(wm->defaultconf, "Clip Graph Editor", SPACE_CLIP, 0); WM_event_add_keymap_handler_v2d_mask(&ar->handlers, keymap); @@ -1047,7 +1048,7 @@ static void graph_region_draw(const bContext *C, ARegion *ar) UI_view2d_view_restore(C); /* time-scrubbing */ - ED_scrubbing_draw(ar, scene, sc->flag & SC_SHOW_SECONDS, true); + ED_time_scrub_draw(ar, scene, sc->flag & SC_SHOW_SECONDS, true); /* scrollers */ scrollers = UI_view2d_scrollers_calc(v2d, NULL); @@ -1061,7 +1062,7 @@ static void graph_region_draw(const bContext *C, ARegion *ar) 0, 15 * UI_DPI_FAC, 15 * UI_DPI_FAC, - UI_DPI_FAC * ar->sizey - UI_SCRUBBING_MARGIN_Y); + UI_DPI_FAC * ar->sizey - UI_TIME_SCRUB_MARGIN_Y); UI_view2d_draw_scale_y__values(ar, v2d, &rect, TH_TEXT); } } @@ -1101,7 +1102,7 @@ static void dopesheet_region_draw(const bContext *C, ARegion *ar) UI_view2d_view_restore(C); /* time-scrubbing */ - ED_scrubbing_draw(ar, scene, sc->flag & SC_SHOW_SECONDS, true); + ED_time_scrub_draw(ar, scene, sc->flag & SC_SHOW_SECONDS, true); /* scrollers */ scrollers = UI_view2d_scrollers_calc(v2d, NULL); @@ -1371,7 +1372,7 @@ void ED_spacetype_clip(void) /* regions: properties */ art = MEM_callocN(sizeof(ARegionType), "spacetype clip region properties"); art->regionid = RGN_TYPE_UI; - art->prefsizex = UI_COMPACT_PANEL_WIDTH; + art->prefsizex = UI_SIDEBAR_PANEL_WIDTH; art->keymapflag = ED_KEYMAP_FRAMES | ED_KEYMAP_UI; art->init = clip_properties_region_init; art->draw = clip_properties_region_draw; @@ -1382,7 +1383,7 @@ void ED_spacetype_clip(void) /* regions: tools */ art = MEM_callocN(sizeof(ARegionType), "spacetype clip region tools"); art->regionid = RGN_TYPE_TOOLS; - art->prefsizex = UI_COMPACT_PANEL_WIDTH; + art->prefsizex = UI_SIDEBAR_PANEL_WIDTH; art->keymapflag = ED_KEYMAP_FRAMES | ED_KEYMAP_UI; art->listener = clip_props_region_listener; art->init = clip_tools_region_init; diff --git a/source/blender/editors/space_clip/tracking_ops.c b/source/blender/editors/space_clip/tracking_ops.c index b51baafbcf5..0425d6da3d8 100644 --- a/source/blender/editors/space_clip/tracking_ops.c +++ b/source/blender/editors/space_clip/tracking_ops.c @@ -1466,6 +1466,7 @@ static int join_tracks_exec(bContext *C, wmOperator *op) } BLI_gset_free(point_tracks, NULL); + DEG_id_tag_update(&clip->id, 0); WM_event_add_notifier(C, NC_MOVIECLIP | NA_EDITED, clip); @@ -1625,6 +1626,7 @@ static int track_copy_color_exec(bContext *C, wmOperator *UNUSED(op)) } } + DEG_id_tag_update(&clip->id, 0); WM_event_add_notifier(C, NC_MOVIECLIP | ND_DISPLAY, clip); return OPERATOR_FINISHED; @@ -1806,6 +1808,7 @@ static int clean_tracks_exec(bContext *C, wmOperator *op) } } + DEG_id_tag_update(&clip->id, 0); BKE_tracking_dopesheet_tag_update(tracking); WM_event_add_notifier(C, NC_MOVIECLIP | ND_SELECT, clip); diff --git a/source/blender/editors/space_graph/graph_edit.c b/source/blender/editors/space_graph/graph_edit.c index 8329218eea9..b68efdc0ea0 100644 --- a/source/blender/editors/space_graph/graph_edit.c +++ b/source/blender/editors/space_graph/graph_edit.c @@ -55,6 +55,7 @@ #include "DEG_depsgraph_build.h" #include "UI_view2d.h" +#include "UI_interface.h" #include "ED_anim_api.h" #include "ED_keyframing.h" @@ -282,10 +283,18 @@ static int graphkeys_viewall(bContext *C, do_sel_only, include_handles); + /* Give some more space at the borders. */ BLI_rctf_scale(&cur_new, 1.1f); - UI_view2d_smooth_view(C, ac.ar, &cur_new, smooth_viewtx); + /* Take regions into account, that could block the view. */ + float pad_top = UI_TIME_SCRUB_MARGIN_Y; + float pad_bottom = 0; + if (!BLI_listbase_is_empty(ED_context_get_markers(C))) { + pad_bottom = UI_MARKER_MARGIN_Y; + } + BLI_rctf_pad_y(&cur_new, ac.ar->sizey * UI_DPI_FAC, pad_bottom, pad_top); + UI_view2d_smooth_view(C, ac.ar, &cur_new, smooth_viewtx); return OPERATOR_FINISHED; } diff --git a/source/blender/editors/space_graph/space_graph.c b/source/blender/editors/space_graph/space_graph.c index 4e131c653f8..6c5ebf77bf4 100644 --- a/source/blender/editors/space_graph/space_graph.c +++ b/source/blender/editors/space_graph/space_graph.c @@ -314,7 +314,7 @@ static void graph_main_region_draw(const bContext *C, ARegion *ar) UI_view2d_view_restore(C); /* time-scrubbing */ - ED_scrubbing_draw(ar, scene, display_seconds, false); + ED_time_scrub_draw(ar, scene, display_seconds, false); /* scrollers */ // FIXME: args for scrollers depend on the type of data being shown... @@ -329,7 +329,7 @@ static void graph_main_region_draw(const bContext *C, ARegion *ar) 0, 15 * UI_DPI_FAC, 15 * UI_DPI_FAC, - UI_DPI_FAC * ar->sizey - UI_SCRUBBING_MARGIN_Y); + UI_DPI_FAC * ar->sizey - UI_TIME_SCRUB_MARGIN_Y); UI_view2d_draw_scale_y__values(ar, v2d, &rect, TH_SCROLL_TEXT); } } @@ -376,7 +376,7 @@ static void graph_channel_region_draw(const bContext *C, ARegion *ar) } /* channel filter next to scrubbing area */ - ED_channel_search_draw(C, ar, ac.ads); + ED_time_scrub_channel_search_draw(C, ar, ac.ads); /* reset view matrix */ UI_view2d_view_restore(C); diff --git a/source/blender/editors/space_image/image_buttons.c b/source/blender/editors/space_image/image_buttons.c index 68af854e367..26512cb232d 100644 --- a/source/blender/editors/space_image/image_buttons.c +++ b/source/blender/editors/space_image/image_buttons.c @@ -42,6 +42,7 @@ #include "RE_pipeline.h" +#include "IMB_colormanagement.h" #include "IMB_imbuf.h" #include "IMB_imbuf_types.h" @@ -62,81 +63,6 @@ #define B_NOP -1 #define MAX_IMAGE_INFO_LEN 128 -/* proto */ - -static void image_info( - Scene *scene, ImageUser *iuser, Image *ima, ImBuf *ibuf, char *str, size_t len) -{ - size_t ofs = 0; - - str[0] = 0; - if (ima == NULL) { - return; - } - - if (ibuf == NULL) { - ofs += BLI_strncpy_rlen(str + ofs, IFACE_("Can't Load Image"), len - ofs); - } - else { - if (ima->source == IMA_SRC_MOVIE) { - ofs += BLI_strncpy_rlen(str + ofs, IFACE_("Movie"), len - ofs); - if (BKE_image_has_anim(ima)) { - ofs += BLI_snprintf( - str + ofs, - len - ofs, - IFACE_(" %d frs"), - IMB_anim_get_duration(((ImageAnim *)ima->anims.first)->anim, IMB_TC_RECORD_RUN)); - } - } - else { - ofs += BLI_strncpy_rlen(str, IFACE_("Image"), len - ofs); - } - - ofs += BLI_snprintf(str + ofs, len - ofs, IFACE_(": size %d x %d,"), ibuf->x, ibuf->y); - - if (ibuf->rect_float) { - if (ibuf->channels != 4) { - ofs += BLI_snprintf(str + ofs, len - ofs, IFACE_("%d float channel(s)"), ibuf->channels); - } - else if (ibuf->planes == R_IMF_PLANES_RGBA) { - ofs += BLI_strncpy_rlen(str + ofs, IFACE_(" RGBA float"), len - ofs); - } - else { - ofs += BLI_strncpy_rlen(str + ofs, IFACE_(" RGB float"), len - ofs); - } - } - else { - if (ibuf->planes == R_IMF_PLANES_RGBA) { - ofs += BLI_strncpy_rlen(str + ofs, IFACE_(" RGBA byte"), len - ofs); - } - else { - ofs += BLI_strncpy_rlen(str + ofs, IFACE_(" RGB byte"), len - ofs); - } - } - if (ibuf->zbuf || ibuf->zbuf_float) { - ofs += BLI_strncpy_rlen(str + ofs, IFACE_(" + Z"), len - ofs); - } - - if (ima->source == IMA_SRC_SEQUENCE) { - const char *file = BLI_last_slash(ibuf->name); - if (file == NULL) { - file = ibuf->name; - } - else { - file++; - } - ofs += BLI_snprintf(str + ofs, len - ofs, ", %s", file); - } - } - - /* the frame number, even if we cant */ - if (ima->source == IMA_SRC_SEQUENCE) { - /* don't use iuser->framenr directly because it may not be updated if auto-refresh is off */ - const int framenr = BKE_image_user_frame_get(iuser, CFRA, NULL); - ofs += BLI_snprintf(str + ofs, len - ofs, IFACE_(", Frame: %d"), framenr); - } -} - /* gets active viewer user */ struct ImageUser *ntree_get_active_iuser(bNodeTree *ntree) { @@ -822,6 +748,22 @@ static void rna_update_cb(bContext *C, void *arg_cb, void *UNUSED(arg)) RNA_property_update(C, &cb->ptr, cb->prop); } +static bool image_has_alpha(Image *ima, ImageUser *iuser) +{ + ImBuf *ibuf = BKE_image_acquire_ibuf(ima, iuser, NULL); + if (ibuf == NULL) { + return false; + } + + int imtype = BKE_image_ftype_to_imtype(ibuf->ftype, &ibuf->foptions); + char valid_channels = BKE_imtype_valid_channels(imtype, false); + bool has_alpha = (valid_channels & IMA_CHAN_FLAG_ALPHA) != 0; + + BKE_image_release_ibuf(ima, ibuf, NULL); + + return has_alpha; +} + void uiTemplateImage(uiLayout *layout, bContext *C, PointerRNA *ptr, @@ -830,24 +772,11 @@ void uiTemplateImage(uiLayout *layout, bool compact, bool multiview) { - PropertyRNA *prop; - PointerRNA imaptr; - RNAUpdateCb *cb; - Image *ima; - ImageUser *iuser; - Scene *scene = CTX_data_scene(C); - SpaceImage *space_image = CTX_wm_space_image(C); - uiLayout *row, *split, *col; - uiBlock *block; - char str[MAX_IMAGE_INFO_LEN]; - - void *lock; - if (!ptr->data) { return; } - prop = RNA_struct_find_property(ptr, propname); + PropertyRNA *prop = RNA_struct_find_property(ptr, propname); if (!prop) { printf( "%s: property not found: %s.%s\n", __func__, RNA_struct_identifier(ptr->type), propname); @@ -862,22 +791,19 @@ void uiTemplateImage(uiLayout *layout, return; } - block = uiLayoutGetBlock(layout); + uiBlock *block = uiLayoutGetBlock(layout); - imaptr = RNA_property_pointer_get(ptr, prop); - ima = imaptr.data; - iuser = userptr->data; + PointerRNA imaptr = RNA_property_pointer_get(ptr, prop); + Image *ima = imaptr.data; + ImageUser *iuser = userptr->data; + Scene *scene = CTX_data_scene(C); BKE_image_user_frame_calc(iuser, (int)scene->r.cfra); - cb = MEM_callocN(sizeof(RNAUpdateCb), "RNAUpdateCb"); - cb->ptr = *ptr; - cb->prop = prop; - cb->iuser = iuser; - uiLayoutSetContextPointer(layout, "edit_image", &imaptr); uiLayoutSetContextPointer(layout, "edit_image_user", userptr); + SpaceImage *space_image = CTX_wm_space_image(C); if (!compact && (space_image == NULL || iuser != &space_image->iuser)) { uiTemplateID(layout, C, @@ -888,164 +814,178 @@ void uiTemplateImage(uiLayout *layout, NULL, UI_TEMPLATE_ID_FILTER_ALL, false); + + if (ima != NULL) { + uiItemS(layout); + } } - if (ima) { - UI_block_funcN_set(block, rna_update_cb, MEM_dupallocN(cb), NULL); + if (ima == NULL) { + return; + } - if (ima->source == IMA_SRC_VIEWER) { - ImBuf *ibuf = BKE_image_acquire_ibuf(ima, iuser, &lock); - image_info(scene, iuser, ima, ibuf, str, MAX_IMAGE_INFO_LEN); - BKE_image_release_ibuf(ima, ibuf, lock); + if (ima->source == IMA_SRC_VIEWER) { + /* Viewer images. */ + uiTemplateImageInfo(layout, C, ima, iuser); - uiItemL(layout, ima->id.name + 2, ICON_NONE); - uiItemL(layout, str, ICON_NONE); + if (ima->type == IMA_TYPE_COMPOSITE) { + } + else if (ima->type == IMA_TYPE_R_RESULT) { + /* browse layer/passes */ + RenderResult *rr; + const float dpi_fac = UI_DPI_FAC; + const int menus_width = 230 * dpi_fac; + + /* use BKE_image_acquire_renderresult so we get the correct slot in the menu */ + rr = BKE_image_acquire_renderresult(scene, ima); + uiblock_layer_pass_buttons(layout, ima, rr, iuser, menus_width, &ima->render_slot); + BKE_image_release_renderresult(scene, ima); + } - if (ima->type == IMA_TYPE_COMPOSITE) { - } - else if (ima->type == IMA_TYPE_R_RESULT) { - /* browse layer/passes */ - RenderResult *rr; - const float dpi_fac = UI_DPI_FAC; - const int menus_width = 230 * dpi_fac; - - /* use BKE_image_acquire_renderresult so we get the correct slot in the menu */ - rr = BKE_image_acquire_renderresult(scene, ima); - uiblock_layer_pass_buttons(layout, ima, rr, iuser, menus_width, &ima->render_slot); - BKE_image_release_renderresult(scene, ima); - } + return; + } + + /* Set custom callback for property updates. */ + RNAUpdateCb *cb = MEM_callocN(sizeof(RNAUpdateCb), "RNAUpdateCb"); + cb->ptr = *ptr; + cb->prop = prop; + cb->iuser = iuser; + UI_block_funcN_set(block, rna_update_cb, cb, NULL); + + /* Disable editing if image was modified, to avoid losing changes. */ + const bool is_dirty = BKE_image_is_dirty(ima); + if (is_dirty) { + uiLayout *row = uiLayoutRow(layout, true); + uiItemO(row, IFACE_("Save"), ICON_NONE, "image.save"); + uiItemO(row, IFACE_("Discard"), ICON_NONE, "image.reload"); + uiItemS(layout); + } + + layout = uiLayoutColumn(layout, false); + uiLayoutSetEnabled(layout, !is_dirty); + uiLayoutSetPropDecorate(layout, false); + + /* Image source */ + { + uiLayout *col = uiLayoutColumn(layout, false); + uiLayoutSetPropSep(col, true); + uiItemR(col, &imaptr, "source", 0, NULL, ICON_NONE); + } + + /* Filepath */ + const bool is_packed = BKE_image_has_packedfile(ima); + const bool no_filepath = is_packed && !BKE_image_has_filepath(ima); + + if ((ima->source != IMA_SRC_GENERATED) && !no_filepath) { + uiItemS(layout); + + uiLayout *row = uiLayoutRow(layout, true); + if (is_packed) { + uiItemO(row, "", ICON_PACKAGE, "image.unpack"); } else { - /* Disable editing if image was modified, to avoid losing changes. */ - const bool is_dirty = BKE_image_is_dirty(ima); - if (is_dirty) { - row = uiLayoutRow(layout, true); - uiItemO(row, IFACE_("Save"), ICON_NONE, "image.save"); - uiItemO(row, IFACE_("Discard Changes"), ICON_NONE, "image.reload"); - uiItemS(layout); - } + uiItemO(row, "", ICON_UGLYPACKAGE, "image.pack"); + } - layout = uiLayoutColumn(layout, false); - uiLayoutSetEnabled(layout, !is_dirty); + row = uiLayoutRow(row, true); + uiLayoutSetEnabled(row, is_packed == false); + uiItemR(row, &imaptr, "filepath", 0, "", ICON_NONE); + uiItemO(row, "", ICON_FILE_REFRESH, "image.reload"); + } - /* Image source */ - uiItemR(layout, &imaptr, "source", 0, NULL, ICON_NONE); + /* Image layers and Info */ + if (ima->type == IMA_TYPE_MULTILAYER && ima->rr) { + uiItemS(layout); - /* Filepath */ - const bool is_packed = BKE_image_has_packedfile(ima); - const bool no_filepath = is_packed && !BKE_image_has_filepath(ima); + const float dpi_fac = UI_DPI_FAC; + uiblock_layer_pass_buttons(layout, ima, ima->rr, iuser, 230 * dpi_fac, NULL); + } + else if (ima->source == IMA_SRC_GENERATED) { + uiItemS(layout); - if ((ima->source != IMA_SRC_GENERATED) && !no_filepath) { - row = uiLayoutRow(layout, true); - if (is_packed) { - uiItemO(row, "", ICON_PACKAGE, "image.unpack"); - } - else { - uiItemO(row, "", ICON_UGLYPACKAGE, "image.pack"); - } + /* Generated */ + uiLayout *col = uiLayoutColumn(layout, false); + uiLayoutSetPropSep(col, true); - row = uiLayoutRow(row, true); - uiLayoutSetEnabled(row, is_packed == false); - uiItemR(row, &imaptr, "filepath", 0, "", ICON_NONE); - uiItemO(row, "", ICON_FILE_REFRESH, "image.reload"); - } + uiLayout *sub = uiLayoutColumn(col, true); + uiItemR(sub, &imaptr, "generated_width", 0, "X", ICON_NONE); + uiItemR(sub, &imaptr, "generated_height", 0, "Y", ICON_NONE); - /* Image layers and Info */ - if (ima->type == IMA_TYPE_MULTILAYER && ima->rr) { - const float dpi_fac = UI_DPI_FAC; - uiblock_layer_pass_buttons(layout, ima, ima->rr, iuser, 230 * dpi_fac, NULL); - } - else if (ima->source != IMA_SRC_GENERATED) { - if (compact == 0) { - uiTemplateImageInfo(layout, C, ima, iuser); - } - } + uiItemR(col, &imaptr, "use_generated_float", 0, NULL, ICON_NONE); - uiItemS(layout); + uiItemS(col); - col = uiLayoutColumn(layout, false); - uiTemplateColorspaceSettings(col, &imaptr, "colorspace_settings"); - uiItemR(col, &imaptr, "use_view_as_render", 0, NULL, ICON_NONE); + uiItemR(col, &imaptr, "generated_type", UI_ITEM_R_EXPAND, IFACE_("Type"), ICON_NONE); + if (ima->gen_type == IMA_GENTYPE_BLANK) { + uiItemR(col, &imaptr, "generated_color", 0, NULL, ICON_NONE); + } + } + else if (compact == 0) { + uiTemplateImageInfo(layout, C, ima, iuser); + } - uiItemS(layout); + if (BKE_image_is_animated(ima)) { + /* Animation */ + uiItemS(layout); - if (ima->source != IMA_SRC_GENERATED) { - if (compact == 0) { /* background image view doesn't need these */ - ImBuf *ibuf = BKE_image_acquire_ibuf(ima, iuser, NULL); - bool has_alpha = true; - - if (ibuf) { - int imtype = BKE_image_ftype_to_imtype(ibuf->ftype, &ibuf->foptions); - char valid_channels = BKE_imtype_valid_channels(imtype, false); - - has_alpha = (valid_channels & IMA_CHAN_FLAG_ALPHA) != 0; - - BKE_image_release_ibuf(ima, ibuf, NULL); - } - - if (multiview) { - if ((scene->r.scemode & R_MULTIVIEW) != 0) { - uiItemR(layout, &imaptr, "use_multiview", 0, NULL, ICON_NONE); - - if (RNA_boolean_get(&imaptr, "use_multiview")) { - uiTemplateImageViews(layout, &imaptr); - } - } - } - - if (has_alpha) { - col = uiLayoutColumn(layout, false); - uiItemR(col, &imaptr, "use_alpha", 0, NULL, ICON_NONE); - row = uiLayoutRow(col, false); - uiLayoutSetActive(row, RNA_boolean_get(&imaptr, "use_alpha")); - uiItemR(row, &imaptr, "alpha_mode", 0, IFACE_("Alpha"), ICON_NONE); - } - - if (ima->source == IMA_SRC_MOVIE) { - col = uiLayoutColumn(layout, false); - uiItemR(col, &imaptr, "use_deinterlace", 0, IFACE_("Deinterlace"), ICON_NONE); - } - } - } + uiLayout *col = uiLayoutColumn(layout, true); + uiLayoutSetPropSep(col, true); + + uiLayout *sub = uiLayoutColumn(col, true); + uiLayout *row = uiLayoutRow(sub, true); + uiItemR(row, userptr, "frame_duration", 0, IFACE_("Frames"), ICON_NONE); + uiItemO(row, "", ICON_FILE_REFRESH, "IMAGE_OT_match_movie_length"); + + uiItemR(sub, userptr, "frame_start", 0, IFACE_("Start"), ICON_NONE); + uiItemR(sub, userptr, "frame_offset", 0, NULL, ICON_NONE); - if (BKE_image_is_animated(ima)) { - uiItemS(layout); + uiItemR(col, userptr, "use_cyclic", 0, NULL, ICON_NONE); + uiItemR(col, userptr, "use_auto_refresh", 0, NULL, ICON_NONE); - split = uiLayoutSplit(layout, 0.0f, false); + if (ima->source == IMA_SRC_MOVIE && compact == 0) { + uiItemR(col, &imaptr, "use_deinterlace", 0, IFACE_("Deinterlace"), ICON_NONE); + } + } - col = uiLayoutColumn(split, false); + /* Multiview */ + if (multiview && compact == 0) { + if ((scene->r.scemode & R_MULTIVIEW) != 0) { + uiItemS(layout); - BLI_snprintf(str, sizeof(str), IFACE_("(%d) Frames"), iuser->framenr); - uiItemR(col, userptr, "frame_duration", 0, str, ICON_NONE); - uiItemR(col, userptr, "frame_start", 0, IFACE_("Start"), ICON_NONE); - uiItemR(col, userptr, "frame_offset", 0, NULL, ICON_NONE); + uiLayout *col = uiLayoutColumn(layout, false); + uiLayoutSetPropSep(col, true); + uiItemR(col, &imaptr, "use_multiview", 0, NULL, ICON_NONE); - col = uiLayoutColumn(split, false); - uiItemO(col, NULL, ICON_NONE, "IMAGE_OT_match_movie_length"); - uiItemR(col, userptr, "use_auto_refresh", 0, NULL, ICON_NONE); - uiItemR(col, userptr, "use_cyclic", 0, NULL, ICON_NONE); + if (RNA_boolean_get(&imaptr, "use_multiview")) { + uiTemplateImageViews(layout, &imaptr); } - else if (ima->source == IMA_SRC_GENERATED) { - split = uiLayoutSplit(layout, 0.0f, false); + } + } - col = uiLayoutColumn(split, true); - uiItemR(col, &imaptr, "generated_width", 0, "X", ICON_NONE); - uiItemR(col, &imaptr, "generated_height", 0, "Y", ICON_NONE); + /* Colorspace and alpha */ + { + uiItemS(layout); - uiItemR(col, &imaptr, "use_generated_float", 0, NULL, ICON_NONE); + uiLayout *col = uiLayoutColumn(layout, false); + uiLayoutSetPropSep(col, true); + uiTemplateColorspaceSettings(col, &imaptr, "colorspace_settings"); - uiItemR(split, &imaptr, "generated_type", UI_ITEM_R_EXPAND, NULL, ICON_NONE); + if (compact == 0) { + if (ima->source != IMA_SRC_GENERATED) { + if (image_has_alpha(ima, iuser)) { + uiLayout *sub = uiLayoutColumn(col, false); + uiItemR(sub, &imaptr, "alpha_mode", 0, IFACE_("Alpha"), ICON_NONE); - if (ima->gen_type == IMA_GENTYPE_BLANK) { - uiItemR(layout, &imaptr, "generated_color", 0, NULL, ICON_NONE); + bool is_data = IMB_colormanagement_space_name_is_data(ima->colorspace_settings.name); + uiLayoutSetActive(sub, !is_data); } } - } - UI_block_funcN_set(block, NULL, NULL, NULL); + uiItemR(col, &imaptr, "use_view_as_render", 0, NULL, ICON_NONE); + } } - MEM_freeN(cb); + UI_block_funcN_set(block, NULL, NULL, NULL); } void uiTemplateImageSettings(uiLayout *layout, PointerRNA *imfptr, bool color_management) @@ -1215,25 +1155,24 @@ void uiTemplateImageFormatViews(uiLayout *layout, PointerRNA *imfptr, PointerRNA { ImageFormatData *imf = imfptr->data; - if (ptr == NULL) { - return; + if (ptr != NULL) { + uiItemR(layout, ptr, "use_multiview", 0, NULL, ICON_NONE); + if (!RNA_boolean_get(ptr, "use_multiview")) { + return; + } } - uiItemR(layout, ptr, "use_multiview", 0, NULL, ICON_NONE); - - if (RNA_boolean_get(ptr, "use_multiview")) { - if (imf->imtype != R_IMF_IMTYPE_MULTILAYER) { - PropertyRNA *prop; - PointerRNA stereo3d_format_ptr; + if (imf->imtype != R_IMF_IMTYPE_MULTILAYER) { + PropertyRNA *prop; + PointerRNA stereo3d_format_ptr; - prop = RNA_struct_find_property(imfptr, "stereo_3d_format"); - stereo3d_format_ptr = RNA_property_pointer_get(imfptr, prop); + prop = RNA_struct_find_property(imfptr, "stereo_3d_format"); + stereo3d_format_ptr = RNA_property_pointer_get(imfptr, prop); - uiTemplateViewsFormat(layout, imfptr, &stereo3d_format_ptr); - } - else { - uiTemplateViewsFormat(layout, imfptr, NULL); - } + uiTemplateViewsFormat(layout, imfptr, &stereo3d_format_ptr); + } + else { + uiTemplateViewsFormat(layout, imfptr, NULL); } } @@ -1258,21 +1197,87 @@ void uiTemplateImageLayers(uiLayout *layout, bContext *C, Image *ima, ImageUser void uiTemplateImageInfo(uiLayout *layout, bContext *C, Image *ima, ImageUser *iuser) { - Scene *scene = CTX_data_scene(C); - ImBuf *ibuf; - char str[MAX_IMAGE_INFO_LEN]; + if (ima == NULL || iuser == NULL) { + return; + } + + /* Acquire image buffer. */ void *lock; + ImBuf *ibuf = BKE_image_acquire_ibuf(ima, iuser, &lock); - if (!ima || !iuser) { - return; + uiLayout *col = uiLayoutColumn(layout, true); + uiLayoutSetAlignment(col, UI_LAYOUT_ALIGN_RIGHT); + + if (ibuf == NULL) { + uiItemL(col, IFACE_("Can't Load Image"), ICON_NONE); } + else { + char str[MAX_IMAGE_INFO_LEN] = {0}; + const int len = MAX_IMAGE_INFO_LEN; + int ofs = 0; - ibuf = BKE_image_acquire_ibuf(ima, iuser, &lock); + ofs += BLI_snprintf(str + ofs, len - ofs, IFACE_("%d x %d, "), ibuf->x, ibuf->y); + + if (ibuf->rect_float) { + if (ibuf->channels != 4) { + ofs += BLI_snprintf(str + ofs, len - ofs, IFACE_("%d float channel(s)"), ibuf->channels); + } + else if (ibuf->planes == R_IMF_PLANES_RGBA) { + ofs += BLI_strncpy_rlen(str + ofs, IFACE_(" RGBA float"), len - ofs); + } + else { + ofs += BLI_strncpy_rlen(str + ofs, IFACE_(" RGB float"), len - ofs); + } + } + else { + if (ibuf->planes == R_IMF_PLANES_RGBA) { + ofs += BLI_strncpy_rlen(str + ofs, IFACE_(" RGBA byte"), len - ofs); + } + else { + ofs += BLI_strncpy_rlen(str + ofs, IFACE_(" RGB byte"), len - ofs); + } + } + if (ibuf->zbuf || ibuf->zbuf_float) { + ofs += BLI_strncpy_rlen(str + ofs, IFACE_(" + Z"), len - ofs); + } + + uiItemL(col, str, ICON_NONE); + } + + /* Frame number, even if we can't load the image. */ + if (ELEM(ima->source, IMA_SRC_SEQUENCE, IMA_SRC_MOVIE)) { + /* don't use iuser->framenr directly because it may not be updated if auto-refresh is off */ + Scene *scene = CTX_data_scene(C); + const int framenr = BKE_image_user_frame_get(iuser, CFRA, NULL); + char str[MAX_IMAGE_INFO_LEN]; + int duration = 0; + + if (ima->source == IMA_SRC_MOVIE && BKE_image_has_anim(ima)) { + struct anim *anim = ((ImageAnim *)ima->anims.first)->anim; + if (anim) { + duration = IMB_anim_get_duration(anim, IMB_TC_RECORD_RUN); + } + } + + if (duration > 0) { + /* Movie duration */ + BLI_snprintf(str, MAX_IMAGE_INFO_LEN, IFACE_("Frame %d / %d"), framenr, duration); + } + else if (ima->source == IMA_SRC_SEQUENCE && ibuf) { + /* Image sequence frame number + filename */ + const char *filename = BLI_last_slash(ibuf->name); + filename = (filename == NULL) ? ibuf->name : filename + 1; + BLI_snprintf(str, MAX_IMAGE_INFO_LEN, IFACE_("Frame %d: %s"), framenr, filename); + } + else { + /* Frame number */ + BLI_snprintf(str, MAX_IMAGE_INFO_LEN, IFACE_("Frame %d"), framenr); + } + + uiItemL(col, str, ICON_NONE); + } - BKE_image_user_frame_calc(iuser, (int)scene->r.cfra); - image_info(scene, iuser, ima, ibuf, str, MAX_IMAGE_INFO_LEN); BKE_image_release_ibuf(ima, ibuf, lock); - uiItemL(layout, str, ICON_NONE); } #undef MAX_IMAGE_INFO_LEN @@ -1304,6 +1309,7 @@ void image_buttons_register(ARegionType *art) strcpy(pt->label, N_("Metadata")); strcpy(pt->category, "Image"); strcpy(pt->translation_context, BLT_I18NCONTEXT_DEFAULT_BPYRNA); + pt->order = 10; pt->poll = metadata_panel_context_poll; pt->draw = metadata_panel_context_draw; pt->flag |= PNL_DEFAULT_CLOSED; diff --git a/source/blender/editors/space_image/image_ops.c b/source/blender/editors/space_image/image_ops.c index 07c2d216a93..8121c577706 100644 --- a/source/blender/editors/space_image/image_ops.c +++ b/source/blender/editors/space_image/image_ops.c @@ -1320,7 +1320,7 @@ static int image_open_exec(bContext *C, wmOperator *op) PointerRNA imaptr; RNA_id_pointer_create(&ima->id, &imaptr); - RNA_property_pointer_set(NULL, &iod->pprop.ptr, iod->pprop.prop, imaptr); + RNA_property_pointer_set(&iod->pprop.ptr, iod->pprop.prop, imaptr, NULL); RNA_property_update(C, &iod->pprop.ptr, iod->pprop.prop); } @@ -1869,8 +1869,7 @@ static int image_save_as_invoke(bContext *C, wmOperator *op, const wmEvent *UNUS Scene *scene = CTX_data_scene(C); ImageSaveOptions opts; PropertyRNA *prop; - const bool save_as_render = ((ima->source == IMA_SRC_VIEWER) || - (ima->flag & IMA_VIEW_AS_RENDER)); + const bool save_as_render = (ima->source == IMA_SRC_VIEWER); if (RNA_struct_property_is_set(op->ptr, "filepath")) { return image_save_as_exec(C, op); @@ -2474,7 +2473,7 @@ static int image_new_exec(bContext *C, wmOperator *op) PointerRNA imaptr; RNA_id_pointer_create(&ima->id, &imaptr); - RNA_property_pointer_set(NULL, &data->pprop.ptr, data->pprop.prop, imaptr); + RNA_property_pointer_set(&data->pprop.ptr, data->pprop.prop, imaptr, NULL); RNA_property_update(C, &data->pprop.ptr, data->pprop.prop); } else if (sima) { diff --git a/source/blender/editors/space_image/space_image.c b/source/blender/editors/space_image/space_image.c index a8be93ad213..73baf1540f7 100644 --- a/source/blender/editors/space_image/space_image.c +++ b/source/blender/editors/space_image/space_image.c @@ -658,7 +658,8 @@ static void image_main_region_draw(const bContext *C, ARegion *ar) BLI_thread_unlock(LOCK_DRAW_IMAGE); } - ED_mask_draw_region(mask, + ED_mask_draw_region(depsgraph, + mask, ar, sima->mask_info.draw_flag, sima->mask_info.draw_type, diff --git a/source/blender/editors/space_nla/space_nla.c b/source/blender/editors/space_nla/space_nla.c index 4b7dfe5d653..3bdd2804efc 100644 --- a/source/blender/editors/space_nla/space_nla.c +++ b/source/blender/editors/space_nla/space_nla.c @@ -205,7 +205,7 @@ static void nla_channel_region_draw(const bContext *C, ARegion *ar) } /* channel filter next to scrubbing area */ - ED_channel_search_draw(C, ar, ac.ads); + ED_time_scrub_channel_search_draw(C, ar, ac.ads); /* reset view matrix */ UI_view2d_view_restore(C); @@ -290,7 +290,7 @@ static void nla_main_region_draw(const bContext *C, ARegion *ar) /* reset view matrix */ UI_view2d_view_restore(C); - ED_scrubbing_draw(ar, scene, snla->flag & SNLA_DRAWTIME, true); + ED_time_scrub_draw(ar, scene, snla->flag & SNLA_DRAWTIME, true); /* scrollers */ scrollers = UI_view2d_scrollers_calc(v2d, NULL); diff --git a/source/blender/editors/space_node/drawnode.c b/source/blender/editors/space_node/drawnode.c index bf6ec961a5d..e39e024e44a 100644 --- a/source/blender/editors/space_node/drawnode.c +++ b/source/blender/editors/space_node/drawnode.c @@ -713,6 +713,11 @@ static void node_buts_image_user(uiLayout *layout, PointerRNA colorspace_settings_ptr = RNA_pointer_get(imaptr, "colorspace_settings"); uiItemL(split, IFACE_("Color Space"), ICON_NONE); uiItemR(split, &colorspace_settings_ptr, "name", 0, "", ICON_NONE); + + /* Avoid losing changes image is painted. */ + if (BKE_image_is_dirty(imaptr->data)) { + uiLayoutSetEnabled(split, false); + } } static void node_shader_buts_mapping(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) diff --git a/source/blender/editors/space_node/node_add.c b/source/blender/editors/space_node/node_add.c index e677c649fb4..01a30f677a3 100644 --- a/source/blender/editors/space_node/node_add.c +++ b/source/blender/editors/space_node/node_add.c @@ -521,7 +521,7 @@ static int new_node_tree_exec(bContext *C, wmOperator *op) id_us_min(&ntree->id); RNA_id_pointer_create(&ntree->id, &idptr); - RNA_property_pointer_set(NULL, &ptr, prop, idptr); + RNA_property_pointer_set(&ptr, prop, idptr, NULL); RNA_property_update(C, &ptr, prop); } else if (snode) { diff --git a/source/blender/editors/space_node/node_select.c b/source/blender/editors/space_node/node_select.c index a8331c26ce6..aab328249fe 100644 --- a/source/blender/editors/space_node/node_select.c +++ b/source/blender/editors/space_node/node_select.c @@ -495,17 +495,7 @@ static int node_mouse_select(bContext *C, } } - /* In case we do two-steps selection, we do not want to select the node if some valid socket - * is below the mouse, as that would prevent draging from sockets (NODE_OT_link) - * to be properly triggered. See T64660. */ - if (wait_to_deselect_others) { - if (node_find_indicated_socket(snode, &node, &sock, cursor, SOCK_IN) || - node_find_indicated_socket(snode, &node, &sock, cursor, SOCK_OUT)) { - ret_value = OPERATOR_CANCELLED; - } - } - - if (sock == NULL) { + if (!sock) { /* find the closest visible node */ node = node_under_mouse_select(snode->edittree, (int)cursor[0], (int)cursor[1]); diff --git a/source/blender/editors/space_outliner/outliner_draw.c b/source/blender/editors/space_outliner/outliner_draw.c index 6a7795393c9..aed7af3911f 100644 --- a/source/blender/editors/space_outliner/outliner_draw.c +++ b/source/blender/editors/space_outliner/outliner_draw.c @@ -2802,7 +2802,11 @@ static void outliner_draw_tree_element(bContext *C, BKE_view_layer_base_find(view_layer, ob); const bool is_selected = (base != NULL) && ((base->flag & BASE_SELECTED) != 0); - if (ob == obact || is_selected) { + if (ob == obact) { + active = OL_DRAWSEL_ACTIVE; + } + + if (is_selected) { if (ob == obact) { /* active selected object */ UI_GetThemeColor3ubv(TH_ACTIVE_OBJECT, text_color); diff --git a/source/blender/editors/space_outliner/outliner_edit.c b/source/blender/editors/space_outliner/outliner_edit.c index 90180c4ea47..c32b2b051f8 100644 --- a/source/blender/editors/space_outliner/outliner_edit.c +++ b/source/blender/editors/space_outliner/outliner_edit.c @@ -88,6 +88,11 @@ static int outliner_highlight_update(bContext *C, wmOperator *UNUSED(op), const wmEvent *event) { + /* stop highlighting if out of area */ + if (!ED_screen_area_active(C)) { + return OPERATOR_PASS_THROUGH; + } + /* Drag and drop does own highlighting. */ wmWindowManager *wm = CTX_wm_manager(C); if (wm->drags.first) { diff --git a/source/blender/editors/space_outliner/outliner_select.c b/source/blender/editors/space_outliner/outliner_select.c index c6fcf1d8cf7..bee615108f9 100644 --- a/source/blender/editors/space_outliner/outliner_select.c +++ b/source/blender/editors/space_outliner/outliner_select.c @@ -450,32 +450,6 @@ static eOLDrawState tree_element_active_material(bContext *C, return OL_DRAWSEL_NONE; } -static eOLDrawState tree_element_active_light(bContext *UNUSED(C), - Scene *UNUSED(scene), - ViewLayer *view_layer, - SpaceOutliner *soops, - TreeElement *te, - const eOLSetState set) -{ - Object *ob; - - /* we search for the object parent */ - ob = (Object *)outliner_search_back(soops, te, ID_OB); - if (ob == NULL || ob != OBACT(view_layer)) { - /* just paranoia */ - return OL_DRAWSEL_NONE; - } - - if (set != OL_SETSEL_NONE) { - // XXX extern_set_butspace(F5KEY, 0); - } - else { - return OL_DRAWSEL_NORMAL; - } - - return OL_DRAWSEL_NONE; -} - static eOLDrawState tree_element_active_camera(bContext *UNUSED(C), Scene *scene, ViewLayer *UNUSED(sl), @@ -1041,8 +1015,6 @@ eOLDrawState tree_element_active(bContext *C, return tree_element_active_material(C, scene, view_layer, soops, te, set); case ID_WO: return tree_element_active_world(C, scene, view_layer, soops, te, set); - case ID_LA: - return tree_element_active_light(C, scene, view_layer, soops, te, set); case ID_TXT: return tree_element_active_text(C, scene, view_layer, soops, te, set); case ID_CA: @@ -1160,7 +1132,7 @@ static void do_outliner_item_activate_tree_element(bContext *C, WM_window_set_active_scene(CTX_data_main(C), C, CTX_wm_window(C), (Scene *)tselem->id); } } - else if (te->idcode == ID_GR) { + else if ((te->idcode == ID_GR) && (soops->outlinevis != SO_VIEW_LAYER)) { Collection *gr = (Collection *)tselem->id; if (extend) { diff --git a/source/blender/editors/space_outliner/outliner_tree.c b/source/blender/editors/space_outliner/outliner_tree.c index 80424f021e2..6da2e913003 100644 --- a/source/blender/editors/space_outliner/outliner_tree.c +++ b/source/blender/editors/space_outliner/outliner_tree.c @@ -1808,7 +1808,7 @@ static void outliner_collections_children_sort(ListBase *lb) } for (te = lb->first; te; te = te->next) { - outliner_sort(&te->subtree); + outliner_collections_children_sort(&te->subtree); } } diff --git a/source/blender/editors/space_outliner/space_outliner.c b/source/blender/editors/space_outliner/space_outliner.c index 4c591a61f67..091efc56c09 100644 --- a/source/blender/editors/space_outliner/space_outliner.c +++ b/source/blender/editors/space_outliner/space_outliner.c @@ -303,6 +303,7 @@ static SpaceLink *outliner_new(const ScrArea *UNUSED(area), const Scene *UNUSED( soutliner->spacetype = SPACE_OUTLINER; soutliner->filter_id_type = ID_GR; soutliner->show_restrict_flags = SO_RESTRICT_ENABLE | SO_RESTRICT_HIDE; + soutliner->outlinevis = SO_VIEW_LAYER; /* header */ ar = MEM_callocN(sizeof(ARegion), "header for outliner"); @@ -384,6 +385,14 @@ static void outliner_id_remap(ScrArea *UNUSED(sa), SpaceLink *slink, ID *old_id, } } +static void outliner_deactivate(struct ScrArea *sa) +{ + /* Remove hover highlights */ + SpaceOutliner *soops = sa->spacedata.first; + outliner_flag_set(&soops->tree, TSE_HIGHLIGHTED, false); + ED_region_tag_redraw(BKE_area_find_region_type(sa, RGN_TYPE_WINDOW)); +} + /* only called once, from space_api/spacetypes.c */ void ED_spacetype_outliner(void) { @@ -401,6 +410,7 @@ void ED_spacetype_outliner(void) st->keymap = outliner_keymap; st->dropboxes = outliner_dropboxes; st->id_remap = outliner_id_remap; + st->deactivate = outliner_deactivate; /* regions: main window */ art = MEM_callocN(sizeof(ARegionType), "spacetype outliner region"); diff --git a/source/blender/editors/space_sequencer/sequencer_add.c b/source/blender/editors/space_sequencer/sequencer_add.c index b5bb79fb430..e8f18eeebc7 100644 --- a/source/blender/editors/space_sequencer/sequencer_add.c +++ b/source/blender/editors/space_sequencer/sequencer_add.c @@ -149,7 +149,7 @@ static int sequencer_generic_invoke_xy_guess_channel(bContext *C, int type) int proximity = INT_MAX; if (!ed || !ed->seqbasep) { - return 1; + return 2; } for (seq = ed->seqbasep->first; seq; seq = seq->next) { @@ -161,9 +161,9 @@ static int sequencer_generic_invoke_xy_guess_channel(bContext *C, int type) } if (tgt) { - return tgt->machine; + return tgt->machine + 1; } - return 1; + return 2; } static void sequencer_generic_invoke_xy__internal(bContext *C, wmOperator *op, int flag, int type) @@ -173,7 +173,7 @@ static void sequencer_generic_invoke_xy__internal(bContext *C, wmOperator *op, i int cfra = (int)CFRA; /* effect strips don't need a channel initialized from the mouse */ - if (!(flag & SEQPROP_NOCHAN)) { + if (!(flag & SEQPROP_NOCHAN) && RNA_struct_property_is_set(op->ptr, "channel") == 0) { RNA_int_set(op->ptr, "channel", sequencer_generic_invoke_xy_guess_channel(C, type)); } diff --git a/source/blender/editors/space_sequencer/sequencer_draw.c b/source/blender/editors/space_sequencer/sequencer_draw.c index 805ec26950a..a59cc36f28e 100644 --- a/source/blender/editors/space_sequencer/sequencer_draw.c +++ b/source/blender/editors/space_sequencer/sequencer_draw.c @@ -1121,8 +1121,7 @@ static void sequencer_display_size(Scene *scene, float r_viewrect[2]) r_viewrect[0] = (float)scene->r.xsch; r_viewrect[1] = (float)scene->r.ysch; - /* Aspect ratio seems to have no effect on output image*/ - /* r_viewrect[0] *= scene->r.xasp / scene->r.yasp; */ + r_viewrect[0] *= scene->r.xasp / scene->r.yasp; } static void sequencer_draw_gpencil(const bContext *C) @@ -1822,7 +1821,7 @@ typedef struct CacheDrawData { /* Called as a callback */ static bool draw_cache_view_cb( - void *userdata, struct Sequence *seq, int cfra, int cache_type, float UNUSED(cost)) + void *userdata, struct Sequence *seq, int nfra, int cache_type, float UNUSED(cost)) { CacheDrawData *drawdata = userdata; const bContext *C = drawdata->C; @@ -1902,6 +1901,7 @@ static bool draw_cache_view_cb( } } + int cfra = seq->start + nfra; immUniformColor4f(color[0], color[1], color[2], color[3]); immRectf(pos, cfra, stripe_bot, cfra + 1, stripe_top); @@ -2087,7 +2087,7 @@ void draw_timeline_seq(const bContext *C, ARegion *ar) UI_view2d_view_restore(C); /* scrubbing region */ - ED_scrubbing_draw(ar, scene, !(sseq->flag & SEQ_DRAWFRAMES), true); + ED_time_scrub_draw(ar, scene, !(sseq->flag & SEQ_DRAWFRAMES), true); /* scrollers */ scrollers = UI_view2d_scrollers_calc(v2d, NULL); @@ -2101,7 +2101,7 @@ void draw_timeline_seq(const bContext *C, ARegion *ar) 0, 15 * UI_DPI_FAC, 15 * UI_DPI_FAC, - UI_DPI_FAC * ar->sizey - UI_SCRUBBING_MARGIN_Y); + UI_DPI_FAC * ar->sizey - UI_TIME_SCRUB_MARGIN_Y); UI_view2d_draw_scale_y__block(ar, v2d, &rect, TH_SCROLL_TEXT); } } diff --git a/source/blender/editors/space_sequencer/sequencer_edit.c b/source/blender/editors/space_sequencer/sequencer_edit.c index a3030153e6c..a998ae7a7b3 100644 --- a/source/blender/editors/space_sequencer/sequencer_edit.c +++ b/source/blender/editors/space_sequencer/sequencer_edit.c @@ -2680,7 +2680,7 @@ static int sequencer_meta_make_exec(bContext *C, wmOperator *op) while (seq) { next = seq->next; if (seq != seqm && (seq->flag & SELECT)) { - BKE_sequence_invalidate_cache(scene, seq); + BKE_sequence_invalidate_dependent(scene, seq); channel_max = max_ii(seq->machine, channel_max); BLI_remlink(ed->seqbasep, seq); BLI_addtail(&seqm->seqbase, seq); @@ -2755,7 +2755,7 @@ static int sequencer_meta_separate_exec(bContext *C, wmOperator *UNUSED(op)) } for (seq = last_seq->seqbase.first; seq != NULL; seq = seq->next) { - BKE_sequence_invalidate_cache(scene, seq); + BKE_sequence_invalidate_dependent(scene, seq); } BLI_movelisttolist(ed->seqbasep, &last_seq->seqbase); @@ -3518,8 +3518,8 @@ static int sequencer_swap_data_exec(bContext *C, wmOperator *op) BKE_sound_add_scene_sound_defaults(scene, seq_other); } - BKE_sequence_invalidate_cache(scene, seq_act); - BKE_sequence_invalidate_cache(scene, seq_other); + BKE_sequence_invalidate_cache_raw(scene, seq_act); + BKE_sequence_invalidate_cache_raw(scene, seq_other); WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene); diff --git a/source/blender/editors/space_sequencer/sequencer_modifier.c b/source/blender/editors/space_sequencer/sequencer_modifier.c index e00d33853a3..f262c6518aa 100644 --- a/source/blender/editors/space_sequencer/sequencer_modifier.c +++ b/source/blender/editors/space_sequencer/sequencer_modifier.c @@ -64,7 +64,7 @@ static int strip_modifier_add_exec(bContext *C, wmOperator *op) BKE_sequence_modifier_new(seq, NULL, type); - BKE_sequence_invalidate_cache(scene, seq); + BKE_sequence_invalidate_cache_preprocessed(scene, seq); WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene); return OPERATOR_FINISHED; @@ -115,7 +115,7 @@ static int strip_modifier_remove_exec(bContext *C, wmOperator *op) BLI_remlink(&seq->modifiers, smd); BKE_sequence_modifier_free(smd); - BKE_sequence_invalidate_cache(scene, seq); + BKE_sequence_invalidate_cache_preprocessed(scene, seq); WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene); return OPERATOR_FINISHED; @@ -175,7 +175,7 @@ static int strip_modifier_move_exec(bContext *C, wmOperator *op) } } - BKE_sequence_invalidate_cache(scene, seq); + BKE_sequence_invalidate_cache_preprocessed(scene, seq); WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene); return OPERATOR_FINISHED; @@ -249,7 +249,7 @@ static int strip_modifier_copy_exec(bContext *C, wmOperator *op) } SEQ_END; - BKE_sequence_invalidate_cache(scene, seq); + BKE_sequence_invalidate_cache_preprocessed(scene, seq); WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene); return OPERATOR_FINISHED; diff --git a/source/blender/editors/space_sequencer/sequencer_view.c b/source/blender/editors/space_sequencer/sequencer_view.c index e16029395bd..593dd86477a 100644 --- a/source/blender/editors/space_sequencer/sequencer_view.c +++ b/source/blender/editors/space_sequencer/sequencer_view.c @@ -108,6 +108,8 @@ static void sample_apply(bContext *C, wmOperator *op, const wmEvent *event) UI_view2d_region_to_view(&ar->v2d, event->mval[0], event->mval[1], &fx, &fy); + fx /= scene->r.xasp / scene->r.yasp; + fx += (float)scene->r.xsch / 2.0f; fy += (float)scene->r.ysch / 2.0f; fx *= (float)ibuf->x / (float)scene->r.xsch; diff --git a/source/blender/editors/space_sequencer/space_sequencer.c b/source/blender/editors/space_sequencer/space_sequencer.c index 7a02b1850ae..6ab44ded046 100644 --- a/source/blender/editors/space_sequencer/space_sequencer.c +++ b/source/blender/editors/space_sequencer/space_sequencer.c @@ -729,6 +729,7 @@ static void sequencer_buttons_region_init(wmWindowManager *wm, ARegion *ar) keymap = WM_keymap_ensure(wm->defaultconf, "SequencerCommon", SPACE_SEQ, 0); WM_event_add_keymap_handler_v2d_mask(&ar->handlers, keymap); + UI_panel_category_active_set_default(ar, "Strip"); ED_region_panels_init(wm, ar); } diff --git a/source/blender/editors/space_text/text_ops.c b/source/blender/editors/space_text/text_ops.c index a9dd2a59d1e..2593571d9a3 100644 --- a/source/blender/editors/space_text/text_ops.c +++ b/source/blender/editors/space_text/text_ops.c @@ -247,7 +247,7 @@ static int text_new_exec(bContext *C, wmOperator *UNUSED(op)) if (prop) { RNA_id_pointer_create(&text->id, &idptr); - RNA_property_pointer_set(NULL, &ptr, prop, idptr); + RNA_property_pointer_set(&ptr, prop, idptr, NULL); RNA_property_update(C, &ptr, prop); } else if (st) { @@ -326,7 +326,7 @@ static int text_open_exec(bContext *C, wmOperator *op) if (pprop->prop) { RNA_id_pointer_create(&text->id, &idptr); - RNA_property_pointer_set(NULL, &pprop->ptr, pprop->prop, idptr); + RNA_property_pointer_set(&pprop->ptr, pprop->prop, idptr, NULL); RNA_property_update(C, &pprop->ptr, pprop->prop); } else if (st) { diff --git a/source/blender/editors/space_userpref/userpref_ops.c b/source/blender/editors/space_userpref/userpref_ops.c index a67e6c27acb..04ef2ed8118 100644 --- a/source/blender/editors/space_userpref/userpref_ops.c +++ b/source/blender/editors/space_userpref/userpref_ops.c @@ -48,7 +48,7 @@ static int reset_default_theme_exec(bContext *C, wmOperator *UNUSED(op)) UI_theme_init_default(); UI_style_init_default(); WM_event_add_notifier(C, NC_WINDOW, NULL); - + U.runtime.is_dirty = true; return OPERATOR_FINISHED; } diff --git a/source/blender/editors/space_view3d/view3d_draw.c b/source/blender/editors/space_view3d/view3d_draw.c index afc3b80fe3e..2ce67bfbe4c 100644 --- a/source/blender/editors/space_view3d/view3d_draw.c +++ b/source/blender/editors/space_view3d/view3d_draw.c @@ -105,7 +105,8 @@ void ED_view3d_update_viewmat(Depsgraph *depsgraph, ARegion *ar, float viewmat[4][4], float winmat[4][4], - const rcti *rect) + const rcti *rect, + bool offscreen) { RegionView3D *rv3d = ar->regiondata; @@ -138,7 +139,7 @@ void ED_view3d_update_viewmat(Depsgraph *depsgraph, /* calculate GLSL view dependent values */ /* store window coordinates scaling/offset */ - if (rv3d->persp == RV3D_CAMOB && v3d->camera) { + if (!offscreen && rv3d->persp == RV3D_CAMOB && v3d->camera) { rctf cameraborder; ED_view3d_calc_camera_border(scene, depsgraph, ar, v3d, rv3d, &cameraborder, false); rv3d->viewcamtexcofac[0] = (float)ar->winx / BLI_rctf_size_x(&cameraborder); @@ -184,7 +185,22 @@ static void view3d_main_region_setup_view(Depsgraph *depsgraph, { RegionView3D *rv3d = ar->regiondata; - ED_view3d_update_viewmat(depsgraph, scene, v3d, ar, viewmat, winmat, rect); + ED_view3d_update_viewmat(depsgraph, scene, v3d, ar, viewmat, winmat, rect, false); + + /* set for opengl */ + GPU_matrix_projection_set(rv3d->winmat); + GPU_matrix_set(rv3d->viewmat); +} + +static void view3d_main_region_setup_offscreen(Depsgraph *depsgraph, + Scene *scene, + View3D *v3d, + ARegion *ar, + float viewmat[4][4], + float winmat[4][4]) +{ + RegionView3D *rv3d = ar->regiondata; + ED_view3d_update_viewmat(depsgraph, scene, v3d, ar, viewmat, winmat, NULL, true); /* set for opengl */ GPU_matrix_projection_set(rv3d->winmat); @@ -1480,14 +1496,14 @@ static void view3d_stereo3d_setup_offscreen(Depsgraph *depsgraph, const bool is_left = STREQ(viewname, STEREO_LEFT_NAME); BKE_camera_multiview_view_matrix(&scene->r, v3d->camera, is_left, viewmat); - view3d_main_region_setup_view(depsgraph, scene, v3d, ar, viewmat, winmat, NULL); + view3d_main_region_setup_offscreen(depsgraph, scene, v3d, ar, viewmat, winmat); } else { /* SCE_VIEWS_FORMAT_MULTIVIEW */ float viewmat[4][4]; Object *camera = BKE_camera_multiview_render(scene, v3d->camera, viewname); BKE_camera_multiview_view_matrix(&scene->r, camera, false, viewmat); - view3d_main_region_setup_view(depsgraph, scene, v3d, ar, viewmat, winmat, NULL); + view3d_main_region_setup_offscreen(depsgraph, scene, v3d, ar, viewmat, winmat); } } @@ -1545,7 +1561,7 @@ void ED_view3d_draw_offscreen(Depsgraph *depsgraph, view3d_stereo3d_setup_offscreen(depsgraph, scene, v3d, ar, winmat, viewname); } else { - view3d_main_region_setup_view(depsgraph, scene, v3d, ar, viewmat, winmat, NULL); + view3d_main_region_setup_offscreen(depsgraph, scene, v3d, ar, viewmat, winmat); } /* main drawing call */ @@ -1579,7 +1595,6 @@ ImBuf *ED_view3d_draw_offscreen_imbuf(Depsgraph *depsgraph, int sizex, int sizey, uint flag, - uint draw_flags, int alpha_mode, int samples, const char *viewname, @@ -1589,7 +1604,6 @@ ImBuf *ED_view3d_draw_offscreen_imbuf(Depsgraph *depsgraph, { RegionView3D *rv3d = ar->regiondata; const bool draw_sky = (alpha_mode == R_ADDSKY); - const bool use_full_sample = (draw_flags & V3D_OFSDRAW_USE_FULL_SAMPLE); /* view state */ bool is_ortho = false; @@ -1611,7 +1625,7 @@ ImBuf *ED_view3d_draw_offscreen_imbuf(Depsgraph *depsgraph, if (own_ofs) { /* bind */ - ofs = GPU_offscreen_create(sizex, sizey, use_full_sample ? 0 : samples, true, false, err_out); + ofs = GPU_offscreen_create(sizex, sizey, samples, true, false, err_out); if (ofs == NULL) { DRW_opengl_context_disable(); return NULL; @@ -1667,120 +1681,28 @@ ImBuf *ED_view3d_draw_offscreen_imbuf(Depsgraph *depsgraph, } } - if ((samples && use_full_sample) == 0) { - const bool do_color_management = (ibuf->rect_float == NULL); - /* Single-pass render, common case */ - ED_view3d_draw_offscreen(depsgraph, - scene, - drawtype, - v3d, - ar, - sizex, - sizey, - NULL, - winmat, - draw_sky, - !is_ortho, - viewname, - do_color_management, - ofs, - NULL); - - if (ibuf->rect_float) { - GPU_offscreen_read_pixels(ofs, GL_FLOAT, ibuf->rect_float); - } - else if (ibuf->rect) { - GPU_offscreen_read_pixels(ofs, GL_UNSIGNED_BYTE, ibuf->rect); - } - } - else { - /* Multi-pass render, use accumulation buffer & jitter for 'full' oversampling. - * Use because OpenGL may use a lower quality MSAA, and only over-sample edges. */ - static float jit_ofs[32][2]; - float winmat_jitter[4][4]; - float *rect_temp = (ibuf->rect_float) ? - ibuf->rect_float : - MEM_mallocN(sizex * sizey * sizeof(float[4]), "rect_temp"); - float *accum_buffer = MEM_mallocN(sizex * sizey * sizeof(float[4]), "accum_buffer"); - GPUViewport *viewport = GPU_viewport_create_from_offscreen(ofs); - - BLI_jitter_init(jit_ofs, samples); - - /* first sample buffer, also initializes 'rv3d->persmat' */ - ED_view3d_draw_offscreen(depsgraph, - scene, - drawtype, - v3d, - ar, - sizex, - sizey, - NULL, - winmat, - draw_sky, - !is_ortho, - viewname, - false, - ofs, - viewport); - GPU_offscreen_read_pixels(ofs, GL_FLOAT, accum_buffer); - - /* skip the first sample */ - for (int j = 1; j < samples; j++) { - copy_m4_m4(winmat_jitter, winmat); - window_translate_m4(winmat_jitter, - rv3d->persmat, - (jit_ofs[j][0] * 2.0f) / sizex, - (jit_ofs[j][1] * 2.0f) / sizey); - - ED_view3d_draw_offscreen(depsgraph, - scene, - drawtype, - v3d, - ar, - sizex, - sizey, - NULL, - winmat_jitter, - draw_sky, - !is_ortho, - viewname, - false, - ofs, - viewport); - GPU_offscreen_read_pixels(ofs, GL_FLOAT, rect_temp); - - uint i = sizex * sizey * 4; - while (i--) { - accum_buffer[i] += rect_temp[i]; - } - } - - { - /* don't free data owned by 'ofs' */ - GPU_viewport_clear_from_offscreen(viewport); - GPU_viewport_free(viewport); - } + const bool do_color_management = (ibuf->rect_float == NULL); + ED_view3d_draw_offscreen(depsgraph, + scene, + drawtype, + v3d, + ar, + sizex, + sizey, + NULL, + winmat, + draw_sky, + !is_ortho, + viewname, + do_color_management, + ofs, + NULL); - if (ibuf->rect_float == NULL) { - MEM_freeN(rect_temp); - } - - if (ibuf->rect_float) { - float *rect_float = ibuf->rect_float; - uint i = sizex * sizey * 4; - while (i--) { - rect_float[i] = accum_buffer[i] / samples; - } - } - else { - uchar *rect_ub = (uchar *)ibuf->rect; - uint i = sizex * sizey * 4; - while (i--) { - rect_ub[i] = (uchar)(255.0f * accum_buffer[i] / samples); - } - } - - MEM_freeN(accum_buffer); + if (ibuf->rect_float) { + GPU_offscreen_read_pixels(ofs, GL_FLOAT, ibuf->rect_float); + } + else if (ibuf->rect) { + GPU_offscreen_read_pixels(ofs, GL_UNSIGNED_BYTE, ibuf->rect); } /* unbind */ @@ -1889,7 +1811,6 @@ ImBuf *ED_view3d_draw_offscreen_imbuf_simple(Depsgraph *depsgraph, width, height, flag, - draw_flags, alpha_mode, samples, viewname, diff --git a/source/blender/editors/space_view3d/view3d_draw_legacy.c b/source/blender/editors/space_view3d/view3d_draw_legacy.c index e0dbe1f6543..755852a2e18 100644 --- a/source/blender/editors/space_view3d/view3d_draw_legacy.c +++ b/source/blender/editors/space_view3d/view3d_draw_legacy.c @@ -152,13 +152,11 @@ void ED_view3d_clipping_enable(void) /* *********************** backdraw for selection *************** */ -static void validate_object_select_id(struct Depsgraph *depsgraph, - Scene *scene, - ARegion *ar, - View3D *v3d, - Object *obact, - Object *obedit, - short select_mode) +/** + * \note Only use in object mode. + */ +static void validate_object_select_id( + struct Depsgraph *depsgraph, Scene *scene, ARegion *ar, View3D *v3d, Object *obact) { RegionView3D *rv3d = ar->regiondata; Scene *scene_eval = (Scene *)DEG_get_evaluated_id(depsgraph, &scene->id); @@ -178,9 +176,6 @@ static void validate_object_select_id(struct Depsgraph *depsgraph, else if ((obact_eval && (obact_eval->mode & OB_MODE_PARTICLE_EDIT)) && !XRAY_ENABLED(v3d)) { /* do nothing */ } - else if ((obedit && (obedit->mode & OB_MODE_EDIT)) && !XRAY_FLAG_ENABLED(v3d)) { - /* do nothing */ - } else { v3d->flag &= ~V3D_INVALID_BACKBUF; return; @@ -190,34 +185,18 @@ static void validate_object_select_id(struct Depsgraph *depsgraph, return; } -#if 0 - if (test) { - if (qtest()) { - addafterqueue(ar->win, BACKBUFDRAW, 1); - return; - } - } -#endif - -#if 0 /* v3d->zbuf deprecated */ - if (v3d->shading.type > OB_WIRE) { - v3d->zbuf = true; - } -#endif - - G.f |= G_FLAG_BACKBUFSEL; - if (obact_eval && ((obact_eval->base_flag & BASE_VISIBLE) != 0)) { + uint dummy_vert_ofs, dummy_edge_ofs, dummy_face_ofs; DRW_framebuffer_select_id_setup(ar, true); DRW_draw_select_id_object(scene_eval, rv3d, obact_eval, - select_mode, + scene->toolsettings->selectmode, false, - 0, - &bm_vertoffs, - &bm_wireoffs, - &bm_solidoffs); + 1, + &dummy_vert_ofs, + &dummy_edge_ofs, + &dummy_face_ofs); DRW_framebuffer_select_id_release(ar); } @@ -225,8 +204,6 @@ static void validate_object_select_id(struct Depsgraph *depsgraph, /* TODO: Create a flag in `DRW_manager` because the drawing is no longer * made on the backbuffer in this case. */ v3d->flag &= ~V3D_INVALID_BACKBUF; - - G.f &= ~G_FLAG_BACKBUFSEL; } /* TODO: Creating, attaching texture, and destroying a framebuffer is quite slow. @@ -251,21 +228,15 @@ static void view3d_opengl_read_Z_pixels(GPUViewport *viewport, rcti *rect, void GPU_framebuffer_free(tmp_fb); } -void ED_view3d_select_id_validate_with_select_mode(ViewContext *vc, short select_mode) +void ED_view3d_select_id_validate(ViewContext *vc) { /* TODO: Create a flag in `DRW_manager` because the drawing is no longer * made on the backbuffer in this case. */ if (vc->v3d->flag & V3D_INVALID_BACKBUF) { - validate_object_select_id( - vc->depsgraph, vc->scene, vc->ar, vc->v3d, vc->obact, vc->obedit, select_mode); + validate_object_select_id(vc->depsgraph, vc->scene, vc->ar, vc->v3d, vc->obact); } } -void ED_view3d_select_id_validate(ViewContext *vc) -{ - ED_view3d_select_id_validate_with_select_mode(vc, -1); -} - void ED_view3d_backbuf_depth_validate(ViewContext *vc) { if (vc->v3d->flag & V3D_INVALID_BACKBUF) { @@ -281,7 +252,7 @@ void ED_view3d_backbuf_depth_validate(ViewContext *vc) } } -uint *ED_view3d_select_id_read_rect(ViewContext *UNUSED(vc), const rcti *clip, uint *r_buf_len) +uint *ED_view3d_select_id_read_rect(const rcti *clip, uint *r_buf_len) { uint width = BLI_rcti_size_x(clip); uint height = BLI_rcti_size_y(clip); @@ -306,25 +277,8 @@ int ED_view3d_backbuf_sample_size_clamp(ARegion *ar, const float dist) return (int)min_ff(ceilf(dist), (float)max_ii(ar->winx, ar->winx)); } -/* samples a single pixel (copied from vpaint) */ -uint ED_view3d_select_id_sample(ViewContext *vc, int x, int y) -{ - if (x >= vc->ar->winx || y >= vc->ar->winy) { - return 0; - } - - uint buf_len; - uint *buf = ED_view3d_select_id_read(vc, x, y, x, y, &buf_len); - BLI_assert(0 != buf_len); - uint ret = buf[0]; - MEM_freeN(buf); - - return ret; -} - /* reads full rect, converts indices */ -uint *ED_view3d_select_id_read( - ViewContext *vc, int xmin, int ymin, int xmax, int ymax, uint *r_buf_len) +uint *ED_view3d_select_id_read(int xmin, int ymin, int xmax, int ymax, uint *r_buf_len) { if (UNLIKELY((xmin > xmax) || (ymin > ymax))) { return NULL; @@ -338,7 +292,7 @@ uint *ED_view3d_select_id_read( }; uint buf_len; - uint *buf = ED_view3d_select_id_read_rect(vc, &rect, &buf_len); + uint *buf = ED_view3d_select_id_read_rect(&rect, &buf_len); if (r_buf_len) { *r_buf_len = buf_len; @@ -347,85 +301,6 @@ uint *ED_view3d_select_id_read( return buf; } -/* smart function to sample a rect spiralling outside, nice for backbuf selection */ -uint ED_view3d_select_id_read_nearest(struct ViewContext *UNUSED(vc), - const int mval[2], - const uint id_min, - const uint id_max, - uint *r_dist) -{ - /* Create region around mouse cursor. This must be square and have an odd - * width, the spiraling algorithm does not work with arbitrary rectangles. */ - rcti rect; - BLI_rcti_init_pt_radius(&rect, mval, *r_dist); - rect.xmax += 1; - rect.ymax += 1; - - int width = BLI_rcti_size_x(&rect); - int height = width; - BLI_assert(width == height); - - /* Read from selection framebuffer. */ - uint *buf = MEM_mallocN(width * height * sizeof(*buf), __func__); - DRW_framebuffer_select_id_read(&rect, buf); - - /* Spiral, starting from center of buffer. */ - int spiral_offset = height * (int)(width / 2) + (height / 2); - int spiral_direction = 0; - - uint index = 0; - - for (int nr = 1; nr <= height; nr++) { - for (int a = 0; a < 2; a++) { - for (int b = 0; b < nr; b++) { - /* Find hit within the specified range. */ - uint hit_id = buf[spiral_offset]; - - if (hit_id && hit_id >= id_min && hit_id < id_max) { - /* Get x/y from spiral offset. */ - int hit_x = spiral_offset % width; - int hit_y = spiral_offset / width; - - int center_x = width / 2; - int center_y = height / 2; - - /* Manhatten distance in keeping with other screen-based selection. */ - *r_dist = (uint)(abs(hit_x - center_x) + abs(hit_y - center_y)); - - /* Indices start at 1 here. */ - index = (hit_id - id_min) + 1; - goto exit; - } - - /* Next spiral step. */ - if (spiral_direction == 0) { - spiral_offset += 1; /* right */ - } - else if (spiral_direction == 1) { - spiral_offset -= width; /* down */ - } - else if (spiral_direction == 2) { - spiral_offset -= 1; /* left */ - } - else { - spiral_offset += width; /* up */ - } - - /* Stop if we are outside the buffer. */ - if (spiral_offset < 0 || spiral_offset >= width * height) { - goto exit; - } - } - - spiral_direction = (spiral_direction + 1) % 4; - } - } - -exit: - MEM_freeN(buf); - return index; -} - /* ************************************************************* */ static void view3d_stereo_bgpic_setup(Scene *scene, View3D *v3d, Image *ima, ImageUser *iuser) diff --git a/source/blender/editors/space_view3d/view3d_gizmo_navigate.c b/source/blender/editors/space_view3d/view3d_gizmo_navigate.c index 5af6fd8b04b..d39be3d8e20 100644 --- a/source/blender/editors/space_view3d/view3d_gizmo_navigate.c +++ b/source/blender/editors/space_view3d/view3d_gizmo_navigate.c @@ -131,7 +131,7 @@ static bool WIDGETGROUP_navigate_poll(const bContext *C, wmGizmoGroupType *UNUSE return true; } -static void WIDGETGROUP_navigate_setup(const bContext *UNUSED(C), wmGizmoGroup *gzgroup) +static void WIDGETGROUP_navigate_setup(const bContext *C, wmGizmoGroup *gzgroup) { struct NavigateWidgetGroup *navgroup = MEM_callocN(sizeof(struct NavigateWidgetGroup), __func__); @@ -227,6 +227,9 @@ static void WIDGETGROUP_navigate_setup(const bContext *UNUSED(C), wmGizmoGroup * } /* When dragging an axis, use this instead. */ + wmWindowManager *wm = CTX_wm_manager(C); + gz->keymap = WM_keymap_ensure( + wm->defaultconf, "Generic Gizmo Click Drag", SPACE_EMPTY, RGN_TYPE_WINDOW); gz->drag_part = 0; } diff --git a/source/blender/editors/space_view3d/view3d_select.c b/source/blender/editors/space_view3d/view3d_select.c index 419ec87eec8..b3b4910c525 100644 --- a/source/blender/editors/space_view3d/view3d_select.c +++ b/source/blender/editors/space_view3d/view3d_select.c @@ -41,6 +41,7 @@ #include "MEM_guardedalloc.h" #include "BLI_array.h" +#include "BLI_bitmap.h" #include "BLI_math.h" #include "BLI_lasso_2d.h" #include "BLI_rect.h" @@ -88,6 +89,7 @@ #include "ED_mesh.h" #include "ED_object.h" #include "ED_screen.h" +#include "ED_select_buffer_utils.h" #include "ED_select_utils.h" #include "ED_sculpt.h" #include "ED_mball.h" @@ -179,20 +181,96 @@ static bool object_deselect_all_except(ViewLayer *view_layer, Base *b) /** \} */ /* -------------------------------------------------------------------- */ +/** \name Internal Edit-Mesh Select Buffer Wrapper + * + * Avoid duplicate code when using edit-mode selection, + * actual logic is handled outside of this function. + * + * \note Currently this #EDBMSelectID_Context which is mesh specific + * however the logic could also be used for non-meshes too. + * + * \{ */ + +struct EditSelectBuf_Cache { + Base **bases; + uint bases_len; + struct EDBMSelectID_Context *sel_id_ctx; + BLI_bitmap *select_bitmap; +}; + +static void editselect_buf_cache_init(struct EditSelectBuf_Cache *esel, ViewContext *vc) +{ + if (vc->obedit) { + esel->bases = BKE_view_layer_array_from_bases_in_edit_mode( + vc->view_layer, vc->v3d, &esel->bases_len); + } + else { + /* Use for paint modes, currently only a single object at a time. */ + if (vc->obact) { + esel->bases = MEM_mallocN(sizeof(esel->bases), __func__); + esel->bases[0] = BKE_view_layer_base_find(vc->view_layer, vc->obact); + esel->bases_len = 1; + } + else { + esel->bases = NULL; + esel->bases_len = 0; + } + } + esel->sel_id_ctx = EDBM_select_id_context_create( + vc, esel->bases, esel->bases_len, vc->scene->toolsettings->selectmode); + for (int i = 0; i < esel->bases_len; i++) { + esel->bases[i]->object->runtime.select_id = i; + } +} + +static void editselect_buf_cache_free(struct EditSelectBuf_Cache *esel) +{ + if (esel->sel_id_ctx) { + EDBM_select_id_context_destroy(esel->sel_id_ctx); + } + MEM_SAFE_FREE(esel->select_bitmap); + MEM_SAFE_FREE(esel->bases); +} + +static void editselect_buf_cache_free_voidp(void *esel_voidp) +{ + editselect_buf_cache_free(esel_voidp); + MEM_freeN(esel_voidp); +} + +static void editselect_buf_cache_init_with_generic_userdata(wmGenericUserData *wm_userdata, + ViewContext *vc) +{ + struct EditSelectBuf_Cache *esel = MEM_callocN(sizeof(*esel), __func__); + wm_userdata->data = esel; + wm_userdata->free_fn = editselect_buf_cache_free_voidp; + wm_userdata->use_free = true; + editselect_buf_cache_init(esel, vc); +} + +/** \} */ + +/* -------------------------------------------------------------------- */ /** \name Internal Edit-Mesh Utilities * \{ */ -static bool edbm_backbuf_check_and_select_verts(BMEditMesh *em, const eSelectOp sel_op) +static bool edbm_backbuf_check_and_select_verts(struct EditSelectBuf_Cache *esel, + Object *ob, + BMEditMesh *em, + const eSelectOp sel_op) { BMVert *eve; BMIter iter; - uint index = bm_wireoffs; bool changed = false; + const BLI_bitmap *select_bitmap = esel->select_bitmap; + uint index = EDBM_select_id_context_offset_for_object_elem( + esel->sel_id_ctx, ob->runtime.select_id, BM_VERT); + BM_ITER_MESH (eve, &iter, em->bm, BM_VERTS_OF_MESH) { if (!BM_elem_flag_test(eve, BM_ELEM_HIDDEN)) { const bool is_select = BM_elem_flag_test(eve, BM_ELEM_SELECT); - const bool is_inside = EDBM_backbuf_check(index); + const bool is_inside = BLI_BITMAP_TEST_BOOL(select_bitmap, index); const int sel_op_result = ED_select_op_action_deselected(sel_op, is_select, is_inside); if (sel_op_result != -1) { BM_vert_select_set(em->bm, eve, sel_op_result); @@ -204,17 +282,23 @@ static bool edbm_backbuf_check_and_select_verts(BMEditMesh *em, const eSelectOp return changed; } -static bool edbm_backbuf_check_and_select_edges(BMEditMesh *em, const eSelectOp sel_op) +static bool edbm_backbuf_check_and_select_edges(struct EditSelectBuf_Cache *esel, + Object *ob, + BMEditMesh *em, + const eSelectOp sel_op) { BMEdge *eed; BMIter iter; - uint index = bm_solidoffs; bool changed = false; + const BLI_bitmap *select_bitmap = esel->select_bitmap; + uint index = EDBM_select_id_context_offset_for_object_elem( + esel->sel_id_ctx, ob->runtime.select_id, BM_EDGE); + BM_ITER_MESH (eed, &iter, em->bm, BM_EDGES_OF_MESH) { if (!BM_elem_flag_test(eed, BM_ELEM_HIDDEN)) { const bool is_select = BM_elem_flag_test(eed, BM_ELEM_SELECT); - const bool is_inside = EDBM_backbuf_check(index); + const bool is_inside = BLI_BITMAP_TEST_BOOL(select_bitmap, index); const int sel_op_result = ED_select_op_action_deselected(sel_op, is_select, is_inside); if (sel_op_result != -1) { BM_edge_select_set(em->bm, eed, sel_op_result); @@ -226,17 +310,23 @@ static bool edbm_backbuf_check_and_select_edges(BMEditMesh *em, const eSelectOp return changed; } -static bool edbm_backbuf_check_and_select_faces(BMEditMesh *em, const eSelectOp sel_op) +static bool edbm_backbuf_check_and_select_faces(struct EditSelectBuf_Cache *esel, + Object *ob, + BMEditMesh *em, + const eSelectOp sel_op) { BMFace *efa; BMIter iter; - uint index = 1; bool changed = false; + const BLI_bitmap *select_bitmap = esel->select_bitmap; + uint index = EDBM_select_id_context_offset_for_object_elem( + esel->sel_id_ctx, ob->runtime.select_id, BM_FACE); + BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { if (!BM_elem_flag_test(efa, BM_ELEM_HIDDEN)) { const bool is_select = BM_elem_flag_test(efa, BM_ELEM_SELECT); - const bool is_inside = EDBM_backbuf_check(index); + const bool is_inside = BLI_BITMAP_TEST_BOOL(select_bitmap, index); const int sel_op_result = ED_select_op_action_deselected(sel_op, is_select, is_inside); if (sel_op_result != -1) { BM_face_select_set(em->bm, efa, sel_op_result); @@ -249,17 +339,21 @@ static bool edbm_backbuf_check_and_select_faces(BMEditMesh *em, const eSelectOp } /* object mode, edbm_ prefix is confusing here, rename? */ -static bool edbm_backbuf_check_and_select_verts_obmode(Mesh *me, const eSelectOp sel_op) +static bool edbm_backbuf_check_and_select_verts_obmode(Mesh *me, + struct EditSelectBuf_Cache *esel, + const eSelectOp sel_op) { MVert *mv = me->mvert; uint index; bool changed = false; + const BLI_bitmap *select_bitmap = esel->select_bitmap; + if (mv) { - for (index = 1; index <= me->totvert; index++, mv++) { + for (index = 0; index < me->totvert; index++, mv++) { if (!(mv->flag & ME_HIDE)) { const bool is_select = mv->flag & SELECT; - const bool is_inside = EDBM_backbuf_check(index); + const bool is_inside = BLI_BITMAP_TEST_BOOL(select_bitmap, index); const int sel_op_result = ED_select_op_action_deselected(sel_op, is_select, is_inside); if (sel_op_result != -1) { SET_FLAG_FROM_TEST(mv->flag, sel_op_result, SELECT); @@ -272,17 +366,21 @@ static bool edbm_backbuf_check_and_select_verts_obmode(Mesh *me, const eSelectOp } /* object mode, edbm_ prefix is confusing here, rename? */ -static bool edbm_backbuf_check_and_select_tfaces(Mesh *me, const eSelectOp sel_op) +static bool edbm_backbuf_check_and_select_faces_obmode(Mesh *me, + struct EditSelectBuf_Cache *esel, + const eSelectOp sel_op) { MPoly *mpoly = me->mpoly; uint index; bool changed = false; + const BLI_bitmap *select_bitmap = esel->select_bitmap; + if (mpoly) { - for (index = 1; index <= me->totpoly; index++, mpoly++) { + for (index = 0; index < me->totpoly; index++, mpoly++) { if (!(mpoly->flag & ME_HIDE)) { const bool is_select = mpoly->flag & ME_FACE_SEL; - const bool is_inside = EDBM_backbuf_check(index); + const bool is_inside = BLI_BITMAP_TEST_BOOL(select_bitmap, index); const int sel_op_result = ED_select_op_action_deselected(sel_op, is_select, is_inside); if (sel_op_result != -1) { SET_FLAG_FROM_TEST(mpoly->flag, sel_op_result, ME_FACE_SEL); @@ -621,14 +719,26 @@ static void do_lasso_select_mesh__doSelectVert(void *userData, data->is_changed = true; } } -static void do_lasso_select_mesh__doSelectEdge_pass0( - void *userData, BMEdge *eed, const float screen_co_a[2], const float screen_co_b[2], int index) -{ - LassoSelectUserData *data = userData; +struct LassoSelectUserData_ForMeshEdge { + LassoSelectUserData *data; + struct EditSelectBuf_Cache *esel; + uint backbuf_offset; +}; +static void do_lasso_select_mesh__doSelectEdge_pass0(void *user_data, + BMEdge *eed, + const float screen_co_a[2], + const float screen_co_b[2], + int index) +{ + struct LassoSelectUserData_ForMeshEdge *data_for_edge = user_data; + LassoSelectUserData *data = data_for_edge->data; + const bool is_visible = (data_for_edge->esel ? + BLI_BITMAP_TEST_BOOL(data_for_edge->esel->select_bitmap, + data_for_edge->backbuf_offset + index) : + true); const bool is_select = BM_elem_flag_test(eed, BM_ELEM_SELECT); const bool is_inside = - (EDBM_backbuf_check(bm_solidoffs + index) && - edge_fully_inside_rect(data->rect_fl, screen_co_a, screen_co_b) && + (is_visible && edge_fully_inside_rect(data->rect_fl, screen_co_a, screen_co_b) && BLI_lasso_is_point_inside(data->mcords, data->moves, UNPACK2(screen_co_a), IS_CLIPPED) && BLI_lasso_is_point_inside(data->mcords, data->moves, UNPACK2(screen_co_b), IS_CLIPPED)); const int sel_op_result = ED_select_op_action_deselected(data->sel_op, is_select, is_inside); @@ -638,15 +748,24 @@ static void do_lasso_select_mesh__doSelectEdge_pass0( data->is_changed = true; } } -static void do_lasso_select_mesh__doSelectEdge_pass1( - void *userData, BMEdge *eed, const float screen_co_a[2], const float screen_co_b[2], int index) +static void do_lasso_select_mesh__doSelectEdge_pass1(void *user_data, + BMEdge *eed, + const float screen_co_a[2], + const float screen_co_b[2], + int index) { - LassoSelectUserData *data = userData; + struct LassoSelectUserData_ForMeshEdge *data_for_edge = user_data; + LassoSelectUserData *data = data_for_edge->data; + const bool is_visible = (data_for_edge->esel ? + BLI_BITMAP_TEST_BOOL(data_for_edge->esel->select_bitmap, + data_for_edge->backbuf_offset + index) : + true); const bool is_select = BM_elem_flag_test(eed, BM_ELEM_SELECT); - const bool is_inside = - (EDBM_backbuf_check(bm_solidoffs + index) && - BLI_lasso_is_edge_inside( - data->mcords, data->moves, UNPACK2(screen_co_a), UNPACK2(screen_co_b), IS_CLIPPED)); + const bool is_inside = (is_visible && BLI_lasso_is_edge_inside(data->mcords, + data->moves, + UNPACK2(screen_co_a), + UNPACK2(screen_co_b), + IS_CLIPPED)); const int sel_op_result = ED_select_op_action_deselected(data->sel_op, is_select, is_inside); if (sel_op_result != -1) { BM_edge_select_set(data->vc->em->bm, eed, sel_op_result); @@ -672,6 +791,7 @@ static void do_lasso_select_mesh__doSelectFace(void *userData, } static bool do_lasso_select_mesh(ViewContext *vc, + wmGenericUserData *wm_userdata, const int mcords[][2], short moves, const eSelectOp sel_op) @@ -679,7 +799,6 @@ static bool do_lasso_select_mesh(ViewContext *vc, LassoSelectUserData data; ToolSettings *ts = vc->scene->toolsettings; rcti rect; - int bbsel; /* set editmesh */ vc->em = BKE_editmesh_from_object(vc->obedit); @@ -699,12 +818,22 @@ static bool do_lasso_select_mesh(ViewContext *vc, ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d); GPU_matrix_set(vc->rv3d->viewmat); - bbsel = EDBM_backbuf_border_mask_init( - vc, mcords, moves, rect.xmin, rect.ymin, rect.xmax, rect.ymax); + + const bool use_zbuf = !XRAY_FLAG_ENABLED(vc->v3d); + + struct EditSelectBuf_Cache *esel = wm_userdata->data; + if (use_zbuf) { + if (wm_userdata->data == NULL) { + editselect_buf_cache_init_with_generic_userdata(wm_userdata, vc); + esel = wm_userdata->data; + const uint buffer_len = EDBM_select_id_context_elem_len(esel->sel_id_ctx); + esel->select_bitmap = ED_select_buffer_bitmap_from_poly(buffer_len, mcords, moves, &rect); + } + } if (ts->selectmode & SCE_SELECT_VERTEX) { - if (bbsel) { - data.is_changed |= edbm_backbuf_check_and_select_verts(vc->em, sel_op); + if (use_zbuf) { + data.is_changed |= edbm_backbuf_check_and_select_verts(esel, vc->obedit, vc->em, sel_op); } else { mesh_foreachScreenVert( @@ -712,18 +841,26 @@ static bool do_lasso_select_mesh(ViewContext *vc, } } if (ts->selectmode & SCE_SELECT_EDGE) { - /* Does both bbsel and non-bbsel versions (need screen cos for both) */ + /* Does both use_zbuf and non-use_zbuf versions (need screen cos for both) */ + struct LassoSelectUserData_ForMeshEdge data_for_edge = { + .data = &data, + .esel = use_zbuf ? esel : NULL, + .backbuf_offset = use_zbuf ? + EDBM_select_id_context_offset_for_object_elem( + esel->sel_id_ctx, vc->obedit->runtime.select_id, BM_EDGE) : + 0, + }; mesh_foreachScreenEdge( - vc, do_lasso_select_mesh__doSelectEdge_pass0, &data, V3D_PROJ_TEST_CLIP_NEAR); + vc, do_lasso_select_mesh__doSelectEdge_pass0, &data_for_edge, V3D_PROJ_TEST_CLIP_NEAR); if (data.is_done == false) { mesh_foreachScreenEdge( - vc, do_lasso_select_mesh__doSelectEdge_pass1, &data, V3D_PROJ_TEST_CLIP_NEAR); + vc, do_lasso_select_mesh__doSelectEdge_pass1, &data_for_edge, V3D_PROJ_TEST_CLIP_NEAR); } } if (ts->selectmode & SCE_SELECT_FACE) { - if (bbsel) { - data.is_changed |= edbm_backbuf_check_and_select_faces(vc->em, sel_op); + if (use_zbuf) { + data.is_changed |= edbm_backbuf_check_and_select_faces(esel, vc->obedit, vc->em, sel_op); } else { mesh_foreachScreenFace( @@ -731,8 +868,6 @@ static bool do_lasso_select_mesh(ViewContext *vc, } } - EDBM_backbuf_free(); - if (data.is_changed) { EDBM_selectmode_flush(vc->em); } @@ -973,6 +1108,7 @@ static void do_lasso_select_meshobject__doSelectVert(void *userData, } } static bool do_lasso_select_paintvert(ViewContext *vc, + wmGenericUserData *wm_userdata, const int mcords[][2], short moves, const eSelectOp sel_op) @@ -994,14 +1130,20 @@ static bool do_lasso_select_paintvert(ViewContext *vc, BLI_lasso_boundbox(&rect, mcords, moves); + struct EditSelectBuf_Cache *esel = wm_userdata->data; if (use_zbuf) { - bm_vertoffs = me->totvert + 1; /* max index array */ - - EDBM_backbuf_border_mask_init(vc, mcords, moves, rect.xmin, rect.ymin, rect.xmax, rect.ymax); - - changed |= edbm_backbuf_check_and_select_verts_obmode(me, sel_op); + if (wm_userdata->data == NULL) { + editselect_buf_cache_init_with_generic_userdata(wm_userdata, vc); + esel = wm_userdata->data; + const uint buffer_len = EDBM_select_id_context_elem_len(esel->sel_id_ctx); + esel->select_bitmap = ED_select_buffer_bitmap_from_poly(buffer_len, mcords, moves, &rect); + } + } - EDBM_backbuf_free(); + if (use_zbuf) { + if (esel->select_bitmap != NULL) { + changed |= edbm_backbuf_check_and_select_verts_obmode(me, esel, sel_op); + } } else { LassoSelectUserData data; @@ -1023,9 +1165,11 @@ static bool do_lasso_select_paintvert(ViewContext *vc, paintvert_flush_flags(ob); paintvert_tag_select_update(vc->C, ob); } + return changed; } static bool do_lasso_select_paintface(ViewContext *vc, + wmGenericUserData *wm_userdata, const int mcords[][2], short moves, const eSelectOp sel_op) @@ -1038,19 +1182,25 @@ static bool do_lasso_select_paintface(ViewContext *vc, return false; } - bm_vertoffs = me->totpoly + 1; /* max index array */ - - BLI_lasso_boundbox(&rect, mcords, moves); - EDBM_backbuf_border_mask_init(vc, mcords, moves, rect.xmin, rect.ymin, rect.xmax, rect.ymax); - bool changed = false; if (SEL_OP_USE_PRE_DESELECT(sel_op)) { /* flush selection at the end */ changed |= paintface_deselect_all_visible(vc->C, ob, SEL_DESELECT, false); } - changed |= edbm_backbuf_check_and_select_tfaces(me, sel_op); - EDBM_backbuf_free(); + BLI_lasso_boundbox(&rect, mcords, moves); + + struct EditSelectBuf_Cache *esel = wm_userdata->data; + if (esel == NULL) { + editselect_buf_cache_init_with_generic_userdata(wm_userdata, vc); + esel = wm_userdata->data; + const uint buffer_len = EDBM_select_id_context_elem_len(esel->sel_id_ctx); + esel->select_bitmap = ED_select_buffer_bitmap_from_poly(buffer_len, mcords, moves, &rect); + } + + if (esel->select_bitmap) { + changed |= edbm_backbuf_check_and_select_faces_obmode(me, esel, sel_op); + } if (changed) { paintface_flush_flags(vc->C, ob, SELECT); @@ -1098,12 +1248,15 @@ static bool view3d_lasso_select( Object *ob = CTX_data_active_object(C); bool changed_multi = false; + wmGenericUserData wm_userdata_buf = {0}; + wmGenericUserData *wm_userdata = &wm_userdata_buf; + if (vc->obedit == NULL) { /* Object Mode */ if (BKE_paint_select_face_test(ob)) { - changed_multi |= do_lasso_select_paintface(vc, mcords, moves, sel_op); + changed_multi |= do_lasso_select_paintface(vc, wm_userdata, mcords, moves, sel_op); } else if (BKE_paint_select_vert_test(ob)) { - changed_multi |= do_lasso_select_paintvert(vc, mcords, moves, sel_op); + changed_multi |= do_lasso_select_paintvert(vc, wm_userdata, mcords, moves, sel_op); } else if (ob && (ob->mode & (OB_MODE_VERTEX_PAINT | OB_MODE_WEIGHT_PAINT | OB_MODE_TEXTURE_PAINT))) { @@ -1120,14 +1273,13 @@ static bool view3d_lasso_select( } } else { /* Edit Mode */ - FOREACH_OBJECT_IN_MODE_BEGIN (vc->view_layer, vc->v3d, ob->type, ob->mode, ob_iter) { ED_view3d_viewcontext_init_object(vc, ob_iter); bool changed = false; switch (vc->obedit->type) { case OB_MESH: - changed = do_lasso_select_mesh(vc, mcords, moves, sel_op); + changed = do_lasso_select_mesh(vc, wm_userdata, mcords, moves, sel_op); break; case OB_CURVE: case OB_SURF: @@ -1155,6 +1307,9 @@ static bool view3d_lasso_select( } FOREACH_OBJECT_IN_MODE_END; } + + WM_generic_user_data_free(wm_userdata); + return changed_multi; } @@ -2336,9 +2491,13 @@ static void do_paintvert_box_select__doSelectVert(void *userData, data->is_changed = true; } } -static bool do_paintvert_box_select(ViewContext *vc, const rcti *rect, const eSelectOp sel_op) +static bool do_paintvert_box_select(ViewContext *vc, + wmGenericUserData *wm_userdata, + const rcti *rect, + const eSelectOp sel_op) { const bool use_zbuf = !XRAY_ENABLED(vc->v3d); + Mesh *me; me = vc->obact->data; @@ -2355,48 +2514,16 @@ static bool do_paintvert_box_select(ViewContext *vc, const rcti *rect, const eSe /* pass */ } else if (use_zbuf) { - MVert *mvert; - uint *rt, *buf, buf_len; - int a, index; - char *selar; - - selar = MEM_callocN(me->totvert + 1, "selar"); - - ED_view3d_select_id_validate(vc); - buf = ED_view3d_select_id_read_rect(vc, rect, &buf_len); - - rt = buf; - - a = buf_len; - while (a--) { - if (*rt) { - index = *rt; - if (index <= me->totvert) { - selar[index] = 1; - } - } - rt++; + struct EditSelectBuf_Cache *esel = wm_userdata->data; + if (wm_userdata->data == NULL) { + editselect_buf_cache_init_with_generic_userdata(wm_userdata, vc); + esel = wm_userdata->data; + const uint buffer_len = EDBM_select_id_context_elem_len(esel->sel_id_ctx); + esel->select_bitmap = ED_select_buffer_bitmap_from_rect(buffer_len, rect); } - - mvert = me->mvert; - for (a = 1; a <= me->totvert; a++, mvert++) { - if ((mvert->flag & ME_HIDE) == 0) { - const bool is_select = mvert->flag & SELECT; - const bool is_inside = (selar[a] != 0); - const int sel_op_result = ED_select_op_action_deselected(sel_op, is_select, is_inside); - if (sel_op_result != -1) { - SET_FLAG_FROM_TEST(mvert->flag, sel_op_result, SELECT); - changed = true; - } - } + if (esel->select_bitmap != NULL) { + changed |= edbm_backbuf_check_and_select_verts_obmode(me, esel, sel_op); } - - MEM_freeN(buf); - MEM_freeN(selar); - -#ifdef __APPLE__ - glReadBuffer(GL_BACK); -#endif } else { BoxSelectUserData data; @@ -2420,6 +2547,46 @@ static bool do_paintvert_box_select(ViewContext *vc, const rcti *rect, const eSe return changed; } +static bool do_paintface_box_select(ViewContext *vc, + wmGenericUserData *wm_userdata, + const rcti *rect, + int sel_op) +{ + Object *ob = vc->obact; + Mesh *me; + + me = BKE_mesh_from_object(ob); + if ((me == NULL) || (me->totpoly == 0)) { + return false; + } + + bool changed = false; + if (SEL_OP_USE_PRE_DESELECT(sel_op)) { + changed |= paintface_deselect_all_visible(vc->C, vc->obact, SEL_DESELECT, false); + } + + if (BLI_rcti_is_empty(rect)) { + /* pass */ + } + else { + struct EditSelectBuf_Cache *esel = wm_userdata->data; + if (wm_userdata->data == NULL) { + editselect_buf_cache_init_with_generic_userdata(wm_userdata, vc); + esel = wm_userdata->data; + const uint buffer_len = EDBM_select_id_context_elem_len(esel->sel_id_ctx); + esel->select_bitmap = ED_select_buffer_bitmap_from_rect(buffer_len, rect); + } + if (esel->select_bitmap != NULL) { + changed |= edbm_backbuf_check_and_select_faces_obmode(me, esel, sel_op); + } + } + + if (changed) { + paintface_flush_flags(vc->C, vc->obact, SELECT); + } + return changed; +} + static void do_nurbs_box_select__doSelect(void *userData, Nurb *UNUSED(nu), BPoint *bp, @@ -2520,12 +2687,22 @@ static void do_mesh_box_select__doSelectVert(void *userData, data->is_changed = true; } } +struct BoxSelectUserData_ForMeshEdge { + BoxSelectUserData *data; + struct EditSelectBuf_Cache *esel; + uint backbuf_offset; +}; static void do_mesh_box_select__doSelectEdge_pass0( void *userData, BMEdge *eed, const float screen_co_a[2], const float screen_co_b[2], int index) { - BoxSelectUserData *data = userData; + struct BoxSelectUserData_ForMeshEdge *data_for_edge = userData; + BoxSelectUserData *data = data_for_edge->data; + const bool is_visible = (data_for_edge->esel ? + BLI_BITMAP_TEST_BOOL(data_for_edge->esel->select_bitmap, + data_for_edge->backbuf_offset + index) : + true); const bool is_select = BM_elem_flag_test(eed, BM_ELEM_SELECT); - const bool is_inside = (EDBM_backbuf_check(bm_solidoffs + index) && + const bool is_inside = (is_visible && edge_fully_inside_rect(data->rect_fl, screen_co_a, screen_co_b)); const int sel_op_result = ED_select_op_action_deselected(data->sel_op, is_select, is_inside); if (sel_op_result != -1) { @@ -2537,10 +2714,14 @@ static void do_mesh_box_select__doSelectEdge_pass0( static void do_mesh_box_select__doSelectEdge_pass1( void *userData, BMEdge *eed, const float screen_co_a[2], const float screen_co_b[2], int index) { - BoxSelectUserData *data = userData; + struct BoxSelectUserData_ForMeshEdge *data_for_edge = userData; + BoxSelectUserData *data = data_for_edge->data; + const bool is_visible = (data_for_edge->esel ? + BLI_BITMAP_TEST_BOOL(data_for_edge->esel->select_bitmap, + data_for_edge->backbuf_offset + index) : + true); const bool is_select = BM_elem_flag_test(eed, BM_ELEM_SELECT); - const bool is_inside = (EDBM_backbuf_check(bm_solidoffs + index) && - edge_inside_rect(data->rect_fl, screen_co_a, screen_co_b)); + const bool is_inside = (is_visible && edge_inside_rect(data->rect_fl, screen_co_a, screen_co_b)); const int sel_op_result = ED_select_op_action_deselected(data->sel_op, is_select, is_inside); if (sel_op_result != -1) { BM_edge_select_set(data->vc->em->bm, eed, sel_op_result); @@ -2561,11 +2742,13 @@ static void do_mesh_box_select__doSelectFace(void *userData, data->is_changed = true; } } -static bool do_mesh_box_select(ViewContext *vc, rcti *rect, const eSelectOp sel_op) +static bool do_mesh_box_select(ViewContext *vc, + wmGenericUserData *wm_userdata, + const rcti *rect, + const eSelectOp sel_op) { BoxSelectUserData data; ToolSettings *ts = vc->scene->toolsettings; - int bbsel; view3d_userdata_boxselect_init(&data, vc, rect, sel_op); @@ -2580,11 +2763,22 @@ static bool do_mesh_box_select(ViewContext *vc, rcti *rect, const eSelectOp sel_ ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d); GPU_matrix_set(vc->rv3d->viewmat); - bbsel = EDBM_backbuf_border_init(vc, rect->xmin, rect->ymin, rect->xmax, rect->ymax); + + const bool use_zbuf = !XRAY_FLAG_ENABLED(vc->v3d); + + struct EditSelectBuf_Cache *esel = wm_userdata->data; + if (use_zbuf) { + if (wm_userdata->data == NULL) { + editselect_buf_cache_init_with_generic_userdata(wm_userdata, vc); + esel = wm_userdata->data; + const uint buffer_len = EDBM_select_id_context_elem_len(esel->sel_id_ctx); + esel->select_bitmap = ED_select_buffer_bitmap_from_rect(buffer_len, rect); + } + } if (ts->selectmode & SCE_SELECT_VERTEX) { - if (bbsel) { - data.is_changed |= edbm_backbuf_check_and_select_verts(vc->em, sel_op); + if (use_zbuf) { + data.is_changed |= edbm_backbuf_check_and_select_verts(esel, vc->obedit, vc->em, sel_op); } else { mesh_foreachScreenVert( @@ -2592,18 +2786,26 @@ static bool do_mesh_box_select(ViewContext *vc, rcti *rect, const eSelectOp sel_ } } if (ts->selectmode & SCE_SELECT_EDGE) { - /* Does both bbsel and non-bbsel versions (need screen cos for both) */ + /* Does both use_zbuf and non-use_zbuf versions (need screen cos for both) */ + struct BoxSelectUserData_ForMeshEdge cb_data = { + .data = &data, + .esel = use_zbuf ? esel : NULL, + .backbuf_offset = use_zbuf ? + EDBM_select_id_context_offset_for_object_elem( + esel->sel_id_ctx, vc->obedit->runtime.select_id, BM_EDGE) : + 0, + }; mesh_foreachScreenEdge( - vc, do_mesh_box_select__doSelectEdge_pass0, &data, V3D_PROJ_TEST_CLIP_NEAR); + vc, do_mesh_box_select__doSelectEdge_pass0, &cb_data, V3D_PROJ_TEST_CLIP_NEAR); if (data.is_done == false) { mesh_foreachScreenEdge( - vc, do_mesh_box_select__doSelectEdge_pass1, &data, V3D_PROJ_TEST_CLIP_NEAR); + vc, do_mesh_box_select__doSelectEdge_pass1, &cb_data, V3D_PROJ_TEST_CLIP_NEAR); } } if (ts->selectmode & SCE_SELECT_FACE) { - if (bbsel) { - data.is_changed |= edbm_backbuf_check_and_select_faces(vc->em, sel_op); + if (use_zbuf) { + data.is_changed |= edbm_backbuf_check_and_select_faces(esel, vc->obedit, vc->em, sel_op); } else { mesh_foreachScreenFace( @@ -2611,8 +2813,6 @@ static bool do_mesh_box_select(ViewContext *vc, rcti *rect, const eSelectOp sel_ } } - EDBM_backbuf_free(); - if (data.is_changed) { EDBM_selectmode_flush(vc->em); } @@ -2930,6 +3130,9 @@ static int view3d_box_select_exec(bContext *C, wmOperator *op) rcti rect; bool changed_multi = false; + wmGenericUserData wm_userdata_buf = {0}; + wmGenericUserData *wm_userdata = &wm_userdata_buf; + view3d_operator_needs_opengl(C); BKE_object_update_select_id(CTX_data_main(C)); @@ -2940,7 +3143,6 @@ static int view3d_box_select_exec(bContext *C, wmOperator *op) WM_operator_properties_border_to_rcti(op, &rect); if (vc.obedit) { - FOREACH_OBJECT_IN_MODE_BEGIN ( vc.view_layer, vc.v3d, vc.obedit->type, vc.obedit->mode, ob_iter) { ED_view3d_viewcontext_init_object(&vc, ob_iter); @@ -2949,7 +3151,7 @@ static int view3d_box_select_exec(bContext *C, wmOperator *op) switch (vc.obedit->type) { case OB_MESH: vc.em = BKE_editmesh_from_object(vc.obedit); - changed = do_mesh_box_select(&vc, &rect, sel_op); + changed = do_mesh_box_select(&vc, wm_userdata, &rect, sel_op); if (changed) { DEG_id_tag_update(vc.obedit->data, ID_RECALC_SELECT); WM_event_add_notifier(C, NC_GEOM | ND_SELECT, vc.obedit->data); @@ -2999,10 +3201,10 @@ static int view3d_box_select_exec(bContext *C, wmOperator *op) C, &vc, &rect, sel_op == SEL_OP_ADD ? true : false); } else if (vc.obact && BKE_paint_select_face_test(vc.obact)) { - changed_multi = do_paintface_box_select(&vc, &rect, sel_op); + changed_multi = do_paintface_box_select(&vc, wm_userdata, &rect, sel_op); } else if (vc.obact && BKE_paint_select_vert_test(vc.obact)) { - changed_multi = do_paintvert_box_select(&vc, &rect, sel_op); + changed_multi = do_paintvert_box_select(&vc, wm_userdata, &rect, sel_op); } else if (vc.obact && vc.obact->mode & OB_MODE_PARTICLE_EDIT) { changed_multi = PE_box_select(C, &rect, sel_op); @@ -3015,6 +3217,8 @@ static int view3d_box_select_exec(bContext *C, wmOperator *op) } } + WM_generic_user_data_free(wm_userdata); + if (changed_multi) { return OPERATOR_FINISHED; } @@ -3120,10 +3324,13 @@ static void mesh_circle_doSelectFace(void *userData, } } -static bool mesh_circle_select(ViewContext *vc, eSelectOp sel_op, const int mval[2], float rad) +static bool mesh_circle_select(ViewContext *vc, + wmGenericUserData *wm_userdata, + eSelectOp sel_op, + const int mval[2], + float rad) { ToolSettings *ts = vc->scene->toolsettings; - int bbsel; CircleSelectUserData data; vc->em = BKE_editmesh_from_object(vc->obedit); @@ -3136,14 +3343,30 @@ static bool mesh_circle_select(ViewContext *vc, eSelectOp sel_op, const int mval } const bool select = (sel_op != SEL_OP_SUB); - bbsel = EDBM_backbuf_circle_init(vc, mval[0], mval[1], (short)(rad + 1.0f)); ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d); /* for foreach's screen/vert projection */ view3d_userdata_circleselect_init(&data, vc, select, mval, rad); + const bool use_zbuf = !XRAY_FLAG_ENABLED(vc->v3d); + + if (use_zbuf) { + if (wm_userdata->data == NULL) { + editselect_buf_cache_init_with_generic_userdata(wm_userdata, vc); + } + } + struct EditSelectBuf_Cache *esel = wm_userdata->data; + + if (use_zbuf) { + const uint buffer_len = EDBM_select_id_context_elem_len(esel->sel_id_ctx); + esel->select_bitmap = ED_select_buffer_bitmap_from_circle(buffer_len, mval, (int)(rad + 1.0f)); + } + if (ts->selectmode & SCE_SELECT_VERTEX) { - if (bbsel) { - changed |= edbm_backbuf_check_and_select_verts(vc->em, select ? SEL_OP_ADD : SEL_OP_SUB); + if (use_zbuf) { + if (esel->select_bitmap != NULL) { + changed |= edbm_backbuf_check_and_select_verts( + esel, vc->obedit, vc->em, select ? SEL_OP_ADD : SEL_OP_SUB); + } } else { mesh_foreachScreenVert(vc, mesh_circle_doSelectVert, &data, V3D_PROJ_TEST_CLIP_DEFAULT); @@ -3151,8 +3374,11 @@ static bool mesh_circle_select(ViewContext *vc, eSelectOp sel_op, const int mval } if (ts->selectmode & SCE_SELECT_EDGE) { - if (bbsel) { - changed |= edbm_backbuf_check_and_select_edges(vc->em, select ? SEL_OP_ADD : SEL_OP_SUB); + if (use_zbuf) { + if (esel->select_bitmap != NULL) { + changed |= edbm_backbuf_check_and_select_edges( + esel, vc->obedit, vc->em, select ? SEL_OP_ADD : SEL_OP_SUB); + } } else { mesh_foreachScreenEdge(vc, mesh_circle_doSelectEdge, &data, V3D_PROJ_TEST_CLIP_NEAR); @@ -3160,17 +3386,25 @@ static bool mesh_circle_select(ViewContext *vc, eSelectOp sel_op, const int mval } if (ts->selectmode & SCE_SELECT_FACE) { - if (bbsel) { - changed |= edbm_backbuf_check_and_select_faces(vc->em, select ? SEL_OP_ADD : SEL_OP_SUB); + if (use_zbuf) { + if (esel->select_bitmap != NULL) { + changed |= edbm_backbuf_check_and_select_faces( + esel, vc->obedit, vc->em, select ? SEL_OP_ADD : SEL_OP_SUB); + } } else { mesh_foreachScreenFace(vc, mesh_circle_doSelectFace, &data, V3D_PROJ_TEST_CLIP_DEFAULT); } } - changed |= data.is_changed; + if (use_zbuf) { + if (esel->select_bitmap != NULL) { + MEM_freeN(esel->select_bitmap); + esel->select_bitmap = NULL; + } + } - EDBM_backbuf_free(); + changed |= data.is_changed; if (changed) { EDBM_selectmode_flush(vc->em); @@ -3179,6 +3413,7 @@ static bool mesh_circle_select(ViewContext *vc, eSelectOp sel_op, const int mval } static bool paint_facesel_circle_select(ViewContext *vc, + wmGenericUserData *wm_userdata, const eSelectOp sel_op, const int mval[2], float rad) @@ -3186,7 +3421,6 @@ static bool paint_facesel_circle_select(ViewContext *vc, BLI_assert(ELEM(sel_op, SEL_OP_SET, SEL_OP_ADD, SEL_OP_SUB)); Object *ob = vc->obact; Mesh *me = ob->data; - bool bbsel; bool changed = false; if (SEL_OP_USE_PRE_DESELECT(sel_op)) { @@ -3194,13 +3428,21 @@ static bool paint_facesel_circle_select(ViewContext *vc, changed |= paintface_deselect_all_visible(vc->C, ob, SEL_DESELECT, false); } - bm_vertoffs = me->totpoly + 1; /* max index array */ + if (wm_userdata->data == NULL) { + editselect_buf_cache_init_with_generic_userdata(wm_userdata, vc); + } - bbsel = EDBM_backbuf_circle_init(vc, mval[0], mval[1], (short)(rad + 1.0f)); - if (bbsel) { - changed |= edbm_backbuf_check_and_select_tfaces(me, sel_op); - EDBM_backbuf_free(); + { + struct EditSelectBuf_Cache *esel = wm_userdata->data; + const uint buffer_len = EDBM_select_id_context_elem_len(esel->sel_id_ctx); + esel->select_bitmap = ED_select_buffer_bitmap_from_circle(buffer_len, mval, (int)(rad + 1.0f)); + if (esel->select_bitmap != NULL) { + changed |= edbm_backbuf_check_and_select_faces_obmode(me, esel, sel_op); + MEM_freeN(esel->select_bitmap); + esel->select_bitmap = NULL; + } } + if (changed) { paintface_flush_flags(vc->C, ob, SELECT); } @@ -3220,6 +3462,7 @@ static void paint_vertsel_circle_select_doSelectVert(void *userData, } } static bool paint_vertsel_circle_select(ViewContext *vc, + wmGenericUserData *wm_userdata, const eSelectOp sel_op, const int mval[2], float rad) @@ -3228,7 +3471,6 @@ static bool paint_vertsel_circle_select(ViewContext *vc, const bool use_zbuf = !XRAY_ENABLED(vc->v3d); Object *ob = vc->obact; Mesh *me = ob->data; - bool bbsel; /* CircleSelectUserData data = {NULL}; */ /* UNUSED */ bool changed = false; @@ -3240,12 +3482,19 @@ static bool paint_vertsel_circle_select(ViewContext *vc, const bool select = (sel_op != SEL_OP_SUB); if (use_zbuf) { - bm_vertoffs = me->totvert + 1; /* max index array */ + if (wm_userdata->data == NULL) { + editselect_buf_cache_init_with_generic_userdata(wm_userdata, vc); + } + } - bbsel = EDBM_backbuf_circle_init(vc, mval[0], mval[1], (short)(rad + 1.0f)); - if (bbsel) { - changed |= edbm_backbuf_check_and_select_verts_obmode(me, sel_op); - EDBM_backbuf_free(); + if (use_zbuf) { + struct EditSelectBuf_Cache *esel = wm_userdata->data; + const uint buffer_len = EDBM_select_id_context_elem_len(esel->sel_id_ctx); + esel->select_bitmap = ED_select_buffer_bitmap_from_circle(buffer_len, mval, (int)(rad + 1.0f)); + if (esel->select_bitmap != NULL) { + changed |= edbm_backbuf_check_and_select_verts_obmode(me, esel, sel_op); + MEM_freeN(esel->select_bitmap); + esel->select_bitmap = NULL; } } else { @@ -3593,27 +3842,40 @@ static bool mball_circle_select(ViewContext *vc, /** Callbacks for circle selection in Editmode */ static bool obedit_circle_select(ViewContext *vc, + wmGenericUserData *wm_userdata, const eSelectOp sel_op, const int mval[2], float rad) { + bool changed = false; BLI_assert(ELEM(sel_op, SEL_OP_SET, SEL_OP_ADD, SEL_OP_SUB)); switch (vc->obedit->type) { case OB_MESH: - return mesh_circle_select(vc, sel_op, mval, rad); + changed = mesh_circle_select(vc, wm_userdata, sel_op, mval, rad); + break; case OB_CURVE: case OB_SURF: - return nurbscurve_circle_select(vc, sel_op, mval, rad); + changed = nurbscurve_circle_select(vc, sel_op, mval, rad); + break; case OB_LATTICE: - return lattice_circle_select(vc, sel_op, mval, rad); + changed = lattice_circle_select(vc, sel_op, mval, rad); + break; case OB_ARMATURE: - return armature_circle_select(vc, sel_op, mval, rad); + changed = armature_circle_select(vc, sel_op, mval, rad); + break; case OB_MBALL: - return mball_circle_select(vc, sel_op, mval, rad); + changed = mball_circle_select(vc, sel_op, mval, rad); + break; default: BLI_assert(0); - return false; + break; } + + if (changed) { + DEG_id_tag_update(vc->obact->data, ID_RECALC_SELECT); + WM_main_add_notifier(NC_GEOM | ND_SELECT, vc->obact->data); + } + return changed; } static bool object_circle_select(ViewContext *vc, @@ -3662,8 +3924,13 @@ static int view3d_circle_select_exec(bContext *C, wmOperator *op) const int radius = RNA_int_get(op->ptr, "radius"); const int mval[2] = {RNA_int_get(op->ptr, "x"), RNA_int_get(op->ptr, "y")}; + /* Allow each selection type to allocate their own data thats used between executions. */ + wmGesture *gesture = op->customdata; /* NULL when non-modal. */ + wmGenericUserData wm_userdata_buf = {0}; + wmGenericUserData *wm_userdata = gesture ? &gesture->user_data : &wm_userdata_buf; + const eSelectOp sel_op = ED_select_op_modal(RNA_enum_get(op->ptr, "mode"), - WM_gesture_is_modal_first(op->customdata)); + WM_gesture_is_modal_first(gesture)); ED_view3d_viewcontext_init(C, &vc); @@ -3672,7 +3939,9 @@ static int view3d_circle_select_exec(bContext *C, wmOperator *op) if (obedit || BKE_paint_select_elem_test(obact) || (obact && (obact->mode & OB_MODE_POSE))) { view3d_operator_needs_opengl(C); - BKE_object_update_select_id(CTX_data_main(C)); + if (obedit == NULL) { + BKE_object_update_select_id(CTX_data_main(C)); + } FOREACH_OBJECT_IN_MODE_BEGIN (vc.view_layer, vc.v3d, obact->type, obact->mode, ob_iter) { ED_view3d_viewcontext_init_object(&vc, ob_iter); @@ -3681,16 +3950,13 @@ static int view3d_circle_select_exec(bContext *C, wmOperator *op) obedit = vc.obedit; if (obedit) { - if (obedit_circle_select(&vc, sel_op, mval, (float)radius)) { - DEG_id_tag_update(obact->data, ID_RECALC_SELECT); - WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obact->data); - } + obedit_circle_select(&vc, wm_userdata, sel_op, mval, (float)radius); } else if (BKE_paint_select_face_test(obact)) { - paint_facesel_circle_select(&vc, sel_op, mval, (float)radius); + paint_facesel_circle_select(&vc, wm_userdata, sel_op, mval, (float)radius); } else if (BKE_paint_select_vert_test(obact)) { - paint_vertsel_circle_select(&vc, sel_op, mval, (float)radius); + paint_vertsel_circle_select(&vc, wm_userdata, sel_op, mval, (float)radius); } else if (obact->mode & OB_MODE_POSE) { pose_circle_select(&vc, sel_op, mval, (float)radius); @@ -3717,6 +3983,11 @@ static int view3d_circle_select_exec(bContext *C, wmOperator *op) } } + /* Otherwise this is freed by the gesture. */ + if (wm_userdata == &wm_userdata_buf) { + WM_generic_user_data_free(wm_userdata); + } + return OPERATOR_FINISHED; } diff --git a/source/blender/editors/space_view3d/view3d_view.c b/source/blender/editors/space_view3d/view3d_view.c index 2454358b687..5865efa0ffa 100644 --- a/source/blender/editors/space_view3d/view3d_view.c +++ b/source/blender/editors/space_view3d/view3d_view.c @@ -428,7 +428,7 @@ void ED_view3d_smooth_view_force_finish(bContext *C, View3D *v3d, ARegion *ar) * can use them without redrawing first */ Depsgraph *depsgraph = CTX_data_depsgraph(C); Scene *scene = CTX_data_scene(C); - ED_view3d_update_viewmat(depsgraph, scene, v3d, ar, NULL, NULL, NULL); + ED_view3d_update_viewmat(depsgraph, scene, v3d, ar, NULL, NULL, NULL, false); } } diff --git a/source/blender/editors/transform/transform.c b/source/blender/editors/transform/transform.c index 09f198ff14c..c3acd604ee1 100644 --- a/source/blender/editors/transform/transform.c +++ b/source/blender/editors/transform/transform.c @@ -4835,6 +4835,7 @@ static void initNormalRotation(TransInfo *t) BMEditMesh *em = BKE_editmesh_from_object(tc->obedit); BMesh *bm = em->bm; + BKE_editmesh_ensure_autosmooth(em); BKE_editmesh_lnorspace_update(em); storeCustomLNorValue(tc, bm); diff --git a/source/blender/editors/transform/transform_generics.c b/source/blender/editors/transform/transform_generics.c index 758551be0b5..6a9c6856a03 100644 --- a/source/blender/editors/transform/transform_generics.c +++ b/source/blender/editors/transform/transform_generics.c @@ -1177,12 +1177,7 @@ static void recalcData_sequencer(TransInfo *t) Sequence *seq = tdsq->seq; if (seq != seq_prev) { - if (BKE_sequence_tx_fullupdate_test(seq)) { - BKE_sequence_invalidate_cache(t->scene, seq); - } - else { - BKE_sequence_invalidate_cache(t->scene, seq); - } + BKE_sequence_invalidate_cache_composite(t->scene, seq); } seq_prev = seq; diff --git a/source/blender/editors/transform/transform_gizmo_3d.c b/source/blender/editors/transform/transform_gizmo_3d.c index e43379dc358..68885a72092 100644 --- a/source/blender/editors/transform/transform_gizmo_3d.c +++ b/source/blender/editors/transform/transform_gizmo_3d.c @@ -1661,7 +1661,12 @@ static void WIDGETGROUP_gizmo_setup(const bContext *C, wmGizmoGroup *gzgroup) else if (tref && STREQ(tref->idname, "builtin.scale")) { ggd->twtype |= V3D_GIZMO_SHOW_OBJECT_SCALE; } + else if (tref && STREQ(tref->idname, "builtin.transform")) { + ggd->twtype = V3D_GIZMO_SHOW_OBJECT_TRANSLATE | V3D_GIZMO_SHOW_OBJECT_ROTATE | + V3D_GIZMO_SHOW_OBJECT_SCALE; + } else { + /* This is also correct logic for 'builtin.transform', no special check needed. */ /* Setup all gizmos, they can be toggled via 'ToolSettings.gizmo_flag' */ ggd->twtype = V3D_GIZMO_SHOW_OBJECT_TRANSLATE | V3D_GIZMO_SHOW_OBJECT_ROTATE | V3D_GIZMO_SHOW_OBJECT_SCALE; @@ -1852,7 +1857,10 @@ static void WIDGETGROUP_gizmo_draw_prepare(const bContext *C, wmGizmoGroup *gzgr } } -static void WIDGETGROUP_gizmo_invoke_prepare(const bContext *C, wmGizmoGroup *gzgroup, wmGizmo *gz) +static void WIDGETGROUP_gizmo_invoke_prepare(const bContext *C, + wmGizmoGroup *gzgroup, + wmGizmo *gz, + const wmEvent *UNUSED(event)) { GizmoGroup *ggd = gzgroup->customdata; @@ -1971,12 +1979,12 @@ static bool WIDGETGROUP_gizmo_poll_tool(const struct bContext *C, struct wmGizmo return true; } -/* Expose as multiple gizmos so tools use one, persistant context another. +/* Expose as multiple gizmos so tools use one, persistent context another. * Needed because they use different options which isn't so simple to dynamically update. */ void VIEW3D_GGT_xform_gizmo(wmGizmoGroupType *gzgt) { - gzgt->name = "Transform Gizmo"; + gzgt->name = "3D View: Transform Gizmo"; gzgt->idname = "VIEW3D_GGT_xform_gizmo"; gzgt->flag = WM_GIZMOGROUPTYPE_3D; @@ -1990,12 +1998,26 @@ void VIEW3D_GGT_xform_gizmo(wmGizmoGroupType *gzgt) gzgt->message_subscribe = WIDGETGROUP_gizmo_message_subscribe; gzgt->draw_prepare = WIDGETGROUP_gizmo_draw_prepare; gzgt->invoke_prepare = WIDGETGROUP_gizmo_invoke_prepare; + + static const EnumPropertyItem rna_enum_gizmo_items[] = { + {V3D_GIZMO_SHOW_OBJECT_TRANSLATE, "TRANSLATE", 0, "Move", ""}, + {V3D_GIZMO_SHOW_OBJECT_ROTATE, "ROTATE", 0, "Rotate", ""}, + {V3D_GIZMO_SHOW_OBJECT_SCALE, "SCALE", 0, "Scale", ""}, + {0, "NONE", 0, "None", ""}, + {0, NULL, 0, NULL, NULL}, + }; + RNA_def_enum(gzgt->srna, + "drag_action", + rna_enum_gizmo_items, + V3D_GIZMO_SHOW_OBJECT_TRANSLATE, + "Drag Action", + ""); } /** Only poll, flag & gzmap_params differ. */ void VIEW3D_GGT_xform_gizmo_context(wmGizmoGroupType *gzgt) { - gzgt->name = "Transform Gizmo Context"; + gzgt->name = "3D View: Transform Gizmo Context"; gzgt->idname = "VIEW3D_GGT_xform_gizmo_context"; gzgt->flag = WM_GIZMOGROUPTYPE_3D | WM_GIZMOGROUPTYPE_PERSISTENT; diff --git a/source/blender/editors/transform/transform_gizmo_extrude_3d.c b/source/blender/editors/transform/transform_gizmo_extrude_3d.c index 47a584561f9..24ef92b3153 100644 --- a/source/blender/editors/transform/transform_gizmo_extrude_3d.c +++ b/source/blender/editors/transform/transform_gizmo_extrude_3d.c @@ -385,7 +385,8 @@ static void gizmo_mesh_extrude_draw_prepare(const bContext *C, wmGizmoGroup *gzg static void gizmo_mesh_extrude_invoke_prepare(const bContext *UNUSED(C), wmGizmoGroup *gzgroup, - wmGizmo *gz) + wmGizmo *gz, + const wmEvent *UNUSED(event)) { GizmoExtrudeGroup *ggd = gzgroup->customdata; if (ELEM(gz, ggd->adjust[0], ggd->adjust[1])) { diff --git a/source/blender/editors/transform/transform_ops.c b/source/blender/editors/transform/transform_ops.c index 8606cd19c96..f028f2dc506 100644 --- a/source/blender/editors/transform/transform_ops.c +++ b/source/blender/editors/transform/transform_ops.c @@ -1170,7 +1170,7 @@ static void TRANSFORM_OT_rotate_normal(struct wmOperatorType *ot) ot->exec = transform_exec; ot->modal = transform_modal; ot->cancel = transform_cancel; - ot->poll = ED_operator_editmesh_auto_smooth; + ot->poll = ED_operator_editmesh; RNA_def_float_rotation( ot->srna, "value", 0, NULL, -FLT_MAX, FLT_MAX, "Angle", "", -M_PI * 2, M_PI * 2); @@ -1210,6 +1210,60 @@ static void TRANSFORM_OT_transform(struct wmOperatorType *ot) P_ALIGN_SNAP | P_GPENCIL_EDIT | P_CENTER); } +static int transform_from_gizmo_invoke(bContext *C, + wmOperator *UNUSED(op), + const wmEvent *UNUSED(event)) +{ + bToolRef *tref = WM_toolsystem_ref_from_context(C); + if (tref) { + ARegion *ar = CTX_wm_region(C); + wmGizmoMap *gzmap = ar->gizmo_map; + wmGizmoGroup *gzgroup = gzmap ? WM_gizmomap_group_find(gzmap, "VIEW3D_GGT_xform_gizmo") : NULL; + if (gzgroup != NULL) { + PointerRNA gzg_ptr; + WM_toolsystem_ref_properties_ensure_from_gizmo_group(tref, gzgroup->type, &gzg_ptr); + const int drag_action = RNA_enum_get(&gzg_ptr, "drag_action"); + const char *op_id = NULL; + switch (drag_action) { + case V3D_GIZMO_SHOW_OBJECT_TRANSLATE: + op_id = "TRANSFORM_OT_translate"; + break; + case V3D_GIZMO_SHOW_OBJECT_ROTATE: + op_id = "TRANSFORM_OT_rotate"; + break; + case V3D_GIZMO_SHOW_OBJECT_SCALE: + op_id = "TRANSFORM_OT_resize"; + break; + default: + break; + } + if (op_id) { + wmOperatorType *ot = WM_operatortype_find(op_id, true); + PointerRNA op_ptr; + WM_operator_properties_create_ptr(&op_ptr, ot); + RNA_boolean_set(&op_ptr, "release_confirm", true); + WM_operator_name_call_ptr(C, ot, WM_OP_INVOKE_DEFAULT, &op_ptr); + WM_operator_properties_free(&op_ptr); + return OPERATOR_FINISHED; + } + } + } + return OPERATOR_PASS_THROUGH; +} + +/* Use with 'TRANSFORM_GGT_gizmo'. */ +static void TRANSFORM_OT_from_gizmo(struct wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Transform From Gizmo"; + ot->description = "Transform selected items by mode type"; + ot->idname = "TRANSFORM_OT_from_gizmo"; + ot->flag = 0; + + /* api callbacks */ + ot->invoke = transform_from_gizmo_invoke; +} + void transform_operatortypes(void) { TransformModeItem *tmode; @@ -1223,6 +1277,8 @@ void transform_operatortypes(void) WM_operatortype_append(TRANSFORM_OT_select_orientation); WM_operatortype_append(TRANSFORM_OT_create_orientation); WM_operatortype_append(TRANSFORM_OT_delete_orientation); + + WM_operatortype_append(TRANSFORM_OT_from_gizmo); } void ED_keymap_transform(wmKeyConfig *keyconf) diff --git a/source/blender/editors/undo/ed_undo.c b/source/blender/editors/undo/ed_undo.c index 49b5cada04a..ccbe12b4a93 100644 --- a/source/blender/editors/undo/ed_undo.c +++ b/source/blender/editors/undo/ed_undo.c @@ -569,7 +569,7 @@ static const EnumPropertyItem *rna_undo_itemf(bContext *C, int *totitem) item_tmp.identifier = us->name; item_tmp.name = IFACE_(us->name); if (us == wm->undo_stack->step_active) { - item_tmp.icon = ICON_HIDE_OFF; + item_tmp.icon = ICON_LAYER_ACTIVE; } else { item_tmp.icon = ICON_NONE; diff --git a/source/blender/editors/util/CMakeLists.txt b/source/blender/editors/util/CMakeLists.txt index 0564cb07897..c09237d825d 100644 --- a/source/blender/editors/util/CMakeLists.txt +++ b/source/blender/editors/util/CMakeLists.txt @@ -41,6 +41,7 @@ set(SRC ed_util.c gizmo_utils.c numinput.c + select_buffer_utils.c select_utils.c # general includes @@ -79,6 +80,7 @@ set(SRC ../include/ED_screen.h ../include/ED_screen_types.h ../include/ED_sculpt.h + ../include/ED_select_buffer_utils.h ../include/ED_select_utils.h ../include/ED_sequencer.h ../include/ED_sound.h diff --git a/source/blender/editors/util/select_buffer_utils.c b/source/blender/editors/util/select_buffer_utils.c new file mode 100644 index 00000000000..130f6819e34 --- /dev/null +++ b/source/blender/editors/util/select_buffer_utils.c @@ -0,0 +1,303 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2008 Blender Foundation. + * All rights reserved. + */ + +/** \file + * \ingroup edutil + * + * Generic utilities for handling buffer selection where selection ID's are drawn onto + * an off screen buffer. + * + * All coordinates are relative to the current region. + */ + +#include "MEM_guardedalloc.h" + +#include "BLI_bitmap.h" +#include "BLI_bitmap_draw_2d.h" +#include "BLI_rect.h" +#include "BLI_utildefines.h" + +#include "ED_select_buffer_utils.h" + +/* Only for #ED_view3d_select_id_read, + * note that this file shouldn't have 3D view specific logic in it, we could have a more general + * way to read from selection buffers that doesn't depend on the view3d API. */ +#include "ED_view3d.h" + +/* -------------------------------------------------------------------- */ +/** \name Select Bitmap from ID's + * + * Given a buffer of select ID's, fill in a booleans (true/false) per index. + * #BLI_bitmap is used for memory effeciency. + * + * \{ */ + +/** + * \param bitmap_len: Number of indices in the selection id buffer. + * \param rect: The rectangle to sample indices from (min/max inclusive). + * \returns a #BLI_bitmap the length of \a bitmap_len or NULL on failure. + */ +uint *ED_select_buffer_bitmap_from_rect(const uint bitmap_len, const rcti *rect) +{ + uint buf_len; + const uint *buf = ED_view3d_select_id_read( + rect->xmin, rect->ymin, rect->xmax, rect->ymax, &buf_len); + if (buf == NULL) { + return NULL; + } + + const uint *buf_iter = buf; + + BLI_bitmap *bitmap_buf = BLI_BITMAP_NEW(bitmap_len, __func__); + + while (buf_len--) { + const uint index = *buf_iter - 1; + if (index < bitmap_len) { + BLI_BITMAP_ENABLE(bitmap_buf, index); + } + buf_iter++; + } + MEM_freeN((void *)buf); + return bitmap_buf; +} + +/** + * \param bitmap_len: Number of indices in the selection id buffer. + * \param center: Circle center. + * \param radius: Circle radius. + * \returns a #BLI_bitmap the length of \a bitmap_len or NULL on failure. + */ +uint *ED_select_buffer_bitmap_from_circle(const uint bitmap_len, + const int center[2], + const int radius) +{ + if (bitmap_len == 0) { + return NULL; + } + + const int xmin = center[0] - radius; + const int xmax = center[0] + radius; + const int ymin = center[1] - radius; + const int ymax = center[1] + radius; + + const uint *buf = ED_view3d_select_id_read(xmin, ymin, xmax, ymax, NULL); + if (buf == NULL) { + return NULL; + } + + const uint *buf_iter = buf; + + BLI_bitmap *bitmap_buf = BLI_BITMAP_NEW(bitmap_len, __func__); + const int radius_sq = radius * radius; + for (int yc = -radius; yc <= radius; yc++) { + for (int xc = -radius; xc <= radius; xc++, buf_iter++) { + if (xc * xc + yc * yc < radius_sq) { + /* Intentionally wrap to max value if this is zero. */ + const uint index = *buf_iter - 1; + if (index < bitmap_len) { + BLI_BITMAP_ENABLE(bitmap_buf, index); + } + } + } + } + MEM_freeN((void *)buf); + return bitmap_buf; +} + +struct PolyMaskData { + BLI_bitmap *px; + int width; +}; + +static void ed_select_buffer_mask_px_cb(int x, int x_end, int y, void *user_data) +{ + struct PolyMaskData *data = user_data; + BLI_bitmap *px = data->px; + int i = (y * data->width) + x; + do { + BLI_BITMAP_ENABLE(px, i); + i++; + } while (++x != x_end); +} + +/** + * \param bitmap_len: Number of indices in the selection id buffer. + * \param center: Circle center. + * \param radius: Circle radius. + * \returns a #BLI_bitmap the length of \a bitmap_len or NULL on failure. + */ +uint *ED_select_buffer_bitmap_from_poly(const uint bitmap_len, + const int poly[][2], + const int poly_len, + const rcti *rect) + +{ + if (bitmap_len == 0) { + return NULL; + } + + struct PolyMaskData poly_mask_data; + uint buf_len; + const uint *buf = ED_view3d_select_id_read( + rect->xmin, rect->ymin, rect->xmax, rect->ymax, &buf_len); + if (buf == NULL) { + return NULL; + } + + BLI_bitmap *buf_mask = BLI_BITMAP_NEW(buf_len, __func__); + poly_mask_data.px = buf_mask; + poly_mask_data.width = (rect->xmax - rect->xmin) + 1; + + BLI_bitmap_draw_2d_poly_v2i_n(rect->xmin, + rect->ymin, + rect->xmax + 1, + rect->ymax + 1, + poly, + poly_len, + ed_select_buffer_mask_px_cb, + &poly_mask_data); + + /* Build selection lookup. */ + const uint *buf_iter = buf; + BLI_bitmap *bitmap_buf = BLI_BITMAP_NEW(bitmap_len, __func__); + int i = 0; + while (buf_len--) { + const uint index = *buf_iter - 1; + if (index < bitmap_len && BLI_BITMAP_TEST(buf_mask, i)) { + BLI_BITMAP_ENABLE(bitmap_buf, index); + } + buf_iter++; + i++; + } + MEM_freeN((void *)buf); + MEM_freeN(buf_mask); + + return bitmap_buf; +} + +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Find Single Select ID's + * + * Given a buffer of select ID's, find the a single select id. + * + * \{ */ + +/** + * Samples a single pixel. + */ +uint ED_select_buffer_sample_point(const int center[2]) +{ + uint buf_len; + uint *buf = ED_view3d_select_id_read(center[0], center[1], center[0], center[1], &buf_len); + BLI_assert(0 != buf_len); + uint ret = buf[0]; + MEM_freeN(buf); + return ret; +} + +/** + * Find the selection id closest to \a center. + * \param dist[in,out]: Use to initalize the distance, + * when found, this value is set to the distance of the selection thats returned. + */ +uint ED_select_buffer_find_nearest_to_point(const int center[2], + const uint id_min, + const uint id_max, + uint *dist) +{ + /* Smart function to sample a rect spiralling outside, nice for selection ID. */ + + /* Create region around center (typically the mouse cursor). + * This must be square and have an odd width, + * the spiraling algorithm does not work with arbitrary rectangles. */ + rcti rect; + BLI_rcti_init_pt_radius(&rect, center, *dist); + rect.xmax += 1; + rect.ymax += 1; + + int width = BLI_rcti_size_x(&rect); + int height = width; + BLI_assert(width == height); + + /* Read from selection framebuffer. */ + + uint buf_len; + const uint *buf = ED_view3d_select_id_read_rect(&rect, &buf_len); + BLI_assert(width * height == buf_len); + + /* Spiral, starting from center of buffer. */ + int spiral_offset = height * (int)(width / 2) + (height / 2); + int spiral_direction = 0; + + uint index = 0; + + for (int nr = 1; nr <= height; nr++) { + for (int a = 0; a < 2; a++) { + for (int b = 0; b < nr; b++) { + /* Find hit within the specified range. */ + uint hit_id = buf[spiral_offset]; + + if (hit_id && hit_id >= id_min && hit_id < id_max) { + /* Get x/y from spiral offset. */ + int hit_x = spiral_offset % width; + int hit_y = spiral_offset / width; + + int center_x = width / 2; + int center_y = height / 2; + + /* Manhatten distance in keeping with other screen-based selection. */ + *dist = (uint)(abs(hit_x - center_x) + abs(hit_y - center_y)); + + /* Indices start at 1 here. */ + index = (hit_id - id_min) + 1; + goto exit; + } + + /* Next spiral step. */ + if (spiral_direction == 0) { + spiral_offset += 1; /* right */ + } + else if (spiral_direction == 1) { + spiral_offset -= width; /* down */ + } + else if (spiral_direction == 2) { + spiral_offset -= 1; /* left */ + } + else { + spiral_offset += width; /* up */ + } + + /* Stop if we are outside the buffer. */ + if (spiral_offset < 0 || spiral_offset >= buf_len) { + goto exit; + } + } + + spiral_direction = (spiral_direction + 1) % 4; + } + } + +exit: + MEM_freeN((void *)buf); + return index; +} + +/** \} */ diff --git a/source/blender/editors/uvedit/uvedit_draw.c b/source/blender/editors/uvedit/uvedit_draw.c index 3a5aead3d44..7f9b90f4496 100644 --- a/source/blender/editors/uvedit/uvedit_draw.c +++ b/source/blender/editors/uvedit/uvedit_draw.c @@ -246,6 +246,7 @@ static void draw_uvs_texpaint(Scene *scene, Object *ob, Depsgraph *depsgraph) bool prev_ma_match = (mpoly->mat_nr == (eval_ob->actcol - 1)); GPU_matrix_bind(geom->interface); + GPU_batch_bind(geom); /* TODO(fclem): If drawcall count becomes a problem in the future * we can use multi draw indirect drawcalls for this. @@ -254,7 +255,7 @@ static void draw_uvs_texpaint(Scene *scene, Object *ob, Depsgraph *depsgraph) bool ma_match = (mpoly->mat_nr == (eval_ob->actcol - 1)); if (ma_match != prev_ma_match) { if (ma_match == false) { - GPU_batch_draw_range_ex(geom, draw_start, idx - draw_start, false); + GPU_batch_draw_advanced(geom, draw_start, idx - draw_start, 0, 0); } else { draw_start = idx; @@ -264,7 +265,7 @@ static void draw_uvs_texpaint(Scene *scene, Object *ob, Depsgraph *depsgraph) prev_ma_match = ma_match; } if (prev_ma_match == true) { - GPU_batch_draw_range_ex(geom, draw_start, idx - draw_start, false); + GPU_batch_draw_advanced(geom, draw_start, idx - draw_start, 0, 0); } GPU_batch_program_use_end(geom); |