diff options
Diffstat (limited to 'source/blender/editors')
158 files changed, 3625 insertions, 1644 deletions
diff --git a/source/blender/editors/animation/anim_markers.c b/source/blender/editors/animation/anim_markers.c index 624c6e9f5de..e957e84857a 100644 --- a/source/blender/editors/animation/anim_markers.c +++ b/source/blender/editors/animation/anim_markers.c @@ -76,6 +76,8 @@ #include "ED_transform.h" #include "ED_types.h" +#include "DEG_depsgraph.h" + /* ************* Marker API **************** */ /* helper function for getting the list of markers to work on */ @@ -1196,6 +1198,7 @@ static int ed_marker_select(bContext *C, const wmEvent *event, bool extend, bool } } + DEG_id_tag_update(&scene->id, DEG_TAG_SELECT_UPDATE); WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene); } #else diff --git a/source/blender/editors/animation/anim_ops.c b/source/blender/editors/animation/anim_ops.c index 23563e7f15f..4402ca78976 100644 --- a/source/blender/editors/animation/anim_ops.c +++ b/source/blender/editors/animation/anim_ops.c @@ -268,7 +268,7 @@ static void ANIM_OT_change_frame(wmOperatorType *ot) /* flags */ ot->flag = OPTYPE_BLOCKING | OPTYPE_GRAB_CURSOR | OPTYPE_UNDO_GROUPED; - ot->undo_group = "FRAME_CHANGE"; + ot->undo_group = "Frame Change"; /* rna */ ot->prop = RNA_def_float(ot->srna, "frame", 0, MINAFRAME, MAXFRAME, "Frame", "", MINAFRAME, MAXFRAME); @@ -332,7 +332,7 @@ static void ANIM_OT_start_frame_set(wmOperatorType *ot) /* identifiers */ ot->name = "Set Start Frame"; ot->idname = "ANIM_OT_start_frame_set"; - ot->description = "Set the start frame"; + ot->description = "Set the current frame as the preview or scene start frame"; /* api callbacks */ ot->exec = anim_set_sfra_exec; @@ -376,7 +376,7 @@ static void ANIM_OT_end_frame_set(wmOperatorType *ot) /* identifiers */ ot->name = "Set End Frame"; ot->idname = "ANIM_OT_end_frame_set"; - ot->description = "Set the end frame"; + ot->description = "Set the current frame as the preview or scene end frame"; /* api callbacks */ ot->exec = anim_set_efra_exec; diff --git a/source/blender/editors/animation/drivers.c b/source/blender/editors/animation/drivers.c index 294cff43c56..f303be0dd76 100644 --- a/source/blender/editors/animation/drivers.c +++ b/source/blender/editors/animation/drivers.c @@ -449,6 +449,7 @@ int ANIM_add_driver(ReportList *reports, ID *id, const char rna_path[], int arra else fval = RNA_property_float_get_index(&ptr, prop, array_index); BLI_snprintf(expression, maxlen, "%s%.3f", dvar_prefix, fval); + BLI_str_rstrip_float_zero(expression, '\0'); } else if (flag & CREATEDRIVER_WITH_DEFAULT_DVAR) { BLI_strncpy(expression, "var", maxlen); diff --git a/source/blender/editors/animation/keyframing.c b/source/blender/editors/animation/keyframing.c index 1913eb944d9..fe5714aba2e 100644 --- a/source/blender/editors/animation/keyframing.c +++ b/source/blender/editors/animation/keyframing.c @@ -954,7 +954,7 @@ bool insert_keyframe_direct(Depsgraph *depsgraph, ReportList *reports, PointerRN if (RNA_path_resolved_create(&ptr, prop, fcu->array_index, &anim_rna)) { /* for making it easier to add corrective drivers... */ - cfra = evaluate_driver(&anim_rna, fcu->driver, cfra); + cfra = evaluate_driver(&anim_rna, fcu->driver, fcu->driver, cfra); } else { cfra = 0.0f; diff --git a/source/blender/editors/armature/armature_relations.c b/source/blender/editors/armature/armature_relations.c index 9282148e857..cc149d3e42f 100644 --- a/source/blender/editors/armature/armature_relations.c +++ b/source/blender/editors/armature/armature_relations.c @@ -377,7 +377,7 @@ int join_armature_exec(bContext *C, wmOperator *op) } else { /* merge in data - we'll fix the drivers manually */ - BKE_animdata_merge_copy(&ob->id, &base->object->id, ADT_MERGECOPY_KEEP_DST, false); + BKE_animdata_merge_copy(bmain, &ob->id, &base->object->id, ADT_MERGECOPY_KEEP_DST, false); } } @@ -388,7 +388,7 @@ int join_armature_exec(bContext *C, wmOperator *op) } else { /* merge in data - we'll fix the drivers manually */ - BKE_animdata_merge_copy(&arm->id, &curarm->id, ADT_MERGECOPY_KEEP_DST, false); + BKE_animdata_merge_copy(bmain, &arm->id, &curarm->id, ADT_MERGECOPY_KEEP_DST, false); } } @@ -403,6 +403,7 @@ int join_armature_exec(bContext *C, wmOperator *op) ED_armature_from_edit(bmain, arm); ED_armature_edit_free(arm); + DEG_id_tag_update(&scene->id, DEG_TAG_SELECT_UPDATE); WM_event_add_notifier(C, NC_SCENE | ND_OB_ACTIVE, scene); return OPERATOR_FINISHED; diff --git a/source/blender/editors/armature/armature_select.c b/source/blender/editors/armature/armature_select.c index 95acc8ab6ba..e295e1fd35a 100644 --- a/source/blender/editors/armature/armature_select.c +++ b/source/blender/editors/armature/armature_select.c @@ -254,7 +254,9 @@ void *get_nearest_bone( rect.xmin = rect.xmax = xy[0]; rect.ymin = rect.ymax = xy[1]; - hits = view3d_opengl_select(&vc, buffer, MAXPICKBUF, &rect, VIEW3D_SELECT_PICK_NEAREST); + hits = view3d_opengl_select( + &vc, buffer, MAXPICKBUF, &rect, + VIEW3D_SELECT_PICK_NEAREST, VIEW3D_SELECT_FILTER_NOP); *r_base = NULL; @@ -446,9 +448,11 @@ static EditBone *get_nearest_editbonepoint( { const int select_mode = (do_nearest ? VIEW3D_SELECT_PICK_NEAREST : VIEW3D_SELECT_PICK_ALL); + const eV3DSelectObjectFilter select_filter = VIEW3D_SELECT_FILTER_NOP; + rcti rect; BLI_rcti_init_pt_radius(&rect, vc->mval, 12); - const int hits12 = view3d_opengl_select(vc, buffer, MAXPICKBUF, &rect, select_mode); + const int hits12 = view3d_opengl_select(vc, buffer, MAXPICKBUF, &rect, select_mode, select_filter); if (hits12 == 1) { hits = selectbuffer_ret_hits_12(buffer, hits12); goto cache_end; @@ -458,7 +462,9 @@ static EditBone *get_nearest_editbonepoint( offs = 4 * hits12; BLI_rcti_init_pt_radius(&rect, vc->mval, 5); - const int hits5 = view3d_opengl_select(vc, buffer + offs, MAXPICKBUF - offs, &rect, select_mode); + const int hits5 = view3d_opengl_select( + vc, buffer + offs, MAXPICKBUF - offs, &rect, + select_mode, select_filter); if (hits5 == 1) { hits = selectbuffer_ret_hits_5(buffer, hits12, hits5); @@ -717,6 +723,7 @@ bool ED_armature_edit_select_pick(bContext *C, const int mval[2], bool extend, b if (vc.view_layer->basact != basact) { vc.view_layer->basact = basact; + DEG_id_tag_update(&vc.scene->id, DEG_TAG_SELECT_UPDATE); WM_event_add_notifier(C, NC_SCENE | ND_OB_ACTIVE, vc.scene); } } diff --git a/source/blender/editors/armature/pose_utils.c b/source/blender/editors/armature/pose_utils.c index b64c8528010..e280284a9ce 100644 --- a/source/blender/editors/armature/pose_utils.c +++ b/source/blender/editors/armature/pose_utils.c @@ -40,6 +40,7 @@ #include "BKE_action.h" #include "BKE_armature.h" #include "BKE_idprop.h" +#include "BKE_main.h" #include "BKE_context.h" diff --git a/source/blender/editors/curve/editcurve.c b/source/blender/editors/curve/editcurve.c index 616017dac0a..aa50916f5e0 100644 --- a/source/blender/editors/curve/editcurve.c +++ b/source/blender/editors/curve/editcurve.c @@ -2896,7 +2896,7 @@ static int hide_exec(bContext *C, wmOperator *op) } } - DEG_id_tag_update(obedit->data, 0); + DEG_id_tag_update(obedit->data, DEG_TAG_COPY_ON_WRITE | DEG_TAG_SELECT_UPDATE); WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data); BKE_curve_nurb_vert_active_validate(obedit->data); @@ -2959,7 +2959,7 @@ static int reveal_exec(bContext *C, wmOperator *op) } } - DEG_id_tag_update(obedit->data, 0); + DEG_id_tag_update(obedit->data, DEG_TAG_COPY_ON_WRITE | DEG_TAG_SELECT_UPDATE); WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data); return OPERATOR_FINISHED; @@ -4413,6 +4413,7 @@ bool ED_curve_editnurb_select_pick(bContext *C, const int mval[2], bool extend, BKE_curve_nurb_active_set(cu, nu); } + DEG_id_tag_update(obedit->data, DEG_TAG_SELECT_UPDATE); WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data); return true; @@ -5300,6 +5301,7 @@ static int duplicate_exec(bContext *C, wmOperator *op) if (BLI_listbase_is_empty(&newnurb) == false) { BLI_movelisttolist(object_editcurve_get(obedit), &newnurb); + DEG_id_tag_update(obedit->data, DEG_TAG_SELECT_UPDATE); WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data); } else { @@ -5803,7 +5805,7 @@ void CURVE_OT_delete(wmOperatorType *ot) /* properties */ prop = RNA_def_enum(ot->srna, "type", curve_delete_type_items, 0, "Type", "Which elements to delete"); RNA_def_enum_funcs(prop, rna_curve_delete_type_itemf); - + RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE); ot->prop = prop; } @@ -6148,6 +6150,7 @@ int join_curve_exec(bContext *C, wmOperator *op) DEG_relations_tag_update(bmain); // because we removed object(s), call before editmode! DEG_id_tag_update(&ob->id, OB_RECALC_OB | OB_RECALC_DATA); + DEG_id_tag_update(&scene->id, DEG_TAG_SELECT_UPDATE); WM_event_add_notifier(C, NC_SCENE | ND_OB_ACTIVE, scene); diff --git a/source/blender/editors/curve/editcurve_select.c b/source/blender/editors/curve/editcurve_select.c index 58fb6d50575..0fae39776a9 100644 --- a/source/blender/editors/curve/editcurve_select.c +++ b/source/blender/editors/curve/editcurve_select.c @@ -55,10 +55,10 @@ #include "curve_intern.h" - #include "RNA_access.h" #include "RNA_define.h" +#include "DEG_depsgraph.h" /* returns 1 in case (de)selection was successful */ bool select_beztriple(BezTriple *bezt, bool selstatus, short flag, eVisible_Types hidden) @@ -404,6 +404,7 @@ static int de_select_first_exec(bContext *C, wmOperator *UNUSED(op)) Object *obedit = CTX_data_edit_object(C); selectend_nurb(obedit, FIRST, true, DESELECT); + DEG_id_tag_update(obedit->data, DEG_TAG_SELECT_UPDATE); WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data); BKE_curve_nurb_vert_active_validate(obedit->data); @@ -430,6 +431,7 @@ static int de_select_last_exec(bContext *C, wmOperator *UNUSED(op)) Object *obedit = CTX_data_edit_object(C); selectend_nurb(obedit, LAST, true, DESELECT); + DEG_id_tag_update(obedit->data, DEG_TAG_SELECT_UPDATE); WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data); BKE_curve_nurb_vert_active_validate(obedit->data); @@ -488,6 +490,7 @@ static int de_select_all_exec(bContext *C, wmOperator *op) break; } + DEG_id_tag_update(obedit->data, DEG_TAG_SELECT_UPDATE); WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data); BKE_curve_nurb_vert_active_validate(cu); } @@ -540,6 +543,7 @@ static int select_linked_exec(bContext *C, wmOperator *UNUSED(op)) } if (changed) { + DEG_id_tag_update(obedit->data, DEG_TAG_SELECT_UPDATE); WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data); } } @@ -608,6 +612,7 @@ static int select_linked_pick_invoke(bContext *C, wmOperator *op, const wmEvent } } + DEG_id_tag_update(obedit->data, DEG_TAG_SELECT_UPDATE); WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data); if (!select) { BKE_curve_nurb_vert_active_validate(obedit->data); @@ -670,6 +675,7 @@ static int select_row_exec(bContext *C, wmOperator *UNUSED(op)) } } + DEG_id_tag_update(obedit->data, DEG_TAG_SELECT_UPDATE); WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data); return OPERATOR_FINISHED; @@ -698,6 +704,7 @@ static int select_next_exec(bContext *C, wmOperator *UNUSED(op)) ListBase *editnurb = object_editcurve_get(obedit); select_adjacent_cp(editnurb, 1, 0, SELECT); + DEG_id_tag_update(obedit->data, DEG_TAG_SELECT_UPDATE); WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data); return OPERATOR_FINISHED; @@ -726,6 +733,7 @@ static int select_previous_exec(bContext *C, wmOperator *UNUSED(op)) ListBase *editnurb = object_editcurve_get(obedit); select_adjacent_cp(editnurb, -1, 0, SELECT); + DEG_id_tag_update(obedit->data, DEG_TAG_SELECT_UPDATE); WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data); return OPERATOR_FINISHED; @@ -814,6 +822,7 @@ static int select_more_exec(bContext *C, wmOperator *UNUSED(op)) select_adjacent_cp(editnurb, -1, 0, SELECT); } + DEG_id_tag_update(obedit->data, DEG_TAG_SELECT_UPDATE); WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data); return OPERATOR_FINISHED; @@ -1001,6 +1010,7 @@ static int select_less_exec(bContext *C, wmOperator *UNUSED(op)) } } + DEG_id_tag_update(obedit->data, DEG_TAG_SELECT_UPDATE); WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data); BKE_curve_nurb_vert_active_validate(obedit->data); @@ -1087,6 +1097,7 @@ static int curve_select_random_exec(bContext *C, wmOperator *op) curve_select_random(editnurb, randfac, seed_iter, select); BKE_curve_nurb_vert_active_validate(obedit->data); + DEG_id_tag_update(obedit->data, DEG_TAG_SELECT_UPDATE); WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data); } @@ -1197,6 +1208,7 @@ static int select_nth_exec(bContext *C, wmOperator *op) return OPERATOR_CANCELLED; } + DEG_id_tag_update(obedit->data, DEG_TAG_SELECT_UPDATE); WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data); return OPERATOR_FINISHED; @@ -1503,6 +1515,7 @@ static int curve_select_similar_exec(bContext *C, wmOperator *op) } if (changed) { + DEG_id_tag_update(obedit->data, DEG_TAG_SELECT_UPDATE); WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data); return OPERATOR_FINISHED; } @@ -1744,6 +1757,7 @@ static int edcu_shortest_path_pick_invoke(bContext *C, wmOperator *op, const wmE BKE_curve_nurb_vert_active_set(cu, nu_dst, vert_dst_p); + DEG_id_tag_update(obedit->data, DEG_TAG_SELECT_UPDATE); WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data); return OPERATOR_FINISHED; } diff --git a/source/blender/editors/curve/editfont.c b/source/blender/editors/curve/editfont.c index 7cdfafdad43..75efdec3dd2 100644 --- a/source/blender/editors/curve/editfont.c +++ b/source/blender/editors/curve/editfont.c @@ -246,7 +246,6 @@ static int insert_into_textbuf(Object *obedit, uintptr_t c) static void text_update_edited(bContext *C, Object *obedit, int mode) { - struct Main *bmain = CTX_data_main(C); Curve *cu = obedit->data; EditFont *ef = cu->editfont; @@ -259,7 +258,7 @@ static void text_update_edited(bContext *C, Object *obedit, int mode) } else { /* depsgraph runs above, but since we're not tagging for update, call direct */ - BKE_vfont_to_curve(bmain, obedit, mode); + BKE_vfont_to_curve(obedit, mode); } cu->curinfo = ef->textbufinfo[ef->pos ? ef->pos - 1 : 0]; @@ -982,16 +981,14 @@ static int move_cursor(bContext *C, int type, const bool select) /* apply virtical cursor motion to position immediately * otherwise the selection will lag behind */ if (FO_CURS_IS_MOTION(cursmove)) { - struct Main *bmain = CTX_data_main(C); - BKE_vfont_to_curve(bmain, obedit, cursmove); + BKE_vfont_to_curve(obedit, cursmove); cursmove = FO_CURS; } if (select == 0) { if (ef->selstart) { - struct Main *bmain = CTX_data_main(C); ef->selstart = ef->selend = 0; - BKE_vfont_to_curve(bmain, obedit, FO_SELCHANGE); + BKE_vfont_to_curve(obedit, FO_SELCHANGE); } } diff --git a/source/blender/editors/datafiles/CMakeLists.txt b/source/blender/editors/datafiles/CMakeLists.txt index 23b328aa8e0..98b57fcbd71 100644 --- a/source/blender/editors/datafiles/CMakeLists.txt +++ b/source/blender/editors/datafiles/CMakeLists.txt @@ -681,32 +681,6 @@ if(WITH_BLENDER) data_to_c_simple(../../../../release/datafiles/brushicons/twist.png SRC) data_to_c_simple(../../../../release/datafiles/brushicons/vertexdraw.png SRC) - # matcap - data_to_c_simple(../../../../release/datafiles/matcaps/mc01.jpg SRC) - data_to_c_simple(../../../../release/datafiles/matcaps/mc02.jpg SRC) - data_to_c_simple(../../../../release/datafiles/matcaps/mc03.jpg SRC) - data_to_c_simple(../../../../release/datafiles/matcaps/mc04.jpg SRC) - data_to_c_simple(../../../../release/datafiles/matcaps/mc05.jpg SRC) - data_to_c_simple(../../../../release/datafiles/matcaps/mc06.jpg SRC) - data_to_c_simple(../../../../release/datafiles/matcaps/mc07.jpg SRC) - data_to_c_simple(../../../../release/datafiles/matcaps/mc08.jpg SRC) - data_to_c_simple(../../../../release/datafiles/matcaps/mc09.jpg SRC) - data_to_c_simple(../../../../release/datafiles/matcaps/mc10.jpg SRC) - data_to_c_simple(../../../../release/datafiles/matcaps/mc11.jpg SRC) - data_to_c_simple(../../../../release/datafiles/matcaps/mc12.jpg SRC) - data_to_c_simple(../../../../release/datafiles/matcaps/mc13.jpg SRC) - data_to_c_simple(../../../../release/datafiles/matcaps/mc14.jpg SRC) - data_to_c_simple(../../../../release/datafiles/matcaps/mc15.jpg SRC) - data_to_c_simple(../../../../release/datafiles/matcaps/mc16.jpg SRC) - data_to_c_simple(../../../../release/datafiles/matcaps/mc17.jpg SRC) - data_to_c_simple(../../../../release/datafiles/matcaps/mc18.jpg SRC) - data_to_c_simple(../../../../release/datafiles/matcaps/mc19.jpg SRC) - data_to_c_simple(../../../../release/datafiles/matcaps/mc20.jpg SRC) - data_to_c_simple(../../../../release/datafiles/matcaps/mc21.jpg SRC) - data_to_c_simple(../../../../release/datafiles/matcaps/mc22.jpg SRC) - data_to_c_simple(../../../../release/datafiles/matcaps/mc23.jpg SRC) - data_to_c_simple(../../../../release/datafiles/matcaps/mc24.jpg SRC) - endif() data_to_c_simple(../../../../release/datafiles/startup.blend SRC) diff --git a/source/blender/editors/gpencil/gpencil_brush.c b/source/blender/editors/gpencil/gpencil_brush.c index c2e532be0b3..f9284d71db3 100644 --- a/source/blender/editors/gpencil/gpencil_brush.c +++ b/source/blender/editors/gpencil/gpencil_brush.c @@ -44,6 +44,8 @@ #include "BLI_rand.h" #include "BLI_utildefines.h" +#include "PIL_time.h" + #include "BLT_translation.h" #include "DNA_scene_types.h" @@ -138,6 +140,8 @@ typedef struct tGP_BrushEditData { /* Timer for in-place accumulation of brush effect */ wmTimer *timer; bool timerTick; /* is this event from a timer */ + + RNG *rng; } tGP_BrushEditData; @@ -658,7 +662,7 @@ static bool gp_brush_randomize_apply(tGP_BrushEditData *gso, bGPDstroke *gps, in * as well as the strength of the brush */ const float inf = gp_brush_influence_calc(gso, radius, co) / 2.0f; - const float fac = BLI_frand() * inf; + const float fac = BLI_rng_get_float(gso->rng) * inf; /* need one flag enabled by default */ if ((gso->settings->flag & (GP_BRUSHEDIT_FLAG_APPLY_POSITION | GP_BRUSHEDIT_FLAG_APPLY_STRENGTH | @@ -685,7 +689,7 @@ static bool gp_brush_randomize_apply(tGP_BrushEditData *gso, bGPDstroke *gps, in svec[1] = mvec[0]; /* scale the displacement by the random displacement, and apply */ - if (BLI_frand() > 0.5f) { + if (BLI_rng_get_float(gso->rng) > 0.5f) { mul_v2_fl(svec, -fac); } else { @@ -724,7 +728,7 @@ static bool gp_brush_randomize_apply(tGP_BrushEditData *gso, bGPDstroke *gps, in } /* apply random to strength */ if (gso->settings->flag & GP_BRUSHEDIT_FLAG_APPLY_STRENGTH) { - if (BLI_frand() > 0.5f) { + if (BLI_rng_get_float(gso->rng) > 0.5f) { pt->strength += fac; } else { @@ -735,7 +739,7 @@ static bool gp_brush_randomize_apply(tGP_BrushEditData *gso, bGPDstroke *gps, in } /* apply random to thickness (use pressure) */ if (gso->settings->flag & GP_BRUSHEDIT_FLAG_APPLY_THICKNESS) { - if (BLI_frand() > 0.5f) { + if (BLI_rng_get_float(gso->rng) > 0.5f) { pt->pressure += fac; } else { @@ -1061,6 +1065,10 @@ static bool gpsculpt_brush_init(bContext *C, wmOperator *op) gso->brush_type = gso->settings->brushtype; + /* Random generator, only init once. */ + uint rng_seed = (uint)(PIL_check_seconds_timer_i() & UINT_MAX); + rng_seed ^= GET_UINT_FROM_POINTER(gso); + gso->rng = BLI_rng_new(rng_seed); gso->is_painting = false; gso->first = true; @@ -1163,6 +1171,10 @@ static void gpsculpt_brush_exit(bContext *C, wmOperator *op) WM_event_remove_timer(CTX_wm_manager(C), win, gso->timer); } + if (gso->rng != NULL) { + BLI_rng_free(gso->rng); + } + /* disable cursor and headerprints */ ED_area_headerprint(CTX_wm_area(C), NULL); WM_cursor_modal_restore(win); diff --git a/source/blender/editors/gpencil/gpencil_convert.c b/source/blender/editors/gpencil/gpencil_convert.c index dfaa1420d68..d2301337c0e 100644 --- a/source/blender/editors/gpencil/gpencil_convert.c +++ b/source/blender/editors/gpencil/gpencil_convert.c @@ -1374,6 +1374,7 @@ static int gp_convert_layer_exec(bContext *C, wmOperator *op) } /* notifiers */ + DEG_id_tag_update(&scene->id, DEG_TAG_SELECT_UPDATE); WM_event_add_notifier(C, NC_OBJECT | NA_ADDED, NULL); WM_event_add_notifier(C, NC_SCENE | ND_OB_ACTIVE, scene); diff --git a/source/blender/editors/gpencil/gpencil_data.c b/source/blender/editors/gpencil/gpencil_data.c index 2e8e48b2f15..9f437f28f0f 100644 --- a/source/blender/editors/gpencil/gpencil_data.c +++ b/source/blender/editors/gpencil/gpencil_data.c @@ -52,14 +52,15 @@ #include "DNA_view3d_types.h" #include "DNA_gpencil_types.h" +#include "BKE_colortools.h" #include "BKE_context.h" #include "BKE_gpencil.h" #include "BKE_library.h" +#include "BKE_main.h" #include "BKE_object.h" #include "BKE_report.h" #include "BKE_scene.h" #include "BKE_screen.h" -#include "BKE_colortools.h" #include "UI_interface.h" #include "UI_resources.h" @@ -83,6 +84,7 @@ /* add new datablock - wrapper around API */ static int gp_data_add_exec(bContext *C, wmOperator *op) { + Main *bmain = CTX_data_main(C); bGPdata **gpd_ptr = ED_gpencil_data_get_pointers(C, NULL); ToolSettings *ts = CTX_data_tool_settings(C); @@ -95,7 +97,7 @@ static int gp_data_add_exec(bContext *C, wmOperator *op) bGPdata *gpd = (*gpd_ptr); id_us_min(&gpd->id); - *gpd_ptr = BKE_gpencil_data_addnew(DATA_("GPencil")); + *gpd_ptr = BKE_gpencil_data_addnew(bmain, DATA_("GPencil")); /* if not exist brushes, create a new set */ if (ts) { @@ -183,6 +185,7 @@ void GPENCIL_OT_data_unlink(wmOperatorType *ot) /* add new layer - wrapper around API */ static int gp_layer_add_exec(bContext *C, wmOperator *op) { + Main *bmain = CTX_data_main(C); bGPdata **gpd_ptr = ED_gpencil_data_get_pointers(C, NULL); ToolSettings *ts = CTX_data_tool_settings(C); @@ -192,7 +195,7 @@ static int gp_layer_add_exec(bContext *C, wmOperator *op) return OPERATOR_CANCELLED; } if (*gpd_ptr == NULL) - *gpd_ptr = BKE_gpencil_data_addnew(DATA_("GPencil")); + *gpd_ptr = BKE_gpencil_data_addnew(bmain, DATA_("GPencil")); /* if not exist brushes, create a new set */ if (ts) { @@ -1376,6 +1379,7 @@ void GPENCIL_OT_brush_select(wmOperatorType *ot) /* add new palette - wrapper around API */ static int gp_palette_add_exec(bContext *C, wmOperator *op) { + Main *bmain = CTX_data_main(C); bGPdata **gpd_ptr = ED_gpencil_data_get_pointers(C, NULL); /* if there's no existing Grease-Pencil data there, add some */ @@ -1384,7 +1388,7 @@ static int gp_palette_add_exec(bContext *C, wmOperator *op) return OPERATOR_CANCELLED; } if (*gpd_ptr == NULL) - *gpd_ptr = BKE_gpencil_data_addnew(DATA_("GPencil")); + *gpd_ptr = BKE_gpencil_data_addnew(bmain, DATA_("GPencil")); /* add new palette now */ BKE_gpencil_palette_addnew(*gpd_ptr, DATA_("GP_Palette"), true); @@ -1588,6 +1592,7 @@ void GPENCIL_OT_palette_lock_layer(wmOperatorType *ot) /* add new palette - wrapper around API */ static int gp_palettecolor_add_exec(bContext *C, wmOperator *op) { + Main *bmain = CTX_data_main(C); bGPdata **gpd_ptr = ED_gpencil_data_get_pointers(C, NULL); /* if there's no existing Grease-Pencil data there, add some */ @@ -1596,7 +1601,7 @@ static int gp_palettecolor_add_exec(bContext *C, wmOperator *op) return OPERATOR_CANCELLED; } if (*gpd_ptr == NULL) - *gpd_ptr = BKE_gpencil_data_addnew(DATA_("GPencil")); + *gpd_ptr = BKE_gpencil_data_addnew(bmain, DATA_("GPencil")); /* verify palette */ bGPDpalette *palette = BKE_gpencil_palette_getactive(*gpd_ptr); diff --git a/source/blender/editors/gpencil/gpencil_intern.h b/source/blender/editors/gpencil/gpencil_intern.h index 33af6cab915..67b88efa285 100644 --- a/source/blender/editors/gpencil/gpencil_intern.h +++ b/source/blender/editors/gpencil/gpencil_intern.h @@ -41,6 +41,7 @@ struct bGPDstroke; struct bGPDspoint; struct GHash; +struct RNG; struct ARegion; struct View2D; @@ -117,7 +118,7 @@ bool gp_smooth_stroke(bGPDstroke *gps, int i, float inf, bool affect_pressure); bool gp_smooth_stroke_strength(bGPDstroke *gps, int i, float inf); bool gp_smooth_stroke_thickness(bGPDstroke *gps, int i, float inf); void gp_subdivide_stroke(bGPDstroke *gps, const int new_totpoints); -void gp_randomize_stroke(bGPDstroke *gps, bGPDbrush *brush); +void gp_randomize_stroke(bGPDstroke *gps, bGPDbrush *brush, struct RNG *rng); /* Layers Enums -------------------------------------- */ diff --git a/source/blender/editors/gpencil/gpencil_paint.c b/source/blender/editors/gpencil/gpencil_paint.c index 437d5cef6f8..c8f1901d075 100644 --- a/source/blender/editors/gpencil/gpencil_paint.c +++ b/source/blender/editors/gpencil/gpencil_paint.c @@ -169,6 +169,8 @@ typedef struct tGPsdata { short straight[2]; /* 1: line horizontal, 2: line vertical, other: not defined, second element position */ int lock_axis; /* lock drawing to one axis */ + RNG *rng; + short keymodifier; /* key used for invoking the operator */ } tGPsdata; @@ -408,7 +410,8 @@ static void gp_stroke_convertcoords(tGPsdata *p, const int mval[2], float out[3] } /* apply jitter to stroke */ -static void gp_brush_jitter(bGPdata *gpd, bGPDbrush *brush, tGPspoint *pt, const int mval[2], int r_mval[2]) +static void gp_brush_jitter( + bGPdata *gpd, bGPDbrush *brush, tGPspoint *pt, const int mval[2], int r_mval[2], RNG *rng) { float pressure = pt->pressure; float tmp_pressure = pt->pressure; @@ -417,7 +420,7 @@ static void gp_brush_jitter(bGPdata *gpd, bGPDbrush *brush, tGPspoint *pt, const tmp_pressure = curvef * brush->draw_sensitivity; } const float exfactor = (brush->draw_jitter + 2.0f) * (brush->draw_jitter + 2.0f); /* exponential value */ - const float fac = BLI_frand() * exfactor * tmp_pressure; + const float fac = BLI_rng_get_float(rng) * exfactor * tmp_pressure; /* Jitter is applied perpendicular to the mouse movement vector (2D space) */ float mvec[2], svec[2]; /* mouse movement in ints -> floats */ @@ -434,7 +437,7 @@ static void gp_brush_jitter(bGPdata *gpd, bGPDbrush *brush, tGPspoint *pt, const svec[0] = -mvec[1]; svec[1] = mvec[0]; /* scale the displacement by the random, and apply */ - if (BLI_frand() > 0.5f) { + if (BLI_rng_get_float(rng) > 0.5f) { mul_v2_fl(svec, -fac); } else { @@ -550,7 +553,7 @@ static short gp_stroke_addpoint( /* Apply jitter to position */ if (brush->draw_jitter > 0.0f) { int r_mval[2]; - gp_brush_jitter(gpd, brush, pt, mval, r_mval); + gp_brush_jitter(gpd, brush, pt, mval, r_mval, p->rng); copy_v2_v2_int(&pt->x, r_mval); } else { @@ -560,11 +563,11 @@ static short gp_stroke_addpoint( if ((brush->draw_random_press > 0.0f) && (brush->flag & GP_BRUSH_USE_RANDOM_PRESSURE)) { float curvef = curvemapping_evaluateF(brush->cur_sensitivity, 0, pressure); float tmp_pressure = curvef * brush->draw_sensitivity; - if (BLI_frand() > 0.5f) { - pt->pressure -= tmp_pressure * brush->draw_random_press * BLI_frand(); + if (BLI_rng_get_float(p->rng) > 0.5f) { + pt->pressure -= tmp_pressure * brush->draw_random_press * BLI_rng_get_float(p->rng); } else { - pt->pressure += tmp_pressure * brush->draw_random_press * BLI_frand(); + pt->pressure += tmp_pressure * brush->draw_random_press * BLI_rng_get_float(p->rng); } CLAMP(pt->pressure, GPENCIL_STRENGTH_MIN, 1.0f); } @@ -588,11 +591,11 @@ static short gp_stroke_addpoint( /* apply randomness to color strength */ if ((brush->draw_random_press > 0.0f) && (brush->flag & GP_BRUSH_USE_RANDOM_STRENGTH)) { - if (BLI_frand() > 0.5f) { - pt->strength -= pt->strength * brush->draw_random_press * BLI_frand(); + if (BLI_rng_get_float(p->rng) > 0.5f) { + pt->strength -= pt->strength * brush->draw_random_press * BLI_rng_get_float(p->rng); } else { - pt->strength += pt->strength * brush->draw_random_press * BLI_frand(); + pt->strength += pt->strength * brush->draw_random_press * BLI_rng_get_float(p->rng); } CLAMP(pt->strength, GPENCIL_STRENGTH_MIN, 1.0f); } @@ -978,7 +981,7 @@ static void gp_stroke_newfrombuffer(tGPsdata *p) } /* apply randomness to stroke */ if (brush->draw_random_sub > 0.0f) { - gp_randomize_stroke(gps, brush); + gp_randomize_stroke(gps, brush, p->rng); } /* smooth stroke after subdiv - only if there's something to do @@ -1387,6 +1390,7 @@ static void gp_init_palette(tGPsdata *p) /* (re)init new painting data */ static bool gp_session_initdata(bContext *C, tGPsdata *p) { + Main *bmain = CTX_data_main(C); bGPdata **gpd_ptr = NULL; ScrArea *curarea = CTX_wm_area(C); ARegion *ar = CTX_wm_region(C); @@ -1537,7 +1541,7 @@ static bool gp_session_initdata(bContext *C, tGPsdata *p) else { /* if no existing GPencil block exists, add one */ if (*gpd_ptr == NULL) - *gpd_ptr = BKE_gpencil_data_addnew("GPencil"); + *gpd_ptr = BKE_gpencil_data_addnew(bmain, "GPencil"); p->gpd = *gpd_ptr; } @@ -1582,6 +1586,11 @@ static tGPsdata *gp_session_initpaint(bContext *C) */ p->radius = U.gp_eraser; + /* Random generator, only init once. */ + uint rng_seed = (uint)(PIL_check_seconds_timer_i() & UINT_MAX); + rng_seed ^= GET_UINT_FROM_POINTER(p); + p->rng = BLI_rng_new(rng_seed); + /* return context data for running paint operator */ return p; } @@ -1608,6 +1617,15 @@ static void gp_session_cleanup(tGPsdata *p) p->inittime = 0.0; } +static void gp_session_free(tGPsdata *p) +{ + if (p->rng != NULL) { + BLI_rng_free(p->rng); + } + MEM_freeN(p); +} + + /* init new stroke */ static void gp_paint_initstroke(tGPsdata *p, eGPencil_PaintModes paintmode, Depsgraph *depsgraph) { @@ -1948,9 +1966,7 @@ static void gpencil_draw_exit(bContext *C, wmOperator *op) /* cleanup */ gp_paint_cleanup(p); gp_session_cleanup(p); - - /* finally, free the temp data */ - MEM_freeN(p); + gp_session_free(p); } op->customdata = NULL; diff --git a/source/blender/editors/gpencil/gpencil_undo.c b/source/blender/editors/gpencil/gpencil_undo.c index 5e2be7c41f0..d35df8bc380 100644 --- a/source/blender/editors/gpencil/gpencil_undo.c +++ b/source/blender/editors/gpencil/gpencil_undo.c @@ -179,7 +179,7 @@ void gpencil_undo_push(bGPdata *gpd) /* create new undo node */ undo_node = MEM_callocN(sizeof(bGPundonode), "gpencil undo node"); - undo_node->gpd = BKE_gpencil_data_duplicate(G.main, gpd, true); + undo_node->gpd = BKE_gpencil_data_duplicate(NULL, gpd, true); cur_node = undo_node; diff --git a/source/blender/editors/gpencil/gpencil_utils.c b/source/blender/editors/gpencil/gpencil_utils.c index f6d72d9e575..4ee3bdd587e 100644 --- a/source/blender/editors/gpencil/gpencil_utils.c +++ b/source/blender/editors/gpencil/gpencil_utils.c @@ -965,7 +965,7 @@ void gp_subdivide_stroke(bGPDstroke *gps, const int new_totpoints) * \param gps Stroke data * \param brush Brush data */ -void gp_randomize_stroke(bGPDstroke *gps, bGPDbrush *brush) +void gp_randomize_stroke(bGPDstroke *gps, bGPDbrush *brush, RNG *rng) { bGPDspoint *pt1, *pt2, *pt3; float v1[3]; @@ -998,10 +998,10 @@ void gp_randomize_stroke(bGPDstroke *gps, bGPDbrush *brush) for (int i = 1; i < gps->totpoints - 1; ++i) { bGPDspoint *pt = &gps->points[i]; /* get vector with shift (apply a division because random is too sensitive */ - const float fac = BLI_frand() * (brush->draw_random_sub / 10.0f); + const float fac = BLI_rng_get_float(rng) * (brush->draw_random_sub / 10.0f); float svec[3]; copy_v3_v3(svec, ortho); - if (BLI_frand() > 0.5f) { + if (BLI_rng_get_float(rng) > 0.5f) { mul_v3_fl(svec, -fac); } else { diff --git a/source/blender/editors/include/ED_manipulator_library.h b/source/blender/editors/include/ED_manipulator_library.h index b67af4274a6..fca0f5c8806 100644 --- a/source/blender/editors/include/ED_manipulator_library.h +++ b/source/blender/editors/include/ED_manipulator_library.h @@ -73,11 +73,18 @@ enum { ED_MANIPULATOR_ARROW_STYLE_CONE = 3, }; +/* transform */ enum { /* inverted offset during interaction - if set it also sets constrained below */ - ED_MANIPULATOR_ARROW_STYLE_INVERTED = (1 << 3), + ED_MANIPULATOR_ARROW_XFORM_FLAG_INVERTED = (1 << 3), /* clamp arrow interaction to property width */ - ED_MANIPULATOR_ARROW_STYLE_CONSTRAINED = (1 << 4), + ED_MANIPULATOR_ARROW_XFORM_FLAG_CONSTRAINED = (1 << 4), +}; + +/* draw_options */ +enum { + /* Show arrow stem. */ + ED_MANIPULATOR_ARROW_DRAW_FLAG_STEM = (1 << 0), }; void ED_manipulator_arrow3d_set_ui_range(struct wmManipulator *mpr, const float min, const float max); diff --git a/source/blender/editors/include/ED_mesh.h b/source/blender/editors/include/ED_mesh.h index 0d323258a19..a9c9e8c0fbd 100644 --- a/source/blender/editors/include/ED_mesh.h +++ b/source/blender/editors/include/ED_mesh.h @@ -83,7 +83,7 @@ void EDBM_mesh_clear(struct BMEditMesh *em); void EDBM_selectmode_to_scene(struct bContext *C); void EDBM_mesh_make(struct Object *ob, const int select_mode, const bool add_key_index); void EDBM_mesh_free(struct BMEditMesh *em); -void EDBM_mesh_load(struct Object *ob); +void EDBM_mesh_load(struct Main *bmain, struct Object *ob); struct DerivedMesh *EDBM_mesh_deform_dm_get(struct BMEditMesh *em); /* flushes based on the current select mode. if in vertex select mode, diff --git a/source/blender/editors/include/ED_object.h b/source/blender/editors/include/ED_object.h index f1311233f23..29f7edaebf0 100644 --- a/source/blender/editors/include/ED_object.h +++ b/source/blender/editors/include/ED_object.h @@ -40,6 +40,7 @@ struct Base; struct EnumPropertyItem; struct ID; struct Main; +struct Menu; struct ModifierData; struct Object; struct ReportList; @@ -58,12 +59,14 @@ struct PointerRNA; struct PropertyRNA; struct EnumPropertyItem; struct Depsgraph; +struct uiLayout; #include "DNA_object_enums.h" /* object_edit.c */ struct Object *ED_object_context(struct bContext *C); /* context.object */ struct Object *ED_object_active_context(struct bContext *C); /* context.object or context.active_object */ +void ED_hide_collections_menu_draw(const struct bContext *C, struct uiLayout *layout); /* object_ops.c */ void ED_operatortypes_object(void); @@ -245,7 +248,7 @@ int ED_object_modifier_convert( struct ReportList *reports, struct Main *bmain, struct Scene *scene, struct ViewLayer *view_layer, struct Object *ob, struct ModifierData *md); int ED_object_modifier_apply( - struct ReportList *reports, struct Depsgraph *depsgraph, struct Scene *scene, + struct Main *bmain, struct ReportList *reports, struct Depsgraph *depsgraph, struct Scene *scene, struct Object *ob, struct ModifierData *md, int mode); int ED_object_modifier_copy(struct ReportList *reports, struct Object *ob, struct ModifierData *md); @@ -277,7 +280,4 @@ void ED_object_facemap_face_remove(struct Object *ob, struct bFaceMap *fmap, int } #endif -/* Don't allow switching object-modes when selecting objects. */ -#define USE_OBJECT_MODE_STRICT - #endif /* __ED_OBJECT_H__ */ diff --git a/source/blender/editors/include/ED_screen.h b/source/blender/editors/include/ED_screen.h index a741f12c112..204c5fa5956 100644 --- a/source/blender/editors/include/ED_screen.h +++ b/source/blender/editors/include/ED_screen.h @@ -69,22 +69,33 @@ void ED_region_do_layout(struct bContext *C, struct ARegion *ar); void ED_region_do_draw(struct bContext *C, struct ARegion *ar); void ED_region_exit(struct bContext *C, struct ARegion *ar); void ED_region_pixelspace(struct ARegion *ar); -void ED_region_update_rect(struct bContext *C, struct ARegion *ar); -void ED_region_init(struct bContext *C, struct ARegion *ar); +void ED_region_update_rect(struct ARegion *ar); +void ED_region_init(struct ARegion *ar); void ED_region_tag_redraw(struct ARegion *ar); void ED_region_tag_redraw_partial(struct ARegion *ar, const struct rcti *rct); void ED_region_tag_redraw_overlay(struct ARegion *ar); void ED_region_tag_redraw_no_rebuild(struct ARegion *ar); void ED_region_tag_refresh_ui(struct ARegion *ar); -void ED_region_panels_init(struct wmWindowManager *wm, struct ARegion *ar); -void ED_region_panels( - const struct bContext *C, struct ARegion *ar, - const char *contexts[], int contextnr, - const bool vertical); -void ED_region_header_init(struct ARegion *ar); -void ED_region_header(const struct bContext *C, struct ARegion *ar); -void ED_region_header_layout(const struct bContext *C, struct ARegion *ar); -void ED_region_header_draw(const struct bContext *C, struct ARegion *ar); + +void ED_region_panels_init(struct wmWindowManager *wm, struct ARegion *ar); +void ED_region_panels_ex( + const struct bContext *C, struct ARegion *ar, + const char *contexts[], int contextnr, const bool vertical); +void ED_region_panels( + const struct bContext *C, struct ARegion *ar); +void ED_region_panels_layout_ex( + const struct bContext *C, struct ARegion *ar, + const char *contexts[], int contextnr, const bool vertical); +void ED_region_panels_layout( + const struct bContext *C, struct ARegion *ar); +void ED_region_panels_draw( + const struct bContext *C, struct ARegion *ar); + +void ED_region_header_init(struct ARegion *ar); +void ED_region_header(const struct bContext *C, struct ARegion *ar); +void ED_region_header_layout(const struct bContext *C, struct ARegion *ar); +void ED_region_header_draw(const struct bContext *C, struct ARegion *ar); + void ED_region_cursor_set(struct wmWindow *win, struct ScrArea *sa, struct ARegion *ar); void ED_region_toggle_hidden(struct bContext *C, struct ARegion *ar); void ED_region_visibility_change_update(struct bContext *C, struct ARegion *ar); @@ -308,6 +319,11 @@ void ED_region_cache_draw_background(const struct ARegion *ar); void ED_region_cache_draw_curfra_label(const int framenr, const float x, const float y); void ED_region_cache_draw_cached_segments(const struct ARegion *ar, const int num_segments, const int *points, const int sfra, const int efra); +/* interface_region_hud.c */ +struct ARegionType *ED_area_type_hud(int space_type); +void ED_area_type_hud_clear(struct wmWindowManager *wm, ScrArea *sa_keep); +void ED_area_type_hud_ensure(struct bContext *C, struct ScrArea *sa); + /* default keymaps, bitflags */ #define ED_KEYMAP_UI 1 #define ED_KEYMAP_VIEW2D 2 diff --git a/source/blender/editors/include/ED_undo.h b/source/blender/editors/include/ED_undo.h index 5103ac97361..37744e7eb0f 100644 --- a/source/blender/editors/include/ED_undo.h +++ b/source/blender/editors/include/ED_undo.h @@ -52,14 +52,6 @@ int ED_undo_operator_repeat(struct bContext *C, struct wmOperator *op); void ED_undo_operator_repeat_cb(struct bContext *C, void *arg_op, void *arg_unused); void ED_undo_operator_repeat_cb_evt(struct bContext *C, void *arg_op, int arg_unused); -/* Context sanity helpers for operator repeat. */ -typedef struct OperatorRepeatContextHandle OperatorRepeatContextHandle; - -const OperatorRepeatContextHandle *ED_operator_repeat_prepare_context( - struct bContext *C, struct wmOperator *op) ATTR_WARN_UNUSED_RESULT; -void ED_operator_repeat_reset_context( - struct bContext *C, const OperatorRepeatContextHandle *context_info); - bool ED_undo_is_valid(const struct bContext *C, const char *undoname); struct UndoStack *ED_undo_stack_get(void); diff --git a/source/blender/editors/include/ED_view3d.h b/source/blender/editors/include/ED_view3d.h index 24e5b3e2662..343bffa0082 100644 --- a/source/blender/editors/include/ED_view3d.h +++ b/source/blender/editors/include/ED_view3d.h @@ -351,12 +351,19 @@ typedef enum { VIEW3D_SELECT_PICK_NEAREST = 2, } eV3DSelectMode; +typedef enum { + /* Don't exclude anything. */ + VIEW3D_SELECT_FILTER_NOP = 0, + /* Don't select objects outside the current mode. */ + VIEW3D_SELECT_FILTER_OBJECT_MODE_LOCK = 1, +} eV3DSelectObjectFilter; + void view3d_opengl_select_cache_begin(void); void view3d_opengl_select_cache_end(void); int view3d_opengl_select( struct ViewContext *vc, unsigned int *buffer, unsigned int bufsize, const struct rcti *input, - eV3DSelectMode select_mode); + eV3DSelectMode select_mode, eV3DSelectObjectFilter select_filter); /* view3d_select.c */ float ED_view3d_select_dist_px(void); diff --git a/source/blender/editors/include/UI_icons.h b/source/blender/editors/include/UI_icons.h index 3bc1255d23f..03c99bb7f0d 100644 --- a/source/blender/editors/include/UI_icons.h +++ b/source/blender/editors/include/UI_icons.h @@ -113,9 +113,7 @@ DEF_ICON(FILE_TICK) DEF_ICON(QUIT) DEF_ICON(URL) DEF_ICON(RECOVER_LAST) -#ifndef DEF_ICON_BLANK_SKIP - DEF_ICON(BLANK038) -#endif +DEF_ICON(PRESET) DEF_ICON(FULLSCREEN_ENTER) DEF_ICON(FULLSCREEN_EXIT) DEF_ICON(BLANK1) // Not actually blank - this is used all over the place @@ -294,8 +292,10 @@ DEF_ICON(RNA_ADD) DEF_ICON(BLANK112) DEF_ICON(BLANK113) DEF_ICON(BLANK114) - DEF_ICON(BLANK115) - DEF_ICON(BLANK116) +#endif +DEF_ICON(RESTRICT_VIEW_OFF) +DEF_ICON(RESTRICT_VIEW_ON) +#ifndef DEF_ICON_BLANK_SKIP DEF_ICON(BLANK116b) #endif @@ -321,8 +321,8 @@ DEF_ICON(OUTLINER_OB_LIGHTPROBE) #endif DEF_ICON(RESTRICT_COLOR_OFF) DEF_ICON(RESTRICT_COLOR_ON) -DEF_ICON(RESTRICT_VIEW_OFF) -DEF_ICON(RESTRICT_VIEW_ON) +DEF_ICON(HIDE_OFF) +DEF_ICON(HIDE_ON) DEF_ICON(RESTRICT_SELECT_OFF) DEF_ICON(RESTRICT_SELECT_ON) DEF_ICON(RESTRICT_RENDER_OFF) diff --git a/source/blender/editors/include/UI_interface.h b/source/blender/editors/include/UI_interface.h index c82a320268f..0b4817c8049 100644 --- a/source/blender/editors/include/UI_interface.h +++ b/source/blender/editors/include/UI_interface.h @@ -830,6 +830,7 @@ struct Panel *UI_panel_begin(struct ScrArea *sa, struct ARegion *ar, struct List void UI_panel_end(uiBlock *block, int width, int height); void UI_panels_scale(struct ARegion *ar, float new_width); void UI_panel_label_offset(struct uiBlock *block, int *x, int *y); +int UI_panel_size_y(const struct Panel *pa); bool UI_panel_category_is_visible(struct ARegion *ar); void UI_panel_category_add(struct ARegion *ar, const char *name); @@ -905,7 +906,7 @@ void UI_exit(void); #define UI_ITEM_O_DEPRESS (1 << 9) #define UI_ITEM_R_COMPACT (1 << 10) -#define UI_HEADER_OFFSET_START ((void)0, 0.4f * UI_UNIT_X) +#define UI_HEADER_OFFSET ((void)0, 0.2f * UI_UNIT_X) /* uiLayoutOperatorButs flags */ enum { @@ -963,6 +964,7 @@ void uiLayoutSetScaleX(uiLayout *layout, float scale); void uiLayoutSetScaleY(uiLayout *layout, float scale); void uiLayoutSetEmboss(uiLayout *layout, char emboss); void uiLayoutSetPropSep(uiLayout *layout, bool is_sep); +void uiLayoutSetPropDecorate(uiLayout *layout, bool is_sep); int uiLayoutGetOperatorContext(uiLayout *layout); bool uiLayoutGetActive(uiLayout *layout); @@ -975,6 +977,7 @@ float uiLayoutGetScaleX(uiLayout *layout); float uiLayoutGetScaleY(uiLayout *layout); int uiLayoutGetEmboss(uiLayout *layout); bool uiLayoutGetPropSep(uiLayout *layout); +bool uiLayoutGetPropDecorate(uiLayout *layout); /* layout specifiers */ uiLayout *uiLayoutRow(uiLayout *layout, int align); @@ -1030,6 +1033,7 @@ uiLayout *uiTemplateConstraint(uiLayout *layout, struct PointerRNA *ptr); void uiTemplatePreview(uiLayout *layout, struct bContext *C, struct ID *id, int show_buttons, struct ID *parent, struct MTex *slot, const char *preview_id); void uiTemplateColorRamp(uiLayout *layout, struct PointerRNA *ptr, const char *propname, int expand); +void uiTemplateIcon(uiLayout *layout, int icon_value, float icon_scale); void uiTemplateIconView(uiLayout *layout, struct PointerRNA *ptr, const char *propname, int show_labels, float icon_scale); void uiTemplateHistogram(uiLayout *layout, struct PointerRNA *ptr, const char *propname); void uiTemplateWaveform(uiLayout *layout, struct PointerRNA *ptr, const char *propname); @@ -1255,5 +1259,7 @@ void UI_widgetbase_draw_cache_end(void); #define USE_UI_POPOVER_ONCE bool UI_but_is_tool(const uiBut *but); +#define UI_but_is_decorator(but) \ + ((but)->func == ui_but_anim_decorate_cb) #endif /* __UI_INTERFACE_H__ */ diff --git a/source/blender/editors/interface/CMakeLists.txt b/source/blender/editors/interface/CMakeLists.txt index 49fe6bfb2dc..07ba3b90e11 100644 --- a/source/blender/editors/interface/CMakeLists.txt +++ b/source/blender/editors/interface/CMakeLists.txt @@ -58,6 +58,7 @@ set(SRC interface_panel.c interface_regions.c interface_region_color_picker.c + interface_region_hud.c interface_region_menu_pie.c interface_region_menu_popup.c interface_region_popover.c diff --git a/source/blender/editors/interface/interface.c b/source/blender/editors/interface/interface.c index 811bd4457d8..8c37054098b 100644 --- a/source/blender/editors/interface/interface.c +++ b/source/blender/editors/interface/interface.c @@ -243,19 +243,44 @@ static void ui_update_flexible_spacing(const ARegion *region, uiBlock *block) rcti rect; ui_but_to_pixelrect(&rect, region, block, block->buttons.last); - const float buttons_width = (float)rect.xmax + UI_HEADER_OFFSET_START; + const float buttons_width = (float)rect.xmax + UI_HEADER_OFFSET; const float region_width = (float)region->sizex * U.dpi_fac; if (region_width <= buttons_width) { return; } - const float spacing = ((region_width - buttons_width) / (float)sepr_flex_len); - float offset = 0; + /* We could get rid of this loop if we agree on a max number of spacer */ + int *spacers_pos = alloca(sizeof(*spacers_pos) * (size_t)sepr_flex_len); + int i = 0; + for (uiBut *but = block->buttons.first; but; but = but->next) { + if (but->type == UI_BTYPE_SEPR_SPACER) { + ui_but_to_pixelrect(&rect, region, block, but); + spacers_pos[i] = rect.xmax + UI_HEADER_OFFSET; + i++; + } + } + + const float segment_width = region_width / (float)sepr_flex_len; + float offset = 0, remaining_space = region_width - buttons_width; + i = 0; for (uiBut *but = block->buttons.first; but; but = but->next) { BLI_rctf_translate(&but->rect, offset, 0); if (but->type == UI_BTYPE_SEPR_SPACER) { - offset += spacing; + /* How much the next block overlap with the current segment */ + int overlap = ( + (i == sepr_flex_len - 1) ? + buttons_width - spacers_pos[i] : + (spacers_pos[i + 1] - spacers_pos[i]) / 2); + int segment_end = segment_width * (i + 1); + int spacer_end = segment_end - overlap; + int spacer_sta = spacers_pos[i] + offset; + if (spacer_end > spacer_sta) { + float step = min_ff(remaining_space, spacer_end - spacer_sta); + remaining_space -= step; + offset += step; + } + i++; } } ui_block_bounds_calc(block); @@ -1247,6 +1272,9 @@ void UI_block_end_ex(const bContext *C, uiBlock *block, const int xy[2], int r_x ui_but_anim_flag(but, (scene) ? scene->r.cfra : 0.0f); ui_but_override_flag(but); + if (UI_but_is_decorator(but)) { + ui_but_anim_decorate_update_from_flag(but); + } } diff --git a/source/blender/editors/interface/interface_anim.c b/source/blender/editors/interface/interface_anim.c index fc0ad7e5dce..cda70d405ad 100644 --- a/source/blender/editors/interface/interface_anim.c +++ b/source/blender/editors/interface/interface_anim.c @@ -103,6 +103,30 @@ void ui_but_anim_flag(uiBut *but, float cfra) } } +void ui_but_anim_decorate_update_from_flag(uiBut *but) +{ + BLI_assert(UI_but_is_decorator(but) && but->prev); + int flag = but->prev->flag; + if (flag & UI_BUT_DRIVEN) { + but->icon = ICON_AUTO; + } + else if (flag & UI_BUT_ANIMATED_KEY) { + but->icon = ICON_SPACE2; + } + else if (flag & UI_BUT_ANIMATED) { + but->icon = ICON_SPACE3; + } + else if (flag & UI_BUT_OVERRIDEN) { + but->icon = ICON_LIBRARY_DATA_OVERRIDE; + } + else { + but->icon = ICON_DOT; + } + + const int flag_copy = (UI_BUT_DISABLED | UI_BUT_INACTIVE); + but->flag = (but->flag & ~flag_copy) | (flag & flag_copy); +} + /** * \a str can be NULL to only perform check if \a but has an expression at all. * \return if button has an expression. @@ -299,3 +323,38 @@ void ui_but_anim_paste_driver(bContext *C) /* this operator calls UI_context_active_but_prop_get */ WM_operator_name_call(C, "ANIM_OT_paste_driver_button", WM_OP_INVOKE_DEFAULT, NULL); } + +void ui_but_anim_decorate_cb(bContext *C, void *arg_but, void *UNUSED(arg_dummy)) +{ + wmWindowManager *wm = CTX_wm_manager(C); + uiBut *but = arg_but; + but = but->prev; + + /* FIXME(campbell), swapping active pointer is weak. */ + SWAP(struct uiHandleButtonData *, but->active, but->next->active); + wm->op_undo_depth++; + + if (but->flag & UI_BUT_DRIVEN) { + /* pass */ + /* TODO: report? */ + } + else if (but->flag & UI_BUT_ANIMATED_KEY) { + PointerRNA props_ptr; + wmOperatorType *ot = WM_operatortype_find("ANIM_OT_keyframe_delete_button", false); + WM_operator_properties_create_ptr(&props_ptr, ot); + RNA_boolean_set(&props_ptr, "all", but->rnaindex == -1); + WM_operator_name_call_ptr(C, ot, WM_OP_INVOKE_DEFAULT, &props_ptr); + WM_operator_properties_free(&props_ptr); + } + else { + PointerRNA props_ptr; + wmOperatorType *ot = WM_operatortype_find("ANIM_OT_keyframe_insert_button", false); + WM_operator_properties_create_ptr(&props_ptr, ot); + RNA_boolean_set(&props_ptr, "all", but->rnaindex == -1); + WM_operator_name_call_ptr(C, ot, WM_OP_INVOKE_DEFAULT, &props_ptr); + WM_operator_properties_free(&props_ptr); + } + + SWAP(struct uiHandleButtonData *, but->active, but->next->active); + wm->op_undo_depth--; +} diff --git a/source/blender/editors/interface/interface_handlers.c b/source/blender/editors/interface/interface_handlers.c index 02844f5e861..63bf29a26ea 100644 --- a/source/blender/editors/interface/interface_handlers.c +++ b/source/blender/editors/interface/interface_handlers.c @@ -58,6 +58,7 @@ #include "PIL_time.h" +#include "BKE_addon.h" #include "BKE_colorband.h" #include "BKE_blender_undo.h" #include "BKE_brush.h" @@ -1267,6 +1268,34 @@ static void ui_multibut_states_apply(bContext *C, uiHandleButtonData *data, uiBl #ifdef USE_DRAG_TOGGLE +/* Helpers that wrap boolean functions, to support different kinds of buttons. */ + +static bool ui_drag_toggle_but_is_supported(const uiBut *but) +{ + if (ui_but_is_bool(but)) { + return true; + } + else if (UI_but_is_decorator(but)) { + return ELEM(but->icon, ICON_SPACE2, ICON_SPACE3, ICON_DOT, ICON_LIBRARY_DATA_OVERRIDE); + } + else { + return false; + } +} + +static bool ui_drag_toggle_but_is_pushed(uiBut *but) +{ + if (ui_but_is_bool(but)) { + return ui_but_is_pushed(but); + } + else if (UI_but_is_decorator(but)) { + return (but->icon == ICON_SPACE2); + } + else { + return false; + } +} + typedef struct uiDragToggleHandle { /* init */ bool is_init; @@ -1304,10 +1333,9 @@ static bool ui_drag_toggle_set_xy_xy( if (BLI_rctf_isect_segment(&but->rect, xy_a_block, xy_b_block)) { /* execute the button */ - if (ui_but_is_bool(but) && but->type == but_type_start) { + if (ui_drag_toggle_but_is_supported(but) && but->type == but_type_start) { /* is it pressed? */ - bool is_set_but = ui_but_is_pushed(but); - BLI_assert(ui_but_is_bool(but) == true); + bool is_set_but = ui_drag_toggle_but_is_pushed(but); if (is_set_but != is_set) { UI_but_execute(C, but); if (do_check) { @@ -1437,7 +1465,7 @@ static int ui_handler_region_drag_toggle(bContext *C, const wmEvent *event, void static bool ui_but_is_drag_toggle(const uiBut *but) { - return ((ui_but_is_bool(but) == true) && + return ((ui_drag_toggle_but_is_supported(but) == true) && /* menu check is importnt so the button dragged over isn't removed instantly */ (ui_block_is_menu(but->block) == false)); } @@ -1745,7 +1773,7 @@ static bool ui_but_drag_init( button_activate_state(C, but, BUTTON_STATE_EXIT); data->cancel = true; #ifdef USE_DRAG_TOGGLE - if (ui_but_is_bool(but)) { + if (ui_drag_toggle_but_is_supported(but)) { uiDragToggleHandle *drag_info = MEM_callocN(sizeof(*drag_info), __func__); ARegion *ar_prev; @@ -1753,7 +1781,7 @@ static bool ui_but_drag_init( * typically 'button_activate_exit()' handles this */ ui_apply_but_autokey(C, but); - drag_info->is_set = ui_but_is_pushed(but); + drag_info->is_set = ui_drag_toggle_but_is_pushed(but); drag_info->but_cent_start[0] = BLI_rctf_cent_x(&but->rect); drag_info->but_cent_start[1] = BLI_rctf_cent_y(&but->rect); drag_info->but_type_start = but->type; @@ -3585,10 +3613,50 @@ static uiBut *ui_but_list_row_text_activate( /* ***************** events for different button types *************** */ +#ifdef USE_DRAG_TOGGLE +/* Shared by any button that supports drag-toggle. */ +static bool ui_do_but_ANY_drag_toggle( + bContext *C, uiBut *but, + uiHandleButtonData *data, const wmEvent *event, + int *r_retval) +{ + if (data->state == BUTTON_STATE_HIGHLIGHT) { + if (event->type == LEFTMOUSE && event->val == KM_PRESS && ui_but_is_drag_toggle(but)) { +#if 0 /* UNUSED */ + data->togdual = event->ctrl; + data->togonly = !event->shift; +#endif + ui_apply_but(C, but->block, but, data, true); + button_activate_state(C, but, BUTTON_STATE_WAIT_DRAG); + data->dragstartx = event->x; + data->dragstarty = event->y; + *r_retval = WM_UI_HANDLER_BREAK; + return true; + } + } + else if (data->state == BUTTON_STATE_WAIT_DRAG) { + /* note: the 'BUTTON_STATE_WAIT_DRAG' part of 'ui_do_but_EXIT' could be refactored into its own function */ + data->applied = false; + *r_retval = ui_do_but_EXIT(C, but, data, event); + return true; + } + return false; +} +#endif /* USE_DRAG_TOGGLE */ + static int ui_do_but_BUT( bContext *C, uiBut *but, uiHandleButtonData *data, const wmEvent *event) { +#ifdef USE_DRAG_TOGGLE + { + int retval; + if (ui_do_but_ANY_drag_toggle(C, but, data, event, &retval)) { + return retval; + } + } +#endif + if (data->state == BUTTON_STATE_HIGHLIGHT) { if (event->type == LEFTMOUSE && event->val == KM_PRESS) { button_activate_state(C, but, BUTTON_STATE_WAIT_RELEASE); @@ -3836,25 +3904,14 @@ static int ui_do_but_TOG( uiHandleButtonData *data, const wmEvent *event) { #ifdef USE_DRAG_TOGGLE - if (data->state == BUTTON_STATE_HIGHLIGHT) { - if (event->type == LEFTMOUSE && event->val == KM_PRESS && ui_but_is_drag_toggle(but)) { -#if 0 /* UNUSED */ - data->togdual = event->ctrl; - data->togonly = !event->shift; -#endif - ui_apply_but(C, but->block, but, data, true); - button_activate_state(C, but, BUTTON_STATE_WAIT_DRAG); - data->dragstartx = event->x; - data->dragstarty = event->y; - return WM_UI_HANDLER_BREAK; + { + int retval; + if (ui_do_but_ANY_drag_toggle(C, but, data, event, &retval)) { + return retval; } } - else if (data->state == BUTTON_STATE_WAIT_DRAG) { - /* note: the 'BUTTON_STATE_WAIT_DRAG' part of 'ui_do_but_EXIT' could be refactored into its own function */ - data->applied = false; - return ui_do_but_EXIT(C, but, data, event); - } #endif + if (data->state == BUTTON_STATE_HIGHLIGHT) { if (ELEM(event->type, LEFTMOUSE, PADENTER, RETKEY) && event->val == KM_PRESS) { #if 0 /* UNUSED */ @@ -4277,10 +4334,14 @@ static int ui_do_but_NUM( retval = WM_UI_HANDLER_BREAK; /* allow accumulating values, otherwise scrolling gets preference */ else if (type == WHEELDOWNMOUSE && event->ctrl) { mx = but->rect.xmin; + but->drawflag &= ~UI_BUT_ACTIVE_RIGHT; + but->drawflag |= UI_BUT_ACTIVE_LEFT; click = 1; } else if (type == WHEELUPMOUSE && event->ctrl) { mx = but->rect.xmax; + but->drawflag &= ~UI_BUT_ACTIVE_LEFT; + but->drawflag |= UI_BUT_ACTIVE_RIGHT; click = 1; } else if (event->val == KM_PRESS) { @@ -5086,12 +5147,12 @@ static int ui_do_but_COLOR( rgb_to_hsv_compat_v(col, hsv); if (event->type == WHEELDOWNMOUSE) - hsv[2] = CLAMPIS(hsv[2] - 0.05f, 0.0f, 1.0f); + hsv[2] = clamp_f(hsv[2] - 0.05f, 0.0f, 1.0f); else if (event->type == WHEELUPMOUSE) - hsv[2] = CLAMPIS(hsv[2] + 0.05f, 0.0f, 1.0f); + hsv[2] = clamp_f(hsv[2] + 0.05f, 0.0f, 1.0f); else { float fac = 0.005 * (event->y - event->prevy); - hsv[2] = CLAMPIS(hsv[2] + fac, 0.0f, 1.0f); + hsv[2] = clamp_f(hsv[2] + fac, 0.0f, 1.0f); } hsv_to_rgb_v(hsv, data->vec); @@ -5810,12 +5871,12 @@ static int ui_do_but_HSVCIRCLE( } /* XXX hardcoded keymap check.... */ else if (event->type == WHEELDOWNMOUSE) { - hsv[2] = CLAMPIS(hsv[2] - 0.05f, 0.0f, 1.0f); + hsv[2] = clamp_f(hsv[2] - 0.05f, 0.0f, 1.0f); ui_but_hsv_set(but); /* converts to rgb */ ui_numedit_apply(C, block, but, data); } else if (event->type == WHEELUPMOUSE) { - hsv[2] = CLAMPIS(hsv[2] + 0.05f, 0.0f, 1.0f); + hsv[2] = clamp_f(hsv[2] + 0.05f, 0.0f, 1.0f); ui_but_hsv_set(but); /* converts to rgb */ ui_numedit_apply(C, block, but, data); } @@ -7010,7 +7071,10 @@ static bool ui_but_menu(bContext *C, uiBut *but) if (ui_block_is_menu(but->block) == false) { uiItemFullO(layout, "UI_OT_editsource", NULL, ICON_NONE, NULL, WM_OP_INVOKE_DEFAULT, 0, NULL); } - uiItemFullO(layout, "UI_OT_edittranslation_init", NULL, ICON_NONE, NULL, WM_OP_INVOKE_DEFAULT, 0, NULL); + + if (BKE_addon_find(&U.addons, "ui_translate")) { + uiItemFullO(layout, "UI_OT_edittranslation_init", NULL, ICON_NONE, NULL, WM_OP_INVOKE_DEFAULT, 0, NULL); + } mt = WM_menutype_find("WM_MT_button_context", true); if (mt) { @@ -8167,6 +8231,10 @@ void UI_context_update_anim_flag(const bContext *C) for (but = block->buttons.first; but; but = but->next) { ui_but_anim_flag(but, (scene) ? scene->r.cfra : 0.0f); ui_but_override_flag(but); + if (UI_but_is_decorator(but)) { + ui_but_anim_decorate_update_from_flag(but); + } + ED_region_tag_redraw(ar); if (but->active) { @@ -9136,7 +9204,7 @@ static int ui_handle_menu_event( add_v2_v2v2_int(menu->popup_create_vars.event_xy, menu->popup_create_vars.event_xy, mdiff); - ui_popup_translate(C, ar, mdiff); + ui_popup_translate(ar, mdiff); } return retval; diff --git a/source/blender/editors/interface/interface_icons.c b/source/blender/editors/interface/interface_icons.c index c2ada1e3733..64fca05c082 100644 --- a/source/blender/editors/interface/interface_icons.c +++ b/source/blender/editors/interface/interface_icons.c @@ -77,6 +77,9 @@ #include "UI_interface.h" #include "UI_interface_icons.h" +#include "WM_api.h" +#include "WM_types.h" + #include "interface_intern.h" #ifndef WITH_HEADLESS @@ -451,49 +454,6 @@ static void icon_verify_datatoc(IconImage *iimg) } } -static void init_matcap_icons(void) -{ - /* dynamic allocation now, tucking datatoc pointers in DrawInfo */ -#define INIT_MATCAP_ICON(icon_id, name) \ - { \ - unsigned char *rect = (unsigned char *)datatoc_ ##name## _jpg; \ - int size = datatoc_ ##name## _jpg_size; \ - DrawInfo *di; \ - \ - di = def_internal_icon(NULL, icon_id, 0, 0, 96, ICON_TYPE_BUFFER); \ - di->data.buffer.image->datatoc_rect = rect; \ - di->data.buffer.image->datatoc_size = size; \ - } (void)0 - - INIT_MATCAP_ICON(ICON_MATCAP_01, mc01); - INIT_MATCAP_ICON(ICON_MATCAP_02, mc02); - INIT_MATCAP_ICON(ICON_MATCAP_03, mc03); - INIT_MATCAP_ICON(ICON_MATCAP_04, mc04); - INIT_MATCAP_ICON(ICON_MATCAP_05, mc05); - INIT_MATCAP_ICON(ICON_MATCAP_06, mc06); - INIT_MATCAP_ICON(ICON_MATCAP_07, mc07); - INIT_MATCAP_ICON(ICON_MATCAP_08, mc08); - INIT_MATCAP_ICON(ICON_MATCAP_09, mc09); - INIT_MATCAP_ICON(ICON_MATCAP_10, mc10); - INIT_MATCAP_ICON(ICON_MATCAP_11, mc11); - INIT_MATCAP_ICON(ICON_MATCAP_12, mc12); - INIT_MATCAP_ICON(ICON_MATCAP_13, mc13); - INIT_MATCAP_ICON(ICON_MATCAP_14, mc14); - INIT_MATCAP_ICON(ICON_MATCAP_15, mc15); - INIT_MATCAP_ICON(ICON_MATCAP_16, mc16); - INIT_MATCAP_ICON(ICON_MATCAP_17, mc17); - INIT_MATCAP_ICON(ICON_MATCAP_18, mc18); - INIT_MATCAP_ICON(ICON_MATCAP_19, mc19); - INIT_MATCAP_ICON(ICON_MATCAP_20, mc20); - INIT_MATCAP_ICON(ICON_MATCAP_21, mc21); - INIT_MATCAP_ICON(ICON_MATCAP_22, mc22); - INIT_MATCAP_ICON(ICON_MATCAP_23, mc23); - INIT_MATCAP_ICON(ICON_MATCAP_24, mc24); - -#undef INIT_MATCAP_ICON - -} - static void init_internal_icons(void) { // bTheme *btheme = UI_GetTheme(); @@ -645,7 +605,7 @@ static void init_iconfile_list(struct ListBase *list) if ((dir[i].type & S_IFREG)) { const char *filename = dir[i].relname; - if (BLI_testextensie(filename, ".png")) { + if (BLI_path_extension_check(filename, ".png")) { /* loading all icons on file start is overkill & slows startup * its possible they change size after blender load anyway. */ #if 0 @@ -777,14 +737,7 @@ static DrawInfo *icon_create_drawinfo(Icon *icon) di->type = ICON_TYPE_GEOM; } else if (icon_data_type == ICON_DATA_STUDIOLIGHT) { - const int STUDIOLIGHT_SIZE = 96; - StudioLight *sl = icon->obj; di->type = ICON_TYPE_BUFFER; - IconImage *img = MEM_mallocN(sizeof(IconImage), __func__); - img->w = STUDIOLIGHT_SIZE; - img->h = STUDIOLIGHT_SIZE; - img->rect = BKE_studiolight_preview(sl, STUDIOLIGHT_SIZE, icon->id_type); - di->data.buffer.image = img; } else { BLI_assert(0); @@ -850,7 +803,6 @@ void UI_icons_init(int first_dyn_id) init_iconfile_list(&iconfilelist); init_internal_icons(); init_brush_icons(); - init_matcap_icons(); #endif } @@ -890,6 +842,41 @@ static void icon_create_rect(struct PreviewImage *prv_img, enum eIconSizes size) static void ui_id_preview_image_render_size( const bContext *C, Scene *scene, ID *id, PreviewImage *pi, int size, const bool use_job); +static void ui_studiolight_icon_job_exec(void *customdata, short *UNUSED(stop), short *UNUSED(do_update), float *UNUSED(progress)) +{ + Icon **tmp = (Icon **)customdata; + Icon *icon = *tmp; + DrawInfo *di = icon_ensure_drawinfo(icon); + StudioLight *sl = icon->obj; + BKE_studiolight_preview(di->data.buffer.image->rect, sl, icon->id_type); +} + +static void ui_studiolight_kill_icon_preview_job(wmWindowManager *wm, int icon_id) +{ + Icon *icon = BKE_icon_get(icon_id); + WM_jobs_kill_type(wm, icon, WM_JOB_TYPE_STUDIOLIGHT); + icon->obj = NULL; +} + +static void ui_studiolight_free_function(StudioLight * sl, void* data) +{ + wmWindowManager *wm = data; + + // get icons_id, get icons and kill wm jobs + if (sl->icon_id_radiance) { + ui_studiolight_kill_icon_preview_job(wm, sl->icon_id_radiance); + } + if (sl->icon_id_irradiance) { + ui_studiolight_kill_icon_preview_job(wm, sl->icon_id_irradiance); + } + if (sl->icon_id_matcap) { + ui_studiolight_kill_icon_preview_job(wm, sl->icon_id_matcap); + } + if (sl->icon_id_matcap_flipped) { + ui_studiolight_kill_icon_preview_job(wm, sl->icon_id_matcap_flipped); + } +} + void ui_icon_ensure_deferred(const bContext *C, const int icon_id, const bool big) { Icon *icon = BKE_icon_get(icon_id); @@ -916,6 +903,33 @@ void ui_icon_ensure_deferred(const bContext *C, const int icon_id, const bool bi } break; } + case ICON_TYPE_BUFFER: + { + if (icon->obj_type == ICON_DATA_STUDIOLIGHT) { + if (di->data.buffer.image == NULL) { + wmWindowManager *wm = CTX_wm_manager(C); + StudioLight *sl = icon->obj; + BKE_studiolight_set_free_function(sl, &ui_studiolight_free_function, wm); + IconImage *img = MEM_mallocN(sizeof(IconImage), __func__); + + img->w = STUDIOLIGHT_ICON_SIZE; + img->h = STUDIOLIGHT_ICON_SIZE; + size_t size = STUDIOLIGHT_ICON_SIZE * STUDIOLIGHT_ICON_SIZE * sizeof(uint); + img->rect = MEM_mallocN(size, __func__); + memset(img->rect, 0, size); + di->data.buffer.image = img; + + wmJob *wm_job = WM_jobs_get(wm, CTX_wm_window(C), icon, "StudioLight Icon", 0, WM_JOB_TYPE_STUDIOLIGHT); + Icon** tmp = MEM_callocN(sizeof(Icon*), __func__); + *tmp = icon; + WM_jobs_customdata_set(wm_job, tmp, MEM_freeN); + WM_jobs_timer(wm_job, 0.01, 0, NC_WINDOW); + WM_jobs_callbacks(wm_job, ui_studiolight_icon_job_exec, NULL, NULL, NULL); + WM_jobs_start(CTX_wm_manager(C), wm_job); + } + } + break; + } } } } @@ -1479,7 +1493,7 @@ int UI_rnaptr_icon_get(bContext *C, PointerRNA *ptr, int rnaicon, const bool big id = RNA_pointer_get(ptr, "texture").data; } else if (RNA_struct_is_a(ptr->type, &RNA_DynamicPaintSurface)) { - DynamicPaintSurface *surface = (DynamicPaintSurface *)ptr->data; + DynamicPaintSurface *surface = ptr->data; if (surface->format == MOD_DPAINT_SURFACE_F_PTEX) return ICON_TEXTURE_SHADED; @@ -1488,6 +1502,18 @@ int UI_rnaptr_icon_get(bContext *C, PointerRNA *ptr, int rnaicon, const bool big else if (surface->format == MOD_DPAINT_SURFACE_F_IMAGESEQ) return ICON_FILE_IMAGE; } + else if (RNA_struct_is_a(ptr->type, &RNA_StudioLight)) { + StudioLight *sl = ptr->data; + switch (sl->flag & STUDIOLIGHT_FLAG_ORIENTATIONS) { + case STUDIOLIGHT_ORIENTATION_CAMERA: + return sl->icon_id_irradiance; + case STUDIOLIGHT_ORIENTATION_WORLD: + default: + return sl->icon_id_radiance; + case STUDIOLIGHT_ORIENTATION_VIEWNORMAL: + return sl->icon_id_matcap; + } + } /* get icon from ID */ if (id) { diff --git a/source/blender/editors/interface/interface_intern.h b/source/blender/editors/interface/interface_intern.h index b5bf9be737b..6f029b81e92 100644 --- a/source/blender/editors/interface/interface_intern.h +++ b/source/blender/editors/interface/interface_intern.h @@ -652,7 +652,7 @@ void ui_pie_menu_level_create( const EnumPropertyItem *items, int totitem, int context, int flag); /* interface_region_popup.c */ -void ui_popup_translate(struct bContext *C, struct ARegion *ar, const int mdiff[2]); +void ui_popup_translate(struct ARegion *ar, const int mdiff[2]); void ui_popup_block_free(struct bContext *C, uiPopupBlockHandle *handle); void ui_popup_block_scrolltest(struct uiBlock *block); @@ -757,8 +757,13 @@ void ui_draw_menu_back(struct uiStyle *style, uiBlock *block, rcti *rect); void ui_draw_popover_back(ARegion *ar, struct uiStyle *style, uiBlock *block, rcti *rect); void ui_draw_pie_center(uiBlock *block); uiWidgetColors *ui_tooltip_get_theme(void); + +void ui_draw_widget_back_color( + uiWidgetTypeEnum type, bool use_shadow, const rcti *rect, + const float color[4]); +void ui_draw_widget_back( + uiWidgetTypeEnum type, bool use_shadow, const rcti *rect); void ui_draw_tooltip_background(uiStyle *UNUSED(style), uiBlock *block, rcti *rect); -void ui_draw_search_back(struct uiStyle *style, uiBlock *block, rcti *rect); extern void ui_draw_but(const struct bContext *C, ARegion *ar, struct uiStyle *style, uiBut *but, rcti *rect); /* theme color init */ @@ -810,6 +815,9 @@ bool ui_but_anim_expression_set(uiBut *but, const char *str); bool ui_but_anim_expression_create(uiBut *but, const char *str); void ui_but_anim_autokey(struct bContext *C, uiBut *but, struct Scene *scene, float cfra); +void ui_but_anim_decorate_cb(struct bContext *C, void *arg_but, void *arg_dummy); +void ui_but_anim_decorate_update_from_flag(uiBut *but); + /* interface_eyedropper.c */ struct wmKeyMap *eyedropper_modal_keymap(struct wmKeyConfig *keyconf); struct wmKeyMap *eyedropper_colorband_modal_keymap(struct wmKeyConfig *keyconf); diff --git a/source/blender/editors/interface/interface_layout.c b/source/blender/editors/interface/interface_layout.c index 9888c6d65cc..3784ab635be 100644 --- a/source/blender/editors/interface/interface_layout.c +++ b/source/blender/editors/interface/interface_layout.c @@ -50,6 +50,7 @@ #include "BKE_global.h" #include "BKE_idprop.h" #include "BKE_screen.h" +#include "BKE_animsys.h" #include "RNA_access.h" @@ -63,6 +64,10 @@ #include "interface_intern.h" +/* Show an icon button after each RNA button to use to quickly set keyframes, + * this is a way to display animation/driven/override status, see T54951. */ +#define UI_PROP_DECORATE + /************************ Structs and Defines *************************/ #define UI_OPERATOR_ERROR_RET(_ot, _opname, return_statement) \ @@ -132,6 +137,9 @@ enum { UI_ITEM_BOX_ITEM = 1 << 2, /* The item is "inside" a box item */ UI_ITEM_PROP_SEP = 1 << 3, + /* Show an icon button next to each property (to set keyframes, show status). + * Enabled by default, depends on 'UI_ITEM_PROP_SEP'. */ + UI_ITEM_PROP_DECORATE = 1 << 4, }; typedef struct uiButtonItem { @@ -1477,6 +1485,19 @@ void uiItemFullR(uiLayout *layout, PointerRNA *ptr, PropertyRNA *prop, int index bool is_array; const bool use_prop_sep = ((layout->item.flag & UI_ITEM_PROP_SEP) != 0); +#ifdef UI_PROP_DECORATE + struct { + bool use_prop_decorate; + int len; + uiLayout *layout; + uiBut *but; + } ui_decorate = { + .use_prop_decorate = ( + ((layout->item.flag & UI_ITEM_PROP_DECORATE) != 0) && + (use_prop_sep && ptr->id.data && id_can_have_animdata(ptr->id.data))), + }; +#endif /* UI_PROP_DECORATE */ + UI_block_layout_set_current(block, layout); /* retrieve info */ @@ -1558,14 +1579,25 @@ void uiItemFullR(uiLayout *layout, PointerRNA *ptr, PropertyRNA *prop, int index /* Split the label / property. */ if (use_prop_sep) { + uiLayout *layout_row = NULL; +#ifdef UI_PROP_DECORATE + if (ui_decorate.use_prop_decorate) { + layout_row = uiLayoutRow(layout, true); + layout_row->space = 0; + ui_decorate.len = max_ii(1, len); + } +#endif /* UI_PROP_DECORATE */ + if (name[0] == '\0') { /* Ensure we get a column when text is not set. */ - layout = uiLayoutColumn(layout, true); + layout = uiLayoutColumn(layout_row ? layout_row : layout, true); layout->space = 0; } else { const PropertySubType subtype = RNA_property_subtype(prop); - uiLayout *layout_split = uiLayoutSplit(layout, UI_ITEM_PROP_SEP_DIVIDE, true); + uiLayout *layout_split = uiLayoutSplit( + layout_row ? layout_row : layout, + UI_ITEM_PROP_SEP_DIVIDE, true); layout_split->space = 0; uiLayout *layout_sub = uiLayoutColumn(layout_split, true); layout_sub->space = 0; @@ -1605,8 +1637,22 @@ void uiItemFullR(uiLayout *layout, PointerRNA *ptr, PropertyRNA *prop, int index /* Watch out! We can only write into the new column now. */ layout = uiLayoutColumn(layout_split, true); layout->space = 0; - name = ""; + if ((type == PROP_ENUM) && (flag & UI_ITEM_R_EXPAND)) { + /* pass (expanded enums each have their own name) */ + } + else { + name = ""; + } } + +#ifdef UI_PROP_DECORATE + if (ui_decorate.use_prop_decorate) { + ui_decorate.layout = uiLayoutColumn(layout_row, true); + ui_decorate.layout->space = 0; + UI_block_layout_set_current(block, layout); + ui_decorate.but = block->buttons.last; + } +#endif /* UI_PROP_DECORATE */ } /* End split. */ @@ -1655,6 +1701,40 @@ void uiItemFullR(uiLayout *layout, PointerRNA *ptr, PropertyRNA *prop, int index UI_but_flag_enable(but, UI_BUT_LIST_ITEM); } +#ifdef UI_PROP_DECORATE + if (ui_decorate.use_prop_decorate) { + const bool is_anim = RNA_property_animateable(ptr, prop); + uiBut *but_decorate = ui_decorate.but ? ui_decorate.but->next : block->buttons.first; + uiLayout *layout_col = uiLayoutColumn(ui_decorate.layout, false); + layout_col->space = 0; + layout_col->emboss = UI_EMBOSS_NONE; + int i; + for (i = 0; i < ui_decorate.len && but_decorate; i++) { + /* The icons are set in 'ui_but_anim_flag' */ + if (is_anim) { + but = uiDefIconBut( + block, UI_BTYPE_BUT, 0, ICON_DOT, 0, 0, UI_UNIT_X, UI_UNIT_Y, + NULL, 0.0, 0.0, 0.0, 0.0, TIP_("Animate property")); + UI_but_func_set(but, ui_but_anim_decorate_cb, but, NULL); + but->flag |= UI_BUT_UNDO | UI_BUT_DRAG_LOCK; + } + else { + /* We may show other information here in future, for now use empty space. */ + but = uiDefIconBut( + block, UI_BTYPE_BUT, 0, ICON_BLANK1, 0, 0, UI_UNIT_X, UI_UNIT_Y, + NULL, 0.0, 0.0, 0.0, 0.0, ""); + but->flag |= UI_BUT_DISABLED; + } + /* Order the decorator after the button we decorate, this is used so we can always + * do a quick lookup. */ + BLI_remlink(&block->buttons, but); + BLI_insertlinkafter(&block->buttons, but_decorate, but); + but_decorate = but->next; + } + BLI_assert(ELEM(i, 1, ui_decorate.len)); + } +#endif /* UI_PROP_DECORATE */ + if (no_bg) { layout->emboss = prev_emboss; } @@ -1811,7 +1891,8 @@ static void search_id_collection(StructRNA *ptype, PointerRNA *ptr, PropertyRNA StructRNA *srna; /* look for collection property in Main */ - RNA_main_pointer_create(G.main, ptr); + /* Note: using global Main is OK-ish here, UI shall not access other Mains anyay... */ + RNA_main_pointer_create(G_MAIN, ptr); *prop = NULL; @@ -1985,12 +2066,15 @@ static uiBut *ui_item_menu( h = UI_UNIT_Y; if (layout->root->type == UI_LAYOUT_HEADER) { /* ugly .. */ - if (force_menu) { - w += UI_UNIT_Y; + if (icon == ICON_NONE && force_menu) { + /* pass */ + } + else if (force_menu) { + w += UI_UNIT_X; } else { if (name[0]) { - w -= UI_UNIT_Y / 2; + w -= UI_UNIT_X / 2; } } } @@ -3014,10 +3098,16 @@ static void ui_litem_grid_flow_compute( const float wfac = (float)(parameters->litem_w - (parameters->tot_columns - 1) * parameters->space_x) / tot_w; for (int col = 0; col < parameters->tot_columns; col++) { - results->cos_x_array[col] = col ? results->cos_x_array[col - 1] + results->widths_array[col - 1] + parameters->space_x : parameters->litem_x; + results->cos_x_array[col] = ( + col ? + results->cos_x_array[col - 1] + results->widths_array[col - 1] + parameters->space_x : + parameters->litem_x + ); if (parameters->even_columns) { - /* (< remaining width > - < space between remaining columns >) / < remaining columns > */ - results->widths_array[col] = ((parameters->litem_w - (results->cos_x_array[col] - parameters->litem_x)) - (parameters->tot_columns - col - 1) * parameters->space_x) / (parameters->tot_columns - col); + /* (< remaining width > - < space between remaining columns >) / < remaining columns > */ + results->widths_array[col] = ( + ((parameters->litem_w - (results->cos_x_array[col] - parameters->litem_x)) - + (parameters->tot_columns - col - 1) * parameters->space_x) / (parameters->tot_columns - col)); } else if (col == parameters->tot_columns - 1) { /* Last column copes width rounding errors... */ @@ -3036,7 +3126,10 @@ static void ui_litem_grid_flow_compute( else { results->heights_array[row] = max_h[row]; } - results->cos_y_array[row] = row ? results->cos_y_array[row - 1] - parameters->space_y - results->heights_array[row] : parameters->litem_y - results->heights_array[row]; + results->cos_y_array[row] = ( + row ? + results->cos_y_array[row - 1] - parameters->space_y - results->heights_array[row] : + parameters->litem_y - results->heights_array[row]); } } @@ -3068,22 +3161,22 @@ static void ui_litem_estimate_grid_flow(uiLayout *litem) int max_h; ui_litem_grid_flow_compute( - &litem->items, - &((UILayoutGridFlowInput) { - .row_major = gflow->row_major, - .even_columns = gflow->even_columns, - .even_rows = gflow->even_rows, - .litem_w = litem->w, - .litem_x = litem->x, - .litem_y = litem->y, - .space_x = space_x, - .space_y = space_y, - }), - &((UILayoutGridFlowOutput) { - .tot_items = &gflow->tot_items, - .global_avg_w = &avg_w, - .global_max_h = &max_h, - })); + &litem->items, + &((UILayoutGridFlowInput) { + .row_major = gflow->row_major, + .even_columns = gflow->even_columns, + .even_rows = gflow->even_rows, + .litem_w = litem->w, + .litem_x = litem->x, + .litem_y = litem->y, + .space_x = space_x, + .space_y = space_y, + }), + &((UILayoutGridFlowOutput) { + .tot_items = &gflow->tot_items, + .global_avg_w = &avg_w, + .global_max_h = &max_h, + })); if (gflow->tot_items == 0) { litem->w = litem->h = 0; @@ -3153,23 +3246,23 @@ static void ui_litem_estimate_grid_flow(uiLayout *litem) int tot_w, tot_h; ui_litem_grid_flow_compute( - &litem->items, - &((UILayoutGridFlowInput) { - .row_major = gflow->row_major, - .even_columns = gflow->even_columns, - .even_rows = gflow->even_rows, - .litem_w = litem->w, - .litem_x = litem->x, - .litem_y = litem->y, - .space_x = space_x, - .space_y = space_y, - .tot_columns = gflow->tot_columns, - .tot_rows = gflow->tot_rows, - }), - &((UILayoutGridFlowOutput) { - .tot_w = &tot_w, - .tot_h = &tot_h, - })); + &litem->items, + &((UILayoutGridFlowInput) { + .row_major = gflow->row_major, + .even_columns = gflow->even_columns, + .even_rows = gflow->even_rows, + .litem_w = litem->w, + .litem_x = litem->x, + .litem_y = litem->y, + .space_x = space_x, + .space_y = space_y, + .tot_columns = gflow->tot_columns, + .tot_rows = gflow->tot_rows, + }), + &((UILayoutGridFlowOutput) { + .tot_w = &tot_w, + .tot_h = &tot_h, + })); litem->w = tot_w; litem->h = tot_h; @@ -3201,25 +3294,25 @@ static void ui_litem_layout_grid_flow(uiLayout *litem) /* This time we directly compute coordinates and sizes of all cells. */ ui_litem_grid_flow_compute( - &litem->items, - &((UILayoutGridFlowInput) { - .row_major = gflow->row_major, - .even_columns = gflow->even_columns, - .even_rows = gflow->even_rows, - .litem_w = litem->w, - .litem_x = litem->x, - .litem_y = litem->y, - .space_x = space_x, - .space_y = space_y, - .tot_columns = gflow->tot_columns, - .tot_rows = gflow->tot_rows, - }), - &((UILayoutGridFlowOutput) { - .cos_x_array = cos_x, - .cos_y_array = cos_y, - .widths_array = widths, - .heights_array = heights, - })); + &litem->items, + &((UILayoutGridFlowInput) { + .row_major = gflow->row_major, + .even_columns = gflow->even_columns, + .even_rows = gflow->even_rows, + .litem_w = litem->w, + .litem_x = litem->x, + .litem_y = litem->y, + .space_x = space_x, + .space_y = space_y, + .tot_columns = gflow->tot_columns, + .tot_rows = gflow->tot_rows, + }), + &((UILayoutGridFlowOutput) { + .cos_x_array = cos_x, + .cos_y_array = cos_y, + .widths_array = widths, + .heights_array = heights, + })); for (item = litem->items.first, i = 0; item; item = item->next, i++) { const int col = gflow->row_major ? i % gflow->tot_columns : i / gflow->tot_rows; @@ -3422,7 +3515,7 @@ static void ui_litem_init_from_parent(uiLayout *litem, uiLayout *layout, int ali litem->redalert = layout->redalert; litem->w = layout->w; litem->emboss = layout->emboss; - litem->item.flag = (layout->item.flag & UI_ITEM_PROP_SEP); + litem->item.flag = (layout->item.flag & (UI_ITEM_PROP_SEP | UI_ITEM_PROP_DECORATE)); BLI_addtail(&layout->items, litem); } @@ -3687,6 +3780,16 @@ void uiLayoutSetPropSep(uiLayout *layout, bool is_sep) SET_FLAG_FROM_TEST(layout->item.flag, is_sep, UI_ITEM_PROP_SEP); } +bool uiLayoutGetPropDecorate(uiLayout *layout) +{ + return (layout->item.flag & UI_ITEM_PROP_DECORATE) != 0; +} + +void uiLayoutSetPropDecorate(uiLayout *layout, bool is_sep) +{ + SET_FLAG_FROM_TEST(layout->item.flag, is_sep, UI_ITEM_PROP_DECORATE); +} + bool uiLayoutGetActive(uiLayout *layout) { return layout->active; @@ -3989,6 +4092,9 @@ uiLayout *UI_block_layout(uiBlock *block, int dir, int type, int x, int y, int s layout = MEM_callocN(sizeof(uiLayout), "uiLayout"); layout->item.type = ITEM_LAYOUT_ROOT; + /* Only used when 'UI_ITEM_PROP_SEP' is set. */ + layout->item.flag = UI_ITEM_PROP_DECORATE; + layout->x = x; layout->y = y; layout->root = root; diff --git a/source/blender/editors/interface/interface_ops.c b/source/blender/editors/interface/interface_ops.c index 6fcede58737..aad48d13277 100644 --- a/source/blender/editors/interface/interface_ops.c +++ b/source/blender/editors/interface/interface_ops.c @@ -1004,6 +1004,7 @@ static int editsource_exec(bContext *C, wmOperator *op) ui_editsource_active_but_set(but); /* redraw and get active button python info */ + ED_region_do_layout(C, ar); ED_region_do_draw(C, ar); ar->do_draw = false; diff --git a/source/blender/editors/interface/interface_panel.c b/source/blender/editors/interface/interface_panel.c index dbdf2a0863c..e383ae42f8c 100644 --- a/source/blender/editors/interface/interface_panel.c +++ b/source/blender/editors/interface/interface_panel.c @@ -110,7 +110,7 @@ typedef struct uiHandlePanelData { int startsizex, startsizey; } uiHandlePanelData; -static int get_panel_real_size_y(Panel *pa); +static int get_panel_real_size_y(const Panel *pa); static void panel_activate_state(const bContext *C, Panel *pa, uiHandlePanelState state); /*********************** space specific code ************************/ @@ -855,7 +855,7 @@ void ui_draw_aligned_panel(uiStyle *style, uiBlock *block, const rcti *rect, con /************************** panel alignment *************************/ -static int get_panel_header(Panel *pa) +static int get_panel_header(const Panel *pa) { if (pa->type && (pa->type->flag & PNL_NO_HEADER)) return 0; @@ -863,7 +863,7 @@ static int get_panel_header(Panel *pa) return PNL_HEADER; } -static int get_panel_size_y(Panel *pa) +static int get_panel_size_y(const Panel *pa) { if (pa->type && (pa->type->flag & PNL_NO_HEADER)) return pa->sizey; @@ -871,7 +871,7 @@ static int get_panel_size_y(Panel *pa) return PNL_HEADER + pa->sizey; } -static int get_panel_real_size_y(Panel *pa) +static int get_panel_real_size_y(const Panel *pa) { int sizey = (pa->flag & PNL_CLOSED) ? 0 : pa->sizey; @@ -881,6 +881,11 @@ static int get_panel_real_size_y(Panel *pa) return PNL_HEADER + sizey; } +int UI_panel_size_y(const Panel *pa) +{ + return get_panel_real_size_y(pa); +} + /* this function is needed because uiBlock and Panel itself don't * change sizey or location when closed */ static int get_panel_real_ofsy(Panel *pa) @@ -1596,6 +1601,10 @@ static void ui_handle_panel_header(const bContext *C, uiBlock *block, int mx, in ED_region_tag_redraw(ar); } else if (show_drag && BLI_rctf_isect_x(&rect_drag, mx)) { + /* XXX, for now don't allow dragging in floating windows yet. */ + if (ar->alignment == RGN_ALIGN_FLOAT) { + return; + } panel_activate_state(C, block->panel, PANEL_STATE_DRAG); } else if (show_pin && BLI_rctf_isect_x(&rect_pin, mx)) { diff --git a/source/blender/editors/interface/interface_region_color_picker.c b/source/blender/editors/interface/interface_region_color_picker.c index 4309e913d9e..00462b456ea 100644 --- a/source/blender/editors/interface/interface_region_color_picker.c +++ b/source/blender/editors/interface/interface_region_color_picker.c @@ -585,7 +585,7 @@ static int ui_colorpicker_small_wheel_cb(const bContext *UNUSED(C), uiBlock *blo ui_rgb_to_color_picker_compat_v(rgb, hsv); - hsv[2] = CLAMPIS(hsv[2] + add, 0.0f, 1.0f); + hsv[2] = clamp_f(hsv[2] + add, 0.0f, 1.0f); ui_color_picker_to_rgb_v(hsv, rgb); if (use_display_colorspace) diff --git a/source/blender/editors/interface/interface_region_hud.c b/source/blender/editors/interface/interface_region_hud.c new file mode 100644 index 00000000000..1a49010ad9d --- /dev/null +++ b/source/blender/editors/interface/interface_region_hud.c @@ -0,0 +1,338 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2008 Blender Foundation. + * All rights reserved. + * + * Contributor(s): Blender Foundation + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file blender/editors/interface/interface_region_hud.c + * \ingroup edinterface + * + * Floating Persistent Region + */ + +#include <string.h> + +#include "MEM_guardedalloc.h" + +#include "DNA_userdef_types.h" + +#include "BLI_string.h" +#include "BLI_rect.h" +#include "BLI_listbase.h" +#include "BLI_utildefines.h" + +#include "BKE_context.h" +#include "BKE_screen.h" +#include "BKE_main.h" + +#include "WM_api.h" +#include "WM_types.h" + +#include "RNA_access.h" + +#include "BIF_gl.h" + +#include "UI_interface.h" +#include "UI_view2d.h" + +#include "BLT_translation.h" + +#include "ED_screen.h" +#include "ED_undo.h" + +#include "interface_intern.h" + + +/* -------------------------------------------------------------------- */ +/** \name Utilities + * \{ */ + +static bool last_redo_poll(const bContext *C) +{ + wmOperator *op = WM_operator_last_redo(C); + if (op == NULL) { + return false; + } + bool success = false; + if (WM_operator_repeat_check(C, op) && + WM_operator_check_ui_empty(op->type) == false) + { + success = WM_operator_poll((bContext *)C, op->type); + } + return success; +} + +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Redo Panel + * \{ */ + +static int hud_panel_operator_redo_poll(const bContext *C, PanelType *UNUSED(pt)) +{ + return last_redo_poll(C); +} + +static void hud_panel_operator_redo_draw_header(const bContext *C, Panel *pa) +{ + wmOperator *op = WM_operator_last_redo(C); + BLI_strncpy(pa->drawname, RNA_struct_ui_name(op->type->srna), sizeof(pa->drawname)); +} + +static void hud_panel_operator_redo_draw(const bContext *C, Panel *pa) +{ + wmOperator *op = WM_operator_last_redo(C); + if (op == NULL) { + return; + } + if (!WM_operator_check_ui_enabled(C, op->type->name)) { + uiLayoutSetEnabled(pa->layout, false); + } + uiLayout *col = uiLayoutColumn(pa->layout, false); + uiTemplateOperatorRedoProperties(col, C); +} + +static void hud_panels_register(ARegionType *art, int space_type, int region_type) +{ + PanelType *pt; + + pt = MEM_callocN(sizeof(PanelType), __func__); + strcpy(pt->idname, "OPERATOR_PT_redo"); + strcpy(pt->label, N_("Redo")); + strcpy(pt->translation_context, BLT_I18NCONTEXT_DEFAULT_BPYRNA); + pt->draw_header = hud_panel_operator_redo_draw_header; + pt->draw = hud_panel_operator_redo_draw; + pt->poll = hud_panel_operator_redo_poll; + pt->space_type = space_type; + pt->region_type = region_type; + BLI_addtail(&art->paneltypes, pt); +} + +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Callbacks for Floating Region + * \{ */ + +struct HudRegionData { + short regionid; +}; + +static void hud_region_init(wmWindowManager *wm, ARegion *ar) +{ + ED_region_panels_init(wm, ar); + UI_region_handlers_add(&ar->handlers); + ar->flag |= RGN_FLAG_TEMP_REGIONDATA; +} + +static void hud_region_free(ARegion *ar) +{ + MEM_SAFE_FREE(ar->regiondata); +} + +static void hud_region_layout(const bContext *C, ARegion *ar) +{ + bool ok = false; + + { + struct HudRegionData *hrd = ar->regiondata; + if (hrd != NULL) { + ScrArea *sa = CTX_wm_area(C); + ARegion *ar_op = (hrd->regionid != -1) ? BKE_area_find_region_type(sa, hrd->regionid) : NULL; + ARegion *ar_prev = CTX_wm_region(C); + CTX_wm_region_set((bContext *)C, ar_op); + ok = last_redo_poll(C); + CTX_wm_region_set((bContext *)C, ar_prev); + } + } + + if (!ok) { + ED_region_tag_redraw(ar); + ar->flag |= RGN_FLAG_HIDDEN; + return; + } + + int size_y = ar->sizey; + + ED_region_panels_layout(C, ar); + + if (ar->panels.first && (ar->sizey != size_y)) { + View2D *v2d = &ar->v2d; + ar->winx = ar->sizex; + ar->winy = ar->sizey; + + ar->winrct.xmax = (ar->winrct.xmin + ar->winx) - 1; + ar->winrct.ymax = (ar->winrct.ymin + ar->winy) - 1; + + UI_view2d_region_reinit(v2d, V2D_COMMONVIEW_PANELS_UI, ar->winx, ar->winy); + } + + /* restore view matrix */ + UI_view2d_view_restore(C); +} + +static void hud_region_draw(const bContext *C, ARegion *ar) +{ + UI_view2d_view_ortho(&ar->v2d); + wmOrtho2_region_pixelspace(ar); + glClearColor(0, 0, 0, 0.0f); + glClear(GL_COLOR_BUFFER_BIT); + + if ((ar->flag & RGN_FLAG_HIDDEN) == 0) { + float color[4]; + UI_GetThemeColor4fv(TH_BUTBACK, color); + if ((U.uiflag2 & USER_REGION_OVERLAP) == 0) { + color[3] = 1.0f; + } + ui_draw_widget_back_color(UI_WTYPE_BOX, false, &(rcti){.xmax = ar->winx, .ymax = ar->winy}, color); + ED_region_panels_draw(C, ar); + } +} + +ARegionType *ED_area_type_hud(int space_type) +{ + ARegionType *art = MEM_callocN(sizeof(ARegionType), __func__); + art->regionid = RGN_TYPE_HUD; + art->keymapflag = ED_KEYMAP_UI | ED_KEYMAP_VIEW2D; + art->layout = hud_region_layout; + art->draw = hud_region_draw; + art->init = hud_region_init; + art->free = hud_region_free; + + hud_panels_register(art, space_type, art->regionid); + + art->lock = 1; /* can become flag, see BKE_spacedata_draw_locks */ + return art; +} + +static ARegion *hud_region_add(ScrArea *sa) +{ + ARegion *ar = MEM_callocN(sizeof(ARegion), "area region"); + ARegion *ar_win = BKE_area_find_region_type(sa, RGN_TYPE_WINDOW); + if (ar_win) { + BLI_insertlinkbefore(&sa->regionbase, ar_win, ar); + } + else { + BLI_addtail(&sa->regionbase, ar); + } + ar->regiontype = RGN_TYPE_HUD; + ar->alignment = RGN_ALIGN_FLOAT; + ar->overlap = true; + ar->flag |= RGN_FLAG_DYNAMIC_SIZE; + + return ar; +} + +void ED_area_type_hud_clear(wmWindowManager *wm, ScrArea *sa_keep) +{ + for (wmWindow *win = wm->windows.first; win; win = win->next) { + bScreen *screen = WM_window_get_active_screen(win); + for (ScrArea *sa = screen->areabase.first; sa; sa = sa->next) { + if (sa != sa_keep) { + for (ARegion *ar = sa->regionbase.first; ar; ar = ar->next) { + if (ar->regiontype == RGN_TYPE_HUD) { + if ((ar->flag & RGN_FLAG_HIDDEN) == 0) { + ar->flag |= RGN_FLAG_HIDDEN; + ED_region_tag_redraw(ar); + ED_area_tag_redraw(sa); + } + } + } + } + } + } +} + +void ED_area_type_hud_ensure(bContext *C, ScrArea *sa) +{ + wmWindowManager *wm = CTX_wm_manager(C); + ED_area_type_hud_clear(wm, sa); + + ARegionType *art = BKE_regiontype_from_id(sa->type, RGN_TYPE_HUD); + if (art == NULL) { + return; + } + + bool init = false; + ARegion *ar = BKE_area_find_region_type(sa, RGN_TYPE_HUD); + if (!last_redo_poll(C)) { + if (ar) { + ED_region_tag_redraw(ar); + ar->flag |= RGN_FLAG_HIDDEN; + } + return; + } + + if (ar == NULL) { + init = true; + ar = hud_region_add(sa); + ar->type = art; + } + + ED_region_init(ar); + ED_region_tag_redraw(ar); + + /* Reset zoom level (not well supported). */ + ar->v2d.cur = ar->v2d.tot = (rctf){.xmax = ar->winx, .ymax = ar->winy}; + ar->v2d.minzoom = 1.0f; + ar->v2d.maxzoom = 1.0f; + + /* Let 'ED_area_update_region_sizes' do the work of placing the region. + * Otherwise we could set the 'ar->winrct' & 'ar->winx/winy' here. */ + if (init) { + sa->flag |= AREA_FLAG_REGION_SIZE_UPDATE; + } + else { + if (ar->flag & RGN_FLAG_HIDDEN) { + sa->flag |= AREA_FLAG_REGION_SIZE_UPDATE; + } + ar->flag &= ~RGN_FLAG_HIDDEN; + } + + { + ARegion *ar_op = CTX_wm_region(C); + BLI_assert((ar_op == NULL) || (ar_op->regiontype != RGN_TYPE_HUD)); + struct HudRegionData *hrd = ar->regiondata; + if (hrd == NULL) { + hrd = MEM_callocN(sizeof(*hrd), __func__); + ar->regiondata = hrd; + } + if (ar_op) { + hrd->regionid = ar_op->regiontype; + } + else { + hrd->regionid = -1; + } + } + + /* XXX, should be handled in more general way. */ + ar->visible = !((ar->flag & RGN_FLAG_HIDDEN) || (ar->flag & RGN_FLAG_TOO_SMALL)); + + /* We shouldn't need to do this every time :S */ + /* XXX, this is evil! - it also makes the menu show on first draw. :( */ + ARegion *ar_prev = CTX_wm_region(C); + CTX_wm_region_set((bContext *)C, ar); + hud_region_layout(C, ar); + CTX_wm_region_set((bContext *)C, ar_prev); +} + +/** \} */ diff --git a/source/blender/editors/interface/interface_region_popover.c b/source/blender/editors/interface/interface_region_popover.c index e769d367b45..fb14ca745c6 100644 --- a/source/blender/editors/interface/interface_region_popover.c +++ b/source/blender/editors/interface/interface_region_popover.c @@ -168,11 +168,17 @@ static uiBlock *ui_block_func_POPOVER(bContext *C, uiPopupBlockHandle *handle, v block->my = handle->prev_my; } - /* Prefer popover from header to be positioned into the editor. */ if (!slideout) { ScrArea *sa = CTX_wm_area(C); - if (sa && ED_area_header_alignment(sa) == RGN_ALIGN_BOTTOM) { - ARegion *ar = CTX_wm_region(C); + ARegion *ar = CTX_wm_region(C); + + if (ar && ar->panels.first) { + /* For regions with panels, prefer to open to top so we can + * see the values of the buttons below changing. */ + UI_block_direction_set(block, UI_DIR_UP | UI_DIR_CENTER_X); + } + else if (sa && ED_area_header_alignment(sa) == RGN_ALIGN_BOTTOM) { + /* Prefer popover from header to be positioned into the editor. */ if (ar && ar->regiontype == RGN_TYPE_HEADER) { UI_block_direction_set(block, UI_DIR_UP | UI_DIR_CENTER_X); } diff --git a/source/blender/editors/interface/interface_region_popup.c b/source/blender/editors/interface/interface_region_popup.c index 654dc5e4d30..0ac4d4d28ec 100644 --- a/source/blender/editors/interface/interface_region_popup.c +++ b/source/blender/editors/interface/interface_region_popup.c @@ -63,13 +63,13 @@ /** * Translate any popup regions (so we can drag them). */ -void ui_popup_translate(bContext *C, ARegion *ar, const int mdiff[2]) +void ui_popup_translate(ARegion *ar, const int mdiff[2]) { uiBlock *block; BLI_rcti_translate(&ar->winrct, UNPACK2(mdiff)); - ED_region_update_rect(C, ar); + ED_region_update_rect(ar); ED_region_tag_redraw(ar); @@ -625,7 +625,7 @@ uiBlock *ui_popup_block_refresh( ui_popup_block_scrolltest(block); /* adds subwindow */ - ED_region_init(C, ar); + ED_region_init(ar); /* get winmat now that we actually have the subwindow */ wmGetProjectionMatrix(block->winmat, &ar->winrct); @@ -633,7 +633,7 @@ uiBlock *ui_popup_block_refresh( /* notify change and redraw */ ED_region_tag_redraw(ar); - ED_region_update_rect(C, ar); + ED_region_update_rect(ar); #ifdef DEBUG window->eventstate = event_back; diff --git a/source/blender/editors/interface/interface_region_search.c b/source/blender/editors/interface/interface_region_search.c index f14f9af8785..e0dc149be17 100644 --- a/source/blender/editors/interface/interface_region_search.c +++ b/source/blender/editors/interface/interface_region_search.c @@ -404,8 +404,9 @@ static void ui_searchbox_region_draw_cb(const bContext *C, ARegion *ar) /* pixel space */ wmOrtho2_region_pixelspace(ar); - if (data->noback == false) - ui_draw_search_back(NULL, NULL, &data->bbox); /* style not used yet */ + if (data->noback == false) { + ui_draw_widget_back(UI_WTYPE_BOX, true, &data->bbox); + } /* draw text */ if (data->items.totitem) { @@ -625,7 +626,7 @@ ARegion *ui_searchbox_create_generic(bContext *C, ARegion *butregion, uiBut *but } /* adds subwindow */ - ED_region_init(C, ar); + ED_region_init(ar); /* notify change and redraw */ ED_region_tag_redraw(ar); @@ -681,8 +682,9 @@ static void ui_searchbox_region_draw_cb__operator(const bContext *UNUSED(C), ARe /* pixel space */ wmOrtho2_region_pixelspace(ar); - if (data->noback == false) - ui_draw_search_back(NULL, NULL, &data->bbox); /* style not used yet */ + if (data->noback == false) { + ui_draw_widget_back(UI_WTYPE_BOX, true, &data->bbox); + } /* draw text */ if (data->items.totitem) { diff --git a/source/blender/editors/interface/interface_region_tooltip.c b/source/blender/editors/interface/interface_region_tooltip.c index aa8fe173638..ed83a715c7e 100644 --- a/source/blender/editors/interface/interface_region_tooltip.c +++ b/source/blender/editors/interface/interface_region_tooltip.c @@ -867,7 +867,7 @@ static ARegion *ui_tooltip_create_with_data( } /* adds subwindow */ - ED_region_init(C, ar); + ED_region_init(ar); /* notify change and redraw */ ED_region_tag_redraw(ar); diff --git a/source/blender/editors/interface/interface_templates.c b/source/blender/editors/interface/interface_templates.c index 9978726fa74..59cb2229905 100644 --- a/source/blender/editors/interface/interface_templates.c +++ b/source/blender/editors/interface/interface_templates.c @@ -500,6 +500,7 @@ static void template_id_cb(bContext *C, void *arg_litem, void *arg_event) Main *bmain = CTX_data_main(C); Scene *scene = CTX_data_scene(C); ED_object_single_user(bmain, scene, (struct Object *)id); + DEG_id_tag_update(&scene->id, DEG_TAG_SELECT_UPDATE); WM_event_add_notifier(C, NC_SCENE | ND_OB_ACTIVE, scene); DEG_relations_tag_update(bmain); } @@ -1578,12 +1579,16 @@ void uiTemplateOperatorRedoProperties(uiLayout *layout, const bContext *C) #endif if (WM_operator_repeat_check(C, op)) { + int layout_flags = 0; + if (block->panel == NULL) { + layout_flags = UI_TEMPLATE_OP_PROPS_SHOW_TITLE; + } #if 0 bool has_advanced = false; #endif UI_block_func_set(block, ED_undo_operator_repeat_cb, op, NULL); - template_operator_redo_property_buts_draw(C, op, layout, UI_TEMPLATE_OP_PROPS_COMPACT, NULL /* &has_advanced */ ); + template_operator_redo_property_buts_draw(C, op, layout, layout_flags, NULL /* &has_advanced */ ); UI_block_func_set(block, NULL, NULL, NULL); /* may want to reset to old state instead of NULLing all */ #if 0 @@ -1743,7 +1748,7 @@ static uiLayout *draw_constraint(uiLayout *layout, Object *ob, bConstraint *con) /* enabled */ UI_block_emboss_set(block, UI_EMBOSS_NONE); uiItemR(row, &ptr, "mute", 0, "", - (con->flag & CONSTRAINT_OFF) ? ICON_RESTRICT_VIEW_ON : ICON_RESTRICT_VIEW_OFF); + (con->flag & CONSTRAINT_OFF) ? ICON_HIDE_ON : ICON_HIDE_OFF); UI_block_emboss_set(block, UI_EMBOSS); uiLayoutSetOperatorContext(row, WM_OP_INVOKE_DEFAULT); @@ -2180,6 +2185,19 @@ void uiTemplateColorRamp(uiLayout *layout, PointerRNA *ptr, const char *propname MEM_freeN(cb); } +/********************* Icon Template ************************/ +/** + * \param icon_scale: Scale of the icon, 1x == button height. + */ +void uiTemplateIcon(uiLayout *layout, int icon_value, float icon_scale) +{ + uiBlock *block; + uiBut *but; + + block = uiLayoutAbsoluteBlock(layout); + but = uiDefIconBut(block, UI_BTYPE_LABEL, 0, ICON_X, 0, 0, UI_UNIT_X * icon_scale, UI_UNIT_Y * icon_scale, NULL, 0.0, 0.0, 0.0, 0.0, ""); + ui_def_but_icon(but, icon_value, UI_HAS_ICON | UI_BUT_ICON_PREVIEW); +} /********************* Icon viewer Template ************************/ typedef struct IconViewMenuArgs { @@ -2266,13 +2284,20 @@ void uiTemplateIconView(uiLayout *layout, PointerRNA *ptr, const char *propname, value = RNA_property_enum_get(ptr, prop); RNA_enum_icon_from_value(items, value, &icon); - cb_args = MEM_callocN(sizeof(IconViewMenuArgs), __func__); - cb_args->ptr = *ptr; - cb_args->prop = prop; - cb_args->show_labels = show_labels; - cb_args->icon_scale = icon_scale; - but = uiDefBlockButN(block, ui_icon_view_menu_cb, cb_args, "", 0, 0, UI_UNIT_X * 6, UI_UNIT_Y * 6, ""); + if (RNA_property_editable(ptr, prop)) { + cb_args = MEM_callocN(sizeof(IconViewMenuArgs), __func__); + cb_args->ptr = *ptr; + cb_args->prop = prop; + cb_args->show_labels = show_labels; + cb_args->icon_scale = icon_scale; + + but = uiDefBlockButN(block, ui_icon_view_menu_cb, cb_args, "", 0, 0, UI_UNIT_X * 6, UI_UNIT_Y * 6, ""); + } + else { + but = uiDefIconBut(block, UI_BTYPE_LABEL, 0, ICON_X, 0, 0, UI_UNIT_X * 6, UI_UNIT_Y * 6, NULL, 0.0, 0.0, 0.0, 0.0, ""); + } + ui_def_but_icon(but, icon, UI_HAS_ICON | UI_BUT_ICON_PREVIEW); @@ -3945,6 +3970,8 @@ eAutoPropButsReturn uiTemplateOperatorPropertyButs( RNA_pointer_create(&wm->id, op->type->srna, op->properties, &ptr); + uiLayoutSetPropSep(layout, true); + /* main draw call */ return_info = uiDefAutoButsRNA(layout, &ptr, check_prop, label_align, (flag & UI_TEMPLATE_OP_PROPS_COMPACT)); diff --git a/source/blender/editors/interface/interface_widgets.c b/source/blender/editors/interface/interface_widgets.c index ac8d900f560..3b7ccb68fd4 100644 --- a/source/blender/editors/interface/interface_widgets.c +++ b/source/blender/editors/interface/interface_widgets.c @@ -230,16 +230,16 @@ static const uint g_shape_preset_hold_action_face[2][3] = {{2, 0, 1}, {3, 5, 4}} static const int tria_ofs[ROUNDBOX_TRIA_MAX] = { [ROUNDBOX_TRIA_NONE] = 0, [ROUNDBOX_TRIA_ARROWS] = 0, - [ROUNDBOX_TRIA_SCROLL] = 6, - [ROUNDBOX_TRIA_MENU] = 22, - [ROUNDBOX_TRIA_CHECK] = 28, - [ROUNDBOX_TRIA_HOLD_ACTION_ARROW] = 34, + [ROUNDBOX_TRIA_SCROLL] = 12, + [ROUNDBOX_TRIA_MENU] = 28, + [ROUNDBOX_TRIA_CHECK] = 34, + [ROUNDBOX_TRIA_HOLD_ACTION_ARROW] = 40, }; static const int tria_vcount[ROUNDBOX_TRIA_MAX] = { [ROUNDBOX_TRIA_NONE] = 0, - [ROUNDBOX_TRIA_ARROWS] = 3, + [ROUNDBOX_TRIA_ARROWS] = 6, [ROUNDBOX_TRIA_SCROLL] = 16, - [ROUNDBOX_TRIA_MENU] = 3, + [ROUNDBOX_TRIA_MENU] = 6, [ROUNDBOX_TRIA_CHECK] = 6, [ROUNDBOX_TRIA_HOLD_ACTION_ARROW] = 3, }; @@ -296,8 +296,8 @@ static uint32_t set_tria_vertex( int tria_type, int tria_v, int tria_id, int jit_v) { uint32_t *data = GWN_vertbuf_raw_step(vflag_step); - if (ELEM(tria_type, ROUNDBOX_TRIA_ARROWS, ROUNDBOX_TRIA_MENU)) { - tria_v += tria_id * 3; + if (ELEM(tria_type, ROUNDBOX_TRIA_ARROWS)) { + tria_v += tria_id * tria_vcount[ROUNDBOX_TRIA_ARROWS]; } *data = tria_ofs[tria_type] + tria_v; *data |= jit_v << 6; @@ -308,7 +308,7 @@ static uint32_t set_tria_vertex( static void roundbox_batch_add_tria(Gwn_VertBufRaw *vflag_step, int tria, uint32_t last_data) { - const int tria_num = ELEM(tria, ROUNDBOX_TRIA_CHECK, ROUNDBOX_TRIA_HOLD_ACTION_ARROW) ? 1 : 2; + const int tria_num = ELEM(tria, ROUNDBOX_TRIA_CHECK, ROUNDBOX_TRIA_HOLD_ACTION_ARROW, ROUNDBOX_TRIA_MENU) ? 1 : 2; /* for each tria */ for (int t = 0; t < tria_num; ++t) { for (int j = 0; j < WIDGET_AA_JITTER; j++) { @@ -335,7 +335,7 @@ Gwn_Batch *ui_batch_roundbox_widget_get(int tria) vcount += ((WIDGET_CURVE_RESOLU * 2) * 2) * WIDGET_AA_JITTER; /* emboss */ if (tria) { vcount += (tria_vcount[tria] + 2) * WIDGET_AA_JITTER; /* tria1 */ - if (!ELEM(tria, ROUNDBOX_TRIA_CHECK, ROUNDBOX_TRIA_HOLD_ACTION_ARROW)) { + if (!ELEM(tria, ROUNDBOX_TRIA_CHECK, ROUNDBOX_TRIA_HOLD_ACTION_ARROW, ROUNDBOX_TRIA_MENU)) { vcount += (tria_vcount[tria] + 2) * WIDGET_AA_JITTER; /* tria2 */ } } @@ -2657,18 +2657,22 @@ static void widget_state_pie_menu_item(uiWidgetType *wt, int state) copy_v4_v4_char(wt->wcol.inner, wt->wcol.item); wt->wcol.inner[3] = 64; } - /* regular disabled */ - else if (state & (UI_BUT_DISABLED | UI_BUT_INACTIVE)) { - widget_state_blend(wt->wcol.text, wt->wcol.inner, 0.5f); - } - /* regular active */ - else if (state & UI_SELECT) { - copy_v4_v4_char(wt->wcol.outline, wt->wcol.inner_sel); - copy_v3_v3_char(wt->wcol.text, wt->wcol.text_sel); - } - else if (state & UI_ACTIVE) { - copy_v4_v4_char(wt->wcol.inner, wt->wcol.item); - copy_v3_v3_char(wt->wcol.text, wt->wcol.text_sel); + else { + /* regular active */ + if (state & (UI_SELECT | UI_ACTIVE)) { + copy_v3_v3_char(wt->wcol.text, wt->wcol.text_sel); + } + else if (state & (UI_BUT_DISABLED | UI_BUT_INACTIVE)) { + /* regular disabled */ + widget_state_blend(wt->wcol.text, wt->wcol.inner, 0.5f); + } + + if (state & UI_SELECT) { + copy_v4_v4_char(wt->wcol.outline, wt->wcol.inner_sel); + } + else if (state & UI_ACTIVE) { + copy_v4_v4_char(wt->wcol.inner, wt->wcol.item); + } } } @@ -2685,14 +2689,19 @@ static void widget_state_menu_item(uiWidgetType *wt, int state) copy_v4_v4_char(wt->wcol.inner, wt->wcol.inner_sel); wt->wcol.inner[3] = 64; } - /* regular disabled */ - else if (state & (UI_BUT_DISABLED | UI_BUT_INACTIVE)) { - widget_state_blend(wt->wcol.text, wt->wcol.inner, 0.5f); - } - /* regular active */ - else if (state & UI_ACTIVE) { - copy_v4_v4_char(wt->wcol.inner, wt->wcol.inner_sel); - copy_v3_v3_char(wt->wcol.text, wt->wcol.text_sel); + else { + /* regular active */ + if (state & UI_ACTIVE) { + copy_v3_v3_char(wt->wcol.text, wt->wcol.text_sel); + } + else if (state & (UI_BUT_DISABLED | UI_BUT_INACTIVE)) { + /* regular disabled */ + widget_state_blend(wt->wcol.text, wt->wcol.inner, 0.5f); + } + + if (state & UI_ACTIVE) { + copy_v4_v4_char(wt->wcol.inner, wt->wcol.inner_sel); + } } } @@ -2825,7 +2834,7 @@ void ui_hsvcircle_pos_from_vals(uiBut *but, const rcti *rect, float *hsv, float else radius_t = hsv[1]; - radius = CLAMPIS(radius_t, 0.0f, 1.0f) * radius; + radius = clamp_f(radius_t, 0.0f, 1.0f) * radius; *xpos = centx + cosf(-ang) * radius; *ypos = centy + sinf(-ang) * radius; } @@ -4916,30 +4925,41 @@ uiWidgetColors *ui_tooltip_get_theme(void) return wt->wcol_theme; } -void ui_draw_tooltip_background(uiStyle *UNUSED(style), uiBlock *UNUSED(block), rcti *rect) +/** + * Generic drawing for background. + */ +void ui_draw_widget_back_color( + uiWidgetTypeEnum type, bool use_shadow, const rcti *rect, + const float color[4]) { - uiWidgetType *wt = widget_type(UI_WTYPE_TOOLTIP); + uiWidgetType *wt = widget_type(type); + + if (use_shadow) { + glEnable(GL_BLEND); + widget_softshadow(rect, UI_CNR_ALL, 0.25f * U.widget_unit); + glDisable(GL_BLEND); + } + + rcti rect_copy = *rect; wt->state(wt, 0); - /* wt->draw ends up using same function to draw the tooltip as menu_back */ - wt->draw(&wt->wcol, rect, 0, 0); + if (color) { + rgba_float_to_uchar((unsigned char *)wt->wcol.inner, color); + } + wt->draw(&wt->wcol, &rect_copy, 0, UI_CNR_ALL); } - -void ui_draw_search_back(uiStyle *UNUSED(style), uiBlock *block, rcti *rect) +void ui_draw_widget_back(uiWidgetTypeEnum type, bool use_shadow, const rcti *rect) { - uiWidgetType *wt = widget_type(UI_WTYPE_BOX); - - glEnable(GL_BLEND); - widget_softshadow(rect, UI_CNR_ALL, 0.25f * U.widget_unit); - glDisable(GL_BLEND); + ui_draw_widget_back_color(type, use_shadow, rect, NULL); +} +void ui_draw_tooltip_background(uiStyle *UNUSED(style), uiBlock *UNUSED(block), rcti *rect) +{ + uiWidgetType *wt = widget_type(UI_WTYPE_TOOLTIP); wt->state(wt, 0); - if (block) - wt->draw(&wt->wcol, rect, block->flag, UI_CNR_ALL); - else - wt->draw(&wt->wcol, rect, 0, UI_CNR_ALL); + /* wt->draw ends up using same function to draw the tooltip as menu_back */ + wt->draw(&wt->wcol, rect, 0, 0); } - /* helper call to draw a menu item without button */ /* state: UI_ACTIVE or 0 */ void ui_draw_menu_item(uiFontStyle *fstyle, rcti *rect, const char *name, int iconid, int state, bool use_sep) diff --git a/source/blender/editors/interface/resources.c b/source/blender/editors/interface/resources.c index 2a61be21589..8bd41b874f5 100644 --- a/source/blender/editors/interface/resources.c +++ b/source/blender/editors/interface/resources.c @@ -3031,6 +3031,7 @@ void init_userdef_do_versions(Main *bmain) rgba_char_args_set(ts->panelcolors.sub_back, 0, 0, 0, 25); } } + U.gpu_viewport_antialias = USER_AA_FXAA; } /** diff --git a/source/blender/editors/interface/view2d_ops.c b/source/blender/editors/interface/view2d_ops.c index fbc8fe790c9..b9e6d43aa87 100644 --- a/source/blender/editors/interface/view2d_ops.c +++ b/source/blender/editors/interface/view2d_ops.c @@ -1123,7 +1123,7 @@ static int view_zoomdrag_modal(bContext *C, wmOperator *op, const wmEvent *event /* some view2d's (graph) don't have min/max zoom, or extreme ones */ if (v2d->maxzoom > 0.0f) - zoomfac = CLAMPIS(0.001f * v2d->maxzoom, 0.001f, 0.01f); + zoomfac = clamp_f(0.001f * v2d->maxzoom, 0.001f, 0.01f); /* x-axis transform */ fac = zoomfac * (event->x - vzd->lastx); diff --git a/source/blender/editors/io/io_alembic.c b/source/blender/editors/io/io_alembic.c index 4440b99f211..91fc1e9fe6a 100644 --- a/source/blender/editors/io/io_alembic.c +++ b/source/blender/editors/io/io_alembic.c @@ -86,7 +86,7 @@ static int wm_alembic_export_invoke(bContext *C, wmOperator *op, const wmEvent * BLI_strncpy(filepath, BKE_main_blendfile_path(bmain), sizeof(filepath)); } - BLI_replace_extension(filepath, sizeof(filepath), ".abc"); + BLI_path_extension_replace(filepath, sizeof(filepath), ".abc"); RNA_string_set(op->ptr, "filepath", filepath); } @@ -284,8 +284,8 @@ static bool wm_alembic_export_check(bContext *UNUSED(C), wmOperator *op) char filepath[FILE_MAX]; RNA_string_get(op->ptr, "filepath", filepath); - if (!BLI_testextensie(filepath, ".abc")) { - BLI_ensure_extension(filepath, FILE_MAX, ".abc"); + if (!BLI_path_extension_check(filepath, ".abc")) { + BLI_path_extension_ensure(filepath, FILE_MAX, ".abc"); RNA_string_set(op->ptr, "filepath", filepath); return true; } diff --git a/source/blender/editors/io/io_cache.c b/source/blender/editors/io/io_cache.c index b13eaced843..221142a6cf8 100644 --- a/source/blender/editors/io/io_cache.c +++ b/source/blender/editors/io/io_cache.c @@ -61,7 +61,7 @@ static int cachefile_open_invoke(bContext *C, wmOperator *op, const wmEvent *eve Main *bmain = CTX_data_main(C); BLI_strncpy(filepath, BKE_main_blendfile_path(bmain), sizeof(filepath)); - BLI_replace_extension(filepath, sizeof(filepath), ".abc"); + BLI_path_extension_replace(filepath, sizeof(filepath), ".abc"); RNA_string_set(op->ptr, "filepath", filepath); } diff --git a/source/blender/editors/io/io_collada.c b/source/blender/editors/io/io_collada.c index aca380c3123..8f05495bb7f 100644 --- a/source/blender/editors/io/io_collada.c +++ b/source/blender/editors/io/io_collada.c @@ -72,7 +72,7 @@ static int wm_collada_export_invoke(bContext *C, wmOperator *op, const wmEvent * else BLI_strncpy(filepath, blendfile_path, sizeof(filepath)); - BLI_replace_extension(filepath, sizeof(filepath), ".dae"); + BLI_path_extension_replace(filepath, sizeof(filepath), ".dae"); RNA_string_set(op->ptr, "filepath", filepath); } @@ -119,7 +119,7 @@ static int wm_collada_export_exec(bContext *C, wmOperator *op) } RNA_string_get(op->ptr, "filepath", filepath); - BLI_ensure_extension(filepath, sizeof(filepath), ".dae"); + BLI_path_extension_ensure(filepath, sizeof(filepath), ".dae"); /* Avoid File write exceptions in Collada */ @@ -337,8 +337,8 @@ static bool wm_collada_export_check(bContext *UNUSED(C), wmOperator *op) char filepath[FILE_MAX]; RNA_string_get(op->ptr, "filepath", filepath); - if (!BLI_testextensie(filepath, ".dae")) { - BLI_ensure_extension(filepath, FILE_MAX, ".dae"); + if (!BLI_path_extension_check(filepath, ".dae")) { + BLI_path_extension_ensure(filepath, FILE_MAX, ".dae"); RNA_string_set(op->ptr, "filepath", filepath); return true; } diff --git a/source/blender/editors/lattice/editlattice_select.c b/source/blender/editors/lattice/editlattice_select.c index 2ba1dde243b..6f1c864130d 100644 --- a/source/blender/editors/lattice/editlattice_select.c +++ b/source/blender/editors/lattice/editlattice_select.c @@ -59,6 +59,8 @@ #include "WM_api.h" #include "WM_types.h" +#include "DEG_depsgraph.h" + #include "lattice_intern.h" /* -------------------------------------------------------------------- */ @@ -118,6 +120,7 @@ static int lattice_select_random_exec(bContext *C, wmOperator *op) BLI_rng_free(rng); + DEG_id_tag_update(obedit->data, DEG_TAG_SELECT_UPDATE); WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data); } @@ -209,6 +212,7 @@ static int lattice_select_mirror_exec(bContext *C, wmOperator *op) } /* TODO, only notify changes */ + DEG_id_tag_update(obedit->data, DEG_TAG_SELECT_UPDATE); WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data); } MEM_freeN(objects); @@ -295,6 +299,7 @@ static int lattice_select_more_less(bContext *C, const bool select) MEM_freeN(selpoints); + DEG_id_tag_update(obedit->data, DEG_TAG_SELECT_UPDATE); WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data); return OPERATOR_FINISHED; } @@ -411,6 +416,7 @@ static int lattice_select_all_exec(bContext *C, wmOperator *op) } break; } + DEG_id_tag_update(obedit->data, DEG_TAG_SELECT_UPDATE); WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data); } MEM_freeN(objects); @@ -470,6 +476,7 @@ static int lattice_select_ungrouped_exec(bContext *C, wmOperator *op) } } + DEG_id_tag_update(obedit->data, DEG_TAG_SELECT_UPDATE); WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data); return OPERATOR_FINISHED; @@ -568,6 +575,7 @@ bool ED_lattice_select_pick(bContext *C, const int mval[2], bool extend, bool de lt->actbp = LT_ACTBP_NONE; } + DEG_id_tag_update(vc.obedit->data, DEG_TAG_SELECT_UPDATE); WM_event_add_notifier(C, NC_GEOM | ND_SELECT, vc.obedit->data); return true; diff --git a/source/blender/editors/manipulator_library/manipulator_types/arrow3d_manipulator.c b/source/blender/editors/manipulator_library/manipulator_types/arrow3d_manipulator.c index 409a2c3ca83..8516b9d8244 100644 --- a/source/blender/editors/manipulator_library/manipulator_types/arrow3d_manipulator.c +++ b/source/blender/editors/manipulator_library/manipulator_types/arrow3d_manipulator.c @@ -92,6 +92,7 @@ static void arrow_draw_geom(const ArrowManipulator3D *arrow, const bool select, uint pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT); bool unbind_shader = true; const int draw_style = RNA_enum_get(arrow->manipulator.ptr, "draw_style"); + const int draw_options = RNA_enum_get(arrow->manipulator.ptr, "draw_options"); immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); @@ -131,9 +132,13 @@ static void arrow_draw_geom(const ArrowManipulator3D *arrow, const bool select, {0.0f, 0.0f, arrow_length}, }; - glLineWidth(arrow->manipulator.line_width); - wm_manipulator_vec_draw(color, vec, ARRAY_SIZE(vec), pos, GWN_PRIM_LINE_STRIP); - + if (draw_options & ED_MANIPULATOR_ARROW_DRAW_FLAG_STEM) { + glLineWidth(arrow->manipulator.line_width); + wm_manipulator_vec_draw(color, vec, ARRAY_SIZE(vec), pos, GWN_PRIM_LINE_STRIP); + } + else { + immUniformColor4fv(color); + } /* *** draw arrow head *** */ @@ -303,9 +308,9 @@ static int manipulator_arrow_modal( /* set the property for the operator and call its modal function */ if (WM_manipulator_target_property_is_valid(mpr_prop)) { - const int draw_options = RNA_enum_get(arrow->manipulator.ptr, "draw_options"); - const bool constrained = (draw_options & ED_MANIPULATOR_ARROW_STYLE_CONSTRAINED) != 0; - const bool inverted = (draw_options & ED_MANIPULATOR_ARROW_STYLE_INVERTED) != 0; + const int transform_flag = RNA_enum_get(arrow->manipulator.ptr, "transform"); + const bool constrained = (transform_flag & ED_MANIPULATOR_ARROW_XFORM_FLAG_CONSTRAINED) != 0; + const bool inverted = (transform_flag & ED_MANIPULATOR_ARROW_XFORM_FLAG_INVERTED) != 0; const bool use_precision = (tweak_flag & WM_MANIPULATOR_TWEAK_PRECISE) != 0; float value = manipulator_value_from_offset(data, inter, ofs_new, constrained, inverted, use_precision); @@ -363,9 +368,9 @@ static int manipulator_arrow_invoke( static void manipulator_arrow_property_update(wmManipulator *mpr, wmManipulatorProperty *mpr_prop) { ArrowManipulator3D *arrow = (ArrowManipulator3D *)mpr; - const int draw_options = RNA_enum_get(arrow->manipulator.ptr, "draw_options"); - const bool constrained = (draw_options & ED_MANIPULATOR_ARROW_STYLE_CONSTRAINED) != 0; - const bool inverted = (draw_options & ED_MANIPULATOR_ARROW_STYLE_INVERTED) != 0; + const int transform_flag = RNA_enum_get(arrow->manipulator.ptr, "transform"); + const bool constrained = (transform_flag & ED_MANIPULATOR_ARROW_XFORM_FLAG_CONSTRAINED) != 0; + const bool inverted = (transform_flag & ED_MANIPULATOR_ARROW_XFORM_FLAG_INVERTED) != 0; manipulator_property_data_update(mpr, &arrow->data, mpr_prop, constrained, inverted); } @@ -448,21 +453,35 @@ static void MANIPULATOR_WT_arrow_3d(wmManipulatorType *wt) wt->struct_size = sizeof(ArrowManipulator3D); /* rna */ - static EnumPropertyItem rna_enum_draw_style[] = { + static EnumPropertyItem rna_enum_draw_style_items[] = { {ED_MANIPULATOR_ARROW_STYLE_NORMAL, "NORMAL", 0, "Normal", ""}, {ED_MANIPULATOR_ARROW_STYLE_CROSS, "CROSS", 0, "Cross", ""}, {ED_MANIPULATOR_ARROW_STYLE_BOX, "BOX", 0, "Box", ""}, {ED_MANIPULATOR_ARROW_STYLE_CONE, "CONE", 0, "Cone", ""}, {0, NULL, 0, NULL, NULL} }; - static EnumPropertyItem rna_enum_draw_options[] = { - {ED_MANIPULATOR_ARROW_STYLE_INVERTED, "INVERT", 0, "Inverted", ""}, - {ED_MANIPULATOR_ARROW_STYLE_CONSTRAINED, "CONSTRAIN", 0, "Constrained", ""}, + static EnumPropertyItem rna_enum_draw_options_items[] = { + {ED_MANIPULATOR_ARROW_DRAW_FLAG_STEM, "STEM", 0, "Stem", ""}, + {0, NULL, 0, NULL, NULL} + }; + static EnumPropertyItem rna_enum_transform_items[] = { + {ED_MANIPULATOR_ARROW_XFORM_FLAG_INVERTED, "INVERT", 0, "Inverted", ""}, + {ED_MANIPULATOR_ARROW_XFORM_FLAG_CONSTRAINED, "CONSTRAIN", 0, "Constrained", ""}, {0, NULL, 0, NULL, NULL} }; - RNA_def_enum(wt->srna, "draw_style", rna_enum_draw_style, ED_MANIPULATOR_ARROW_STYLE_NORMAL, "Draw Style", ""); - RNA_def_enum_flag(wt->srna, "draw_options", rna_enum_draw_options, 0, "Draw Options", ""); + RNA_def_enum( + wt->srna, "draw_style", rna_enum_draw_style_items, + ED_MANIPULATOR_ARROW_STYLE_NORMAL, + "Draw Style", ""); + RNA_def_enum_flag( + wt->srna, "draw_options", rna_enum_draw_options_items, + ED_MANIPULATOR_ARROW_DRAW_FLAG_STEM, + "Draw Options", ""); + RNA_def_enum_flag( + wt->srna, "transform", rna_enum_transform_items, + 0, + "Transform", ""); RNA_def_float(wt->srna, "length", 1.0f, 0.0f, FLT_MAX, "Arrow Line Length", "", 0.0f, FLT_MAX); RNA_def_float_vector(wt->srna, "aspect", 2, NULL, 0, FLT_MAX, "Aspect", "Cone/box style only", 0.0f, FLT_MAX); diff --git a/source/blender/editors/manipulator_library/manipulator_types/dial3d_manipulator.c b/source/blender/editors/manipulator_library/manipulator_types/dial3d_manipulator.c index a3034597f56..643a379cbb0 100644 --- a/source/blender/editors/manipulator_library/manipulator_types/dial3d_manipulator.c +++ b/source/blender/editors/manipulator_library/manipulator_types/dial3d_manipulator.c @@ -94,6 +94,9 @@ typedef struct DialInteraction { #define DIAL_WIDTH 1.0f #define DIAL_RESOLUTION 48 +/* Could make option, negative to clip more (don't show when view aligned). */ +#define DIAL_CLIP_BIAS 0.02 + /** * We can't use this for the #wmManipulatorType.matrix_basis_get callback, it conflicts with depth picking. */ @@ -347,6 +350,7 @@ static void manipulator_dial_draw_select(const bContext *C, wmManipulator *mpr, copy_v3_v3(clip_plane, rv3d->viewinv[2]); clip_plane[3] = -dot_v3v3(rv3d->viewinv[2], mpr->matrix_basis[3]); + clip_plane[3] += DIAL_CLIP_BIAS * mpr->scale_final; glEnable(GL_CLIP_DISTANCE0); } @@ -373,7 +377,7 @@ static void manipulator_dial_draw(const bContext *C, wmManipulator *mpr) copy_v3_v3(clip_plane, rv3d->viewinv[2]); clip_plane[3] = -dot_v3v3(rv3d->viewinv[2], mpr->matrix_basis[3]); - clip_plane[3] -= 0.02f * mpr->scale_final; + clip_plane[3] += DIAL_CLIP_BIAS * mpr->scale_final; glEnable(GL_CLIP_DISTANCE0); } diff --git a/source/blender/editors/mesh/editface.c b/source/blender/editors/mesh/editface.c index 7e31b6a3774..cf4d8ebf05d 100644 --- a/source/blender/editors/mesh/editface.c +++ b/source/blender/editors/mesh/editface.c @@ -52,6 +52,8 @@ #include "GPU_draw.h" +#include "DEG_depsgraph.h" + /* own include */ /* copy the face flags, most importantly selection from the mesh to the final derived mesh, @@ -382,6 +384,7 @@ bool paintface_mouse_select(struct bContext *C, Object *ob, const int mval[2], b /* image window redraw */ paintface_flush_flags(ob, SELECT); + DEG_id_tag_update(ob->data, DEG_TAG_SELECT_UPDATE); WM_event_add_notifier(C, NC_GEOM | ND_SELECT, ob->data); ED_region_tag_redraw(CTX_wm_region(C)); // XXX - should redraw all 3D views return true; diff --git a/source/blender/editors/mesh/editmesh_intersect.c b/source/blender/editors/mesh/editmesh_intersect.c index ad76f0c66f1..9af700aa6bf 100644 --- a/source/blender/editors/mesh/editmesh_intersect.c +++ b/source/blender/editors/mesh/editmesh_intersect.c @@ -197,18 +197,18 @@ static int edbm_intersect_exec(bContext *C, wmOperator *op) } has_isect = BM_mesh_intersect( - em->bm, - em->looptris, em->tottri, - test_fn, NULL, - use_self, use_separate_all, true, true, true, - -1, - eps); + em->bm, + em->looptris, em->tottri, + test_fn, NULL, + use_self, use_separate_all, true, true, true, true, + -1, + eps); if (use_separate_cut) { /* detach selected/un-selected faces */ BM_mesh_separate_faces( - em->bm, - BM_elem_cb_check_hflag_enabled_simple(const BMFace *, BM_ELEM_SELECT)); + em->bm, + BM_elem_cb_check_hflag_enabled_simple(const BMFace *, BM_ELEM_SELECT)); } if (has_isect) { @@ -300,12 +300,12 @@ static int edbm_intersect_boolean_exec(bContext *C, wmOperator *op) } has_isect = BM_mesh_intersect( - em->bm, - em->looptris, em->tottri, - test_fn, NULL, - false, false, true, true, true, - boolean_operation, - eps); + em->bm, + em->looptris, em->tottri, + test_fn, NULL, + false, false, true, true, false, true, + boolean_operation, + eps); if (has_isect) { diff --git a/source/blender/editors/mesh/editmesh_loopcut.c b/source/blender/editors/mesh/editmesh_loopcut.c index 3e787b2055a..7dac9a09b97 100644 --- a/source/blender/editors/mesh/editmesh_loopcut.c +++ b/source/blender/editors/mesh/editmesh_loopcut.c @@ -400,6 +400,7 @@ static void edgering_select(RingSelOpData *lcd) Object *ob_iter = lcd->objects[ob_index]; BMEditMesh *em = BKE_editmesh_from_object(ob_iter); EDBM_flag_disable_all(em, BM_ELEM_SELECT); + DEG_id_tag_update(ob_iter->data, DEG_TAG_SELECT_UPDATE); WM_main_add_notifier(NC_GEOM | ND_SELECT, ob_iter->data); } } @@ -496,6 +497,7 @@ static void ringsel_finish(bContext *C, wmOperator *op) BM_select_history_store(em->bm, lcd->eed); EDBM_selectmode_flush(lcd->em); + DEG_id_tag_update(lcd->ob->data, DEG_TAG_SELECT_UPDATE); WM_event_add_notifier(C, NC_GEOM | ND_SELECT, lcd->ob->data); } } @@ -868,7 +870,7 @@ static int loopcut_modal(bContext *C, wmOperator *op, const wmEvent *event) if (cuts != lcd->cuts) { /* allow zero so you can backspace and type in a value * otherwise 1 as minimum would make more sense */ - lcd->cuts = CLAMPIS(cuts, 0, SUBD_CUTS_MAX); + lcd->cuts = clamp_i(cuts, 0, SUBD_CUTS_MAX); RNA_int_set(op->ptr, "number_cuts", (int)lcd->cuts); ringsel_find_edge(lcd, (int)lcd->cuts); show_cuts = true; @@ -876,7 +878,7 @@ static int loopcut_modal(bContext *C, wmOperator *op, const wmEvent *event) } if (smoothness != lcd->smoothness) { - lcd->smoothness = CLAMPIS(smoothness, -SUBD_SMOOTH_MAX, SUBD_SMOOTH_MAX); + lcd->smoothness = clamp_f(smoothness, -SUBD_SMOOTH_MAX, SUBD_SMOOTH_MAX); RNA_float_set(op->ptr, "smoothness", lcd->smoothness); show_cuts = true; ED_region_tag_redraw(lcd->ar); diff --git a/source/blender/editors/mesh/editmesh_select.c b/source/blender/editors/mesh/editmesh_select.c index 634c65485e9..99a95c27b7b 100644 --- a/source/blender/editors/mesh/editmesh_select.c +++ b/source/blender/editors/mesh/editmesh_select.c @@ -1414,6 +1414,7 @@ static int edbm_select_similar_region_exec(bContext *C, wmOperator *op) MEM_freeN(group_index); if (changed) { + DEG_id_tag_update(obedit->data, DEG_TAG_SELECT_UPDATE); WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data); } else { @@ -1621,6 +1622,7 @@ static int edbm_loop_multiselect_exec(bContext *C, wmOperator *op) MEM_freeN(edarray); // if (EM_texFaceCheck()) + DEG_id_tag_update(obedit->data, DEG_TAG_SELECT_UPDATE); WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data); } MEM_freeN(objects); @@ -1824,6 +1826,7 @@ static bool mouse_mesh_loop(bContext *C, const int mval[2], bool extend, bool de } } + DEG_id_tag_update(vc.obedit->data, DEG_TAG_SELECT_UPDATE); WM_event_add_notifier(C, NC_GEOM | ND_SELECT, vc.obedit->data); return true; @@ -1930,6 +1933,7 @@ static int edbm_select_all_exec(bContext *C, wmOperator *op) EDBM_selectmode_flush(em); break; } + DEG_id_tag_update(obedit->data, DEG_TAG_SELECT_UPDATE); WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data); } @@ -1975,6 +1979,7 @@ static int edbm_faces_select_interior_exec(bContext *C, wmOperator *UNUSED(op)) continue; } + DEG_id_tag_update(obedit->data, DEG_TAG_SELECT_UPDATE); WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data); } MEM_freeN(objects); @@ -2032,6 +2037,7 @@ bool EDBM_select_pick(bContext *C, const int mval[2], bool extend, bool deselect Object *ob_iter = objects[ob_index]; EDBM_flag_disable_all(BKE_editmesh_from_object(ob_iter), BM_ELEM_SELECT); if (basact->object != ob_iter) { + DEG_id_tag_update(ob_iter->data, DEG_TAG_SELECT_UPDATE); WM_event_add_notifier(C, NC_GEOM | ND_SELECT, ob_iter->data); } } @@ -2150,8 +2156,10 @@ bool EDBM_select_pick(bContext *C, const int mval[2], bool extend, bool deselect * switch UV layers, vgroups for eg. */ if (vc.view_layer->basact != basact) { vc.view_layer->basact = basact; + DEG_id_tag_update(&vc.scene->id, DEG_TAG_SELECT_UPDATE); WM_event_add_notifier(C, NC_SCENE | ND_OB_ACTIVE, vc.scene); } + DEG_id_tag_update(vc.obedit->data, DEG_TAG_SELECT_UPDATE); WM_event_add_notifier(C, NC_GEOM | ND_SELECT, vc.obedit->data); return true; @@ -2482,7 +2490,7 @@ bool EDBM_selectmode_toggle( Object *ob_iter = objects[ob_index]; BMEditMesh *em_iter = BKE_editmesh_from_object(ob_iter); EDBM_selectmode_set(em_iter); - DEG_id_tag_update(ob_iter->data, DEG_TAG_COPY_ON_WRITE); + DEG_id_tag_update(ob_iter->data, DEG_TAG_COPY_ON_WRITE | DEG_TAG_SELECT_UPDATE); WM_event_add_notifier(C, NC_GEOM | ND_SELECT, ob_iter->data); } WM_main_add_notifier(NC_SCENE | ND_TOOLSETTINGS, NULL); @@ -2932,6 +2940,7 @@ static int edbm_select_linked_exec(bContext *C, wmOperator *op) select_linked_delimit_end(em); } + DEG_id_tag_update(obedit->data, DEG_TAG_SELECT_UPDATE); WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data); } @@ -3143,6 +3152,7 @@ static int edbm_select_linked_pick_invoke(bContext *C, wmOperator *op, const wmE * index selections isn't very common. */ RNA_int_set(op->ptr, "index", index); + DEG_id_tag_update(basact->object->data, DEG_TAG_SELECT_UPDATE); WM_event_add_notifier(C, NC_GEOM | ND_SELECT, basact->object->data); return OPERATOR_FINISHED; @@ -3172,6 +3182,7 @@ static int edbm_select_linked_pick_exec(bContext *C, wmOperator *op) edbm_select_linked_pick_ex(em, ele, sel, delimit); + DEG_id_tag_update(obedit->data, DEG_TAG_SELECT_UPDATE); WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data); return OPERATOR_FINISHED; @@ -3260,6 +3271,7 @@ static int edbm_select_face_by_sides_exec(bContext *C, wmOperator *op) EDBM_selectmode_flush(em); + DEG_id_tag_update(obedit->data, DEG_TAG_SELECT_UPDATE); WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data); } @@ -3357,6 +3369,7 @@ static int edbm_select_loose_exec(bContext *C, wmOperator *op) EDBM_selectmode_flush(em); + DEG_id_tag_update(obedit->data, DEG_TAG_SELECT_UPDATE); WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data); } @@ -3420,6 +3433,8 @@ static int edbm_select_mirror_exec(bContext *C, wmOperator *op) if (tot_mirr_iter) { EDBM_selectmode_flush(em); + + DEG_id_tag_update(obedit->data, DEG_TAG_SELECT_UPDATE); WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data); } @@ -3480,6 +3495,7 @@ static int edbm_select_more_exec(bContext *C, wmOperator *op) } EDBM_select_more(em, use_face_step); + DEG_id_tag_update(obedit->data, DEG_TAG_SELECT_UPDATE); WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data); } @@ -3530,6 +3546,7 @@ static int edbm_select_less_exec(bContext *C, wmOperator *op) } EDBM_select_less(em, use_face_step); + DEG_id_tag_update(obedit->data, DEG_TAG_SELECT_UPDATE); WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data); } @@ -3855,6 +3872,7 @@ static int edbm_select_sharp_edges_exec(bContext *C, wmOperator *op) else { EDBM_selectmode_flush(em); } + DEG_id_tag_update(obedit->data, DEG_TAG_SELECT_UPDATE); WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data); } MEM_freeN(objects); @@ -3953,6 +3971,7 @@ static int edbm_select_linked_flat_faces_exec(bContext *C, wmOperator *op) BLI_LINKSTACK_FREE(stack); + DEG_id_tag_update(obedit->data, DEG_TAG_SELECT_UPDATE); WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data); } MEM_freeN(objects); @@ -4049,6 +4068,7 @@ static int edbm_select_non_manifold_exec(bContext *C, wmOperator *op) } } + DEG_id_tag_update(obedit->data, DEG_TAG_SELECT_UPDATE); WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data); EDBM_selectmode_flush(em); @@ -4152,6 +4172,7 @@ static int edbm_select_random_exec(bContext *C, wmOperator *op) EDBM_deselect_flush(em); } + DEG_id_tag_update(obedit->data, DEG_TAG_SELECT_UPDATE); WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data); } @@ -4246,6 +4267,7 @@ static int edbm_select_ungrouped_exec(bContext *C, wmOperator *op) if (changed) { EDBM_selectmode_flush(em); + DEG_id_tag_update(obedit->data, DEG_TAG_SELECT_UPDATE); WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data); } } @@ -4418,6 +4440,7 @@ static int edbm_region_to_loop_exec(bContext *C, wmOperator *UNUSED(op)) EDBM_selectmode_to_scene(C); } + DEG_id_tag_update(obedit->data, DEG_TAG_SELECT_UPDATE); WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data); } MEM_freeN(objects); @@ -4625,6 +4648,7 @@ static int edbm_loop_to_region_exec(bContext *C, wmOperator *op) EDBM_selectmode_flush(em); + DEG_id_tag_update(obedit->data, DEG_TAG_SELECT_UPDATE); WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data); } MEM_freeN(objects); diff --git a/source/blender/editors/mesh/editmesh_tools.c b/source/blender/editors/mesh/editmesh_tools.c index bbeb80fa8af..15840f8f9d6 100644 --- a/source/blender/editors/mesh/editmesh_tools.c +++ b/source/blender/editors/mesh/editmesh_tools.c @@ -104,13 +104,13 @@ static int edbm_subdivide_exec(bContext *C, wmOperator *op) const float fractal = RNA_float_get(op->ptr, "fractal") / 2.5f; const float along_normal = RNA_float_get(op->ptr, "fractal_along_normal"); - if (RNA_boolean_get(op->ptr, "quadtri") && + if (RNA_boolean_get(op->ptr, "ngon") && RNA_enum_get(op->ptr, "quadcorner") == SUBD_CORNER_STRAIGHT_CUT) { RNA_enum_set(op->ptr, "quadcorner", SUBD_CORNER_INNERVERT); } const int quad_corner_type = RNA_enum_get(op->ptr, "quadcorner"); - const bool use_quad_tri = RNA_boolean_get(op->ptr, "quadtri"); + const bool use_quad_tri = !RNA_boolean_get(op->ptr, "ngon"); const int seed = RNA_int_get(op->ptr, "seed"); ViewLayer *view_layer = CTX_data_view_layer(C); @@ -176,7 +176,7 @@ void MESH_OT_subdivide(wmOperatorType *ot) WM_operatortype_props_advanced_begin(ot); - RNA_def_boolean(ot->srna, "quadtri", 0, "Quad/Tri Mode", "Tries to prevent ngons"); + RNA_def_boolean(ot->srna, "ngon", true, "Create N-Gons", "When disabled, newly created faces are limited to 3-4 sided faces"); RNA_def_enum(ot->srna, "quadcorner", prop_mesh_cornervert_types, SUBD_CORNER_STRAIGHT_CUT, "Quad Corner Type", "How to subdivide quad corners (anything other than Straight Cut will prevent ngons)"); @@ -518,6 +518,7 @@ void MESH_OT_delete(wmOperatorType *ot) /* props */ ot->prop = RNA_def_enum(ot->srna, "type", prop_mesh_delete_types, MESH_DELETE_VERT, "Type", "Method used for deleting mesh data"); + RNA_def_property_flag(ot->prop, PROP_HIDDEN | PROP_SKIP_SAVE); } /** \} */ @@ -1036,7 +1037,7 @@ void MESH_OT_mark_seam(wmOperatorType *ot) ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; prop = RNA_def_boolean(ot->srna, "clear", 0, "Clear", ""); - RNA_def_property_flag(prop, PROP_SKIP_SAVE); + RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE); WM_operatortype_props_advanced_begin(ot); } @@ -1109,7 +1110,7 @@ void MESH_OT_mark_sharp(wmOperatorType *ot) ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; prop = RNA_def_boolean(ot->srna, "clear", false, "Clear", ""); - RNA_def_property_flag(prop, PROP_SKIP_SAVE); + RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE); prop = RNA_def_boolean(ot->srna, "use_verts", false, "Vertices", "Consider vertices instead of edges to select which edges to (un)tag as sharp"); RNA_def_property_flag(prop, PROP_SKIP_SAVE); @@ -3647,7 +3648,7 @@ static Base *mesh_separate_tagged(Main *bmain, Scene *scene, ViewLayer *view_lay BM_mesh_normals_update(bm_new); - BM_mesh_bm_to_me(bm_new, base_new->object->data, (&(struct BMeshToMeshParams){0})); + BM_mesh_bm_to_me(bmain, bm_new, base_new->object->data, (&(struct BMeshToMeshParams){0})); BM_mesh_free(bm_new); ((Mesh *)base_new->object->data)->edit_btmesh = NULL; @@ -3960,7 +3961,7 @@ static int edbm_separate_exec(bContext *C, wmOperator *op) if (retval_iter) { BM_mesh_bm_to_me( - bm_old, me, + bmain, bm_old, me, (&(struct BMeshToMeshParams){ .calc_object_remap = true, })); @@ -6835,7 +6836,7 @@ void MESH_OT_mark_freestyle_edge(wmOperatorType *ot) ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; prop = RNA_def_boolean(ot->srna, "clear", false, "Clear", ""); - RNA_def_property_flag(prop, PROP_SKIP_SAVE); + RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE); } /** \} */ @@ -6918,7 +6919,7 @@ void MESH_OT_mark_freestyle_face(wmOperatorType *ot) ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; prop = RNA_def_boolean(ot->srna, "clear", false, "Clear", ""); - RNA_def_property_flag(prop, PROP_SKIP_SAVE); + RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE); } /** \} */ diff --git a/source/blender/editors/mesh/editmesh_undo.c b/source/blender/editors/mesh/editmesh_undo.c index 6fb7a713ce0..33864cd1e95 100644 --- a/source/blender/editors/mesh/editmesh_undo.c +++ b/source/blender/editors/mesh/editmesh_undo.c @@ -511,8 +511,8 @@ static void *undomesh_from_editmesh(UndoMesh *um, BMEditMesh *em, Key *key) /* BM_mesh_validate(em->bm); */ /* for troubleshooting */ BM_mesh_bm_to_me( - em->bm, &um->me, (&(struct BMeshToMeshParams){ - /* Undo code should not be manipulating 'G.main->object' hooks/vertex-parent. */ + NULL, em->bm, &um->me, (&(struct BMeshToMeshParams){ + /* Undo code should not be manipulating 'G_MAIN->object' hooks/vertex-parent. */ .calc_object_remap = false, .cd_mask_extra = CD_MASK_SHAPE_KEYINDEX, })); diff --git a/source/blender/editors/mesh/editmesh_utils.c b/source/blender/editors/mesh/editmesh_utils.c index 16c1a2c45ec..9524d1b0791 100644 --- a/source/blender/editors/mesh/editmesh_utils.c +++ b/source/blender/editors/mesh/editmesh_utils.c @@ -43,6 +43,7 @@ #include "BKE_DerivedMesh.h" #include "BKE_context.h" +#include "BKE_main.h" #include "BKE_mesh.h" #include "BKE_mesh_mapping.h" #include "BKE_report.h" @@ -172,6 +173,10 @@ bool EDBM_op_finish(BMEditMesh *em, BMOperator *bmop, wmOperator *op, const bool BKE_editmesh_tessface_calc(em); } + if (em->ob) { + DEG_id_tag_update(&((Mesh *)em->ob->data)->id, DEG_TAG_COPY_ON_WRITE); + } + return false; } else { @@ -326,7 +331,7 @@ void EDBM_mesh_make(Object *ob, const int select_mode, const bool add_key_index) * \warning This can invalidate the #DerivedMesh cache of other objects (for linked duplicates). * Most callers should run #DEG_id_tag_update on \a ob->data, see: T46738, T46913 */ -void EDBM_mesh_load(Object *ob) +void EDBM_mesh_load(Main *bmain, Object *ob) { Mesh *me = ob->data; BMesh *bm = me->edit_btmesh->bm; @@ -338,7 +343,7 @@ void EDBM_mesh_load(Object *ob) } BM_mesh_bm_to_me( - bm, me, (&(struct BMeshToMeshParams){ + bmain, bm, me, (&(struct BMeshToMeshParams){ .calc_object_remap = true, })); @@ -358,7 +363,7 @@ void EDBM_mesh_load(Object *ob) * cycles. */ #if 0 - for (Object *other_object = G.main->object.first; + for (Object *other_object = bmain->object.first; other_object != NULL; other_object = other_object->id.next) { diff --git a/source/blender/editors/mesh/mesh_data.c b/source/blender/editors/mesh/mesh_data.c index d2410c7d97b..46b84f328cc 100644 --- a/source/blender/editors/mesh/mesh_data.c +++ b/source/blender/editors/mesh/mesh_data.c @@ -538,6 +538,7 @@ void MESH_OT_uv_texture_add(wmOperatorType *ot) static int drop_named_image_invoke(bContext *C, wmOperator *op, const wmEvent *event) { + Main *bmain = CTX_data_main(C); Scene *scene = CTX_data_scene(C); View3D *v3d = CTX_wm_view3d(C); Base *base; @@ -578,7 +579,7 @@ static int drop_named_image_invoke(bContext *C, wmOperator *op, const wmEvent *e return OPERATOR_CANCELLED; if (exitmode) { - EDBM_mesh_load(obedit); + EDBM_mesh_load(bmain, obedit); EDBM_mesh_free(me->edit_btmesh); MEM_freeN(me->edit_btmesh); me->edit_btmesh = NULL; diff --git a/source/blender/editors/mesh/meshtools.c b/source/blender/editors/mesh/meshtools.c index 41e1ca13b79..6c8de1a481e 100644 --- a/source/blender/editors/mesh/meshtools.c +++ b/source/blender/editors/mesh/meshtools.c @@ -373,7 +373,7 @@ int join_mesh_exec(bContext *C, wmOperator *op) } else if (haskey) { /* add a new key-block and add to the mesh */ - key = me->key = BKE_key_add((ID *)me); + key = me->key = BKE_key_add(bmain, (ID *)me); key->type = KEY_RELATIVE; } @@ -593,6 +593,7 @@ int join_mesh_exec(bContext *C, wmOperator *op) DEG_id_tag_update(&ob->id, OB_RECALC_OB | OB_RECALC_DATA); + DEG_id_tag_update(&scene->id, DEG_TAG_SELECT_UPDATE); WM_event_add_notifier(C, NC_SCENE | ND_OB_ACTIVE, scene); return OPERATOR_FINISHED; @@ -605,6 +606,7 @@ int join_mesh_exec(bContext *C, wmOperator *op) int join_mesh_shapes_exec(bContext *C, wmOperator *op) { + Main *bmain = CTX_data_main(C); Scene *scene = CTX_data_scene(C); Object *ob = CTX_data_active_object(C); Depsgraph *depsgraph = CTX_data_depsgraph(C); @@ -639,7 +641,7 @@ int join_mesh_shapes_exec(bContext *C, wmOperator *op) } if (key == NULL) { - key = me->key = BKE_key_add((ID *)me); + key = me->key = BKE_key_add(bmain, (ID *)me); key->type = KEY_RELATIVE; /* first key added, so it was the basis. initialize it with the existing mesh */ @@ -670,6 +672,7 @@ int join_mesh_shapes_exec(bContext *C, wmOperator *op) } CTX_DATA_END; + DEG_id_tag_update(&scene->id, DEG_TAG_SELECT_UPDATE); WM_event_add_notifier(C, NC_SCENE | ND_OB_ACTIVE, scene); return OPERATOR_FINISHED; diff --git a/source/blender/editors/metaball/mball_edit.c b/source/blender/editors/metaball/mball_edit.c index 65bf258f334..1ae122a3801 100644 --- a/source/blender/editors/metaball/mball_edit.c +++ b/source/blender/editors/metaball/mball_edit.c @@ -154,6 +154,7 @@ static int mball_select_all_exec(bContext *C, wmOperator *op) break; } + DEG_id_tag_update(&mb->id, DEG_TAG_SELECT_UPDATE); WM_event_add_notifier(C, NC_GEOM | ND_SELECT, mb); return OPERATOR_FINISHED; @@ -335,6 +336,7 @@ static int mball_select_similar_exec(bContext *C, wmOperator *op) } if (changed) { + DEG_id_tag_update(&mb->id, DEG_TAG_SELECT_UPDATE); WM_event_add_notifier(C, NC_GEOM | ND_SELECT, mb); } @@ -403,6 +405,7 @@ static int select_random_metaelems_exec(bContext *C, wmOperator *op) BLI_rng_free(rng); + DEG_id_tag_update(&mb->id, DEG_TAG_SELECT_UPDATE); WM_event_add_notifier(C, NC_GEOM | ND_SELECT, mb); } MEM_freeN(objects); @@ -614,7 +617,9 @@ bool ED_mball_select_pick(bContext *C, const int mval[2], bool extend, bool dese BLI_rcti_init_pt_radius(&rect, mval, 12); - hits = view3d_opengl_select(&vc, buffer, MAXPICKBUF, &rect, VIEW3D_SELECT_PICK_NEAREST); + hits = view3d_opengl_select( + &vc, buffer, MAXPICKBUF, &rect, + VIEW3D_SELECT_PICK_NEAREST, VIEW3D_SELECT_FILTER_NOP); /* does startelem exist? */ ml = mb->editelems->first; @@ -670,6 +675,7 @@ bool ED_mball_select_pick(bContext *C, const int mval[2], bool extend, bool dese mb->lastelem = ml_act; + DEG_id_tag_update(&mb->id, DEG_TAG_SELECT_UPDATE); WM_event_add_notifier(C, NC_GEOM | ND_SELECT, mb); return true; @@ -678,5 +684,3 @@ bool ED_mball_select_pick(bContext *C, const int mval[2], bool extend, bool dese return false; } - - diff --git a/source/blender/editors/object/object_add.c b/source/blender/editors/object/object_add.c index 9ce7f556448..dd358b95722 100644 --- a/source/blender/editors/object/object_add.c +++ b/source/blender/editors/object/object_add.c @@ -931,6 +931,7 @@ static int empty_drop_named_image_invoke(bContext *C, wmOperator *op, const wmEv /* if empty under cursor, then set object */ if (base && base->object->type == OB_EMPTY) { ob = base->object; + DEG_id_tag_update(&scene->id, DEG_TAG_SELECT_UPDATE); WM_event_add_notifier(C, NC_SCENE | ND_OB_ACTIVE, scene); } else { @@ -1098,6 +1099,7 @@ static int collection_instance_add_exec(bContext *C, wmOperator *op) DEG_relations_tag_update(bmain); DEG_id_tag_update(&collection->id, 0); + DEG_id_tag_update(&scene->id, DEG_TAG_SELECT_UPDATE); WM_event_add_notifier(C, NC_SCENE | ND_OB_ACTIVE, scene); return OPERATOR_FINISHED; @@ -1294,6 +1296,7 @@ static int object_delete_exec(bContext *C, wmOperator *op) DEG_relations_tag_update(bmain); + DEG_id_tag_update(&scene->id, DEG_TAG_SELECT_UPDATE); WM_event_add_notifier(C, NC_SCENE | ND_OB_ACTIVE, scene); WM_event_add_notifier(C, NC_SCENE | ND_LAYER_CONTENT, scene); } @@ -1846,7 +1849,7 @@ static int convert_exec(bContext *C, wmOperator *op) * datablock, but for until we've got granular update * lets take care by selves. */ - BKE_vfont_to_curve(bmain, newob, FO_EDIT); + BKE_vfont_to_curve(newob, FO_EDIT); newob->type = OB_CURVE; cu->type = OB_CURVE; @@ -2018,6 +2021,7 @@ static int convert_exec(bContext *C, wmOperator *op) } DEG_relations_tag_update(bmain); + DEG_id_tag_update(&scene->id, DEG_TAG_SELECT_UPDATE); WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, scene); WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene); @@ -2098,7 +2102,7 @@ static Base *object_add_duplicate_internal(Main *bmain, Scene *scene, ViewLayer /* duplicates using userflags */ if (dupflag & USER_DUP_ACT) { - BKE_animdata_copy_id_action(&obn->id, true); + BKE_animdata_copy_id_action(bmain, &obn->id, true); } if (dupflag & USER_DUP_MAT) { @@ -2112,7 +2116,7 @@ static Base *object_add_duplicate_internal(Main *bmain, Scene *scene, ViewLayer id_us_min(id); if (dupflag & USER_DUP_ACT) { - BKE_animdata_copy_id_action(&obn->mat[a]->id, true); + BKE_animdata_copy_id_action(bmain, &obn->mat[a]->id, true); } } } @@ -2128,7 +2132,7 @@ static Base *object_add_duplicate_internal(Main *bmain, Scene *scene, ViewLayer } if (dupflag & USER_DUP_ACT) { - BKE_animdata_copy_id_action(&psys->part->id, true); + BKE_animdata_copy_id_action(bmain, &psys->part->id, true); } id_us_min(id); @@ -2256,9 +2260,9 @@ static Base *object_add_duplicate_internal(Main *bmain, Scene *scene, ViewLayer } if (dupflag & USER_DUP_ACT) { - BKE_animdata_copy_id_action((ID *)obn->data, true); + BKE_animdata_copy_id_action(bmain, (ID *)obn->data, true); if (key) { - BKE_animdata_copy_id_action((ID *)key, true); + BKE_animdata_copy_id_action(bmain, (ID *)key, true); } } @@ -2353,8 +2357,7 @@ static int duplicate_exec(bContext *C, wmOperator *op) BKE_main_id_clear_newpoins(bmain); DEG_relations_tag_update(bmain); - /* TODO(sergey): Use proper flag for tagging here. */ - DEG_id_tag_update(&scene->id, 0); + DEG_id_tag_update(&scene->id, DEG_TAG_COPY_ON_WRITE | DEG_TAG_SELECT_UPDATE); WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene); @@ -2436,6 +2439,7 @@ static int add_named_exec(bContext *C, wmOperator *op) /* TODO(sergey): Only update relations for the current scene. */ DEG_relations_tag_update(bmain); + DEG_id_tag_update(&scene->id, DEG_TAG_SELECT_UPDATE); WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene); WM_event_add_notifier(C, NC_SCENE | ND_OB_ACTIVE, scene); diff --git a/source/blender/editors/object/object_data_transfer.c b/source/blender/editors/object/object_data_transfer.c index db81c51cc90..788f0826848 100644 --- a/source/blender/editors/object/object_data_transfer.c +++ b/source/blender/editors/object/object_data_transfer.c @@ -40,7 +40,6 @@ #include "BKE_context.h" #include "BKE_data_transfer.h" -#include "BKE_DerivedMesh.h" #include "BKE_mesh_mapping.h" #include "BKE_mesh_remap.h" #include "BKE_mesh_runtime.h" @@ -137,20 +136,17 @@ static const EnumPropertyItem *dt_layers_select_src_itemf( Scene *scene = CTX_data_scene(C); if (ob_src) { - DerivedMesh *dm_src; - CustomData *ldata; + Mesh *me_eval; int num_data, i; - /* XXX Is this OK? */ - dm_src = mesh_get_derived_final(depsgraph, scene, ob_src, CD_MASK_BAREMESH | CD_MLOOPUV); - ldata = dm_src->getLoopDataLayout(dm_src); - num_data = CustomData_number_of_layers(ldata, CD_MLOOPUV); + me_eval = mesh_get_eval_final(depsgraph, scene, ob_src, CD_MASK_BAREMESH | CD_MLOOPUV); + num_data = CustomData_number_of_layers(&me_eval->ldata, CD_MLOOPUV); RNA_enum_item_add_separator(&item, &totitem); for (i = 0; i < num_data; i++) { tmp_item.value = i; - tmp_item.identifier = tmp_item.name = CustomData_get_layer_name(ldata, CD_MLOOPUV, i); + tmp_item.identifier = tmp_item.name = CustomData_get_layer_name(&me_eval->ldata, CD_MLOOPUV, i); RNA_enum_item_add(&item, &totitem, &tmp_item); } } @@ -160,20 +156,17 @@ static const EnumPropertyItem *dt_layers_select_src_itemf( Scene *scene = CTX_data_scene(C); if (ob_src) { - DerivedMesh *dm_src; - CustomData *ldata; + Mesh *me_eval; int num_data, i; - /* XXX Is this OK? */ - dm_src = mesh_get_derived_final(depsgraph, scene, ob_src, CD_MASK_BAREMESH | CD_MLOOPCOL); - ldata = dm_src->getLoopDataLayout(dm_src); - num_data = CustomData_number_of_layers(ldata, CD_MLOOPCOL); + me_eval = mesh_get_eval_final(depsgraph, scene, ob_src, CD_MASK_BAREMESH | CD_MLOOPCOL); + num_data = CustomData_number_of_layers(&me_eval->ldata, CD_MLOOPCOL); RNA_enum_item_add_separator(&item, &totitem); for (i = 0; i < num_data; i++) { tmp_item.value = i; - tmp_item.identifier = tmp_item.name = CustomData_get_layer_name(ldata, CD_MLOOPCOL, i); + tmp_item.identifier = tmp_item.name = CustomData_get_layer_name(&me_eval->ldata, CD_MLOOPCOL, i); RNA_enum_item_add(&item, &totitem, &tmp_item); } } diff --git a/source/blender/editors/object/object_edit.c b/source/blender/editors/object/object_edit.c index b7f59285186..f050297ee2f 100644 --- a/source/blender/editors/object/object_edit.c +++ b/source/blender/editors/object/object_edit.c @@ -146,6 +146,228 @@ Object *ED_object_active_context(bContext *C) return ob; } +/* ********************** object hiding *************************** */ + +static int object_hide_poll(bContext *C) +{ + if (CTX_wm_space_outliner(C) != NULL) { + return ED_outliner_collections_editor_poll(C); + } + else { + return ED_operator_view3d_active(C); + } +} + +static int object_hide_view_clear_exec(bContext *C, wmOperator *op) +{ + Scene *scene = CTX_data_scene(C); + ViewLayer *view_layer = CTX_data_view_layer(C); + const bool select = RNA_boolean_get(op->ptr, "select"); + bool changed = false; + + for (Base *base = view_layer->object_bases.first; base; base = base->next) { + if (base->flag & BASE_HIDE) { + base->flag &= ~BASE_HIDE; + changed = true; + + if (select) { + ED_object_base_select(base, BA_SELECT); + } + } + } + + if (!changed) { + return OPERATOR_CANCELLED; + } + + BKE_layer_collection_sync(scene, view_layer); + DEG_id_tag_update(&scene->id, DEG_TAG_BASE_FLAGS_UPDATE); + WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene); + + return OPERATOR_FINISHED; +} + +void OBJECT_OT_hide_view_clear(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Show Hidden Objects"; + ot->description = "Reveal temporarily hidden objects"; + ot->idname = "OBJECT_OT_hide_view_clear"; + + /* api callbacks */ + ot->exec = object_hide_view_clear_exec; + ot->poll = object_hide_poll; + + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + + PropertyRNA *prop = RNA_def_boolean(ot->srna, "select", false, "Select", ""); + RNA_def_property_flag(prop, PROP_SKIP_SAVE | PROP_HIDDEN); +} + +static int object_hide_view_set_exec(bContext *C, wmOperator *op) +{ + Scene *scene = CTX_data_scene(C); + ViewLayer *view_layer = CTX_data_view_layer(C); + const bool unselected = RNA_boolean_get(op->ptr, "unselected"); + bool changed = false; + + for (Base *base = view_layer->object_bases.first; base; base = base->next) { + if (!(base->flag & BASE_VISIBLED)) { + continue; + } + + if (!unselected) { + if (base->flag & BASE_SELECTED) { + ED_object_base_select(base, BA_DESELECT); + base->flag |= BASE_HIDE; + changed = true; + } + } + else { + if (!(base->flag & BASE_SELECTED)) { + ED_object_base_select(base, BA_DESELECT); + base->flag |= BASE_HIDE; + changed = true; + } + } + } + + if (!changed) { + return OPERATOR_CANCELLED; + } + + BKE_layer_collection_sync(scene, view_layer); + DEG_id_tag_update(&scene->id, DEG_TAG_BASE_FLAGS_UPDATE); + WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene); + + return OPERATOR_FINISHED; +} + +void OBJECT_OT_hide_view_set(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Hide Objects"; + ot->description = "Temporarily hide objects from the viewport"; + ot->idname = "OBJECT_OT_hide_view_set"; + + /* api callbacks */ + ot->exec = object_hide_view_set_exec; + ot->poll = object_hide_poll; + + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + + PropertyRNA *prop; + prop = RNA_def_boolean(ot->srna, "unselected", 0, "Unselected", "Hide unselected rather than selected objects"); + RNA_def_property_flag(prop, PROP_SKIP_SAVE | PROP_HIDDEN); +} + +static int object_hide_collection_exec(bContext *C, wmOperator *op) +{ + int index = RNA_int_get(op->ptr, "collection_index"); + bool extend = (CTX_wm_window(C)->eventstate->shift != 0); + + if (CTX_wm_window(C)->eventstate->alt != 0) { + index += 10; + } + + Scene *scene = CTX_data_scene(C); + ViewLayer *view_layer = CTX_data_view_layer(C); + LayerCollection *lc = BKE_layer_collection_from_index(view_layer, index); + + if (!lc) { + return OPERATOR_CANCELLED; + } + + BKE_layer_collection_set_visible(scene, view_layer, lc, extend); + + DEG_id_tag_update(&scene->id, DEG_TAG_BASE_FLAGS_UPDATE); + WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene); + + return OPERATOR_FINISHED; +} + +#define COLLECTION_INVALID_INDEX -1 + +void ED_hide_collections_menu_draw(const bContext *C, uiLayout *layout) +{ + ViewLayer *view_layer = CTX_data_view_layer(C); + LayerCollection *lc_scene = view_layer->layer_collections.first; + + uiLayoutSetOperatorContext(layout, WM_OP_EXEC_REGION_WIN); + + for (LayerCollection *lc = lc_scene->layer_collections.first; lc; lc = lc->next) { + int index = BKE_layer_collection_findindex(view_layer, lc); + uiLayout *row = uiLayoutRow(layout, false); + + if (lc->collection->flag & COLLECTION_RESTRICT_VIEW) { + continue; + } + + if ((view_layer->runtime_flag & VIEW_LAYER_HAS_HIDE) && + !(lc->runtime_flag & LAYER_COLLECTION_HAS_VISIBLE_OBJECTS)) { + uiLayoutSetActive(row, false); + } + + int icon = ICON_NONE; + if (BKE_layer_collection_has_selected_objects(view_layer, lc)) { + icon = ICON_LAYER_ACTIVE; + } + else if (lc->runtime_flag & LAYER_COLLECTION_HAS_OBJECTS) { + icon = ICON_LAYER_USED; + } + + uiItemIntO(row, + lc->collection->id.name + 2, + icon, + "OBJECT_OT_hide_collection", + "collection_index", + index); + } +} + +static int object_hide_collection_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) +{ + /* Immediately execute if collection index was specified. */ + int index = RNA_int_get(op->ptr, "collection_index"); + if (index != COLLECTION_INVALID_INDEX) { + return object_hide_collection_exec(C, op); + } + + /* Open popup menu. */ + const char *title = CTX_IFACE_(op->type->translation_context, op->type->name); + uiPopupMenu *pup = UI_popup_menu_begin(C, title, ICON_GROUP); + uiLayout *layout = UI_popup_menu_layout(pup); + + ED_hide_collections_menu_draw(C, layout); + + UI_popup_menu_end(C, pup); + + return OPERATOR_INTERFACE; +} + +void OBJECT_OT_hide_collection(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Hide Objects By Collection"; + ot->description = "Show only objects in collection (Shift to extend)"; + ot->idname = "OBJECT_OT_hide_collection"; + + /* api callbacks */ + ot->exec = object_hide_collection_exec; + ot->invoke = object_hide_collection_invoke; + ot->poll = ED_operator_view3d_active; + + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + + /* Properties. */ + PropertyRNA *prop; + prop = RNA_def_int(ot->srna, "collection_index", COLLECTION_INVALID_INDEX, COLLECTION_INVALID_INDEX, INT_MAX, + "Collection Index", "Index of the collection to change visibility", 0, INT_MAX); + RNA_def_property_flag(prop, PROP_SKIP_SAVE | PROP_HIDDEN); +} /* ******************* toggle editmode operator ***************** */ @@ -191,7 +413,7 @@ static bool ED_object_editmode_load_ex(Main *bmain, Object *obedit, const bool f return false; } - EDBM_mesh_load(obedit); + EDBM_mesh_load(bmain, obedit); if (freedata) { EDBM_mesh_free(me->edit_btmesh); @@ -1548,8 +1770,6 @@ bool ED_object_editmode_calc_active_center(Object *obedit, const bool select_onl return false; } -#define COLLECTION_INVALID_INDEX -1 - static int move_to_collection_poll(bContext *C) { if (CTX_wm_space_outliner(C) != NULL) { @@ -1631,7 +1851,7 @@ static int move_to_collection_exec(bContext *C, wmOperator *op) collection->id.name + 2); DEG_relations_tag_update(CTX_data_main(C)); - DEG_id_tag_update(&scene->id, 0); + DEG_id_tag_update(&scene->id, DEG_TAG_COPY_ON_WRITE | DEG_TAG_SELECT_UPDATE); WM_event_add_notifier(C, NC_SCENE | ND_LAYER, scene); WM_event_add_notifier(C, NC_SCENE | ND_OB_ACTIVE, scene); @@ -1870,4 +2090,3 @@ void OBJECT_OT_link_to_collection(wmOperatorType *ot) RNA_def_property_flag(prop, PROP_SKIP_SAVE); } -#undef COLLECTION_INVALID_INDEX diff --git a/source/blender/editors/object/object_hook.c b/source/blender/editors/object/object_hook.c index 31e8685e323..6a3cb9aa097 100644 --- a/source/blender/editors/object/object_hook.c +++ b/source/blender/editors/object/object_hook.c @@ -318,7 +318,7 @@ static bool object_hook_index_array(Main *bmain, Scene *scene, Object *obedit, BMEditMesh *em; - EDBM_mesh_load(obedit); + EDBM_mesh_load(bmain, obedit); EDBM_mesh_make(obedit, scene->toolsettings->selectmode, true); DEG_id_tag_update(obedit->data, 0); @@ -619,6 +619,7 @@ static int object_add_hook_newob_exec(bContext *C, wmOperator *op) Object *obedit = CTX_data_edit_object(C); if (add_hook_object(C, bmain, scene, view_layer, obedit, NULL, OBJECT_ADDHOOK_NEWOB, op->reports)) { + DEG_id_tag_update(&scene->id, DEG_TAG_SELECT_UPDATE); WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene); WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, obedit); return OPERATOR_FINISHED; @@ -889,6 +890,7 @@ static int object_hook_select_exec(bContext *C, wmOperator *op) /* select functionality */ object_hook_select(ob, hmd); + DEG_id_tag_update(ob->data, DEG_TAG_SELECT_UPDATE); WM_event_add_notifier(C, NC_GEOM | ND_SELECT, ob->data); return OPERATOR_FINISHED; diff --git a/source/blender/editors/object/object_intern.h b/source/blender/editors/object/object_intern.h index 18251a25b73..f7179912f52 100644 --- a/source/blender/editors/object/object_intern.h +++ b/source/blender/editors/object/object_intern.h @@ -76,6 +76,9 @@ void OBJECT_OT_drop_named_material(struct wmOperatorType *ot); void OBJECT_OT_unlink_data(struct wmOperatorType *ot); /* object_edit.c */ +void OBJECT_OT_hide_view_set(struct wmOperatorType *ot); +void OBJECT_OT_hide_view_clear(struct wmOperatorType *ot); +void OBJECT_OT_hide_collection(struct wmOperatorType *ot); void OBJECT_OT_mode_set(struct wmOperatorType *ot); void OBJECT_OT_mode_set_or_submode(struct wmOperatorType *ot); void OBJECT_OT_editmode_toggle(struct wmOperatorType *ot); diff --git a/source/blender/editors/object/object_modifier.c b/source/blender/editors/object/object_modifier.c index 1b9af3725ca..425a0acff17 100644 --- a/source/blender/editors/object/object_modifier.c +++ b/source/blender/editors/object/object_modifier.c @@ -119,7 +119,7 @@ ModifierData *ED_object_modifier_add(ReportList *reports, Main *bmain, Scene *sc /* don't need to worry about the new modifier's name, since that is set to the number * of particle systems which shouldn't have too many duplicates */ - new_md = object_add_particle_system(scene, ob, name); + new_md = object_add_particle_system(bmain, scene, ob, name); } else { /* get new modifier data to add */ @@ -524,7 +524,8 @@ int ED_object_modifier_convert(ReportList *UNUSED(reports), Main *bmain, Scene * return 1; } -static int modifier_apply_shape(ReportList *reports, Depsgraph *depsgraph, Scene *scene, Object *ob, ModifierData *md) +static int modifier_apply_shape( + Main *bmain, ReportList *reports, Depsgraph *depsgraph, Scene *scene, Object *ob, ModifierData *md) { const ModifierTypeInfo *mti = modifierType_getInfo(md->type); @@ -564,7 +565,7 @@ static int modifier_apply_shape(ReportList *reports, Depsgraph *depsgraph, Scene } if (key == NULL) { - key = me->key = BKE_key_add((ID *)me); + key = me->key = BKE_key_add(bmain, (ID *)me); key->type = KEY_RELATIVE; /* if that was the first key block added, then it was the basis. * Initialize it with the mesh, and add another for the modifier */ @@ -673,7 +674,7 @@ static int modifier_apply_obdata(ReportList *reports, Depsgraph *depsgraph, Scen } int ED_object_modifier_apply( - ReportList *reports, Depsgraph *depsgraph, + Main *bmain, ReportList *reports, Depsgraph *depsgraph, Scene *scene, Object *ob, ModifierData *md, int mode) { int prev_mode; @@ -702,7 +703,7 @@ int ED_object_modifier_apply( md->mode |= eModifierMode_Realtime; if (mode == MODIFIER_APPLY_SHAPE) { - if (!modifier_apply_shape(reports, depsgraph, scene, ob, md)) { + if (!modifier_apply_shape(bmain, reports, depsgraph, scene, ob, md)) { md->mode = prev_mode; return 0; } @@ -1017,13 +1018,14 @@ void OBJECT_OT_modifier_move_down(wmOperatorType *ot) static int modifier_apply_exec(bContext *C, wmOperator *op) { + Main *bmain = CTX_data_main(C); Depsgraph *depsgraph = CTX_data_depsgraph(C); Scene *scene = CTX_data_scene(C); Object *ob = ED_object_active_context(C); ModifierData *md = edit_modifier_property_get(op, ob, 0); int apply_as = RNA_enum_get(op->ptr, "apply_as"); - if (!md || !ED_object_modifier_apply(op->reports, depsgraph, scene, ob, md, apply_as)) { + if (!md || !ED_object_modifier_apply(bmain, op->reports, depsgraph, scene, ob, md, apply_as)) { return OPERATOR_CANCELLED; } diff --git a/source/blender/editors/object/object_ops.c b/source/blender/editors/object/object_ops.c index af572824068..89dd54b6f64 100644 --- a/source/blender/editors/object/object_ops.c +++ b/source/blender/editors/object/object_ops.c @@ -247,6 +247,10 @@ void ED_operatortypes_object(void) WM_operatortype_append(OBJECT_OT_data_transfer); WM_operatortype_append(OBJECT_OT_datalayout_transfer); WM_operatortype_append(OBJECT_OT_surfacedeform_bind); + + WM_operatortype_append(OBJECT_OT_hide_view_clear); + WM_operatortype_append(OBJECT_OT_hide_view_set); + WM_operatortype_append(OBJECT_OT_hide_collection); } void ED_operatormacros_object(void) @@ -289,11 +293,11 @@ void ED_keymap_object(wmKeyConfig *keyconf) keymap = WM_keymap_find(keyconf, "Object Non-modal", 0, 0); /* modes */ - kmi = WM_keymap_add_item(keymap, "OBJECT_OT_mode_set", TABKEY, KM_RELEASE, 0, 0); + kmi = WM_keymap_add_item(keymap, "OBJECT_OT_mode_set", TABKEY, KM_CLICK, 0, 0); RNA_enum_set(kmi->ptr, "mode", OB_MODE_EDIT); RNA_boolean_set(kmi->ptr, "toggle", true); - kmi = WM_keymap_add_menu_pie(keymap, "VIEW3D_PIE_object_mode", TABKEY, KM_CLICK_DRAG, 0, 0); + kmi = WM_keymap_add_menu_pie(keymap, "VIEW3D_MT_object_mode_pie", TABKEY, KM_CLICK_DRAG, 0, 0); WM_keymap_add_item(keymap, "OBJECT_OT_origin_set", CKEY, KM_PRESS, KM_ALT | KM_SHIFT | KM_CTRL, 0); @@ -404,6 +408,19 @@ void ED_keymap_object(wmKeyConfig *keyconf) WM_keymap_add_item(keymap, "OBJECT_OT_move_to_collection", MKEY, KM_PRESS, 0, 0); WM_keymap_add_item(keymap, "OBJECT_OT_link_to_collection", MKEY, KM_PRESS, KM_SHIFT, 0); + + kmi = WM_keymap_add_item(keymap, "OBJECT_OT_hide_view_clear", HKEY, KM_PRESS, KM_ALT, 0); + kmi = WM_keymap_add_item(keymap, "OBJECT_OT_hide_view_set", HKEY, KM_PRESS, 0, 0); + RNA_boolean_set(kmi->ptr, "unselected", false); + kmi = WM_keymap_add_item(keymap, "OBJECT_OT_hide_view_set", HKEY, KM_PRESS, KM_SHIFT, 0); + RNA_boolean_set(kmi->ptr, "unselected", true); + kmi = WM_keymap_add_item(keymap, "OBJECT_OT_hide_collection", HKEY, KM_PRESS, KM_CTRL, 0); + + /* Collection switching. */ + for (int i = 0; i < 10; i++) { + kmi = WM_keymap_add_item(keymap, "OBJECT_OT_hide_collection", ZEROKEY + i, KM_PRESS, KM_ANY, 0); + RNA_int_set(kmi->ptr, "collection_index", (i == 0) ? 10 : i); + } } void ED_keymap_proportional_cycle(struct wmKeyConfig *UNUSED(keyconf), struct wmKeyMap *keymap) diff --git a/source/blender/editors/object/object_relations.c b/source/blender/editors/object/object_relations.c index 4f441826bfd..a114b2cc6d5 100644 --- a/source/blender/editors/object/object_relations.c +++ b/source/blender/editors/object/object_relations.c @@ -145,7 +145,7 @@ static int vertex_parent_set_exec(bContext *C, wmOperator *op) Mesh *me = obedit->data; BMEditMesh *em; - EDBM_mesh_load(obedit); + EDBM_mesh_load(bmain, obedit); EDBM_mesh_make(obedit, scene->toolsettings->selectmode, true); DEG_id_tag_update(obedit->data, 0); @@ -1786,7 +1786,7 @@ static void single_obdata_users(Main *bmain, Scene *scene, ViewLayer *view_layer /* Needed to remap texcomesh below. */ me = ob->data = ID_NEW_SET(ob->data, BKE_mesh_copy(bmain, ob->data)); if (me->key) /* We do not need to set me->key->id.newid here... */ - BKE_animdata_copy_id_action((ID *)me->key, false); + BKE_animdata_copy_id_action(bmain, (ID *)me->key, false); break; case OB_MBALL: ob->data = ID_NEW_SET(ob->data, BKE_mball_copy(bmain, ob->data)); @@ -1798,12 +1798,12 @@ static void single_obdata_users(Main *bmain, Scene *scene, ViewLayer *view_layer ID_NEW_REMAP(cu->bevobj); ID_NEW_REMAP(cu->taperobj); if (cu->key) /* We do not need to set cu->key->id.newid here... */ - BKE_animdata_copy_id_action((ID *)cu->key, false); + BKE_animdata_copy_id_action(bmain, (ID *)cu->key, false); break; case OB_LATTICE: ob->data = lat = ID_NEW_SET(ob->data, BKE_lattice_copy(bmain, ob->data)); if (lat->key) /* We do not need to set lat->key->id.newid here... */ - BKE_animdata_copy_id_action((ID *)lat->key, false); + BKE_animdata_copy_id_action(bmain, (ID *)lat->key, false); break; case OB_ARMATURE: DEG_id_tag_update(&ob->id, OB_RECALC_DATA); @@ -1830,7 +1830,7 @@ static void single_obdata_users(Main *bmain, Scene *scene, ViewLayer *view_layer * AnimData structure, which is not what we want. * (sergey) */ - BKE_animdata_copy_id_action((ID *)ob->data, false); + BKE_animdata_copy_id_action(bmain, (ID *)ob->data, false); id_us_min(id); } @@ -1845,13 +1845,13 @@ static void single_obdata_users(Main *bmain, Scene *scene, ViewLayer *view_layer } } -static void single_object_action_users(Scene *scene, ViewLayer *view_layer, const int flag) +static void single_object_action_users(Main *bmain, Scene *scene, ViewLayer *view_layer, const int flag) { FOREACH_OBJECT_FLAG_BEGIN(scene, view_layer, flag, ob) { if (!ID_IS_LINKED(ob)) { DEG_id_tag_update(&ob->id, OB_RECALC_DATA); - BKE_animdata_copy_id_action(&ob->id, false); + BKE_animdata_copy_id_action(bmain, &ob->id, false); } } FOREACH_OBJECT_FLAG_END; @@ -1872,7 +1872,7 @@ static void single_mat_users(Main *bmain, Scene *scene, ViewLayer *view_layer, c if (ma->id.us > 1) { man = BKE_material_copy(bmain, ma); - BKE_animdata_copy_id_action(&man->id, false); + BKE_animdata_copy_id_action(bmain, &man->id, false); man->id.us = 0; assign_material(bmain, ob, man, a, BKE_MAT_ASSIGN_USERPREF); @@ -1916,7 +1916,7 @@ void ED_object_single_users(Main *bmain, Scene *scene, const bool full, const bo if (full) { single_obdata_users(bmain, scene, NULL, 0); - single_object_action_users(scene, NULL, 0); + single_object_action_users(bmain, scene, NULL, 0); single_mat_users_expand(bmain); } @@ -2457,7 +2457,7 @@ static int make_single_user_exec(bContext *C, wmOperator *op) } if (RNA_boolean_get(op->ptr, "animation")) { - single_object_action_users(scene, view_layer, flag); + single_object_action_users(bmain, scene, view_layer, flag); } BKE_main_id_clear_newpoins(bmain); diff --git a/source/blender/editors/object/object_select.c b/source/blender/editors/object/object_select.c index bac1ba0e37d..ce29125ac79 100644 --- a/source/blender/editors/object/object_select.c +++ b/source/blender/editors/object/object_select.c @@ -129,6 +129,7 @@ void ED_object_base_activate(bContext *C, Base *base) else { WM_event_add_notifier(C, NC_SCENE | ND_OB_ACTIVE, NULL); } + DEG_id_tag_update(&CTX_data_scene(C)->id, DEG_TAG_SELECT_UPDATE); } /********************** Selection Operators **********************/ @@ -172,7 +173,9 @@ static int object_select_by_type_exec(bContext *C, wmOperator *op) } CTX_DATA_END; - WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, CTX_data_scene(C)); + Scene *scene = CTX_data_scene(C); + DEG_id_tag_update(&scene->id, DEG_TAG_SELECT_UPDATE); + WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene); return OPERATOR_FINISHED; } @@ -365,7 +368,9 @@ void ED_object_select_linked_by_id(bContext *C, ID *id) } if (changed) { - WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, CTX_data_scene(C)); + Scene *scene = CTX_data_scene(C); + DEG_id_tag_update(&scene->id, DEG_TAG_SELECT_UPDATE); + WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene); } } @@ -439,6 +444,7 @@ static int object_select_linked_exec(bContext *C, wmOperator *op) return OPERATOR_CANCELLED; if (changed) { + DEG_id_tag_update(&scene->id, DEG_TAG_SELECT_UPDATE); WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene); return OPERATOR_FINISHED; } @@ -809,6 +815,7 @@ static int object_select_grouped_exec(bContext *C, wmOperator *op) } if (changed) { + DEG_id_tag_update(&scene->id, DEG_TAG_SELECT_UPDATE); WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene); return OPERATOR_FINISHED; } @@ -878,7 +885,9 @@ static int object_select_all_exec(bContext *C, wmOperator *op) } CTX_DATA_END; - WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, CTX_data_scene(C)); + Scene *scene = CTX_data_scene(C); + DEG_id_tag_update(&scene->id, DEG_TAG_SELECT_UPDATE); + WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene); return OPERATOR_FINISHED; } @@ -930,7 +939,9 @@ static int object_select_same_collection_exec(bContext *C, wmOperator *op) } CTX_DATA_END; - WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, CTX_data_scene(C)); + Scene *scene = CTX_data_scene(C); + DEG_id_tag_update(&scene->id, DEG_TAG_SELECT_UPDATE); + WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene); return OPERATOR_FINISHED; } @@ -986,6 +997,7 @@ static int object_select_mirror_exec(bContext *C, wmOperator *op) CTX_DATA_END; /* undo? */ + DEG_id_tag_update(&scene->id, DEG_TAG_SELECT_UPDATE); WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene); return OPERATOR_FINISHED; @@ -1073,7 +1085,9 @@ static int object_select_more_exec(bContext *C, wmOperator *UNUSED(op)) bool changed = object_select_more_less(C, true); if (changed) { - WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, CTX_data_scene(C)); + Scene *scene = CTX_data_scene(C); + DEG_id_tag_update(&scene->id, DEG_TAG_SELECT_UPDATE); + WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene); return OPERATOR_FINISHED; } else { @@ -1101,7 +1115,9 @@ static int object_select_less_exec(bContext *C, wmOperator *UNUSED(op)) bool changed = object_select_more_less(C, false); if (changed) { - WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, CTX_data_scene(C)); + Scene *scene = CTX_data_scene(C); + DEG_id_tag_update(&scene->id, DEG_TAG_SELECT_UPDATE); + WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene); return OPERATOR_FINISHED; } else { @@ -1147,7 +1163,9 @@ static int object_select_random_exec(bContext *C, wmOperator *op) BLI_rng_free(rng); - WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, CTX_data_scene(C)); + Scene *scene = CTX_data_scene(C); + DEG_id_tag_update(&scene->id, DEG_TAG_SELECT_UPDATE); + WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene); return OPERATOR_FINISHED; } diff --git a/source/blender/editors/object/object_shapekey.c b/source/blender/editors/object/object_shapekey.c index 03fe6e9de65..4f985293ec3 100644 --- a/source/blender/editors/object/object_shapekey.c +++ b/source/blender/editors/object/object_shapekey.c @@ -78,8 +78,9 @@ static void ED_object_shape_key_add(bContext *C, Object *ob, const bool from_mix) { + Main *bmain = CTX_data_main(C); KeyBlock *kb; - if ((kb = BKE_object_shapekey_insert(ob, NULL, from_mix))) { + if ((kb = BKE_object_shapekey_insert(bmain, ob, NULL, from_mix))) { Key *key = BKE_key_from_object(ob); /* for absolute shape keys, new keys may not be added last */ ob->shapenr = BLI_findindex(&key->block, kb) + 1; diff --git a/source/blender/editors/object/object_vgroup.c b/source/blender/editors/object/object_vgroup.c index 84786024160..a6f688c49fb 100644 --- a/source/blender/editors/object/object_vgroup.c +++ b/source/blender/editors/object/object_vgroup.c @@ -2820,6 +2820,7 @@ static int vertex_group_select_exec(bContext *C, wmOperator *UNUSED(op)) return OPERATOR_CANCELLED; vgroup_select_verts(ob, 1); + DEG_id_tag_update(ob->data, DEG_TAG_SELECT_UPDATE); WM_event_add_notifier(C, NC_GEOM | ND_SELECT, ob->data); return OPERATOR_FINISHED; @@ -2845,6 +2846,7 @@ static int vertex_group_deselect_exec(bContext *C, wmOperator *UNUSED(op)) Object *ob = ED_object_context(C); vgroup_select_verts(ob, 0); + DEG_id_tag_update(ob->data, DEG_TAG_SELECT_UPDATE); WM_event_add_notifier(C, NC_GEOM | ND_SELECT, ob->data); return OPERATOR_FINISHED; diff --git a/source/blender/editors/physics/dynamicpaint_ops.c b/source/blender/editors/physics/dynamicpaint_ops.c index f45ee050ef9..7f74dd4666a 100644 --- a/source/blender/editors/physics/dynamicpaint_ops.c +++ b/source/blender/editors/physics/dynamicpaint_ops.c @@ -316,7 +316,7 @@ static void dpaint_bake_endjob(void *customdata) G.is_rendering = false; BKE_spacedata_draw_locks(false); - WM_set_locked_interface(G.main->wm.first, false); + WM_set_locked_interface(G_MAIN->wm.first, false); /* Bake was successful: * Report for ended bake and how long it took */ diff --git a/source/blender/editors/physics/particle_edit.c b/source/blender/editors/physics/particle_edit.c index 359e9365ea7..08eaaa7284f 100644 --- a/source/blender/editors/physics/particle_edit.c +++ b/source/blender/editors/physics/particle_edit.c @@ -49,6 +49,7 @@ #include "BLI_string.h" #include "BLI_kdtree.h" #include "BLI_rand.h" +#include "BLI_task.h" #include "BLI_utildefines.h" #include "BKE_context.h" @@ -56,6 +57,7 @@ #include "BKE_global.h" #include "BKE_object.h" #include "BKE_library.h" +#include "BKE_main.h" #include "BKE_mesh.h" #include "BKE_mesh_runtime.h" #include "BKE_modifier.h" @@ -91,6 +93,8 @@ #include "DEG_depsgraph_query.h" +#include "PIL_time_utildefines.h" + #include "physics_intern.h" #include "particle_edit_utildefines.h" @@ -117,7 +121,7 @@ int PE_hair_poll(bContext *C) if (!scene || !ob || !(ob->mode & OB_MODE_PARTICLE_EDIT)) { return 0; } - edit= PE_get_current(scene, ob); + edit = PE_get_current(scene, ob); return (edit && edit->psys); } @@ -213,6 +217,31 @@ PTCacheEdit *PE_get_current_from_psys(ParticleSystem *psys) return NULL; } +/* NOTE: Similar to creation of edit, but only updates pointers in the + * existing struct. + */ +static void pe_update_hair_particle_edit_pointers(PTCacheEdit *edit) +{ + ParticleSystem *psys = edit->psys; + ParticleData *pa = psys->particles; + for (int p = 0; p < edit->totpoint; p++) { + PTCacheEditPoint *point = &edit->points[p]; + HairKey *hair_key = pa->hair; + for (int k = 0; k < point->totkey; k++) { + PTCacheEditKey *key = &point->keys[k]; + key->co = hair_key->co; + key->time = &hair_key->time; + key->flag = hair_key->editflag; + if (!(psys->flag & PSYS_GLOBAL_HAIR)) { + key->flag |= PEK_USE_WCO; + hair_key->editflag |= PEK_USE_WCO; + } + hair_key++; + } + pa++; + } +} + /* always gets at least the first particlesystem even if PSYS_CURRENT flag is not set * * note: this function runs on poll, therefor it can runs many times a second @@ -298,8 +327,16 @@ static PTCacheEdit *pe_get_current( } } - if (edit) + if (edit) { edit->pid = *pid; + if (edit->flags & PT_CACHE_EDIT_UPDATE_PARTICLE_FROM_EVAL) { + if (edit->psys != NULL) { + psys_copy_particles(edit->psys, edit->psys_eval); + pe_update_hair_particle_edit_pointers(edit); + } + edit->flags &= ~PT_CACHE_EDIT_UPDATE_PARTICLE_FROM_EVAL; + } + } BLI_freelistN(&pidlist); @@ -364,6 +401,7 @@ typedef struct PEData { ViewContext vc; const bContext *context; + Main *bmain; Scene *scene; ViewLayer *view_layer; Object *ob; @@ -372,6 +410,8 @@ typedef struct PEData { BVHTreeFromMesh shape_bvh; Depsgraph *depsgraph; + RNG *rng; + const int *mval; rcti *rect; float rad; @@ -400,6 +440,7 @@ static void PE_set_data(bContext *C, PEData *data) { memset(data, 0, sizeof(*data)); + data->bmain = CTX_data_main(C); data->scene = CTX_data_scene(C); data->view_layer = CTX_data_view_layer(C); data->ob = CTX_data_active_object(C); @@ -445,6 +486,22 @@ static void PE_free_shape_tree(PEData *data) free_bvhtree_from_mesh(&data->shape_bvh); } +static void PE_create_random_generator(PEData *data) +{ + uint rng_seed = (uint)(PIL_check_seconds_timer_i() & UINT_MAX); + rng_seed ^= GET_UINT_FROM_POINTER(data->ob); + rng_seed ^= GET_UINT_FROM_POINTER(data->edit); + data->rng = BLI_rng_new(rng_seed); +} + +static void PE_free_random_generator(PEData *data) +{ + if (data->rng != NULL) { + BLI_rng_free(data->rng); + data->rng = NULL; + } +} + /*************************** selection utilities *******************************/ static bool key_test_depth(PEData *data, const float co[3], const int screen_co[2]) @@ -642,61 +699,87 @@ static void foreach_mouse_hit_point(PEData *data, ForPointFunc func, int selecte } } -static void foreach_mouse_hit_key(PEData *data, ForKeyMatFunc func, int selected) +typedef struct KeyIterData { + PEData *data; + PTCacheEdit *edit; + int selected; + ForKeyMatFunc func; +} KeyIterData; + +static void foreach_mouse_hit_key_iter( + void *__restrict iter_data_v, + const int iter, + const ParallelRangeTLS *__restrict UNUSED(tls)) { + KeyIterData *iter_data = (KeyIterData *)iter_data_v; + PEData *data = iter_data->data; PTCacheEdit *edit = data->edit; + PTCacheEditPoint *point = &edit->points[iter]; + if (point->flag & PEP_HIDE) { + return; + } ParticleSystem *psys = edit->psys; - ParticleSystemModifierData *psmd = NULL; - ParticleEditSettings *pset= PE_settings(data->scene); - POINT_P; KEY_K; + ParticleSystemModifierData *psmd_eval = iter_data->edit->psmd_eval; + ParticleEditSettings *pset = PE_settings(data->scene); + const int selected = iter_data->selected; float mat[4][4], imat[4][4]; - unit_m4(mat); unit_m4(imat); - - if (edit->psys) - psmd= psys_get_modifier(data->ob, edit->psys); - - /* all is selected in path mode */ - if (pset->selectmode==SCE_SELECT_PATH) - selected= 0; - - LOOP_VISIBLE_POINTS { - if (pset->selectmode==SCE_SELECT_END) { - if (point->totkey) { - /* only do end keys */ - key= point->keys + point->totkey-1; - - if (selected==0 || key->flag & PEK_SELECT) { - if (key_inside_circle(data, data->rad, KEY_WCO, &data->dist)) { - if (edit->psys && !(edit->psys->flag & PSYS_GLOBAL_HAIR)) { - psys_mat_hair_to_global(data->ob, psmd->mesh_final, psys->part->from, psys->particles + p, mat); - invert_m4_m4(imat, mat); - } - - func(data, mat, imat, p, point->totkey-1, key); + if (pset->selectmode==SCE_SELECT_END) { + if (point->totkey) { + /* only do end keys */ + PTCacheEditKey *key = point->keys + point->totkey-1; + + if (selected==0 || key->flag & PEK_SELECT) { + if (key_inside_circle(data, data->rad, KEY_WCO, &data->dist)) { + if (edit->psys && !(edit->psys->flag & PSYS_GLOBAL_HAIR)) { + psys_mat_hair_to_global(data->ob, psmd_eval->mesh_final, psys->part->from, psys->particles + iter, mat); + invert_m4_m4(imat, mat); } + iter_data->func(data, mat, imat, iter, point->totkey-1, key); } } } - else { - /* do all keys */ - LOOP_VISIBLE_KEYS { - if (selected==0 || key->flag & PEK_SELECT) { - if (key_inside_circle(data, data->rad, KEY_WCO, &data->dist)) { - if (edit->psys && !(edit->psys->flag & PSYS_GLOBAL_HAIR)) { - psys_mat_hair_to_global(data->ob, psmd->mesh_final, psys->part->from, psys->particles + p, mat); - invert_m4_m4(imat, mat); - } - - func(data, mat, imat, p, k, key); + } + else { + /* do all keys */ + PTCacheEditKey *key; + int k; + LOOP_VISIBLE_KEYS { + if (selected==0 || key->flag & PEK_SELECT) { + if (key_inside_circle(data, data->rad, KEY_WCO, &data->dist)) { + if (edit->psys && !(edit->psys->flag & PSYS_GLOBAL_HAIR)) { + psys_mat_hair_to_global(data->ob, psmd_eval->mesh_final, psys->part->from, psys->particles + iter, mat); + invert_m4_m4(imat, mat); } + iter_data->func(data, mat, imat, iter, k, key); } } } } } +static void foreach_mouse_hit_key(PEData *data, ForKeyMatFunc func, int selected) +{ + PTCacheEdit *edit = data->edit; + ParticleEditSettings *pset = PE_settings(data->scene); + /* all is selected in path mode */ + if (pset->selectmode == SCE_SELECT_PATH) { + selected = 0; + } + + KeyIterData iter_data; + iter_data.data = data; + iter_data.edit = edit; + iter_data.selected = selected; + iter_data.func = func; + + ParallelRangeSettings settings; + BLI_parallel_range_settings_defaults(&settings); + settings.scheduling_mode = TASK_SCHEDULING_DYNAMIC; + BLI_task_parallel_range(0, edit->totpoint, &iter_data, foreach_mouse_hit_key_iter, &settings); +} + static void foreach_selected_point(PEData *data, ForPointFunc func) { PTCacheEdit *edit = data->edit; @@ -760,7 +843,7 @@ static int count_selected_keys(Scene *scene, PTCacheEdit *edit) static void PE_update_mirror_cache(Object *ob, ParticleSystem *psys) { PTCacheEdit *edit; - ParticleSystemModifierData *psmd; + ParticleSystemModifierData *psmd_eval; KDTree *tree; KDTreeNearest nearest; HairKey *key; @@ -769,10 +852,10 @@ static void PE_update_mirror_cache(Object *ob, ParticleSystem *psys) int index, totpart; edit= psys->edit; - psmd= psys_get_modifier(ob, psys); + psmd_eval = edit->psmd_eval; totpart= psys->totpart; - if (!psmd->mesh_final) + if (!psmd_eval->mesh_final) return; tree= BLI_kdtree_new(totpart); @@ -780,7 +863,7 @@ static void PE_update_mirror_cache(Object *ob, ParticleSystem *psys) /* insert particles into kd tree */ LOOP_PARTICLES { key = pa->hair; - psys_mat_hair_to_orco(ob, psmd->mesh_final, psys->part->from, pa, mat); + psys_mat_hair_to_orco(ob, psmd_eval->mesh_final, psys->part->from, pa, mat); copy_v3_v3(co, key->co); mul_m4_v3(mat, co); BLI_kdtree_insert(tree, p, co); @@ -794,7 +877,7 @@ static void PE_update_mirror_cache(Object *ob, ParticleSystem *psys) LOOP_PARTICLES { key = pa->hair; - psys_mat_hair_to_orco(ob, psmd->mesh_final, psys->part->from, pa, mat); + psys_mat_hair_to_orco(ob, psmd_eval->mesh_final, psys->part->from, pa, mat); copy_v3_v3(co, key->co); mul_m4_v3(mat, co); co[0] = -co[0]; @@ -900,16 +983,16 @@ static void PE_mirror_particle(Object *ob, Mesh *mesh, ParticleSystem *psys, Par static void PE_apply_mirror(Object *ob, ParticleSystem *psys) { PTCacheEdit *edit; - ParticleSystemModifierData *psmd; + ParticleSystemModifierData *psmd_eval; POINT_P; if (!psys) return; edit= psys->edit; - psmd= psys_get_modifier(ob, psys); + psmd_eval= edit->psmd_eval; - if (!psmd->mesh_final) + if (!psmd_eval->mesh_final) return; if (!edit->mirror_cache) @@ -922,7 +1005,7 @@ static void PE_apply_mirror(Object *ob, ParticleSystem *psys) * to avoid doing mirror twice */ LOOP_POINTS { if (point->flag & PEP_EDIT_RECALC) { - PE_mirror_particle(ob, psmd->mesh_final, psys, psys->particles + p, NULL); + PE_mirror_particle(ob, psmd_eval->mesh_final, psys, psys->particles + p, NULL); if (edit->mirror_cache[p] != -1) edit->points[edit->mirror_cache[p]].flag &= ~PEP_EDIT_RECALC; @@ -939,110 +1022,152 @@ static void PE_apply_mirror(Object *ob, ParticleSystem *psys) /************************************************/ /* Edit Calculation */ /************************************************/ -/* tries to stop edited particles from going through the emitter's surface */ -static void pe_deflect_emitter(Scene *scene, Object *ob, PTCacheEdit *edit) -{ - ParticleEditSettings *pset= PE_settings(scene); + +typedef struct DeflectEmitterIter { + Object *object; ParticleSystem *psys; - ParticleSystemModifierData *psmd; - POINT_P; KEY_K; + PTCacheEdit *edit; + float dist; + float emitterdist; +} DeflectEmitterIter; + +static void deflect_emitter_iter( + void *__restrict iter_data_v, + const int iter, + const ParallelRangeTLS *__restrict UNUSED(tls)) + { + DeflectEmitterIter *iter_data = (DeflectEmitterIter *)iter_data_v; + PTCacheEdit *edit = iter_data->edit; + PTCacheEditPoint *point = &edit->points[iter]; + if ((point->flag & PEP_EDIT_RECALC) == 0) { + return; + } + Object *object = iter_data->object; + ParticleSystem *psys = iter_data->psys; + ParticleSystemModifierData *psmd_eval = iter_data->edit->psmd_eval; + PTCacheEditKey *key; + int k; + float hairimat[4][4], hairmat[4][4]; int index; float *vec, *nor, dvec[3], dot, dist_1st=0.0f; - float hairimat[4][4], hairmat[4][4]; - const float dist = ED_view3d_select_dist_px() * 0.01f; - - if (edit==NULL || edit->psys==NULL || (pset->flag & PE_DEFLECT_EMITTER)==0 || (edit->psys->flag & PSYS_GLOBAL_HAIR)) - return; - - psys = edit->psys; - psmd = psys_get_modifier(ob, psys); - - if (!psmd->mesh_final) - return; + const float dist = iter_data->dist; + const float emitterdist = iter_data->emitterdist; + psys_mat_hair_to_object(object, + psmd_eval->mesh_final, + psys->part->from, + psys->particles + iter, + hairmat); - LOOP_EDITED_POINTS { - psys_mat_hair_to_object(ob, psmd->mesh_final, psys->part->from, psys->particles + p, hairmat); + LOOP_KEYS { + mul_m4_v3(hairmat, key->co); + } - LOOP_KEYS { - mul_m4_v3(hairmat, key->co); + LOOP_KEYS { + if (k == 0) { + dist_1st = len_v3v3((key + 1)->co, key->co); + dist_1st *= dist * emitterdist; } + else { + index = BLI_kdtree_find_nearest(edit->emitter_field, key->co, NULL); - LOOP_KEYS { - if (k==0) { - dist_1st = len_v3v3((key+1)->co, key->co); - dist_1st *= dist * pset->emitterdist; - } - else { - index= BLI_kdtree_find_nearest(edit->emitter_field, key->co, NULL); - - vec=edit->emitter_cosnos +index*6; - nor=vec+3; + vec = edit->emitter_cosnos + index * 6; + nor = vec + 3; - sub_v3_v3v3(dvec, key->co, vec); + sub_v3_v3v3(dvec, key->co, vec); - dot=dot_v3v3(dvec, nor); - copy_v3_v3(dvec, nor); + dot = dot_v3v3(dvec, nor); + copy_v3_v3(dvec, nor); - if (dot>0.0f) { - if (dot<dist_1st) { - normalize_v3(dvec); - mul_v3_fl(dvec, dist_1st-dot); - add_v3_v3(key->co, dvec); - } - } - else { + if (dot > 0.0f) { + if (dot < dist_1st) { normalize_v3(dvec); - mul_v3_fl(dvec, dist_1st-dot); + mul_v3_fl(dvec, dist_1st - dot); add_v3_v3(key->co, dvec); } - if (k==1) - dist_1st*=1.3333f; + } + else { + normalize_v3(dvec); + mul_v3_fl(dvec, dist_1st - dot); + add_v3_v3(key->co, dvec); + } + if (k == 1) { + dist_1st *= 1.3333f; } } + } - invert_m4_m4(hairimat, hairmat); + invert_m4_m4(hairimat, hairmat); - LOOP_KEYS { - mul_m4_v3(hairimat, key->co); - } + LOOP_KEYS { + mul_m4_v3(hairimat, key->co); } } -/* force set distances between neighboring keys */ -static void PE_apply_lengths(Scene *scene, PTCacheEdit *edit) -{ - ParticleEditSettings *pset=PE_settings(scene); - POINT_P; KEY_K; - float dv1[3]; +/* tries to stop edited particles from going through the emitter's surface */ +static void pe_deflect_emitter(Scene *scene, Object *ob, PTCacheEdit *edit) +{ + ParticleEditSettings *pset = PE_settings(scene); + ParticleSystem *psys; + const float dist = ED_view3d_select_dist_px() * 0.01f; - if (edit==0 || (pset->flag & PE_KEEP_LENGTHS)==0) + if (edit == NULL || edit->psys == NULL || + (pset->flag & PE_DEFLECT_EMITTER) == 0 || + (edit->psys->flag & PSYS_GLOBAL_HAIR)) + { return; + } - if (edit->psys && edit->psys->flag & PSYS_GLOBAL_HAIR) + psys = edit->psys; + + if (!edit->psmd_eval->mesh_final) { return; + } - LOOP_EDITED_POINTS { - LOOP_KEYS { - if (k) { - sub_v3_v3v3(dv1, key->co, (key - 1)->co); - normalize_v3(dv1); - mul_v3_fl(dv1, (key - 1)->length); - add_v3_v3v3(key->co, (key - 1)->co, dv1); - } + DeflectEmitterIter iter_data; + iter_data.object = ob; + iter_data.psys = psys; + iter_data.edit = edit; + iter_data.dist = dist; + iter_data.emitterdist = pset->emitterdist; + + ParallelRangeSettings settings; + BLI_parallel_range_settings_defaults(&settings); + settings.scheduling_mode = TASK_SCHEDULING_DYNAMIC; + BLI_task_parallel_range(0, edit->totpoint, &iter_data, deflect_emitter_iter, &settings); +} + +typedef struct ApplyLengthsIterData { + PTCacheEdit *edit; +} ApplyLengthsIterData; + +static void apply_lengths_iter( + void *__restrict iter_data_v, + const int iter, + const ParallelRangeTLS *__restrict UNUSED(tls)) + { + ApplyLengthsIterData *iter_data = (ApplyLengthsIterData *)iter_data_v; + PTCacheEdit *edit = iter_data->edit; + PTCacheEditPoint *point = &edit->points[iter]; + if ((point->flag & PEP_EDIT_RECALC) == 0) { + return; + } + PTCacheEditKey *key; + int k; + LOOP_KEYS { + if (k) { + float dv1[3]; + sub_v3_v3v3(dv1, key->co, (key - 1)->co); + normalize_v3(dv1); + mul_v3_fl(dv1, (key - 1)->length); + add_v3_v3v3(key->co, (key - 1)->co, dv1); } } } -/* try to find a nice solution to keep distances between neighboring keys */ -static void pe_iterate_lengths(Scene *scene, PTCacheEdit *edit) + +/* force set distances between neighboring keys */ +static void PE_apply_lengths(Scene *scene, PTCacheEdit *edit) { ParticleEditSettings *pset=PE_settings(scene); - POINT_P; - PTCacheEditKey *key; - int j, k; - float tlen; - float dv0[3] = {0.0f, 0.0f, 0.0f}; - float dv1[3] = {0.0f, 0.0f, 0.0f}; - float dv2[3] = {0.0f, 0.0f, 0.0f}; if (edit==0 || (pset->flag & PE_KEEP_LENGTHS)==0) return; @@ -1050,43 +1175,91 @@ static void pe_iterate_lengths(Scene *scene, PTCacheEdit *edit) if (edit->psys && edit->psys->flag & PSYS_GLOBAL_HAIR) return; - LOOP_EDITED_POINTS { - for (j=1; j<point->totkey; j++) { - float mul= 1.0f / (float)point->totkey; - - if (pset->flag & PE_LOCK_FIRST) { - key= point->keys + 1; - k= 1; - dv1[0] = dv1[1] = dv1[2] = 0.0; - } - else { - key= point->keys; - k= 0; - dv0[0] = dv0[1] = dv0[2] = 0.0; - } - - for (; k<point->totkey; k++, key++) { - if (k) { - sub_v3_v3v3(dv0, (key - 1)->co, key->co); - tlen= normalize_v3(dv0); - mul_v3_fl(dv0, (mul * (tlen - (key - 1)->length))); - } + ApplyLengthsIterData iter_data; + iter_data.edit = edit; - if (k < point->totkey - 1) { - sub_v3_v3v3(dv2, (key + 1)->co, key->co); - tlen= normalize_v3(dv2); - mul_v3_fl(dv2, mul * (tlen - key->length)); - } + ParallelRangeSettings settings; + BLI_parallel_range_settings_defaults(&settings); + settings.scheduling_mode = TASK_SCHEDULING_DYNAMIC; + BLI_task_parallel_range(0, edit->totpoint, &iter_data, apply_lengths_iter, &settings); +} - if (k) { - add_v3_v3((key-1)->co, dv1); - } +typedef struct IterateLengthsIterData { + PTCacheEdit *edit; + ParticleEditSettings *pset; +} IterateLengthsIterData; + +static void iterate_lengths_iter( + void *__restrict iter_data_v, + const int iter, + const ParallelRangeTLS *__restrict UNUSED(tls)) +{ + IterateLengthsIterData *iter_data = (IterateLengthsIterData *)iter_data_v; + PTCacheEdit *edit = iter_data->edit; + PTCacheEditPoint *point = &edit->points[iter]; + if ((point->flag & PEP_EDIT_RECALC) == 0) { + return; + } + ParticleEditSettings *pset = iter_data->pset; + float tlen; + float dv0[3] = {0.0f, 0.0f, 0.0f}; + float dv1[3] = {0.0f, 0.0f, 0.0f}; + float dv2[3] = {0.0f, 0.0f, 0.0f}; + for (int j = 1; j < point->totkey; j++) { + PTCacheEditKey *key; + int k; + float mul = 1.0f / (float)point->totkey; + if (pset->flag & PE_LOCK_FIRST) { + key = point->keys + 1; + k = 1; + dv1[0] = dv1[1] = dv1[2] = 0.0; + } + else { + key = point->keys; + k = 0; + dv0[0] = dv0[1] = dv0[2] = 0.0; + } - add_v3_v3v3(dv1, dv0, dv2); + for (; k < point->totkey; k++, key++) { + if (k) { + sub_v3_v3v3(dv0, (key - 1)->co, key->co); + tlen = normalize_v3(dv0); + mul_v3_fl(dv0, (mul * (tlen - (key - 1)->length))); + } + if (k < point->totkey - 1) { + sub_v3_v3v3(dv2, (key + 1)->co, key->co); + tlen = normalize_v3(dv2); + mul_v3_fl(dv2, mul * (tlen - key->length)); + } + if (k) { + add_v3_v3((key-1)->co, dv1); } + add_v3_v3v3(dv1, dv0, dv2); } } } + +/* try to find a nice solution to keep distances between neighboring keys */ +static void pe_iterate_lengths(Scene *scene, PTCacheEdit *edit) +{ + ParticleEditSettings *pset = PE_settings(scene); + if (edit==0 || (pset->flag & PE_KEEP_LENGTHS)==0) { + return; + } + if (edit->psys && edit->psys->flag & PSYS_GLOBAL_HAIR) { + return; + } + + IterateLengthsIterData iter_data; + iter_data.edit = edit; + iter_data.pset = pset; + + ParallelRangeSettings settings; + BLI_parallel_range_settings_defaults(&settings); + settings.scheduling_mode = TASK_SCHEDULING_DYNAMIC; + BLI_task_parallel_range(0, edit->totpoint, &iter_data, iterate_lengths_iter, &settings); +} + /* set current distances to be kept between neighbouting keys */ void recalc_lengths(PTCacheEdit *edit) { @@ -1104,10 +1277,10 @@ void recalc_lengths(PTCacheEdit *edit) } /* calculate a tree for finding nearest emitter's vertice */ -void recalc_emitter_field(Depsgraph *UNUSED(depsgraph), Object *ob, ParticleSystem *psys) +void recalc_emitter_field(Depsgraph *UNUSED(depsgraph), Object *UNUSED(ob), ParticleSystem *psys) { - Mesh *mesh = psys_get_modifier(ob, psys)->mesh_final; PTCacheEdit *edit = psys->edit; + Mesh *mesh = edit->psmd_eval->mesh_final; float *vec, *nor; int i, totface /*, totvert*/; @@ -1197,16 +1370,16 @@ static void PE_update_selection(Depsgraph *depsgraph, Scene *scene, Object *ob, void update_world_cos(Depsgraph *UNUSED(depsgraph), Object *ob, PTCacheEdit *edit) { ParticleSystem *psys = edit->psys; - ParticleSystemModifierData *psmd = psys_get_modifier(ob, psys); + ParticleSystemModifierData *psmd_eval = edit->psmd_eval; POINT_P; KEY_K; float hairmat[4][4]; - if (psys == 0 || psys->edit == 0 || psmd->mesh_final == NULL) + if (psys == 0 || psys->edit == 0 || psmd_eval->mesh_final == NULL) return; LOOP_POINTS { if (!(psys->flag & PSYS_GLOBAL_HAIR)) - psys_mat_hair_to_global(ob, psmd->mesh_final, psys->part->from, psys->particles+p, hairmat); + psys_mat_hair_to_global(ob, psmd_eval->mesh_final, psys->part->from, psys->particles+p, hairmat); LOOP_KEYS { copy_v3_v3(key->world_co, key->co); @@ -1638,8 +1811,6 @@ static int select_random_exec(bContext *C, wmOperator *op) { PEData data; int type; - Scene *scene; - Object *ob; /* used by LOOP_VISIBLE_POINTS, LOOP_VISIBLE_KEYS and LOOP_KEYS */ PTCacheEdit *edit; @@ -1657,9 +1828,7 @@ static int select_random_exec(bContext *C, wmOperator *op) PE_set_data(C, &data); data.select_action = SEL_SELECT; - scene = CTX_data_scene(C); - ob = CTX_data_active_object(C); - edit = PE_get_current(scene, ob); + edit = PE_get_current(data.scene, data.ob); rng = BLI_rng_new_srandom(seed); @@ -1833,7 +2002,7 @@ int PE_lasso_select(bContext *C, const int mcords[][2], const short moves, bool ParticleEditSettings *pset= PE_settings(scene); PTCacheEdit *edit = PE_get_current(scene, ob); ParticleSystem *psys = edit->psys; - ParticleSystemModifierData *psmd = psys_get_modifier(ob, psys); + ParticleSystemModifierData *psmd_eval = edit->psmd_eval; POINT_P; KEY_K; float co[3], mat[4][4]; int screen_co[2]; @@ -1853,7 +2022,7 @@ int PE_lasso_select(bContext *C, const int mcords[][2], const short moves, bool LOOP_VISIBLE_POINTS { if (edit->psys && !(psys->flag & PSYS_GLOBAL_HAIR)) - psys_mat_hair_to_global(ob, psmd->mesh_final, psys->part->from, psys->particles + p, mat); + psys_mat_hair_to_global(ob, psmd_eval->mesh_final, psys->part->from, psys->particles + p, mat); if (pset->selectmode==SCE_SELECT_POINT) { LOOP_KEYS { @@ -2290,15 +2459,15 @@ static int remove_tagged_particles(Object *ob, ParticleSystem *psys, int mirror) ParticleData *pa, *npa=0, *new_pars=0; POINT_P; PTCacheEditPoint *npoint=0, *new_points=0; - ParticleSystemModifierData *psmd; + ParticleSystemModifierData *psmd_eval; int i, new_totpart= psys->totpart, removed= 0; if (mirror) { /* mirror tags */ - psmd= psys_get_modifier(ob, psys); + psmd_eval = edit->psmd_eval; LOOP_TAGGED_POINTS { - PE_mirror_particle(ob, psmd->mesh_final, psys, psys->particles + p, NULL); + PE_mirror_particle(ob, psmd_eval->mesh_final, psys, psys->particles + p, NULL); } } @@ -2369,16 +2538,16 @@ static void remove_tagged_keys(Object *ob, ParticleSystem *psys) HairKey *hkey, *nhkey, *new_hkeys=0; POINT_P; KEY_K; PTCacheEditKey *nkey, *new_keys; - ParticleSystemModifierData *psmd; + ParticleSystemModifierData *psmd_eval; short new_totkey; if (pe_x_mirror(ob)) { /* mirror key tags */ - psmd= psys_get_modifier(ob, psys); + psmd_eval = psys_get_modifier(ob, psys); LOOP_POINTS { LOOP_TAGGED_KEYS { - PE_mirror_particle(ob, psmd->mesh_final, psys, psys->particles + p, NULL); + PE_mirror_particle(ob, psmd_eval->mesh_final, psys, psys->particles + p, NULL); break; } } @@ -2572,7 +2741,7 @@ static int remove_doubles_exec(bContext *C, wmOperator *op) Object *ob= CTX_data_active_object(C); PTCacheEdit *edit= PE_get_current(scene, ob); ParticleSystem *psys = edit->psys; - ParticleSystemModifierData *psmd; + ParticleSystemModifierData *psmd_eval; KDTree *tree; KDTreeNearest nearest[10]; POINT_P; @@ -2583,7 +2752,7 @@ static int remove_doubles_exec(bContext *C, wmOperator *op) return OPERATOR_CANCELLED; edit= psys->edit; - psmd= psys_get_modifier(ob, psys); + psmd_eval = edit->psmd_eval; totremoved= 0; do { @@ -2593,7 +2762,7 @@ static int remove_doubles_exec(bContext *C, wmOperator *op) /* insert particles into kd tree */ LOOP_SELECTED_POINTS { - psys_mat_hair_to_object(ob, psmd->mesh_final, psys->part->from, psys->particles+p, mat); + psys_mat_hair_to_object(ob, psmd_eval->mesh_final, psys->part->from, psys->particles+p, mat); copy_v3_v3(co, point->keys->co); mul_m4_v3(mat, co); BLI_kdtree_insert(tree, p, co); @@ -2603,7 +2772,7 @@ static int remove_doubles_exec(bContext *C, wmOperator *op) /* tag particles to be removed */ LOOP_SELECTED_POINTS { - psys_mat_hair_to_object(ob, psmd->mesh_final, psys->part->from, psys->particles+p, mat); + psys_mat_hair_to_object(ob, psmd_eval->mesh_final, psys->part->from, psys->particles+p, mat); copy_v3_v3(co, point->keys->co); mul_m4_v3(mat, co); @@ -2824,7 +2993,7 @@ static void PE_mirror_x( Scene *scene, Object *ob, int tagged) { Mesh *me= (Mesh *)(ob->data); - ParticleSystemModifierData *psmd; + ParticleSystemModifierData *psmd_eval; PTCacheEdit *edit = PE_get_current(scene, ob); ParticleSystem *psys = edit->psys; ParticleData *pa, *newpa, *new_pars; @@ -2837,18 +3006,18 @@ static void PE_mirror_x( if (psys->flag & PSYS_GLOBAL_HAIR) return; - psmd= psys_get_modifier(ob, psys); - if (!psmd->mesh_final) + psmd_eval = edit->psmd_eval; + if (!psmd_eval->mesh_final) return; - const bool use_dm_final_indices = (psys->part->use_modifier_stack && !psmd->mesh_final->runtime.deformed_only); + const bool use_dm_final_indices = (psys->part->use_modifier_stack && !psmd_eval->mesh_final->runtime.deformed_only); /* NOTE: this is not nice to use tessfaces but hard to avoid since pa->num uses tessfaces */ BKE_mesh_tessface_ensure(me); /* Note: In case psys uses Mesh tessface indices, we mirror final Mesh itself, not orig mesh. Avoids an (impossible) * mesh -> orig -> mesh tessface indices conversion... */ - mirrorfaces = mesh_get_x_mirror_faces__real_mesh(ob, NULL, use_dm_final_indices ? psmd->mesh_final : NULL); + mirrorfaces = mesh_get_x_mirror_faces__real_mesh(ob, NULL, use_dm_final_indices ? psmd_eval->mesh_final : NULL); if (!edit->mirror_cache) PE_update_mirror_cache(ob, psys); @@ -2862,7 +3031,7 @@ static void PE_mirror_x( if (point_is_selected(point)) { if (edit->mirror_cache[p] != -1) { /* already has a mirror, don't need to duplicate */ - PE_mirror_particle(ob, psmd->mesh_final, psys, pa, NULL); + PE_mirror_particle(ob, psmd_eval->mesh_final, psys, pa, NULL); continue; } else @@ -2875,7 +3044,7 @@ static void PE_mirror_x( } if (newtotpart != psys->totpart) { - MFace *mtessface = use_dm_final_indices ? psmd->mesh_final->mface : me->mface; + MFace *mtessface = use_dm_final_indices ? psmd_eval->mesh_final->mface : me->mface; /* allocate new arrays and copy existing */ new_pars= MEM_callocN(newtotpart*sizeof(ParticleData), "ParticleData new"); @@ -2944,7 +3113,7 @@ static void PE_mirror_x( } else { newpa->num_dmcache = psys_particle_dm_face_lookup( - psmd->mesh_final, psmd->mesh_original, newpa->num, newpa->fuv, NULL); + psmd_eval->mesh_final, psmd_eval->mesh_original, newpa->num, newpa->fuv, NULL); } /* update edit key pointers */ @@ -2955,7 +3124,7 @@ static void PE_mirror_x( } /* map key positions as mirror over x axis */ - PE_mirror_particle(ob, psmd->mesh_final, psys, pa, newpa); + PE_mirror_particle(ob, psmd_eval->mesh_final, psys, pa, newpa); newpa++; newpoint++; @@ -3030,8 +3199,11 @@ static void brush_cut(PEData *data, int pa_index) int k, cut, keys= (int)pow(2.0, (double)pset->draw_step); int screen_co[2]; + BLI_assert(data->rng != NULL); /* blunt scissors */ - if (BLI_frand() > data->cutfac) return; + if (BLI_rng_get_float(data->rng) > data->cutfac) { + return; + } /* don't cut hidden */ if (edit->points[pa_index].flag & PEP_HIDE) @@ -3360,14 +3532,13 @@ static void intersect_dm_quad_weights(const float v1[3], const float v2[3], cons } /* check intersection with a derivedmesh */ -static int particle_intersect_mesh(const bContext *C, Scene *scene, Object *ob, Mesh *mesh, - float *vert_cos, - const float co1[3], const float co2[3], - float *min_d, int *min_face, float *min_w, - float *face_minmax, float *pa_minmax, - float radius, float *ipoint) +static int particle_intersect_mesh(Depsgraph *depsgraph, Scene *scene, Object *ob, Mesh *mesh, + float *vert_cos, + const float co1[3], const float co2[3], + float *min_d, int *min_face, float *min_w, + float *face_minmax, float *pa_minmax, + float radius, float *ipoint) { - Depsgraph *depsgraph = CTX_data_depsgraph(C); MFace *mface= NULL; MVert *mvert= NULL; int i, totface, intersect=0; @@ -3496,6 +3667,109 @@ static int particle_intersect_mesh(const bContext *C, Scene *scene, Object *ob, return intersect; } +typedef struct BrushAddCountIterData { + Depsgraph *depsgraph; + Scene *scene; + Object *object; + Mesh *mesh; + PEData *data; + int number; + short size; + float imat[4][4]; + ParticleData *add_pars; + int num_added; +} BrushAddCountIterData; + +typedef struct BrushAddCountIterTLSData { + RNG *rng; + int num_added; +} BrushAddCountIterTLSData; + +static void brush_add_count_iter( + void *__restrict iter_data_v, + const int iter, + const ParallelRangeTLS *__restrict tls_v) +{ + BrushAddCountIterData *iter_data = (BrushAddCountIterData *)iter_data_v; + Depsgraph *depsgraph = iter_data->depsgraph; + PEData *data = iter_data->data; + PTCacheEdit *edit = data->edit; + ParticleSystem *psys = edit->psys; + ParticleSystemModifierData *psmd_eval = edit->psmd_eval; + ParticleData *add_pars = iter_data->add_pars; + BrushAddCountIterTLSData *tls = tls_v->userdata_chunk; + const int number = iter_data->number; + const short size = iter_data->size; + const short size2 = size*size; + float dmx, dmy; + if (number > 1) { + dmx = size; + dmy = size; + if (tls->rng == NULL) { + tls->rng = BLI_rng_new_srandom( + psys->seed + data->mval[0] + data->mval[1] + tls_v->thread_id); + } + /* rejection sampling to get points in circle */ + while (dmx*dmx + dmy*dmy > size2) { + dmx = (2.0f*BLI_rng_get_float(tls->rng) - 1.0f)*size; + dmy = (2.0f*BLI_rng_get_float(tls->rng) - 1.0f)*size; + } + } + else { + dmx = 0.0f; + dmy = 0.0f; + } + + float mco[2]; + mco[0] = data->mval[0] + dmx; + mco[1] = data->mval[1] + dmy; + + float co1[3], co2[3]; + ED_view3d_win_to_segment(depsgraph, data->vc.ar, data->vc.v3d, mco, co1, co2, true); + + mul_m4_v3(iter_data->imat, co1); + mul_m4_v3(iter_data->imat, co2); + float min_d = 2.0; + + /* warning, returns the derived mesh face */ + BLI_assert(iter_data->mesh != NULL); + if (particle_intersect_mesh(depsgraph, iter_data->scene, iter_data->object, iter_data->mesh, + 0, co1, co2, + &min_d, + &add_pars[iter].num_dmcache, + add_pars[iter].fuv, + 0, 0, 0, 0)) { + if (psys->part->use_modifier_stack && !psmd_eval->mesh_final->runtime.deformed_only) { + add_pars[iter].num = add_pars[iter].num_dmcache; + add_pars[iter].num_dmcache = DMCACHE_ISCHILD; + } + else if (iter_data->mesh == psmd_eval->mesh_original) { + /* Final DM is not same topology as orig mesh, we have to map num_dmcache to real final dm. */ + add_pars[iter].num = add_pars[iter].num_dmcache; + add_pars[iter].num_dmcache = psys_particle_dm_face_lookup( + psmd_eval->mesh_final, psmd_eval->mesh_original, + add_pars[iter].num, add_pars[iter].fuv, NULL); + } + else { + add_pars[iter].num = add_pars[iter].num_dmcache; + } + if (add_pars[iter].num != DMCACHE_NOTFOUND) { + tls->num_added++; + } + } +} + +static void brush_add_count_iter_finalize(void *__restrict userdata_v, + void *__restrict userdata_chunk_v) +{ + BrushAddCountIterData *iter_data = (BrushAddCountIterData *)userdata_v; + BrushAddCountIterTLSData *tls = (BrushAddCountIterTLSData *)userdata_chunk_v; + iter_data->num_added += tls->num_added; + if (tls->rng != NULL) { + BLI_rng_free(tls->rng); + } +} + static int brush_add(const bContext *C, PEData *data, short number) { Depsgraph *depsgraph = CTX_data_depsgraph(C); @@ -3505,16 +3779,13 @@ static int brush_add(const bContext *C, PEData *data, short number) PTCacheEdit *edit = data->edit; ParticleSystem *psys= edit->psys; ParticleData *add_pars; - ParticleSystemModifierData *psmd= psys_get_modifier(ob, psys); + ParticleSystemModifierData *psmd_eval = edit->psmd_eval; ParticleSimulationData sim= {0}; ParticleEditSettings *pset= PE_settings(scene); int i, k, n= 0, totpart= psys->totpart; - float mco[2]; - float dmx, dmy; - float co1[3], co2[3], min_d, imat[4][4]; + float co1[3], imat[4][4]; float framestep, timestep; short size= pset->brush[PE_BRUSH_ADD].size; - short size2= size*size; RNG *rng; invert_m4_m4(imat, ob->obmat); @@ -3527,67 +3798,65 @@ static int brush_add(const bContext *C, PEData *data, short number) rng = BLI_rng_new_srandom(psys->seed+data->mval[0]+data->mval[1]); sim.depsgraph = depsgraph; - sim.scene= scene; - sim.ob= ob; - sim.psys= psys; - sim.psmd= psmd; + sim.scene = scene; + sim.ob = ob; + sim.psys = psys; + sim.psmd = psmd_eval; - timestep= psys_get_timestep(&sim); + timestep = psys_get_timestep(&sim); - if (psys->part->use_modifier_stack || psmd->mesh_final->runtime.deformed_only) { - mesh = psmd->mesh_final; + if (psys->part->use_modifier_stack || psmd_eval->mesh_final->runtime.deformed_only) { + mesh = psmd_eval->mesh_final; } else { - mesh = psmd->mesh_original; + mesh = psmd_eval->mesh_original; } BLI_assert(mesh); - for (i=0; i<number; i++) { - if (number>1) { - dmx = size; - dmy = size; - - /* rejection sampling to get points in circle */ - while (dmx*dmx + dmy*dmy > size2) { - dmx= (2.0f*BLI_rng_get_float(rng) - 1.0f)*size; - dmy= (2.0f*BLI_rng_get_float(rng) - 1.0f)*size; - } + /* Calculate positions of new particles to add, based on brush interseciton + * with object. New particle data is assigned to a correponding to check + * index element of add_pars array. This means, that add_pars is a sparse + * array. + */ + BrushAddCountIterData iter_data; + iter_data.depsgraph = depsgraph; + iter_data.scene = scene; + iter_data.object = ob; + iter_data.mesh = mesh; + iter_data.data = data; + iter_data.number = number; + iter_data.size = size; + iter_data.add_pars = add_pars; + iter_data.num_added = 0; + copy_m4_m4(iter_data.imat, imat); + + BrushAddCountIterTLSData tls = {NULL}; + + ParallelRangeSettings settings; + BLI_parallel_range_settings_defaults(&settings); + settings.scheduling_mode = TASK_SCHEDULING_DYNAMIC; + settings.userdata_chunk = &tls; + settings.userdata_chunk_size = sizeof(BrushAddCountIterTLSData); + settings.func_finalize = brush_add_count_iter_finalize; + BLI_task_parallel_range(0, number, &iter_data, brush_add_count_iter, &settings); + + /* Convert add_parse to a dense array, where all new particles are in the + * beginnign of the array. + */ + n = iter_data.num_added; + for (int current_iter = 0, new_index = 0; current_iter < number; current_iter++) { + if (add_pars[current_iter].num == DMCACHE_NOTFOUND) { + continue; } - else { - dmx = 0.0f; - dmy = 0.0f; - } - - mco[0] = data->mval[0] + dmx; - mco[1] = data->mval[1] + dmy; - ED_view3d_win_to_segment(depsgraph, data->vc.ar, data->vc.v3d, mco, co1, co2, true); - - mul_m4_v3(imat, co1); - mul_m4_v3(imat, co2); - min_d=2.0; - - /* warning, returns the derived mesh face */ - if (particle_intersect_mesh(C, scene, ob, mesh, 0, co1, co2, &min_d, &add_pars[n].num_dmcache, add_pars[n].fuv, 0, 0, 0, 0)) { - if (psys->part->use_modifier_stack && !psmd->mesh_final->runtime.deformed_only) { - add_pars[n].num = add_pars[n].num_dmcache; - add_pars[n].num_dmcache = DMCACHE_ISCHILD; - } - else if (mesh == psmd->mesh_original) { - /* Final DM is not same topology as orig mesh, we have to map num_dmcache to real final dm. */ - add_pars[n].num = add_pars[n].num_dmcache; - add_pars[n].num_dmcache = psys_particle_dm_face_lookup( - psmd->mesh_final, psmd->mesh_original, - add_pars[n].num, add_pars[n].fuv, NULL); - } - else { - add_pars[n].num = add_pars[n].num_dmcache; - } - - if (add_pars[n].num != DMCACHE_NOTFOUND) { - n++; - } + if (new_index != current_iter) { + new_index++; + continue; } + memcpy(add_pars + new_index, add_pars + current_iter, sizeof(ParticleData)); + new_index++; } + + /* TODO(sergey): Consider multi-threading this part as well. */ if (n) { int newtotpart=totpart+n; float hairmat[4][4], cur_co[3]; @@ -3618,7 +3887,7 @@ static int brush_add(const bContext *C, PEData *data, short number) tree=BLI_kdtree_new(psys->totpart); for (i=0, pa=psys->particles; i<totpart; i++, pa++) { - psys_particle_on_dm(psmd->mesh_final, psys->part->from, pa->num, pa->num_dmcache, pa->fuv, pa->foffset, cur_co, 0, 0, 0, 0); + psys_particle_on_dm(psmd_eval->mesh_final, psys->part->from, pa->num, pa->num_dmcache, pa->fuv, pa->foffset, cur_co, 0, 0, 0, 0); BLI_kdtree_insert(tree, i, cur_co); } @@ -3662,7 +3931,7 @@ static int brush_add(const bContext *C, PEData *data, short number) int w, maxw; float maxd, totw=0.0, weight[3]; - psys_particle_on_dm(psmd->mesh_final, psys->part->from, pa->num, pa->num_dmcache, pa->fuv, pa->foffset, co1, 0, 0, 0, 0); + psys_particle_on_dm(psmd_eval->mesh_final, psys->part->from, pa->num, pa->num_dmcache, pa->fuv, pa->foffset, co1, 0, 0, 0, 0); maxw = BLI_kdtree_find_nearest_n(tree, co1, ptn, 3); maxd= ptn[maxw-1].dist; @@ -3727,7 +3996,7 @@ static int brush_add(const bContext *C, PEData *data, short number) } } for (k=0, hkey=pa->hair; k<pset->totaddkey; k++, hkey++) { - psys_mat_hair_to_global(ob, psmd->mesh_final, psys->part->from, pa, hairmat); + psys_mat_hair_to_global(ob, psmd_eval->mesh_final, psys->part->from, pa, hairmat); invert_m4_m4(imat, hairmat); mul_m4_v3(imat, hkey->co); } @@ -3792,6 +4061,7 @@ static int brush_edit_init(bContext *C, wmOperator *op) /* cache view depths and settings for re-use */ PE_set_view3d_data(C, &bedit->data); + PE_create_random_generator(&bedit->data); return 1; } @@ -3804,7 +4074,7 @@ static void brush_edit_apply(bContext *C, wmOperator *op, PointerRNA *itemptr) Object *ob= bedit->ob; PTCacheEdit *edit= bedit->edit; ParticleEditSettings *pset= PE_settings(scene); - ParticleSystemModifierData *psmd= edit->psys ? psys_get_modifier(ob, edit->psys) : NULL; + ParticleSystemModifierData *psmd_eval = edit->psmd_eval; ParticleBrushData *brush= &pset->brush[pset->brushtype]; ARegion *ar= CTX_wm_region(C); float vec[3], mousef[2]; @@ -3840,7 +4110,7 @@ static void brush_edit_apply(bContext *C, wmOperator *op, PointerRNA *itemptr) if (((pset->brushtype == PE_BRUSH_ADD) ? (sqrtf(dx * dx + dy * dy) > pset->brush[PE_BRUSH_ADD].step) : (dx != 0 || dy != 0)) || bedit->first) { - PEData data= bedit->data; + PEData data = bedit->data; data.context = C; // TODO(mai): why isnt this set in bedit->data? view3d_operator_needs_opengl(C); @@ -3919,7 +4189,7 @@ static void brush_edit_apply(bContext *C, wmOperator *op, PointerRNA *itemptr) case PE_BRUSH_PUFF: { if (edit->psys) { - data.mesh = psmd->mesh_final; + data.mesh = psmd_eval->mesh_final; data.mval= mval; data.rad= pe_brush_size_get(scene, brush); data.select= selected; @@ -3975,7 +4245,7 @@ static void brush_edit_apply(bContext *C, wmOperator *op, PointerRNA *itemptr) case PE_BRUSH_WEIGHT: { if (edit->psys) { - data.mesh = psmd->mesh_final; + data.mesh = psmd_eval->mesh_final; data.mval= mval; data.rad= pe_brush_size_get(scene, brush); @@ -4006,7 +4276,7 @@ static void brush_edit_apply(bContext *C, wmOperator *op, PointerRNA *itemptr) if (edit->psys) { WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE|NA_EDITED, ob); BKE_particle_batch_cache_dirty(edit->psys, BKE_PARTICLE_BATCH_DIRTY_ALL); - DEG_id_tag_update(&ob->id, DEG_TAG_COPY_ON_WRITE); + DEG_id_tag_update(&ob->id, DEG_TAG_SELECT_UPDATE); } else { DEG_id_tag_update(&ob->id, OB_RECALC_DATA); @@ -4025,6 +4295,7 @@ static void brush_edit_exit(wmOperator *op) { BrushEdit *bedit= op->customdata; + PE_free_random_generator(&bedit->data); MEM_freeN(bedit); } @@ -4079,8 +4350,11 @@ static int brush_edit_modal(bContext *C, wmOperator *op, const wmEvent *event) case LEFTMOUSE: case MIDDLEMOUSE: case RIGHTMOUSE: // XXX hardcoded - brush_edit_exit(op); - return OPERATOR_FINISHED; + if (event->val == KM_RELEASE) { + brush_edit_exit(op); + return OPERATOR_FINISHED; + } + break; case MOUSEMOVE: brush_edit_apply_event(C, op, event); break; @@ -4271,7 +4545,7 @@ static int shape_cut_exec(bContext *C, wmOperator *UNUSED(op)) if (edit->psys) { WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE|NA_EDITED, ob); BKE_particle_batch_cache_dirty(edit->psys, BKE_PARTICLE_BATCH_DIRTY_ALL); - DEG_id_tag_update(&ob->id, DEG_TAG_COPY_ON_WRITE); + DEG_id_tag_update(&ob->id, DEG_TAG_SELECT_UPDATE); } else { DEG_id_tag_update(&ob->id, OB_RECALC_DATA); @@ -4308,7 +4582,7 @@ int PE_minmax(Scene *scene, ViewLayer *view_layer, float min[3], float max[3]) Object *ob= OBACT(view_layer); PTCacheEdit *edit= PE_get_current(scene, ob); ParticleSystem *psys; - ParticleSystemModifierData *psmd = NULL; + ParticleSystemModifierData *psmd_eval = NULL; POINT_P; KEY_K; float co[3], mat[4][4]; int ok= 0; @@ -4316,13 +4590,13 @@ int PE_minmax(Scene *scene, ViewLayer *view_layer, float min[3], float max[3]) if (!edit) return ok; if ((psys = edit->psys)) - psmd= psys_get_modifier(ob, psys); + psmd_eval = edit->psmd_eval; else unit_m4(mat); LOOP_VISIBLE_POINTS { if (psys) - psys_mat_hair_to_global(ob, psmd->mesh_final, psys->part->from, psys->particles+p, mat); + psys_mat_hair_to_global(ob, psmd_eval->mesh_final, psys->part->from, psys->particles+p, mat); LOOP_SELECTED_KEYS { copy_v3_v3(co, key->co); @@ -4342,19 +4616,43 @@ int PE_minmax(Scene *scene, ViewLayer *view_layer, float min[3], float max[3]) /************************ particle edit toggle operator ************************/ +static struct ParticleSystem *psys_eval_get(Depsgraph *depsgraph, + Object *object, + ParticleSystem *psys) +{ + Object *object_eval = DEG_get_evaluated_object(depsgraph, object); + if (object_eval == object) { + return psys; + } + ParticleSystem *psys_eval = object_eval->particlesystem.first; + while (psys_eval != NULL) { + if (psys_eval->orig_psys == psys) { + return psys_eval; + } + psys_eval = psys_eval->next; + } + return psys_eval; +} + /* initialize needed data for bake edit */ void PE_create_particle_edit( Depsgraph *depsgraph, Scene *scene, Object *ob, PointCache *cache, ParticleSystem *psys) { + Object *ob_eval = DEG_get_evaluated_object(depsgraph, ob); PTCacheEdit *edit; ParticleSystemModifierData *psmd = (psys) ? psys_get_modifier(ob, psys) : NULL; + ParticleSystemModifierData *psmd_eval = NULL; POINT_P; KEY_K; ParticleData *pa = NULL; HairKey *hkey; int totpoint; + if (psmd != NULL) { + psmd_eval = (ParticleSystemModifierData *)modifiers_findByName(ob_eval, psmd->modifier.name); + } + /* no psmd->dm happens in case particle system modifier is not enabled */ - if (!(psys && psmd && psmd->mesh_final) && !cache) + if (!(psys && psmd && psmd_eval->mesh_final) && !cache) return; if (cache && cache->flag & PTCACHE_DISK_CACHE) @@ -4366,6 +4664,9 @@ void PE_create_particle_edit( edit = (psys) ? psys->edit : cache->edit; if (!edit) { + ParticleSystem *psys_eval = psys_eval_get(depsgraph, ob, psys); + psys_copy_particles(psys, psys_eval); + totpoint = psys ? psys->totpart : (int)((PTCacheMem *)cache->mem_cache.first)->totpoint; edit= MEM_callocN(sizeof(PTCacheEdit), "PE_create_particle_edit"); @@ -4373,8 +4674,11 @@ void PE_create_particle_edit( edit->totpoint = totpoint; if (psys && !cache) { - psys->edit= edit; + edit->psmd = psmd; + edit->psmd_eval = psmd_eval; + psys->edit = edit; edit->psys = psys; + edit->psys_eval = psys_eval; psys->free_edit= PE_free_ptcache_edit; @@ -4439,9 +4743,14 @@ void PE_create_particle_edit( psys = NULL; } + /* Causes assert on startup. */ +#if 0 UI_GetThemeColor3ubv(TH_EDGE_SELECT, edit->sel_col); UI_GetThemeColor3ubv(TH_WIRE, edit->nosel_col); - +#else + memset(edit->sel_col, 0xff, sizeof(edit->sel_col)); + memset(edit->nosel_col, 0x00, sizeof(edit->nosel_col)); +#endif recalc_lengths(edit); if (psys && !cache) recalc_emitter_field(depsgraph, ob, psys); @@ -4484,14 +4793,6 @@ static int particle_edit_toggle_exec(bContext *C, wmOperator *op) if (!is_mode_set) { PTCacheEdit *edit; - /* Particle edit mode requires original object to have all strands - * cached. A bit annoying to do update here, but is simpler than - * rewriting the while edit mode code. - */ - ob->id.recalc |= (ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY); - BKE_scene_graph_update_tagged(depsgraph, CTX_data_main(C)); - BKE_object_eval_transform_all(depsgraph, scene, ob); - BKE_object_handle_data_update(depsgraph, scene, ob); ob->mode |= mode_flag; edit= PE_create_current(depsgraph, scene, ob); @@ -4678,7 +4979,6 @@ static int unify_length_exec(bContext *C, wmOperator *UNUSED(op)) } scale_points_to_length(edit, average_length); - PE_update_object(depsgraph, scene, ob, 1); if (edit->psys) { WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE|NA_EDITED, ob); diff --git a/source/blender/editors/physics/particle_edit_undo.c b/source/blender/editors/physics/particle_edit_undo.c index 6576d692f70..fdf765e4557 100644 --- a/source/blender/editors/physics/particle_edit_undo.c +++ b/source/blender/editors/physics/particle_edit_undo.c @@ -44,9 +44,9 @@ #include "BLI_string.h" #include "BLI_utildefines.h" +#include "BKE_context.h" #include "BKE_particle.h" #include "BKE_pointcache.h" -#include "BKE_context.h" #include "BKE_undo_system.h" #include "DEG_depsgraph.h" diff --git a/source/blender/editors/physics/particle_object.c b/source/blender/editors/physics/particle_object.c index fbccdcfcdba..8a9eb369e66 100644 --- a/source/blender/editors/physics/particle_object.c +++ b/source/blender/editors/physics/particle_object.c @@ -82,13 +82,14 @@ static float I[4][4] = {{1.0f, 0.0f, 0.0f, 0.0f}, {0.0f, 1.0f, 0.0f, 0.0f}, {0.0 static int particle_system_add_exec(bContext *C, wmOperator *UNUSED(op)) { + Main *bmain = CTX_data_main(C); Object *ob= ED_object_context(C); Scene *scene = CTX_data_scene(C); if (!scene || !ob) return OPERATOR_CANCELLED; - object_add_particle_system(scene, ob, NULL); + object_add_particle_system(bmain, scene, ob, NULL); WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE, ob); WM_event_add_notifier(C, NC_OBJECT|ND_POINTCACHE, ob); @@ -113,6 +114,7 @@ void OBJECT_OT_particle_system_add(wmOperatorType *ot) static int particle_system_remove_exec(bContext *C, wmOperator *UNUSED(op)) { + Main *bmain = CTX_data_main(C); Object *ob = ED_object_context(C); Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); @@ -122,7 +124,7 @@ static int particle_system_remove_exec(bContext *C, wmOperator *UNUSED(op)) return OPERATOR_CANCELLED; mode_orig = ob->mode; - object_remove_particle_system(scene, ob); + object_remove_particle_system(bmain, scene, ob); /* possible this isn't the active object * object_remove_particle_system() clears the mode on the last psys diff --git a/source/blender/editors/physics/physics_fluid.c b/source/blender/editors/physics/physics_fluid.c index 130dcba060d..904e4242ed1 100644 --- a/source/blender/editors/physics/physics_fluid.c +++ b/source/blender/editors/physics/physics_fluid.c @@ -399,7 +399,7 @@ static void fluid_init_all_channels(bContext *C, Object *UNUSED(fsDomain), Fluid /* XXX: This can't be used due to an anim sys optimization that ignores recalc object animation, * leaving it for the depgraph (this ignores object animation such as modifier properties though... :/ ) - * --> BKE_animsys_evaluate_all_animation(G.main, eval_time); + * --> BKE_animsys_evaluate_all_animation(CTX_data_main(C), eval_time); * This doesn't work with drivers: * --> BKE_animsys_evaluate_animdata(&fsDomain->id, fsDomain->adt, eval_time, ADT_RECALC_ALL); */ diff --git a/source/blender/editors/physics/physics_pointcache.c b/source/blender/editors/physics/physics_pointcache.c index 45172774d55..343804726bf 100644 --- a/source/blender/editors/physics/physics_pointcache.c +++ b/source/blender/editors/physics/physics_pointcache.c @@ -140,7 +140,7 @@ static void ptcache_job_endjob(void *customdata) G.is_rendering = false; BKE_spacedata_draw_locks(false); - WM_set_locked_interface(G.main->wm.first, false); + WM_set_locked_interface(G_MAIN->wm.first, false); WM_main_add_notifier(NC_SCENE | ND_FRAME, scene); WM_main_add_notifier(NC_OBJECT | ND_POINTCACHE, job->baker->pid.ob); @@ -164,7 +164,7 @@ static PTCacheBaker *ptcache_baker_create(bContext *C, wmOperator *op, bool all) { PTCacheBaker *baker = MEM_callocN(sizeof(PTCacheBaker), "PTCacheBaker"); - baker->main = CTX_data_main(C); + baker->bmain = CTX_data_main(C); baker->scene = CTX_data_scene(C); baker->view_layer = CTX_data_view_layer(C); baker->depsgraph = CTX_data_depsgraph(C); diff --git a/source/blender/editors/physics/rigidbody_object.c b/source/blender/editors/physics/rigidbody_object.c index 99976898ac1..bdfbc47b22f 100644 --- a/source/blender/editors/physics/rigidbody_object.c +++ b/source/blender/editors/physics/rigidbody_object.c @@ -110,6 +110,7 @@ bool ED_rigidbody_object_add(Main *bmain, Scene *scene, Object *ob, int type, Re } if (rbw->group == NULL) { rbw->group = BKE_collection_add(bmain, NULL, "RigidBodyWorld"); + id_fake_user_set(&rbw->group->id); } /* make rigidbody object settings */ @@ -130,11 +131,7 @@ bool ED_rigidbody_object_add(Main *bmain, Scene *scene, Object *ob, int type, Re void ED_rigidbody_object_remove(Main *bmain, Scene *scene, Object *ob) { - RigidBodyWorld *rbw = BKE_rigidbody_get_world(scene); - - BKE_rigidbody_remove_object(scene, ob); - if (rbw) - BKE_collection_object_remove(bmain, rbw->group, ob, false); + BKE_rigidbody_remove_object(bmain, scene, ob); DEG_relations_tag_update(bmain); DEG_id_tag_update(&ob->id, OB_RECALC_OB); diff --git a/source/blender/editors/render/render_internal.c b/source/blender/editors/render/render_internal.c index d990f0b34d0..6a5844e323f 100644 --- a/source/blender/editors/render/render_internal.c +++ b/source/blender/editors/render/render_internal.c @@ -673,14 +673,14 @@ static void render_endjob(void *rjv) * would be re-assigned. assign dummy callbacks to avoid referencing freed renderjobs bug [#24508] */ RE_InitRenderCB(rj->re); - if (rj->main != G.main) + if (rj->main != G_MAIN) BKE_main_free(rj->main); /* else the frame will not update for the original value */ if (rj->anim && !(rj->scene->r.scemode & R_NO_FRAME_UPDATE)) { /* possible this fails of loading new file while rendering */ - if (G.main->wm.first) { - ED_update_for_newframe(G.main, rj->depsgraph); + if (G_MAIN->wm.first) { + ED_update_for_newframe(G_MAIN, rj->depsgraph); } } @@ -741,7 +741,7 @@ static void render_endjob(void *rjv) * and using one from Global will unlock exactly the same manager as * was locked before running the job. */ - WM_set_locked_interface(G.main->wm.first, false); + WM_set_locked_interface(G_MAIN->wm.first, false); /* We've freed all the derived caches before rendering, which is * effectively the same as if we re-loaded the file. @@ -749,11 +749,11 @@ static void render_endjob(void *rjv) * So let's not try being smart here and just reset all updated * scene layers and use generic DAG_on_visible_update. */ - for (scene = G.main->scene.first; scene; scene = scene->id.next) { + for (scene = G_MAIN->scene.first; scene; scene = scene->id.next) { scene->lay_updated = 0; } - DEG_on_visible_update(G.main, false); + DEG_on_visible_update(G_MAIN, false); } } diff --git a/source/blender/editors/render/render_preview.c b/source/blender/editors/render/render_preview.c index 4a3c7a3fd4b..cdd79f43a72 100644 --- a/source/blender/editors/render/render_preview.c +++ b/source/blender/editors/render/render_preview.c @@ -176,6 +176,9 @@ typedef struct ShaderPreview { Main *bmain; Main *pr_main; + + void *gl_context; + bool gl_context_owner; } ShaderPreview; typedef struct IconPreviewSize { @@ -191,6 +194,8 @@ typedef struct IconPreview { void *owner; ID *id; ListBase sizes; + + void *gl_context; } IconPreview; /* *************************** Preview for buttons *********************** */ @@ -741,6 +746,10 @@ static void shader_preview_render(ShaderPreview *sp, ID *id, int split, int firs /* set this for all previews, default is react to G.is_break still */ RE_test_break_cb(re, sp, shader_preview_break); + if (sp->gl_context) { + RE_gl_context_set(re, sp->gl_context); + } + /* lens adjust */ oldlens = ((Camera *)sce->camera->data)->lens; if (sizex > sp->sizey) @@ -860,6 +869,10 @@ static void shader_preview_free(void *customdata) } MEM_freeN(sp->lampcopy); } + if (sp->gl_context_owner && sp->gl_context) { + WM_opengl_context_dispose(sp->gl_context); + sp->gl_context = NULL; + } MEM_freeN(sp); } @@ -1075,6 +1088,8 @@ static void icon_preview_startjob_all_sizes(void *customdata, short *stop, short sp->pr_rect = cur_size->rect; sp->id = ip->id; sp->bmain = ip->bmain; + sp->gl_context = ip->gl_context; + sp->gl_context_owner = false; if (is_render) { BLI_assert(ip->id); @@ -1091,6 +1106,11 @@ static void icon_preview_startjob_all_sizes(void *customdata, short *stop, short common_preview_startjob(sp, stop, do_update, progress); shader_preview_free(sp); } + + if (ip->gl_context) { + WM_opengl_context_dispose(ip->gl_context); + ip->gl_context = NULL; + } } static void icon_preview_endjob(void *customdata) @@ -1174,8 +1194,17 @@ void ED_preview_icon_job(const bContext *C, void *owner, ID *id, unsigned int *r /* render all resolutions from suspended job too */ old_ip = WM_jobs_customdata_get(wm_job); - if (old_ip) + if (old_ip) { BLI_movelisttolist(&ip->sizes, &old_ip->sizes); + /* NOTE: This assumes that it will be the same thread + * that will be used when resuming the job. */ + ip->gl_context = old_ip->gl_context; + } + + if (ip->gl_context == NULL) { + /* Create context in the main thread. */ + ip->gl_context = WM_opengl_context_create(); + } /* customdata for preview thread */ ip->bmain = CTX_data_main(C); @@ -1206,7 +1235,7 @@ void ED_preview_shader_job(const bContext *C, void *owner, ID *id, ID *parent, M { Object *ob = CTX_data_active_object(C); wmJob *wm_job; - ShaderPreview *sp; + ShaderPreview *sp, *old_sp; Scene *scene = CTX_data_scene(C); short id_type = GS(id->name); @@ -1223,6 +1252,21 @@ void ED_preview_shader_job(const bContext *C, void *owner, ID *id, ID *parent, M WM_JOB_EXCL_RENDER, WM_JOB_TYPE_RENDER_PREVIEW); sp = MEM_callocN(sizeof(ShaderPreview), "shader preview"); + /* Reuse previous gl context. */ + old_sp = WM_jobs_customdata_get(wm_job); + if (old_sp) { + /* NOTE: This assumes that it will be the same thread + * that will be used when resuming the job. */ + old_sp->gl_context_owner = false; /* Don't free it */ + sp->gl_context = old_sp->gl_context; + } + + if (sp->gl_context == NULL) { + /* Create context in the main thread. */ + sp->gl_context = WM_opengl_context_create(); + } + sp->gl_context_owner = true; + /* customdata for preview thread */ sp->scene = scene; sp->depsgraph = CTX_data_depsgraph(C); diff --git a/source/blender/editors/render/render_shading.c b/source/blender/editors/render/render_shading.c index 3f32242cd1b..a822dabf7b4 100644 --- a/source/blender/editors/render/render_shading.c +++ b/source/blender/editors/render/render_shading.c @@ -303,6 +303,7 @@ static int material_slot_de_select(bContext *C, bool select) } } + DEG_id_tag_update(ob->data, DEG_TAG_SELECT_UPDATE); WM_event_add_notifier(C, NC_GEOM | ND_SELECT, ob->data); return OPERATOR_FINISHED; diff --git a/source/blender/editors/screen/area.c b/source/blender/editors/screen/area.c index f73ce24c24b..d9851487569 100644 --- a/source/blender/editors/screen/area.c +++ b/source/blender/editors/screen/area.c @@ -953,6 +953,9 @@ static void region_overlap_fix(ScrArea *sa, ARegion *ar) } if (ar1->overlap && ((ar1->alignment & RGN_SPLIT_PREV) == 0)) { + if (ELEM(ar1->alignment, RGN_ALIGN_FLOAT)) { + continue; + } align1 = ar1->alignment; if (BLI_rcti_isect(&ar1->winrct, &ar->winrct, NULL)) { if (align1 != align) { @@ -994,6 +997,9 @@ static void region_overlap_fix(ScrArea *sa, ARegion *ar) if (ar1->flag & (RGN_FLAG_HIDDEN)) { continue; } + if (ELEM(ar1->alignment, RGN_ALIGN_FLOAT)) { + continue; + } if (ar1->overlap && (ar1->alignment & RGN_SPLIT_PREV) == 0) { if ((ar1->alignment != align) && BLI_rcti_isect(&ar1->winrct, &ar->winrct, NULL)) { @@ -1008,6 +1014,9 @@ static void region_overlap_fix(ScrArea *sa, ARegion *ar) /* overlapping regions only in the following restricted cases */ bool ED_region_is_overlap(int spacetype, int regiontype) { + if (regiontype == RGN_TYPE_HUD) { + return 1; + } if (U.uiflag2 & USER_REGION_OVERLAP) { if (ELEM(spacetype, SPACE_VIEW3D, SPACE_SEQ, SPACE_IMAGE)) { if (ELEM(regiontype, RGN_TYPE_TOOLS, RGN_TYPE_UI, RGN_TYPE_TOOL_PROPS)) @@ -1052,8 +1061,9 @@ static void region_rect_recursive(wmWindow *win, ScrArea *sa, ARegion *ar, rcti /* clear state flags first */ ar->flag &= ~RGN_FLAG_TOO_SMALL; /* user errors */ - if (ar->next == NULL && alignment != RGN_ALIGN_QSPLIT) + if ((ar->next == NULL) && !ELEM(alignment, RGN_ALIGN_QSPLIT, RGN_ALIGN_FLOAT)) { alignment = RGN_ALIGN_NONE; + } /* prefsize, taking into account DPI */ prefsizex = UI_DPI_FAC * ((ar->sizex > 1) ? ar->sizex + 0.5f : ar->type->prefsizex); @@ -1076,7 +1086,28 @@ static void region_rect_recursive(wmWindow *win, ScrArea *sa, ARegion *ar, rcti /* hidden is user flag */ } else if (alignment == RGN_ALIGN_FLOAT) { - /* XXX floating area region, not handled yet here */ + /** + * \note Currently this window type is only used for #RGN_TYPE_HUD, + * We expect the panel to resize it's self to be larger. + * + * This aligns to the lower left of the area. + */ + rcti overlap_remainder_margin = *overlap_remainder; + BLI_rcti_resize( + &overlap_remainder_margin, + max_ii(0, BLI_rcti_size_x(overlap_remainder) - UI_UNIT_X / 2), + max_ii(0, BLI_rcti_size_y(overlap_remainder) - UI_UNIT_Y / 2)); + ar->winrct.xmin = overlap_remainder_margin.xmin; + ar->winrct.ymin = overlap_remainder_margin.ymin; + ar->winrct.xmax = ar->winrct.xmin + ar->sizex - 1; + ar->winrct.ymax = ar->winrct.ymin + ar->sizey - 1; + + BLI_rcti_isect(&ar->winrct, &overlap_remainder_margin, &ar->winrct); + if (BLI_rcti_size_x(&ar->winrct) < UI_UNIT_X || + BLI_rcti_size_y(&ar->winrct) < UI_UNIT_Y) + { + ar->flag |= RGN_FLAG_TOO_SMALL; + } } else if (rct_fits(remainder, 'v', 1) < 0 || rct_fits(remainder, 'h', 1) < 0) { /* remainder is too small for any usage */ @@ -1215,7 +1246,7 @@ static void region_rect_recursive(wmWindow *win, ScrArea *sa, ARegion *ar, rcti if (ar->winy > 1) ar->sizey = (ar->winy + 0.5f) / UI_DPI_FAC; /* exception for multiple overlapping regions on same spot */ - if (ar->overlap) { + if (ar->overlap & (alignment != RGN_ALIGN_FLOAT)) { region_overlap_fix(sa, ar); } @@ -1424,7 +1455,7 @@ void ED_area_initialize(wmWindowManager *wm, wmWindow *win, ScrArea *sa) } for (ar = sa->regionbase.first; ar; ar = ar->next) - ar->type = BKE_regiontype_from_id(sa->type, ar->regiontype); + ar->type = BKE_regiontype_from_id_or_first(sa->type, ar->regiontype); /* area sizes */ area_calc_totrct(sa, &window_rect); @@ -1480,13 +1511,13 @@ static void region_update_rect(ARegion *ar) /** * Call to move a popup window (keep OpenGL context free!) */ -void ED_region_update_rect(bContext *UNUSED(C), ARegion *ar) +void ED_region_update_rect(ARegion *ar) { region_update_rect(ar); } /* externally called for floating regions like menus */ -void ED_region_init(bContext *UNUSED(C), ARegion *ar) +void ED_region_init(ARegion *ar) { /* refresh can be called before window opened */ region_subwindow(ar); @@ -1781,7 +1812,10 @@ static ThemeColorID region_background_color_id(const bContext *C, const ARegion static void region_clear_color(const bContext *C, const ARegion *ar, ThemeColorID colorid) { - if (ar->overlap) { + if (ar->alignment == RGN_ALIGN_FLOAT) { + /* handle our own drawing. */ + } + else if (ar->overlap) { /* view should be in pixelspace */ UI_view2d_view_restore(C); @@ -1806,15 +1840,16 @@ BLI_INLINE bool streq_array_any(const char *s, const char *arr[]) return false; } -static void ed_panel_draw(const bContext *C, - ScrArea *sa, - ARegion *ar, - ListBase *lb, - PanelType *pt, - Panel *panel, - int w, - int em, - bool vertical) +static void ed_panel_draw( + const bContext *C, + ScrArea *sa, + ARegion *ar, + ListBase *lb, + PanelType *pt, + Panel *panel, + int w, + int em, + bool vertical) { uiStyle *style = UI_style_get_dpi(); @@ -1827,6 +1862,21 @@ static void ed_panel_draw(const bContext *C, /* bad fixed values */ int xco, yco, h = 0; + if (pt->draw_header_preset && !(pt->flag & PNL_NO_HEADER) && (open || vertical)) { + /* for preset menu */ + panel->layout = UI_block_layout( + block, UI_LAYOUT_HORIZONTAL, UI_LAYOUT_HEADER, + 0, (UI_UNIT_Y * 1.1f) + style->panelspace, UI_UNIT_Y, 1, 0, style); + + pt->draw_header_preset(C, panel); + + int headerend = w - UI_UNIT_X; + + UI_block_layout_resolve(block, &xco, &yco); + UI_block_translate(block, headerend - xco, 0); + panel->layout = NULL; + } + if (pt->draw_header && !(pt->flag & PNL_NO_HEADER) && (open || vertical)) { int labelx, labely; UI_panel_label_offset(block, &labelx, &labely); @@ -1891,13 +1941,16 @@ static void ed_panel_draw(const bContext *C, * Matching against any of these strings will draw the panel. * Can be NULL to skip context checks. */ -void ED_region_panels(const bContext *C, ARegion *ar, const char *contexts[], int contextnr, const bool vertical) +void ED_region_panels_layout_ex( + const bContext *C, ARegion *ar, + const char *contexts[], int contextnr, const bool vertical) { + ar->runtime.category = NULL; + const WorkSpace *workspace = CTX_wm_workspace(C); ScrArea *sa = CTX_wm_area(C); PanelType *pt; View2D *v2d = &ar->v2d; - View2DScrollers *scrollers; int x, y, w, em; bool is_context_new = 0; int scroll; @@ -1908,6 +1961,7 @@ void ED_region_panels(const bContext *C, ARegion *ar, const char *contexts[], in const char *category = NULL; const int category_tabs_width = UI_PANEL_CATEGORY_MARGIN_WIDTH; int margin_x = 0; + const bool region_layout_based = ar->flag & RGN_FLAG_DYNAMIC_SIZE; BLI_SMALLSTACK_DECLARE(pt_stack, PanelType *); @@ -2018,7 +2072,28 @@ void ED_region_panels(const bContext *C, ARegion *ar, const char *contexts[], in UI_panels_end(C, ar, &x, &y); /* before setting the view */ - if (vertical) { + if (region_layout_based) { + /* XXX, only single panel support atm. + * Can't use x/y values calculated above because they're not using the real height of panels, + * instead they calculate offsets for the next panel to start drawing. */ + Panel *panel = ar->panels.last; + if (panel != NULL) { + int size_dyn[2] = { + UI_UNIT_X * ((panel->flag & PNL_CLOSED) ? 8 : 14), + UI_panel_size_y(panel), + }; + /* region size is layout based and needs to be updated */ + if ((ar->sizex != size_dyn[0]) || + (ar->sizey != size_dyn[1])) + { + ar->sizex = size_dyn[0]; + ar->sizey = size_dyn[1]; + sa->flag |= AREA_FLAG_REGION_SIZE_UPDATE; + } + y = ABS(ar->sizey - 1); + } + } + else if (vertical) { /* we always keep the scroll offset - so the total view gets increased with the scrolled away part */ if (v2d->cur.ymax < -FLT_EPSILON) { /* Clamp to lower view boundary */ @@ -2059,7 +2134,22 @@ void ED_region_panels(const bContext *C, ARegion *ar, const char *contexts[], in #endif } - region_clear_color(C, ar, (ar->type->regionid == RGN_TYPE_PREVIEW) ? TH_PREVIEW_BACK : TH_BACK); + if (use_category_tabs) { + ar->runtime.category = category; + } +} +void ED_region_panels_layout(const bContext *C, ARegion *ar) +{ + ED_region_panels_layout_ex(C, ar, NULL, -1, true); +} + +void ED_region_panels_draw(const bContext *C, ARegion *ar) +{ + View2D *v2d = &ar->v2d; + + if (ar->alignment != RGN_ALIGN_FLOAT) { + region_clear_color(C, ar, (ar->type->regionid == RGN_TYPE_PREVIEW) ? TH_PREVIEW_BACK : TH_BACK); + } /* reset line width for drawing tabs */ glLineWidth(1.0f); @@ -2073,16 +2163,34 @@ void ED_region_panels(const bContext *C, ARegion *ar, const char *contexts[], in /* restore view matrix */ UI_view2d_view_restore(C); - if (use_category_tabs) { - UI_panel_category_draw_all(ar, category); + /* Set in layout. */ + if (ar->runtime.category) { + UI_panel_category_draw_all(ar, ar->runtime.category); } /* scrollers */ - scrollers = UI_view2d_scrollers_calc(C, v2d, V2D_ARG_DUMMY, V2D_ARG_DUMMY, V2D_ARG_DUMMY, V2D_ARG_DUMMY); + View2DScrollers *scrollers = UI_view2d_scrollers_calc( + C, v2d, V2D_ARG_DUMMY, V2D_ARG_DUMMY, V2D_ARG_DUMMY, V2D_ARG_DUMMY); UI_view2d_scrollers_draw(C, v2d, scrollers); UI_view2d_scrollers_free(scrollers); } +void ED_region_panels_ex( + const bContext *C, ARegion *ar, + const char *contexts[], int contextnr, const bool vertical) +{ + /* TODO: remove? */ + ED_region_panels_layout_ex(C, ar, contexts, contextnr, vertical); + ED_region_panels_draw(C, ar); +} + +void ED_region_panels(const bContext *C, ARegion *ar) +{ + /* TODO: remove? */ + ED_region_panels_layout(C, ar); + ED_region_panels_draw(C, ar); +} + void ED_region_panels_init(wmWindowManager *wm, ARegion *ar) { wmKeyMap *keymap; @@ -2102,13 +2210,12 @@ void ED_region_header_layout(const bContext *C, ARegion *ar) Header header = {NULL}; int maxco, xco, yco; int headery = ED_area_headersize(); - const int start_ofs = UI_HEADER_OFFSET_START; bool region_layout_based = ar->flag & RGN_FLAG_DYNAMIC_SIZE; /* set view2d view matrix for scrolling (without scrollers) */ UI_view2d_view_ortho(&ar->v2d); - xco = maxco = start_ofs; + xco = maxco = UI_HEADER_OFFSET; yco = headery + (ar->winy - headery) / 2 - floor(0.2f * UI_UNIT_Y); /* XXX workaround for 1 px alignment issue. Not sure what causes it... Would prefer a proper fix - Julian */ @@ -2139,7 +2246,7 @@ void ED_region_header_layout(const bContext *C, ARegion *ar) if (xco > maxco) maxco = xco; - int new_sizex = (maxco + start_ofs) / UI_DPI_FAC; + int new_sizex = (maxco + UI_HEADER_OFFSET) / UI_DPI_FAC; if (region_layout_based && (ar->sizex != new_sizex)) { /* region size is layout based and needs to be updated */ @@ -2152,8 +2259,12 @@ void ED_region_header_layout(const bContext *C, ARegion *ar) UI_block_end(C, block); } + if (!region_layout_based) { + maxco += UI_HEADER_OFFSET; + } + /* always as last */ - UI_view2d_totRect_set(&ar->v2d, maxco + (region_layout_based ? 0 : UI_UNIT_X + 80), headery); + UI_view2d_totRect_set(&ar->v2d, maxco, headery); /* restore view matrix */ UI_view2d_view_restore(C); @@ -2161,11 +2272,11 @@ void ED_region_header_layout(const bContext *C, ARegion *ar) void ED_region_header_draw(const bContext *C, ARegion *ar) { - UI_view2d_view_ortho(&ar->v2d); - /* clear */ region_clear_color(C, ar, region_background_color_id(C, ar)); + UI_view2d_view_ortho(&ar->v2d); + /* View2D matrix might have changed due to dynamic sized regions. */ UI_blocklist_update_window_matrix(C, &ar->uiblocks); @@ -2687,6 +2798,9 @@ void ED_region_visible_rect(ARegion *ar, rcti *rect) rect->ymax = arn->winrct.ymin; } } + else if (arn->alignment == RGN_ALIGN_FLOAT) { + /* Skip floating. */ + } else { BLI_assert(!"Region overlap with unknown alignment"); } diff --git a/source/blender/editors/screen/screen_edit.c b/source/blender/editors/screen/screen_edit.c index ac4ab3461a3..53abe3ed4ea 100644 --- a/source/blender/editors/screen/screen_edit.c +++ b/source/blender/editors/screen/screen_edit.c @@ -832,13 +832,13 @@ void ED_screen_refresh(wmWindowManager *wm, wmWindow *win) } /* file read, set all screens, ... */ -void ED_screens_initialize(Main *UNUSED(bmain), wmWindowManager *wm) +void ED_screens_initialize(Main *bmain, wmWindowManager *wm) { wmWindow *win; for (win = wm->windows.first; win; win = win->next) { if (WM_window_get_active_workspace(win) == NULL) { - WM_window_set_active_workspace(win, G.main->workspaces.first); + WM_window_set_active_workspace(win, bmain->workspaces.first); } if (BLI_listbase_is_empty(&win->global_areas.areabase)) { @@ -961,7 +961,7 @@ static void screen_cursor_set(wmWindow *win, const int xy[2]) ScrArea *sa; for (sa = screen->areabase.first; sa; sa = sa->next) - if ((az = is_in_area_actionzone(sa, xy))) + if ((az = ED_area_actionzone_find_xy(sa, xy))) break; if (sa) { @@ -1003,7 +1003,7 @@ void ED_screen_set_active_region(bContext *C, wmWindow *win, const int xy[2]) ED_screen_areas_iter(win, scr, area_iter) { if (xy[0] > area_iter->totrct.xmin && xy[0] < area_iter->totrct.xmax) { if (xy[1] > area_iter->totrct.ymin && xy[1] < area_iter->totrct.ymax) { - if (is_in_area_actionzone(area_iter, xy) == NULL) { + if (ED_area_actionzone_refresh_xy(area_iter, xy) == NULL) { sa = area_iter; break; } @@ -1073,7 +1073,7 @@ int ED_screen_area_active(const bContext *C) ScrArea *sa = CTX_wm_area(C); if (win && sc && sa) { - AZone *az = is_in_area_actionzone(sa, &win->eventstate->x); + AZone *az = ED_area_actionzone_find_xy(sa, &win->eventstate->x); ARegion *ar; if (az && az->type == AZONE_REGION) diff --git a/source/blender/editors/screen/screen_intern.h b/source/blender/editors/screen/screen_intern.h index b02198764e0..2c343fb9d70 100644 --- a/source/blender/editors/screen/screen_intern.h +++ b/source/blender/editors/screen/screen_intern.h @@ -67,7 +67,8 @@ ScrEdge *screen_find_active_scredge( const wmWindow *win, const bScreen *screen, const int mx, const int my); -struct AZone *is_in_area_actionzone(ScrArea *sa, const int xy[2]); +struct AZone *ED_area_actionzone_find_xy(ScrArea *sa, const int xy[2]); +struct AZone *ED_area_actionzone_refresh_xy(ScrArea *sa, const int xy[2]); /* screen_context.c */ int ed_screen_context( diff --git a/source/blender/editors/screen/screen_ops.c b/source/blender/editors/screen/screen_ops.c index 1ecc3f72355..e08755c84c6 100644 --- a/source/blender/editors/screen/screen_ops.c +++ b/source/blender/editors/screen/screen_ops.c @@ -679,7 +679,7 @@ static void fullscreen_click_rcti_init(rcti *rect, const short x1, const short y BLI_rcti_init(rect, x, x + icon_size, y, y + icon_size); } -AZone *is_in_area_actionzone(ScrArea *sa, const int xy[2]) +static AZone *area_actionzone_refresh_xy(ScrArea *sa, const int xy[2], const bool test_only) { AZone *az = NULL; @@ -687,102 +687,117 @@ AZone *is_in_area_actionzone(ScrArea *sa, const int xy[2]) if (BLI_rcti_isect_pt_v(&az->rect, xy)) { if (az->type == AZONE_AREA) { /* no triangle intersect but a hotspot circle based on corner */ - int radius = (xy[0] - az->x1) * (xy[0] - az->x1) + (xy[1] - az->y1) * (xy[1] - az->y1); - - if (radius <= AZONESPOT * AZONESPOT) + int radius_sq = SQUARE(xy[0] - az->x1) + SQUARE(xy[1] - az->y1); + if (radius_sq <= SQUARE(AZONESPOT)) { break; + } } else if (az->type == AZONE_REGION) { break; } else if (az->type == AZONE_FULLSCREEN) { - int mouse_radius, spot_radius, fadein_radius, fadeout_radius; rcti click_rect; - fullscreen_click_rcti_init(&click_rect, az->x1, az->y1, az->x2, az->y2); + const bool click_isect = BLI_rcti_isect_pt_v(&click_rect, xy); - if (BLI_rcti_isect_pt_v(&click_rect, xy)) { - az->alpha = 1.0f; + if (test_only) { + if (click_isect) { + break; + } } else { - mouse_radius = (xy[0] - az->x2) * (xy[0] - az->x2) + (xy[1] - az->y2) * (xy[1] - az->y2); - spot_radius = AZONESPOT * AZONESPOT; - fadein_radius = AZONEFADEIN * AZONEFADEIN; - fadeout_radius = AZONEFADEOUT * AZONEFADEOUT; - - if (mouse_radius < spot_radius) { + if (click_isect) { az->alpha = 1.0f; } - else if (mouse_radius < fadein_radius) { - az->alpha = 1.0f; - } - else if (mouse_radius < fadeout_radius) { - az->alpha = 1.0f - ((float)(mouse_radius - fadein_radius)) / ((float)(fadeout_radius - fadein_radius)); - } else { - az->alpha = 0.0f; + const int mouse_sq = SQUARE(xy[0] - az->x2) + SQUARE(xy[1] - az->y2); + const int spot_sq = SQUARE(AZONESPOT); + const int fadein_sq = SQUARE(AZONEFADEIN); + const int fadeout_sq = SQUARE(AZONEFADEOUT); + + if (mouse_sq < spot_sq) { + az->alpha = 1.0f; + } + else if (mouse_sq < fadein_sq) { + az->alpha = 1.0f; + } + else if (mouse_sq < fadeout_sq) { + az->alpha = 1.0f - ((float)(mouse_sq - fadein_sq)) / ((float)(fadeout_sq - fadein_sq)); + } + else { + az->alpha = 0.0f; + } + + /* fade in/out but no click */ + az = NULL; } - /* fade in/out but no click */ - az = NULL; + /* XXX force redraw to show/hide the action zone */ + ED_area_tag_redraw(sa); + break; } - - /* XXX force redraw to show/hide the action zone */ - ED_area_tag_redraw_no_rebuild(sa); - break; } else if (az->type == AZONE_REGION_SCROLL) { ARegion *ar = az->ar; View2D *v2d = &ar->v2d; const short isect_value = UI_view2d_mouse_in_scrollers(ar, v2d, xy[0], xy[1]); - bool redraw = false; - - if (isect_value == 'h') { - if (az->direction == AZ_SCROLL_HOR) { - az->alpha = 1.0f; - v2d->alpha_hor = 255; - v2d->size_hor = V2D_SCROLL_HEIGHT; - redraw = true; - } - } - else if (isect_value == 'v') { - if (az->direction == AZ_SCROLL_VERT) { - az->alpha = 1.0f; - v2d->alpha_vert = 255; - v2d->size_vert = V2D_SCROLL_WIDTH; - redraw = true; + if (test_only) { + if (isect_value != 0) { + break; } } else { - const int local_xy[2] = {xy[0] - ar->winrct.xmin, xy[1] - ar->winrct.ymin}; - float dist_fac = 0.0f, alpha = 0.0f; - - if (az->direction == AZ_SCROLL_HOR) { - dist_fac = BLI_rcti_length_y(&v2d->hor, local_xy[1]) / AZONEFADEIN; - CLAMP(dist_fac, 0.0f, 1.0f); - alpha = 1.0f - dist_fac; + bool redraw = false; - v2d->alpha_hor = alpha * 255; - v2d->size_hor = round_fl_to_int(V2D_SCROLL_HEIGHT - - ((V2D_SCROLL_HEIGHT - V2D_SCROLL_HEIGHT_MIN) * dist_fac)); + if (isect_value == 'h') { + if (az->direction == AZ_SCROLL_HOR) { + az->alpha = 1.0f; + v2d->alpha_hor = 255; + v2d->size_hor = V2D_SCROLL_HEIGHT; + redraw = true; + } } - else if (az->direction == AZ_SCROLL_VERT) { - dist_fac = BLI_rcti_length_x(&v2d->vert, local_xy[0]) / AZONEFADEIN; - CLAMP(dist_fac, 0.0f, 1.0f); - alpha = 1.0f - dist_fac; - - v2d->alpha_vert = alpha * 255; - v2d->size_vert = round_fl_to_int(V2D_SCROLL_WIDTH - - ((V2D_SCROLL_WIDTH - V2D_SCROLL_WIDTH_MIN) * dist_fac)); + else if (isect_value == 'v') { + if (az->direction == AZ_SCROLL_VERT) { + az->alpha = 1.0f; + v2d->alpha_vert = 255; + v2d->size_vert = V2D_SCROLL_WIDTH; + redraw = true; + } + } + else { + const int local_xy[2] = {xy[0] - ar->winrct.xmin, xy[1] - ar->winrct.ymin}; + float dist_fac = 0.0f, alpha = 0.0f; + + if (az->direction == AZ_SCROLL_HOR) { + dist_fac = BLI_rcti_length_y(&v2d->hor, local_xy[1]) / AZONEFADEIN; + CLAMP(dist_fac, 0.0f, 1.0f); + alpha = 1.0f - dist_fac; + + v2d->alpha_hor = alpha * 255; + v2d->size_hor = round_fl_to_int( + V2D_SCROLL_HEIGHT - + ((V2D_SCROLL_HEIGHT - V2D_SCROLL_HEIGHT_MIN) * dist_fac)); + } + else if (az->direction == AZ_SCROLL_VERT) { + dist_fac = BLI_rcti_length_x(&v2d->vert, local_xy[0]) / AZONEFADEIN; + CLAMP(dist_fac, 0.0f, 1.0f); + alpha = 1.0f - dist_fac; + + v2d->alpha_vert = alpha * 255; + v2d->size_vert = round_fl_to_int( + V2D_SCROLL_WIDTH - + ((V2D_SCROLL_WIDTH - V2D_SCROLL_WIDTH_MIN) * dist_fac)); + } + az->alpha = alpha; + redraw = true; } - az->alpha = alpha; - redraw = true; - } - if (redraw) { - ED_area_tag_redraw_no_rebuild(sa); + if (redraw) { + ED_area_tag_redraw_no_rebuild(sa); + } + /* Don't return! */ } - /* Don't return! */ } } } @@ -790,6 +805,15 @@ AZone *is_in_area_actionzone(ScrArea *sa, const int xy[2]) return az; } +AZone *ED_area_actionzone_find_xy(ScrArea *sa, const int xy[2]) +{ + return area_actionzone_refresh_xy(sa, xy, true); +} + +AZone *ED_area_actionzone_refresh_xy(ScrArea *sa, const int xy[2]) +{ + return area_actionzone_refresh_xy(sa, xy, false); +} static void actionzone_exit(wmOperator *op) { @@ -827,7 +851,7 @@ static void actionzone_apply(bContext *C, wmOperator *op, int type) static int actionzone_invoke(bContext *C, wmOperator *op, const wmEvent *event) { ScrArea *sa = CTX_wm_area(C); - AZone *az = is_in_area_actionzone(sa, &event->x); + AZone *az = ED_area_actionzone_find_xy(sa, &event->x); sActionzoneData *sad; /* quick escape */ @@ -888,7 +912,7 @@ static int actionzone_modal(bContext *C, wmOperator *op, const wmEvent *event) WM_window_screen_rect_calc(win, &screen_rect); /* once we drag outside the actionzone, register a gesture * check we're not on an edge so join finds the other area */ - is_gesture = ((is_in_area_actionzone(sad->sa1, &event->x) != sad->az) && + is_gesture = ((ED_area_actionzone_find_xy(sad->sa1, &event->x) != sad->az) && (screen_area_map_find_active_scredge( AREAMAP_FROM_SCREEN(sc), &screen_rect, event->x, event->y) == NULL)); } @@ -2262,7 +2286,7 @@ static int region_scale_modal(bContext *C, wmOperator *op, const wmEvent *event) case MOUSEMOVE: { const float aspect = BLI_rctf_size_x(&rmd->ar->v2d.cur) / (BLI_rcti_size_x(&rmd->ar->v2d.mask) + 1); - const int snap_size_threshold = (U.widget_unit * 3) / aspect; + const int snap_size_threshold = (U.widget_unit * 2) / aspect; if (rmd->edge == AE_LEFT_TO_TOPRIGHT || rmd->edge == AE_RIGHT_TO_TOPLEFT) { delta = event->x - rmd->origx; if (rmd->edge == AE_LEFT_TO_TOPRIGHT) delta = -delta; @@ -2454,7 +2478,7 @@ static void SCREEN_OT_frame_offset(wmOperatorType *ot) ot->poll = ED_operator_screenactive_norender; ot->flag = OPTYPE_UNDO_GROUPED; - ot->undo_group = "FRAME_CHANGE"; + ot->undo_group = "Frame Change"; /* rna */ RNA_def_int(ot->srna, "delta", 0, INT_MIN, INT_MAX, "Delta", "", INT_MIN, INT_MAX); @@ -2513,7 +2537,7 @@ static void SCREEN_OT_frame_jump(wmOperatorType *ot) ot->poll = ED_operator_screenactive_norender; ot->flag = OPTYPE_UNDO_GROUPED; - ot->undo_group = "FRAME_CHANGE"; + ot->undo_group = "Frame Change"; /* rna */ RNA_def_boolean(ot->srna, "end", 0, "Last Frame", "Jump to the last frame of the frame range"); @@ -2626,7 +2650,7 @@ static void SCREEN_OT_keyframe_jump(wmOperatorType *ot) ot->poll = ED_operator_screenactive_norender; ot->flag = OPTYPE_UNDO_GROUPED; - ot->undo_group = "FRAME_CHANGE"; + ot->undo_group = "Frame Change"; /* properties */ RNA_def_boolean(ot->srna, "next", true, "Next Keyframe", ""); @@ -2693,7 +2717,7 @@ static void SCREEN_OT_marker_jump(wmOperatorType *ot) ot->poll = ED_operator_screenactive_norender; ot->flag = OPTYPE_UNDO_GROUPED; - ot->undo_group = "FRAME_CHANGE"; + ot->undo_group = "Frame Change"; /* properties */ RNA_def_boolean(ot->srna, "next", true, "Next Marker", ""); diff --git a/source/blender/editors/screen/screendump.c b/source/blender/editors/screen/screendump.c index 7e50f8d41c4..e7b075dd5d0 100644 --- a/source/blender/editors/screen/screendump.c +++ b/source/blender/editors/screen/screendump.c @@ -234,7 +234,7 @@ static int screenshot_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED( char filepath[FILE_MAX] = "//screen"; if (G.relbase_valid) { BLI_strncpy(filepath, BKE_main_blendfile_path_from_global(), sizeof(filepath)); - BLI_replace_extension(filepath, sizeof(filepath), ""); /* strip '.blend' */ + BLI_path_extension_replace(filepath, sizeof(filepath), ""); /* strip '.blend' */ } RNA_string_set(op->ptr, "filepath", filepath); diff --git a/source/blender/editors/screen/workspace_layout_edit.c b/source/blender/editors/screen/workspace_layout_edit.c index 0c7431cb2e7..6d504c05dd1 100644 --- a/source/blender/editors/screen/workspace_layout_edit.c +++ b/source/blender/editors/screen/workspace_layout_edit.c @@ -57,7 +57,7 @@ WorkSpaceLayout *ED_workspace_layout_add( WM_window_screen_rect_calc(win, &screen_rect); screen = screen_add(bmain, name, &screen_rect); - return BKE_workspace_layout_add(workspace, screen, name); + return BKE_workspace_layout_add(bmain, workspace, screen, name); } WorkSpaceLayout *ED_workspace_layout_duplicate( diff --git a/source/blender/editors/sculpt_paint/paint_image_proj.c b/source/blender/editors/sculpt_paint/paint_image_proj.c index f6cf0f56764..62bc379241f 100644 --- a/source/blender/editors/sculpt_paint/paint_image_proj.c +++ b/source/blender/editors/sculpt_paint/paint_image_proj.c @@ -354,28 +354,30 @@ typedef struct ProjPaintState { SpinLock *tile_lock; - DerivedMesh *dm; - int dm_totlooptri; - int dm_totpoly; - int dm_totedge; - int dm_totvert; - bool dm_release; + Mesh *me_eval; + int totlooptri_eval; + int totpoly_eval; + int totedge_eval; + int totvert_eval; - const MVert *dm_mvert; - const MEdge *dm_medge; - const MPoly *dm_mpoly; - const MLoop *dm_mloop; - const MLoopTri *dm_mlooptri; + const MVert *mvert_eval; + const MEdge *medge_eval; + const MPoly *mpoly_eval; + const MLoop *mloop_eval; + const MLoopTri *mlooptri_eval; - const MLoopUV *dm_mloopuv_stencil; + const MLoopUV *mloopuv_stencil_eval; /** - * \note These UV layers are aligned to \a dm_mpoly + * \note These UV layers are aligned to \a mpoly_eval * but each pointer references the start of the layer, * so a loop indirection is needed as well. */ - const MLoopUV **dm_mloopuv; - const MLoopUV **dm_mloopuv_clone; /* other UV map, use for cloning between layers */ + const MLoopUV **poly_to_loop_uv; + const MLoopUV **poly_to_loop_uv_clone; /* other UV map, use for cloning between layers */ + + /* Actual material for each index, either from object or Mesh datablock... */ + Material **mat_array; bool use_colormanagement; } ProjPaintState; @@ -441,13 +443,13 @@ typedef struct { BLI_INLINE const MPoly *ps_tri_index_to_mpoly(const ProjPaintState *ps, int tri_index) { - return &ps->dm_mpoly[ps->dm_mlooptri[tri_index].poly]; + return &ps->mpoly_eval[ps->mlooptri_eval[tri_index].poly]; } #define PS_LOOPTRI_AS_VERT_INDEX_3(ps, lt) \ - ps->dm_mloop[lt->tri[0]].v, \ - ps->dm_mloop[lt->tri[1]].v, \ - ps->dm_mloop[lt->tri[2]].v, + ps->mloop_eval[lt->tri[0]].v, \ + ps->mloop_eval[lt->tri[1]].v, \ + ps->mloop_eval[lt->tri[2]].v, #define PS_LOOPTRI_AS_UV_3(uvlayer, lt) \ uvlayer[lt->poly][lt->tri[0]].uv, \ @@ -469,7 +471,7 @@ BLI_INLINE const MPoly *ps_tri_index_to_mpoly(const ProjPaintState *ps, int tri_ static TexPaintSlot *project_paint_face_paint_slot(const ProjPaintState *ps, int tri_index) { const MPoly *mp = ps_tri_index_to_mpoly(ps, tri_index); - Material *ma = ps->dm->mat[mp->mat_nr]; + Material *ma = ps->mat_array[mp->mat_nr]; return ma ? ma->texpaintslot + ma->paint_active_slot : NULL; } @@ -480,7 +482,7 @@ static Image *project_paint_face_paint_image(const ProjPaintState *ps, int tri_i } else { const MPoly *mp = ps_tri_index_to_mpoly(ps, tri_index); - Material *ma = ps->dm->mat[mp->mat_nr]; + Material *ma = ps->mat_array[mp->mat_nr]; TexPaintSlot *slot = ma ? ma->texpaintslot + ma->paint_active_slot : NULL; return slot ? slot->ima : ps->canvas_ima; } @@ -489,14 +491,14 @@ static Image *project_paint_face_paint_image(const ProjPaintState *ps, int tri_i static TexPaintSlot *project_paint_face_clone_slot(const ProjPaintState *ps, int tri_index) { const MPoly *mp = ps_tri_index_to_mpoly(ps, tri_index); - Material *ma = ps->dm->mat[mp->mat_nr]; + Material *ma = ps->mat_array[mp->mat_nr]; return ma ? ma->texpaintslot + ma->paint_clone_slot : NULL; } static Image *project_paint_face_clone_image(const ProjPaintState *ps, int tri_index) { const MPoly *mp = ps_tri_index_to_mpoly(ps, tri_index); - Material *ma = ps->dm->mat[mp->mat_nr]; + Material *ma = ps->mat_array[mp->mat_nr]; TexPaintSlot *slot = ma ? ma->texpaintslot + ma->paint_clone_slot : NULL; return slot ? slot->ima : ps->clone_ima; } @@ -597,11 +599,11 @@ static int project_paint_PickFace( for (node = ps->bucketFaces[bucket_index]; node; node = node->next) { const int tri_index = GET_INT_FROM_POINTER(node->link); - const MLoopTri *lt = &ps->dm_mlooptri[tri_index]; + const MLoopTri *lt = &ps->mlooptri_eval[tri_index]; const float *vtri_ss[3] = { - ps->screenCoords[ps->dm_mloop[lt->tri[0]].v], - ps->screenCoords[ps->dm_mloop[lt->tri[1]].v], - ps->screenCoords[ps->dm_mloop[lt->tri[2]].v], + ps->screenCoords[ps->mloop_eval[lt->tri[0]].v], + ps->screenCoords[ps->mloop_eval[lt->tri[1]].v], + ps->screenCoords[ps->mloop_eval[lt->tri[2]].v], }; @@ -656,8 +658,8 @@ static bool project_paint_PickColor( if (tri_index == -1) return 0; - lt = &ps->dm_mlooptri[tri_index]; - PS_LOOPTRI_ASSIGN_UV_3(lt_tri_uv, ps->dm_mloopuv, lt); + lt = &ps->mlooptri_eval[tri_index]; + PS_LOOPTRI_ASSIGN_UV_3(lt_tri_uv, ps->poly_to_loop_uv, lt); interp_v2_v2v2v2(uv, UNPACK3(lt_tri_uv), w); @@ -813,19 +815,19 @@ static bool project_bucket_point_occluded( const int tri_index = GET_INT_FROM_POINTER(bucketFace->link); if (orig_face != tri_index) { - const MLoopTri *lt = &ps->dm_mlooptri[tri_index]; + const MLoopTri *lt = &ps->mlooptri_eval[tri_index]; const float *vtri_ss[3] = { - ps->screenCoords[ps->dm_mloop[lt->tri[0]].v], - ps->screenCoords[ps->dm_mloop[lt->tri[1]].v], - ps->screenCoords[ps->dm_mloop[lt->tri[2]].v], + ps->screenCoords[ps->mloop_eval[lt->tri[0]].v], + ps->screenCoords[ps->mloop_eval[lt->tri[1]].v], + ps->screenCoords[ps->mloop_eval[lt->tri[2]].v], }; float w[3]; if (do_clip) { const float *vtri_co[3] = { - ps->dm_mvert[ps->dm_mloop[lt->tri[0]].v].co, - ps->dm_mvert[ps->dm_mloop[lt->tri[1]].v].co, - ps->dm_mvert[ps->dm_mloop[lt->tri[2]].v].co, + ps->mvert_eval[ps->mloop_eval[lt->tri[0]].v].co, + ps->mvert_eval[ps->mloop_eval[lt->tri[1]].v].co, + ps->mvert_eval[ps->mloop_eval[lt->tri[2]].v].co, }; isect_ret = project_paint_occlude_ptv_clip( pixelScreenCo, UNPACK3(vtri_ss), UNPACK3(vtri_co), @@ -1005,8 +1007,8 @@ static bool pixel_bounds_array(float (*uv)[2], rcti *bounds_px, const int ibuf_x static void project_face_winding_init(const ProjPaintState *ps, const int tri_index) { /* detect the winding of faces in uv space */ - const MLoopTri *lt = &ps->dm_mlooptri[tri_index]; - const float *lt_tri_uv[3] = { PS_LOOPTRI_AS_UV_3(ps->dm_mloopuv, lt) }; + const MLoopTri *lt = &ps->mlooptri_eval[tri_index]; + const float *lt_tri_uv[3] = { PS_LOOPTRI_AS_UV_3(ps->poly_to_loop_uv, lt) }; float winding = cross_tri_v2(lt_tri_uv[0], lt_tri_uv[1], lt_tri_uv[2]); if (winding > 0) @@ -1022,11 +1024,11 @@ static bool check_seam( const int orig_face, const int orig_i1_fidx, const int orig_i2_fidx, int *other_face, int *orig_fidx) { - const MLoopTri *orig_lt = &ps->dm_mlooptri[orig_face]; - const float *orig_lt_tri_uv[3] = { PS_LOOPTRI_AS_UV_3(ps->dm_mloopuv, orig_lt) }; + const MLoopTri *orig_lt = &ps->mlooptri_eval[orig_face]; + const float *orig_lt_tri_uv[3] = { PS_LOOPTRI_AS_UV_3(ps->poly_to_loop_uv, orig_lt) }; /* vert indices from face vert order indices */ - const unsigned int i1 = ps->dm_mloop[orig_lt->tri[orig_i1_fidx]].v; - const unsigned int i2 = ps->dm_mloop[orig_lt->tri[orig_i2_fidx]].v; + const unsigned int i1 = ps->mloop_eval[orig_lt->tri[orig_i1_fidx]].v; + const unsigned int i2 = ps->mloop_eval[orig_lt->tri[orig_i2_fidx]].v; LinkNode *node; int i1_fidx = -1, i2_fidx = -1; /* index in face */ @@ -1034,7 +1036,7 @@ static bool check_seam( const int tri_index = GET_INT_FROM_POINTER(node->link); if (tri_index != orig_face) { - const MLoopTri *lt = &ps->dm_mlooptri[tri_index]; + const MLoopTri *lt = &ps->mlooptri_eval[tri_index]; const int lt_vtri[3] = { PS_LOOPTRI_AS_VERT_INDEX_3(ps, lt) }; /* could check if the 2 faces images match here, * but then there wouldn't be a way to return the opposite face's info */ @@ -1047,7 +1049,7 @@ static bool check_seam( /* Only need to check if 'i2_fidx' is valid because we know i1_fidx is the same vert on both faces */ if (i2_fidx != -1) { - const float *lt_tri_uv[3] = { PS_LOOPTRI_AS_UV_3(ps->dm_mloopuv, lt) }; + const float *lt_tri_uv[3] = { PS_LOOPTRI_AS_UV_3(ps->poly_to_loop_uv, lt) }; Image *tpage = project_paint_face_paint_image(ps, tri_index); Image *orig_tpage = project_paint_face_paint_image(ps, orig_face); @@ -1351,8 +1353,8 @@ static float project_paint_uvpixel_mask( Image *other_tpage = ps->stencil_ima; if (other_tpage && (ibuf_other = BKE_image_acquire_ibuf(other_tpage, NULL, NULL))) { - const MLoopTri *lt_other = &ps->dm_mlooptri[tri_index]; - const float *lt_other_tri_uv[3] = { PS_LOOPTRI_AS_UV_3(ps->dm_mloopuv, lt_other) }; + const MLoopTri *lt_other = &ps->mlooptri_eval[tri_index]; + const float *lt_other_tri_uv[3] = { PS_LOOPTRI_AS_UV_3(ps->poly_to_loop_uv, lt_other) }; /* BKE_image_acquire_ibuf - TODO - this may be slow */ unsigned char rgba_ub[4]; @@ -1385,7 +1387,7 @@ static float project_paint_uvpixel_mask( } if (ps->do_mask_cavity) { - const MLoopTri *lt = &ps->dm_mlooptri[tri_index]; + const MLoopTri *lt = &ps->mlooptri_eval[tri_index]; const int lt_vtri[3] = { PS_LOOPTRI_AS_VERT_INDEX_3(ps, lt) }; float ca1, ca2, ca3, ca_mask; ca1 = ps->cavities[lt_vtri[0]]; @@ -1400,16 +1402,16 @@ static float project_paint_uvpixel_mask( /* calculate mask */ if (ps->do_mask_normal) { - const MLoopTri *lt = &ps->dm_mlooptri[tri_index]; + const MLoopTri *lt = &ps->mlooptri_eval[tri_index]; const int lt_vtri[3] = { PS_LOOPTRI_AS_VERT_INDEX_3(ps, lt) }; - const MPoly *mp = &ps->dm_mpoly[lt->poly]; + const MPoly *mp = &ps->mpoly_eval[lt->poly]; float no[3], angle_cos; if (mp->flag & ME_SMOOTH) { const short *no1, *no2, *no3; - no1 = ps->dm_mvert[lt_vtri[0]].no; - no2 = ps->dm_mvert[lt_vtri[1]].no; - no3 = ps->dm_mvert[lt_vtri[2]].no; + no1 = ps->mvert_eval[lt_vtri[0]].no; + no2 = ps->mvert_eval[lt_vtri[1]].no; + no3 = ps->mvert_eval[lt_vtri[2]].no; no[0] = w[0] * no1[0] + w[1] * no2[0] + w[2] * no3[0]; no[1] = w[0] * no1[1] + w[1] * no2[1] + w[2] * no3[1]; @@ -1421,9 +1423,9 @@ static float project_paint_uvpixel_mask( #if 1 /* normalizing per pixel isn't optimal, we could cache or check ps->*/ normal_tri_v3(no, - ps->dm_mvert[lt_vtri[0]].co, - ps->dm_mvert[lt_vtri[1]].co, - ps->dm_mvert[lt_vtri[2]].co); + ps->mvert_eval[lt_vtri[0]].co, + ps->mvert_eval[lt_vtri[1]].co, + ps->mvert_eval[lt_vtri[2]].co); #else /* don't use because some modifiers dont have normal data (subsurf for eg) */ copy_v3_v3(no, (float *)ps->dm->getTessFaceData(ps->dm, tri_index, CD_NORMAL)); @@ -1442,9 +1444,9 @@ static float project_paint_uvpixel_mask( /* Annoying but for the perspective view we need to get the pixels location in 3D space :/ */ float viewDirPersp[3]; const float *co1, *co2, *co3; - co1 = ps->dm_mvert[lt_vtri[0]].co; - co2 = ps->dm_mvert[lt_vtri[1]].co; - co3 = ps->dm_mvert[lt_vtri[2]].co; + co1 = ps->mvert_eval[lt_vtri[0]].co; + co2 = ps->mvert_eval[lt_vtri[1]].co; + co3 = ps->mvert_eval[lt_vtri[2]].co; /* Get the direction from the viewPoint to the pixel and normalize */ viewDirPersp[0] = (ps->viewPos[0] - (w[0] * co1[0] + w[1] * co2[0] + w[2] * co3[0])); @@ -1613,13 +1615,13 @@ static ProjPixel *project_paint_uvpixel_init( /* done with view3d_project_float inline */ if (ps->tool == PAINT_TOOL_CLONE) { - if (ps->dm_mloopuv_clone) { + if (ps->poly_to_loop_uv_clone) { ImBuf *ibuf_other; Image *other_tpage = project_paint_face_clone_image(ps, tri_index); if (other_tpage && (ibuf_other = BKE_image_acquire_ibuf(other_tpage, NULL, NULL))) { - const MLoopTri *lt_other = &ps->dm_mlooptri[tri_index]; - const float *lt_other_tri_uv[3] = { PS_LOOPTRI_AS_UV_3(ps->dm_mloopuv_clone, lt_other) }; + const MLoopTri *lt_other = &ps->mlooptri_eval[tri_index]; + const float *lt_other_tri_uv[3] = { PS_LOOPTRI_AS_UV_3(ps->poly_to_loop_uv_clone, lt_other) }; /* BKE_image_acquire_ibuf - TODO - this may be slow */ @@ -2510,9 +2512,9 @@ static void project_paint_face_init( ps->projImages + image_index }; - const MLoopTri *lt = &ps->dm_mlooptri[tri_index]; + const MLoopTri *lt = &ps->mlooptri_eval[tri_index]; const int lt_vtri[3] = { PS_LOOPTRI_AS_VERT_INDEX_3(ps, lt) }; - const float *lt_tri_uv[3] = { PS_LOOPTRI_AS_UV_3(ps->dm_mloopuv, lt) }; + const float *lt_tri_uv[3] = { PS_LOOPTRI_AS_UV_3(ps->poly_to_loop_uv, lt) }; /* UV/pixel seeking data */ int x; /* Image X-Pixel */ @@ -2546,9 +2548,9 @@ static void project_paint_face_init( const bool do_backfacecull = ps->do_backfacecull; const bool do_clip = ps->rv3d ? ps->rv3d->rflag & RV3D_CLIPPING : 0; - vCo[0] = ps->dm_mvert[lt_vtri[0]].co; - vCo[1] = ps->dm_mvert[lt_vtri[1]].co; - vCo[2] = ps->dm_mvert[lt_vtri[2]].co; + vCo[0] = ps->mvert_eval[lt_vtri[0]].co; + vCo[1] = ps->mvert_eval[lt_vtri[1]].co; + vCo[2] = ps->mvert_eval[lt_vtri[2]].co; /* Use lt_uv_pxoffset instead of lt_tri_uv so we can offset the UV half a pixel @@ -2632,9 +2634,9 @@ static void project_paint_face_init( if (do_clip || do_3d_mapping) { interp_v3_v3v3v3( wco, - ps->dm_mvert[lt_vtri[0]].co, - ps->dm_mvert[lt_vtri[1]].co, - ps->dm_mvert[lt_vtri[2]].co, + ps->mvert_eval[lt_vtri[0]].co, + ps->mvert_eval[lt_vtri[1]].co, + ps->mvert_eval[lt_vtri[2]].co, w); if (do_clip && ED_view3d_clipping_test(ps->rv3d, wco, true)) { continue; /* Watch out that no code below this needs to run */ @@ -2814,7 +2816,7 @@ static void project_paint_face_init( !project_bucket_point_occluded(ps, bucketFaceNodes, tri_index, pixelScreenCo)) { /* Only bother calculating the weights if we intersect */ - if (ps->do_mask_normal || ps->dm_mloopuv_clone) { + if (ps->do_mask_normal || ps->poly_to_loop_uv_clone) { const float uv_fac = fac1 + (fac * (fac2 - fac1)); #if 0 /* get the UV on the line since we want to copy the pixels from there for bleeding */ @@ -3067,24 +3069,6 @@ static void project_paint_delayed_face_init(ProjPaintState *ps, const MLoopTri * #endif } -/** - * \note when using subsurf or multires, some arrays are thrown away, we need to keep a copy - */ -static void proj_paint_state_non_cddm_init(ProjPaintState *ps) -{ - if (ps->dm->type != DM_TYPE_CDDM) { - ps->dm_mvert = MEM_dupallocN(ps->dm_mvert); - ps->dm_mpoly = MEM_dupallocN(ps->dm_mpoly); - ps->dm_mloop = MEM_dupallocN(ps->dm_mloop); - /* looks like these are ok for now.*/ -#if 0 - ps->dm_mloopuv = MEM_dupallocN(ps->dm_mloopuv); - ps->dm_mloopuv_clone = MEM_dupallocN(ps->dm_mloopuv_clone); - ps->dm_mloopuv_stencil = MEM_dupallocN(ps->dm_mloopuv_stencil); -#endif - } -} - static void proj_paint_state_viewport_init( ProjPaintState *ps, const Depsgraph *depsgraph, const char symmetry_flag) { @@ -3204,11 +3188,11 @@ static void proj_paint_state_screen_coords_init(ProjPaintState *ps, const int di INIT_MINMAX2(ps->screenMin, ps->screenMax); - ps->screenCoords = MEM_mallocN(sizeof(float) * ps->dm_totvert * 4, "ProjectPaint ScreenVerts"); + ps->screenCoords = MEM_mallocN(sizeof(float) * ps->totvert_eval * 4, "ProjectPaint ScreenVerts"); projScreenCo = *ps->screenCoords; if (ps->is_ortho) { - for (a = 0, mv = ps->dm_mvert; a < ps->dm_totvert; a++, mv++, projScreenCo += 4) { + for (a = 0, mv = ps->mvert_eval; a < ps->totvert_eval; a++, mv++, projScreenCo += 4) { mul_v3_m4v3(projScreenCo, ps->projectMat, mv->co); /* screen space, not clamped */ @@ -3218,7 +3202,7 @@ static void proj_paint_state_screen_coords_init(ProjPaintState *ps, const int di } } else { - for (a = 0, mv = ps->dm_mvert; a < ps->dm_totvert; a++, mv++, projScreenCo += 4) { + for (a = 0, mv = ps->mvert_eval; a < ps->totvert_eval; a++, mv++, projScreenCo += 4) { copy_v3_v3(projScreenCo, mv->co); projScreenCo[3] = 1.0f; @@ -3279,21 +3263,21 @@ static void proj_paint_state_cavity_init(ProjPaintState *ps) int a; if (ps->do_mask_cavity) { - int *counter = MEM_callocN(sizeof(int) * ps->dm_totvert, "counter"); - float (*edges)[3] = MEM_callocN(sizeof(float) * 3 * ps->dm_totvert, "edges"); - ps->cavities = MEM_mallocN(sizeof(float) * ps->dm_totvert, "ProjectPaint Cavities"); + int *counter = MEM_callocN(sizeof(int) * ps->totvert_eval, "counter"); + float (*edges)[3] = MEM_callocN(sizeof(float) * 3 * ps->totvert_eval, "edges"); + ps->cavities = MEM_mallocN(sizeof(float) * ps->totvert_eval, "ProjectPaint Cavities"); cavities = ps->cavities; - for (a = 0, me = ps->dm_medge; a < ps->dm_totedge; a++, me++) { + for (a = 0, me = ps->medge_eval; a < ps->totedge_eval; a++, me++) { float e[3]; - sub_v3_v3v3(e, ps->dm_mvert[me->v1].co, ps->dm_mvert[me->v2].co); + sub_v3_v3v3(e, ps->mvert_eval[me->v1].co, ps->mvert_eval[me->v2].co); normalize_v3(e); add_v3_v3(edges[me->v2], e); counter[me->v2]++; sub_v3_v3(edges[me->v1], e); counter[me->v1]++; } - for (a = 0, mv = ps->dm_mvert; a < ps->dm_totvert; a++, mv++) { + for (a = 0, mv = ps->mvert_eval; a < ps->totvert_eval; a++, mv++) { if (counter[a] > 0) { float no[3]; mul_v3_fl(edges[a], 1.0f / counter[a]); @@ -3314,10 +3298,10 @@ static void proj_paint_state_cavity_init(ProjPaintState *ps) static void proj_paint_state_seam_bleed_init(ProjPaintState *ps) { if (ps->seam_bleed_px > 0.0f) { - ps->vertFaces = MEM_callocN(sizeof(LinkNode *) * ps->dm_totvert, "paint-vertFaces"); - ps->faceSeamFlags = MEM_callocN(sizeof(char) * ps->dm_totlooptri, "paint-faceSeamFlags"); - ps->faceWindingFlags = MEM_callocN(sizeof(char) * ps->dm_totlooptri, "paint-faceWindindFlags"); - ps->faceSeamUVs = MEM_mallocN(sizeof(float[3][2]) * ps->dm_totlooptri, "paint-faceSeamUVs"); + ps->vertFaces = MEM_callocN(sizeof(LinkNode *) * ps->totvert_eval, "paint-vertFaces"); + ps->faceSeamFlags = MEM_callocN(sizeof(char) * ps->totlooptri_eval, "paint-faceSeamFlags"); + ps->faceWindingFlags = MEM_callocN(sizeof(char) * ps->totlooptri_eval, "paint-faceWindindFlags"); + ps->faceSeamUVs = MEM_mallocN(sizeof(float[3][2]) * ps->totlooptri_eval, "paint-faceSeamUVs"); } } #endif @@ -3361,9 +3345,9 @@ static void proj_paint_state_vert_flags_init(ProjPaintState *ps) float no[3]; int a; - ps->vertFlags = MEM_callocN(sizeof(char) * ps->dm_totvert, "paint-vertFlags"); + ps->vertFlags = MEM_callocN(sizeof(char) * ps->totvert_eval, "paint-vertFlags"); - for (a = 0, mv = ps->dm_mvert; a < ps->dm_totvert; a++, mv++) { + for (a = 0, mv = ps->mvert_eval; a < ps->totvert_eval; a++, mv++) { normal_short_to_float_v3(no, mv->no); if (UNLIKELY(ps->is_flip_object)) { negate_v3(no); @@ -3408,58 +3392,63 @@ static void project_paint_bleed_add_face_user( } #endif -/* Return true if DM can be painted on, false otherwise */ -static bool proj_paint_state_dm_init(const bContext *C, ProjPaintState *ps) +/* Return true if evaluated mesh can be painted on, false otherwise */ +static bool proj_paint_state_mesh_eval_init(const bContext *C, ProjPaintState *ps) { Depsgraph *depsgraph = CTX_data_depsgraph(C); + Scene *sce = ps->scene; + Object *ob = ps->ob; /* Workaround for subsurf selection, try the display mesh first */ + /* XXX Don't think this is easily doable with new system, and not sure why that was needed in the first place :/ */ +#if 0 if (ps->source == PROJ_SRC_IMAGE_CAM) { /* using render mesh, assume only camera was rendered from */ - ps->dm = mesh_create_derived_render(depsgraph, ps->scene, ps->ob, ps->scene->customdata_mask | CD_MASK_MTFACE); + ps->dm = mesh_create_derived_render( + depsgraph, ps->scene, ps->ob, ps->scene->customdata_mask | CD_MASK_MLOOPUV | CD_MASK_MTFACE); ps->dm_release = true; } - else if (ps->ob->derivedFinal && - CustomData_has_layer(&ps->ob->derivedFinal->loopData, CD_MLOOPUV) && - (ps->do_face_sel == false || CustomData_has_layer(&ps->ob->derivedFinal->polyData, CD_ORIGINDEX))) - { - ps->dm = ps->ob->derivedFinal; - ps->dm_release = false; - } else { ps->dm = mesh_get_derived_final( depsgraph, ps->scene, ps->ob, - ps->scene->customdata_mask | CD_MASK_MTFACE | (ps->do_face_sel ? CD_ORIGINDEX : 0)); - ps->dm_release = true; + ps->scene->customdata_mask | CD_MASK_MLOOPUV | CD_MASK_MTFACE | (ps->do_face_sel ? CD_MASK_ORIGINDEX : 0)); + ps->dm_release = false; } - - if (!CustomData_has_layer(&ps->dm->loopData, CD_MLOOPUV)) { - - if (ps->dm_release) - ps->dm->release(ps->dm); - - ps->dm = NULL; +#endif + ps->me_eval = mesh_get_eval_final( + depsgraph, sce, ob, + sce->customdata_mask | CD_MASK_MLOOPUV | CD_MASK_MTFACE | (ps->do_face_sel ? CD_MASK_ORIGINDEX : 0)); + if (!CustomData_has_layer(&ps->me_eval->ldata, CD_MLOOPUV)) { + ps->me_eval = NULL; return false; } - DM_update_materials(ps->dm, ps->ob); - - ps->dm_mvert = ps->dm->getVertArray(ps->dm); - - if (ps->do_mask_cavity) - ps->dm_medge = ps->dm->getEdgeArray(ps->dm); + /* Build final material array, we use this a lot here. */ + const int totmat = ob->totcol + 1; /* materials start from 1, default material is 0 */ + ps->mat_array = MEM_malloc_arrayN(totmat, sizeof(*ps->mat_array), __func__); + /* We leave last material as empty - rationale here is being able to index + * the materials by using the mf->mat_nr directly and leaving the last + * material as NULL in case no materials exist on mesh, so indexing will not fail. */ + for (int i = 0; i < totmat - 1; i++) { + ps->mat_array[i] = give_current_material(ob, i + 1); + } + ps->mat_array[totmat - 1] = NULL; - ps->dm_mloop = ps->dm->getLoopArray(ps->dm); - ps->dm_mpoly = ps->dm->getPolyArray(ps->dm); + ps->mvert_eval = ps->me_eval->mvert; + if (ps->do_mask_cavity) { + ps->medge_eval = ps->me_eval->medge; + } + ps->mloop_eval = ps->me_eval->mloop; + ps->mpoly_eval = ps->me_eval->mpoly; - ps->dm_mlooptri = ps->dm->getLoopTriArray(ps->dm); + ps->totvert_eval = ps->me_eval->totvert; + ps->totedge_eval = ps->me_eval->totedge; + ps->totpoly_eval = ps->me_eval->totpoly; - ps->dm_totvert = ps->dm->getNumVerts(ps->dm); - ps->dm_totedge = ps->dm->getNumEdges(ps->dm); - ps->dm_totpoly = ps->dm->getNumPolys(ps->dm); - ps->dm_totlooptri = ps->dm->getNumLoopTri(ps->dm); + ps->mlooptri_eval = BKE_mesh_runtime_looptri_ensure(ps->me_eval); + ps->totlooptri_eval = ps->me_eval->runtime.looptris.len; - ps->dm_mloopuv = MEM_mallocN(ps->dm_totpoly * sizeof(MLoopUV *), "proj_paint_mtfaces"); + ps->poly_to_loop_uv = MEM_mallocN(ps->totpoly_eval * sizeof(MLoopUV *), "proj_paint_mtfaces"); return true; } @@ -3480,14 +3469,14 @@ static void proj_paint_layer_clone_init( if (ps->do_layer_clone) { const int layer_num = CustomData_get_clone_layer(&((Mesh *)ps->ob->data)->ldata, CD_MLOOPUV); - ps->dm_mloopuv_clone = MEM_mallocN(ps->dm_totpoly * sizeof(MLoopUV *), "proj_paint_mtfaces"); + ps->poly_to_loop_uv_clone = MEM_mallocN(ps->totpoly_eval * sizeof(MLoopUV *), "proj_paint_mtfaces"); if (layer_num != -1) - mloopuv_clone_base = CustomData_get_layer_n(&ps->dm->loopData, CD_MLOOPUV, layer_num); + mloopuv_clone_base = CustomData_get_layer_n(&ps->me_eval->ldata, CD_MLOOPUV, layer_num); if (mloopuv_clone_base == NULL) { /* get active instead */ - mloopuv_clone_base = CustomData_get_layer(&ps->dm->loopData, CD_MLOOPUV); + mloopuv_clone_base = CustomData_get_layer(&ps->me_eval->ldata, CD_MLOOPUV); } } @@ -3517,17 +3506,17 @@ static bool project_paint_clone_face_skip( if (lc->slot_clone != lc->slot_last_clone) { if (!slot->uvname || !(lc->mloopuv_clone_base = CustomData_get_layer_named( - &ps->dm->loopData, CD_MLOOPUV, + &ps->me_eval->ldata, CD_MLOOPUV, lc->slot_clone->uvname))) { - lc->mloopuv_clone_base = CustomData_get_layer(&ps->dm->loopData, CD_MLOOPUV); + lc->mloopuv_clone_base = CustomData_get_layer(&ps->me_eval->ldata, CD_MLOOPUV); } lc->slot_last_clone = lc->slot_clone; } } /* will set multiple times for 4+ sided poly */ - ps->dm_mloopuv_clone[ps->dm_mlooptri[tri_index].poly] = lc->mloopuv_clone_base; + ps->poly_to_loop_uv_clone[ps->mlooptri_eval[tri_index].poly] = lc->mloopuv_clone_base; } return false; } @@ -3544,7 +3533,7 @@ static void proj_paint_face_lookup_init( { memset(face_lookup, 0, sizeof(*face_lookup)); if (ps->do_face_sel) { - face_lookup->index_mp_to_orig = ps->dm->getPolyDataArray(ps->dm, CD_ORIGINDEX); + face_lookup->index_mp_to_orig = CustomData_get_layer(&ps->me_eval->pdata, CD_ORIGINDEX); face_lookup->mpoly_orig = ((Mesh *)ps->ob->data)->mpoly; } } @@ -3565,7 +3554,7 @@ static bool project_paint_check_face_sel( mp = &face_lookup->mpoly_orig[orig_index]; } else { - mp = &ps->dm_mpoly[lt->poly]; + mp = &ps->mpoly_eval[lt->poly]; } return ((mp->flag & ME_FACE_SEL) != 0); @@ -3679,7 +3668,7 @@ static void project_paint_prepare_all_faces( int image_index = -1, tri_index; int prev_poly = -1; - for (tri_index = 0, lt = ps->dm_mlooptri; tri_index < ps->dm_totlooptri; tri_index++, lt++) { + for (tri_index = 0, lt = ps->mlooptri_eval; tri_index < ps->totlooptri_eval; tri_index++, lt++) { bool is_face_sel; #ifndef PROJ_DEBUG_NOSEAMBLEED @@ -3692,13 +3681,13 @@ static void project_paint_prepare_all_faces( slot = project_paint_face_paint_slot(ps, tri_index); /* all faces should have a valid slot, reassert here */ if (slot == NULL) { - mloopuv_base = CustomData_get_layer(&ps->dm->loopData, CD_MLOOPUV); + mloopuv_base = CustomData_get_layer(&ps->me_eval->ldata, CD_MLOOPUV); tpage = ps->canvas_ima; } else { if (slot != slot_last) { - if (!slot->uvname || !(mloopuv_base = CustomData_get_layer_named(&ps->dm->loopData, CD_MLOOPUV, slot->uvname))) - mloopuv_base = CustomData_get_layer(&ps->dm->loopData, CD_MLOOPUV); + if (!slot->uvname || !(mloopuv_base = CustomData_get_layer_named(&ps->me_eval->ldata, CD_MLOOPUV, slot->uvname))) + mloopuv_base = CustomData_get_layer(&ps->me_eval->ldata, CD_MLOOPUV); slot_last = slot; } @@ -3706,7 +3695,7 @@ static void project_paint_prepare_all_faces( if (slot->ima == ps->stencil_ima) { /* While this shouldn't be used, face-winding reads all polys. * It's less trouble to set all faces to valid UV's, avoiding NULL checks all over. */ - ps->dm_mloopuv[lt->poly] = mloopuv_base; + ps->poly_to_loop_uv[lt->poly] = mloopuv_base; continue; } @@ -3717,7 +3706,7 @@ static void project_paint_prepare_all_faces( tpage = ps->stencil_ima; } - ps->dm_mloopuv[lt->poly] = mloopuv_base; + ps->poly_to_loop_uv[lt->poly] = mloopuv_base; if (project_paint_clone_face_skip(ps, layer_clone, slot, tri_index)) { continue; @@ -3748,11 +3737,11 @@ static void project_paint_prepare_all_faces( if (prev_poly != lt->poly) { int iloop; bool culled = true; - const MPoly *poly = ps->dm_mpoly + lt->poly; + const MPoly *poly = ps->mpoly_eval + lt->poly; int poly_loops = poly->totloop; prev_poly = lt->poly; for (iloop = 0; iloop < poly_loops; iloop++) { - if (!(ps->vertFlags[ps->dm_mloop[poly->loopstart + iloop].v] & PROJ_VERT_CULL)) { + if (!(ps->vertFlags[ps->mloop_eval[poly->loopstart + iloop].v] & PROJ_VERT_CULL)) { culled = false; break; } @@ -3831,7 +3820,7 @@ static void project_paint_begin( /* paint onto the derived mesh */ if (ps->is_shared_user == false) { - if (!proj_paint_state_dm_init(C, ps)) { + if (!proj_paint_state_mesh_eval_init(C, ps)) { return; } } @@ -3840,24 +3829,22 @@ static void project_paint_begin( proj_paint_layer_clone_init(ps, &layer_clone); if (ps->do_layer_stencil || ps->do_stencil_brush) { - //int layer_num = CustomData_get_stencil_layer(&ps->dm->loopData, CD_MLOOPUV); + //int layer_num = CustomData_get_stencil_layer(&ps->me_eval->ldata, CD_MLOOPUV); int layer_num = CustomData_get_stencil_layer(&((Mesh *)ps->ob->data)->ldata, CD_MLOOPUV); if (layer_num != -1) - ps->dm_mloopuv_stencil = CustomData_get_layer_n(&ps->dm->loopData, CD_MLOOPUV, layer_num); + ps->mloopuv_stencil_eval = CustomData_get_layer_n(&ps->me_eval->ldata, CD_MLOOPUV, layer_num); - if (ps->dm_mloopuv_stencil == NULL) { + if (ps->mloopuv_stencil_eval == NULL) { /* get active instead */ - ps->dm_mloopuv_stencil = CustomData_get_layer(&ps->dm->loopData, CD_MLOOPUV); + ps->mloopuv_stencil_eval = CustomData_get_layer(&ps->me_eval->ldata, CD_MLOOPUV); } if (ps->do_stencil_brush) - mloopuv_base = ps->dm_mloopuv_stencil; + mloopuv_base = ps->mloopuv_stencil_eval; } /* when using subsurf or multires, mface arrays are thrown away, we need to keep a copy */ if (ps->is_shared_user == false) { - proj_paint_state_non_cddm_init(ps); - proj_paint_state_cavity_init(ps); } @@ -3947,14 +3934,17 @@ static void project_paint_end(ProjPaintState *ps) MEM_freeN(ps->bucketFlags); if (ps->is_shared_user == false) { + if (ps->mat_array != NULL) { + MEM_freeN(ps->mat_array); + } /* must be set for non-shared */ - BLI_assert(ps->dm_mloopuv || ps->is_shared_user); - if (ps->dm_mloopuv) - MEM_freeN((void *)ps->dm_mloopuv); + BLI_assert(ps->poly_to_loop_uv || ps->is_shared_user); + if (ps->poly_to_loop_uv) + MEM_freeN((void *)ps->poly_to_loop_uv); if (ps->do_layer_clone) - MEM_freeN((void *)ps->dm_mloopuv_clone); + MEM_freeN((void *)ps->poly_to_loop_uv_clone); if (ps->thread_tot > 1) { BLI_spin_end(ps->tile_lock); MEM_freeN((void *)ps->tile_lock); @@ -3974,22 +3964,6 @@ static void project_paint_end(ProjPaintState *ps) if (ps->do_mask_cavity) { MEM_freeN(ps->cavities); } - - /* copy for subsurf/multires, so throw away */ - if (ps->dm->type != DM_TYPE_CDDM) { - if (ps->dm_mvert) MEM_freeN((void *)ps->dm_mvert); - if (ps->dm_mpoly) MEM_freeN((void *)ps->dm_mpoly); - if (ps->dm_mloop) MEM_freeN((void *)ps->dm_mloop); - /* looks like these don't need copying */ -#if 0 - if (ps->dm_mloopuv) MEM_freeN(ps->dm_mloopuv); - if (ps->dm_mloopuv_clone) MEM_freeN(ps->dm_mloopuv_clone); - if (ps->dm_mloopuv_stencil) MEM_freeN(ps->dm_mloopuv_stencil); -#endif - } - - if (ps->dm_release) - ps->dm->release(ps->dm); } if (ps->blurkernel) { @@ -4864,7 +4838,7 @@ static bool project_paint_op(void *state, const float lastpos[2], const float po struct ImagePool *pool; if (!project_bucket_iter_init(ps, pos)) { - return 0; + return touch_any; } if (ps->thread_tot > 1) @@ -4930,16 +4904,16 @@ static bool project_paint_op(void *state, const float lastpos[2], const float po tri_index = project_paint_PickFace(ps, pos, w); if (tri_index != -1) { - const MLoopTri *lt = &ps->dm_mlooptri[tri_index]; + const MLoopTri *lt = &ps->mlooptri_eval[tri_index]; const int lt_vtri[3] = { PS_LOOPTRI_AS_VERT_INDEX_3(ps, lt) }; float world[3]; UnifiedPaintSettings *ups = &ps->scene->toolsettings->unified_paint_settings; interp_v3_v3v3v3( world, - ps->dm_mvert[lt_vtri[0]].co, - ps->dm_mvert[lt_vtri[1]].co, - ps->dm_mvert[lt_vtri[2]].co, + ps->mvert_eval[lt_vtri[0]].co, + ps->mvert_eval[lt_vtri[1]].co, + ps->mvert_eval[lt_vtri[2]].co, w); ups->average_stroke_counter++; @@ -5228,13 +5202,11 @@ void *paint_proj_new_stroke(bContext *C, Object *ob, const float mouse[2], int m } project_paint_begin(C, ps, is_multi_view, symmetry_flag_views[i]); - - paint_proj_begin_clone(ps, mouse); - - if (ps->dm == NULL) { + if (ps->me_eval == NULL) { goto fail; - return NULL; } + + paint_proj_begin_clone(ps, mouse); } paint_brush_init_tex(ps_handle->brush); @@ -5382,8 +5354,9 @@ static int texture_paint_camera_project_exec(bContext *C, wmOperator *op) /* allocate and initialize spatial data structures */ project_paint_begin(C, &ps, false, 0); - if (ps.dm == NULL) { + if (ps.me_eval == NULL) { BKE_brush_size_set(scene, ps.brush, orig_brush_size); + BKE_report(op->reports, RPT_ERROR, "Could not get valid evaluated mesh"); return OPERATOR_CANCELLED; } else { @@ -5791,6 +5764,7 @@ void PAINT_OT_add_texture_paint_slot(wmOperatorType *ot) static int add_simple_uvs_exec(bContext *C, wmOperator *UNUSED(op)) { /* no checks here, poll function does them for us */ + Main *bmain = CTX_data_main(C); Object *ob = CTX_data_active_object(C); Scene *scene = CTX_data_scene(C); Mesh *me = ob->data; @@ -5815,7 +5789,7 @@ static int add_simple_uvs_exec(bContext *C, wmOperator *UNUSED(op)) /* set the margin really quickly before the packing operation*/ scene->toolsettings->uvcalc_margin = 0.001f; ED_uvedit_pack_islands(scene, ob, bm, false, false, true); - BM_mesh_bm_to_me(bm, me, (&(struct BMeshToMeshParams){0})); + BM_mesh_bm_to_me(bmain, bm, me, (&(struct BMeshToMeshParams){0})); BM_mesh_free(bm); if (synch_selection) diff --git a/source/blender/editors/sculpt_paint/paint_stroke.c b/source/blender/editors/sculpt_paint/paint_stroke.c index b63f9461401..a7aa19807dd 100644 --- a/source/blender/editors/sculpt_paint/paint_stroke.c +++ b/source/blender/editors/sculpt_paint/paint_stroke.c @@ -38,6 +38,8 @@ #include "BLI_rand.h" #include "BLI_listbase.h" +#include "PIL_time.h" + #include "DNA_object_types.h" #include "DNA_scene_types.h" #include "DNA_brush_types.h" @@ -86,6 +88,7 @@ typedef struct PaintStroke { void *mode_data; void *stroke_cursor; wmTimer *timer; + struct RNG *rng; /* Cached values */ ViewContext vc; @@ -403,17 +406,24 @@ static bool paint_brush_update(bContext *C, } } + if ((do_random || do_random_mask) && stroke->rng == NULL) { + /* Lazy initialization. */ + uint rng_seed = (uint)(PIL_check_seconds_timer_i() & UINT_MAX); + rng_seed ^= (uint)GET_INT_FROM_POINTER(brush); + stroke->rng = BLI_rng_new(rng_seed); + } + if (do_random) { if (brush->mtex.brush_angle_mode & MTEX_ANGLE_RANDOM) { ups->brush_rotation += -brush->mtex.random_angle / 2.0f + - brush->mtex.random_angle * BLI_frand(); + brush->mtex.random_angle * BLI_rng_get_float(stroke->rng); } } if (do_random_mask) { if (brush->mask_mtex.brush_angle_mode & MTEX_ANGLE_RANDOM) { ups->brush_rotation_sec += -brush->mask_mtex.random_angle / 2.0f + - brush->mask_mtex.random_angle * BLI_frand(); + brush->mask_mtex.random_angle * BLI_rng_get_float(stroke->rng); } } @@ -785,6 +795,10 @@ static void stroke_done(struct bContext *C, struct wmOperator *op) stroke->timer); } + if (stroke->rng) { + BLI_rng_free(stroke->rng); + } + if (stroke->stroke_cursor) WM_paint_cursor_end(CTX_wm_manager(C), stroke->stroke_cursor); diff --git a/source/blender/editors/sculpt_paint/paint_vertex.c b/source/blender/editors/sculpt_paint/paint_vertex.c index ac6bfe019a1..85a1f11be4b 100644 --- a/source/blender/editors/sculpt_paint/paint_vertex.c +++ b/source/blender/editors/sculpt_paint/paint_vertex.c @@ -967,15 +967,20 @@ static void do_weight_paint_vertex( /* Toggle operator for turning vertex paint mode on or off (copied from sculpt.c) */ -static void vertex_paint_init_session(Depsgraph *depsgraph, Scene *scene, Object *ob) +static void vertex_paint_init_session(Depsgraph *depsgraph, Scene *scene, Object *ob, eObjectMode object_mode) { /* Create persistent sculpt mode data */ BKE_sculpt_toolsettings_data_ensure(scene); - if (ob->sculpt == NULL) { - ob->sculpt = MEM_callocN(sizeof(SculptSession), "sculpt session"); - BKE_sculpt_update_mesh_elements(depsgraph, scene, scene->toolsettings->sculpt, ob, false, false); - } + BLI_assert(ob->sculpt == NULL); + ob->sculpt = MEM_callocN(sizeof(SculptSession), "sculpt session"); + ob->sculpt->mode_type = object_mode; + BKE_sculpt_update_mesh_elements(depsgraph, scene, scene->toolsettings->sculpt, ob, false, false); +} + +static void vertex_paint_init_stroke(Depsgraph *depsgraph, Scene *scene, Object *ob) +{ + BKE_sculpt_update_mesh_elements(depsgraph, scene, scene->toolsettings->sculpt, ob, false, false); } static void vertex_paint_init_session_data(const ToolSettings *ts, Object *ob) @@ -986,12 +991,12 @@ static void vertex_paint_init_session_data(const ToolSettings *ts, Object *ob) if (ob->mode == OB_MODE_VERTEX_PAINT) { gmap = &ob->sculpt->mode.vpaint.gmap; brush = BKE_paint_brush(&ts->vpaint->paint); - ob->sculpt->mode_type = OB_MODE_VERTEX_PAINT; + BLI_assert(ob->sculpt->mode_type == OB_MODE_VERTEX_PAINT); } else if (ob->mode == OB_MODE_WEIGHT_PAINT) { gmap = &ob->sculpt->mode.wpaint.gmap; brush = BKE_paint_brush(&ts->wpaint->paint); - ob->sculpt->mode_type = OB_MODE_WEIGHT_PAINT; + BLI_assert(ob->sculpt->mode_type == OB_MODE_WEIGHT_PAINT); } else { ob->sculpt->mode_type = 0; @@ -1113,7 +1118,7 @@ static void ed_vwpaintmode_enter_generic( BKE_sculptsession_free(ob); } - vertex_paint_init_session(depsgraph, scene, ob); + vertex_paint_init_session(depsgraph, scene, ob, mode_flag); /* Flush object mode. */ DEG_id_tag_update(&ob->id, DEG_TAG_COPY_ON_WRITE); @@ -1556,7 +1561,7 @@ static bool wpaint_stroke_test_start(bContext *C, wmOperator *op, const float mo } /* If not previously created, create vertex/weight paint mode session data */ - vertex_paint_init_session(depsgraph, scene, ob); + vertex_paint_init_stroke(depsgraph, scene, ob); vwpaint_update_cache_invariants(C, vp, ss, op, mouse); vertex_paint_init_session_data(ts, ob); @@ -2545,7 +2550,7 @@ static bool vpaint_stroke_test_start(bContext *C, struct wmOperator *op, const f } /* If not previously created, create vertex/weight paint mode session data */ - vertex_paint_init_session(depsgraph, scene, ob); + vertex_paint_init_stroke(depsgraph, scene, ob); vwpaint_update_cache_invariants(C, vp, ss, op, mouse); vertex_paint_init_session_data(ts, ob); 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 7c2977a0788..01c62704db3 100644 --- a/source/blender/editors/sculpt_paint/paint_vertex_weight_ops.c +++ b/source/blender/editors/sculpt_paint/paint_vertex_weight_ops.c @@ -51,6 +51,7 @@ #include "BKE_context.h" #include "BKE_deform.h" #include "BKE_mesh.h" +#include "BKE_mesh_iterators.h" #include "BKE_mesh_mapping.h" #include "BKE_mesh_runtime.h" #include "BKE_modifier.h" @@ -534,21 +535,21 @@ void PAINT_OT_weight_set(wmOperatorType *ot) * \{ */ /* *** VGroups Gradient *** */ -typedef struct DMGradient_vertStore { +typedef struct WPGradient_vertStore { float sco[2]; float weight_orig; enum { VGRAD_STORE_NOP = 0, VGRAD_STORE_DW_EXIST = (1 << 0) } flag; -} DMGradient_vertStore; +} WPGradient_vertStore; -typedef struct DMGradient_vertStoreBase { +typedef struct WPGradient_vertStoreBase { struct WPaintPrev wpp; - DMGradient_vertStore elem[0]; -} DMGradient_vertStoreBase; + WPGradient_vertStore elem[0]; +} WPGradient_vertStoreBase; -typedef struct DMGradient_userData { +typedef struct WPGradient_userData { struct ARegion *ar; Scene *scene; Mesh *me; @@ -558,7 +559,7 @@ typedef struct DMGradient_userData { float sco_line_div; /* store (1.0f / len_v2v2(sco_start, sco_end)) */ int def_nr; bool is_init; - DMGradient_vertStoreBase *vert_cache; + WPGradient_vertStoreBase *vert_cache; /* only for init */ BLI_bitmap *vert_visit; @@ -566,12 +567,12 @@ typedef struct DMGradient_userData { short use_select; short type; float weightpaint; -} DMGradient_userData; +} WPGradient_userData; -static void gradientVert_update(DMGradient_userData *grad_data, int index) +static void gradientVert_update(WPGradient_userData *grad_data, int index) { Mesh *me = grad_data->me; - DMGradient_vertStore *vs = &grad_data->vert_cache->elem[index]; + WPGradient_vertStore *vs = &grad_data->vert_cache->elem[index]; float alpha; if (grad_data->type == WPAINT_GRADIENT_TYPE_LINEAR) { @@ -619,10 +620,10 @@ static void gradientVertUpdate__mapFunc( void *userData, int index, const float UNUSED(co[3]), const float UNUSED(no_f[3]), const short UNUSED(no_s[3])) { - DMGradient_userData *grad_data = userData; + WPGradient_userData *grad_data = userData; Mesh *me = grad_data->me; if ((grad_data->use_select == false) || (me->mvert[index].flag & SELECT)) { - DMGradient_vertStore *vs = &grad_data->vert_cache->elem[index]; + WPGradient_vertStore *vs = &grad_data->vert_cache->elem[index]; if (vs->sco[0] != FLT_MAX) { gradientVert_update(grad_data, index); } @@ -633,7 +634,7 @@ static void gradientVertInit__mapFunc( void *userData, int index, const float co[3], const float UNUSED(no_f[3]), const short UNUSED(no_s[3])) { - DMGradient_userData *grad_data = userData; + WPGradient_userData *grad_data = userData; Mesh *me = grad_data->me; if ((grad_data->use_select == false) || (me->mvert[index].flag & SELECT)) { @@ -642,7 +643,7 @@ static void gradientVertInit__mapFunc( * updating the mesh may move them about (entering feedback loop) */ if (BLI_BITMAP_TEST(grad_data->vert_visit, index) == 0) { - DMGradient_vertStore *vs = &grad_data->vert_cache->elem[index]; + WPGradient_vertStore *vs = &grad_data->vert_cache->elem[index]; if (ED_view3d_project_float_object(grad_data->ar, co, vs->sco, V3D_PROJ_TEST_CLIP_BB | V3D_PROJ_TEST_CLIP_NEAR) == V3D_PROJ_RET_OK) @@ -675,7 +676,7 @@ static void gradientVertInit__mapFunc( static int paint_weight_gradient_modal(bContext *C, wmOperator *op, const wmEvent *event) { wmGesture *gesture = op->customdata; - DMGradient_vertStoreBase *vert_cache = gesture->userdata; + WPGradient_vertStoreBase *vert_cache = gesture->userdata; int ret = WM_gesture_straightline_modal(C, op, event); if (ret & OPERATOR_RUNNING_MODAL) { @@ -711,7 +712,7 @@ static int paint_weight_gradient_modal(bContext *C, wmOperator *op, const wmEven static int paint_weight_gradient_exec(bContext *C, wmOperator *op) { wmGesture *gesture = op->customdata; - DMGradient_vertStoreBase *vert_cache; + WPGradient_vertStoreBase *vert_cache; struct ARegion *ar = CTX_wm_region(C); Scene *scene = CTX_data_scene(C); Object *ob = CTX_data_active_object(C); @@ -726,20 +727,18 @@ static int paint_weight_gradient_exec(bContext *C, wmOperator *op) Depsgraph *depsgraph = CTX_data_depsgraph(C); - DerivedMesh *dm = mesh_get_derived_final(depsgraph, scene, ob, scene->customdata_mask); - - DMGradient_userData data = {NULL}; + WPGradient_userData data = {NULL}; if (is_interactive) { if (gesture->userdata == NULL) { gesture->userdata = MEM_mallocN( - sizeof(DMGradient_vertStoreBase) + - (sizeof(DMGradient_vertStore) * me->totvert), + sizeof(WPGradient_vertStoreBase) + + (sizeof(WPGradient_vertStore) * me->totvert), __func__); gesture->userdata_free = false; data.is_init = true; - wpaint_prev_create(&((DMGradient_vertStoreBase *)gesture->userdata)->wpp, me->dvert, me->totvert); + wpaint_prev_create(&((WPGradient_vertStoreBase *)gesture->userdata)->wpp, me->dvert, me->totvert); /* on init only, convert face -> vert sel */ if (me->editflag & ME_EDIT_PAINT_FACE_SEL) { @@ -756,8 +755,8 @@ static int paint_weight_gradient_exec(bContext *C, wmOperator *op) data.is_init = true; vert_cache = MEM_mallocN( - sizeof(DMGradient_vertStoreBase) + - (sizeof(DMGradient_vertStore) * me->totvert), + sizeof(WPGradient_vertStoreBase) + + (sizeof(WPGradient_vertStore) * me->totvert), __func__); } @@ -786,16 +785,17 @@ static int paint_weight_gradient_exec(bContext *C, wmOperator *op) ED_view3d_init_mats_rv3d(ob, ar->regiondata); + Mesh *me_eval = mesh_get_eval_final(depsgraph, scene, ob, scene->customdata_mask | CD_MASK_ORIGINDEX); if (data.is_init) { data.vert_visit = BLI_BITMAP_NEW(me->totvert, __func__); - dm->foreachMappedVert(dm, gradientVertInit__mapFunc, &data, DM_FOREACH_NOP); + BKE_mesh_foreach_mapped_vert(me_eval, gradientVertInit__mapFunc, &data, MESH_FOREACH_NOP); MEM_freeN(data.vert_visit); data.vert_visit = NULL; } else { - dm->foreachMappedVert(dm, gradientVertUpdate__mapFunc, &data, DM_FOREACH_NOP); + BKE_mesh_foreach_mapped_vert(me_eval, gradientVertUpdate__mapFunc, &data, MESH_FOREACH_NOP); } DEG_id_tag_update(&ob->id, OB_RECALC_DATA); diff --git a/source/blender/editors/sculpt_paint/sculpt.c b/source/blender/editors/sculpt_paint/sculpt.c index 1c76f20d45c..414b9f2062f 100644 --- a/source/blender/editors/sculpt_paint/sculpt.c +++ b/source/blender/editors/sculpt_paint/sculpt.c @@ -4808,7 +4808,7 @@ static void sculpt_brush_init_tex(const Scene *scene, Sculpt *sd, SculptSession sculpt_update_tex(scene, sd, ss); } -static bool sculpt_brush_stroke_init(bContext *C, wmOperator *op) +static void sculpt_brush_stroke_init(bContext *C, wmOperator *op) { Depsgraph *depsgraph = CTX_data_depsgraph(C); Scene *scene = CTX_data_scene(C); @@ -4829,8 +4829,6 @@ static bool sculpt_brush_stroke_init(bContext *C, wmOperator *op) is_smooth = sculpt_any_smooth_mode(brush, NULL, mode); BKE_sculpt_update_mesh_elements(depsgraph, scene, sd, ob, is_smooth, need_mask); - - return 1; } static void sculpt_restore_mesh(Sculpt *sd, Object *ob) @@ -5075,8 +5073,7 @@ static int sculpt_brush_stroke_invoke(bContext *C, wmOperator *op, const wmEvent int ignore_background_click; int retval; - if (!sculpt_brush_stroke_init(C, op)) - return OPERATOR_CANCELLED; + sculpt_brush_stroke_init(C, op); stroke = paint_stroke_new(C, op, sculpt_stroke_get_location, sculpt_stroke_test_start, @@ -5108,8 +5105,7 @@ static int sculpt_brush_stroke_invoke(bContext *C, wmOperator *op, const wmEvent static int sculpt_brush_stroke_exec(bContext *C, wmOperator *op) { - if (!sculpt_brush_stroke_init(C, op)) - return OPERATOR_CANCELLED; + sculpt_brush_stroke_init(C, op); op->customdata = paint_stroke_new(C, op, sculpt_stroke_get_location, sculpt_stroke_test_start, sculpt_stroke_update_step, NULL, sculpt_stroke_done, 0); @@ -5666,7 +5662,7 @@ void ED_object_sculptmode_enter_ex( /* Make sure derived final from original object does not reference possibly * freed memory. */ - BKE_object_free_derived_mesh_caches(ob); + BKE_object_free_derived_caches(ob); sculpt_init_session(depsgraph, scene, ob); @@ -5737,7 +5733,7 @@ void ED_object_sculptmode_enter_ex( } } - // ED_workspace_object_mode_sync_from_object(G.main->wm.first, workspace, ob); + // ED_workspace_object_mode_sync_from_object(bmain->wm.first, workspace, ob); /* Flush object mode. */ DEG_id_tag_update(&ob->id, DEG_TAG_COPY_ON_WRITE); @@ -5789,14 +5785,14 @@ void ED_object_sculptmode_exit_ex( /* Leave sculptmode */ ob->mode &= ~mode_flag; - // ED_workspace_object_mode_sync_from_object(G.main->wm.first, workspace, ob); + // ED_workspace_object_mode_sync_from_object(G_MAIN->wm.first, workspace, ob); BKE_sculptsession_free(ob); paint_cursor_delete_textures(); /* Never leave derived meshes behind. */ - BKE_object_free_derived_mesh_caches(ob); + BKE_object_free_derived_caches(ob); /* Flush object mode. */ DEG_id_tag_update(&ob->id, DEG_TAG_COPY_ON_WRITE); diff --git a/source/blender/editors/sound/sound_ops.c b/source/blender/editors/sound/sound_ops.c index b7a80a92998..049feea2d8a 100644 --- a/source/blender/editors/sound/sound_ops.c +++ b/source/blender/editors/sound/sound_ops.c @@ -455,10 +455,10 @@ static bool sound_mixdown_check(bContext *UNUSED(C), wmOperator *op) prop = RNA_struct_find_property(op->ptr, "filepath"); RNA_property_string_get(op->ptr, prop, filepath); - if (BLI_testextensie_array(filepath, snd_ext_sound)) - check = BLI_replace_extension(filepath, FILE_MAX, extension); + if (BLI_path_extension_check_array(filepath, snd_ext_sound)) + check = BLI_path_extension_replace(filepath, FILE_MAX, extension); else - check = BLI_ensure_extension(filepath, FILE_MAX, extension); + check = BLI_path_extension_ensure(filepath, FILE_MAX, extension); if (!check) return check; diff --git a/source/blender/editors/space_action/action_buttons.c b/source/blender/editors/space_action/action_buttons.c index a5cc66add87..55ad773f4df 100644 --- a/source/blender/editors/space_action/action_buttons.c +++ b/source/blender/editors/space_action/action_buttons.c @@ -117,7 +117,7 @@ static int action_properties_toggle_exec(bContext *C, wmOperator *UNUSED(op)) void ACTION_OT_properties(wmOperatorType *ot) { - ot->name = "Properties"; + ot->name = "Toggle Sidebar"; ot->idname = "ACTION_OT_properties"; ot->description = "Toggle the properties region visibility"; diff --git a/source/blender/editors/space_action/action_draw.c b/source/blender/editors/space_action/action_draw.c index 7c8be943a87..35ebb62a7cc 100644 --- a/source/blender/editors/space_action/action_draw.c +++ b/source/blender/editors/space_action/action_draw.c @@ -436,7 +436,7 @@ void timeline_draw_cache(SpaceAction *saction, Object *ob, Scene *scene) continue; gpuPushMatrix(); - gpuTranslate2f(0.0, (float)V2D_SCROLL_HEIGHT + yoffs); + gpuTranslate2f(0.0, (float)V2D_SCROLL_HEIGHT_TEXT + yoffs); gpuScale2f(1.0, cache_draw_height); switch (pid->type) { diff --git a/source/blender/editors/space_action/space_action.c b/source/blender/editors/space_action/space_action.c index e130ea9369c..527e382ec1e 100644 --- a/source/blender/editors/space_action/space_action.c +++ b/source/blender/editors/space_action/space_action.c @@ -116,7 +116,7 @@ static SpaceLink *action_new(const ScrArea *sa, const Scene *scene) BLI_addtail(&saction->regionbase, ar); ar->regiontype = RGN_TYPE_HEADER; - ar->alignment = RGN_ALIGN_BOTTOM; + ar->alignment = RGN_ALIGN_TOP; /* channel list region */ ar = MEM_callocN(sizeof(ARegion), "channel region for action"); @@ -752,7 +752,7 @@ static void action_buttons_area_init(wmWindowManager *wm, ARegion *ar) static void action_buttons_area_draw(const bContext *C, ARegion *ar) { - ED_region_panels(C, ar, NULL, -1, true); + ED_region_panels(C, ar); } static void action_region_listener( diff --git a/source/blender/editors/space_buttons/space_buttons.c b/source/blender/editors/space_buttons/space_buttons.c index be687d365f3..4fe3423e730 100644 --- a/source/blender/editors/space_buttons/space_buttons.c +++ b/source/blender/editors/space_buttons/space_buttons.c @@ -144,7 +144,7 @@ static void buttons_main_region_init(wmWindowManager *wm, ARegion *ar) WM_event_add_keymap_handler(&ar->handlers, keymap); } -static void buttons_main_region_draw_properties(const bContext *C, SpaceButs *sbuts, ARegion *ar) +static void buttons_main_region_layout_properties(const bContext *C, SpaceButs *sbuts, ARegion *ar) { const bool vertical = (sbuts->align == BUT_VERTICAL); @@ -203,12 +203,10 @@ static void buttons_main_region_draw_properties(const bContext *C, SpaceButs *sb break; } - if (contexts[0]) { - ED_region_panels(C, ar, contexts, sbuts->mainb, vertical); - } + ED_region_panels_layout_ex(C, ar, contexts, sbuts->mainb, vertical); } -static void buttons_main_region_draw_tool(const bContext *C, SpaceButs *sbuts, ARegion *ar) +static void buttons_main_region_layout_tool(const bContext *C, SpaceButs *sbuts, ARegion *ar) { const bool vertical = (sbuts->align == BUT_VERTICAL); const char *contexts[3] = {NULL}; @@ -260,30 +258,24 @@ static void buttons_main_region_draw_tool(const bContext *C, SpaceButs *sbuts, A ARRAY_SET_ITEMS(contexts, ".todo"); break; } - if (contexts[0]) { - ED_region_panels(C, ar, contexts, -1, vertical); - } } else if (workspace->tools_space_type == SPACE_IMAGE) { /* TODO */ } - if (contexts[0] == NULL) { - UI_ThemeClearColor(TH_BACK); - glClear(GL_COLOR_BUFFER_BIT); - } + ED_region_panels_layout_ex(C, ar, contexts, -1, vertical); } -static void buttons_main_region_draw(const bContext *C, ARegion *ar) +static void buttons_main_region_layout(const bContext *C, ARegion *ar) { /* draw entirely, view changes should be handled here */ SpaceButs *sbuts = CTX_wm_space_buts(C); if (sbuts->mainb == BCONTEXT_TOOL) { - buttons_main_region_draw_tool(C, sbuts, ar); + buttons_main_region_layout_tool(C, sbuts, ar); } else { - buttons_main_region_draw_properties(C, sbuts, ar); + buttons_main_region_layout_properties(C, sbuts, ar); } sbuts->re_align = 0; @@ -619,7 +611,8 @@ void ED_spacetype_buttons(void) art = MEM_callocN(sizeof(ARegionType), "spacetype buttons region"); art->regionid = RGN_TYPE_WINDOW; art->init = buttons_main_region_init; - art->draw = buttons_main_region_draw; + art->layout = buttons_main_region_layout; + art->draw = ED_region_panels_draw; art->listener = buttons_main_region_listener; art->keymapflag = ED_KEYMAP_UI | ED_KEYMAP_FRAMES; BLI_addhead(&st->regiontypes, art); diff --git a/source/blender/editors/space_clip/clip_buttons.c b/source/blender/editors/space_clip/clip_buttons.c index 469d94fed3a..f2fe06874d7 100644 --- a/source/blender/editors/space_clip/clip_buttons.c +++ b/source/blender/editors/space_clip/clip_buttons.c @@ -387,7 +387,7 @@ void uiTemplateMarker(uiLayout *layout, PointerRNA *ptr, const char *propname, P else tip = TIP_("Marker is enabled at current frame"); - bt = uiDefIconButBitI(block, UI_BTYPE_TOGGLE_N, MARKER_DISABLED, 0, ICON_RESTRICT_VIEW_OFF, 0, 0, UI_UNIT_X, UI_UNIT_Y, + bt = uiDefIconButBitI(block, UI_BTYPE_TOGGLE_N, MARKER_DISABLED, 0, ICON_HIDE_OFF, 0, 0, UI_UNIT_X, UI_UNIT_Y, &cb->marker_flag, 0, 0, 1, 0, tip); UI_but_funcN_set(bt, marker_update_cb, cb, NULL); } diff --git a/source/blender/editors/space_clip/clip_intern.h b/source/blender/editors/space_clip/clip_intern.h index ab8a7add009..e5c4f567d5c 100644 --- a/source/blender/editors/space_clip/clip_intern.h +++ b/source/blender/editors/space_clip/clip_intern.h @@ -145,6 +145,8 @@ void clip_view_center_to_point(SpaceClip *sc, float x, float y); void clip_draw_sfra_efra(struct View2D *v2d, struct Scene *scene); +void clip_on_marker_selection_changed(struct bContext *C); + /* tracking_ops.c */ struct MovieTrackingTrack *tracking_marker_check_slide(struct bContext *C, const struct wmEvent *event, int *area_r, int *action_r, int *corner_r); diff --git a/source/blender/editors/space_clip/clip_toolbar.c b/source/blender/editors/space_clip/clip_toolbar.c index 61bd8df3dbf..3e4d0cd5bb4 100644 --- a/source/blender/editors/space_clip/clip_toolbar.c +++ b/source/blender/editors/space_clip/clip_toolbar.c @@ -106,7 +106,7 @@ static int properties_exec(bContext *C, wmOperator *UNUSED(op)) void CLIP_OT_properties(wmOperatorType *ot) { /* identifiers */ - ot->name = "Properties"; + ot->name = "Toggle Sidebar"; ot->description = "Toggle the properties region visibility"; ot->idname = "CLIP_OT_properties"; @@ -170,7 +170,7 @@ static int tools_exec(bContext *C, wmOperator *UNUSED(op)) void CLIP_OT_tools(wmOperatorType *ot) { /* identifiers */ - ot->name = "Tools"; + ot->name = "Toggle Toolbar"; ot->description = "Toggle clip tools panel"; ot->idname = "CLIP_OT_tools"; diff --git a/source/blender/editors/space_clip/space_clip.c b/source/blender/editors/space_clip/space_clip.c index f022bb7e6f8..b050e991140 100644 --- a/source/blender/editors/space_clip/space_clip.c +++ b/source/blender/editors/space_clip/space_clip.c @@ -1435,7 +1435,7 @@ static void clip_tools_region_init(wmWindowManager *wm, ARegion *ar) static void clip_tools_region_draw(const bContext *C, ARegion *ar) { - ED_region_panels(C, ar, NULL, -1, true); + ED_region_panels(C, ar); } /****************** tool properties region ******************/ @@ -1484,7 +1484,7 @@ static void clip_properties_region_draw(const bContext *C, ARegion *ar) BKE_movieclip_update_scopes(sc->clip, &sc->user, &sc->scopes); - ED_region_panels(C, ar, NULL, -1, true); + ED_region_panels(C, ar); } static void clip_properties_region_listener( diff --git a/source/blender/editors/space_file/filelist.c b/source/blender/editors/space_file/filelist.c index 8123bed541c..09e2660a762 100644 --- a/source/blender/editors/space_file/filelist.c +++ b/source/blender/editors/space_file/filelist.c @@ -267,10 +267,11 @@ typedef struct FileListEntryPreview { ImBuf *img; } FileListEntryPreview; + typedef struct FileListFilter { unsigned int filter; unsigned int filter_id; - char filter_glob[256]; + char filter_glob[FILE_MAXFILE]; char filter_search[66]; /* + 2 for heading/trailing implicit '*' wildcards. */ short flags; } FileListFilter; @@ -1973,31 +1974,31 @@ int ED_path_extension_type(const char *path) else if (file_is_blend_backup(path)) { return FILE_TYPE_BLENDER_BACKUP; } - else if (BLI_testextensie(path, ".app")) { + else if (BLI_path_extension_check(path, ".app")) { return FILE_TYPE_APPLICATIONBUNDLE; } - else if (BLI_testextensie(path, ".py")) { + else if (BLI_path_extension_check(path, ".py")) { return FILE_TYPE_PYSCRIPT; } - else if (BLI_testextensie_n(path, ".txt", ".glsl", ".osl", ".data", ".pov", ".ini", ".mcr", ".inc", NULL)) { + else if (BLI_path_extension_check_n(path, ".txt", ".glsl", ".osl", ".data", ".pov", ".ini", ".mcr", ".inc", NULL)) { return FILE_TYPE_TEXT; } - else if (BLI_testextensie_n(path, ".ttf", ".ttc", ".pfb", ".otf", ".otc", NULL)) { + else if (BLI_path_extension_check_n(path, ".ttf", ".ttc", ".pfb", ".otf", ".otc", NULL)) { return FILE_TYPE_FTFONT; } - else if (BLI_testextensie(path, ".btx")) { + else if (BLI_path_extension_check(path, ".btx")) { return FILE_TYPE_BTX; } - else if (BLI_testextensie(path, ".dae")) { + else if (BLI_path_extension_check(path, ".dae")) { return FILE_TYPE_COLLADA; } - else if (BLI_testextensie(path, ".abc")) { + else if (BLI_path_extension_check(path, ".abc")) { return FILE_TYPE_ALEMBIC; } - else if (BLI_testextensie_array(path, imb_ext_image)) { + else if (BLI_path_extension_check_array(path, imb_ext_image)) { return FILE_TYPE_IMAGE; } - else if (BLI_testextensie(path, ".ogg")) { + else if (BLI_path_extension_check(path, ".ogg")) { if (IMB_isanim(path)) { return FILE_TYPE_MOVIE; } @@ -2005,10 +2006,10 @@ int ED_path_extension_type(const char *path) return FILE_TYPE_SOUND; } } - else if (BLI_testextensie_array(path, imb_ext_movie)) { + else if (BLI_path_extension_check_array(path, imb_ext_movie)) { return FILE_TYPE_MOVIE; } - else if (BLI_testextensie_array(path, imb_ext_audio)) { + else if (BLI_path_extension_check_array(path, imb_ext_audio)) { return FILE_TYPE_SOUND; } return 0; @@ -2233,7 +2234,7 @@ static int filelist_readjob_list_dir( /* Otherwise, do not check extensions for directories! */ else if (!(entry->typeflag & FILE_TYPE_DIR)) { entry->typeflag = file_extension_type(root, entry->relpath); - if (filter_glob[0] && BLI_testextensie_glob(entry->relpath, filter_glob)) { + if (filter_glob[0] && BLI_path_extension_check_glob(entry->relpath, filter_glob)) { entry->typeflag |= FILE_TYPE_OPERATOR; } } @@ -2464,7 +2465,7 @@ static void filelist_readjob_do( BLI_Stack *todo_dirs; TodoDir *td_dir; char dir[FILE_MAX_LIBEXTRA]; - char filter_glob[64]; /* TODO should be define! */ + char filter_glob[FILE_MAXFILE]; const char *root = filelist->filelist.root; const int max_recursion = filelist->max_recursion; int nbr_done_dirs = 0, nbr_todo_dirs = 1; diff --git a/source/blender/editors/space_file/filesel.c b/source/blender/editors/space_file/filesel.c index 418a9f8c16f..cb014f30d95 100644 --- a/source/blender/editors/space_file/filesel.c +++ b/source/blender/editors/space_file/filesel.c @@ -196,6 +196,10 @@ short ED_fileselect_set_params(SpaceFile *sfile) if (tmp != params->filter_glob) { BLI_strncpy(params->filter_glob, tmp, sizeof(params->filter_glob)); MEM_freeN(tmp); + + /* Fix stupid things that truncating might have generated, + * like last group being a 'match everything' wildcard-only one... */ + BLI_path_extension_glob_validate(params->filter_glob); } params->filter |= (FILE_TYPE_OPERATOR | FILE_TYPE_FOLDER); } diff --git a/source/blender/editors/space_file/space_file.c b/source/blender/editors/space_file/space_file.c index 62e7c7923e8..7b045a42595 100644 --- a/source/blender/editors/space_file/space_file.c +++ b/source/blender/editors/space_file/space_file.c @@ -636,7 +636,7 @@ static void file_tools_region_init(wmWindowManager *wm, ARegion *ar) static void file_tools_region_draw(const bContext *C, ARegion *ar) { - ED_region_panels(C, ar, NULL, -1, true); + ED_region_panels(C, ar); } static void file_tools_region_listener( diff --git a/source/blender/editors/space_graph/graph_buttons.c b/source/blender/editors/space_graph/graph_buttons.c index 4f3de0398a2..2a0d5baa5c3 100644 --- a/source/blender/editors/space_graph/graph_buttons.c +++ b/source/blender/editors/space_graph/graph_buttons.c @@ -801,7 +801,7 @@ static void graph_draw_driver_settings_panel(uiLayout *layout, ID *id, FCurve *f if ((G.f & G_SCRIPT_AUTOEXEC) == 0) { /* TODO: Add button to enable? */ - uiItemL(col, IFACE_("ERROR: Python auto-execution disabled"), ICON_CANCEL); + uiItemL(col, IFACE_("WARNING: Python expressions limited for security"), ICON_ERROR); } else if (driver->flag & DRIVER_FLAG_INVALID) { uiItemL(col, IFACE_("ERROR: Invalid Python expression"), ICON_CANCEL); @@ -1207,7 +1207,7 @@ static int graph_properties_toggle_exec(bContext *C, wmOperator *UNUSED(op)) void GRAPH_OT_properties(wmOperatorType *ot) { - ot->name = "Properties"; + ot->name = "Toggle Sidebar"; ot->idname = "GRAPH_OT_properties"; ot->description = "Toggle the properties region visibility"; diff --git a/source/blender/editors/space_graph/space_graph.c b/source/blender/editors/space_graph/space_graph.c index 56236ea8f47..d208ead317b 100644 --- a/source/blender/editors/space_graph/space_graph.c +++ b/source/blender/editors/space_graph/space_graph.c @@ -181,14 +181,14 @@ static void graph_free(SpaceLink *sl) /* spacetype; init callback */ -static void graph_init(struct wmWindowManager *UNUSED(wm), ScrArea *sa) +static void graph_init(struct wmWindowManager *wm, ScrArea *sa) { SpaceIpo *sipo = (SpaceIpo *)sa->spacedata.first; /* init dopesheet data if non-existent (i.e. for old files) */ if (sipo->ads == NULL) { sipo->ads = MEM_callocN(sizeof(bDopeSheet), "GraphEdit DopeSheet"); - sipo->ads->source = (ID *)(G.main->scene.first); // FIXME: this is a really nasty hack here for now... + sipo->ads->source = (ID *)WM_window_get_active_scene(wm->winactive); } /* force immediate init of any invalid F-Curve colors */ @@ -422,7 +422,7 @@ static void graph_buttons_region_init(wmWindowManager *wm, ARegion *ar) static void graph_buttons_region_draw(const bContext *C, ARegion *ar) { - ED_region_panels(C, ar, NULL, -1, true); + ED_region_panels(C, ar); } static void graph_region_listener( diff --git a/source/blender/editors/space_image/image_buttons.c b/source/blender/editors/space_image/image_buttons.c index 8b8aabb2ce0..7236a99ad80 100644 --- a/source/blender/editors/space_image/image_buttons.c +++ b/source/blender/editors/space_image/image_buttons.c @@ -291,23 +291,24 @@ static void ui_imageuser_slot_menu(bContext *UNUSED(C), uiLayout *layout, void * { uiBlock *block = uiLayoutGetBlock(layout); Image *image = image_p; - int slot; + int slot_id; uiDefBut(block, UI_BTYPE_LABEL, 0, IFACE_("Slot"), 0, 0, UI_UNIT_X * 5, UI_UNIT_Y, NULL, 0.0, 0.0, 0, 0, ""); uiItemS(layout); - slot = IMA_MAX_RENDER_SLOT; - while (slot--) { + slot_id = BLI_listbase_count(&image->renderslots) - 1; + for (RenderSlot *slot = image->renderslots.last; slot; slot = slot->prev) { char str[64]; - if (image->render_slots[slot].name[0] != '\0') { - BLI_strncpy(str, image->render_slots[slot].name, sizeof(str)); + if (slot->name[0] != '\0') { + BLI_strncpy(str, slot->name, sizeof(str)); } else { - BLI_snprintf(str, sizeof(str), IFACE_("Slot %d"), slot + 1); + BLI_snprintf(str, sizeof(str), IFACE_("Slot %d"), slot_id + 1); } uiDefButS(block, UI_BTYPE_BUT_MENU, B_NOP, str, 0, 0, - UI_UNIT_X * 5, UI_UNIT_X, &image->render_slot, (float) slot, 0.0, 0, -1, ""); + UI_UNIT_X * 5, UI_UNIT_X, &image->render_slot, (float) slot_id, 0.0, 0, -1, ""); + slot_id--; } } @@ -708,8 +709,9 @@ static void uiblock_layer_pass_buttons( /* menu buts */ if (render_slot) { char str[64]; - if (image->render_slots[*render_slot].name[0] != '\0') { - BLI_strncpy(str, image->render_slots[*render_slot].name, sizeof(str)); + RenderSlot *slot = BKE_image_get_renderslot(image, *render_slot); + if (slot->name[0] != '\0') { + BLI_strncpy(str, slot->name, sizeof(str)); } else { BLI_snprintf(str, sizeof(str), IFACE_("Slot %d"), *render_slot + 1); @@ -1313,7 +1315,7 @@ static int image_properties_toggle_exec(bContext *C, wmOperator *UNUSED(op)) void IMAGE_OT_properties(wmOperatorType *ot) { - ot->name = "Properties"; + ot->name = "Toggle Sidebar"; ot->idname = "IMAGE_OT_properties"; ot->description = "Toggle the properties region visibility"; @@ -1337,7 +1339,7 @@ static int image_scopes_toggle_exec(bContext *C, wmOperator *UNUSED(op)) void IMAGE_OT_toolshelf(wmOperatorType *ot) { - ot->name = "Tool Shelf"; + ot->name = "Toggle Toolbar"; ot->idname = "IMAGE_OT_toolshelf"; ot->description = "Toggles tool shelf display"; diff --git a/source/blender/editors/space_image/image_edit.c b/source/blender/editors/space_image/image_edit.c index 0eb6a2400d2..f4ecd2e7d34 100644 --- a/source/blender/editors/space_image/image_edit.c +++ b/source/blender/editors/space_image/image_edit.c @@ -34,6 +34,7 @@ #include "DNA_scene_types.h" #include "BLI_rect.h" +#include "BLI_listbase.h" #include "BKE_colortools.h" #include "BKE_context.h" @@ -302,17 +303,19 @@ bool ED_image_slot_cycle(struct Image *image, int direction) BLI_assert(ELEM(direction, -1, 1)); - for (i = 1; i < IMA_MAX_RENDER_SLOT; i++) { - slot = (cur + ((direction == -1) ? -i : i)) % IMA_MAX_RENDER_SLOT; - if (slot < 0) slot += IMA_MAX_RENDER_SLOT; + int num_slots = BLI_listbase_count(&image->renderslots); + for (i = 1; i < num_slots; i++) { + slot = (cur + ((direction == -1) ? -i : i)) % num_slots; + if (slot < 0) slot += num_slots; - if (image->renders[slot] || slot == image->last_render_slot) { + RenderSlot *render_slot = BKE_image_get_renderslot(image, slot); + if ((render_slot && render_slot->render) || slot == image->last_render_slot) { image->render_slot = slot; break; } } - if (i == IMA_MAX_RENDER_SLOT) { + if (i == num_slots) { image->render_slot = ((cur == 1) ? 0 : 1); } diff --git a/source/blender/editors/space_image/image_intern.h b/source/blender/editors/space_image/image_intern.h index 9167a193f2d..49c2690daaf 100644 --- a/source/blender/editors/space_image/image_intern.h +++ b/source/blender/editors/space_image/image_intern.h @@ -83,6 +83,9 @@ void IMAGE_OT_unpack(struct wmOperatorType *ot); void IMAGE_OT_invert(struct wmOperatorType *ot); void IMAGE_OT_cycle_render_slot(struct wmOperatorType *ot); +void IMAGE_OT_clear_render_slot(struct wmOperatorType *ot); +void IMAGE_OT_add_render_slot(struct wmOperatorType *ot); +void IMAGE_OT_remove_render_slot(struct wmOperatorType *ot); void IMAGE_OT_sample(struct wmOperatorType *ot); void IMAGE_OT_sample_line(struct wmOperatorType *ot); diff --git a/source/blender/editors/space_image/image_ops.c b/source/blender/editors/space_image/image_ops.c index 39544eb55dd..b2116b1a770 100644 --- a/source/blender/editors/space_image/image_ops.c +++ b/source/blender/editors/space_image/image_ops.c @@ -1538,7 +1538,7 @@ static int image_replace_exec(bContext *C, wmOperator *op) BKE_image_signal(bmain, sima->image, &sima->iuser, IMA_SIGNAL_SRC_CHANGE); } - if (BLI_testextensie_array(str, imb_ext_movie)) + if (BLI_path_extension_check_array(str, imb_ext_movie)) sima->image->source = IMA_SRC_MOVIE; else sima->image->source = IMA_SRC_FILE; @@ -3464,7 +3464,8 @@ static int image_cycle_render_slot_exec(bContext *C, wmOperator *op) WM_event_add_notifier(C, NC_IMAGE | ND_DRAW, NULL); /* no undo push for browsing existing */ - if (ima->renders[ima->render_slot] || ima->render_slot == ima->last_render_slot) + RenderSlot *slot = BKE_image_get_renderslot(ima, ima->render_slot); + if ((slot && slot->render) || ima->render_slot == ima->last_render_slot) return OPERATOR_CANCELLED; return OPERATOR_FINISHED; @@ -3487,6 +3488,97 @@ void IMAGE_OT_cycle_render_slot(wmOperatorType *ot) RNA_def_boolean(ot->srna, "reverse", 0, "Cycle in Reverse", ""); } +/********************* clear render slot operator *********************/ + +static int image_clear_render_slot_exec(bContext *C, wmOperator *UNUSED(op)) +{ + SpaceImage *sima = CTX_wm_space_image(C); + Image *ima = CTX_data_edit_image(C); + + if (!BKE_image_clear_renderslot(ima, &sima->iuser, ima->render_slot)) { + return OPERATOR_CANCELLED; + } + + WM_event_add_notifier(C, NC_IMAGE | ND_DRAW, NULL); + + return OPERATOR_FINISHED; +} + +void IMAGE_OT_clear_render_slot(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Clear Render Slot"; + ot->idname = "IMAGE_OT_clear_render_slot"; + ot->description = "Clear the currently selected render slot"; + + /* api callbacks */ + ot->exec = image_clear_render_slot_exec; + ot->poll = image_cycle_render_slot_poll; + + /* flags */ + ot->flag = OPTYPE_REGISTER; +} + +/********************* add render slot operator *********************/ + +static int image_add_render_slot_exec(bContext *C, wmOperator *UNUSED(op)) +{ + Image *ima = CTX_data_edit_image(C); + + RenderSlot *slot = BKE_image_add_renderslot(ima, NULL); + ima->render_slot = BLI_findindex(&ima->renderslots, slot); + + WM_event_add_notifier(C, NC_IMAGE | ND_DRAW, NULL); + + return OPERATOR_FINISHED; +} + +void IMAGE_OT_add_render_slot(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Add Render Slot"; + ot->idname = "IMAGE_OT_add_render_slot"; + ot->description = "Add a new render slot"; + + /* api callbacks */ + ot->exec = image_add_render_slot_exec; + ot->poll = image_cycle_render_slot_poll; + + /* flags */ + ot->flag = OPTYPE_REGISTER; +} + +/********************* remove render slot operator *********************/ + +static int image_remove_render_slot_exec(bContext *C, wmOperator *UNUSED(op)) +{ + SpaceImage *sima = CTX_wm_space_image(C); + Image *ima = CTX_data_edit_image(C); + + if (!BKE_image_remove_renderslot(ima, &sima->iuser, ima->render_slot)) { + return OPERATOR_CANCELLED; + } + + WM_event_add_notifier(C, NC_IMAGE | ND_DRAW, NULL); + + return OPERATOR_FINISHED; +} + +void IMAGE_OT_remove_render_slot(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Remove Render Slot"; + ot->idname = "IMAGE_OT_remove_render_slot"; + ot->description = "Remove the current render slot"; + + /* api callbacks */ + ot->exec = image_remove_render_slot_exec; + ot->poll = image_cycle_render_slot_poll; + + /* flags */ + ot->flag = OPTYPE_REGISTER; +} + /********************** change frame operator *********************/ static int change_frame_poll(bContext *C) diff --git a/source/blender/editors/space_image/space_image.c b/source/blender/editors/space_image/space_image.c index c143ebbcd67..e84b596530e 100644 --- a/source/blender/editors/space_image/space_image.c +++ b/source/blender/editors/space_image/space_image.c @@ -272,6 +272,9 @@ static void image_operatortypes(void) WM_operatortype_append(IMAGE_OT_invert); WM_operatortype_append(IMAGE_OT_cycle_render_slot); + WM_operatortype_append(IMAGE_OT_clear_render_slot); + WM_operatortype_append(IMAGE_OT_add_render_slot); + WM_operatortype_append(IMAGE_OT_remove_render_slot); WM_operatortype_append(IMAGE_OT_sample); WM_operatortype_append(IMAGE_OT_sample_line); @@ -358,7 +361,7 @@ static void image_keymap(struct wmKeyConfig *keyconf) RNA_boolean_set(kmi->ptr, "toggle", true); /* fast switch to render slots */ - for (i = 0; i < MIN2(IMA_MAX_RENDER_SLOT, 9); i++) { + for (i = 0; i < 9; i++) { kmi = WM_keymap_add_item(keymap, "WM_OT_context_set_int", ONEKEY + i, KM_PRESS, 0, 0); RNA_string_set(kmi->ptr, "data_path", "space_data.image.render_slots.active_index"); RNA_int_set(kmi->ptr, "value", i); @@ -869,7 +872,7 @@ static void image_buttons_region_init(wmWindowManager *wm, ARegion *ar) static void image_buttons_region_draw(const bContext *C, ARegion *ar) { - ED_region_panels(C, ar, NULL, -1, true); + ED_region_panels(C, ar); } static void image_buttons_region_listener( @@ -944,7 +947,7 @@ static void image_tools_region_draw(const bContext *C, ARegion *ar) } ED_space_image_release_buffer(sima, ibuf, lock); - ED_region_panels(C, ar, NULL, -1, true); + ED_region_panels(C, ar); } static void image_tools_region_listener( @@ -1096,7 +1099,6 @@ void ED_spacetype_image(void) art->init = image_main_region_init; art->draw = image_main_region_draw; art->listener = image_main_region_listener; - BLI_addhead(&st->regiontypes, art); /* regions: listview/buttons */ @@ -1134,5 +1136,9 @@ void ED_spacetype_image(void) BLI_addhead(&st->regiontypes, art); + /* regions: hud */ + art = ED_area_type_hud(st->spaceid); + BLI_addhead(&st->regiontypes, art); + BKE_spacetype_register(st); } diff --git a/source/blender/editors/space_nla/nla_buttons.c b/source/blender/editors/space_nla/nla_buttons.c index a26e6b0280e..cafb40626ee 100644 --- a/source/blender/editors/space_nla/nla_buttons.c +++ b/source/blender/editors/space_nla/nla_buttons.c @@ -574,7 +574,7 @@ static int nla_properties_toggle_exec(bContext *C, wmOperator *UNUSED(op)) void NLA_OT_properties(wmOperatorType *ot) { - ot->name = "Properties"; + ot->name = "Toggle Sidebar"; ot->idname = "NLA_OT_properties"; ot->description = "Toggle the properties region visibility"; diff --git a/source/blender/editors/space_nla/nla_edit.c b/source/blender/editors/space_nla/nla_edit.c index 26ac06446c4..23cd504978c 100644 --- a/source/blender/editors/space_nla/nla_edit.c +++ b/source/blender/editors/space_nla/nla_edit.c @@ -1057,7 +1057,7 @@ static int nlaedit_duplicate_exec(bContext *C, wmOperator *op) /* if selected, split the strip at its midpoint */ if (strip->flag & NLASTRIP_FLAG_SELECT) { /* make a copy (assume that this is possible) */ - nstrip = BKE_nlastrip_copy(strip, linked); + nstrip = BKE_nlastrip_copy(ac.bmain, strip, linked); /* in case there's no space in the track above, or we haven't got a reference to it yet, try adding */ if (BKE_nlatrack_add_strip(nlt->next, nstrip) == 0) { @@ -1207,7 +1207,7 @@ void NLA_OT_delete(wmOperatorType *ot) // - variable-length splits? /* split a given Action-Clip strip */ -static void nlaedit_split_strip_actclip(AnimData *adt, NlaTrack *nlt, NlaStrip *strip, float cfra) +static void nlaedit_split_strip_actclip(Main *bmain, AnimData *adt, NlaTrack *nlt, NlaStrip *strip, float cfra) { NlaStrip *nstrip; float splitframe, splitaframe; @@ -1242,7 +1242,7 @@ static void nlaedit_split_strip_actclip(AnimData *adt, NlaTrack *nlt, NlaStrip * /* make a copy (assume that this is possible) and append * it immediately after the current strip */ - nstrip = BKE_nlastrip_copy(strip, true); + nstrip = BKE_nlastrip_copy(bmain, strip, true); BLI_insertlinkafter(&nlt->strips, strip, nstrip); /* set the endpoint of the first strip and the start of the new strip @@ -1303,7 +1303,7 @@ static int nlaedit_split_exec(bContext *C, wmOperator *UNUSED(op)) /* splitting method depends on the type of strip */ switch (strip->type) { case NLASTRIP_TYPE_CLIP: /* action-clip */ - nlaedit_split_strip_actclip(adt, nlt, strip, (float)ac.scene->r.cfra); + nlaedit_split_strip_actclip(ac.bmain, adt, nlt, strip, (float)ac.scene->r.cfra); break; case NLASTRIP_TYPE_META: /* meta-strips need special handling */ diff --git a/source/blender/editors/space_nla/space_nla.c b/source/blender/editors/space_nla/space_nla.c index 318d8bf777b..745cea37ea3 100644 --- a/source/blender/editors/space_nla/space_nla.c +++ b/source/blender/editors/space_nla/space_nla.c @@ -178,14 +178,14 @@ static void nla_free(SpaceLink *sl) /* spacetype; init callback */ -static void nla_init(struct wmWindowManager *UNUSED(wm), ScrArea *sa) +static void nla_init(struct wmWindowManager *wm, ScrArea *sa) { SpaceNla *snla = (SpaceNla *)sa->spacedata.first; /* init dopesheet data if non-existent (i.e. for old files) */ if (snla->ads == NULL) { snla->ads = MEM_callocN(sizeof(bDopeSheet), "NlaEdit DopeSheet"); - snla->ads->source = (ID *)G.main->scene.first; // XXX this is bad, but we need this to be set correct + snla->ads->source = (ID *)WM_window_get_active_scene(wm->winactive); } ED_area_tag_refresh(sa); @@ -360,7 +360,7 @@ static void nla_buttons_region_init(wmWindowManager *wm, ARegion *ar) static void nla_buttons_region_draw(const bContext *C, ARegion *ar) { - ED_region_panels(C, ar, NULL, -1, true); + ED_region_panels(C, ar); } static void nla_region_listener( diff --git a/source/blender/editors/space_node/drawnode.c b/source/blender/editors/space_node/drawnode.c index db718da12ef..a162a863038 100644 --- a/source/blender/editors/space_node/drawnode.c +++ b/source/blender/editors/space_node/drawnode.c @@ -1080,6 +1080,13 @@ static void node_shader_buts_bevel(uiLayout *layout, bContext *UNUSED(C), Pointe uiItemR(layout, ptr, "samples", 0, NULL, ICON_NONE); } +static void node_shader_buts_ambient_occlusion(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) +{ + uiItemR(layout, ptr, "samples", 0, NULL, ICON_NONE); + uiItemR(layout, ptr, "inside", 0, NULL, ICON_NONE); + uiItemR(layout, ptr, "only_local", 0, NULL, ICON_NONE); +} + /* only once called */ static void node_shader_set_butfunc(bNodeType *ntype) { @@ -1210,6 +1217,9 @@ static void node_shader_set_butfunc(bNodeType *ntype) case SH_NODE_BEVEL: ntype->draw_buttons = node_shader_buts_bevel; break; + case SH_NODE_AMBIENT_OCCLUSION: + ntype->draw_buttons = node_shader_buts_ambient_occlusion; + break; } } diff --git a/source/blender/editors/space_node/node_buttons.c b/source/blender/editors/space_node/node_buttons.c index 0a656ee1deb..38183637750 100644 --- a/source/blender/editors/space_node/node_buttons.c +++ b/source/blender/editors/space_node/node_buttons.c @@ -224,7 +224,7 @@ static int node_properties_poll(bContext *C) void NODE_OT_properties(wmOperatorType *ot) { - ot->name = "Properties"; + ot->name = "Toggle Sidebar"; ot->description = "Toggle the properties region visibility"; ot->idname = "NODE_OT_properties"; diff --git a/source/blender/editors/space_node/node_edit.c b/source/blender/editors/space_node/node_edit.c index 91101d1101e..ff87dcf409a 100644 --- a/source/blender/editors/space_node/node_edit.c +++ b/source/blender/editors/space_node/node_edit.c @@ -656,6 +656,7 @@ void ED_node_set_active(Main *bmain, bNodeTree *ntree, bNode *node) if (wo->nodetree && wo->use_nodes && ntreeHasTree(wo->nodetree, ntree)) GPU_material_free(&wo->gpumaterial); + ED_node_tag_update_nodetree(bmain, ntree, node); WM_main_add_notifier(NC_IMAGE, NULL); } @@ -929,11 +930,13 @@ static int node_resize_modal(bContext *C, wmOperator *op, const wmEvent *event) case LEFTMOUSE: case MIDDLEMOUSE: case RIGHTMOUSE: + if (event->val == KM_RELEASE) { + node_resize_exit(C, op, false); + ED_node_post_apply_transform(C, snode->edittree); - node_resize_exit(C, op, false); - ED_node_post_apply_transform(C, snode->edittree); - - return OPERATOR_FINISHED; + return OPERATOR_FINISHED; + } + break; } return OPERATOR_RUNNING_MODAL; diff --git a/source/blender/editors/space_node/node_group.c b/source/blender/editors/space_node/node_group.c index 5d326a0be38..926fff7a3b6 100644 --- a/source/blender/editors/space_node/node_group.c +++ b/source/blender/editors/space_node/node_group.c @@ -260,7 +260,7 @@ static int node_group_ungroup(Main *bmain, bNodeTree *ntree, bNode *gnode) waction = wgroup->adt->action = BKE_action_copy(bmain, wgroup->adt->action); /* now perform the moving */ - BKE_animdata_separate_by_basepath(&wgroup->id, &ntree->id, &anim_basepaths); + BKE_animdata_separate_by_basepath(bmain, &wgroup->id, &ntree->id, &anim_basepaths); /* paths + their wrappers need to be freed */ for (ld = anim_basepaths.first; ld; ld = ldn) { @@ -397,7 +397,8 @@ void NODE_OT_group_ungroup(wmOperatorType *ot) /* ******************** Separate operator ********************** */ /* returns 1 if its OK */ -static int node_group_separate_selected(bNodeTree *ntree, bNodeTree *ngroup, float offx, float offy, int make_copy) +static int node_group_separate_selected( + Main *bmain, bNodeTree *ntree, bNodeTree *ngroup, float offx, float offy, int make_copy) { bNodeLink *link, *link_next; bNode *node, *node_next, *newnode; @@ -492,7 +493,7 @@ static int node_group_separate_selected(bNodeTree *ntree, bNodeTree *ngroup, flo LinkData *ld, *ldn = NULL; /* now perform the moving */ - BKE_animdata_separate_by_basepath(&ngroup->id, &ntree->id, &anim_basepaths); + BKE_animdata_separate_by_basepath(bmain, &ngroup->id, &ntree->id, &anim_basepaths); /* paths + their wrappers need to be freed */ for (ld = anim_basepaths.first; ld; ld = ldn) { @@ -524,12 +525,13 @@ static const EnumPropertyItem node_group_separate_types[] = { static int node_group_separate_exec(bContext *C, wmOperator *op) { + Main *bmain = CTX_data_main(C); SpaceNode *snode = CTX_wm_space_node(C); bNodeTree *ngroup, *nparent; int type = RNA_enum_get(op->ptr, "type"); float offx, offy; - ED_preview_kill_jobs(CTX_wm_manager(C), CTX_data_main(C)); + ED_preview_kill_jobs(CTX_wm_manager(C), bmain); /* are we inside of a group? */ ngroup = snode->edittree; @@ -543,13 +545,13 @@ static int node_group_separate_exec(bContext *C, wmOperator *op) switch (type) { case NODE_GS_COPY: - if (!node_group_separate_selected(nparent, ngroup, offx, offy, 1)) { + if (!node_group_separate_selected(bmain, nparent, ngroup, offx, offy, 1)) { BKE_report(op->reports, RPT_WARNING, "Cannot separate nodes"); return OPERATOR_CANCELLED; } break; case NODE_GS_MOVE: - if (!node_group_separate_selected(nparent, ngroup, offx, offy, 0)) { + if (!node_group_separate_selected(bmain, nparent, ngroup, offx, offy, 0)) { BKE_report(op->reports, RPT_WARNING, "Cannot separate nodes"); return OPERATOR_CANCELLED; } @@ -681,6 +683,7 @@ static int node_get_selected_minmax(bNodeTree *ntree, bNode *gnode, float *min, static void node_group_make_insert_selected(const bContext *C, bNodeTree *ntree, bNode *gnode) { + Main *bmain = CTX_data_main(C); bNodeTree *ngroup = (bNodeTree *)gnode->id; bNodeLink *link, *linkn; bNode *node, *nextn; @@ -742,7 +745,7 @@ static void node_group_make_insert_selected(const bContext *C, bNodeTree *ntree, if (ntree->adt) { LinkData *ld, *ldn = NULL; - BKE_animdata_separate_by_basepath(&ntree->id, &ngroup->id, &anim_basepaths); + BKE_animdata_separate_by_basepath(bmain, &ntree->id, &ngroup->id, &anim_basepaths); /* paths + their wrappers need to be freed */ for (ld = anim_basepaths.first; ld; ld = ldn) { diff --git a/source/blender/editors/space_node/space_node.c b/source/blender/editors/space_node/space_node.c index 36886d0ab32..441ab03cb28 100644 --- a/source/blender/editors/space_node/space_node.c +++ b/source/blender/editors/space_node/space_node.c @@ -603,7 +603,7 @@ static void node_buttons_region_init(wmWindowManager *wm, ARegion *ar) static void node_buttons_region_draw(const bContext *C, ARegion *ar) { - ED_region_panels(C, ar, NULL, -1, true); + ED_region_panels(C, ar); } /* add handlers, stuff you only do once or on area/region changes */ @@ -619,7 +619,7 @@ static void node_toolbar_region_init(wmWindowManager *wm, ARegion *ar) static void node_toolbar_region_draw(const bContext *C, ARegion *ar) { - ED_region_panels(C, ar, NULL, -1, true); + ED_region_panels(C, ar); } static void node_cursor(wmWindow *win, ScrArea *sa, ARegion *ar) diff --git a/source/blender/editors/space_outliner/outliner_collections.c b/source/blender/editors/space_outliner/outliner_collections.c index 909938ad606..a700f8e20e0 100644 --- a/source/blender/editors/space_outliner/outliner_collections.c +++ b/source/blender/editors/space_outliner/outliner_collections.c @@ -320,7 +320,10 @@ static int collection_objects_select_exec(bContext *C, wmOperator *op) } BKE_layer_collection_objects_select(view_layer, layer_collection, deselect); - WM_main_add_notifier(NC_SCENE | ND_OB_SELECT, CTX_data_scene(C)); + + Scene *scene = CTX_data_scene(C); + DEG_id_tag_update(&scene->id, DEG_TAG_SELECT_UPDATE); + WM_main_add_notifier(NC_SCENE | ND_OB_SELECT, scene); return OPERATOR_FINISHED; } diff --git a/source/blender/editors/space_outliner/outliner_draw.c b/source/blender/editors/space_outliner/outliner_draw.c index a514d7f1335..a3f3acf1c32 100644 --- a/source/blender/editors/space_outliner/outliner_draw.c +++ b/source/blender/editors/space_outliner/outliner_draw.c @@ -92,8 +92,9 @@ static void outliner_height(SpaceOops *soops, ListBase *lb, int *h) TreeElement *te = lb->first; while (te) { TreeStoreElem *tselem = TREESTORE(te); - if (TSELEM_OPEN(tselem, soops)) + if (TSELEM_OPEN(tselem, soops)) { outliner_height(soops, &te->subtree, h); + } (*h) += UI_UNIT_Y; te = te->next; } @@ -132,8 +133,9 @@ static void outliner_rna_width(SpaceOops *soops, ListBase *lb, int *w, int start if (startx + 100 > *w) *w = startx + 100; - if (TSELEM_OPEN(tselem, soops)) + if (TSELEM_OPEN(tselem, soops)) { outliner_rna_width(soops, &te->subtree, w, startx + UI_UNIT_X); + } te = te->next; } } @@ -276,6 +278,44 @@ static void restrictbutton_id_user_toggle(bContext *UNUSED(C), void *poin, void } } +static void hidebutton_base_flag_cb(bContext *C, void *poin, void *poin2) +{ + Scene *scene = CTX_data_scene(C); + ViewLayer *view_layer = poin; + Base *base = poin2; + bool extend = (CTX_wm_window(C)->eventstate->ctrl == 0); + + /* Undo button toggle, let function do it. */ + base->flag ^= BASE_HIDE; + + BKE_base_set_visible(scene, view_layer, base, extend); + + if (!extend && (base->flag & BASE_VISIBLED)) { + /* Auto select solo-ed object. */ + ED_object_base_select(base, BA_SELECT); + view_layer->basact = base; + } + + DEG_id_tag_update(&scene->id, DEG_TAG_BASE_FLAGS_UPDATE); + WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene); +} + +static void hidebutton_layer_collection_flag_cb(bContext *C, void *poin, void *poin2) +{ + Scene *scene = CTX_data_scene(C); + ViewLayer *view_layer = poin; + LayerCollection *lc = poin2; + bool extend = (CTX_wm_window(C)->eventstate->ctrl == 0); + + /* Undo button toggle, let function do it. */ + lc->runtime_flag ^= LAYER_COLLECTION_HAS_VISIBLE_OBJECTS; + + BKE_layer_collection_set_visible(scene, view_layer, lc, extend); + + DEG_id_tag_update(&scene->id, DEG_TAG_BASE_FLAGS_UPDATE); + WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene); +} + static void namebutton_cb(bContext *C, void *tsep, char *oldname) { Main *bmain = CTX_data_main(C); @@ -432,172 +472,214 @@ static void namebutton_cb(bContext *C, void *tsep, char *oldname) } } -static void outliner_draw_restrictbuts(uiBlock *block, Scene *scene, ARegion *ar, SpaceOops *soops, ListBase *lb) +static void outliner_draw_restrictbuts( + uiBlock *block, Scene *scene, ViewLayer *view_layer, ARegion *ar, SpaceOops *soops, ListBase *lb) { uiBut *bt; - TreeElement *te; - TreeStoreElem *tselem; - Object *ob = NULL; /* get RNA properties (once for speed) */ - PropertyRNA *collection_prop_hide_viewport; - PropertyRNA *collection_prop_hide_select; - PropertyRNA *collection_prop_hide_render; + PropertyRNA *object_prop_hide_viewport, *object_prop_hide_select, *object_prop_hide_render; + PropertyRNA *collection_prop_hide_viewport, *collection_prop_hide_select, *collection_prop_hide_render; + + object_prop_hide_viewport = RNA_struct_type_find_property(&RNA_Object, "hide_viewport"); + object_prop_hide_select = RNA_struct_type_find_property(&RNA_Object, "hide_select"); + object_prop_hide_render = RNA_struct_type_find_property(&RNA_Object, "hide_render"); collection_prop_hide_select = RNA_struct_type_find_property(&RNA_Collection, "hide_select"); collection_prop_hide_viewport = RNA_struct_type_find_property(&RNA_Collection, "hide_viewport"); collection_prop_hide_render = RNA_struct_type_find_property(&RNA_Collection, "hide_render"); - BLI_assert(collection_prop_hide_viewport && + + BLI_assert(object_prop_hide_viewport && + object_prop_hide_select && + object_prop_hide_render && + collection_prop_hide_viewport && collection_prop_hide_select && collection_prop_hide_render); - for (te = lb->first; te; te = te->next) { - tselem = TREESTORE(te); + for (TreeElement *te = lb->first; te; te = te->next) { + TreeStoreElem *tselem = TREESTORE(te); if (te->ys + 2 * UI_UNIT_Y >= ar->v2d.cur.ymin && te->ys <= ar->v2d.cur.ymax) { if (tselem->type == TSE_R_LAYER && (soops->outlinevis == SO_SCENES)) { /* View layer render toggle. */ - ViewLayer *view_layer = te->directdata; - - UI_block_emboss_set(block, UI_EMBOSS_NONE); + ViewLayer *layer = te->directdata; - bt = uiDefIconButBitS(block, UI_BTYPE_ICON_TOGGLE_N, VIEW_LAYER_RENDER, 0, ICON_RESTRICT_RENDER_OFF, - (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_RENDERX), te->ys, UI_UNIT_X, - UI_UNIT_Y, &view_layer->flag, 0, 0, 0, 0, TIP_("Use view layer for rendering")); + bt = uiDefIconButBitS( + block, UI_BTYPE_ICON_TOGGLE_N, VIEW_LAYER_RENDER, 0, ICON_RESTRICT_RENDER_OFF, + (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_RENDERX), te->ys, UI_UNIT_X, + UI_UNIT_Y, &layer->flag, 0, 0, 0, 0, TIP_("Use view layer for rendering")); UI_but_func_set(bt, restrictbutton_r_lay_cb, tselem->id, NULL); UI_but_flag_enable(bt, UI_BUT_DRAG_LOCK); + } + else if (tselem->type == 0 && te->idcode == ID_OB) { + Object *ob = (Object *)tselem->id; + Base *base = BKE_view_layer_base_find(view_layer, ob); + + if (base) { + bt = uiDefIconButBitS( + block, UI_BTYPE_ICON_TOGGLE, BASE_HIDE, 0, ICON_HIDE_OFF, + (int)(ar->v2d.cur.xmax - OL_TOG_HIDEX), te->ys, UI_UNIT_X, + UI_UNIT_Y, &base->flag, 0, 0, 0, 0, + TIP_("Hide object in viewport (Ctrl to isolate)")); + UI_but_func_set(bt, hidebutton_base_flag_cb, view_layer, base); + UI_but_flag_enable(bt, UI_BUT_DRAG_LOCK); + } + + PointerRNA ptr; + RNA_pointer_create((ID *)ob, &RNA_Object, ob, &ptr); + + bt = uiDefIconButR_prop(block, UI_BTYPE_ICON_TOGGLE, 0, ICON_RESTRICT_VIEW_OFF, + (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_VIEWX), te->ys, UI_UNIT_X, UI_UNIT_Y, + &ptr, object_prop_hide_viewport, -1, 0, 0, -1, -1, + TIP_("Restrict viewport visibility")); + UI_but_flag_enable(bt, UI_BUT_DRAG_LOCK); + + bt = uiDefIconButR_prop(block, UI_BTYPE_ICON_TOGGLE, 0, ICON_RESTRICT_SELECT_OFF, + (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_SELECTX), te->ys, UI_UNIT_X, UI_UNIT_Y, + &ptr, object_prop_hide_select, -1, 0, 0, -1, -1, + TIP_("Restrict viewport selection")); + UI_but_flag_enable(bt, UI_BUT_DRAG_LOCK); + + bt = uiDefIconButR_prop(block, UI_BTYPE_ICON_TOGGLE, 0, ICON_RESTRICT_RENDER_OFF, + (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_RENDERX), te->ys, UI_UNIT_X, UI_UNIT_Y, + &ptr, object_prop_hide_render, -1, 0, 0, -1, -1, + TIP_("Restrict render visibility")); + UI_but_flag_enable(bt, UI_BUT_DRAG_LOCK); - UI_block_emboss_set(block, UI_EMBOSS); } else if (tselem->type == TSE_MODIFIER) { ModifierData *md = (ModifierData *)te->directdata; - ob = (Object *)tselem->id; + Object *ob = (Object *)tselem->id; - UI_block_emboss_set(block, UI_EMBOSS_NONE); - bt = uiDefIconButBitI(block, UI_BTYPE_ICON_TOGGLE_N, eModifierMode_Realtime, 0, ICON_RESTRICT_VIEW_OFF, - (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_VIEWX), te->ys, UI_UNIT_X, - UI_UNIT_Y, &(md->mode), 0, 0, 0, 0, - TIP_("Restrict/Allow visibility in the 3D View")); + bt = uiDefIconButBitI( + block, UI_BTYPE_ICON_TOGGLE_N, eModifierMode_Realtime, 0, ICON_RESTRICT_VIEW_OFF, + (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_VIEWX), te->ys, UI_UNIT_X, + UI_UNIT_Y, &(md->mode), 0, 0, 0, 0, + TIP_("Restrict/Allow visibility in the 3D View")); UI_but_func_set(bt, restrictbutton_modifier_cb, scene, ob); UI_but_flag_enable(bt, UI_BUT_DRAG_LOCK); - bt = uiDefIconButBitI(block, UI_BTYPE_ICON_TOGGLE_N, eModifierMode_Render, 0, ICON_RESTRICT_RENDER_OFF, - (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_RENDERX), te->ys, UI_UNIT_X, - UI_UNIT_Y, &(md->mode), 0, 0, 0, 0, TIP_("Restrict/Allow renderability")); + bt = uiDefIconButBitI( + block, UI_BTYPE_ICON_TOGGLE_N, eModifierMode_Render, 0, ICON_RESTRICT_RENDER_OFF, + (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_RENDERX), te->ys, UI_UNIT_X, + UI_UNIT_Y, &(md->mode), 0, 0, 0, 0, TIP_("Restrict/Allow renderability")); UI_but_func_set(bt, restrictbutton_modifier_cb, scene, ob); UI_but_flag_enable(bt, UI_BUT_DRAG_LOCK); - - UI_block_emboss_set(block, UI_EMBOSS); } else if (tselem->type == TSE_POSE_CHANNEL) { bPoseChannel *pchan = (bPoseChannel *)te->directdata; Bone *bone = pchan->bone; - ob = (Object *)tselem->id; + Object *ob = (Object *)tselem->id; - UI_block_emboss_set(block, UI_EMBOSS_NONE); - bt = uiDefIconButBitI(block, UI_BTYPE_ICON_TOGGLE, BONE_HIDDEN_P, 0, ICON_RESTRICT_VIEW_OFF, - (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_VIEWX), te->ys, UI_UNIT_X, - UI_UNIT_Y, &(bone->flag), 0, 0, 0, 0, - TIP_("Restrict/Allow visibility in the 3D View")); + bt = uiDefIconButBitI( + block, UI_BTYPE_ICON_TOGGLE, BONE_HIDDEN_P, 0, ICON_HIDE_OFF, + (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_VIEWX), te->ys, UI_UNIT_X, + UI_UNIT_Y, &(bone->flag), 0, 0, 0, 0, + TIP_("Restrict/Allow visibility in the 3D View")); UI_but_func_set(bt, restrictbutton_bone_visibility_cb, ob->data, bone); UI_but_flag_enable(bt, UI_BUT_DRAG_LOCK); - bt = uiDefIconButBitI(block, UI_BTYPE_ICON_TOGGLE, BONE_UNSELECTABLE, 0, ICON_RESTRICT_SELECT_OFF, - (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_SELECTX), te->ys, UI_UNIT_X, - UI_UNIT_Y, &(bone->flag), 0, 0, 0, 0, - TIP_("Restrict/Allow selection in the 3D View")); + bt = uiDefIconButBitI( + block, UI_BTYPE_ICON_TOGGLE, BONE_UNSELECTABLE, 0, ICON_RESTRICT_SELECT_OFF, + (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_SELECTX), te->ys, UI_UNIT_X, + UI_UNIT_Y, &(bone->flag), 0, 0, 0, 0, + TIP_("Restrict/Allow selection in the 3D View")); UI_but_func_set(bt, restrictbutton_bone_select_cb, ob->data, bone); UI_but_flag_enable(bt, UI_BUT_DRAG_LOCK); - - UI_block_emboss_set(block, UI_EMBOSS); } else if (tselem->type == TSE_EBONE) { EditBone *ebone = (EditBone *)te->directdata; - UI_block_emboss_set(block, UI_EMBOSS_NONE); - bt = uiDefIconButBitI(block, UI_BTYPE_ICON_TOGGLE, BONE_HIDDEN_A, 0, ICON_RESTRICT_VIEW_OFF, - (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_VIEWX), te->ys, UI_UNIT_X, - UI_UNIT_Y, &(ebone->flag), 0, 0, 0, 0, - TIP_("Restrict/Allow visibility in the 3D View")); + bt = uiDefIconButBitI( + block, UI_BTYPE_ICON_TOGGLE, BONE_HIDDEN_A, 0, ICON_RESTRICT_VIEW_OFF, + (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_VIEWX), te->ys, UI_UNIT_X, + UI_UNIT_Y, &(ebone->flag), 0, 0, 0, 0, + TIP_("Restrict/Allow visibility in the 3D View")); UI_but_func_set(bt, restrictbutton_ebone_visibility_cb, NULL, ebone); UI_but_flag_enable(bt, UI_BUT_DRAG_LOCK); - bt = uiDefIconButBitI(block, UI_BTYPE_ICON_TOGGLE, BONE_UNSELECTABLE, 0, ICON_RESTRICT_SELECT_OFF, - (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_SELECTX), te->ys, UI_UNIT_X, - UI_UNIT_Y, &(ebone->flag), 0, 0, 0, 0, - TIP_("Restrict/Allow selection in the 3D View")); + bt = uiDefIconButBitI( + block, UI_BTYPE_ICON_TOGGLE, BONE_UNSELECTABLE, 0, ICON_RESTRICT_SELECT_OFF, + (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_SELECTX), te->ys, UI_UNIT_X, + UI_UNIT_Y, &(ebone->flag), 0, 0, 0, 0, + TIP_("Restrict/Allow selection in the 3D View")); UI_but_func_set(bt, restrictbutton_ebone_select_cb, NULL, ebone); UI_but_flag_enable(bt, UI_BUT_DRAG_LOCK); - - UI_block_emboss_set(block, UI_EMBOSS); } else if (tselem->type == TSE_GP_LAYER) { bGPDlayer *gpl = (bGPDlayer *)te->directdata; - UI_block_emboss_set(block, UI_EMBOSS_NONE); - - bt = uiDefIconButBitS(block, UI_BTYPE_ICON_TOGGLE, GP_LAYER_HIDE, 0, ICON_RESTRICT_VIEW_OFF, - (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_VIEWX), te->ys, UI_UNIT_X, - UI_UNIT_Y, &gpl->flag, 0, 0, 0, 0, - TIP_("Restrict/Allow visibility in the 3D View")); + bt = uiDefIconButBitS( + block, UI_BTYPE_ICON_TOGGLE, GP_LAYER_HIDE, 0, ICON_HIDE_OFF, + (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_VIEWX), te->ys, UI_UNIT_X, + UI_UNIT_Y, &gpl->flag, 0, 0, 0, 0, + TIP_("Restrict/Allow visibility in the 3D View")); UI_but_func_set(bt, restrictbutton_gp_layer_flag_cb, NULL, gpl); UI_but_flag_enable(bt, UI_BUT_DRAG_LOCK); - bt = uiDefIconButBitS(block, UI_BTYPE_ICON_TOGGLE, GP_LAYER_LOCKED, 0, ICON_UNLOCKED, - (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_SELECTX), te->ys, UI_UNIT_X, - UI_UNIT_Y, &gpl->flag, 0, 0, 0, 0, - TIP_("Restrict/Allow editing of strokes and keyframes in this layer")); + bt = uiDefIconButBitS( + block, UI_BTYPE_ICON_TOGGLE, GP_LAYER_LOCKED, 0, ICON_UNLOCKED, + (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_SELECTX), te->ys, UI_UNIT_X, + UI_UNIT_Y, &gpl->flag, 0, 0, 0, 0, + TIP_("Restrict/Allow editing of strokes and keyframes in this layer")); UI_but_func_set(bt, restrictbutton_gp_layer_flag_cb, NULL, gpl); UI_but_flag_enable(bt, UI_BUT_DRAG_LOCK); /* TODO: visibility in renders */ - - UI_block_emboss_set(block, UI_EMBOSS); } else if (outliner_is_collection_tree_element(te)) { LayerCollection *lc = (tselem->type == TSE_LAYER_COLLECTION) ? te->directdata : NULL; Collection *collection = outliner_collection_from_tree_element(te); - UI_block_emboss_set(block, UI_EMBOSS_NONE); - if ((!lc || !(lc->flag & LAYER_COLLECTION_EXCLUDE)) && !(collection->flag & COLLECTION_IS_MASTER)) { + if (lc && (lc->runtime_flag & LAYER_COLLECTION_HAS_ENABLED_OBJECTS)) { + bt = uiDefIconButBitS( + block, UI_BTYPE_ICON_TOGGLE_N, LAYER_COLLECTION_HAS_VISIBLE_OBJECTS, 0, ICON_HIDE_OFF, + (int)(ar->v2d.cur.xmax - OL_TOG_HIDEX), te->ys, UI_UNIT_X, + UI_UNIT_Y, &lc->runtime_flag, 0, 0, 0, 0, + TIP_("Hide collection in viewport (Ctrl to isolate)")); + UI_but_func_set(bt, hidebutton_layer_collection_flag_cb, view_layer, lc); + UI_but_flag_enable(bt, UI_BUT_DRAG_LOCK); + } + PointerRNA collection_ptr; RNA_id_pointer_create(&collection->id, &collection_ptr); - bt = uiDefIconButR_prop(block, UI_BTYPE_ICON_TOGGLE, 0, ICON_RESTRICT_VIEW_OFF, - (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_VIEWX), te->ys, UI_UNIT_X, - UI_UNIT_Y, &collection_ptr, collection_prop_hide_viewport, -1, 0, 0, 0, 0, NULL); + bt = uiDefIconButR_prop( + block, UI_BTYPE_ICON_TOGGLE, 0, ICON_RESTRICT_VIEW_OFF, + (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_VIEWX), te->ys, UI_UNIT_X, + UI_UNIT_Y, &collection_ptr, collection_prop_hide_viewport, -1, 0, 0, 0, 0, NULL); UI_but_flag_enable(bt, UI_BUT_DRAG_LOCK); - bt = uiDefIconButR_prop(block, UI_BTYPE_ICON_TOGGLE, 0, ICON_RESTRICT_RENDER_OFF, - (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_RENDERX), te->ys, UI_UNIT_X, - UI_UNIT_Y, &collection_ptr, collection_prop_hide_render, -1, 0, 0, 0, 0, NULL); + bt = uiDefIconButR_prop( + block, UI_BTYPE_ICON_TOGGLE, 0, ICON_RESTRICT_RENDER_OFF, + (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_RENDERX), te->ys, UI_UNIT_X, + UI_UNIT_Y, &collection_ptr, collection_prop_hide_render, -1, 0, 0, 0, 0, NULL); UI_but_flag_enable(bt, UI_BUT_DRAG_LOCK); - bt = uiDefIconButR_prop(block, UI_BTYPE_ICON_TOGGLE, 0, ICON_RESTRICT_SELECT_OFF, - (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_SELECTX), te->ys, UI_UNIT_X, - UI_UNIT_Y, &collection_ptr, collection_prop_hide_select, -1, 0, 0, 0, 0, NULL); + bt = uiDefIconButR_prop( + block, UI_BTYPE_ICON_TOGGLE, 0, ICON_RESTRICT_SELECT_OFF, + (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_SELECTX), te->ys, UI_UNIT_X, + UI_UNIT_Y, &collection_ptr, collection_prop_hide_select, -1, 0, 0, 0, 0, NULL); UI_but_flag_enable(bt, UI_BUT_DRAG_LOCK); } - - UI_block_emboss_set(block, UI_EMBOSS); } } - if (TSELEM_OPEN(tselem, soops)) outliner_draw_restrictbuts(block, scene, ar, soops, &te->subtree); + if (TSELEM_OPEN(tselem, soops)) { + outliner_draw_restrictbuts(block, scene, view_layer, ar, soops, &te->subtree); + } } } static void outliner_draw_userbuts(uiBlock *block, ARegion *ar, SpaceOops *soops, ListBase *lb) { - uiBut *bt; - TreeElement *te; - TreeStoreElem *tselem; - for (te = lb->first; te; te = te->next) { - tselem = TREESTORE(te); + for (TreeElement *te = lb->first; te; te = te->next) { + TreeStoreElem *tselem = TREESTORE(te); if (te->ys + 2 * UI_UNIT_Y >= ar->v2d.cur.ymin && te->ys <= ar->v2d.cur.ymax) { if (tselem->type == 0) { + uiBut *bt; ID *id = tselem->id; const char *tip = NULL; int icon = ICON_NONE; @@ -607,8 +689,6 @@ static void outliner_draw_userbuts(uiBlock *block, ARegion *ar, SpaceOops *soops if (ID_IS_LINKED(id)) but_flag |= UI_BUT_DISABLED; - UI_block_emboss_set(block, UI_EMBOSS_NONE); - if (id->flag & LIB_FAKEUSER) { icon = ICON_FILE_TICK; tip = TIP_("Data-block will be retained using a fake user"); @@ -617,34 +697,37 @@ static void outliner_draw_userbuts(uiBlock *block, ARegion *ar, SpaceOops *soops icon = ICON_X; tip = TIP_("Data-block has no users and will be deleted"); } - bt = uiDefIconButBitS(block, UI_BTYPE_TOGGLE, LIB_FAKEUSER, 1, icon, - (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_VIEWX), te->ys, UI_UNIT_X, UI_UNIT_Y, - &id->flag, 0, 0, 0, 0, tip); + bt = uiDefIconButBitS( + block, UI_BTYPE_TOGGLE, LIB_FAKEUSER, 1, icon, + (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_VIEWX), te->ys, UI_UNIT_X, UI_UNIT_Y, + &id->flag, 0, 0, 0, 0, tip); UI_but_func_set(bt, restrictbutton_id_user_toggle, id, NULL); UI_but_flag_enable(bt, but_flag); BLI_str_format_int_grouped(buf, id->us); - bt = uiDefBut(block, UI_BTYPE_BUT, 1, buf, - (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_SELECTX), te->ys, - UI_UNIT_X, UI_UNIT_Y, NULL, 0.0, 0.0, 0, 0, - TIP_("Number of users of this data-block")); + bt = uiDefBut( + block, UI_BTYPE_BUT, 1, buf, + (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_SELECTX), te->ys, + UI_UNIT_X, UI_UNIT_Y, NULL, 0.0, 0.0, 0, 0, + TIP_("Number of users of this data-block")); UI_but_flag_enable(bt, but_flag); - bt = uiDefButBitS(block, UI_BTYPE_TOGGLE, LIB_FAKEUSER, 1, (id->flag & LIB_FAKEUSER) ? "F" : " ", - (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_RENDERX), te->ys, UI_UNIT_X, UI_UNIT_Y, - &id->flag, 0, 0, 0, 0, - TIP_("Data-block has a 'fake' user which will keep it in the file " - "even if nothing else uses it")); + bt = uiDefButBitS( + block, UI_BTYPE_TOGGLE, LIB_FAKEUSER, 1, (id->flag & LIB_FAKEUSER) ? "F" : " ", + (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_RENDERX), te->ys, UI_UNIT_X, UI_UNIT_Y, + &id->flag, 0, 0, 0, 0, + TIP_("Data-block has a 'fake' user which will keep it in the file " + "even if nothing else uses it")); UI_but_func_set(bt, restrictbutton_id_user_toggle, id, NULL); UI_but_flag_enable(bt, but_flag); - - UI_block_emboss_set(block, UI_EMBOSS); } } - if (TSELEM_OPEN(tselem, soops)) outliner_draw_userbuts(block, ar, soops, &te->subtree); + if (TSELEM_OPEN(tselem, soops)) { + outliner_draw_userbuts(block, ar, soops, &te->subtree); + } } } @@ -676,13 +759,11 @@ static void outliner_draw_rnacols(ARegion *ar, int sizex) static void outliner_draw_rnabuts(uiBlock *block, ARegion *ar, SpaceOops *soops, int sizex, ListBase *lb) { - TreeElement *te; - TreeStoreElem *tselem; PointerRNA *ptr; PropertyRNA *prop; - for (te = lb->first; te; te = te->next) { - tselem = TREESTORE(te); + for (TreeElement *te = lb->first; te; te = te->next) { + TreeStoreElem *tselem = TREESTORE(te); if (te->ys + 2 * UI_UNIT_Y >= ar->v2d.cur.ymin && te->ys <= ar->v2d.cur.ymax) { if (tselem->type == TSE_RNA_PROPERTY) { ptr = &te->rnaptr; @@ -690,17 +771,20 @@ static void outliner_draw_rnabuts(uiBlock *block, ARegion *ar, SpaceOops *soops, if (!TSELEM_OPEN(tselem, soops)) { if (RNA_property_type(prop) == PROP_POINTER) { - uiBut *but = uiDefAutoButR(block, ptr, prop, -1, "", ICON_NONE, sizex, te->ys, - OL_RNA_COL_SIZEX, UI_UNIT_Y - 1); + uiBut *but = uiDefAutoButR( + block, ptr, prop, -1, "", ICON_NONE, sizex, te->ys, + OL_RNA_COL_SIZEX, UI_UNIT_Y - 1); UI_but_flag_enable(but, UI_BUT_DISABLED); } else if (RNA_property_type(prop) == PROP_ENUM) { - uiDefAutoButR(block, ptr, prop, -1, NULL, ICON_NONE, sizex, te->ys, OL_RNA_COL_SIZEX, - UI_UNIT_Y - 1); + uiDefAutoButR( + block, ptr, prop, -1, NULL, ICON_NONE, sizex, te->ys, OL_RNA_COL_SIZEX, + UI_UNIT_Y - 1); } else { - uiDefAutoButR(block, ptr, prop, -1, "", ICON_NONE, sizex, te->ys, OL_RNA_COL_SIZEX, - UI_UNIT_Y - 1); + uiDefAutoButR( + block, ptr, prop, -1, "", ICON_NONE, sizex, te->ys, OL_RNA_COL_SIZEX, + UI_UNIT_Y - 1); } } } @@ -708,15 +792,16 @@ static void outliner_draw_rnabuts(uiBlock *block, ARegion *ar, SpaceOops *soops, ptr = &te->rnaptr; prop = te->directdata; - uiDefAutoButR(block, ptr, prop, te->index, "", ICON_NONE, sizex, te->ys, OL_RNA_COL_SIZEX, - UI_UNIT_Y - 1); + uiDefAutoButR( + block, ptr, prop, te->index, "", ICON_NONE, sizex, te->ys, OL_RNA_COL_SIZEX, + UI_UNIT_Y - 1); } } - if (TSELEM_OPEN(tselem, soops)) outliner_draw_rnabuts(block, ar, soops, sizex, &te->subtree); + if (TSELEM_OPEN(tselem, soops)) { + outliner_draw_rnabuts(block, ar, soops, sizex, &te->subtree); + } } - - UI_block_emboss_set(block, UI_EMBOSS); } static void outliner_buttons(const bContext *C, uiBlock *block, ARegion *ar, TreeElement *te) @@ -740,8 +825,9 @@ static void outliner_buttons(const bContext *C, uiBlock *block, ARegion *ar, Tre spx = te->xs + 1.8f * UI_UNIT_X; dx = ar->v2d.cur.xmax - (spx + 3.2f * UI_UNIT_X); - bt = uiDefBut(block, UI_BTYPE_TEXT, OL_NAMEBUTTON, "", spx, te->ys, dx, UI_UNIT_Y - 1, (void *)te->name, - 1.0, (float)len, 0, 0, ""); + bt = uiDefBut( + block, UI_BTYPE_TEXT, OL_NAMEBUTTON, "", spx, te->ys, dx, UI_UNIT_Y - 1, (void *)te->name, + 1.0, (float)len, 0, 0, ""); UI_but_func_rename_set(bt, namebutton_cb, tselem); /* returns false if button got removed */ @@ -773,9 +859,10 @@ static void tselem_draw_icon_uibut(struct DrawIconArg *arg, int icon) glDisable(GL_BLEND); } else { - uiBut *but = uiDefIconBut(arg->block, UI_BTYPE_LABEL, 0, icon, arg->xb, arg->yb, UI_UNIT_X, UI_UNIT_Y, NULL, - 0.0, 0.0, 1.0, arg->alpha, - (arg->id && ID_IS_LINKED(arg->id)) ? arg->id->lib->name : ""); + uiBut *but = uiDefIconBut( + arg->block, UI_BTYPE_LABEL, 0, icon, arg->xb, arg->yb, UI_UNIT_X, UI_UNIT_Y, NULL, + 0.0, 0.0, 1.0, arg->alpha, + (arg->id && ID_IS_LINKED(arg->id)) ? arg->id->lib->name : ""); if (arg->id) UI_but_drag_set_id(but, arg->id); @@ -816,8 +903,9 @@ static void UNUSED_FUNCTION(tselem_draw_gp_icon_uibut)(struct DrawIconArg *arg, } } -static void tselem_draw_icon(uiBlock *block, int xmax, float x, float y, TreeStoreElem *tselem, TreeElement *te, - float alpha) +static void tselem_draw_icon( + uiBlock *block, int xmax, float x, float y, TreeStoreElem *tselem, TreeElement *te, + float alpha) { struct DrawIconArg arg; float aspect; @@ -1248,17 +1336,15 @@ static void outliner_draw_iconrow( bContext *C, uiBlock *block, Scene *scene, ViewLayer *view_layer, SpaceOops *soops, ListBase *lb, int level, int xmax, int *offsx, int ys, float alpha_fac) { - TreeElement *te; - TreeStoreElem *tselem; eOLDrawState active; const Object *obact = OBACT(view_layer); - for (te = lb->first; te; te = te->next) { + for (TreeElement *te = lb->first; te; te = te->next) { /* exit drawing early */ if ((*offsx) - UI_UNIT_X > xmax) break; - tselem = TREESTORE(te); + TreeStoreElem *tselem = TREESTORE(te); /* object hierarchy always, further constrained on level */ if (level < 1 || (tselem->type == 0 && te->idcode == ID_OB)) { @@ -1437,12 +1523,16 @@ static void outliner_draw_tree_element( int icon_x = startx; // icons a bit higher - if (TSELEM_OPEN(tselem, soops)) - UI_icon_draw_alpha((float)icon_x + 2 * ufac, (float)*starty + 1 * ufac, ICON_DISCLOSURE_TRI_DOWN, - alpha_fac); - else - UI_icon_draw_alpha((float)icon_x + 2 * ufac, (float)*starty + 1 * ufac, ICON_DISCLOSURE_TRI_RIGHT, - alpha_fac); + if (TSELEM_OPEN(tselem, soops)) { + UI_icon_draw_alpha( + (float)icon_x + 2 * ufac, (float)*starty + 1 * ufac, ICON_DISCLOSURE_TRI_DOWN, + alpha_fac); + } + else { + UI_icon_draw_alpha( + (float)icon_x + 2 * ufac, (float)*starty + 1 * ufac, ICON_DISCLOSURE_TRI_RIGHT, + alpha_fac); + } } offsx += UI_UNIT_X; @@ -1457,22 +1547,26 @@ static void outliner_draw_tree_element( if (ELEM(tselem->type, 0, TSE_LAYER_COLLECTION) && ID_IS_LINKED(tselem->id)) { if (tselem->id->tag & LIB_TAG_MISSING) { - UI_icon_draw_alpha((float)startx + offsx + 2 * ufac, (float)*starty + 2 * ufac, ICON_LIBRARY_DATA_BROKEN, - alpha_fac); + UI_icon_draw_alpha( + (float)startx + offsx + 2 * ufac, (float)*starty + 2 * ufac, ICON_LIBRARY_DATA_BROKEN, + alpha_fac); } else if (tselem->id->tag & LIB_TAG_INDIRECT) { - UI_icon_draw_alpha((float)startx + offsx + 2 * ufac, (float)*starty + 2 * ufac, ICON_LIBRARY_DATA_INDIRECT, - alpha_fac); + UI_icon_draw_alpha( + (float)startx + offsx + 2 * ufac, (float)*starty + 2 * ufac, ICON_LIBRARY_DATA_INDIRECT, + alpha_fac); } else { - UI_icon_draw_alpha((float)startx + offsx + 2 * ufac, (float)*starty + 2 * ufac, ICON_LIBRARY_DATA_DIRECT, - alpha_fac); + UI_icon_draw_alpha( + (float)startx + offsx + 2 * ufac, (float)*starty + 2 * ufac, ICON_LIBRARY_DATA_DIRECT, + alpha_fac); } offsx += UI_UNIT_X + 2 * ufac; } else if (ELEM(tselem->type, 0, TSE_LAYER_COLLECTION) && ID_IS_STATIC_OVERRIDE(tselem->id)) { - UI_icon_draw_alpha((float)startx + offsx + 2 * ufac, (float)*starty + 2 * ufac, ICON_LIBRARY_DATA_OVERRIDE, - alpha_fac); + UI_icon_draw_alpha( + (float)startx + offsx + 2 * ufac, (float)*starty + 2 * ufac, ICON_LIBRARY_DATA_OVERRIDE, + alpha_fac); offsx += UI_UNIT_X + 2 * ufac; } glDisable(GL_BLEND); @@ -1612,12 +1706,12 @@ static void outliner_draw_tree_element_floating( immUnbindProgram(); } -static void outliner_draw_hierarchy_lines_recursive(unsigned pos, SpaceOops *soops, ListBase *lb, int startx, - const unsigned char col[4], bool draw_grayed_out, - int *starty) +static void outliner_draw_hierarchy_lines_recursive( + unsigned pos, SpaceOops *soops, ListBase *lb, int startx, + const unsigned char col[4], bool draw_grayed_out, + int *starty) { TreeElement *te, *te_vertical_line_last = NULL; - TreeStoreElem *tselem; int y1, y2; if (BLI_listbase_is_empty(lb)) { @@ -1630,7 +1724,7 @@ static void outliner_draw_hierarchy_lines_recursive(unsigned pos, SpaceOops *soo y1 = y2 = *starty; for (te = lb->first; te; te = te->next) { bool draw_childs_grayed_out = draw_grayed_out || (te->drag_data != NULL); - tselem = TREESTORE(te); + TreeStoreElem *tselem = TREESTORE(te); if (draw_childs_grayed_out) { immUniformColor3ubvAlpha(col, grayed_alpha); @@ -1653,8 +1747,9 @@ static void outliner_draw_hierarchy_lines_recursive(unsigned pos, SpaceOops *soo *starty -= UI_UNIT_Y; if (TSELEM_OPEN(tselem, soops)) - outliner_draw_hierarchy_lines_recursive(pos, soops, &te->subtree, startx + UI_UNIT_X, - col, draw_childs_grayed_out, starty); + outliner_draw_hierarchy_lines_recursive( + pos, soops, &te->subtree, startx + UI_UNIT_X, + col, draw_childs_grayed_out, starty); } if (draw_grayed_out) { @@ -1690,14 +1785,11 @@ static void outliner_draw_hierarchy_lines(SpaceOops *soops, ListBase *lb, int st static void outliner_draw_struct_marks(ARegion *ar, SpaceOops *soops, ListBase *lb, int *starty) { - TreeElement *te; - TreeStoreElem *tselem; - - for (te = lb->first; te; te = te->next) { - tselem = TREESTORE(te); + for (TreeElement *te = lb->first; te; te = te->next) { + TreeStoreElem *tselem = TREESTORE(te); /* selection status */ - if (TSELEM_OPEN(tselem, soops)) + if (TSELEM_OPEN(tselem, soops)) { if (tselem->type == TSE_RNA_STRUCT) { Gwn_VertFormat *format = immVertexFormat(); unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_I32, 2, GWN_FETCH_INT_TO_FLOAT); @@ -1706,6 +1798,7 @@ static void outliner_draw_struct_marks(ARegion *ar, SpaceOops *soops, ListBase * immRecti(pos, 0, *starty + 1, (int)ar->v2d.cur.xmax, *starty + UI_UNIT_Y - 1); immUnbindProgram(); } + } *starty -= UI_UNIT_Y; if (TSELEM_OPEN(tselem, soops)) { @@ -1732,10 +1825,11 @@ static void outliner_draw_highlights_recursive( const float col_selection[4], const float col_highlight[4], const float col_searchmatch[4], int start_x, int *io_start_y) { - const bool is_searching = SEARCHING_OUTLINER(soops) || - (soops->outlinevis == SO_DATA_API && - (soops->filter & SO_FILTER_SEARCH) && - soops->search_string[0] != 0); + const bool is_searching = ( + SEARCHING_OUTLINER(soops) || + (soops->outlinevis == SO_DATA_API && + (soops->filter & SO_FILTER_SEARCH) && + soops->search_string[0] != 0)); for (TreeElement *te = lb->first; te; te = te->next) { const TreeStoreElem *tselem = TREESTORE(te); @@ -1784,8 +1878,9 @@ static void outliner_draw_highlights(ARegion *ar, SpaceOops *soops, int startx, Gwn_VertFormat *format = immVertexFormat(); unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_I32, 2, GWN_FETCH_INT_TO_FLOAT); immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); - outliner_draw_highlights_recursive(pos, ar, soops, &soops->tree, col_selection, col_highlight, col_searchmatch, - startx, starty); + outliner_draw_highlights_recursive( + pos, ar, soops, &soops->tree, col_selection, col_highlight, col_searchmatch, + startx, starty); immUnbindProgram(); glDisable(GL_BLEND); } @@ -1890,7 +1985,10 @@ static void outliner_draw_restrictcols(ARegion *ar) unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_I32, 2, GWN_FETCH_INT_TO_FLOAT); immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); immUniformThemeColorShadeAlpha(TH_BACK, -15, -200); - immBegin(GWN_PRIM_LINES, 6); + immBegin(GWN_PRIM_LINES, 8); + + immVertex2i(pos, (int)(ar->v2d.cur.xmax - OL_TOG_HIDEX), (int)ar->v2d.cur.ymax); + immVertex2i(pos, (int)(ar->v2d.cur.xmax - OL_TOG_HIDEX), (int)ar->v2d.cur.ymin); immVertex2i(pos, (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_VIEWX), (int)ar->v2d.cur.ymax); immVertex2i(pos, (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_VIEWX), (int)ar->v2d.cur.ymin); @@ -1976,10 +2074,16 @@ void draw_outliner(const bContext *C) (bContext *)C, block, scene, view_layer, ar, soops, has_restrict_icons, &te_edit); + /* Default to no emboss for outliner UI. */ + UI_block_emboss_set(block, UI_EMBOSS_NONE); + if (soops->outlinevis == SO_DATA_API) { /* draw rna buttons */ outliner_draw_rnacols(ar, sizex_rna); + + UI_block_emboss_set(block, UI_EMBOSS); outliner_draw_rnabuts(block, ar, soops, sizex_rna, &soops->tree); + UI_block_emboss_set(block, UI_EMBOSS_NONE); } else if ((soops->outlinevis == SO_ID_ORPHANS) && has_restrict_icons) { /* draw user toggle columns */ @@ -1989,7 +2093,8 @@ void draw_outliner(const bContext *C) else if (has_restrict_icons) { /* draw restriction columns */ outliner_draw_restrictcols(ar); - outliner_draw_restrictbuts(block, scene, ar, soops, &soops->tree); + + outliner_draw_restrictbuts(block, scene, view_layer, ar, soops, &soops->tree); } /* draw edit buttons if nessecery */ @@ -1997,6 +2102,8 @@ void draw_outliner(const bContext *C) outliner_buttons(C, block, ar, te_edit); } + UI_block_emboss_set(block, UI_EMBOSS); + UI_block_end(C, block); UI_block_draw(C, block); } diff --git a/source/blender/editors/space_outliner/outliner_edit.c b/source/blender/editors/space_outliner/outliner_edit.c index 2a694e2e2e3..a455f8c076a 100644 --- a/source/blender/editors/space_outliner/outliner_edit.c +++ b/source/blender/editors/space_outliner/outliner_edit.c @@ -63,6 +63,7 @@ #include "BKE_scene.h" #include "BKE_material.h" +#include "DEG_depsgraph.h" #include "DEG_depsgraph_build.h" #include "../blenloader/BLO_readfile.h" @@ -252,6 +253,55 @@ void OUTLINER_OT_item_openclose(wmOperatorType *ot) RNA_def_boolean(ot->srna, "all", 1, "All", "Close or open all items"); } +/* -------------------------------------------------------------------- */ +/** \name Object Mode Enter/Exit + * \{ */ + +static void item_object_mode_enter_exit( + bContext *C, ReportList *reports, Object *ob, + bool enter) +{ + ViewLayer *view_layer = CTX_data_view_layer(C); + Object *obact = OBACT(view_layer); + + if ((ob->type != obact->type) || ID_IS_LINKED(ob->data)) { + return; + } + if (((ob->mode & obact->mode) != 0) == enter) { + return; + } + + if (ob == obact) { + BKE_report(reports, RPT_WARNING, "Active object mode not changed"); + return; + } + + Base *base = BKE_view_layer_base_find(view_layer, ob); + if (base == NULL) { + return; + } + Scene *scene = CTX_data_scene(C); + outliner_object_mode_toggle(C, scene, view_layer, base); +} + +void item_object_mode_enter_cb( + bContext *C, ReportList *reports, Scene *UNUSED(scene), TreeElement *UNUSED(te), + TreeStoreElem *UNUSED(tsep), TreeStoreElem *tselem, void *UNUSED(user_data)) +{ + Object *ob = (Object *)tselem->id; + item_object_mode_enter_exit(C, reports, ob, true); +} + +void item_object_mode_exit_cb( + bContext *C, ReportList *reports, Scene *UNUSED(scene), TreeElement *UNUSED(te), + TreeStoreElem *UNUSED(tsep), TreeStoreElem *tselem, void *UNUSED(user_data)) +{ + Object *ob = (Object *)tselem->id; + item_object_mode_enter_exit(C, reports, ob, false); +} + +/** \} */ + /* Rename --------------------------------------------------- */ static void do_item_rename(ARegion *ar, TreeElement *te, TreeStoreElem *tselem, @@ -901,6 +951,7 @@ static int outliner_toggle_selected_exec(bContext *C, wmOperator *UNUSED(op)) else outliner_set_flag(&soops->tree, TSE_SELECTED, 1); + DEG_id_tag_update(&scene->id, DEG_TAG_SELECT_UPDATE); WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene); ED_region_tag_redraw_no_rebuild(ar); @@ -2169,6 +2220,7 @@ static int scene_drop_invoke(bContext *C, wmOperator *op, const wmEvent *event) DEG_relations_tag_update(bmain); + DEG_id_tag_update(&scene->id, DEG_TAG_SELECT_UPDATE); WM_main_add_notifier(NC_SCENE | ND_OB_SELECT, scene); return OPERATOR_FINISHED; diff --git a/source/blender/editors/space_outliner/outliner_intern.h b/source/blender/editors/space_outliner/outliner_intern.h index 8ac09648d60..1f8320f73a0 100644 --- a/source/blender/editors/space_outliner/outliner_intern.h +++ b/source/blender/editors/space_outliner/outliner_intern.h @@ -151,11 +151,12 @@ typedef enum { /* size constants */ #define OL_Y_OFFSET 2 +#define OL_TOG_HIDEX (UI_UNIT_X * 4.0f) #define OL_TOG_RESTRICT_SELECTX (UI_UNIT_X * 3.0f) #define OL_TOG_RESTRICT_VIEWX (UI_UNIT_X * 2.0f) #define OL_TOG_RESTRICT_RENDERX UI_UNIT_X -#define OL_TOGW OL_TOG_RESTRICT_SELECTX +#define OL_TOGW OL_TOG_HIDEX #define OL_RNA_COLX (UI_UNIT_X * 15) #define OL_RNA_COL_SIZEX (UI_UNIT_X * 7.5f) @@ -226,6 +227,10 @@ void outliner_item_select( struct SpaceOops *soops, const struct TreeElement *te, const bool extend, const bool toggle); +void outliner_object_mode_toggle( + struct bContext *C, Scene *scene, ViewLayer *view_layer, + Base *base); + /* outliner_edit.c ---------------------------------------------- */ typedef void (*outliner_operation_cb)( struct bContext *C, struct ReportList *, struct Scene *scene, @@ -271,6 +276,13 @@ void id_remap_cb( struct bContext *C, struct ReportList *reports, struct Scene *scene, struct TreeElement *te, struct TreeStoreElem *tsep, struct TreeStoreElem *tselem, void *user_data); +void item_object_mode_enter_cb( + struct bContext *C, struct ReportList *reports, struct Scene *scene, + TreeElement *te, struct TreeStoreElem *tsep, struct TreeStoreElem *tselem, void *user_data); +void item_object_mode_exit_cb( + struct bContext *C, struct ReportList *reports, struct Scene *scene, + TreeElement *te, struct TreeStoreElem *tsep, struct TreeStoreElem *tselem, void *user_data); + TreeElement *outliner_dropzone_find(const struct SpaceOops *soops, const float fmval[2], const bool children); void outliner_set_coordinates(struct ARegion *ar, struct SpaceOops *soops); diff --git a/source/blender/editors/space_outliner/outliner_ops.c b/source/blender/editors/space_outliner/outliner_ops.c index ecfd12618e5..316caf0e239 100644 --- a/source/blender/editors/space_outliner/outliner_ops.c +++ b/source/blender/editors/space_outliner/outliner_ops.c @@ -560,6 +560,13 @@ void outliner_keymap(wmKeyConfig *keyconf) WM_keymap_verify_item(keymap, "OBJECT_OT_move_to_collection", MKEY, KM_PRESS, 0, 0); WM_keymap_verify_item(keymap, "OBJECT_OT_link_to_collection", MKEY, KM_PRESS, KM_SHIFT, 0); + kmi = WM_keymap_add_item(keymap, "OBJECT_OT_hide_view_clear", HKEY, KM_PRESS, KM_ALT, 0); + RNA_boolean_set(kmi->ptr, "select", false); + kmi = WM_keymap_add_item(keymap, "OBJECT_OT_hide_view_set", HKEY, KM_PRESS, 0, 0); + RNA_boolean_set(kmi->ptr, "unselected", false); + kmi = WM_keymap_add_item(keymap, "OBJECT_OT_hide_view_set", HKEY, KM_PRESS, KM_SHIFT, 0); + RNA_boolean_set(kmi->ptr, "unselected", true); + outliner_item_drag_drop_modal_keymap(keyconf); } diff --git a/source/blender/editors/space_outliner/outliner_select.c b/source/blender/editors/space_outliner/outliner_select.c index 36fd37e1134..38ae0683d4b 100644 --- a/source/blender/editors/space_outliner/outliner_select.c +++ b/source/blender/editors/space_outliner/outliner_select.c @@ -81,6 +81,7 @@ static void do_outliner_activate_obdata(bContext *C, Scene *scene, ViewLayer *vi if (obact == NULL) { ED_object_base_activate(C, base); + DEG_id_tag_update(&scene->id, DEG_TAG_SELECT_UPDATE); WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene); obact = base->object; use_all = true; @@ -104,6 +105,7 @@ static void do_outliner_activate_obdata(bContext *C, Scene *scene, ViewLayer *vi } if (ok) { ED_object_base_select(base, (ob->mode & OB_MODE_EDIT) ? BA_SELECT : BA_DESELECT); + DEG_id_tag_update(&scene->id, DEG_TAG_SELECT_UPDATE); WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene); } } @@ -118,6 +120,7 @@ static void do_outliner_activate_pose(bContext *C, ViewLayer *view_layer, Base * if (obact == NULL) { ED_object_base_activate(C, base); Scene *scene = CTX_data_scene(C); + DEG_id_tag_update(&scene->id, DEG_TAG_SELECT_UPDATE); WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene); obact = base->object; use_all = true; @@ -144,6 +147,7 @@ static void do_outliner_activate_pose(bContext *C, ViewLayer *view_layer, Base * ED_object_base_select(base, (ob->mode & OB_MODE_POSE) ? BA_SELECT : BA_DESELECT); Scene *scene = CTX_data_scene(C); + DEG_id_tag_update(&scene->id, DEG_TAG_SELECT_UPDATE); WM_event_add_notifier(C, NC_SCENE | ND_MODE | NS_MODE_OBJECT, NULL); WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene); } @@ -151,6 +155,20 @@ static void do_outliner_activate_pose(bContext *C, ViewLayer *view_layer, Base * } } +/* For draw callback to run mode switching */ +void outliner_object_mode_toggle( + bContext *C, Scene *scene, ViewLayer *view_layer, + Base *base) +{ + Object *obact = OBACT(view_layer); + if (obact->mode & OB_MODE_EDIT) { + do_outliner_activate_obdata(C, scene, view_layer, base); + } + else if (obact->mode & OB_MODE_POSE) { + do_outliner_activate_pose(C, view_layer, base); + } +} + /* ****************************************************** */ /* Outliner Element Selection/Activation on Click */ @@ -251,22 +269,22 @@ static eOLDrawState tree_element_set_active_object( /* find associated base in current scene */ base = BKE_view_layer_base_find(view_layer, ob); -#ifdef USE_OBJECT_MODE_STRICT - if (base != NULL) { - Object *obact = OBACT(view_layer); - const eObjectMode object_mode = obact ? obact->mode : OB_MODE_OBJECT; - if (base && !BKE_object_is_mode_compat(base->object, object_mode)) { - if (object_mode == OB_MODE_OBJECT) { - struct Main *bmain = CTX_data_main(C); - Depsgraph *depsgraph = CTX_data_depsgraph(C); - ED_object_mode_generic_exit(bmain, depsgraph, scene, base->object); - } - if (!BKE_object_is_mode_compat(base->object, object_mode)) { - base = NULL; + if (scene->toolsettings->object_flag & SCE_OBJECT_MODE_LOCK) { + if (base != NULL) { + Object *obact = OBACT(view_layer); + const eObjectMode object_mode = obact ? obact->mode : OB_MODE_OBJECT; + if (base && !BKE_object_is_mode_compat(base->object, object_mode)) { + if (object_mode == OB_MODE_OBJECT) { + struct Main *bmain = CTX_data_main(C); + Depsgraph *depsgraph = CTX_data_depsgraph(C); + ED_object_mode_generic_exit(bmain, depsgraph, scene, base->object); + } + if (!BKE_object_is_mode_compat(base->object, object_mode)) { + base = NULL; + } } } } -#endif if (base) { if (set == OL_SETSEL_EXTEND) { @@ -278,13 +296,11 @@ static eOLDrawState tree_element_set_active_object( } else { /* deleselect all */ -#ifdef USE_OBJECT_MODE_STRICT + /* Only in object mode so we can switch the active object, * keeping all objects in the current 'mode' selected, useful for multi-pose/edit mode. * This keeps the convention that all objects in the current mode are also selected. see T55246. */ - if (ob->mode == OB_MODE_OBJECT) -#endif - { + if ((scene->toolsettings->object_flag & SCE_OBJECT_MODE_LOCK) ? (ob->mode == OB_MODE_OBJECT) : true) { BKE_view_layer_base_deselect_all(view_layer); } ED_object_base_select(base, BA_SELECT); @@ -297,6 +313,7 @@ static eOLDrawState tree_element_set_active_object( if (set != OL_SETSEL_NONE) { ED_object_base_activate(C, base); /* adds notifier */ + DEG_id_tag_update(&scene->id, DEG_TAG_SELECT_UPDATE); WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene); } @@ -976,6 +993,7 @@ static void do_outliner_item_activate_tree_element( FOREACH_COLLECTION_OBJECT_RECURSIVE_END; } + DEG_id_tag_update(&scene->id, DEG_TAG_SELECT_UPDATE); WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene); } else if (OB_DATA_SUPPORT_EDITMODE(te->idcode)) { @@ -1176,6 +1194,7 @@ static int outliner_border_select_exec(bContext *C, wmOperator *op) outliner_item_border_select(scene, &rectf, te, select); } + DEG_id_tag_update(&scene->id, DEG_TAG_SELECT_UPDATE); WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene); ED_region_tag_redraw(ar); diff --git a/source/blender/editors/space_outliner/outliner_tools.c b/source/blender/editors/space_outliner/outliner_tools.c index 8a01e5a7f2f..32918806765 100644 --- a/source/blender/editors/space_outliner/outliner_tools.c +++ b/source/blender/editors/space_outliner/outliner_tools.c @@ -893,6 +893,7 @@ static void object_delete_hierarchy_cb( #endif } + DEG_id_tag_update(&scene->id, DEG_TAG_SELECT_UPDATE); WM_event_add_notifier(C, NC_SCENE | ND_OB_ACTIVE, scene); } @@ -910,6 +911,8 @@ enum { OL_OP_TOGSEL, OL_OP_TOGREN, OL_OP_RENAME, + OL_OP_OBJECT_MODE_ENTER, + OL_OP_OBJECT_MODE_EXIT, }; static const EnumPropertyItem prop_object_op_types[] = { @@ -921,6 +924,8 @@ static const EnumPropertyItem prop_object_op_types[] = { {OL_OP_REMAP, "REMAP", 0, "Remap Users", "Make all users of selected data-blocks to use instead a new chosen one"}, {OL_OP_RENAME, "RENAME", 0, "Rename", ""}, + {OL_OP_OBJECT_MODE_ENTER, "OBJECT_MODE_ENTER", 0, "Enter Mode", ""}, + {OL_OP_OBJECT_MODE_EXIT, "OBJECT_MODE_EXIT", 0, "Exit Mode", ""}, {0, NULL, 0, NULL, NULL} }; @@ -947,6 +952,7 @@ static int outliner_object_operation_exec(bContext *C, wmOperator *op) } str = "Select Objects"; + DEG_id_tag_update(&scene->id, DEG_TAG_SELECT_UPDATE); WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene); } else if (event == OL_OP_SELECT_HIERARCHY) { @@ -956,11 +962,13 @@ static int outliner_object_operation_exec(bContext *C, wmOperator *op) WM_window_change_active_scene(bmain, C, win, sce); } str = "Select Object Hierarchy"; + DEG_id_tag_update(&scene->id, DEG_TAG_SELECT_UPDATE); WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene); } else if (event == OL_OP_DESELECT) { outliner_do_object_operation(C, op->reports, scene, soops, &soops->tree, object_deselect_cb); str = "Deselect Objects"; + DEG_id_tag_update(&scene->id, DEG_TAG_SELECT_UPDATE); WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene); } else if (event == OL_OP_DELETE) { @@ -975,6 +983,7 @@ static int outliner_object_operation_exec(bContext *C, wmOperator *op) DEG_relations_tag_update(bmain); str = "Delete Objects"; + DEG_id_tag_update(&scene->id, DEG_TAG_SELECT_UPDATE); WM_event_add_notifier(C, NC_SCENE | ND_OB_ACTIVE, scene); } else if (event == OL_OP_DELETE_HIERARCHY) { @@ -985,6 +994,7 @@ static int outliner_object_operation_exec(bContext *C, wmOperator *op) DEG_relations_tag_update(bmain); str = "Delete Object Hierarchy"; + DEG_id_tag_update(&scene->id, DEG_TAG_SELECT_UPDATE); WM_event_add_notifier(C, NC_SCENE | ND_OB_ACTIVE, scene); } else if (event == OL_OP_REMAP) { @@ -999,6 +1009,14 @@ static int outliner_object_operation_exec(bContext *C, wmOperator *op) outliner_do_object_operation(C, op->reports, scene, soops, &soops->tree, item_rename_cb); str = "Rename Object"; } + else if (event == OL_OP_OBJECT_MODE_ENTER) { + outliner_do_object_operation(C, op->reports, scene, soops, &soops->tree, item_object_mode_enter_cb); + str = "Enter Current Mode"; + } + else if (event == OL_OP_OBJECT_MODE_EXIT) { + outliner_do_object_operation(C, op->reports, scene, soops, &soops->tree, item_object_mode_exit_cb); + str = "Exit Current Mode"; + } else { BLI_assert(0); return OPERATOR_CANCELLED; @@ -1568,8 +1586,8 @@ void OUTLINER_OT_animdata_operation(wmOperatorType *ot) /* **************************************** */ static const EnumPropertyItem prop_constraint_op_types[] = { - {OL_CONSTRAINTOP_ENABLE, "ENABLE", ICON_RESTRICT_VIEW_OFF, "Enable", ""}, - {OL_CONSTRAINTOP_DISABLE, "DISABLE", ICON_RESTRICT_VIEW_ON, "Disable", ""}, + {OL_CONSTRAINTOP_ENABLE, "ENABLE", ICON_HIDE_OFF, "Enable", ""}, + {OL_CONSTRAINTOP_DISABLE, "DISABLE", ICON_HIDE_ON, "Disable", ""}, {OL_CONSTRAINTOP_DELETE, "DELETE", ICON_X, "Delete", ""}, {0, NULL, 0, NULL, NULL} }; diff --git a/source/blender/editors/space_outliner/outliner_tree.c b/source/blender/editors/space_outliner/outliner_tree.c index d155457a208..13b62b766f5 100644 --- a/source/blender/editors/space_outliner/outliner_tree.c +++ b/source/blender/editors/space_outliner/outliner_tree.c @@ -1469,6 +1469,10 @@ static void outliner_add_layer_collection_objects( Base *base = BKE_view_layer_base_find(layer, cob->ob); TreeElement *te_object = outliner_add_element(soops, tree, base->object, ten, 0, 0); te_object->directdata = base; + + if (!(base->flag & BASE_VISIBLED)) { + te_object->flag |= TE_DISABLED; + } } } @@ -1487,7 +1491,9 @@ static void outliner_add_layer_collections_recursive( ten->reinsert_poll = outliner_collections_reorder_poll; const bool exclude = (lc->flag & LAYER_COLLECTION_EXCLUDE) != 0; - if (exclude) { + if (exclude || + ((layer->runtime_flag & VIEW_LAYER_HAS_HIDE) && + !(lc->runtime_flag & LAYER_COLLECTION_HAS_VISIBLE_OBJECTS))) { ten->flag |= TE_DISABLED; } diff --git a/source/blender/editors/space_sequencer/sequencer_edit.c b/source/blender/editors/space_sequencer/sequencer_edit.c index b24817f2af8..a78b3ee79c1 100644 --- a/source/blender/editors/space_sequencer/sequencer_edit.c +++ b/source/blender/editors/space_sequencer/sequencer_edit.c @@ -3874,7 +3874,7 @@ static int sequencer_export_subtitles_invoke(bContext *C, wmOperator *op, const else BLI_strncpy(filepath, BKE_main_blendfile_path(bmain), sizeof(filepath)); - BLI_replace_extension(filepath, sizeof(filepath), ".srt"); + BLI_path_extension_replace(filepath, sizeof(filepath), ".srt"); RNA_string_set(op->ptr, "filepath", filepath); } @@ -3899,7 +3899,7 @@ static int sequencer_export_subtitles_exec(bContext *C, wmOperator *op) } RNA_string_get(op->ptr, "filepath", filepath); - BLI_ensure_extension(filepath, sizeof(filepath), ".srt"); + BLI_path_extension_ensure(filepath, sizeof(filepath), ".srt"); /* Avoid File write exceptions */ if (!BLI_exists(filepath)) { diff --git a/source/blender/editors/space_sequencer/space_sequencer.c b/source/blender/editors/space_sequencer/space_sequencer.c index 75734963a0e..fc47934bc1e 100644 --- a/source/blender/editors/space_sequencer/space_sequencer.c +++ b/source/blender/editors/space_sequencer/space_sequencer.c @@ -708,7 +708,7 @@ static void sequencer_buttons_region_init(wmWindowManager *wm, ARegion *ar) static void sequencer_buttons_region_draw(const bContext *C, ARegion *ar) { - ED_region_panels(C, ar, NULL, -1, true); + ED_region_panels(C, ar); } static void sequencer_buttons_region_listener( diff --git a/source/blender/editors/space_text/space_text.c b/source/blender/editors/space_text/space_text.c index 5885312e255..e827f4f0149 100644 --- a/source/blender/editors/space_text/space_text.c +++ b/source/blender/editors/space_text/space_text.c @@ -551,7 +551,7 @@ static void text_properties_region_draw(const bContext *C, ARegion *ar) { SpaceText *st = CTX_wm_space_text(C); - ED_region_panels(C, ar, NULL, -1, true); + ED_region_panels(C, ar); /* this flag trick is make sure buttons have been added already */ if (st->flags & ST_FIND_ACTIVATE) { diff --git a/source/blender/editors/space_text/text_header.c b/source/blender/editors/space_text/text_header.c index 50a8739c5b4..3d964d07908 100644 --- a/source/blender/editors/space_text/text_header.c +++ b/source/blender/editors/space_text/text_header.c @@ -91,7 +91,7 @@ static int text_properties_exec(bContext *C, wmOperator *UNUSED(op)) void TEXT_OT_properties(wmOperatorType *ot) { /* identifiers */ - ot->name = "Properties"; + ot->name = "Toggle Sidebar"; ot->description = "Toggle the properties region visibility"; ot->idname = "TEXT_OT_properties"; diff --git a/source/blender/editors/space_text/text_ops.c b/source/blender/editors/space_text/text_ops.c index b3815d73c5c..e34edc8908f 100644 --- a/source/blender/editors/space_text/text_ops.c +++ b/source/blender/editors/space_text/text_ops.c @@ -2071,7 +2071,9 @@ void TEXT_OT_delete(wmOperatorType *ot) ot->flag = OPTYPE_UNDO; /* properties */ - RNA_def_enum(ot->srna, "type", delete_type_items, DEL_NEXT_CHAR, "Type", "Which part of the text to delete"); + PropertyRNA *prop; + prop = RNA_def_enum(ot->srna, "type", delete_type_items, DEL_NEXT_CHAR, "Type", "Which part of the text to delete"); + RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE); } /******************* toggle overwrite operator **********************/ @@ -2243,13 +2245,15 @@ static int text_scroll_modal(bContext *C, wmOperator *op, const wmEvent *event) case LEFTMOUSE: case RIGHTMOUSE: case MIDDLEMOUSE: - if (ELEM(tsc->zone, SCROLLHANDLE_MIN_OUTSIDE, SCROLLHANDLE_MAX_OUTSIDE)) { - txt_screen_skip(st, ar, st->viewlines * (tsc->zone == SCROLLHANDLE_MIN_OUTSIDE ? 1 : -1)); + if (event->val == KM_RELEASE) { + if (ELEM(tsc->zone, SCROLLHANDLE_MIN_OUTSIDE, SCROLLHANDLE_MAX_OUTSIDE)) { + txt_screen_skip(st, ar, st->viewlines * (tsc->zone == SCROLLHANDLE_MIN_OUTSIDE ? 1 : -1)); - ED_area_tag_redraw(CTX_wm_area(C)); + ED_area_tag_redraw(CTX_wm_area(C)); + } + scroll_exit(C, op); + return OPERATOR_FINISHED; } - scroll_exit(C, op); - return OPERATOR_FINISHED; } return OPERATOR_RUNNING_MODAL; diff --git a/source/blender/editors/space_topbar/space_topbar.c b/source/blender/editors/space_topbar/space_topbar.c index 4342fa87f89..c7ef6591c0d 100644 --- a/source/blender/editors/space_topbar/space_topbar.c +++ b/source/blender/editors/space_topbar/space_topbar.c @@ -57,9 +57,6 @@ #include "WM_types.h" #include "WM_message.h" - -void topbar_panels_register(ARegionType *art); - /* ******************** default callbacks for topbar space ***************** */ static SpaceLink *topbar_new(const ScrArea *UNUSED(area), const Scene *UNUSED(scene)) @@ -277,64 +274,9 @@ void ED_spacetype_topbar(void) art->layout = ED_region_header_layout; art->draw = ED_region_header_draw; - /* For popovers. */ - topbar_panels_register(art); - BLI_addhead(&st->regiontypes, art); recent_files_menu_register(); BKE_spacetype_register(st); } - - -/* -------------------------------------------------------------------- */ -/** \name Redo Panel - * \{ */ - -static int topbar_panel_operator_redo_poll(const bContext *C, PanelType *UNUSED(pt)) -{ - wmOperator *op = WM_operator_last_redo(C); - if (op == NULL) { - return false; - } - - bool success = false; - if (!WM_operator_check_ui_empty(op->type)) { - const OperatorRepeatContextHandle *context_info; - context_info = ED_operator_repeat_prepare_context((bContext *)C, op); - success = WM_operator_poll((bContext *)C, op->type); - ED_operator_repeat_reset_context((bContext *)C, context_info); - } - return success; -} - -static void topbar_panel_operator_redo(const bContext *C, Panel *pa) -{ - wmOperator *op = WM_operator_last_redo(C); - if (op == NULL) { - return; - } - if (!WM_operator_check_ui_enabled(C, op->type->name)) { - uiLayoutSetEnabled(pa->layout, false); - } - uiLayout *col = uiLayoutColumn(pa->layout, false); - uiTemplateOperatorRedoProperties(col, C); -} - -void topbar_panels_register(ARegionType *art) -{ - PanelType *pt; - - pt = MEM_callocN(sizeof(PanelType), __func__); - strcpy(pt->idname, "TOPBAR_PT_redo"); - strcpy(pt->label, N_("Redo")); - strcpy(pt->translation_context, BLT_I18NCONTEXT_DEFAULT_BPYRNA); - pt->draw = topbar_panel_operator_redo; - pt->poll = topbar_panel_operator_redo_poll; - pt->space_type = SPACE_TOPBAR; - pt->region_type = RGN_TYPE_HEADER; - BLI_addtail(&art->paneltypes, pt); -} - -/** \} */ diff --git a/source/blender/editors/space_userpref/space_userpref.c b/source/blender/editors/space_userpref/space_userpref.c index b3f45de518b..1d3c24c518a 100644 --- a/source/blender/editors/space_userpref/space_userpref.c +++ b/source/blender/editors/space_userpref/space_userpref.c @@ -64,7 +64,7 @@ static SpaceLink *userpref_new(const ScrArea *UNUSED(area), const Scene *UNUSED( BLI_addtail(&spref->regionbase, ar); ar->regiontype = RGN_TYPE_HEADER; - ar->alignment = RGN_ALIGN_TOP; + ar->alignment = RGN_ALIGN_BOTTOM; /* main region */ ar = MEM_callocN(sizeof(ARegion), "main region for userpref"); @@ -113,7 +113,7 @@ static void userpref_main_region_init(wmWindowManager *wm, ARegion *ar) static void userpref_main_region_draw(const bContext *C, ARegion *ar) { - ED_region_panels(C, ar, NULL, -1, true); + ED_region_panels(C, ar); } static void userpref_operatortypes(void) diff --git a/source/blender/editors/space_view3d/space_view3d.c b/source/blender/editors/space_view3d/space_view3d.c index 63d7d98b689..d77b13630e3 100644 --- a/source/blender/editors/space_view3d/space_view3d.c +++ b/source/blender/editors/space_view3d/space_view3d.c @@ -296,8 +296,10 @@ void ED_view3d_shade_update(Main *bmain, View3D *v3d, ScrArea *sa) ARegion *ar; for (ar = sa->regionbase.first; ar; ar = ar->next) { - if (ar->regiondata) + if ((ar->regiontype == RGN_TYPE_WINDOW) && ar->regiondata) { ED_view3d_stop_render_preview(wm, ar); + break; + } } } } @@ -820,7 +822,6 @@ static void view3d_main_region_listener( break; case ND_OB_ACTIVE: case ND_OB_SELECT: - DEG_id_tag_update((ID *)&scene->id, DEG_TAG_SELECT_UPDATE); ATTR_FALLTHROUGH; case ND_FRAME: case ND_TRANSFORM: @@ -875,18 +876,6 @@ static void view3d_main_region_listener( case ND_SELECT: { WM_manipulatormap_tag_refresh(mmap); - - ID *ob_data = wmn->reference; - if (ob_data == NULL) { - BLI_assert(wmn->window); // Use `WM_event_add_notifier` instead of `WM_main_add_notifier` - ViewLayer *view_layer = WM_window_get_active_view_layer(wmn->window); - ob_data = OBEDIT_FROM_VIEW_LAYER(view_layer)->data; - } - if (ob_data) { - BLI_assert(OB_DATA_SUPPORT_ID(GS(ob_data->name))); - /* TODO(sergey): Notifiers shouldn't really be doing DEG tags. */ - DEG_id_tag_update(ob_data, DEG_TAG_SELECT_UPDATE); - } ATTR_FALLTHROUGH; } case ND_DATA: @@ -1232,7 +1221,7 @@ static void view3d_buttons_region_init(wmWindowManager *wm, ARegion *ar) static void view3d_buttons_region_draw(const bContext *C, ARegion *ar) { - ED_region_panels(C, ar, NULL, -1, true); + ED_region_panels(C, ar); } static void view3d_buttons_region_listener( @@ -1361,7 +1350,7 @@ static void view3d_tools_region_init(wmWindowManager *wm, ARegion *ar) static void view3d_tools_region_draw(const bContext *C, ARegion *ar) { - ED_region_panels(C, ar, (const char * []){CTX_data_mode_string(C), NULL}, -1, true); + ED_region_panels_ex(C, ar, (const char * []){CTX_data_mode_string(C), NULL}, -1, true); } /* area (not region) level listener */ @@ -1565,5 +1554,9 @@ void ED_spacetype_view3d(void) art->message_subscribe = view3d_header_region_message_subscribe; BLI_addhead(&st->regiontypes, art); + /* regions: hud */ + art = ED_area_type_hud(st->spaceid); + BLI_addhead(&st->regiontypes, art); + BKE_spacetype_register(st); } diff --git a/source/blender/editors/space_view3d/view3d_buttons.c b/source/blender/editors/space_view3d/view3d_buttons.c index 69e8aa07d3f..6ebed88728e 100644 --- a/source/blender/editors/space_view3d/view3d_buttons.c +++ b/source/blender/editors/space_view3d/view3d_buttons.c @@ -69,6 +69,7 @@ #include "RNA_access.h" #include "ED_armature.h" +#include "ED_object.h" #include "ED_mesh.h" #include "ED_screen.h" @@ -1163,6 +1164,11 @@ static void view3d_panel_transform(const bContext *C, Panel *pa) } } +static void hide_collections_menu_draw(const bContext *C, Menu *menu) +{ + ED_hide_collections_menu_draw(C, menu->layout); +} + void view3d_buttons_register(ARegionType *art) { PanelType *pt; @@ -1182,6 +1188,15 @@ void view3d_buttons_register(ARegionType *art) pt->draw = view3d_panel_vgroup; pt->poll = view3d_panel_vgroup_poll; BLI_addtail(&art->paneltypes, pt); + + MenuType *mt; + + mt = MEM_callocN(sizeof(MenuType), "spacetype view3d menu collections"); + strcpy(mt->idname, "VIEW3D_MT_collection"); + strcpy(mt->label, N_("Collection")); + strcpy(mt->translation_context, BLT_I18NCONTEXT_DEFAULT_BPYRNA); + mt->draw = hide_collections_menu_draw; + WM_menutype_add(mt); } static int view3d_properties_toggle_exec(bContext *C, wmOperator *UNUSED(op)) @@ -1197,7 +1212,7 @@ static int view3d_properties_toggle_exec(bContext *C, wmOperator *UNUSED(op)) void VIEW3D_OT_properties(wmOperatorType *ot) { - ot->name = "Properties"; + ot->name = "Toggle Sidebar"; ot->description = "Toggle the properties region visibility"; ot->idname = "VIEW3D_OT_properties"; diff --git a/source/blender/editors/space_view3d/view3d_edit.c b/source/blender/editors/space_view3d/view3d_edit.c index cdf2106d8bf..bae186097a8 100644 --- a/source/blender/editors/space_view3d/view3d_edit.c +++ b/source/blender/editors/space_view3d/view3d_edit.c @@ -1112,7 +1112,6 @@ static void view3d_ndof_pan_zoom( static void view3d_ndof_orbit( const struct wmNDOFMotionData *ndof, ScrArea *sa, ARegion *ar, - /* optional, can be NULL*/ ViewOpsData *vod, const bool apply_dyn_ofs) { View3D *v3d = sa->spacedata.first; @@ -1445,7 +1444,7 @@ static int ndof_orbit_zoom_invoke(bContext *C, wmOperator *op, const wmEvent *ev ED_view3d_distance_set(rv3d, 0.0f); if (has_rotation) { - view3d_ndof_orbit(ndof, vod->sa, vod->ar, NULL, false); + view3d_ndof_orbit(ndof, vod->sa, vod->ar, vod, false); } ED_view3d_distance_set(rv3d, dist_backup); @@ -1812,7 +1811,7 @@ static void view_zoom_to_window_xy_camera( { RegionView3D *rv3d = ar->regiondata; const float zoomfac = BKE_screen_view3d_zoom_to_fac(rv3d->camzoom); - const float zoomfac_new = CLAMPIS(zoomfac * (1.0f / dfac), RV3D_CAMZOOM_MIN_FACTOR, RV3D_CAMZOOM_MAX_FACTOR); + const float zoomfac_new = clamp_f(zoomfac * (1.0f / dfac), RV3D_CAMZOOM_MIN_FACTOR, RV3D_CAMZOOM_MAX_FACTOR); const float camzoom_new = BKE_screen_view3d_zoom_from_fac(zoomfac_new); diff --git a/source/blender/editors/space_view3d/view3d_manipulator_camera.c b/source/blender/editors/space_view3d/view3d_manipulator_camera.c index 49fa83e82fc..023e16c070e 100644 --- a/source/blender/editors/space_view3d/view3d_manipulator_camera.c +++ b/source/blender/editors/space_view3d/view3d_manipulator_camera.c @@ -109,7 +109,7 @@ static void WIDGETGROUP_camera_setup(const bContext *C, wmManipulatorGroup *mgro mpr = camgroup->focal_len = WM_manipulator_new_ptr(wt_arrow, mgroup, NULL); mpr->flag |= WM_MANIPULATOR_DRAW_NO_SCALE; RNA_enum_set(mpr->ptr, "draw_style", ED_MANIPULATOR_ARROW_STYLE_CONE); - RNA_enum_set(mpr->ptr, "draw_options", ED_MANIPULATOR_ARROW_STYLE_CONSTRAINED); + RNA_enum_set(mpr->ptr, "transform", ED_MANIPULATOR_ARROW_XFORM_FLAG_CONSTRAINED); UI_GetThemeColor3fv(TH_MANIPULATOR_PRIMARY, mpr->color); UI_GetThemeColor3fv(TH_MANIPULATOR_HI, mpr->color_hi); @@ -117,7 +117,7 @@ static void WIDGETGROUP_camera_setup(const bContext *C, wmManipulatorGroup *mgro mpr = camgroup->ortho_scale = WM_manipulator_new_ptr(wt_arrow, mgroup, NULL); mpr->flag |= WM_MANIPULATOR_DRAW_NO_SCALE; RNA_enum_set(mpr->ptr, "draw_style", ED_MANIPULATOR_ARROW_STYLE_CONE); - RNA_enum_set(mpr->ptr, "draw_options", ED_MANIPULATOR_ARROW_STYLE_CONSTRAINED); + RNA_enum_set(mpr->ptr, "transform", ED_MANIPULATOR_ARROW_XFORM_FLAG_CONSTRAINED); UI_GetThemeColor3fv(TH_MANIPULATOR_PRIMARY, mpr->color); UI_GetThemeColor3fv(TH_MANIPULATOR_HI, mpr->color_hi); diff --git a/source/blender/editors/space_view3d/view3d_manipulator_forcefield.c b/source/blender/editors/space_view3d/view3d_manipulator_forcefield.c index 2a1fdee8e8a..305085be370 100644 --- a/source/blender/editors/space_view3d/view3d_manipulator_forcefield.c +++ b/source/blender/editors/space_view3d/view3d_manipulator_forcefield.c @@ -72,7 +72,7 @@ static void WIDGETGROUP_forcefield_setup(const bContext *UNUSED(C), wmManipulato wwrapper->manipulator = WM_manipulator_new("MANIPULATOR_WT_arrow_3d", mgroup, NULL); wmManipulator *mpr = wwrapper->manipulator; - RNA_enum_set(mpr->ptr, "draw_options", ED_MANIPULATOR_ARROW_STYLE_CONSTRAINED); + RNA_enum_set(mpr->ptr, "transform", ED_MANIPULATOR_ARROW_XFORM_FLAG_CONSTRAINED); ED_manipulator_arrow3d_set_ui_range(mpr, -200.0f, 200.0f); ED_manipulator_arrow3d_set_range_fac(mpr, 6.0f); diff --git a/source/blender/editors/space_view3d/view3d_manipulator_lamp.c b/source/blender/editors/space_view3d/view3d_manipulator_lamp.c index 01c38cfd899..f98a2f336bc 100644 --- a/source/blender/editors/space_view3d/view3d_manipulator_lamp.c +++ b/source/blender/editors/space_view3d/view3d_manipulator_lamp.c @@ -74,7 +74,7 @@ static void WIDGETGROUP_lamp_spot_setup(const bContext *UNUSED(C), wmManipulator wwrapper->manipulator = WM_manipulator_new("MANIPULATOR_WT_arrow_3d", mgroup, NULL); wmManipulator *mpr = wwrapper->manipulator; - RNA_enum_set(mpr->ptr, "draw_options", ED_MANIPULATOR_ARROW_STYLE_INVERTED); + RNA_enum_set(mpr->ptr, "transform", ED_MANIPULATOR_ARROW_XFORM_FLAG_INVERTED); mgroup->customdata = wwrapper; diff --git a/source/blender/editors/space_view3d/view3d_manipulator_navigate.c b/source/blender/editors/space_view3d/view3d_manipulator_navigate.c index c869e23d552..22b7af48de6 100644 --- a/source/blender/editors/space_view3d/view3d_manipulator_navigate.c +++ b/source/blender/editors/space_view3d/view3d_manipulator_navigate.c @@ -51,13 +51,13 @@ * \{ */ /* Offset from screen edge. */ -#define MANIPULATOR_OFFSET_FAC 2.5 +#define MANIPULATOR_OFFSET_FAC 1.5f /* Size of main icon. */ #define MANIPULATOR_SIZE 64 /* Factor for size of smaller button. */ -#define MANIPULATOR_MINI_FAC 0.5 +#define MANIPULATOR_MINI_FAC 0.35f /* How much mini buttons offset from the primary. */ -#define MANIPULATOR_MINI_OFFSET_FAC 0.6666f +#define MANIPULATOR_MINI_OFFSET_FAC 0.42f enum { @@ -297,10 +297,21 @@ static void WIDGETGROUP_navigate_draw_prepare(const bContext *C, wmManipulatorGr navgroup->state.rv3d.is_camera = (rv3d->persp == RV3D_CAMOB); navgroup->state.rv3d.viewlock = rv3d->viewlock; + const bool show_rotate = ( + ((rv3d->viewlock & RV3D_LOCKED) == 0) && + (navgroup->state.rv3d.is_camera == false)); + const bool show_fixed_offset = navgroup->state.rv3d.is_camera; const float icon_size = MANIPULATOR_SIZE; - const float icon_offset = (icon_size / 2.0) * MANIPULATOR_OFFSET_FAC * UI_DPI_FAC; + const float icon_offset = (icon_size * 0.52f) * MANIPULATOR_OFFSET_FAC * UI_DPI_FAC; const float icon_offset_mini = icon_size * MANIPULATOR_MINI_OFFSET_FAC * UI_DPI_FAC; - const float co[2] = {rect_visible.xmax - icon_offset, rect_visible.ymax - icon_offset}; + const float co_rotate[2] = { + rect_visible.xmax - icon_offset, + rect_visible.ymax - icon_offset, + }; + const float co[2] = { + rect_visible.xmax - ((show_rotate || show_fixed_offset) ? (icon_offset * 2.0f) : (icon_offset_mini * 0.75f)), + rect_visible.ymax - icon_offset_mini * 0.75f, + }; wmManipulator *mpr; @@ -309,48 +320,36 @@ static void WIDGETGROUP_navigate_draw_prepare(const bContext *C, wmManipulatorGr WM_manipulator_set_flag(mpr, WM_MANIPULATOR_HIDDEN, true); } - if (((rv3d->viewlock & RV3D_LOCKED) == 0) && (navgroup->state.rv3d.is_camera == false)) { + /* RV3D_LOCKED or Camera: only show supported buttons. */ + if (show_rotate) { mpr = navgroup->mpr_array[MPR_ROTATE]; - mpr->matrix_basis[3][0] = co[0]; - mpr->matrix_basis[3][1] = co[1]; + mpr->matrix_basis[3][0] = co_rotate[0]; + mpr->matrix_basis[3][1] = co_rotate[1]; WM_manipulator_set_flag(mpr, WM_MANIPULATOR_HIDDEN, false); + } - mpr = navgroup->mpr_array[MPR_MOVE]; - mpr->matrix_basis[3][0] = co[0] + icon_offset_mini; - mpr->matrix_basis[3][1] = co[1] - icon_offset_mini; - WM_manipulator_set_flag(mpr, WM_MANIPULATOR_HIDDEN, false); + int icon_mini_slot = 0; - mpr = navgroup->mpr_array[MPR_ZOOM]; - mpr->matrix_basis[3][0] = co[0] - icon_offset_mini; - mpr->matrix_basis[3][1] = co[1] - icon_offset_mini; - WM_manipulator_set_flag(mpr, WM_MANIPULATOR_HIDDEN, false); + mpr = navgroup->mpr_array[MPR_ZOOM]; + mpr->matrix_basis[3][0] = co[0] - (icon_offset_mini * icon_mini_slot++); + mpr->matrix_basis[3][1] = co[1]; + WM_manipulator_set_flag(mpr, WM_MANIPULATOR_HIDDEN, false); - mpr = navgroup->mpr_array[rv3d->is_persp ? MPR_ORTHO : MPR_PERSP]; - mpr->matrix_basis[3][0] = co[0] + icon_offset_mini; - mpr->matrix_basis[3][1] = co[1] + icon_offset_mini; - WM_manipulator_set_flag(mpr, WM_MANIPULATOR_HIDDEN, false); + mpr = navgroup->mpr_array[MPR_MOVE]; + mpr->matrix_basis[3][0] = co[0] - (icon_offset_mini * icon_mini_slot++); + mpr->matrix_basis[3][1] = co[1]; + WM_manipulator_set_flag(mpr, WM_MANIPULATOR_HIDDEN, false); + if ((rv3d->viewlock & RV3D_LOCKED) == 0) { mpr = navgroup->mpr_array[MPR_CAMERA]; - mpr->matrix_basis[3][0] = co[0] - icon_offset_mini; - mpr->matrix_basis[3][1] = co[1] + icon_offset_mini; - WM_manipulator_set_flag(mpr, WM_MANIPULATOR_HIDDEN, false); - } - else { - /* RV3D_LOCKED or Camera: only show supported buttons. */ - mpr = navgroup->mpr_array[MPR_MOVE]; - mpr->matrix_basis[3][0] = co[0] + icon_offset_mini; - mpr->matrix_basis[3][1] = co[1] + icon_offset_mini; - WM_manipulator_set_flag(mpr, WM_MANIPULATOR_HIDDEN, false); - - mpr = navgroup->mpr_array[MPR_ZOOM]; - mpr->matrix_basis[3][0] = co[0]; - mpr->matrix_basis[3][1] = co[1] + icon_offset_mini; + mpr->matrix_basis[3][0] = co[0] - (icon_offset_mini * icon_mini_slot++); + mpr->matrix_basis[3][1] = co[1]; WM_manipulator_set_flag(mpr, WM_MANIPULATOR_HIDDEN, false); - if (navgroup->state.rv3d.is_camera) { - mpr = navgroup->mpr_array[MPR_CAMERA]; - mpr->matrix_basis[3][0] = co[0] - icon_offset_mini; - mpr->matrix_basis[3][1] = co[1] + icon_offset_mini; + if (navgroup->state.rv3d.is_camera == false) { + mpr = navgroup->mpr_array[rv3d->is_persp ? MPR_PERSP : MPR_ORTHO]; + mpr->matrix_basis[3][0] = co[0] - (icon_offset_mini * icon_mini_slot++); + mpr->matrix_basis[3][1] = co[1]; WM_manipulator_set_flag(mpr, WM_MANIPULATOR_HIDDEN, false); } } diff --git a/source/blender/editors/space_view3d/view3d_manipulator_ruler.c b/source/blender/editors/space_view3d/view3d_manipulator_ruler.c index cd918695f60..8178c2f5be9 100644 --- a/source/blender/editors/space_view3d/view3d_manipulator_ruler.c +++ b/source/blender/editors/space_view3d/view3d_manipulator_ruler.c @@ -382,6 +382,7 @@ static bool view3d_ruler_item_mousemove( static bool view3d_ruler_to_gpencil(bContext *C, wmManipulatorGroup *mgroup) { // RulerInfo *ruler_info = mgroup->customdata; + Main *bmain = CTX_data_main(C); Scene *scene = CTX_data_scene(C); bGPDlayer *gpl; bGPDframe *gpf; @@ -393,7 +394,7 @@ static bool view3d_ruler_to_gpencil(bContext *C, wmManipulatorGroup *mgroup) bool changed = false; if (scene->gpd == NULL) { - scene->gpd = BKE_gpencil_data_addnew("GPencil"); + scene->gpd = BKE_gpencil_data_addnew(bmain, "GPencil"); } gpl = BLI_findstring(&scene->gpd->layers, ruler_name, offsetof(bGPDlayer, info)); diff --git a/source/blender/editors/space_view3d/view3d_ops.c b/source/blender/editors/space_view3d/view3d_ops.c index b3211ed1108..267712b3339 100644 --- a/source/blender/editors/space_view3d/view3d_ops.c +++ b/source/blender/editors/space_view3d/view3d_ops.c @@ -302,7 +302,7 @@ void view3d_keymap(wmKeyConfig *keyconf) kmi = WM_keymap_add_item(keymap, "VIEW3D_OT_view_all", CKEY, KM_PRESS, KM_SHIFT, 0); RNA_boolean_set(kmi->ptr, "center", true); - WM_keymap_add_menu_pie(keymap, "VIEW3D_PIE_view", ACCENTGRAVEKEY, KM_CLICK_DRAG, 0, 0); + WM_keymap_add_menu_pie(keymap, "VIEW3D_MT_view_pie", ACCENTGRAVEKEY, KM_CLICK_DRAG, 0, 0); /* numpad view hotkeys*/ RNA_enum_set(WM_keymap_add_item(keymap, "VIEW3D_OT_viewnumpad", PAD0, KM_PRESS, 0, 0)->ptr, "type", RV3D_VIEW_CAMERA); diff --git a/source/blender/editors/space_view3d/view3d_ruler.c b/source/blender/editors/space_view3d/view3d_ruler.c index c30b72bfb95..e001ed9112b 100644 --- a/source/blender/editors/space_view3d/view3d_ruler.c +++ b/source/blender/editors/space_view3d/view3d_ruler.c @@ -297,6 +297,7 @@ static void ruler_state_set(bContext *C, RulerInfo *ruler_info, int state) #define RULER_ID "RulerData3D" static bool view3d_ruler_to_gpencil(bContext *C, RulerInfo *ruler_info) { + Main *bmain = CTX_data_main(C); Scene *scene = CTX_data_scene(C); bGPDlayer *gpl; bGPDframe *gpf; @@ -308,7 +309,7 @@ static bool view3d_ruler_to_gpencil(bContext *C, RulerInfo *ruler_info) bool changed = false; if (scene->gpd == NULL) { - scene->gpd = BKE_gpencil_data_addnew("GPencil"); + scene->gpd = BKE_gpencil_data_addnew(bmain, "GPencil"); } gpl = BLI_findstring(&scene->gpd->layers, ruler_name, offsetof(bGPDlayer, info)); diff --git a/source/blender/editors/space_view3d/view3d_select.c b/source/blender/editors/space_view3d/view3d_select.c index f4e39c7a563..b4f3be178aa 100644 --- a/source/blender/editors/space_view3d/view3d_select.c +++ b/source/blender/editors/space_view3d/view3d_select.c @@ -424,10 +424,8 @@ static void do_lasso_select_objects( for (base = vc->view_layer->object_bases.first; base; base = base->next) { if (BASE_SELECTABLE(base)) { /* use this to avoid un-needed lasso lookups */ - if ( -#ifdef USE_OBJECT_MODE_STRICT - (is_pose_mode == false) && -#endif + if (((vc->scene->toolsettings->object_flag & SCE_OBJECT_MODE_LOCK) ? + (is_pose_mode == false) : true) && ED_view3d_project_base(vc->ar, base) == V3D_PROJ_RET_OK) { if (BLI_lasso_is_point_inside(mcords, moves, base->sx, base->sy, IS_CLIPPED)) { @@ -855,6 +853,7 @@ static void view3d_lasso_select( } else { do_lasso_select_objects(vc, mcords, moves, extend, select); + DEG_id_tag_update(&vc->scene->id, DEG_TAG_SELECT_UPDATE); WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, vc->scene); } } @@ -885,6 +884,7 @@ static void view3d_lasso_select( break; } + DEG_id_tag_update(vc->obedit->data, DEG_TAG_SELECT_UPDATE); WM_event_add_notifier(C, NC_GEOM | ND_SELECT, vc->obedit->data); } FOREACH_OBJECT_IN_MODE_END; @@ -1009,7 +1009,9 @@ static int object_select_menu_exec(bContext *C, wmOperator *op) /* undo? */ if (changed) { - WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, CTX_data_scene(C)); + Scene *scene = CTX_data_scene(C); + DEG_id_tag_update(&scene->id, DEG_TAG_SELECT_UPDATE); + WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene); return OPERATOR_FINISHED; } else { @@ -1170,7 +1172,7 @@ static int selectbuffer_ret_hits_5(unsigned int *buffer, const int hits15, const /* so check three selection levels and compare */ static int mixed_bones_object_selectbuffer( ViewContext *vc, unsigned int *buffer, const int mval[2], - bool use_cycle, bool enumerate, + bool use_cycle, bool enumerate, eV3DSelectObjectFilter select_filter, bool *r_do_nearest) { rcti rect; @@ -1209,7 +1211,7 @@ static int mixed_bones_object_selectbuffer( view3d_opengl_select_cache_begin(); BLI_rcti_init_pt_radius(&rect, mval, 14); - hits15 = view3d_opengl_select(vc, buffer, MAXPICKBUF, &rect, select_mode); + hits15 = view3d_opengl_select(vc, buffer, MAXPICKBUF, &rect, select_mode, select_filter); if (hits15 == 1) { hits = selectbuffer_ret_hits_15(buffer, hits15); goto finally; @@ -1220,7 +1222,7 @@ static int mixed_bones_object_selectbuffer( offs = 4 * hits15; BLI_rcti_init_pt_radius(&rect, mval, 9); - hits9 = view3d_opengl_select(vc, buffer + offs, MAXPICKBUF - offs, &rect, select_mode); + hits9 = view3d_opengl_select(vc, buffer + offs, MAXPICKBUF - offs, &rect, select_mode, select_filter); if (hits9 == 1) { hits = selectbuffer_ret_hits_9(buffer, hits15, hits9); goto finally; @@ -1230,7 +1232,7 @@ static int mixed_bones_object_selectbuffer( offs += 4 * hits9; BLI_rcti_init_pt_radius(&rect, mval, 5); - hits5 = view3d_opengl_select(vc, buffer + offs, MAXPICKBUF - offs, &rect, select_mode); + hits5 = view3d_opengl_select(vc, buffer + offs, MAXPICKBUF - offs, &rect, select_mode, select_filter); if (hits5 == 1) { hits = selectbuffer_ret_hits_5(buffer, hits15, hits9, hits5); goto finally; @@ -1252,8 +1254,7 @@ static int mixed_bones_object_selectbuffer( finally: view3d_opengl_select_cache_end(); -#ifdef USE_OBJECT_MODE_STRICT - { + if (vc->scene->toolsettings->object_flag & SCE_OBJECT_MODE_LOCK) { const bool is_pose_mode = (vc->obact && vc->obact->mode & OB_MODE_POSE); struct { uint data[4]; @@ -1269,7 +1270,6 @@ finally: } hits = j; } -#endif return hits; } @@ -1373,7 +1373,10 @@ Base *ED_view3d_give_base_under_cursor(bContext *C, const int mval[2]) ED_view3d_viewcontext_init(C, &vc); - hits = mixed_bones_object_selectbuffer(&vc, buffer, mval, false, false, &do_nearest); + hits = mixed_bones_object_selectbuffer( + &vc, buffer, mval, + false, false, VIEW3D_SELECT_FILTER_NOP, + &do_nearest); if (hits > 0) { const bool has_bones = selectbuffer_has_bones(buffer, hits); @@ -1466,19 +1469,19 @@ static bool ed_object_select_pick( if (base == startbase) break; } } -#ifdef USE_OBJECT_MODE_STRICT - if (is_obedit == false) { - if (basact && !BKE_object_is_mode_compat(basact->object, object_mode)) { - if (object_mode == OB_MODE_OBJECT) { - struct Main *bmain = CTX_data_main(C); - ED_object_mode_generic_exit(bmain, vc.depsgraph, scene, basact->object); - } - if (!BKE_object_is_mode_compat(basact->object, object_mode)) { - basact = NULL; + if (scene->toolsettings->object_flag & SCE_OBJECT_MODE_LOCK) { + if (is_obedit == false) { + if (basact && !BKE_object_is_mode_compat(basact->object, object_mode)) { + if (object_mode == OB_MODE_OBJECT) { + struct Main *bmain = CTX_data_main(C); + ED_object_mode_generic_exit(bmain, vc.depsgraph, scene, basact->object); + } + if (!BKE_object_is_mode_compat(basact->object, object_mode)) { + basact = NULL; + } } } } -#endif } else { unsigned int buffer[MAXPICKBUF]; @@ -1487,7 +1490,13 @@ static bool ed_object_select_pick( // TIMEIT_START(select_time); /* if objects have posemode set, the bones are in the same selection buffer */ - hits = mixed_bones_object_selectbuffer(&vc, buffer, mval, true, enumerate, &do_nearest); + const eV3DSelectObjectFilter select_filter = ( + (scene->toolsettings->object_flag & SCE_OBJECT_MODE_LOCK) ? + VIEW3D_SELECT_FILTER_OBJECT_MODE_LOCK : VIEW3D_SELECT_FILTER_NOP); + hits = mixed_bones_object_selectbuffer( + &vc, buffer, mval, + true, enumerate, select_filter, + &do_nearest); // TIMEIT_END(select_time); @@ -1503,19 +1512,19 @@ static bool ed_object_select_pick( basact = mouse_select_eval_buffer(&vc, buffer, hits, startbase, has_bones, do_nearest); } -#ifdef USE_OBJECT_MODE_STRICT - if (is_obedit == false) { - if (basact && !BKE_object_is_mode_compat(basact->object, object_mode)) { - if (object_mode == OB_MODE_OBJECT) { - struct Main *bmain = CTX_data_main(C); - ED_object_mode_generic_exit(bmain, vc.depsgraph, scene, basact->object); - } - if (!BKE_object_is_mode_compat(basact->object, object_mode)) { - basact = NULL; + if (scene->toolsettings->object_flag & SCE_OBJECT_MODE_LOCK) { + if (is_obedit == false) { + if (basact && !BKE_object_is_mode_compat(basact->object, object_mode)) { + if (object_mode == OB_MODE_OBJECT) { + struct Main *bmain = CTX_data_main(C); + ED_object_mode_generic_exit(bmain, vc.depsgraph, scene, basact->object); + } + if (!BKE_object_is_mode_compat(basact->object, object_mode)) { + basact = NULL; + } } } } -#endif if (has_bones && basact) { if (basact->object->type == OB_CAMERA) { @@ -1562,6 +1571,7 @@ static bool ed_object_select_pick( retval = true; + DEG_id_tag_update(&scene->id, DEG_TAG_SELECT_UPDATE); WM_event_add_notifier(C, NC_MOVIECLIP | ND_SELECT, track); WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene); @@ -1604,19 +1614,19 @@ static bool ed_object_select_pick( } } -#ifdef USE_OBJECT_MODE_STRICT - /* Disallow switching modes, - * special exception for edit-mode - vertex-parent operator. */ - if (is_obedit == false) { - if (oldbasact && basact) { - if ((oldbasact->object->mode != basact->object->mode) && - (oldbasact->object->mode & basact->object->mode) == 0) - { - basact = NULL; + if (scene->toolsettings->object_flag & SCE_OBJECT_MODE_LOCK) { + /* Disallow switching modes, + * special exception for edit-mode - vertex-parent operator. */ + if (is_obedit == false) { + if (oldbasact && basact) { + if ((oldbasact->object->mode != basact->object->mode) && + (oldbasact->object->mode & basact->object->mode) == 0) + { + basact = NULL; + } } } } -#endif /* so, do we have something selected? */ if (basact) { @@ -1658,6 +1668,7 @@ static bool ed_object_select_pick( } } + DEG_id_tag_update(&scene->id, DEG_TAG_SELECT_UPDATE); WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene); } @@ -1966,7 +1977,9 @@ static int do_meta_box_select( unsigned int buffer[MAXPICKBUF]; int hits; - hits = view3d_opengl_select(vc, buffer, MAXPICKBUF, rect, VIEW3D_SELECT_ALL); + hits = view3d_opengl_select( + vc, buffer, MAXPICKBUF, rect, + VIEW3D_SELECT_ALL, VIEW3D_SELECT_FILTER_NOP); if (extend == false && select) BKE_mball_deselect_all(mb); @@ -2000,7 +2013,9 @@ static int do_armature_box_select( unsigned int buffer[MAXPICKBUF]; int hits; - hits = view3d_opengl_select(vc, buffer, MAXPICKBUF, rect, VIEW3D_SELECT_ALL); + hits = view3d_opengl_select( + vc, buffer, MAXPICKBUF, rect, + VIEW3D_SELECT_ALL, VIEW3D_SELECT_FILTER_NOP); uint objects_len = 0; Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(vc->view_layer, &objects_len); @@ -2148,7 +2163,12 @@ static int do_object_pose_box_select(bContext *C, ViewContext *vc, rcti *rect, b /* selection buffer now has bones potentially too, so we add MAXPICKBUF */ vbuffer = MEM_mallocN(4 * (totobj + MAXPICKELEMS) * sizeof(unsigned int), "selection buffer"); - hits = view3d_opengl_select(vc, vbuffer, 4 * (totobj + MAXPICKELEMS), rect, VIEW3D_SELECT_ALL); + const eV3DSelectObjectFilter select_filter = ( + (vc->scene->toolsettings->object_flag & SCE_OBJECT_MODE_LOCK) ? + VIEW3D_SELECT_FILTER_OBJECT_MODE_LOCK : VIEW3D_SELECT_FILTER_NOP); + hits = view3d_opengl_select( + vc, vbuffer, 4 * (totobj + MAXPICKELEMS), rect, + VIEW3D_SELECT_ALL, select_filter); /* * LOGIC NOTES (theeth): * The buffer and ListBase have the same relative order, which makes the selection @@ -2241,6 +2261,7 @@ static int do_object_pose_box_select(bContext *C, ViewContext *vc, rcti *rect, b MEM_freeN(bases); + DEG_id_tag_update(&vc->scene->id, DEG_TAG_SELECT_UPDATE); WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, vc->scene); } MEM_freeN(vbuffer); @@ -2276,6 +2297,7 @@ static int view3d_borderselect_exec(bContext *C, wmOperator *op) vc.em = BKE_editmesh_from_object(vc.obedit); ret |= do_mesh_box_select(&vc, &rect, select, extend); if (ret & OPERATOR_FINISHED) { + DEG_id_tag_update(vc.obedit->data, DEG_TAG_SELECT_UPDATE); WM_event_add_notifier(C, NC_GEOM | ND_SELECT, vc.obedit->data); } break; @@ -2283,24 +2305,28 @@ static int view3d_borderselect_exec(bContext *C, wmOperator *op) case OB_SURF: ret |= do_nurbs_box_select(&vc, &rect, select, extend); if (ret & OPERATOR_FINISHED) { + DEG_id_tag_update(vc.obedit->data, DEG_TAG_SELECT_UPDATE); WM_event_add_notifier(C, NC_GEOM | ND_SELECT, vc.obedit->data); } break; case OB_MBALL: ret |= do_meta_box_select(&vc, &rect, select, extend); if (ret & OPERATOR_FINISHED) { + DEG_id_tag_update(vc.obedit->data, DEG_TAG_SELECT_UPDATE); WM_event_add_notifier(C, NC_GEOM | ND_SELECT, vc.obedit->data); } break; case OB_ARMATURE: ret |= do_armature_box_select(&vc, &rect, select, extend); if (ret & OPERATOR_FINISHED) { + DEG_id_tag_update(&vc.obedit->id, DEG_TAG_SELECT_UPDATE); WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, vc.obedit); } break; case OB_LATTICE: ret |= do_lattice_box_select(&vc, &rect, select, extend); if (ret & OPERATOR_FINISHED) { + DEG_id_tag_update(vc.obedit->data, DEG_TAG_SELECT_UPDATE); WM_event_add_notifier(C, NC_GEOM | ND_SELECT, vc.obedit->data); } break; @@ -2403,6 +2429,7 @@ static bool ed_wpaint_vertex_select_pick( } paintvert_flush_flags(obact); + DEG_id_tag_update(obact->data, DEG_TAG_SELECT_UPDATE); WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obact->data); return true; } @@ -3004,14 +3031,17 @@ static int view3d_circle_select_exec(bContext *C, wmOperator *op) if (CTX_data_edit_object(C)) { obedit_circle_select(&vc, select, mval, (float)radius); + DEG_id_tag_update(obact->data, DEG_TAG_SELECT_UPDATE); WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obact->data); } else if (BKE_paint_select_face_test(obact)) { paint_facesel_circle_select(&vc, select, mval, (float)radius); + DEG_id_tag_update(obact->data, DEG_TAG_SELECT_UPDATE); WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obact->data); } else if (BKE_paint_select_vert_test(obact)) { paint_vertsel_circle_select(&vc, select, mval, (float)radius); + DEG_id_tag_update(obact->data, DEG_TAG_SELECT_UPDATE); WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obact->data); } else if (obact->mode & OB_MODE_POSE) { @@ -3028,6 +3058,7 @@ static int view3d_circle_select_exec(bContext *C, wmOperator *op) } else { if (object_circle_select(&vc, select, mval, (float)radius)) { + DEG_id_tag_update(&vc.scene->id, DEG_TAG_SELECT_UPDATE); WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, vc.scene); } } diff --git a/source/blender/editors/space_view3d/view3d_toolbar.c b/source/blender/editors/space_view3d/view3d_toolbar.c index 8ea33927c4d..acceb40beaa 100644 --- a/source/blender/editors/space_view3d/view3d_toolbar.c +++ b/source/blender/editors/space_view3d/view3d_toolbar.c @@ -190,7 +190,7 @@ static int view3d_toolshelf_toggle_exec(bContext *C, wmOperator *UNUSED(op)) void VIEW3D_OT_toolshelf(wmOperatorType *ot) { - ot->name = "Tool Shelf"; + ot->name = "Toggle Toolbar"; ot->description = "Toggles tool shelf display"; ot->idname = "VIEW3D_OT_toolshelf"; diff --git a/source/blender/editors/space_view3d/view3d_view.c b/source/blender/editors/space_view3d/view3d_view.c index 73b9a67ac56..abb8c688e05 100644 --- a/source/blender/editors/space_view3d/view3d_view.c +++ b/source/blender/editors/space_view3d/view3d_view.c @@ -896,6 +896,13 @@ static bool drw_select_loop_pass(eDRWSelectStage stage, void *user_data) } #endif /* WITH_OPENGL_LEGACY */ +/** Implement #VIEW3D_SELECT_FILTER_OBJECT_MODE_LOCK. */ +static bool drw_select_filter_object_mode_lock(Object *ob, void *user_data) +{ + const Object *obact = user_data; + return BKE_object_is_mode_compat(ob, obact->mode); +} + /** * \warning be sure to account for a negative return value * This is an error, "Too many objects in select buffer" @@ -905,7 +912,7 @@ static bool drw_select_loop_pass(eDRWSelectStage stage, void *user_data) */ int view3d_opengl_select( ViewContext *vc, unsigned int *buffer, unsigned int bufsize, const rcti *input, - eV3DSelectMode select_mode) + eV3DSelectMode select_mode, eV3DSelectObjectFilter select_filter) { struct bThemeState theme_state; Depsgraph *depsgraph = vc->depsgraph; @@ -953,6 +960,25 @@ int view3d_opengl_select( } } + struct { + DRW_ObjectFilterFn fn; + void *user_data; + } object_filter = {NULL, NULL}; + switch (select_filter) { + case VIEW3D_SELECT_FILTER_OBJECT_MODE_LOCK: + { + Object *obact = OBACT(vc->view_layer); + if (obact && obact->mode != OB_MODE_OBJECT) { + object_filter.fn = drw_select_filter_object_mode_lock; + object_filter.user_data = obact; + } + break; + } + case VIEW3D_SELECT_FILTER_NOP: + break; + + } + /* Tools may request depth outside of regular drawing code. */ UI_Theme_Store(&theme_state); UI_SetTheme(SPACE_VIEW3D, RGN_TYPE_WINDOW); @@ -1014,7 +1040,8 @@ int view3d_opengl_select( DRW_draw_select_loop( depsgraph, ar, v3d, use_obedit_skip, use_nearest, &rect, - drw_select_loop_pass, &drw_select_loop_user_data); + drw_select_loop_pass, &drw_select_loop_user_data, + object_filter.fn, object_filter.user_data); hits = drw_select_loop_user_data.hits; } #endif /* WITH_OPENGL_LEGACY */ diff --git a/source/blender/editors/transform/transform.h b/source/blender/editors/transform/transform.h index c2548fe497f..d72d311e0f6 100644 --- a/source/blender/editors/transform/transform.h +++ b/source/blender/editors/transform/transform.h @@ -65,6 +65,7 @@ struct wmEvent; struct wmTimer; struct ARegion; struct ReportList; +struct RNG; struct EditBone; struct RenderEngineType; struct SnapObjectContext; @@ -536,6 +537,9 @@ typedef struct TransInfo { void *draw_handle_pixel; void *draw_handle_cursor; + /** Currently only used for random curve of proportional editing. */ + struct RNG *rng; + /** Typically for mode settings. */ TransCustomDataContainer custom; } TransInfo; diff --git a/source/blender/editors/transform/transform_conversions.c b/source/blender/editors/transform/transform_conversions.c index 6c608a0b5e4..8462004c549 100644 --- a/source/blender/editors/transform/transform_conversions.c +++ b/source/blender/editors/transform/transform_conversions.c @@ -1255,7 +1255,7 @@ static void createTransArmatureVerts(TransInfo *t) bool mirror = ((arm->flag & ARM_MIRROR_EDIT) != 0); int total_mirrored = 0, i; int oldtot; - BoneInitData *bid; + BoneInitData *bid = NULL; tc->data_len = 0; for (ebo = edbo->first; ebo; ebo = ebo->next) { @@ -2120,7 +2120,6 @@ static void createTransParticleVerts(bContext *C, TransInfo *t) void flushTransParticles(TransInfo *t) { FOREACH_TRANS_DATA_CONTAINER (t, tc) { - Scene *scene = t->scene; ViewLayer *view_layer = t->view_layer; Object *ob = OBACT(view_layer); @@ -8633,6 +8632,10 @@ void createTransData(bContext *C, TransInfo *t) createTransPaintCurveVerts(C, t); countAndCleanTransDataContainer(t); } + /* Mark as initialized if above checks fail. */ + if (t->data_len_all == -1) { + t->data_len_all = 0; + } } else { createTransObject(C, t); diff --git a/source/blender/editors/transform/transform_generics.c b/source/blender/editors/transform/transform_generics.c index 8bef63dba1a..053647cbfea 100644 --- a/source/blender/editors/transform/transform_generics.c +++ b/source/blender/editors/transform/transform_generics.c @@ -58,6 +58,8 @@ #include "BLI_rand.h" #include "BLI_utildefines.h" +#include "PIL_time.h" + #include "BLT_translation.h" #include "RNA_access.h" @@ -74,6 +76,7 @@ #include "BKE_fcurve.h" #include "BKE_lattice.h" #include "BKE_library.h" +#include "BKE_main.h" #include "BKE_nla.h" #include "BKE_context.h" #include "BKE_paint.h" @@ -1695,6 +1698,10 @@ void postTrans(bContext *C, TransInfo *t) MEM_freeN(t->mouse.data); } + if (t->rng != NULL) { + BLI_rng_free(t->rng); + } + freeSnapping(t); } @@ -2163,7 +2170,12 @@ void calculatePropRatio(TransInfo *t) td->factor = sqrtf(2 * dist - dist * dist); break; case PROP_RANDOM: - td->factor = BLI_frand() * dist; + if (t->rng == NULL) { + /* Lazy initialization. */ + uint rng_seed = (uint)(PIL_check_seconds_timer_i() & UINT_MAX); + t->rng = BLI_rng_new(rng_seed); + } + td->factor = BLI_rng_get_float(t->rng) * dist; break; case PROP_INVSQUARE: td->factor = dist * (2.0f - dist); diff --git a/source/blender/editors/transform/transform_input.c b/source/blender/editors/transform/transform_input.c index 270ef08be50..5b5c4902377 100644 --- a/source/blender/editors/transform/transform_input.c +++ b/source/blender/editors/transform/transform_input.c @@ -375,8 +375,11 @@ void initMouseInputMode(TransInfo *t, MouseInput *mi, MouseInputMode mode) MEM_freeN(mi_data_prev); } - /* bootstrap mouse input with initial values */ - applyMouseInput(t, mi, mi->imval, t->values); + /* Don't write into the values when non-modal because they are already set from operator redo values. */ + if (t->flag & T_MODAL) { + /* bootstrap mouse input with initial values */ + applyMouseInput(t, mi, mi->imval, t->values); + } } void setInputPostFct(MouseInput *mi, void (*post)(struct TransInfo *t, float values[3])) diff --git a/source/blender/editors/transform/transform_manipulator_3d.c b/source/blender/editors/transform/transform_manipulator_3d.c index b6782470f96..75da0fc2d23 100644 --- a/source/blender/editors/transform/transform_manipulator_3d.c +++ b/source/blender/editors/transform/transform_manipulator_3d.c @@ -107,8 +107,15 @@ #define MAN_SCALE_C (MAN_SCALE_X | MAN_SCALE_Y | MAN_SCALE_Z) /* threshold for testing view aligned manipulator axis */ -#define TW_AXIS_DOT_MIN 0.02f -#define TW_AXIS_DOT_MAX 0.1f +struct { + float min, max; +} g_tw_axis_range[2] = { + /* Regular range */ + {0.02f, 0.1f}, + /* Use a different range because we flip the dot product, + * also the view aligned planes are harder to see so hiding early is preferred. */ + {0.175f, 0.25f}, +}; /* axes as index */ enum { @@ -247,16 +254,18 @@ static bool manipulator_is_axis_visible( const RegionView3D *rv3d, const int twtype, const float idot[3], const int axis_type, const int axis_idx) { - bool is_plane = false; - const uint aidx_norm = manipulator_orientation_axis(axis_idx, &is_plane); - /* don't draw axis perpendicular to the view */ - if (aidx_norm < 3) { - float idot_axis = idot[aidx_norm]; - if (is_plane) { - idot_axis = 1.0f - idot_axis; - } - if (idot_axis < TW_AXIS_DOT_MIN) { - return false; + if ((axis_idx >= MAN_AXIS_RANGE_ROT_START && axis_idx < MAN_AXIS_RANGE_ROT_END) == 0) { + bool is_plane = false; + const uint aidx_norm = manipulator_orientation_axis(axis_idx, &is_plane); + /* don't draw axis perpendicular to the view */ + if (aidx_norm < 3) { + float idot_axis = idot[aidx_norm]; + if (is_plane) { + idot_axis = 1.0f - idot_axis; + } + if (idot_axis < g_tw_axis_range[is_plane].min) { + return false; + } } } @@ -333,22 +342,31 @@ static void manipulator_get_axis_color( const float alpha_hi = 1.0f; float alpha_fac; - bool is_plane = false; - const int axis_idx_norm = manipulator_orientation_axis(axis_idx, &is_plane); - /* get alpha fac based on axis angle, to fade axis out when hiding it because it points towards view */ - if (axis_idx_norm < 3) { - float idot_axis = idot[axis_idx_norm]; - if (is_plane) { - idot_axis = 1.0f - idot_axis; - } - alpha_fac = (idot_axis > TW_AXIS_DOT_MAX) ? - 1.0f : (idot_axis < TW_AXIS_DOT_MIN) ? - 0.0f : ((idot_axis - TW_AXIS_DOT_MIN) / (TW_AXIS_DOT_MAX - TW_AXIS_DOT_MIN)); - } - else { + if (axis_idx >= MAN_AXIS_RANGE_ROT_START && axis_idx < MAN_AXIS_RANGE_ROT_END) { + /* Never fade rotation rings. */ /* trackball rotation axis is a special case, we only draw a slight overlay */ alpha_fac = (axis_idx == MAN_AXIS_ROT_T) ? 0.1f : 1.0f; } + else { + bool is_plane = false; + const int axis_idx_norm = manipulator_orientation_axis(axis_idx, &is_plane); + /* get alpha fac based on axis angle, to fade axis out when hiding it because it points towards view */ + if (axis_idx_norm < 3) { + const float idot_min = g_tw_axis_range[is_plane].min; + const float idot_max = g_tw_axis_range[is_plane].max; + float idot_axis = idot[axis_idx_norm]; + if (is_plane) { + idot_axis = 1.0f - idot_axis; + } + alpha_fac = ( + (idot_axis > idot_max) ? + 1.0f : (idot_axis < idot_min) ? + 0.0f : ((idot_axis - idot_min) / (idot_max - idot_min))); + } + else { + alpha_fac = 1.0f; + } + } switch (axis_idx) { case MAN_AXIS_TRANS_X: @@ -1238,9 +1256,14 @@ static ManipulatorGroup *manipulatorgroup_init(wmManipulatorGroup *mgroup) * Custom handler for manipulator widgets */ static int manipulator_modal( - bContext *C, wmManipulator *widget, const wmEvent *UNUSED(event), + bContext *C, wmManipulator *widget, const wmEvent *event, eWM_ManipulatorTweak UNUSED(tweak_flag)) { + /* Avoid unnecessary updates, partially address: T55458. */ + if (ELEM(event->type, TIMER, INBETWEEN_MOUSEMOVE)) { + return OPERATOR_RUNNING_MODAL; + } + const ScrArea *sa = CTX_wm_area(C); ARegion *ar = CTX_wm_region(C); View3D *v3d = sa->spacedata.first; @@ -1315,6 +1338,14 @@ static void WIDGETGROUP_manipulator_setup(const bContext *C, wmManipulatorGroup case MAN_AXIS_SCALE_X: case MAN_AXIS_SCALE_Y: case MAN_AXIS_SCALE_Z: + if (axis_idx >= MAN_AXIS_RANGE_TRANS_START && axis_idx < MAN_AXIS_RANGE_TRANS_END) { + int draw_options = 0; + if ((man->twtype & (V3D_MANIP_ROTATE | V3D_MANIP_SCALE)) == 0) { + draw_options |= ED_MANIPULATOR_ARROW_DRAW_FLAG_STEM; + } + RNA_enum_set(axis->ptr, "draw_options", draw_options); + } + WM_manipulator_set_line_width(axis, MANIPULATOR_AXIS_LINE_WIDTH); break; case MAN_AXIS_ROT_X: @@ -1348,6 +1379,7 @@ static void WIDGETGROUP_manipulator_setup(const bContext *C, wmManipulatorGroup } else if (axis_idx == MAN_AXIS_ROT_C) { WM_manipulator_set_flag(axis, WM_MANIPULATOR_DRAW_VALUE, true); + WM_manipulator_set_scale(axis, 1.2f); } else { WM_manipulator_set_scale(axis, 0.2f); @@ -1447,6 +1479,13 @@ static void WIDGETGROUP_manipulator_refresh(const bContext *C, wmManipulatorGrou WM_manipulator_set_matrix_rotation_from_z_axis(axis, rv3d->twmat[aidx_norm]); RNA_float_set(axis->ptr, "length", len); + + if (axis_idx >= MAN_AXIS_RANGE_TRANS_START && axis_idx < MAN_AXIS_RANGE_TRANS_END) { + if (man->twtype & V3D_MANIP_ROTATE) { + /* Avoid rotate and translate arrows overlap. */ + start_co[2] += 0.215f; + } + } WM_manipulator_set_matrix_offset_location(axis, start_co); WM_manipulator_set_flag(axis, WM_MANIPULATOR_DRAW_OFFSET_SCALE, true); break; diff --git a/source/blender/editors/transform/transform_ops.c b/source/blender/editors/transform/transform_ops.c index 18d30db7a21..d98e3e3261a 100644 --- a/source/blender/editors/transform/transform_ops.c +++ b/source/blender/editors/transform/transform_ops.c @@ -45,6 +45,7 @@ #include "RNA_enum_types.h" #include "WM_api.h" +#include "WM_message.h" #include "WM_types.h" #include "UI_interface.h" @@ -170,6 +171,9 @@ static int select_orientation_exec(bContext *C, wmOperator *op) WM_event_add_notifier(C, NC_SCENE | ND_TOOLSETTINGS, NULL); + struct wmMsgBus *mbus = CTX_wm_message_bus(C); + WM_msg_publish_rna_prop(mbus, &scene->id, scene, Scene, transform_orientation); + return OPERATOR_FINISHED; } @@ -537,7 +541,7 @@ void Transform_Properties(struct wmOperatorType *ot, int flags) if (flags & P_PROPORTIONAL) { RNA_def_enum(ot->srna, "proportional", rna_enum_proportional_editing_items, 0, "Proportional Editing", ""); prop = RNA_def_enum(ot->srna, "proportional_edit_falloff", rna_enum_proportional_falloff_items, 0, - "Proportional Editing Falloff", "Falloff type for proportional editing mode"); + "Proportional Falloff", "Falloff type for proportional editing mode"); RNA_def_property_translation_context(prop, BLT_I18NCONTEXT_ID_CURVE); /* Abusing id_curve :/ */ RNA_def_float(ot->srna, "proportional_size", 1, T_PROP_SIZE_MIN, T_PROP_SIZE_MAX, "Proportional Size", "", 0.001f, 100.0f); @@ -563,17 +567,20 @@ void Transform_Properties(struct wmOperatorType *ot, int flags) } if (flags & P_GPENCIL_EDIT) { - RNA_def_boolean(ot->srna, "gpencil_strokes", 0, "Edit Grease Pencil", "Edit selected Grease Pencil strokes"); + prop = RNA_def_boolean(ot->srna, "gpencil_strokes", 0, "Edit Grease Pencil", "Edit selected Grease Pencil strokes"); + RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE); } if (flags & P_CURSOR_EDIT) { - RNA_def_boolean(ot->srna, "cursor_transform", 0, "Transform Cursor", ""); + prop = RNA_def_boolean(ot->srna, "cursor_transform", 0, "Transform Cursor", ""); + RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE); } if ((flags & P_OPTIONS) && !(flags & P_NO_TEXSPACE)) { - RNA_def_boolean(ot->srna, "texture_space", 0, "Edit Texture Space", "Edit Object data texture space"); + prop = RNA_def_boolean(ot->srna, "texture_space", 0, "Edit Texture Space", "Edit Object data texture space"); + RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE); prop = RNA_def_boolean(ot->srna, "remove_on_cancel", 0, "Remove on Cancel", "Remove elements on cancel"); - RNA_def_property_flag(prop, PROP_HIDDEN); + RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE); } if (flags & P_CORRECT_UV) { diff --git a/source/blender/editors/undo/ed_undo.c b/source/blender/editors/undo/ed_undo.c index d2ac346df10..478e004743d 100644 --- a/source/blender/editors/undo/ed_undo.c +++ b/source/blender/editors/undo/ed_undo.c @@ -148,15 +148,10 @@ static int ed_undo_step(bContext *C, int step, const char *undoname) void ED_undo_grouped_push(bContext *C, const char *str) { /* do nothing if previous undo task is the same as this one (or from the same undo group) */ - { - wmWindowManager *wm = CTX_wm_manager(C); - if (wm->undo_stack->steps.last) { - const UndoStep *us = wm->undo_stack->steps.last; - if (STREQ(str, us->name)) { - return; - } - } - + wmWindowManager *wm = CTX_wm_manager(C); + const UndoStep *us = wm->undo_stack->step_active; + if (us && STREQ(str, us->name)) { + BKE_undosys_stack_clear_active(wm->undo_stack); } /* push as usual */ @@ -210,7 +205,7 @@ bool ED_undo_is_valid(const bContext *C, const char *undoname) */ UndoStack *ED_undo_stack_get(void) { - wmWindowManager *wm = G.main->wm.first; + wmWindowManager *wm = G_MAIN->wm.first; return wm->undo_stack; } @@ -307,36 +302,6 @@ void ED_OT_undo_redo(wmOperatorType *ot) /** \} */ -struct OperatorRepeatContextHandle { - ScrArea *restore_area; - ARegion *restore_region; -}; - -/** - * Resets the context to the state \a op was executed in (or at least, was in when registering). - * #ED_operator_repeat_reset_context should be called when done repeating! - */ -const OperatorRepeatContextHandle *ED_operator_repeat_prepare_context(bContext *C, wmOperator *op) -{ - static OperatorRepeatContextHandle context_info; - - context_info.restore_area = CTX_wm_area(C); - context_info.restore_region = CTX_wm_region(C); - - CTX_wm_area_set(C, op->execution_area); - CTX_wm_region_set(C, op->execution_region); - - return &context_info; -} -/** - * Resets context to the old state from before #ED_operator_repeat_prepare_context was called. - */ -void ED_operator_repeat_reset_context(bContext *C, const OperatorRepeatContextHandle *context_info) -{ - CTX_wm_area_set(C, context_info->restore_area); - CTX_wm_region_set(C, context_info->restore_region); -} - /* -------------------------------------------------------------------- */ /** \name Operator Repeat * \{ */ @@ -351,8 +316,13 @@ int ED_undo_operator_repeat(bContext *C, wmOperator *op) wmWindowManager *wm = CTX_wm_manager(C); struct Scene *scene = CTX_data_scene(C); - const OperatorRepeatContextHandle *context_info; - context_info = ED_operator_repeat_prepare_context(C, op); + /* keep in sync with logic in view3d_panel_operator_redo() */ + ARegion *ar_orig = CTX_wm_region(C); + ARegion *ar_win = BKE_area_find_region_active_win(CTX_wm_area(C)); + + if (ar_win) { + CTX_wm_region_set(C, ar_win); + } if ((WM_operator_repeat_check(C, op)) && (WM_operator_poll(C, op->type)) && @@ -398,7 +368,8 @@ int ED_undo_operator_repeat(bContext *C, wmOperator *op) } } - ED_operator_repeat_reset_context(C, context_info); + /* set region back */ + CTX_wm_region_set(C, ar_orig); } else { CLOG_WARN(&LOG, "called with NULL 'op'"); @@ -440,7 +411,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_RESTRICT_VIEW_OFF; + item_tmp.icon = ICON_HIDE_OFF; } else { item_tmp.icon = ICON_NONE; diff --git a/source/blender/editors/util/CMakeLists.txt b/source/blender/editors/util/CMakeLists.txt index 24cfde90804..fa21facefc2 100644 --- a/source/blender/editors/util/CMakeLists.txt +++ b/source/blender/editors/util/CMakeLists.txt @@ -87,6 +87,7 @@ set(SRC ../include/ED_transform_snap_object_context.h ../include/ED_transverts.h ../include/ED_types.h + ../include/ED_undo.h ../include/ED_util.h ../include/ED_uvedit.h ../include/ED_view3d.h diff --git a/source/blender/editors/util/ed_util.c b/source/blender/editors/util/ed_util.c index a829f8c1144..549b9b7de77 100644 --- a/source/blender/editors/util/ed_util.c +++ b/source/blender/editors/util/ed_util.c @@ -145,8 +145,8 @@ void ED_editors_exit(bContext *C) return; /* frees all editmode undos */ - if (G.main->wm.first) { - wmWindowManager *wm = G.main->wm.first; + if (G_MAIN->wm.first) { + wmWindowManager *wm = G_MAIN->wm.first; /* normally we don't check for NULL undo stack, do here since it may run in different context. */ if (wm->undo_stack) { BKE_undosys_stack_destroy(wm->undo_stack); diff --git a/source/blender/editors/uvedit/uvedit_ops.c b/source/blender/editors/uvedit/uvedit_ops.c index 45a6ccfe28b..e3d2537c040 100644 --- a/source/blender/editors/uvedit/uvedit_ops.c +++ b/source/blender/editors/uvedit/uvedit_ops.c @@ -1362,7 +1362,7 @@ static int uv_select_more_less(bContext *C, const bool select) else { EDBM_select_less(em, true); } - + DEG_id_tag_update(obedit->data, DEG_TAG_SELECT_UPDATE); WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data); return OPERATOR_FINISHED; } @@ -1434,6 +1434,7 @@ static int uv_select_more_less(bContext *C, const bool select) uv_select_flush_from_tag_loop(sima, scene, obedit, select); } + DEG_id_tag_update(obedit->data, DEG_TAG_SELECT_UPDATE); WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data); return OPERATOR_FINISHED; @@ -2058,6 +2059,7 @@ static int uv_select_all_exec(bContext *C, wmOperator *op) for (uint ob_index = 0; ob_index < objects_len; ob_index++) { Object *obedit = objects[ob_index]; + DEG_id_tag_update(obedit->data, DEG_TAG_SELECT_UPDATE); WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data); } @@ -2371,7 +2373,7 @@ static int uv_mouse_select_multi( #endif } - DEG_id_tag_update(obedit->data, 0); + DEG_id_tag_update(obedit->data, DEG_TAG_COPY_ON_WRITE | DEG_TAG_SELECT_UPDATE); WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data); return OPERATOR_PASS_THROUGH | OPERATOR_FINISHED; @@ -2547,7 +2549,7 @@ static int uv_select_linked_internal(bContext *C, wmOperator *op, const wmEvent for (uint ob_index = 0; ob_index < objects_len; ob_index++) { Object *obedit = objects[ob_index]; - DEG_id_tag_update(obedit->data, 0); + DEG_id_tag_update(obedit->data, DEG_TAG_COPY_ON_WRITE | DEG_TAG_SELECT_UPDATE); WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data); } @@ -3052,6 +3054,7 @@ static int uv_border_select_exec(bContext *C, wmOperator *op) uv_select_sync_flush(ts, em, select); if (ts->uv_flag & UV_SYNC_SELECTION) { + DEG_id_tag_update(obedit->data, DEG_TAG_SELECT_UPDATE); WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data); } } @@ -3181,6 +3184,7 @@ static int uv_circle_select_exec(bContext *C, wmOperator *op) if (changed) { uv_select_sync_flush(ts, em, select); + DEG_id_tag_update(obedit->data, DEG_TAG_SELECT_UPDATE); WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data); } @@ -3314,6 +3318,7 @@ static bool do_lasso_select_mesh_uv(bContext *C, const int mcords[][2], short mo uv_select_sync_flush(scene->toolsettings, em, select); if (ts->uv_flag & UV_SYNC_SELECTION) { + DEG_id_tag_update(obedit->data, DEG_TAG_SELECT_UPDATE); WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data); } } @@ -3746,6 +3751,7 @@ static int uv_select_pinned_exec(bContext *C, wmOperator *UNUSED(op)) } } + DEG_id_tag_update(obedit->data, DEG_TAG_SELECT_UPDATE); WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data); return OPERATOR_FINISHED; @@ -3812,6 +3818,8 @@ static int uv_hide_exec(bContext *C, wmOperator *op) if (ts->uv_flag & UV_SYNC_SELECTION) { EDBM_mesh_hide(em, swap); + + DEG_id_tag_update(obedit->data, DEG_TAG_SELECT_UPDATE); WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data); return OPERATOR_FINISHED; @@ -3880,6 +3888,8 @@ static int uv_hide_exec(bContext *C, wmOperator *op) EDBM_selectmode_flush_ex(em, SCE_SELECT_VERTEX | SCE_SELECT_EDGE); BM_select_history_validate(em->bm); + + DEG_id_tag_update(obedit->data, DEG_TAG_SELECT_UPDATE); WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data); return OPERATOR_FINISHED; @@ -3933,6 +3943,7 @@ static int uv_reveal_exec(bContext *C, wmOperator *op) /* call the mesh function if we are in mesh sync sel */ if (ts->uv_flag & UV_SYNC_SELECTION) { EDBM_mesh_reveal(em, select); + DEG_id_tag_update(obedit->data, DEG_TAG_SELECT_UPDATE); WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data); return OPERATOR_FINISHED; @@ -4022,6 +4033,7 @@ static int uv_reveal_exec(bContext *C, wmOperator *op) /* re-select tagged faces */ BM_mesh_elem_hflag_enable_test(em->bm, BM_FACE, BM_ELEM_SELECT, true, false, BM_ELEM_TAG); + DEG_id_tag_update(obedit->data, DEG_TAG_SELECT_UPDATE); WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data); return OPERATOR_FINISHED; |