diff options
Diffstat (limited to 'source/blender/editors')
457 files changed, 11445 insertions, 7169 deletions
diff --git a/source/blender/editors/animation/CMakeLists.txt b/source/blender/editors/animation/CMakeLists.txt index 6adfab6e921..a72b2874f95 100644 --- a/source/blender/editors/animation/CMakeLists.txt +++ b/source/blender/editors/animation/CMakeLists.txt @@ -12,7 +12,6 @@ set(INC ../../sequencer ../../windowmanager ../../../../intern/clog - ../../../../intern/glew-mx ../../../../intern/guardedalloc # RNA_prototypes.h ${CMAKE_BINARY_DIR}/source/blender/makesrna diff --git a/source/blender/editors/animation/anim_channels_defines.c b/source/blender/editors/animation/anim_channels_defines.c index f665ec27b07..8edeea49cbb 100644 --- a/source/blender/editors/animation/anim_channels_defines.c +++ b/source/blender/editors/animation/anim_channels_defines.c @@ -157,7 +157,7 @@ static void acf_generic_dataexpand_backdrop(bAnimContext *ac, /* set backdrop drawing color */ acf->get_backdrop_color(ac, ale, color); - immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); immUniformColor3fv(color); /* no rounded corner - just rectangular box */ @@ -246,7 +246,7 @@ static void acf_generic_channel_backdrop(bAnimContext *ac, /* set backdrop drawing color */ acf->get_backdrop_color(ac, ale, color); - immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); immUniformColor3fv(color); /* no rounded corners - just rectangular box */ @@ -4449,7 +4449,7 @@ void ANIM_channel_draw( uint pos = GPU_vertformat_attr_add( immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); - immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); /* F-Curve channels need to have a special 'color code' box drawn, * which is colored with whatever color the curve has stored. @@ -4513,7 +4513,7 @@ void ANIM_channel_draw( uint pos = GPU_vertformat_attr_add( immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); - immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); /* FIXME: replace hardcoded color here, and check on extents! */ immUniformColor3f(1.0f, 0.0f, 0.0f); @@ -4549,7 +4549,7 @@ void ANIM_channel_draw( float color[3]; uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); - immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); /* get and set backdrop color */ acf->get_backdrop_color(ac, ale, color); @@ -5353,8 +5353,8 @@ void ANIM_channel_draw_widgets(const bContext *C, * and wouldn't be able to auto-keyframe. * - Slider should start before the toggles (if they're visible) * to keep a clean line down the side. - * - Sliders are always drawn in Shapekey mode now. Prior to this - * the SACTION_SLIDERS flag would be set when changing into Shapekey mode. + * - Sliders are always drawn in Shape-key mode now. Prior to this + * the SACTION_SLIDERS flag would be set when changing into shape-key mode. */ if (((draw_sliders) && ELEM(ale->type, ANIMTYPE_FCURVE, diff --git a/source/blender/editors/animation/anim_channels_edit.c b/source/blender/editors/animation/anim_channels_edit.c index 06a62b7a9de..ea631da27af 100644 --- a/source/blender/editors/animation/anim_channels_edit.c +++ b/source/blender/editors/animation/anim_channels_edit.c @@ -31,6 +31,7 @@ #include "BKE_fcurve.h" #include "BKE_global.h" #include "BKE_gpencil.h" +#include "BKE_layer.h" #include "BKE_lib_id.h" #include "BKE_mask.h" #include "BKE_nla.h" @@ -2953,6 +2954,7 @@ static int click_select_channel_object(bContext *C, bAnimListElem *ale, const short /* eEditKeyframes_Select or -1 */ selectmode) { + Scene *scene = ac->scene; ViewLayer *view_layer = ac->view_layer; Base *base = (Base *)ale->data; Object *ob = base->object; @@ -2971,11 +2973,10 @@ static int click_select_channel_object(bContext *C, } } else { - Base *b; - /* deselect all */ + BKE_view_layer_synced_ensure(scene, view_layer); /* TODO: should this deselect all other types of channels too? */ - for (b = view_layer->object_bases.first; b; b = b->next) { + LISTBASE_FOREACH (Base *, b, BKE_view_layer_object_bases_get(view_layer)) { ED_object_base_select(b, BA_DESELECT); if (b->object->adt) { b->object->adt->flag &= ~(ADT_UI_SELECTED | ADT_UI_ACTIVE); diff --git a/source/blender/editors/animation/anim_draw.c b/source/blender/editors/animation/anim_draw.c index e352b4e26fe..06a0077df9b 100644 --- a/source/blender/editors/animation/anim_draw.c +++ b/source/blender/editors/animation/anim_draw.c @@ -60,7 +60,7 @@ void ANIM_draw_cfra(const bContext *C, View2D *v2d, short flag) GPUVertFormat *format = immVertexFormat(); uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); - immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); /* Draw a light green line to indicate current frame */ immUniformThemeColor(TH_CFRAME); @@ -87,7 +87,7 @@ void ANIM_draw_previewrange(const bContext *C, View2D *v2d, int end_frame_width) GPUVertFormat *format = immVertexFormat(); uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); - immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); immUniformThemeColorShadeAlpha(TH_ANIM_PREVIEW_RANGE, -25, -30); /* XXX: Fix this hardcoded color (anim_active) */ // immUniformColor4f(0.8f, 0.44f, 0.1f, 0.2f); @@ -118,7 +118,7 @@ void ANIM_draw_framerange(Scene *scene, View2D *v2d) GPUVertFormat *format = immVertexFormat(); uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); - immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); immUniformThemeColorShadeAlpha(TH_BACK, -25, -100); if (scene->r.sfra < scene->r.efra) { @@ -193,7 +193,7 @@ void ANIM_draw_action_framerange( GPU_blend(GPU_BLEND_NONE); /* Thin lines where the actual frames are. */ - immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); immUniformThemeColorShade(TH_BACK, -60); GPU_line_width(1.0f); diff --git a/source/blender/editors/animation/anim_filter.c b/source/blender/editors/animation/anim_filter.c index d9eeed94868..5b4d436b0e0 100644 --- a/source/blender/editors/animation/anim_filter.c +++ b/source/blender/editors/animation/anim_filter.c @@ -118,11 +118,13 @@ static void animedit_get_yscale_factor(bAnimContext *ac) /* NOTE: there's a similar function in key.c #BKE_key_from_object. */ static Key *actedit_get_shapekeys(bAnimContext *ac) { + Scene *scene = ac->scene; ViewLayer *view_layer = ac->view_layer; Object *ob; Key *key; - ob = OBACT(view_layer); + BKE_view_layer_synced_ensure(scene, view_layer); + ob = BKE_view_layer_active_object_get(view_layer); if (ob == NULL) { return NULL; } @@ -393,12 +395,13 @@ bool ANIM_animdata_get_context(const bContext *C, bAnimContext *ac) /* get useful default context settings from context */ ac->bmain = bmain; ac->scene = scene; + ac->view_layer = CTX_data_view_layer(C); if (scene) { ac->markers = ED_context_get_markers(C); + BKE_view_layer_synced_ensure(ac->scene, ac->view_layer); } - ac->view_layer = CTX_data_view_layer(C); ac->depsgraph = CTX_data_depsgraph_pointer(C); - ac->obact = (ac->view_layer->basact) ? ac->view_layer->basact->object : NULL; + ac->obact = BKE_view_layer_active_object_get(ac->view_layer); ac->area = area; ac->region = region; ac->sl = sl; @@ -1846,8 +1849,8 @@ static size_t animdata_filter_gpencil(bAnimContext *ac, bDopeSheet *ads = ac->ads; size_t items = 0; + Scene *scene = ac->scene; ViewLayer *view_layer = (ViewLayer *)ac->view_layer; - Base *base; /* Include all annotation datablocks. */ if (((ads->filterflag & ADS_FILTER_ONLYSEL) == 0) || @@ -1859,7 +1862,8 @@ static size_t animdata_filter_gpencil(bAnimContext *ac, } } /* Objects in the scene */ - for (base = view_layer->object_bases.first; base; base = base->next) { + BKE_view_layer_synced_ensure(scene, view_layer); + LISTBASE_FOREACH (Base *, base, BKE_view_layer_object_bases_get(view_layer)) { /* Only consider this object if it has got some GP data (saving on all the other tests) */ if (base->object && (base->object->type == OB_GPENCIL)) { Object *ob = base->object; @@ -1876,8 +1880,8 @@ static size_t animdata_filter_gpencil(bAnimContext *ac, if ((filter_mode & ANIMFILTER_DATA_VISIBLE) && !(ads->filterflag & ADS_FILTER_INCL_HIDDEN)) { /* Layer visibility - we check both object and base, * since these may not be in sync yet. */ - if ((base->flag & BASE_VISIBLE_DEPSGRAPH) == 0 || - (base->flag & BASE_VISIBLE_VIEWLAYER) == 0) { + if ((base->flag & BASE_ENABLED_AND_MAYBE_VISIBLE_IN_VIEWPORT) == 0 || + (base->flag & BASE_ENABLED_AND_VISIBLE_IN_DEFAULT_VIEWPORT) == 0) { continue; } @@ -3089,7 +3093,8 @@ static bool animdata_filter_base_is_ok(bDopeSheet *ads, */ if ((filter_mode & ANIMFILTER_DATA_VISIBLE) && !(ads->filterflag & ADS_FILTER_INCL_HIDDEN)) { /* layer visibility - we check both object and base, since these may not be in sync yet */ - if ((base->flag & BASE_VISIBLE_DEPSGRAPH) == 0 || (base->flag & BASE_VISIBLE_VIEWLAYER) == 0) { + if ((base->flag & BASE_ENABLED_AND_MAYBE_VISIBLE_IN_VIEWPORT) == 0 || + (base->flag & BASE_ENABLED_AND_VISIBLE_IN_DEFAULT_VIEWPORT) == 0) { return false; } @@ -3169,16 +3174,19 @@ static int ds_base_sorting_cmp(const void *base1_ptr, const void *base2_ptr) /* Get a sorted list of all the bases - for inclusion in dopesheet (when drawing channels) */ static Base **animdata_filter_ds_sorted_bases(bDopeSheet *ads, + const Scene *scene, ViewLayer *view_layer, int filter_mode, size_t *r_usable_bases) { /* Create an array with space for all the bases, but only containing the usable ones */ - size_t tot_bases = BLI_listbase_count(&view_layer->object_bases); + BKE_view_layer_synced_ensure(scene, view_layer); + ListBase *object_bases = BKE_view_layer_object_bases_get(view_layer); + size_t tot_bases = BLI_listbase_count(object_bases); size_t num_bases = 0; Base **sorted_bases = MEM_mallocN(sizeof(Base *) * tot_bases, "Dopesheet Usable Sorted Bases"); - LISTBASE_FOREACH (Base *, base, &view_layer->object_bases) { + LISTBASE_FOREACH (Base *, base, object_bases) { if (animdata_filter_base_is_ok(ads, base, OB_MODE_OBJECT, filter_mode)) { sorted_bases[num_bases++] = base; } @@ -3248,14 +3256,17 @@ static size_t animdata_filter_dopesheet(bAnimContext *ac, * - Don't do this if this behavior has been turned off (i.e. due to it being too slow) * - Don't do this if there's just a single object */ + BKE_view_layer_synced_ensure(scene, view_layer); + ListBase *object_bases = BKE_view_layer_object_bases_get(view_layer); if ((filter_mode & ANIMFILTER_LIST_CHANNELS) && !(ads->flag & ADS_FLAG_NO_DB_SORT) && - (view_layer->object_bases.first != view_layer->object_bases.last)) { + (object_bases->first != object_bases->last)) { /* Filter list of bases (i.e. objects), sort them, then add their contents normally... */ /* TODO: Cache the old sorted order - if the set of bases hasn't changed, don't re-sort... */ Base **sorted_bases; size_t num_bases; - sorted_bases = animdata_filter_ds_sorted_bases(ads, view_layer, filter_mode, &num_bases); + sorted_bases = animdata_filter_ds_sorted_bases( + ads, scene, view_layer, filter_mode, &num_bases); if (sorted_bases) { /* Add the necessary channels for these bases... */ for (size_t i = 0; i < num_bases; i++) { @@ -3272,9 +3283,9 @@ static size_t animdata_filter_dopesheet(bAnimContext *ac, /* Filter and add contents of each base (i.e. object) without them sorting first * NOTE: This saves performance in cases where order doesn't matter */ - Object *obact = OBACT(view_layer); + Object *obact = BKE_view_layer_active_object_get(view_layer); const eObjectMode object_mode = obact ? obact->mode : OB_MODE_OBJECT; - LISTBASE_FOREACH (Base *, base, &view_layer->object_bases) { + LISTBASE_FOREACH (Base *, base, object_bases) { if (animdata_filter_base_is_ok(ads, base, object_mode, filter_mode)) { /* since we're still here, this object should be usable */ items += animdata_filter_dopesheet_ob(ac, anim_data, ads, base, filter_mode); @@ -3406,9 +3417,8 @@ static size_t animdata_filter_remove_duplis(ListBase *anim_data) GSet *gs; size_t items = 0; - /* build new hashtable to efficiently store and retrieve which entries have been - * encountered already while searching - */ + /* Build new hash-table to efficiently store and retrieve which entries have been + * encountered already while searching. */ gs = BLI_gset_ptr_new(__func__); /* loop through items, removing them from the list if a similar item occurs already */ diff --git a/source/blender/editors/animation/anim_markers.c b/source/blender/editors/animation/anim_markers.c index e7c7f679b16..94746837259 100644 --- a/source/blender/editors/animation/anim_markers.c +++ b/source/blender/editors/animation/anim_markers.c @@ -51,7 +51,6 @@ #include "ED_screen.h" #include "ED_select_utils.h" #include "ED_transform.h" -#include "ED_types.h" #include "ED_util.h" #include "DEG_depsgraph.h" @@ -437,7 +436,7 @@ static void draw_marker_line(const uchar *color, int xpos, int ymin, int ymax) GPUVertFormat *format = immVertexFormat(); uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); - immBindBuiltinProgram(GPU_SHADER_2D_LINE_DASHED_UNIFORM_COLOR); + immBindBuiltinProgram(GPU_SHADER_3D_LINE_DASHED_UNIFORM_COLOR); float viewport_size[4]; GPU_viewport_size_get_f(viewport_size); @@ -459,9 +458,7 @@ static void draw_marker_line(const uchar *color, int xpos, int ymin, int ymax) static int marker_get_icon_id(TimeMarker *marker, int flag) { if (flag & DRAW_MARKERS_LOCAL) { - return (marker->flag & ACTIVE) ? ICON_PMARKER_ACT : - (marker->flag & SELECT) ? ICON_PMARKER_SEL : - ICON_PMARKER; + return (marker->flag & SELECT) ? ICON_PMARKER_SEL : ICON_PMARKER; } #ifdef DURIAN_CAMERA_SWITCH if (marker->camera) { @@ -503,7 +500,7 @@ static void draw_marker(const uiFontStyle *fstyle, static void draw_markers_background(rctf *rect) { uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); - immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); uchar shade[4]; UI_GetThemeColor4ubv(TH_TIME_SCRUB_BACKGROUND, shade); @@ -1113,7 +1110,7 @@ static void MARKER_OT_move(wmOperatorType *ot) RNA_def_int(ot->srna, "frames", 0, INT_MIN, INT_MAX, "Frames", "", INT_MIN, INT_MAX); PropertyRNA *prop = RNA_def_boolean( ot->srna, "tweak", 0, "Tweak", "Operator has been activated using a click-drag event"); - RNA_def_property_flag(prop, PROP_SKIP_SAVE); + RNA_def_property_flag(prop, PROP_SKIP_SAVE | PROP_HIDDEN); } /** \} */ @@ -1258,14 +1255,14 @@ static int select_timeline_marker_frame(ListBase *markers, deselect_markers(markers); } - LISTBASE_CIRCULAR_FORWARD_BEGIN (markers, marker, marker_cycle_selected) { + LISTBASE_CIRCULAR_FORWARD_BEGIN (TimeMarker *, markers, marker, marker_cycle_selected) { /* this way a not-extend select will always give 1 selected marker */ if (marker->frame == frame) { marker->flag ^= SELECT; break; } } - LISTBASE_CIRCULAR_FORWARD_END(markers, marker, marker_cycle_selected); + LISTBASE_CIRCULAR_FORWARD_END(TimeMarker *, markers, marker, marker_cycle_selected); } return ret_val; @@ -1284,7 +1281,7 @@ static void select_marker_camera_switch( int sel = 0; if (!extend) { - BKE_view_layer_base_deselect_all(view_layer); + BKE_view_layer_base_deselect_all(scene, view_layer); } for (marker = markers->first; marker; marker = marker->next) { @@ -1294,6 +1291,7 @@ static void select_marker_camera_switch( } } + BKE_view_layer_synced_ensure(scene, view_layer); for (marker = markers->first; marker; marker = marker->next) { if (marker->camera) { if (marker->frame == cfra) { @@ -1381,7 +1379,7 @@ static void MARKER_OT_select(wmOperatorType *ot) ot->modal = WM_generic_select_modal; /* flags */ - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + ot->flag = OPTYPE_UNDO; WM_operator_properties_generic_select(ot); prop = RNA_def_boolean(ot->srna, "extend", 0, "Extend", "Extend the selection"); @@ -1481,7 +1479,7 @@ static void MARKER_OT_select_box(wmOperatorType *ot) ot->poll = ed_markers_poll_markers_exist; /* flags */ - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + ot->flag = OPTYPE_UNDO; /* properties */ WM_operator_properties_gesture_box(ot); @@ -1605,8 +1603,8 @@ static void MARKER_OT_select_leftright(wmOperatorType *ot) /* rna storage */ RNA_def_enum( - ot->srna, "mode", prop_markers_select_leftright_modes, MARKERS_LRSEL_LEFT, "mode", "Mode"); - RNA_def_boolean(ot->srna, "extend", false, "extend", "Extend"); + ot->srna, "mode", prop_markers_select_leftright_modes, MARKERS_LRSEL_LEFT, "Mode", ""); + RNA_def_boolean(ot->srna, "extend", false, "Extend Select", ""); } /** \} */ diff --git a/source/blender/editors/animation/keyframes_draw.c b/source/blender/editors/animation/keyframes_draw.c index 786204a52ed..6df9dc1e86d 100644 --- a/source/blender/editors/animation/keyframes_draw.c +++ b/source/blender/editors/animation/keyframes_draw.c @@ -608,7 +608,7 @@ static AnimKeylistDrawListElem *ed_keylist_draw_list_add_elem( return draw_elem; } -/* *************************** Channel Drawing Funcs *************************** */ +/* *************************** Channel Drawing Functions *************************** */ void draw_summary_channel(struct AnimKeylistDrawList *draw_list, bAnimContext *ac, diff --git a/source/blender/editors/animation/keyframes_edit.c b/source/blender/editors/animation/keyframes_edit.c index 63bd5665459..2a94c5db439 100644 --- a/source/blender/editors/animation/keyframes_edit.c +++ b/source/blender/editors/animation/keyframes_edit.c @@ -1303,7 +1303,8 @@ void ANIM_fcurve_equalize_keyframes_loop(FCurve *fcu, /* Perform handle equalization if mode is 'Both' or 'Left'. */ if (mode & EQUALIZE_HANDLES_LEFT) { - /*If left handle type is 'Auto', 'Auto Clamped', or 'Vector', convert handles to 'Aligned'.*/ + /* If left handle type is 'Auto', 'Auto Clamped', or 'Vector', convert handles to 'Aligned'. + */ if (ELEM(bezt->h1, HD_AUTO, HD_AUTO_ANIM, HD_VECT)) { bezt->h1 = HD_ALIGN; bezt->h2 = HD_ALIGN; @@ -1319,8 +1320,8 @@ void ANIM_fcurve_equalize_keyframes_loop(FCurve *fcu, /* Perform handle equalization if mode is 'Both' or 'Right'. */ if (mode & EQUALIZE_HANDLES_RIGHT) { - /*If right handle type is 'Auto', 'Auto Clamped', or 'Vector', convert handles to - * 'Aligned'.*/ + /* If right handle type is 'Auto', 'Auto Clamped', or 'Vector', convert handles to + * 'Aligned'. */ if (ELEM(bezt->h2, HD_AUTO, HD_AUTO_ANIM, HD_VECT)) { bezt->h1 = HD_ALIGN; bezt->h2 = HD_ALIGN; diff --git a/source/blender/editors/animation/keyframing.c b/source/blender/editors/animation/keyframing.c index 12f83343299..acf53541843 100644 --- a/source/blender/editors/animation/keyframing.c +++ b/source/blender/editors/animation/keyframing.c @@ -1081,10 +1081,7 @@ static float *visualkey_get_values( } if (strstr(identifier, "rotation_quaternion")) { - float mat3[3][3]; - - copy_m3_m4(mat3, tmat); - mat3_to_quat_is_ok(buffer, mat3); + mat4_to_quat(buffer, tmat); *r_count = 4; return buffer; diff --git a/source/blender/editors/animation/keyingsets.c b/source/blender/editors/animation/keyingsets.c index 967a324ef95..97e90af019b 100644 --- a/source/blender/editors/animation/keyingsets.c +++ b/source/blender/editors/animation/keyingsets.c @@ -589,7 +589,7 @@ void ANIM_keyingset_info_unregister(Main *bmain, KeyingSetInfo *ksi) /* find relevant builtin KeyingSets which use this, and remove them */ /* TODO: this isn't done now, since unregister is really only used at the moment when we - * reload the scripts, which kindof defeats the purpose of "builtin"? */ + * reload the scripts, which kind of defeats the purpose of "builtin"? */ for (ks = builtin_keyingsets.first; ks; ks = ksn) { ksn = ks->next; @@ -714,7 +714,7 @@ static void anim_keyingset_visit_for_search_impl(const bContext *C, void *visit_user_data, const bool use_poll) { - /* Poll requires context. */ + /* Poll requires context. */ if (use_poll && (C == NULL)) { return; } diff --git a/source/blender/editors/animation/time_scrub_ui.c b/source/blender/editors/animation/time_scrub_ui.c index 623d4e605ba..ebeac6552cd 100644 --- a/source/blender/editors/animation/time_scrub_ui.c +++ b/source/blender/editors/animation/time_scrub_ui.c @@ -48,7 +48,7 @@ static int get_centered_text_y(const rcti *rect) static void draw_background(const rcti *rect) { uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); - immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); immUniformThemeColor(TH_TIME_SCRUB_BACKGROUND); @@ -97,7 +97,7 @@ static void draw_current_frame(const Scene *scene, uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); GPU_blend(GPU_BLEND_ALPHA); - immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); /* Outline. */ immUniformThemeColorShadeAlpha(TH_BACK, -25, -100); @@ -208,7 +208,7 @@ void ED_time_scrub_channel_search_draw(const bContext *C, ARegion *region, bDope rect.ymax = region->winy; uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); - immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); immUniformThemeColor(TH_BACK); immRectf(pos, rect.xmin, rect.ymin, rect.xmax, rect.ymax); immUnbindProgram(); diff --git a/source/blender/editors/armature/CMakeLists.txt b/source/blender/editors/armature/CMakeLists.txt index 3ce5b70918d..243b2950e2e 100644 --- a/source/blender/editors/armature/CMakeLists.txt +++ b/source/blender/editors/armature/CMakeLists.txt @@ -14,7 +14,6 @@ set(INC ../../windowmanager ../../../../intern/clog ../../../../intern/eigen - ../../../../intern/glew-mx ../../../../intern/guardedalloc # RNA_prototypes.h ${CMAKE_BINARY_DIR}/source/blender/makesrna diff --git a/source/blender/editors/armature/armature_add.c b/source/blender/editors/armature/armature_add.c index 2071f056f9e..17484b2b0b7 100644 --- a/source/blender/editors/armature/armature_add.c +++ b/source/blender/editors/armature/armature_add.c @@ -541,7 +541,7 @@ static void updateDuplicateActionConstraintSettings( } BLI_freelistN(&ani_curves); - /* Make deps graph aware of our changes */ + /* Make depsgraph aware of our changes. */ DEG_id_tag_update(&act->id, ID_RECALC_ANIMATION_NO_FLUSH); } @@ -920,6 +920,7 @@ EditBone *duplicateEditBone(EditBone *cur_bone, const char *name, ListBase *edit static int armature_duplicate_selected_exec(bContext *C, wmOperator *op) { + const Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); const bool do_flip_names = RNA_boolean_get(op->ptr, "do_flip_names"); @@ -930,7 +931,7 @@ static int armature_duplicate_selected_exec(bContext *C, wmOperator *op) uint objects_len = 0; Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data( - view_layer, CTX_wm_view3d(C), &objects_len); + scene, view_layer, CTX_wm_view3d(C), &objects_len); for (uint ob_index = 0; ob_index < objects_len; ob_index++) { EditBone *ebone_iter; /* The beginning of the duplicated bones in the edbo list */ @@ -1094,6 +1095,7 @@ static EditBone *get_symmetrized_bone(bArmature *arm, EditBone *bone) */ static int armature_symmetrize_exec(bContext *C, wmOperator *op) { + const Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); const int direction = RNA_enum_get(op->ptr, "direction"); const int axis = 0; @@ -1105,7 +1107,7 @@ static int armature_symmetrize_exec(bContext *C, wmOperator *op) uint objects_len = 0; Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data( - view_layer, CTX_wm_view3d(C), &objects_len); + scene, view_layer, CTX_wm_view3d(C), &objects_len); for (uint ob_index = 0; ob_index < objects_len; ob_index++) { Object *obedit = objects[ob_index]; bArmature *arm = obedit->data; @@ -1349,13 +1351,14 @@ void ARMATURE_OT_symmetrize(wmOperatorType *ot) /* if forked && mirror-edit: makes two bones with flipped names */ static int armature_extrude_exec(bContext *C, wmOperator *op) { + const Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); const bool forked = RNA_boolean_get(op->ptr, "forked"); bool changed_multi = false; uint objects_len = 0; Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data( - view_layer, CTX_wm_view3d(C), &objects_len); + scene, view_layer, CTX_wm_view3d(C), &objects_len); for (uint ob_index = 0; ob_index < objects_len; ob_index++) { Object *ob = objects[ob_index]; bArmature *arm = ob->data; diff --git a/source/blender/editors/armature/armature_edit.c b/source/blender/editors/armature/armature_edit.c index 3c445f46902..81b1c096d76 100644 --- a/source/blender/editors/armature/armature_edit.c +++ b/source/blender/editors/armature/armature_edit.c @@ -254,6 +254,7 @@ static const EnumPropertyItem prop_calc_roll_types[] = { static int armature_calc_roll_exec(bContext *C, wmOperator *op) { + const Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); Object *ob_active = CTX_data_edit_object(C); int ret = OPERATOR_FINISHED; @@ -267,7 +268,7 @@ static int armature_calc_roll_exec(bContext *C, wmOperator *op) uint objects_len = 0; Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data( - view_layer, CTX_wm_view3d(C), &objects_len); + scene, view_layer, CTX_wm_view3d(C), &objects_len); for (uint ob_index = 0; ob_index < objects_len; ob_index++) { Object *ob = objects[ob_index]; bArmature *arm = ob->data; @@ -285,7 +286,6 @@ static int armature_calc_roll_exec(bContext *C, wmOperator *op) invert_m3(imat); if (type == CALC_ROLL_CURSOR) { /* Cursor */ - Scene *scene = CTX_data_scene(C); float cursor_local[3]; const View3DCursor *cursor = &scene->cursor; @@ -463,12 +463,13 @@ void ARMATURE_OT_calculate_roll(wmOperatorType *ot) static int armature_roll_clear_exec(bContext *C, wmOperator *op) { + const Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); const float roll = RNA_float_get(op->ptr, "roll"); uint objects_len = 0; Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data( - view_layer, CTX_wm_view3d(C), &objects_len); + scene, view_layer, CTX_wm_view3d(C), &objects_len); for (uint ob_index = 0; ob_index < objects_len; ob_index++) { Object *ob = objects[ob_index]; bArmature *arm = ob->data; @@ -712,7 +713,7 @@ static int armature_fill_bones_exec(bContext *C, wmOperator *op) Object *obedit = NULL; { ViewLayer *view_layer = CTX_data_view_layer(C); - FOREACH_OBJECT_IN_EDIT_MODE_BEGIN (view_layer, v3d, ob_iter) { + FOREACH_OBJECT_IN_EDIT_MODE_BEGIN (scene, view_layer, v3d, ob_iter) { if (ob_iter->data == arm) { obedit = ob_iter; } @@ -884,10 +885,11 @@ static void armature_clear_swap_done_flags(bArmature *arm) static int armature_switch_direction_exec(bContext *C, wmOperator *UNUSED(op)) { + const Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); uint objects_len = 0; Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data( - view_layer, CTX_wm_view3d(C), &objects_len); + scene, view_layer, CTX_wm_view3d(C), &objects_len); for (uint ob_index = 0; ob_index < objects_len; ob_index++) { Object *ob = objects[ob_index]; @@ -1157,11 +1159,12 @@ void ARMATURE_OT_align(wmOperatorType *ot) static int armature_split_exec(bContext *C, wmOperator *UNUSED(op)) { + const Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); uint objects_len = 0; Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data( - view_layer, CTX_wm_view3d(C), &objects_len); + scene, view_layer, CTX_wm_view3d(C), &objects_len); for (uint ob_index = 0; ob_index < objects_len; ob_index++) { Object *ob = objects[ob_index]; bArmature *arm = ob->data; @@ -1226,10 +1229,11 @@ static int armature_delete_selected_exec(bContext *C, wmOperator *UNUSED(op)) return OPERATOR_CANCELLED; } + const Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); uint objects_len = 0; Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data( - view_layer, CTX_wm_view3d(C), &objects_len); + scene, view_layer, CTX_wm_view3d(C), &objects_len); for (uint ob_index = 0; ob_index < objects_len; ob_index++) { Object *obedit = objects[ob_index]; bArmature *arm = obedit->data; @@ -1299,13 +1303,14 @@ static bool armature_dissolve_ebone_cb(const char *bone_name, void *arm_p) static int armature_dissolve_selected_exec(bContext *C, wmOperator *UNUSED(op)) { + const Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); EditBone *ebone, *ebone_next; bool changed_multi = false; uint objects_len = 0; Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data( - view_layer, CTX_wm_view3d(C), &objects_len); + scene, view_layer, CTX_wm_view3d(C), &objects_len); for (uint ob_index = 0; ob_index < objects_len; ob_index++) { Object *obedit = objects[ob_index]; bArmature *arm = obedit->data; @@ -1471,6 +1476,7 @@ void ARMATURE_OT_dissolve(wmOperatorType *ot) static int armature_hide_exec(bContext *C, wmOperator *op) { + const Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); const int invert = RNA_boolean_get(op->ptr, "unselected") ? BONE_SELECTED : 0; @@ -1481,7 +1487,7 @@ static int armature_hide_exec(bContext *C, wmOperator *op) uint objects_len = 0; Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data( - view_layer, CTX_wm_view3d(C), &objects_len); + scene, view_layer, CTX_wm_view3d(C), &objects_len); for (uint ob_index = 0; ob_index < objects_len; ob_index++) { Object *obedit = objects[ob_index]; bArmature *arm = obedit->data; @@ -1536,11 +1542,12 @@ void ARMATURE_OT_hide(wmOperatorType *ot) static int armature_reveal_exec(bContext *C, wmOperator *op) { + const Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); const bool select = RNA_boolean_get(op->ptr, "select"); uint objects_len = 0; Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data( - view_layer, CTX_wm_view3d(C), &objects_len); + scene, view_layer, CTX_wm_view3d(C), &objects_len); for (uint ob_index = 0; ob_index < objects_len; ob_index++) { Object *obedit = objects[ob_index]; bArmature *arm = obedit->data; diff --git a/source/blender/editors/armature/armature_naming.c b/source/blender/editors/armature/armature_naming.c index 4f329dbe449..26ec05cc503 100644 --- a/source/blender/editors/armature/armature_naming.c +++ b/source/blender/editors/armature/armature_naming.c @@ -429,6 +429,7 @@ void ED_armature_bones_flip_names(Main *bmain, static int armature_flip_names_exec(bContext *C, wmOperator *op) { Main *bmain = CTX_data_main(C); + const Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); Object *ob_active = CTX_data_edit_object(C); @@ -436,7 +437,7 @@ static int armature_flip_names_exec(bContext *C, wmOperator *op) uint objects_len = 0; Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data( - view_layer, CTX_wm_view3d(C), &objects_len); + scene, view_layer, CTX_wm_view3d(C), &objects_len); for (uint ob_index = 0; ob_index < objects_len; ob_index++) { Object *ob = objects[ob_index]; bArmature *arm = ob->data; @@ -516,6 +517,7 @@ void ARMATURE_OT_flip_names(wmOperatorType *ot) static int armature_autoside_names_exec(bContext *C, wmOperator *op) { + const Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); Main *bmain = CTX_data_main(C); char newname[MAXBONENAME]; @@ -524,7 +526,7 @@ static int armature_autoside_names_exec(bContext *C, wmOperator *op) uint objects_len = 0; Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data( - view_layer, CTX_wm_view3d(C), &objects_len); + scene, view_layer, CTX_wm_view3d(C), &objects_len); for (uint ob_index = 0; ob_index < objects_len; ob_index++) { Object *ob = objects[ob_index]; bArmature *arm = ob->data; diff --git a/source/blender/editors/armature/armature_relations.c b/source/blender/editors/armature/armature_relations.c index 0825d6968c6..9f1883ccac0 100644 --- a/source/blender/editors/armature/armature_relations.c +++ b/source/blender/editors/armature/armature_relations.c @@ -610,7 +610,7 @@ static int separate_armature_exec(bContext *C, wmOperator *op) uint bases_len = 0; Base **bases = BKE_view_layer_array_from_bases_in_edit_mode_unique_data( - view_layer, CTX_wm_view3d(C), &bases_len); + scene, view_layer, CTX_wm_view3d(C), &bases_len); for (uint base_index = 0; base_index < bases_len; base_index++) { Base *base_old = bases[base_index]; @@ -974,6 +974,7 @@ static void editbone_clear_parent(EditBone *ebone, int mode) static int armature_parent_clear_exec(bContext *C, wmOperator *op) { + const Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); const int val = RNA_enum_get(op->ptr, "type"); @@ -984,7 +985,7 @@ static int armature_parent_clear_exec(bContext *C, wmOperator *op) uint objects_len = 0; Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data( - view_layer, CTX_wm_view3d(C), &objects_len); + scene, view_layer, CTX_wm_view3d(C), &objects_len); for (uint ob_index = 0; ob_index < objects_len; ob_index++) { Object *ob = objects[ob_index]; bArmature *arm = ob->data; diff --git a/source/blender/editors/armature/armature_select.c b/source/blender/editors/armature/armature_select.c index ae15bc39ec8..e490f21f16d 100644 --- a/source/blender/editors/armature/armature_select.c +++ b/source/blender/editors/armature/armature_select.c @@ -339,15 +339,11 @@ static void *ed_armature_pick_bone_impl( Base **bases; if (vc.obedit != NULL) { - bases = BKE_view_layer_array_from_bases_in_mode(vc.view_layer, - vc.v3d, - &bases_len, - { - .object_mode = OB_MODE_EDIT, - }); + bases = BKE_view_layer_array_from_bases_in_edit_mode( + vc.scene, vc.view_layer, vc.v3d, &bases_len); } else { - bases = BKE_object_pose_base_array_get(vc.view_layer, vc.v3d, &bases_len); + bases = BKE_object_pose_base_array_get(vc.scene, vc.view_layer, vc.v3d, &bases_len); } void *bone = ed_armature_pick_bone_from_selectbuffer_impl( @@ -499,10 +495,11 @@ static int armature_select_linked_exec(bContext *C, wmOperator *op) const bool all_forks = RNA_boolean_get(op->ptr, "all_forks"); bool changed_multi = false; + const Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); uint objects_len = 0; Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data( - view_layer, CTX_wm_view3d(C), &objects_len); + scene, view_layer, CTX_wm_view3d(C), &objects_len); for (uint ob_index = 0; ob_index < objects_len; ob_index++) { Object *ob = objects[ob_index]; bArmature *arm = ob->data; @@ -718,7 +715,7 @@ cache_end: uint bases_len; Base **bases = BKE_view_layer_array_from_bases_in_edit_mode_unique_data( - vc->view_layer, vc->v3d, &bases_len); + vc->scene, vc->view_layer, vc->v3d, &bases_len); /* See if there are any selected bones in this group */ if (hits > 0) { @@ -935,7 +932,7 @@ bool ED_armature_edit_deselect_all_visible_multi(bContext *C) ED_view3d_viewcontext_init(C, &vc, depsgraph); uint bases_len = 0; Base **bases = BKE_view_layer_array_from_bases_in_edit_mode_unique_data( - vc.view_layer, vc.v3d, &bases_len); + vc.scene, vc.view_layer, vc.v3d, &bases_len); bool changed_multi = ED_armature_edit_deselect_all_multi_ex(bases, bases_len); MEM_freeN(bases); return changed_multi; @@ -953,6 +950,7 @@ bool ED_armature_edit_select_pick_bone(bContext *C, const int selmask, const struct SelectPick_Params *params) { + const Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); View3D *v3d = CTX_wm_view3d(C); bool changed = false; @@ -974,7 +972,7 @@ bool ED_armature_edit_select_pick_bone(bContext *C, /* Deselect everything. */ uint bases_len = 0; Base **bases = BKE_view_layer_array_from_bases_in_edit_mode_unique_data( - view_layer, v3d, &bases_len); + scene, view_layer, v3d, &bases_len); ED_armature_edit_deselect_all_multi_ex(bases, bases_len); MEM_freeN(bases); changed = true; @@ -1105,7 +1103,8 @@ bool ED_armature_edit_select_pick_bone(bContext *C, arm->act_edbone = ebone; } - if (view_layer->basact != basact) { + BKE_view_layer_synced_ensure(scene, view_layer); + if (BKE_view_layer_active_base_get(view_layer) != basact) { ED_object_base_activate(C, basact); } @@ -1494,10 +1493,11 @@ static void armature_select_more_less(Object *ob, bool more) static int armature_de_select_more_exec(bContext *C, wmOperator *UNUSED(op)) { + const Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); uint objects_len = 0; Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data( - view_layer, CTX_wm_view3d(C), &objects_len); + scene, view_layer, CTX_wm_view3d(C), &objects_len); for (uint ob_index = 0; ob_index < objects_len; ob_index++) { Object *ob = objects[ob_index]; armature_select_more_less(ob, true); @@ -1533,10 +1533,11 @@ void ARMATURE_OT_select_more(wmOperatorType *ot) static int armature_de_select_less_exec(bContext *C, wmOperator *UNUSED(op)) { + const Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); uint objects_len = 0; Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data( - view_layer, CTX_wm_view3d(C), &objects_len); + scene, view_layer, CTX_wm_view3d(C), &objects_len); for (uint ob_index = 0; ob_index < objects_len; ob_index++) { Object *ob = objects[ob_index]; armature_select_more_less(ob, false); @@ -1607,6 +1608,7 @@ static float bone_length_squared_worldspace_get(Object *ob, EditBone *ebone) static void select_similar_length(bContext *C, const float thresh) { + const Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); Object *ob_act = CTX_data_edit_object(C); EditBone *ebone_act = CTX_data_active_bone(C); @@ -1618,7 +1620,7 @@ static void select_similar_length(bContext *C, const float thresh) uint objects_len = 0; Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data( - view_layer, CTX_wm_view3d(C), &objects_len); + scene, view_layer, CTX_wm_view3d(C), &objects_len); for (uint ob_index = 0; ob_index < objects_len; ob_index++) { Object *ob = objects[ob_index]; bArmature *arm = ob->data; @@ -1657,6 +1659,7 @@ static void bone_direction_worldspace_get(Object *ob, EditBone *ebone, float *r_ static void select_similar_direction(bContext *C, const float thresh) { + const Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); Object *ob_act = CTX_data_edit_object(C); EditBone *ebone_act = CTX_data_active_bone(C); @@ -1666,7 +1669,7 @@ static void select_similar_direction(bContext *C, const float thresh) uint objects_len = 0; Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data( - view_layer, CTX_wm_view3d(C), &objects_len); + scene, view_layer, CTX_wm_view3d(C), &objects_len); for (uint ob_index = 0; ob_index < objects_len; ob_index++) { Object *ob = objects[ob_index]; bArmature *arm = ob->data; @@ -1695,12 +1698,13 @@ static void select_similar_direction(bContext *C, const float thresh) static void select_similar_layer(bContext *C) { + const Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); EditBone *ebone_act = CTX_data_active_bone(C); uint objects_len = 0; Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data( - view_layer, CTX_wm_view3d(C), &objects_len); + scene, view_layer, CTX_wm_view3d(C), &objects_len); for (uint ob_index = 0; ob_index < objects_len; ob_index++) { Object *ob = objects[ob_index]; bArmature *arm = ob->data; @@ -1725,6 +1729,7 @@ static void select_similar_layer(bContext *C) static void select_similar_prefix(bContext *C) { + const Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); EditBone *ebone_act = CTX_data_active_bone(C); @@ -1739,7 +1744,7 @@ static void select_similar_prefix(bContext *C) uint objects_len = 0; Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data( - view_layer, CTX_wm_view3d(C), &objects_len); + scene, view_layer, CTX_wm_view3d(C), &objects_len); for (uint ob_index = 0; ob_index < objects_len; ob_index++) { Object *ob = objects[ob_index]; bArmature *arm = ob->data; @@ -1767,6 +1772,7 @@ static void select_similar_prefix(bContext *C) static void select_similar_suffix(bContext *C) { + const Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); EditBone *ebone_act = CTX_data_active_bone(C); @@ -1781,7 +1787,7 @@ static void select_similar_suffix(bContext *C) uint objects_len = 0; Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data( - view_layer, CTX_wm_view3d(C), &objects_len); + scene, view_layer, CTX_wm_view3d(C), &objects_len); for (uint ob_index = 0; ob_index < objects_len; ob_index++) { Object *ob = objects[ob_index]; bArmature *arm = ob->data; @@ -2106,13 +2112,14 @@ void ARMATURE_OT_select_hierarchy(wmOperatorType *ot) */ static int armature_select_mirror_exec(bContext *C, wmOperator *op) { + const Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); const bool active_only = RNA_boolean_get(op->ptr, "only_active"); const bool extend = RNA_boolean_get(op->ptr, "extend"); uint objects_len = 0; Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data( - view_layer, CTX_wm_view3d(C), &objects_len); + scene, view_layer, CTX_wm_view3d(C), &objects_len); for (uint ob_index = 0; ob_index < objects_len; ob_index++) { Object *ob = objects[ob_index]; bArmature *arm = ob->data; diff --git a/source/blender/editors/armature/armature_skinning.c b/source/blender/editors/armature/armature_skinning.c index 3a1e7419d3c..6155aac621d 100644 --- a/source/blender/editors/armature/armature_skinning.c +++ b/source/blender/editors/armature/armature_skinning.c @@ -21,6 +21,7 @@ #include "BKE_action.h" #include "BKE_armature.h" #include "BKE_deform.h" +#include "BKE_mesh.h" #include "BKE_mesh_iterators.h" #include "BKE_mesh_runtime.h" #include "BKE_modifier.h" @@ -202,10 +203,13 @@ static void envelope_bone_weighting(Object *ob, use_mask = true; } + const bool *select_vert = (const bool *)CustomData_get_layer_named( + &mesh->vdata, CD_PROP_BOOL, ".select_vert"); + /* for each vertex in the mesh */ for (int i = 0; i < mesh->totvert; i++) { - if (use_mask && !(mesh->mvert[i].flag & SELECT)) { + if (use_mask && !(select_vert && select_vert[i])) { continue; } @@ -405,9 +409,10 @@ static void add_verts_to_dgroups(ReportList *reports, } /* transform verts to global space */ + const MVert *mesh_verts = BKE_mesh_verts(mesh); for (int i = 0; i < mesh->totvert; i++) { if (!vertsfilled) { - copy_v3_v3(verts[i], mesh->mvert[i].co); + copy_v3_v3(verts[i], mesh_verts[i].co); } mul_m4_v3(ob->obmat, verts[i]); } diff --git a/source/blender/editors/armature/editarmature_undo.c b/source/blender/editors/armature/editarmature_undo.c index bcf8b7cff99..379ad4f5376 100644 --- a/source/blender/editors/armature/editarmature_undo.c +++ b/source/blender/editors/armature/editarmature_undo.c @@ -97,8 +97,10 @@ static void undoarm_free_data(UndoArmature *uarm) static Object *editarm_object_from_context(bContext *C) { + Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); - Object *obedit = OBEDIT_FROM_VIEW_LAYER(view_layer); + BKE_view_layer_synced_ensure(scene, view_layer); + Object *obedit = BKE_view_layer_edit_object_get(view_layer); if (obedit && obedit->type == OB_ARMATURE) { bArmature *arm = obedit->data; if (arm->edbo != NULL) { @@ -139,9 +141,10 @@ static bool armature_undosys_step_encode(struct bContext *C, struct Main *bmain, /* Important not to use the 3D view when getting objects because all objects * outside of this list will be moved out of edit-mode when reading back undo steps. */ + const Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); uint objects_len = 0; - Object **objects = ED_undo_editmode_objects_from_view_layer(view_layer, &objects_len); + Object **objects = ED_undo_editmode_objects_from_view_layer(scene, view_layer, &objects_len); us->elems = MEM_callocN(sizeof(*us->elems) * objects_len, __func__); us->elems_len = objects_len; diff --git a/source/blender/editors/armature/meshlaplacian.c b/source/blender/editors/armature/meshlaplacian.c index 7016511111e..567977e51c4 100644 --- a/source/blender/editors/armature/meshlaplacian.c +++ b/source/blender/editors/armature/meshlaplacian.c @@ -645,14 +645,16 @@ void heat_bone_weighting(Object *ob, { LaplacianSystem *sys; MLoopTri *mlooptri; - MPoly *mp; - MLoop *ml; + const MPoly *mp; + const MLoop *ml; float solution, weight; int *vertsflipped = NULL, *mask = NULL; int a, tris_num, j, bbone, firstsegment, lastsegment; bool use_topology = (me->editflag & ME_EDIT_MIRROR_TOPO) != 0; - MVert *mvert = me->mvert; + const MVert *mesh_verts = BKE_mesh_verts(me); + const MPoly *polys = BKE_mesh_polys(me); + const MLoop *loops = BKE_mesh_loops(me); bool use_vert_sel = (me->editflag & ME_EDIT_PAINT_VERT_SEL) != 0; bool use_face_sel = (me->editflag & ME_EDIT_PAINT_FACE_SEL) != 0; @@ -667,17 +669,25 @@ void heat_bone_weighting(Object *ob, /* (added selectedVerts content for vertex mask, they used to just equal 1) */ if (use_vert_sel) { - for (a = 0, mp = me->mpoly; a < me->totpoly; mp++, a++) { - for (j = 0, ml = me->mloop + mp->loopstart; j < mp->totloop; j++, ml++) { - mask[ml->v] = (mvert[ml->v].flag & SELECT) != 0; + const bool *select_vert = (const bool *)CustomData_get_layer_named( + &me->vdata, CD_PROP_BOOL, ".select_vert"); + if (select_vert) { + for (a = 0, mp = polys; a < me->totpoly; mp++, a++) { + for (j = 0, ml = loops + mp->loopstart; j < mp->totloop; j++, ml++) { + mask[ml->v] = select_vert[ml->v]; + } } } } else if (use_face_sel) { - for (a = 0, mp = me->mpoly; a < me->totpoly; mp++, a++) { - if (mp->flag & ME_FACE_SEL) { - for (j = 0, ml = me->mloop + mp->loopstart; j < mp->totloop; j++, ml++) { - mask[ml->v] = 1; + const bool *select_poly = (const bool *)CustomData_get_layer_named( + &me->pdata, CD_PROP_BOOL, ".select_poly"); + if (select_poly) { + for (a = 0, mp = polys; a < me->totpoly; mp++, a++) { + if (select_poly[a]) { + for (j = 0, ml = loops + mp->loopstart; j < mp->totloop; j++, ml++) { + mask[ml->v] = 1; + } } } } @@ -690,10 +700,10 @@ void heat_bone_weighting(Object *ob, sys->heat.tris_num = poly_to_tri_count(me->totpoly, me->totloop); mlooptri = MEM_mallocN(sizeof(*sys->heat.mlooptri) * sys->heat.tris_num, __func__); - BKE_mesh_recalc_looptri(me->mloop, me->mpoly, me->mvert, me->totloop, me->totpoly, mlooptri); + BKE_mesh_recalc_looptri(loops, polys, mesh_verts, me->totloop, me->totpoly, mlooptri); sys->heat.mlooptri = mlooptri; - sys->heat.mloop = me->mloop; + sys->heat.mloop = loops; sys->heat.verts_num = me->totvert; sys->heat.verts = verts; sys->heat.root = root; @@ -1606,8 +1616,8 @@ static void harmonic_coordinates_bind(MeshDeformModifierData *mmd, MeshDeformBin /* initialize data from 'cagedm' for reuse */ { Mesh *me = mdb->cagemesh; - mdb->cagemesh_cache.mpoly = me->mpoly; - mdb->cagemesh_cache.mloop = me->mloop; + mdb->cagemesh_cache.mpoly = BKE_mesh_polys(me); + mdb->cagemesh_cache.mloop = BKE_mesh_loops(me); mdb->cagemesh_cache.looptri = BKE_mesh_runtime_looptri_ensure(me); mdb->cagemesh_cache.poly_nors = BKE_mesh_poly_normals_ensure(me); } @@ -1743,7 +1753,7 @@ void ED_mesh_deform_bind_callback(Object *object, MeshDeformModifierData *mmd_orig = (MeshDeformModifierData *)BKE_modifier_get_original( object, &mmd->modifier); MeshDeformBind mdb; - MVert *mvert; + const MVert *mvert; int a; waitcursor(1); @@ -1763,7 +1773,7 @@ void ED_mesh_deform_bind_callback(Object *object, mdb.cagecos = MEM_callocN(sizeof(*mdb.cagecos) * mdb.cage_verts_num, "MeshDeformBindCos"); copy_m4_m4(mdb.cagemat, cagemat); - mvert = mdb.cagemesh->mvert; + mvert = BKE_mesh_verts(mdb.cagemesh); for (a = 0; a < mdb.cage_verts_num; a++) { copy_v3_v3(mdb.cagecos[a], mvert[a].co); } diff --git a/source/blender/editors/armature/pose_edit.c b/source/blender/editors/armature/pose_edit.c index cec83ffa0f0..98861dc2b63 100644 --- a/source/blender/editors/armature/pose_edit.c +++ b/source/blender/editors/armature/pose_edit.c @@ -499,11 +499,12 @@ void POSE_OT_paths_range_update(wmOperatorType *ot) static int pose_flip_names_exec(bContext *C, wmOperator *op) { Main *bmain = CTX_data_main(C); + const Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); View3D *v3d = CTX_wm_view3d(C); const bool do_strip_numbers = RNA_boolean_get(op->ptr, "do_strip_numbers"); - FOREACH_OBJECT_IN_MODE_BEGIN (view_layer, v3d, OB_ARMATURE, OB_MODE_POSE, ob) { + FOREACH_OBJECT_IN_MODE_BEGIN (scene, view_layer, v3d, OB_ARMATURE, OB_MODE_POSE, ob) { bArmature *arm = ob->data; ListBase bones_names = {NULL}; @@ -856,9 +857,10 @@ static int pose_bone_layers_exec(bContext *C, wmOperator *op) struct Main *bmain = CTX_data_main(C); wmWindow *win = CTX_wm_window(C); View3D *v3d = CTX_wm_view3d(C); /* This may be NULL in a lot of cases. */ + const Scene *scene = WM_window_get_active_scene(win); ViewLayer *view_layer = WM_window_get_active_view_layer(win); - FOREACH_OBJECT_IN_MODE_BEGIN (view_layer, v3d, OB_ARMATURE, OB_MODE_POSE, ob_iter) { + FOREACH_OBJECT_IN_MODE_BEGIN (scene, view_layer, v3d, OB_ARMATURE, OB_MODE_POSE, ob_iter) { bArmature *arm = ob_iter->data; BKE_pose_ensure(bmain, ob_iter, arm, true); } @@ -952,6 +954,7 @@ static int armature_bone_layers_exec(bContext *C, wmOperator *op) /* NOTE: notifier might evolve. */ WM_event_add_notifier(C, NC_OBJECT | ND_POSE, ob); + DEG_id_tag_update((ID *)ob->data, ID_RECALC_PARAMETERS); return OPERATOR_FINISHED; } @@ -1001,9 +1004,11 @@ static int hide_pose_bone_fn(Object *ob, Bone *bone, void *ptr) /* active object is armature in posemode, poll checked */ static int pose_hide_exec(bContext *C, wmOperator *op) { + const Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); uint objects_len; - Object **objects = BKE_object_pose_array_get_unique(view_layer, CTX_wm_view3d(C), &objects_len); + Object **objects = BKE_object_pose_array_get_unique( + scene, view_layer, CTX_wm_view3d(C), &objects_len); bool changed_multi = false; const int hide_select = !RNA_boolean_get(op->ptr, "unselected"); @@ -1066,9 +1071,11 @@ static int show_pose_bone_cb(Object *ob, Bone *bone, void *data) /* active object is armature in posemode, poll checked */ static int pose_reveal_exec(bContext *C, wmOperator *op) { + const Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); uint objects_len; - Object **objects = BKE_object_pose_array_get_unique(view_layer, CTX_wm_view3d(C), &objects_len); + Object **objects = BKE_object_pose_array_get_unique( + scene, view_layer, CTX_wm_view3d(C), &objects_len); bool changed_multi = false; const bool select = RNA_boolean_get(op->ptr, "select"); void *select_p = POINTER_FROM_INT(select); @@ -1118,7 +1125,7 @@ static int pose_flip_quats_exec(bContext *C, wmOperator *UNUSED(op)) ViewLayer *view_layer = CTX_data_view_layer(C); View3D *v3d = CTX_wm_view3d(C); - FOREACH_OBJECT_IN_MODE_BEGIN (view_layer, v3d, OB_ARMATURE, OB_MODE_POSE, ob_iter) { + FOREACH_OBJECT_IN_MODE_BEGIN (scene, view_layer, v3d, OB_ARMATURE, OB_MODE_POSE, ob_iter) { bool changed = false; /* loop through all selected pchans, flipping and keying (as needed) */ FOREACH_PCHAN_SELECTED_IN_OBJECT_BEGIN (ob_iter, pchan) { diff --git a/source/blender/editors/armature/pose_select.c b/source/blender/editors/armature/pose_select.c index 6756dec1c95..6a31c7f1496 100644 --- a/source/blender/editors/armature/pose_select.c +++ b/source/blender/editors/armature/pose_select.c @@ -121,7 +121,8 @@ void ED_pose_bone_select(Object *ob, bPoseChannel *pchan, bool select) } } -bool ED_armature_pose_select_pick_bone(ViewLayer *view_layer, +bool ED_armature_pose_select_pick_bone(const Scene *scene, + ViewLayer *view_layer, View3D *v3d, Object *ob, Bone *bone, @@ -144,7 +145,7 @@ bool ED_armature_pose_select_pick_bone(ViewLayer *view_layer, /* Deselect everything. */ /* Don't use 'BKE_object_pose_base_array_get_unique' * because we may be selecting from object mode. */ - FOREACH_VISIBLE_BASE_BEGIN (view_layer, v3d, base_iter) { + FOREACH_VISIBLE_BASE_BEGIN (scene, view_layer, v3d, base_iter) { Object *ob_iter = base_iter->object; if ((ob_iter->type == OB_ARMATURE) && (ob_iter->mode & OB_MODE_POSE)) { if (ED_pose_deselect_all(ob_iter, SEL_DESELECT, true)) { @@ -158,8 +159,9 @@ bool ED_armature_pose_select_pick_bone(ViewLayer *view_layer, } if (found) { - Object *ob_act = OBACT(view_layer); - BLI_assert(OBEDIT_FROM_VIEW_LAYER(view_layer) == NULL); + BKE_view_layer_synced_ensure(scene, view_layer); + Object *ob_act = BKE_view_layer_active_object_get(view_layer); + BLI_assert(BKE_view_layer_edit_object_get(view_layer) == NULL); /* If the bone cannot be affected, don't do anything. */ bArmature *arm = ob->data; @@ -243,7 +245,8 @@ bool ED_armature_pose_select_pick_bone(ViewLayer *view_layer, return changed || found; } -bool ED_armature_pose_select_pick_with_buffer(ViewLayer *view_layer, +bool ED_armature_pose_select_pick_with_buffer(const Scene *scene, + ViewLayer *view_layer, View3D *v3d, Base *base, const struct GPUSelectResult *buffer, @@ -263,13 +266,16 @@ bool ED_armature_pose_select_pick_with_buffer(ViewLayer *view_layer, nearBone = ED_armature_pick_bone_from_selectbuffer( &base, 1, buffer, hits, 1, do_nearest, &base_dummy); - return ED_armature_pose_select_pick_bone(view_layer, v3d, ob, nearBone, params); + return ED_armature_pose_select_pick_bone(scene, view_layer, v3d, ob, nearBone, params); } -void ED_armature_pose_select_in_wpaint_mode(ViewLayer *view_layer, Base *base_select) +void ED_armature_pose_select_in_wpaint_mode(const Scene *scene, + ViewLayer *view_layer, + Base *base_select) { BLI_assert(base_select && (base_select->object->type == OB_ARMATURE)); - Object *ob_active = OBACT(view_layer); + BKE_view_layer_synced_ensure(scene, view_layer); + Object *ob_active = BKE_view_layer_active_object_get(view_layer); BLI_assert(ob_active && (ob_active->mode & OB_MODE_ALL_WEIGHT_PAINT)); if (ob_active->type == OB_GPENCIL) { @@ -401,7 +407,8 @@ bool ED_pose_deselect_all_multi(bContext *C, int select_mode, const bool ignore_ ED_view3d_viewcontext_init(C, &vc, depsgraph); uint bases_len = 0; - Base **bases = BKE_object_pose_base_array_get_unique(vc.view_layer, vc.v3d, &bases_len); + Base **bases = BKE_object_pose_base_array_get_unique( + vc.scene, vc.view_layer, vc.v3d, &bases_len); bool changed_multi = ED_pose_deselect_all_multi_ex( bases, bases_len, select_mode, ignore_visibility); MEM_freeN(bases); @@ -844,6 +851,7 @@ typedef enum ePose_SelectSame_Mode { static bool pose_select_same_group(bContext *C, bool extend) { + Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); bool *group_flags_array; bool *group_flags = NULL; @@ -853,7 +861,8 @@ static bool pose_select_same_group(bContext *C, bool extend) uint ob_index; uint objects_len = 0; - Object **objects = BKE_object_pose_array_get_unique(view_layer, CTX_wm_view3d(C), &objects_len); + Object **objects = BKE_object_pose_array_get_unique( + scene, view_layer, CTX_wm_view3d(C), &objects_len); for (ob_index = 0; ob_index < objects_len; ob_index++) { Object *ob = BKE_object_pose_armature_get(objects[ob_index]); @@ -947,6 +956,7 @@ static bool pose_select_same_group(bContext *C, bool extend) static bool pose_select_same_layer(bContext *C, bool extend) { + Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); int *layers_array, *layers = NULL; Object *ob_prev = NULL; @@ -954,7 +964,8 @@ static bool pose_select_same_layer(bContext *C, bool extend) bool changed = false; uint objects_len = 0; - Object **objects = BKE_object_pose_array_get_unique(view_layer, CTX_wm_view3d(C), &objects_len); + Object **objects = BKE_object_pose_array_get_unique( + scene, view_layer, CTX_wm_view3d(C), &objects_len); for (ob_index = 0; ob_index < objects_len; ob_index++) { Object *ob = objects[ob_index]; @@ -1032,6 +1043,7 @@ cleanup: static bool pose_select_same_keyingset(bContext *C, ReportList *reports, bool extend) { + Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); bool changed_multi = false; KeyingSet *ks = ANIM_scene_get_active_keyingset(CTX_data_scene(C)); @@ -1068,7 +1080,8 @@ static bool pose_select_same_keyingset(bContext *C, ReportList *reports, bool ex } uint objects_len = 0; - Object **objects = BKE_object_pose_array_get_unique(view_layer, CTX_wm_view3d(C), &objects_len); + Object **objects = BKE_object_pose_array_get_unique( + scene, view_layer, CTX_wm_view3d(C), &objects_len); for (uint ob_index = 0; ob_index < objects_len; ob_index++) { Object *ob = BKE_object_pose_armature_get(objects[ob_index]); @@ -1196,6 +1209,7 @@ void POSE_OT_select_grouped(wmOperatorType *ot) */ static int pose_select_mirror_exec(bContext *C, wmOperator *op) { + const Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); Object *ob_active = CTX_data_active_object(C); @@ -1204,7 +1218,8 @@ static int pose_select_mirror_exec(bContext *C, wmOperator *op) const bool extend = RNA_boolean_get(op->ptr, "extend"); uint objects_len = 0; - Object **objects = BKE_object_pose_array_get_unique(view_layer, CTX_wm_view3d(C), &objects_len); + Object **objects = BKE_object_pose_array_get_unique( + scene, view_layer, CTX_wm_view3d(C), &objects_len); for (uint ob_index = 0; ob_index < objects_len; ob_index++) { Object *ob = objects[ob_index]; diff --git a/source/blender/editors/armature/pose_slide.c b/source/blender/editors/armature/pose_slide.c index 3e36a0d233a..14b3451bd80 100644 --- a/source/blender/editors/armature/pose_slide.c +++ b/source/blender/editors/armature/pose_slide.c @@ -232,8 +232,11 @@ static int pose_slide_init(bContext *C, wmOperator *op, ePoseSlide_Modes mode) * and set the relevant transform flags. */ poseAnim_mapping_get(C, &pso->pfLinks); - Object **objects = BKE_view_layer_array_from_objects_in_mode_unique_data( - CTX_data_view_layer(C), CTX_wm_view3d(C), &pso->objects_len, OB_MODE_POSE); + Object **objects = BKE_view_layer_array_from_objects_in_mode_unique_data(CTX_data_scene(C), + CTX_data_view_layer(C), + CTX_wm_view3d(C), + &pso->objects_len, + OB_MODE_POSE); pso->ob_data_array = MEM_callocN(pso->objects_len * sizeof(tPoseSlideObject), "pose slide objects data"); @@ -286,8 +289,10 @@ static void pose_slide_exit(bContext *C, wmOperator *op) ED_slider_destroy(C, pso->slider); /* Hide Bone Overlay. */ - View3D *v3d = pso->area->spacedata.first; - v3d->overlay.flag = pso->overlay_flag; + if (pso->area) { + View3D *v3d = pso->area->spacedata.first; + v3d->overlay.flag = pso->overlay_flag; + } /* Free the temp pchan links and their data. */ poseAnim_mapping_free(&pso->pfLinks); @@ -2079,7 +2084,7 @@ static int pose_propagate_exec(bContext *C, wmOperator *op) } /* Updates + notifiers. */ - FOREACH_OBJECT_IN_MODE_BEGIN (view_layer, v3d, OB_ARMATURE, OB_MODE_POSE, ob) { + FOREACH_OBJECT_IN_MODE_BEGIN (scene, view_layer, v3d, OB_ARMATURE, OB_MODE_POSE, ob) { poseAnim_mapping_refresh(C, scene, ob); } FOREACH_OBJECT_IN_MODE_END; diff --git a/source/blender/editors/armature/pose_transform.c b/source/blender/editors/armature/pose_transform.c index cfc6b0b6b6e..2a23615caa3 100644 --- a/source/blender/editors/armature/pose_transform.c +++ b/source/blender/editors/armature/pose_transform.c @@ -491,13 +491,14 @@ void POSE_OT_armature_apply(wmOperatorType *ot) /* set the current pose as the restpose */ static int pose_visual_transform_apply_exec(bContext *C, wmOperator *UNUSED(op)) { + const Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); View3D *v3d = CTX_wm_view3d(C); /* Needed to ensure #bPoseChannel.pose_mat are up to date. */ CTX_data_ensure_evaluated_depsgraph(C); - FOREACH_OBJECT_IN_MODE_BEGIN (view_layer, v3d, OB_ARMATURE, OB_MODE_POSE, ob) { + FOREACH_OBJECT_IN_MODE_BEGIN (scene, view_layer, v3d, OB_ARMATURE, OB_MODE_POSE, ob) { const bArmature *arm = ob->data; int chanbase_len = BLI_listbase_count(&ob->pose->chanbase); @@ -1115,7 +1116,7 @@ static void pchan_clear_rot(bPoseChannel *pchan) } /* Clear also Bendy Bone stuff - Roll is obvious, - * but Curve X/Y stuff is also kindof rotational in nature... */ + * but Curve X/Y stuff is also kind of rotational in nature... */ pchan->roll1 = 0.0f; pchan->roll2 = 0.0f; @@ -1168,7 +1169,7 @@ static int pose_clear_transform_generic_exec(bContext *C, /* only clear relevant transforms for selected bones */ ViewLayer *view_layer = CTX_data_view_layer(C); View3D *v3d = CTX_wm_view3d(C); - FOREACH_OBJECT_IN_MODE_BEGIN (view_layer, v3d, OB_ARMATURE, OB_MODE_POSE, ob_iter) { + FOREACH_OBJECT_IN_MODE_BEGIN (scene, view_layer, v3d, OB_ARMATURE, OB_MODE_POSE, ob_iter) { /* XXX: UGLY HACK (for auto-key + clear transforms). */ Object *ob_eval = DEG_get_evaluated_object(depsgraph, ob_iter); ListBase dsources = {NULL, NULL}; @@ -1347,7 +1348,7 @@ static int pose_clear_user_transforms_exec(bContext *C, wmOperator *op) depsgraph, (float)scene->r.cfra); const bool only_select = RNA_boolean_get(op->ptr, "only_selected"); - FOREACH_OBJECT_IN_MODE_BEGIN (view_layer, v3d, OB_ARMATURE, OB_MODE_POSE, ob) { + FOREACH_OBJECT_IN_MODE_BEGIN (scene, view_layer, v3d, OB_ARMATURE, OB_MODE_POSE, ob) { if ((ob->adt) && (ob->adt->action)) { /* XXX: this is just like this to avoid contaminating anything else; * just pose values should change, so this should be fine diff --git a/source/blender/editors/armature/pose_utils.c b/source/blender/editors/armature/pose_utils.c index ea038362532..57ead6a0e65 100644 --- a/source/blender/editors/armature/pose_utils.c +++ b/source/blender/editors/armature/pose_utils.c @@ -251,7 +251,7 @@ void poseAnim_mapping_autoKeyframe(bContext *C, Scene *scene, ListBase *pfLinks, View3D *v3d = CTX_wm_view3d(C); bool skip = true; - FOREACH_OBJECT_IN_MODE_BEGIN (view_layer, v3d, OB_ARMATURE, OB_MODE_POSE, ob) { + FOREACH_OBJECT_IN_MODE_BEGIN (scene, view_layer, v3d, OB_ARMATURE, OB_MODE_POSE, ob) { ob->id.tag &= ~LIB_TAG_DOIT; ob = poseAnim_object_get(ob); @@ -299,7 +299,7 @@ void poseAnim_mapping_autoKeyframe(bContext *C, Scene *scene, ListBase *pfLinks, * - only do this if keyframes should have been added * - do not calculate unless there are paths already to update... */ - FOREACH_OBJECT_IN_MODE_BEGIN (view_layer, v3d, OB_ARMATURE, OB_MODE_POSE, ob) { + FOREACH_OBJECT_IN_MODE_BEGIN (scene, view_layer, v3d, OB_ARMATURE, OB_MODE_POSE, ob) { if (ob->id.tag & LIB_TAG_DOIT) { if (ob->pose->avs.path_bakeflag & MOTIONPATH_BAKE_HAS_PATHS) { // ED_pose_clear_paths(C, ob); /* XXX for now, don't need to clear. */ diff --git a/source/blender/editors/asset/ED_asset_handle.h b/source/blender/editors/asset/ED_asset_handle.h index b408e919f32..4a81840c40d 100644 --- a/source/blender/editors/asset/ED_asset_handle.h +++ b/source/blender/editors/asset/ED_asset_handle.h @@ -35,3 +35,16 @@ void ED_asset_handle_get_full_library_path(const struct bContext *C, #ifdef __cplusplus } #endif + +#ifdef __cplusplus + +namespace blender::ed::asset { + +/** If the ID already exists in the database, return it, otherwise add it. */ +ID *get_local_id_from_asset_or_append_and_reuse(Main &bmain, + const AssetLibraryReference &library_ref, + AssetHandle asset); + +} // namespace blender::ed::asset + +#endif diff --git a/source/blender/editors/asset/intern/asset_handle.cc b/source/blender/editors/asset/intern/asset_handle.cc index ade8b803ed3..00fffd595c0 100644 --- a/source/blender/editors/asset/intern/asset_handle.cc +++ b/source/blender/editors/asset/intern/asset_handle.cc @@ -13,6 +13,8 @@ #include "ED_asset_handle.h" #include "ED_asset_list.hh" +#include "WM_api.h" + const char *ED_asset_handle_get_name(const AssetHandle *asset) { return asset->file_data->name; @@ -52,3 +54,31 @@ void ED_asset_handle_get_full_library_path(const bContext *C, BLO_library_path_explode(asset_path.c_str(), r_full_lib_path, nullptr, nullptr); } + +namespace blender::ed::asset { + +ID *get_local_id_from_asset_or_append_and_reuse(Main &bmain, + const AssetLibraryReference &library_ref, + const AssetHandle asset) +{ + if (ID *local_id = ED_asset_handle_get_local_id(&asset)) { + return local_id; + } + + char blend_path[FILE_MAX_LIBEXTRA]; + ED_asset_handle_get_full_library_path(nullptr, &library_ref, &asset, blend_path); + const char *id_name = ED_asset_handle_get_name(&asset); + + return WM_file_append_datablock(&bmain, + nullptr, + nullptr, + nullptr, + blend_path, + ED_asset_handle_get_id_type(&asset), + id_name, + BLO_LIBLINK_APPEND_RECURSIVE | + BLO_LIBLINK_APPEND_ASSET_DATA_CLEAR | + BLO_LIBLINK_APPEND_LOCAL_ID_REUSE); +} + +} // namespace blender::ed::asset diff --git a/source/blender/editors/asset/intern/asset_indexer.cc b/source/blender/editors/asset/intern/asset_indexer.cc index 3cc3638c299..cc06fa80429 100644 --- a/source/blender/editors/asset/intern/asset_indexer.cc +++ b/source/blender/editors/asset/intern/asset_indexer.cc @@ -351,7 +351,7 @@ static void init_indexer_entry_from_value(FileIndexerEntry &indexer_entry, { indexer_entry.idcode = entry.get_idcode(); - const std::string &name = entry.get_name(); + const std::string name = entry.get_name(); BLI_strncpy( indexer_entry.datablock_info.name, name.c_str(), sizeof(indexer_entry.datablock_info.name)); @@ -359,19 +359,19 @@ static void init_indexer_entry_from_value(FileIndexerEntry &indexer_entry, indexer_entry.datablock_info.asset_data = asset_data; if (entry.has_description()) { - const std::string &description = entry.get_description(); - char *description_c_str = static_cast<char *>(MEM_mallocN(description.length() + 1, __func__)); - BLI_strncpy(description_c_str, description.c_str(), description.length() + 1); + const StringRefNull description = entry.get_description(); + char *description_c_str = static_cast<char *>(MEM_mallocN(description.size() + 1, __func__)); + BLI_strncpy(description_c_str, description.c_str(), description.size() + 1); asset_data->description = description_c_str; } if (entry.has_author()) { - const std::string &author = entry.get_author(); - char *author_c_str = static_cast<char *>(MEM_mallocN(author.length() + 1, __func__)); - BLI_strncpy(author_c_str, author.c_str(), author.length() + 1); + const StringRefNull author = entry.get_author(); + char *author_c_str = static_cast<char *>(MEM_mallocN(author.size() + 1, __func__)); + BLI_strncpy(author_c_str, author.c_str(), author.size() + 1); asset_data->author = author_c_str; } - const std::string &catalog_name = entry.get_catalog_name(); + const StringRefNull catalog_name = entry.get_catalog_name(); BLI_strncpy(asset_data->catalog_simple_name, catalog_name.c_str(), sizeof(asset_data->catalog_simple_name)); diff --git a/source/blender/editors/asset/intern/asset_ops.cc b/source/blender/editors/asset/intern/asset_ops.cc index 05d0b7d0af4..ba7b56db3ec 100644 --- a/source/blender/editors/asset/intern/asset_ops.cc +++ b/source/blender/editors/asset/intern/asset_ops.cc @@ -781,6 +781,7 @@ static const EnumPropertyItem *rna_asset_library_reference_itemf(bContext *UNUSE const EnumPropertyItem *items = ED_asset_library_reference_to_rna_enum_itemf(false); if (!items) { *r_free = false; + return nullptr; } *r_free = true; diff --git a/source/blender/editors/curve/CMakeLists.txt b/source/blender/editors/curve/CMakeLists.txt index 791e28de694..0cedc05981b 100644 --- a/source/blender/editors/curve/CMakeLists.txt +++ b/source/blender/editors/curve/CMakeLists.txt @@ -11,7 +11,6 @@ set(INC ../../makesrna ../../windowmanager ../../../../intern/clog - ../../../../intern/glew-mx ../../../../intern/guardedalloc ../../../../extern/curve_fit_nd # RNA_prototypes.h diff --git a/source/blender/editors/curve/editcurve.c b/source/blender/editors/curve/editcurve.c index 164336c4b22..5e810d93115 100644 --- a/source/blender/editors/curve/editcurve.c +++ b/source/blender/editors/curve/editcurve.c @@ -47,7 +47,6 @@ #include "ED_select_utils.h" #include "ED_transform.h" #include "ED_transform_snap_object_context.h" -#include "ED_types.h" #include "ED_view3d.h" #include "curve_intern.h" @@ -1255,7 +1254,7 @@ void ED_curve_editnurb_load(Main *bmain, Object *obedit) } /* We have to pass also new copied nurbs, since we want to restore original curve - * (without edited shapekey) on obdata, but *not* on editcurve itself + * (without edited shape-key) on obdata, but *not* on editcurve itself * (ED_curve_editnurb_load call does not always implies freeing * of editcurve, e.g. when called to generate render data). */ calc_shapeKeys(obedit, &newnurb); @@ -1299,15 +1298,15 @@ void ED_curve_editnurb_make(Object *obedit) BLI_addtail(&editnurb->nurbs, newnu); } - /* animation could be added in editmode even if there was no animdata in - * object mode hence we always need CVs index be created */ + /* Animation could be added in edit-mode even if there was no animdata in + * object mode hence we always need CVs index be created. */ init_editNurb_keyIndex(editnurb, &cu->nurb); if (actkey) { editnurb->shapenr = obedit->shapenr; - /* Apply shapekey to new nurbs of editnurb, not those of original curve + /* Apply shape-key to new nurbs of editnurb, not those of original curve * (and *after* we generated keyIndex), else we do not have valid 'original' data - * to properly restore curve when leaving editmode. */ + * to properly restore curve when leaving edit-mode. */ BKE_keyblock_convert_to_curve(actkey, cu, &editnurb->nurbs); } } @@ -1344,7 +1343,7 @@ static int separate_exec(bContext *C, wmOperator *op) uint bases_len = 0; Base **bases = BKE_view_layer_array_from_bases_in_edit_mode_unique_data( - view_layer, CTX_wm_view3d(C), &bases_len); + scene, view_layer, CTX_wm_view3d(C), &bases_len); for (uint b_index = 0; b_index < bases_len; b_index++) { Base *oldbase = bases[b_index]; Base *newbase; @@ -1469,6 +1468,7 @@ void CURVE_OT_separate(wmOperatorType *ot) static int curve_split_exec(bContext *C, wmOperator *op) { Main *bmain = CTX_data_main(C); + const Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); View3D *v3d = CTX_wm_view3d(C); bool changed = false; @@ -1476,7 +1476,7 @@ static int curve_split_exec(bContext *C, wmOperator *op) uint objects_len; Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data( - view_layer, CTX_wm_view3d(C), &objects_len); + scene, view_layer, CTX_wm_view3d(C), &objects_len); for (uint ob_index = 0; ob_index < objects_len; ob_index++) { Object *obedit = objects[ob_index]; Curve *cu = obedit->data; @@ -1989,7 +1989,7 @@ static int sel_to_copy_ints(const BPoint *bp, } if (selected_leg_count && /* Prevents leading and trailing unselected legs if all selected. - * Unless it is extrusion from point or curve.*/ + * Unless it is extrusion from point or curve. */ (selected_leg_count < max_j || max_j == 1)) { /* Prepend unselected leg if more than one leg selected at the starting edge. * max_j == 1 handles extrusion from point to curve and from curve to surface cases. */ @@ -2088,7 +2088,7 @@ bool ed_editnurb_extrude_flag(EditNurb *editnurb, const uint8_t flag) const int copy_from = intvls_u[i - 1]; const int copy_to = intvls_u[i]; const int copy_count = copy_to - copy_from + 1; - const bool sel_status = selected_u || selected_v ? SELECT : DESELECT; + const bool sel_status = selected_u || selected_v ? true : false; ED_curve_bpcpy(editnurb, new_bp_u_v, old_bp_v + copy_from, copy_count); select_bpoints(new_bp_u_v, 1, copy_count, sel_status, flag, HIDDEN); new_bp_u_v += copy_count; @@ -2154,7 +2154,7 @@ static void adduplicateflagNurb( starta = a; while ((bezt->f1 & flag) || (bezt->f2 & flag) || (bezt->f3 & flag)) { if (!split) { - select_beztriple(bezt, DESELECT, flag, HIDDEN); + select_beztriple(bezt, false, flag, HIDDEN); } enda = a; if (a >= nu->pntsu - 1) { @@ -2194,7 +2194,7 @@ static void adduplicateflagNurb( } for (b = 0, bezt1 = newnu->bezt; b < newnu->pntsu; b++, bezt1++) { - select_beztriple(bezt1, SELECT, flag, HIDDEN); + select_beztriple(bezt1, true, flag, HIDDEN); } BLI_addtail(newnurb, newnu); @@ -2212,7 +2212,7 @@ static void adduplicateflagNurb( newnu->flagu &= ~CU_NURB_CYCLIC; for (b = 0, bezt1 = newnu->bezt; b < newnu->pntsu; b++, bezt1++) { - select_beztriple(bezt1, SELECT, flag, HIDDEN); + select_beztriple(bezt1, true, flag, HIDDEN); } BLI_addtail(newnurb, newnu); @@ -2224,7 +2224,7 @@ static void adduplicateflagNurb( starta = a; while (bp->f1 & flag) { if (!split) { - select_bpoint(bp, DESELECT, flag, HIDDEN); + select_bpoint(bp, false, flag, HIDDEN); } enda = a; if (a >= nu->pntsu - 1) { @@ -2264,7 +2264,7 @@ static void adduplicateflagNurb( } for (b = 0, bp1 = newnu->bp; b < newnu->pntsu; b++, bp1++) { - select_bpoint(bp1, SELECT, flag, HIDDEN); + select_bpoint(bp1, true, flag, HIDDEN); } BLI_addtail(newnurb, newnu); @@ -2282,7 +2282,7 @@ static void adduplicateflagNurb( newnu->flagu &= ~CU_NURB_CYCLIC; for (b = 0, bp1 = newnu->bp; b < newnu->pntsu; b++, bp1++) { - select_bpoint(bp1, SELECT, flag, HIDDEN); + select_bpoint(bp1, true, flag, HIDDEN); } BLI_addtail(newnurb, newnu); @@ -2502,7 +2502,7 @@ static void adduplicateflagNurb( for (b = 0, bp1 = nu->bp; b < nu->pntsu * nu->pntsv; b++, bp1++) { bp1->f1 &= ~SURF_SEEN; if (!split) { - select_bpoint(bp1, DESELECT, flag, HIDDEN); + select_bpoint(bp1, false, flag, HIDDEN); } } } @@ -2546,12 +2546,13 @@ static void adduplicateflagNurb( static int switch_direction_exec(bContext *C, wmOperator *UNUSED(op)) { Main *bmain = CTX_data_main(C); + const Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); View3D *v3d = CTX_wm_view3d(C); uint objects_len; Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data( - view_layer, CTX_wm_view3d(C), &objects_len); + scene, view_layer, CTX_wm_view3d(C), &objects_len); for (uint ob_index = 0; ob_index < objects_len; ob_index++) { Object *obedit = objects[ob_index]; Curve *cu = obedit->data; @@ -2607,10 +2608,11 @@ void CURVE_OT_switch_direction(wmOperatorType *ot) static int set_goal_weight_exec(bContext *C, wmOperator *op) { + const Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); uint objects_len; Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data( - view_layer, CTX_wm_view3d(C), &objects_len); + scene, view_layer, CTX_wm_view3d(C), &objects_len); for (uint ob_index = 0; ob_index < objects_len; ob_index++) { Object *obedit = objects[ob_index]; @@ -2673,10 +2675,11 @@ void CURVE_OT_spline_weight_set(wmOperatorType *ot) static int set_radius_exec(bContext *C, wmOperator *op) { + const Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); uint objects_len; Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data( - view_layer, CTX_wm_view3d(C), &objects_len); + scene, view_layer, CTX_wm_view3d(C), &objects_len); for (uint ob_index = 0; ob_index < objects_len; ob_index++) { Object *obedit = objects[ob_index]; @@ -2784,10 +2787,11 @@ static void smooth_single_bp(BPoint *bp, static int smooth_exec(bContext *C, wmOperator *UNUSED(op)) { const float factor = 1.0f / 6.0f; + const Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); uint objects_len; Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data( - view_layer, CTX_wm_view3d(C), &objects_len); + scene, view_layer, CTX_wm_view3d(C), &objects_len); for (uint ob_index = 0; ob_index < objects_len; ob_index++) { Object *obedit = objects[ob_index]; @@ -3080,10 +3084,11 @@ static void curve_smooth_value(ListBase *editnurb, const int bezt_offsetof, cons static int curve_smooth_weight_exec(bContext *C, wmOperator *UNUSED(op)) { + const Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); uint objects_len; Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data( - view_layer, CTX_wm_view3d(C), &objects_len); + scene, view_layer, CTX_wm_view3d(C), &objects_len); for (uint ob_index = 0; ob_index < objects_len; ob_index++) { Object *obedit = objects[ob_index]; @@ -3123,10 +3128,11 @@ void CURVE_OT_smooth_weight(wmOperatorType *ot) static int curve_smooth_radius_exec(bContext *C, wmOperator *UNUSED(op)) { + const Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); uint objects_len; Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data( - view_layer, CTX_wm_view3d(C), &objects_len); + scene, view_layer, CTX_wm_view3d(C), &objects_len); for (uint ob_index = 0; ob_index < objects_len; ob_index++) { Object *obedit = objects[ob_index]; @@ -3166,10 +3172,11 @@ void CURVE_OT_smooth_radius(wmOperatorType *ot) static int curve_smooth_tilt_exec(bContext *C, wmOperator *UNUSED(op)) { + const Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); uint objects_len; Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data( - view_layer, CTX_wm_view3d(C), &objects_len); + scene, view_layer, CTX_wm_view3d(C), &objects_len); for (uint ob_index = 0; ob_index < objects_len; ob_index++) { Object *obedit = objects[ob_index]; @@ -3209,6 +3216,7 @@ void CURVE_OT_smooth_tilt(wmOperatorType *ot) static int hide_exec(bContext *C, wmOperator *op) { + const Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); View3D *v3d = CTX_wm_view3d(C); @@ -3216,7 +3224,7 @@ static int hide_exec(bContext *C, wmOperator *op) uint objects_len; Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data( - view_layer, CTX_wm_view3d(C), &objects_len); + scene, view_layer, CTX_wm_view3d(C), &objects_len); for (uint ob_index = 0; ob_index < objects_len; ob_index++) { Object *obedit = objects[ob_index]; Curve *cu = obedit->data; @@ -3237,11 +3245,11 @@ static int hide_exec(bContext *C, wmOperator *op) sel = 0; while (a--) { if (invert == 0 && BEZT_ISSEL_ANY_HIDDENHANDLES(v3d, bezt)) { - select_beztriple(bezt, DESELECT, SELECT, HIDDEN); + select_beztriple(bezt, false, SELECT, HIDDEN); bezt->hide = 1; } else if (invert && !BEZT_ISSEL_ANY_HIDDENHANDLES(v3d, bezt)) { - select_beztriple(bezt, DESELECT, SELECT, HIDDEN); + select_beztriple(bezt, false, SELECT, HIDDEN); bezt->hide = 1; } if (bezt->hide) { @@ -3259,11 +3267,11 @@ static int hide_exec(bContext *C, wmOperator *op) sel = 0; while (a--) { if (invert == 0 && (bp->f1 & SELECT)) { - select_bpoint(bp, DESELECT, SELECT, HIDDEN); + select_bpoint(bp, false, SELECT, HIDDEN); bp->hide = 1; } else if (invert && (bp->f1 & SELECT) == 0) { - select_bpoint(bp, DESELECT, SELECT, HIDDEN); + select_bpoint(bp, false, SELECT, HIDDEN); bp->hide = 1; } if (bp->hide) { @@ -3311,13 +3319,14 @@ void CURVE_OT_hide(wmOperatorType *ot) static int reveal_exec(bContext *C, wmOperator *op) { + const 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_multi = false; uint objects_len; Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data( - view_layer, CTX_wm_view3d(C), &objects_len); + scene, view_layer, CTX_wm_view3d(C), &objects_len); for (uint ob_index = 0; ob_index < objects_len; ob_index++) { Object *obedit = objects[ob_index]; ListBase *editnurb = object_editcurve_get(obedit); @@ -3790,12 +3799,13 @@ static int subdivide_exec(bContext *C, wmOperator *op) const int number_cuts = RNA_int_get(op->ptr, "number_cuts"); Main *bmain = CTX_data_main(C); + const Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); View3D *v3d = CTX_wm_view3d(C); uint objects_len = 0; Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data( - view_layer, CTX_wm_view3d(C), &objects_len); + scene, view_layer, CTX_wm_view3d(C), &objects_len); for (uint ob_index = 0; ob_index < objects_len; ob_index++) { Object *obedit = objects[ob_index]; Curve *cu = obedit->data; @@ -3848,10 +3858,11 @@ void CURVE_OT_subdivide(wmOperatorType *ot) static int set_spline_type_exec(bContext *C, wmOperator *op) { + const Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); uint objects_len; Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data( - view_layer, CTX_wm_view3d(C), &objects_len); + scene, view_layer, CTX_wm_view3d(C), &objects_len); int ret_value = OPERATOR_CANCELLED; for (uint ob_index = 0; ob_index < objects_len; ob_index++) { @@ -3941,13 +3952,14 @@ void CURVE_OT_spline_type_set(wmOperatorType *ot) static int set_handle_type_exec(bContext *C, wmOperator *op) { + const Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); View3D *v3d = CTX_wm_view3d(C); const int handle_type = RNA_enum_get(op->ptr, "type"); uint objects_len; Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data( - view_layer, CTX_wm_view3d(C), &objects_len); + scene, view_layer, CTX_wm_view3d(C), &objects_len); for (uint ob_index = 0; ob_index < objects_len; ob_index++) { Object *obedit = objects[ob_index]; Curve *cu = obedit->data; @@ -4003,6 +4015,7 @@ void CURVE_OT_handle_type_set(wmOperatorType *ot) static int curve_normals_make_consistent_exec(bContext *C, wmOperator *op) { + const Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); View3D *v3d = CTX_wm_view3d(C); @@ -4010,7 +4023,7 @@ static int curve_normals_make_consistent_exec(bContext *C, wmOperator *op) uint objects_len; Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data( - view_layer, CTX_wm_view3d(C), &objects_len); + scene, view_layer, CTX_wm_view3d(C), &objects_len); for (uint ob_index = 0; ob_index < objects_len; ob_index++) { Object *obedit = objects[ob_index]; Curve *cu = obedit->data; @@ -4353,7 +4366,7 @@ static bool merge_2_nurb(Curve *cu, ListBase *editnurb, Nurb *nu1, Nurb *nu2) keyIndex_updateBP(cu->editnurb, bp1, bp, 1); *bp = *bp1; bp1++; - select_bpoint(bp, SELECT, SELECT, HIDDEN); + select_bpoint(bp, true, SELECT, HIDDEN); } else { keyIndex_updateBP(cu->editnurb, bp2, bp, 1); @@ -4443,6 +4456,7 @@ static int merge_nurb(View3D *v3d, Object *obedit) static int make_segment_exec(bContext *C, wmOperator *op) { Main *bmain = CTX_data_main(C); + const Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); View3D *v3d = CTX_wm_view3d(C); @@ -4456,7 +4470,7 @@ static int make_segment_exec(bContext *C, wmOperator *op) uint objects_len; Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data( - view_layer, CTX_wm_view3d(C), &objects_len); + scene, view_layer, CTX_wm_view3d(C), &objects_len); for (uint ob_index = 0; ob_index < objects_len; ob_index++) { Object *obedit = objects[ob_index]; Curve *cu = obedit->data; @@ -4780,7 +4794,7 @@ bool ED_curve_editnurb_select_pick(bContext *C, /* Deselect everything. */ uint objects_len = 0; Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data( - vc.view_layer, vc.v3d, &objects_len); + vc.scene, vc.view_layer, vc.v3d, &objects_len); for (uint ob_index = 0; ob_index < objects_len; ob_index++) { Object *ob_iter = objects[ob_index]; @@ -4808,7 +4822,7 @@ bool ED_curve_editnurb_select_pick(bContext *C, bezt->f2 |= SELECT; } else { - select_beztriple(bezt, SELECT, SELECT, HIDDEN); + select_beztriple(bezt, true, SELECT, HIDDEN); } } else { @@ -4822,7 +4836,7 @@ bool ED_curve_editnurb_select_pick(bContext *C, BKE_curve_nurb_vert_active_set(cu, nu, bezt); } else { - select_bpoint(bp, SELECT, SELECT, HIDDEN); + select_bpoint(bp, true, SELECT, HIDDEN); BKE_curve_nurb_vert_active_set(cu, nu, bp); } break; @@ -4834,7 +4848,7 @@ bool ED_curve_editnurb_select_pick(bContext *C, bezt->f2 &= ~SELECT; } else { - select_beztriple(bezt, DESELECT, SELECT, HIDDEN); + select_beztriple(bezt, false, SELECT, HIDDEN); } if (bezt == vert) { cu->actvert = CU_ACT_NONE; @@ -4848,7 +4862,7 @@ bool ED_curve_editnurb_select_pick(bContext *C, } } else { - select_bpoint(bp, DESELECT, SELECT, HIDDEN); + select_bpoint(bp, false, SELECT, HIDDEN); if (bp == vert) { cu->actvert = CU_ACT_NONE; } @@ -4863,7 +4877,7 @@ bool ED_curve_editnurb_select_pick(bContext *C, bezt->f2 &= ~SELECT; } else { - select_beztriple(bezt, DESELECT, SELECT, HIDDEN); + select_beztriple(bezt, false, SELECT, HIDDEN); } if (bezt == vert) { cu->actvert = CU_ACT_NONE; @@ -4874,7 +4888,7 @@ bool ED_curve_editnurb_select_pick(bContext *C, bezt->f2 |= SELECT; } else { - select_beztriple(bezt, SELECT, SELECT, HIDDEN); + select_beztriple(bezt, true, SELECT, HIDDEN); } BKE_curve_nurb_vert_active_set(cu, nu, bezt); } @@ -4888,13 +4902,13 @@ bool ED_curve_editnurb_select_pick(bContext *C, } else { if (bp->f1 & SELECT) { - select_bpoint(bp, DESELECT, SELECT, HIDDEN); + select_bpoint(bp, false, SELECT, HIDDEN); if (bp == vert) { cu->actvert = CU_ACT_NONE; } } else { - select_bpoint(bp, SELECT, SELECT, HIDDEN); + select_bpoint(bp, true, SELECT, HIDDEN); BKE_curve_nurb_vert_active_set(cu, nu, bp); } } @@ -4910,7 +4924,7 @@ bool ED_curve_editnurb_select_pick(bContext *C, bezt->f2 |= SELECT; } else { - select_beztriple(bezt, SELECT, SELECT, HIDDEN); + select_beztriple(bezt, true, SELECT, HIDDEN); } } else { @@ -4924,7 +4938,7 @@ bool ED_curve_editnurb_select_pick(bContext *C, BKE_curve_nurb_vert_active_set(cu, nu, bezt); } else { - select_bpoint(bp, SELECT, SELECT, HIDDEN); + select_bpoint(bp, true, SELECT, HIDDEN); BKE_curve_nurb_vert_active_set(cu, nu, bp); } break; @@ -4946,7 +4960,8 @@ bool ED_curve_editnurb_select_pick(bContext *C, WM_event_add_notifier(C, NC_MATERIAL | ND_SHADING_LINKS, NULL); } - if (vc.view_layer->basact != basact) { + BKE_view_layer_synced_ensure(vc.scene, vc.view_layer); + if (BKE_view_layer_active_base_get(vc.view_layer) != basact) { ED_object_base_activate(C, basact); } @@ -5047,6 +5062,7 @@ bool ed_editnurb_spin( static int spin_exec(bContext *C, wmOperator *op) { Main *bmain = CTX_data_main(C); + const Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); View3D *v3d = CTX_wm_view3d(C); RegionView3D *rv3d = ED_view3d_context_rv3d(C); @@ -5066,7 +5082,7 @@ static int spin_exec(bContext *C, wmOperator *op) uint objects_len; Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data( - view_layer, CTX_wm_view3d(C), &objects_len); + scene, view_layer, CTX_wm_view3d(C), &objects_len); for (uint ob_index = 0; ob_index < objects_len; ob_index++) { Object *obedit = objects[ob_index]; Curve *cu = (Curve *)obedit->data; @@ -5705,12 +5721,13 @@ void CURVE_OT_vertex_add(wmOperatorType *ot) static int curve_extrude_exec(bContext *C, wmOperator *UNUSED(op)) { Main *bmain = CTX_data_main(C); + const Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); View3D *v3d = CTX_wm_view3d(C); uint objects_len; Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data( - view_layer, CTX_wm_view3d(C), &objects_len); + scene, view_layer, CTX_wm_view3d(C), &objects_len); for (uint ob_index = 0; ob_index < objects_len; ob_index++) { Object *obedit = objects[ob_index]; Curve *cu = obedit->data; @@ -5847,12 +5864,13 @@ static int toggle_cyclic_exec(bContext *C, wmOperator *op) { const int direction = RNA_enum_get(op->ptr, "direction"); View3D *v3d = CTX_wm_view3d(C); + const Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); bool changed_multi = false; uint objects_len; Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data( - view_layer, CTX_wm_view3d(C), &objects_len); + scene, view_layer, CTX_wm_view3d(C), &objects_len); for (uint ob_index = 0; ob_index < objects_len; ob_index++) { Object *obedit = objects[ob_index]; Curve *cu = obedit->data; @@ -5935,6 +5953,7 @@ void CURVE_OT_cyclic_toggle(wmOperatorType *ot) static int duplicate_exec(bContext *C, wmOperator *op) { + const Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); View3D *v3d = CTX_wm_view3d(C); @@ -5943,7 +5962,7 @@ static int duplicate_exec(bContext *C, wmOperator *op) uint objects_len = 0; Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data( - view_layer, CTX_wm_view3d(C), &objects_len); + scene, view_layer, CTX_wm_view3d(C), &objects_len); for (uint ob_index = 0; ob_index < objects_len; ob_index++) { Object *obedit = objects[ob_index]; Curve *cu = obedit->data; @@ -6407,7 +6426,7 @@ static bool curve_delete_segments(Object *obedit, View3D *v3d, const bool split) if (split) { /* deselect for split operator */ for (b = 0, bezt1 = nu->bezt; b < nu->pntsu; b++, bezt1++) { - select_beztriple(bezt1, DESELECT, SELECT, true); + select_beztriple(bezt1, false, SELECT, true); } } @@ -6417,7 +6436,7 @@ static bool curve_delete_segments(Object *obedit, View3D *v3d, const bool split) if (split) { /* deselect for split operator */ for (b = 0, bp1 = nu->bp; b < nu->pntsu * nu->pntsv; b++, bp1++) { - select_bpoint(bp1, DESELECT, SELECT, HIDDEN); + select_bpoint(bp1, false, SELECT, HIDDEN); } } @@ -6443,10 +6462,11 @@ static int curve_delete_exec(bContext *C, wmOperator *op) Main *bmain = CTX_data_main(C); View3D *v3d = CTX_wm_view3d(C); eCurveElem_Types type = RNA_enum_get(op->ptr, "type"); + const Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); uint objects_len = 0; Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data( - view_layer, CTX_wm_view3d(C), &objects_len); + scene, view_layer, CTX_wm_view3d(C), &objects_len); bool changed_multi = false; for (uint ob_index = 0; ob_index < objects_len; ob_index++) { @@ -6619,12 +6639,13 @@ void ed_dissolve_bez_segment(BezTriple *bezt_prev, static int curve_dissolve_exec(bContext *C, wmOperator *UNUSED(op)) { Main *bmain = CTX_data_main(C); + const Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); View3D *v3d = CTX_wm_view3d(C); uint objects_len; Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data( - view_layer, CTX_wm_view3d(C), &objects_len); + scene, view_layer, CTX_wm_view3d(C), &objects_len); for (uint ob_index = 0; ob_index < objects_len; ob_index++) { Object *obedit = objects[ob_index]; Curve *cu = (Curve *)obedit->data; @@ -6713,10 +6734,11 @@ static int curve_decimate_exec(bContext *C, wmOperator *op) float ratio = RNA_float_get(op->ptr, "ratio"); bool all_supported_multi = true; + const Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); uint objects_len = 0; Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data( - view_layer, CTX_wm_view3d(C), &objects_len); + scene, view_layer, CTX_wm_view3d(C), &objects_len); for (uint ob_index = 0; ob_index < objects_len; ob_index++) { Object *obedit = objects[ob_index]; Curve *cu = (Curve *)obedit->data; @@ -6793,11 +6815,12 @@ void CURVE_OT_decimate(wmOperatorType *ot) static int shade_smooth_exec(bContext *C, wmOperator *op) { View3D *v3d = CTX_wm_view3d(C); + const Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); int clear = (STREQ(op->idname, "CURVE_OT_shade_flat")); uint objects_len; Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data( - view_layer, CTX_wm_view3d(C), &objects_len); + scene, view_layer, CTX_wm_view3d(C), &objects_len); int ret_value = OPERATOR_CANCELLED; for (uint ob_index = 0; ob_index < objects_len; ob_index++) { @@ -6987,12 +7010,13 @@ int ED_curve_join_objects_exec(bContext *C, wmOperator *op) static int clear_tilt_exec(bContext *C, wmOperator *UNUSED(op)) { + const Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); View3D *v3d = CTX_wm_view3d(C); uint objects_len; Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data( - view_layer, CTX_wm_view3d(C), &objects_len); + scene, view_layer, CTX_wm_view3d(C), &objects_len); for (uint ob_index = 0; ob_index < objects_len; ob_index++) { Object *obedit = objects[ob_index]; Curve *cu = obedit->data; diff --git a/source/blender/editors/curve/editcurve_add.c b/source/blender/editors/curve/editcurve_add.c index ee6376ca95f..f2cc48049d7 100644 --- a/source/blender/editors/curve/editcurve_add.c +++ b/source/blender/editors/curve/editcurve_add.c @@ -18,6 +18,7 @@ #include "BKE_context.h" #include "BKE_curve.h" +#include "BKE_layer.h" #include "DEG_depsgraph.h" @@ -495,7 +496,8 @@ static int curvesurf_prim_add(bContext *C, wmOperator *op, int type, int isSurf) struct Main *bmain = CTX_data_main(C); Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); - Object *obedit = OBEDIT_FROM_VIEW_LAYER(view_layer); + BKE_view_layer_synced_ensure(scene, view_layer); + Object *obedit = BKE_view_layer_edit_object_get(view_layer); ListBase *editnurb; Nurb *nu; bool newob = false; diff --git a/source/blender/editors/curve/editcurve_pen.c b/source/blender/editors/curve/editcurve_pen.c index 27f4e4fca61..f71173f951e 100644 --- a/source/blender/editors/curve/editcurve_pen.c +++ b/source/blender/editors/curve/editcurve_pen.c @@ -1366,12 +1366,10 @@ static bool make_cyclic_if_endpoints(ViewContext *vc, BPoint *sel_bp) { if (sel_bezt || (sel_bp && sel_nu->pntsu > 2)) { - const bool is_bezt_endpoint = (sel_nu->type == CU_BEZIER && - (sel_bezt == sel_nu->bezt || - sel_bezt == sel_nu->bezt + sel_nu->pntsu - 1)); - const bool is_bp_endpoint = (sel_nu->type != CU_BEZIER && - (sel_bp == sel_nu->bp || - sel_bp == sel_nu->bp + sel_nu->pntsu - 1)); + const bool is_bezt_endpoint = ((sel_nu->type == CU_BEZIER) && + ELEM(sel_bezt, sel_nu->bezt, sel_nu->bezt + sel_nu->pntsu - 1)); + const bool is_bp_endpoint = ((sel_nu->type != CU_BEZIER) && + ELEM(sel_bp, sel_nu->bp, sel_nu->bp + sel_nu->pntsu - 1)); if (!(is_bezt_endpoint || is_bp_endpoint)) { return false; } @@ -1388,9 +1386,8 @@ static bool make_cyclic_if_endpoints(ViewContext *vc, if (nu == sel_nu && ((nu->type == CU_BEZIER && bezt != sel_bezt && - (bezt == nu->bezt || bezt == nu->bezt + nu->pntsu - 1) && bezt_idx == 1) || - (nu->type != CU_BEZIER && bp != sel_bp && - (bp == nu->bp || bp == nu->bp + nu->pntsu - 1)))) { + ELEM(bezt, nu->bezt, nu->bezt + nu->pntsu - 1) && bezt_idx == 1) || + (nu->type != CU_BEZIER && bp != sel_bp && ELEM(bp, nu->bp, nu->bp + nu->pntsu - 1)))) { View3D *v3d = vc->v3d; ListBase *nurbs = object_editcurve_get(vc->obedit); curve_toggle_cyclic(v3d, nurbs, 0); @@ -1532,7 +1529,7 @@ wmKeyMap *curve_pen_modal_keymap(wmKeyConfig *keyconf) wmKeyMap *keymap = WM_modalkeymap_find(keyconf, "Curve Pen Modal Map"); - /* This function is called for each spacetype, only needs to add map once */ + /* This function is called for each space-type, only needs to add map once. */ if (keymap && keymap->modal_items) { return NULL; } diff --git a/source/blender/editors/curve/editcurve_query.c b/source/blender/editors/curve/editcurve_query.c index a08dbbe6132..56268baf1f1 100644 --- a/source/blender/editors/curve/editcurve_query.c +++ b/source/blender/editors/curve/editcurve_query.c @@ -118,7 +118,7 @@ bool ED_curve_pick_vert_ex(ViewContext *vc, uint bases_len; Base **bases = BKE_view_layer_array_from_bases_in_edit_mode_unique_data( - vc->view_layer, vc->v3d, &bases_len); + vc->scene, vc->view_layer, vc->v3d, &bases_len); for (uint base_index = 0; base_index < bases_len; base_index++) { Base *base = bases[base_index]; data.is_changed = false; diff --git a/source/blender/editors/curve/editcurve_select.c b/source/blender/editors/curve/editcurve_select.c index 5a1777b7097..4015ae545da 100644 --- a/source/blender/editors/curve/editcurve_select.c +++ b/source/blender/editors/curve/editcurve_select.c @@ -30,7 +30,6 @@ #include "ED_object.h" #include "ED_screen.h" #include "ED_select_utils.h" -#include "ED_types.h" #include "ED_view3d.h" #include "curve_intern.h" @@ -47,7 +46,7 @@ bool select_beztriple(BezTriple *bezt, bool selstatus, uint8_t flag, eVisible_Types hidden) { if ((bezt->hide == 0) || (hidden == HIDDEN)) { - if (selstatus == SELECT) { /* selects */ + if (selstatus) { /* selects */ bezt->f1 |= flag; bezt->f2 |= flag; bezt->f3 |= flag; @@ -66,7 +65,7 @@ bool select_beztriple(BezTriple *bezt, bool selstatus, uint8_t flag, eVisible_Ty bool select_bpoint(BPoint *bp, bool selstatus, uint8_t flag, bool hidden) { if ((bp->hide == 0) || (hidden == 1)) { - if (selstatus == SELECT) { + if (selstatus) { bp->f1 |= flag; return true; } @@ -80,17 +79,17 @@ bool select_bpoint(BPoint *bp, bool selstatus, uint8_t flag, bool hidden) static bool swap_selection_beztriple(BezTriple *bezt) { if (bezt->f2 & SELECT) { - return select_beztriple(bezt, DESELECT, SELECT, VISIBLE); + return select_beztriple(bezt, false, SELECT, VISIBLE); } - return select_beztriple(bezt, SELECT, SELECT, VISIBLE); + return select_beztriple(bezt, true, SELECT, VISIBLE); } static bool swap_selection_bpoint(BPoint *bp) { if (bp->f1 & SELECT) { - return select_bpoint(bp, DESELECT, SELECT, VISIBLE); + return select_bpoint(bp, false, SELECT, VISIBLE); } - return select_bpoint(bp, SELECT, SELECT, VISIBLE); + return select_bpoint(bp, true, SELECT, VISIBLE); } bool ED_curve_nurb_select_check(const View3D *v3d, const Nurb *nu) @@ -260,7 +259,7 @@ bool ED_curve_deselect_all_multi(struct bContext *C) ED_view3d_viewcontext_init(C, &vc, depsgraph); uint bases_len = 0; Base **bases = BKE_view_layer_array_from_bases_in_edit_mode_unique_data( - vc.view_layer, vc.v3d, &bases_len); + vc.scene, vc.view_layer, vc.v3d, &bases_len); bool changed_multi = ED_curve_deselect_all_multi_ex(bases, bases_len); MEM_freeN(bases); return changed_multi; @@ -336,9 +335,9 @@ static void select_adjacent_cp(ListBase *editnurb, break; } if ((lastsel == false) && (bezt->hide == 0) && - ((bezt->f2 & SELECT) || (selstatus == DESELECT))) { + ((bezt->f2 & SELECT) || (selstatus == false))) { bezt += next; - if (!(bezt->f2 & SELECT) || (selstatus == DESELECT)) { + if (!(bezt->f2 & SELECT) || (selstatus == false)) { bool sel = select_beztriple(bezt, selstatus, SELECT, VISIBLE); if (sel && !cont) { lastsel = true; @@ -363,10 +362,9 @@ static void select_adjacent_cp(ListBase *editnurb, if (a - abs(next) < 0) { break; } - if ((lastsel == false) && (bp->hide == 0) && - ((bp->f1 & SELECT) || (selstatus == DESELECT))) { + if ((lastsel == false) && (bp->hide == 0) && ((bp->f1 & SELECT) || (selstatus == false))) { bp += next; - if (!(bp->f1 & SELECT) || (selstatus == DESELECT)) { + if (!(bp->f1 & SELECT) || (selstatus == false)) { bool sel = select_bpoint(bp, selstatus, SELECT, VISIBLE); if (sel && !cont) { lastsel = true; @@ -470,14 +468,15 @@ static void selectend_nurb(Object *obedit, eEndPoint_Types selfirst, bool doswap static int de_select_first_exec(bContext *C, wmOperator *UNUSED(op)) { + const Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); uint objects_len = 0; Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data( - view_layer, CTX_wm_view3d(C), &objects_len); + scene, view_layer, CTX_wm_view3d(C), &objects_len); for (uint ob_index = 0; ob_index < objects_len; ob_index++) { Object *obedit = objects[ob_index]; - selectend_nurb(obedit, FIRST, true, DESELECT); + selectend_nurb(obedit, FIRST, true, false); DEG_id_tag_update(obedit->data, ID_RECALC_SELECT); WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data); BKE_curve_nurb_vert_active_validate(obedit->data); @@ -503,14 +502,15 @@ void CURVE_OT_de_select_first(wmOperatorType *ot) static int de_select_last_exec(bContext *C, wmOperator *UNUSED(op)) { + Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); uint objects_len = 0; Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data( - view_layer, CTX_wm_view3d(C), &objects_len); + scene, view_layer, CTX_wm_view3d(C), &objects_len); for (uint ob_index = 0; ob_index < objects_len; ob_index++) { Object *obedit = objects[ob_index]; - selectend_nurb(obedit, LAST, true, DESELECT); + selectend_nurb(obedit, LAST, true, false); DEG_id_tag_update(obedit->data, ID_RECALC_SELECT); WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data); BKE_curve_nurb_vert_active_validate(obedit->data); @@ -545,11 +545,12 @@ static int de_select_all_exec(bContext *C, wmOperator *op) { int action = RNA_enum_get(op->ptr, "action"); + Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); View3D *v3d = CTX_wm_view3d(C); uint objects_len = 0; Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data( - view_layer, CTX_wm_view3d(C), &objects_len); + scene, view_layer, CTX_wm_view3d(C), &objects_len); if (action == SEL_TOGGLE) { action = SEL_SELECT; for (uint ob_index = 0; ob_index < objects_len; ob_index++) { @@ -618,12 +619,13 @@ void CURVE_OT_select_all(wmOperatorType *ot) static int select_linked_exec(bContext *C, wmOperator *UNUSED(op)) { + Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); View3D *v3d = CTX_wm_view3d(C); uint objects_len = 0; Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data( - view_layer, CTX_wm_view3d(C), &objects_len); + scene, view_layer, CTX_wm_view3d(C), &objects_len); for (uint ob_index = 0; ob_index < objects_len; ob_index++) { Object *obedit = objects[ob_index]; Curve *cu = obedit->data; @@ -780,12 +782,12 @@ static int select_row_exec(bContext *C, wmOperator *UNUSED(op)) for (b = 0; b < nu->pntsu; b++, bp++) { if (direction) { if (a == v) { - select_bpoint(bp, SELECT, SELECT, VISIBLE); + select_bpoint(bp, true, SELECT, VISIBLE); } } else { if (b == u) { - select_bpoint(bp, SELECT, SELECT, VISIBLE); + select_bpoint(bp, true, SELECT, VISIBLE); } } } @@ -820,10 +822,11 @@ void CURVE_OT_select_row(wmOperatorType *ot) static int select_next_exec(bContext *C, wmOperator *UNUSED(op)) { + Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); uint objects_len = 0; Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data( - view_layer, CTX_wm_view3d(C), &objects_len); + scene, view_layer, CTX_wm_view3d(C), &objects_len); for (uint ob_index = 0; ob_index < objects_len; ob_index++) { Object *obedit = objects[ob_index]; @@ -861,10 +864,11 @@ void CURVE_OT_select_next(wmOperatorType *ot) static int select_previous_exec(bContext *C, wmOperator *UNUSED(op)) { + Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); uint objects_len = 0; Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data( - view_layer, CTX_wm_view3d(C), &objects_len); + scene, view_layer, CTX_wm_view3d(C), &objects_len); for (uint ob_index = 0; ob_index < objects_len; ob_index++) { Object *obedit = objects[ob_index]; @@ -923,7 +927,7 @@ static void curve_select_more(Object *obedit) if (a % nu->pntsu != 0) { tempbp = bp - 1; if (!(tempbp->f1 & SELECT)) { - select_bpoint(tempbp, SELECT, SELECT, VISIBLE); + select_bpoint(tempbp, true, SELECT, VISIBLE); } } @@ -932,7 +936,7 @@ static void curve_select_more(Object *obedit) sel = 0; tempbp = bp + nu->pntsu; if (!(tempbp->f1 & SELECT)) { - sel = select_bpoint(tempbp, SELECT, SELECT, VISIBLE); + sel = select_bpoint(tempbp, true, SELECT, VISIBLE); } /* make sure selected bpoint is discarded */ if (sel == 1) { @@ -944,7 +948,7 @@ static void curve_select_more(Object *obedit) if (a + nu->pntsu < nu->pntsu * nu->pntsv) { tempbp = bp - nu->pntsu; if (!(tempbp->f1 & SELECT)) { - select_bpoint(tempbp, SELECT, SELECT, VISIBLE); + select_bpoint(tempbp, true, SELECT, VISIBLE); } } @@ -953,7 +957,7 @@ static void curve_select_more(Object *obedit) sel = 0; tempbp = bp + 1; if (!(tempbp->f1 & SELECT)) { - sel = select_bpoint(tempbp, SELECT, SELECT, VISIBLE); + sel = select_bpoint(tempbp, true, SELECT, VISIBLE); } if (sel) { bp++; @@ -977,10 +981,11 @@ static void curve_select_more(Object *obedit) static int curve_select_more_exec(bContext *C, wmOperator *UNUSED(op)) { + Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); uint objects_len = 0; Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data( - view_layer, CTX_wm_view3d(C), &objects_len); + scene, view_layer, CTX_wm_view3d(C), &objects_len); for (uint ob_index = 0; ob_index < objects_len; ob_index++) { Object *obedit = objects[ob_index]; curve_select_more(obedit); @@ -1080,7 +1085,7 @@ static void curve_select_less(Object *obedit) } if (sel != 4) { - select_bpoint(bp, DESELECT, SELECT, VISIBLE); + select_bpoint(bp, false, SELECT, VISIBLE); BLI_BITMAP_ENABLE(selbpoints, a); } } @@ -1130,7 +1135,7 @@ static void curve_select_less(Object *obedit) } if (sel != 2) { - select_beztriple(bezt, DESELECT, SELECT, VISIBLE); + select_beztriple(bezt, false, SELECT, VISIBLE); lastsel = true; } else { @@ -1175,7 +1180,7 @@ static void curve_select_less(Object *obedit) } if (sel != 2) { - select_bpoint(bp, DESELECT, SELECT, VISIBLE); + select_bpoint(bp, false, SELECT, VISIBLE); lastsel = true; } else { @@ -1195,10 +1200,11 @@ static void curve_select_less(Object *obedit) static int curve_select_less_exec(bContext *C, wmOperator *UNUSED(op)) { + const Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); uint objects_len = 0; Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data( - view_layer, CTX_wm_view3d(C), &objects_len); + scene, view_layer, CTX_wm_view3d(C), &objects_len); for (uint ob_index = 0; ob_index < objects_len; ob_index++) { Object *obedit = objects[ob_index]; curve_select_less(obedit); @@ -1236,10 +1242,11 @@ static int curve_select_random_exec(bContext *C, wmOperator *op) const float randfac = RNA_float_get(op->ptr, "ratio"); const int seed = WM_operator_properties_select_random_seed_increment_get(op); + const Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); uint objects_len = 0; Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data( - view_layer, CTX_wm_view3d(C), &objects_len); + scene, view_layer, CTX_wm_view3d(C), &objects_len); for (uint ob_index = 0; ob_index < objects_len; ob_index++) { Object *obedit = objects[ob_index]; @@ -1359,7 +1366,7 @@ static void select_nth_bezt(Nurb *nu, BezTriple *bezt, const struct CheckerInter while (a--) { const int depth = abs(start - a); if (!WM_operator_properties_checker_interval_test(params, depth)) { - select_beztriple(bezt, DESELECT, SELECT, HIDDEN); + select_beztriple(bezt, false, SELECT, HIDDEN); } bezt--; @@ -1382,7 +1389,7 @@ static void select_nth_bp(Nurb *nu, BPoint *bp, const struct CheckerIntervalPara while (a--) { const int depth = abs(pnt - startpnt) + abs(row - startrow); if (!WM_operator_properties_checker_interval_test(params, depth)) { - select_bpoint(bp, DESELECT, SELECT, HIDDEN); + select_bpoint(bp, false, SELECT, HIDDEN); } pnt--; @@ -1416,6 +1423,7 @@ static bool ed_curve_select_nth(Curve *cu, const struct CheckerIntervalParams *p static int select_nth_exec(bContext *C, wmOperator *op) { + const Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); Object *obact = CTX_data_edit_object(C); View3D *v3d = CTX_wm_view3d(C); @@ -1426,7 +1434,7 @@ static int select_nth_exec(bContext *C, wmOperator *op) uint objects_len = 0; Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data( - view_layer, CTX_wm_view3d(C), &objects_len); + scene, view_layer, CTX_wm_view3d(C), &objects_len); for (uint ob_index = 0; ob_index < objects_len; ob_index++) { Object *obedit = objects[ob_index]; Curve *cu = obedit->data; @@ -1645,7 +1653,7 @@ static bool curve_nurb_select_similar_type(Object *ob, } if (select) { - select_beztriple(bezt, SELECT, SELECT, VISIBLE); + select_beztriple(bezt, true, SELECT, VISIBLE); changed = true; } } @@ -1690,7 +1698,7 @@ static bool curve_nurb_select_similar_type(Object *ob, } if (select) { - select_bpoint(bp, SELECT, SELECT, VISIBLE); + select_bpoint(bp, true, SELECT, VISIBLE); changed = true; } } @@ -1706,12 +1714,13 @@ static int curve_select_similar_exec(bContext *C, wmOperator *op) const float thresh = RNA_float_get(op->ptr, "threshold"); const int compare = RNA_enum_get(op->ptr, "compare"); + const Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); View3D *v3d = CTX_wm_view3d(C); int tot_nurbs_selected_all = 0; uint objects_len = 0; Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data( - view_layer, CTX_wm_view3d(C), &objects_len); + scene, view_layer, CTX_wm_view3d(C), &objects_len); for (uint ob_index = 0; ob_index < objects_len; ob_index++) { Object *obedit = objects[ob_index]; @@ -1898,10 +1907,10 @@ static void curve_select_shortest_path_curve(Nurb *nu, int vert_src, int vert_ds i = vert_src; while (true) { if (nu->type & CU_BEZIER) { - select_beztriple(&nu->bezt[i], SELECT, SELECT, HIDDEN); + select_beztriple(&nu->bezt[i], true, SELECT, HIDDEN); } else { - select_bpoint(&nu->bp[i], SELECT, SELECT, HIDDEN); + select_bpoint(&nu->bp[i], true, SELECT, HIDDEN); } if (i == vert_dst) { @@ -1979,10 +1988,10 @@ static void curve_select_shortest_path_surf(Nurb *nu, int vert_src, int vert_dst int i = 0; while (vert_curr != vert_src && i++ < vert_num) { if (nu->type == CU_BEZIER) { - select_beztriple(&nu->bezt[vert_curr], SELECT, SELECT, HIDDEN); + select_beztriple(&nu->bezt[vert_curr], true, SELECT, HIDDEN); } else { - select_bpoint(&nu->bp[vert_curr], SELECT, SELECT, HIDDEN); + select_bpoint(&nu->bp[vert_curr], true, SELECT, HIDDEN); } vert_curr = data[vert_curr].vert_prev; } @@ -2040,7 +2049,8 @@ 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); - if (vc.view_layer->basact != basact) { + BKE_view_layer_synced_ensure(vc.scene, vc.view_layer); + if (BKE_view_layer_active_base_get(vc.view_layer) != basact) { ED_object_base_activate(C, basact); } diff --git a/source/blender/editors/curve/editcurve_undo.c b/source/blender/editors/curve/editcurve_undo.c index 888bb2169e0..3f53a88ba5d 100644 --- a/source/blender/editors/curve/editcurve_undo.c +++ b/source/blender/editors/curve/editcurve_undo.c @@ -160,8 +160,10 @@ static void undocurve_free_data(UndoCurve *uc) static Object *editcurve_object_from_context(bContext *C) { + Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); - Object *obedit = OBEDIT_FROM_VIEW_LAYER(view_layer); + BKE_view_layer_synced_ensure(scene, view_layer); + Object *obedit = BKE_view_layer_edit_object_get(view_layer); if (obedit && ELEM(obedit->type, OB_CURVES_LEGACY, OB_SURF)) { Curve *cu = obedit->data; if (BKE_curve_editNurbs_get(cu) != NULL) { @@ -202,9 +204,10 @@ static bool curve_undosys_step_encode(struct bContext *C, struct Main *bmain, Un /* Important not to use the 3D view when getting objects because all objects * outside of this list will be moved out of edit-mode when reading back undo steps. */ + Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); uint objects_len = 0; - Object **objects = ED_undo_editmode_objects_from_view_layer(view_layer, &objects_len); + Object **objects = ED_undo_editmode_objects_from_view_layer(scene, view_layer, &objects_len); us->elems = MEM_callocN(sizeof(*us->elems) * objects_len, __func__); us->elems_len = objects_len; diff --git a/source/blender/editors/curve/editfont.c b/source/blender/editors/curve/editfont.c index ceed12dcff1..03c485a7671 100644 --- a/source/blender/editors/curve/editfont.c +++ b/source/blender/editors/curve/editfont.c @@ -26,12 +26,15 @@ #include "BKE_context.h" #include "BKE_curve.h" +#include "BKE_layer.h" #include "BKE_lib_id.h" #include "BKE_main.h" #include "BKE_object.h" #include "BKE_report.h" #include "BKE_vfont.h" +#include "BLT_translation.h" + #include "DEG_depsgraph.h" #include "DEG_depsgraph_query.h" @@ -619,18 +622,19 @@ static void txt_add_object(bContext *C, ViewLayer *view_layer = CTX_data_view_layer(C); Curve *cu; Object *obedit; - Base *base; + Object *object; const struct TextLine *tmp; int nchars = 0, nbytes = 0; char *s; int a; const float rot[3] = {0.0f, 0.0f, 0.0f}; - obedit = BKE_object_add(bmain, view_layer, OB_FONT, NULL); - base = view_layer->basact; + obedit = BKE_object_add(bmain, scene, view_layer, OB_FONT, NULL); + BKE_view_layer_synced_ensure(scene, view_layer); + object = BKE_view_layer_active_object_get(view_layer); /* seems to assume view align ? TODO: look into this, could be an operator option. */ - ED_object_base_init_transform_on_add(base->object, NULL, rot); + ED_object_base_init_transform_on_add(object, NULL, rot); BKE_object_where_is_calc(depsgraph, scene, obedit); @@ -1962,6 +1966,8 @@ static int set_case_exec(bContext *C, wmOperator *op) void FONT_OT_case_set(wmOperatorType *ot) { + PropertyRNA *prop; + /* identifiers */ ot->name = "Set Case"; ot->description = "Set font case"; @@ -1975,7 +1981,8 @@ void FONT_OT_case_set(wmOperatorType *ot) ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; /* properties */ - RNA_def_enum(ot->srna, "case", case_items, CASE_LOWER, "Case", "Lower or upper case"); + prop = RNA_def_enum(ot->srna, "case", case_items, CASE_LOWER, "Case", "Lower or upper case"); + RNA_def_property_translation_context(prop, BLT_I18NCONTEXT_ID_TEXT); } /** \} */ diff --git a/source/blender/editors/curve/editfont_undo.c b/source/blender/editors/curve/editfont_undo.c index 09e5428b0f9..17ed75b9d10 100644 --- a/source/blender/editors/curve/editfont_undo.c +++ b/source/blender/editors/curve/editfont_undo.c @@ -19,6 +19,7 @@ #include "DNA_scene_types.h" #include "BKE_context.h" +#include "BKE_layer.h" #include "BKE_main.h" #include "BKE_undo_system.h" #include "BKE_vfont.h" @@ -307,8 +308,10 @@ static void undofont_free_data(UndoFont *uf) static Object *editfont_object_from_context(bContext *C) { + Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); - Object *obedit = OBEDIT_FROM_VIEW_LAYER(view_layer); + BKE_view_layer_synced_ensure(scene, view_layer); + Object *obedit = BKE_view_layer_edit_object_get(view_layer); if (obedit && obedit->type == OB_FONT) { Curve *cu = obedit->data; EditFont *ef = cu->editfont; diff --git a/source/blender/editors/curves/intern/curves_add.cc b/source/blender/editors/curves/intern/curves_add.cc index 79916253207..f234a58f439 100644 --- a/source/blender/editors/curves/intern/curves_add.cc +++ b/source/blender/editors/curves/intern/curves_add.cc @@ -102,10 +102,9 @@ bke::CurvesGeometry primitive_random_sphere(const int curves_size, const int poi MutableSpan<int> offsets = curves.offsets_for_write(); MutableSpan<float3> positions = curves.positions_for_write(); - - float *radius_data = (float *)CustomData_add_layer_named( - &curves.point_data, CD_PROP_FLOAT, CD_DEFAULT, nullptr, curves.point_num, "radius"); - MutableSpan<float> radii{radius_data, curves.points_num()}; + bke::MutableAttributeAccessor attributes = curves.attributes_for_write(); + bke::SpanAttributeWriter<float> radius = attributes.lookup_or_add_for_write_only_span<float>( + "radius", ATTR_DOMAIN_POINT); for (const int i : offsets.index_range()) { offsets[i] = points_per_curve * i; @@ -114,9 +113,9 @@ bke::CurvesGeometry primitive_random_sphere(const int curves_size, const int poi RandomNumberGenerator rng; for (const int i : curves.curves_range()) { - const IndexRange curve_range = curves.points_for_curve(i); - MutableSpan<float3> curve_positions = positions.slice(curve_range); - MutableSpan<float> curve_radii = radii.slice(curve_range); + const IndexRange points = curves.points_for_curve(i); + MutableSpan<float3> curve_positions = positions.slice(points); + MutableSpan<float> curve_radii = radius.span.slice(points); const float theta = 2.0f * M_PI * rng.get_float(); const float phi = saacosf(2.0f * rng.get_float() - 1.0f); @@ -135,6 +134,8 @@ bke::CurvesGeometry primitive_random_sphere(const int curves_size, const int poi } } + radius.finish(); + return curves; } diff --git a/source/blender/editors/curves/intern/curves_ops.cc b/source/blender/editors/curves/intern/curves_ops.cc index eec2c5d205d..54d91ccfc90 100644 --- a/source/blender/editors/curves/intern/curves_ops.cc +++ b/source/blender/editors/curves/intern/curves_ops.cc @@ -139,7 +139,8 @@ using bke::CurvesGeometry; namespace convert_to_particle_system { -static int find_mface_for_root_position(const Mesh &mesh, +static int find_mface_for_root_position(const Span<MVert> verts, + const MFace *mface, const Span<int> possible_mface_indices, const float3 &root_pos) { @@ -151,14 +152,14 @@ static int find_mface_for_root_position(const Mesh &mesh, int mface_i; float best_distance_sq = FLT_MAX; for (const int possible_mface_i : possible_mface_indices) { - const MFace &possible_mface = mesh.mface[possible_mface_i]; + const MFace &possible_mface = mface[possible_mface_i]; { float3 point_in_triangle; closest_on_tri_to_point_v3(point_in_triangle, root_pos, - mesh.mvert[possible_mface.v1].co, - mesh.mvert[possible_mface.v2].co, - mesh.mvert[possible_mface.v3].co); + verts[possible_mface.v1].co, + verts[possible_mface.v2].co, + verts[possible_mface.v3].co); const float distance_sq = len_squared_v3v3(root_pos, point_in_triangle); if (distance_sq < best_distance_sq) { best_distance_sq = distance_sq; @@ -170,9 +171,9 @@ static int find_mface_for_root_position(const Mesh &mesh, float3 point_in_triangle; closest_on_tri_to_point_v3(point_in_triangle, root_pos, - mesh.mvert[possible_mface.v1].co, - mesh.mvert[possible_mface.v3].co, - mesh.mvert[possible_mface.v4].co); + verts[possible_mface.v1].co, + verts[possible_mface.v3].co, + verts[possible_mface.v4].co); const float distance_sq = len_squared_v3v3(root_pos, point_in_triangle); if (distance_sq < best_distance_sq) { best_distance_sq = distance_sq; @@ -186,25 +187,22 @@ static int find_mface_for_root_position(const Mesh &mesh, /** * \return Barycentric coordinates in the #MFace. */ -static float4 compute_mface_weights_for_position(const Mesh &mesh, +static float4 compute_mface_weights_for_position(const Span<MVert> verts, const MFace &mface, const float3 &position) { float4 mface_weights; if (mface.v4) { float mface_verts_su[4][3]; - copy_v3_v3(mface_verts_su[0], mesh.mvert[mface.v1].co); - copy_v3_v3(mface_verts_su[1], mesh.mvert[mface.v2].co); - copy_v3_v3(mface_verts_su[2], mesh.mvert[mface.v3].co); - copy_v3_v3(mface_verts_su[3], mesh.mvert[mface.v4].co); + copy_v3_v3(mface_verts_su[0], verts[mface.v1].co); + copy_v3_v3(mface_verts_su[1], verts[mface.v2].co); + copy_v3_v3(mface_verts_su[2], verts[mface.v3].co); + copy_v3_v3(mface_verts_su[3], verts[mface.v4].co); interp_weights_poly_v3(mface_weights, mface_verts_su, 4, position); } else { - interp_weights_tri_v3(mface_weights, - mesh.mvert[mface.v1].co, - mesh.mvert[mface.v2].co, - mesh.mvert[mface.v3].co, - position); + interp_weights_tri_v3( + mface_weights, verts[mface.v1].co, verts[mface.v2].co, verts[mface.v3].co, position); mface_weights[3] = 0.0f; } return mface_weights; @@ -287,6 +285,9 @@ static void try_convert_single_object(Object &curves_ob, /* Prepare transformation matrices. */ const bke::CurvesSurfaceTransforms transforms{curves_ob, &surface_ob}; + const MFace *mfaces = (const MFace *)CustomData_get_layer(&surface_me.fdata, CD_MFACE); + const Span<MVert> verts = surface_me.verts(); + for (const int new_hair_i : IndexRange(hair_num)) { const int curve_i = new_hair_i; const IndexRange points = curves.points_for_curve(curve_i); @@ -305,11 +306,10 @@ static void try_convert_single_object(Object &curves_ob, const int poly_i = looptri.poly; const int mface_i = find_mface_for_root_position( - surface_me, poly_to_mface_map[poly_i], root_pos_su); - const MFace &mface = surface_me.mface[mface_i]; + verts, mfaces, poly_to_mface_map[poly_i], root_pos_su); + const MFace &mface = mfaces[mface_i]; - const float4 mface_weights = compute_mface_weights_for_position( - surface_me, mface, root_pos_su); + const float4 mface_weights = compute_mface_weights_for_position(verts, mface, root_pos_su); ParticleData &particle = particles[new_hair_i]; const int num_keys = points.size(); @@ -471,6 +471,7 @@ static bke::CurvesGeometry particles_to_curves(Object &object, ParticleSystem &p static int curves_convert_from_particle_system_exec(bContext *C, wmOperator *UNUSED(op)) { Main &bmain = *CTX_data_main(C); + Scene &scene = *CTX_data_scene(C); ViewLayer &view_layer = *CTX_data_view_layer(C); Depsgraph &depsgraph = *CTX_data_depsgraph_pointer(C); Object *ob_from_orig = ED_object_active_context(C); @@ -495,7 +496,7 @@ static int curves_convert_from_particle_system_exec(bContext *C, wmOperator *UNU psys_eval = psmd->psys; } - Object *ob_new = BKE_object_add(&bmain, &view_layer, OB_CURVES, psys_eval->name); + Object *ob_new = BKE_object_add(&bmain, &scene, &view_layer, OB_CURVES, psys_eval->name); Curves *curves_id = static_cast<Curves *>(ob_new->data); BKE_object_apply_mat4(ob_new, ob_from_orig->obmat, true, false); bke::CurvesGeometry::wrap(curves_id->geometry) = particles_to_curves(*ob_from_eval, *psys_eval); @@ -541,11 +542,14 @@ static void snap_curves_to_surface_exec_object(Object &curves_ob, Curves &curves_id = *static_cast<Curves *>(curves_ob.data); CurvesGeometry &curves = CurvesGeometry::wrap(curves_id.geometry); - Mesh &surface_mesh = *static_cast<Mesh *>(surface_ob.data); - + const Mesh &surface_mesh = *static_cast<const Mesh *>(surface_ob.data); + const Span<MVert> verts = surface_mesh.verts(); + const Span<MLoop> loops = surface_mesh.loops(); + const Span<MLoopTri> surface_looptris = {BKE_mesh_runtime_looptri_ensure(&surface_mesh), + BKE_mesh_runtime_looptri_len(&surface_mesh)}; VArraySpan<float2> surface_uv_map; if (curves_id.surface_uv_map != nullptr) { - const bke::AttributeAccessor surface_attributes = bke::mesh_attributes(surface_mesh); + const bke::AttributeAccessor surface_attributes = surface_mesh.attributes(); surface_uv_map = surface_attributes .lookup(curves_id.surface_uv_map, ATTR_DOMAIN_CORNER, CD_PROP_FLOAT2) .typed<float2>(); @@ -554,9 +558,6 @@ static void snap_curves_to_surface_exec_object(Object &curves_ob, MutableSpan<float3> positions_cu = curves.positions_for_write(); MutableSpan<float2> surface_uv_coords = curves.surface_uv_coords_for_write(); - const Span<MLoopTri> surface_looptris = {BKE_mesh_runtime_looptri_ensure(&surface_mesh), - BKE_mesh_runtime_looptri_len(&surface_mesh)}; - const bke::CurvesSurfaceTransforms transforms{curves_ob, &surface_ob}; switch (attach_mode) { @@ -603,9 +604,9 @@ static void snap_curves_to_surface_exec_object(Object &curves_ob, const float2 &uv0 = surface_uv_map[corner0]; const float2 &uv1 = surface_uv_map[corner1]; const float2 &uv2 = surface_uv_map[corner2]; - const float3 &p0_su = surface_mesh.mvert[surface_mesh.mloop[corner0].v].co; - const float3 &p1_su = surface_mesh.mvert[surface_mesh.mloop[corner1].v].co; - const float3 &p2_su = surface_mesh.mvert[surface_mesh.mloop[corner2].v].co; + const float3 &p0_su = verts[loops[corner0].v].co; + const float3 &p1_su = verts[loops[corner1].v].co; + const float3 &p2_su = verts[loops[corner2].v].co; float3 bary_coords; interp_weights_tri_v3(bary_coords, p0_su, p1_su, p2_su, new_first_point_pos_su); const float2 uv = attribute_math::mix3(bary_coords, uv0, uv1, uv2); @@ -639,9 +640,9 @@ static void snap_curves_to_surface_exec_object(Object &curves_ob, const MLoopTri &looptri = *lookup_result.looptri; const float3 &bary_coords = lookup_result.bary_weights; - const float3 &p0_su = surface_mesh.mvert[surface_mesh.mloop[looptri.tri[0]].v].co; - const float3 &p1_su = surface_mesh.mvert[surface_mesh.mloop[looptri.tri[1]].v].co; - const float3 &p2_su = surface_mesh.mvert[surface_mesh.mloop[looptri.tri[2]].v].co; + const float3 &p0_su = verts[loops[looptri.tri[0]].v].co; + const float3 &p1_su = verts[loops[looptri.tri[1]].v].co; + const float3 &p2_su = verts[loops[looptri.tri[2]].v].co; float3 new_first_point_pos_su; interp_v3_v3v3v3(new_first_point_pos_su, p0_su, p1_su, p2_su, bary_coords); @@ -693,7 +694,7 @@ static int snap_curves_to_surface_exec(bContext *C, wmOperator *op) BKE_report(op->reports, RPT_INFO, "Could not snap some curves to the surface"); } - /* Refresh the entire window to also clear eventual modifier and nodes editor warnings.*/ + /* Refresh the entire window to also clear eventual modifier and nodes editor warnings. */ WM_event_add_notifier(C, NC_WINDOW, nullptr); return OPERATOR_FINISHED; diff --git a/source/blender/editors/geometry/geometry_attributes.cc b/source/blender/editors/geometry/geometry_attributes.cc index a6a9b2fcd26..14f2f8c6af5 100644 --- a/source/blender/editors/geometry/geometry_attributes.cc +++ b/source/blender/editors/geometry/geometry_attributes.cc @@ -275,14 +275,14 @@ static int geometry_attribute_convert_exec(bContext *C, wmOperator *op) { Object *ob = ED_object_context(C); ID *ob_data = static_cast<ID *>(ob->data); - CustomDataLayer *layer = BKE_id_attributes_active_get(ob_data); + const CustomDataLayer *layer = BKE_id_attributes_active_get(ob_data); const std::string name = layer->name; const ConvertAttributeMode mode = static_cast<ConvertAttributeMode>( RNA_enum_get(op->ptr, "mode")); Mesh *mesh = reinterpret_cast<Mesh *>(ob_data); - bke::MutableAttributeAccessor attributes = bke::mesh_attributes_for_write(*mesh); + bke::MutableAttributeAccessor attributes = mesh->attributes_for_write(); /* General conversion steps are always the same: * 1. Convert old data to right domain and data type. @@ -305,7 +305,7 @@ static int geometry_attribute_convert_exec(bContext *C, wmOperator *op) void *new_data = MEM_malloc_arrayN(src_varray.size(), cpp_type.size(), __func__); src_varray.materialize_to_uninitialized(new_data); attributes.remove(name); - attributes.add(name, dst_domain, dst_type, blender::bke::AttributeInitMove(new_data)); + attributes.add(name, dst_domain, dst_type, blender::bke::AttributeInitMoveArray(new_data)); break; } case ConvertAttributeMode::UVMap: { @@ -471,11 +471,6 @@ static int geometry_color_attribute_remove_exec(bContext *C, wmOperator *op) return OPERATOR_CANCELLED; } - if (GS(id->name) == ID_ME) { - Mesh *me = static_cast<Mesh *>(ob->data); - BKE_mesh_update_customdata_pointers(me, true); - } - DEG_id_tag_update(id, ID_RECALC_GEOMETRY); WM_main_add_notifier(NC_GEOM | ND_DATA, id); @@ -651,8 +646,7 @@ bool ED_geometry_attribute_convert(Mesh *mesh, return false; } - blender::bke::MutableAttributeAccessor attributes = blender::bke::mesh_attributes_for_write( - *mesh); + blender::bke::MutableAttributeAccessor attributes = mesh->attributes_for_write(); GVArray src_varray = attributes.lookup_or_default(name, new_domain, new_type); @@ -660,7 +654,7 @@ bool ED_geometry_attribute_convert(Mesh *mesh, void *new_data = MEM_malloc_arrayN(src_varray.size(), cpp_type.size(), __func__); src_varray.materialize_to_uninitialized(new_data); attributes.remove(name); - attributes.add(name, new_domain, new_type, blender::bke::AttributeInitMove(new_data)); + attributes.add(name, new_domain, new_type, blender::bke::AttributeInitMoveArray(new_data)); int *active_index = BKE_id_attributes_active_index_p(&mesh->id); if (*active_index > 0) { diff --git a/source/blender/editors/gizmo_library/CMakeLists.txt b/source/blender/editors/gizmo_library/CMakeLists.txt index 0484c47f081..84181b5f95d 100644 --- a/source/blender/editors/gizmo_library/CMakeLists.txt +++ b/source/blender/editors/gizmo_library/CMakeLists.txt @@ -13,7 +13,6 @@ set(INC ../../windowmanager ../../../../intern/clog ../../../../intern/eigen - ../../../../intern/glew-mx ../../../../intern/guardedalloc # RNA_prototypes.h ${CMAKE_BINARY_DIR}/source/blender/makesrna diff --git a/source/blender/editors/gizmo_library/gizmo_types/button2d_gizmo.c b/source/blender/editors/gizmo_library/gizmo_types/button2d_gizmo.c index 2c886230f10..6eac235a191 100644 --- a/source/blender/editors/gizmo_library/gizmo_types/button2d_gizmo.c +++ b/source/blender/editors/gizmo_library/gizmo_types/button2d_gizmo.c @@ -217,7 +217,7 @@ static void button2d_draw_intern(const bContext *C, GPU_batch_uniform_1f(button->shape_batch[i], "lineWidth", gz->line_width * U.pixelsize); } else { - GPU_batch_program_set_builtin(button->shape_batch[i], GPU_SHADER_2D_UNIFORM_COLOR); + GPU_batch_program_set_builtin(button->shape_batch[i], GPU_SHADER_3D_UNIFORM_COLOR); } /* Invert line color for wire. */ diff --git a/source/blender/editors/gizmo_library/gizmo_types/cage2d_gizmo.c b/source/blender/editors/gizmo_library/gizmo_types/cage2d_gizmo.c index 54aa5d16941..600abaf3737 100644 --- a/source/blender/editors/gizmo_library/gizmo_types/cage2d_gizmo.c +++ b/source/blender/editors/gizmo_library/gizmo_types/cage2d_gizmo.c @@ -388,7 +388,7 @@ static void cage2d_draw_box_interaction(const float color[4], .pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT), .col = GPU_vertformat_attr_add(format, "color", GPU_COMP_F32, 3, GPU_FETCH_FLOAT), }; - immBindBuiltinProgram(is_solid ? GPU_SHADER_2D_FLAT_COLOR : GPU_SHADER_3D_POLYLINE_FLAT_COLOR); + immBindBuiltinProgram(is_solid ? GPU_SHADER_3D_FLAT_COLOR : GPU_SHADER_3D_POLYLINE_FLAT_COLOR); { if (is_solid) { @@ -546,7 +546,7 @@ static void cage2d_draw_circle_handles(const rctf *r, const int resolu = 12; const float rad[2] = {margin[0] / 3, margin[1] / 3}; - immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); immUniformColor3fv(color); /* should really divide by two, but looks too bulky. */ @@ -598,7 +598,7 @@ static void gizmo_cage2d_draw_intern(wmGizmo *gz, if (false) { GPU_blend(GPU_BLEND_ALPHA); uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); - immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); immUniformColor4fv((const float[4]){1, 1, 1, 0.5f}); float s = 0.5f; immRectf(pos, -s, -s, s, s); diff --git a/source/blender/editors/gpencil/CMakeLists.txt b/source/blender/editors/gpencil/CMakeLists.txt index 9cb9e7ca1af..866df16f3d6 100644 --- a/source/blender/editors/gpencil/CMakeLists.txt +++ b/source/blender/editors/gpencil/CMakeLists.txt @@ -12,7 +12,6 @@ set(INC ../../makesdna ../../makesrna ../../windowmanager - ../../../../intern/glew-mx ../../../../intern/guardedalloc ../../bmesh # RNA_prototypes.h diff --git a/source/blender/editors/gpencil/annotate_paint.c b/source/blender/editors/gpencil/annotate_paint.c index d08d56a354a..ea34e6530fa 100644 --- a/source/blender/editors/gpencil/annotate_paint.c +++ b/source/blender/editors/gpencil/annotate_paint.c @@ -1715,7 +1715,7 @@ static void annotation_draw_eraser(bContext *UNUSED(C), int x, int y, void *p_pt if (p->paintmode == GP_PAINTMODE_ERASER) { GPUVertFormat *format = immVertexFormat(); const uint shdr_pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); - immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); GPU_line_smooth(true); GPU_blend(GPU_BLEND_ALPHA); @@ -1725,7 +1725,7 @@ static void annotation_draw_eraser(bContext *UNUSED(C), int x, int y, void *p_pt immUnbindProgram(); - immBindBuiltinProgram(GPU_SHADER_2D_LINE_DASHED_UNIFORM_COLOR); + immBindBuiltinProgram(GPU_SHADER_3D_LINE_DASHED_UNIFORM_COLOR); float viewport_size[4]; GPU_viewport_size_get_f(viewport_size); @@ -1782,7 +1782,7 @@ static void annotation_draw_stabilizer(bContext *C, int x, int y, void *p_ptr) GPUVertFormat *format = immVertexFormat(); uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); - immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); GPU_line_smooth(true); GPU_blend(GPU_BLEND_ALPHA); GPU_line_width(1.25f); @@ -2346,7 +2346,7 @@ static int annotation_draw_invoke(bContext *C, wmOperator *op, const wmEvent *ev return OPERATOR_RUNNING_MODAL; } -/* gpencil modal operator stores area, which can be removed while using it (like fullscreen) */ +/* gpencil modal operator stores area, which can be removed while using it (like full-screen). */ static bool annotation_area_exists(bContext *C, ScrArea *area_test) { bScreen *screen = CTX_wm_screen(C); @@ -2698,7 +2698,7 @@ static int annotation_draw_modal(bContext *C, wmOperator *op, const wmEvent *eve } } - /* gpencil modal operator stores area, which can be removed while using it (like fullscreen) */ + /* gpencil modal operator stores area, which can be removed while using it (like full-screen). */ if (0 == annotation_area_exists(C, p->area)) { estate = OPERATOR_CANCELLED; } diff --git a/source/blender/editors/gpencil/gpencil_add_monkey.c b/source/blender/editors/gpencil/gpencil_add_monkey.c index ce38c261c1f..00066d5f2b8 100644 --- a/source/blender/editors/gpencil/gpencil_add_monkey.c +++ b/source/blender/editors/gpencil/gpencil_add_monkey.c @@ -823,6 +823,8 @@ static const ColorTemplate gp_monkey_pct_pupils = { void ED_gpencil_create_monkey(bContext *C, Object *ob, float mat[4][4]) { + /* Original model created by Matias Mendiola. */ + Main *bmain = CTX_data_main(C); Scene *scene = CTX_data_scene(C); bGPdata *gpd = (bGPdata *)ob->data; diff --git a/source/blender/editors/gpencil/gpencil_add_stroke.c b/source/blender/editors/gpencil/gpencil_add_stroke.c index 4687f9188fd..8522c81cb39 100644 --- a/source/blender/editors/gpencil/gpencil_add_stroke.c +++ b/source/blender/editors/gpencil/gpencil_add_stroke.c @@ -192,6 +192,8 @@ static const ColorTemplate gp_stroke_material_grey = { void ED_gpencil_create_stroke(bContext *C, Object *ob, float mat[4][4]) { + /* Original design created by Daniel M. Lara and Matias Mendiola. */ + Main *bmain = CTX_data_main(C); Scene *scene = CTX_data_scene(C); bGPdata *gpd = (bGPdata *)ob->data; diff --git a/source/blender/editors/gpencil/gpencil_armature.c b/source/blender/editors/gpencil/gpencil_armature.c index d389f7eb5dd..5f5a4b41b27 100644 --- a/source/blender/editors/gpencil/gpencil_armature.c +++ b/source/blender/editors/gpencil/gpencil_armature.c @@ -29,6 +29,7 @@ #include "BKE_deform.h" #include "BKE_gpencil.h" #include "BKE_gpencil_modifier.h" +#include "BKE_layer.h" #include "BKE_main.h" #include "BKE_object_deform.h" #include "BKE_report.h" @@ -528,6 +529,7 @@ static bool gpencil_generate_weights_poll(bContext *C) return false; } + Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); bGPdata *gpd = (bGPdata *)ob->data; @@ -536,7 +538,8 @@ static bool gpencil_generate_weights_poll(bContext *C) } /* need some armature in the view layer */ - LISTBASE_FOREACH (Base *, base, &view_layer->object_bases) { + BKE_view_layer_synced_ensure(scene, view_layer); + LISTBASE_FOREACH (Base *, base, BKE_view_layer_object_bases_get(view_layer)) { if (base->object->type == OB_ARMATURE) { return true; } @@ -548,6 +551,7 @@ static bool gpencil_generate_weights_poll(bContext *C) static int gpencil_generate_weights_exec(bContext *C, wmOperator *op) { Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C); + Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); Object *ob = CTX_data_active_object(C); Object *ob_eval = DEG_get_evaluated_object(depsgraph, ob); @@ -566,7 +570,8 @@ static int gpencil_generate_weights_exec(bContext *C, wmOperator *op) /* get armature */ const int arm_idx = RNA_enum_get(op->ptr, "armature"); if (arm_idx > 0) { - Base *base = BLI_findlink(&view_layer->object_bases, arm_idx - 1); + BKE_view_layer_synced_ensure(scene, view_layer); + Base *base = BLI_findlink(BKE_view_layer_object_bases_get(view_layer), arm_idx - 1); ob_arm = base->object; } else { @@ -607,6 +612,7 @@ static const EnumPropertyItem *gpencil_armatures_enum_itemf(bContext *C, PropertyRNA *UNUSED(prop), bool *r_free) { + Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); EnumPropertyItem *item = NULL, item_tmp = {0}; int totitem = 0; @@ -623,7 +629,8 @@ static const EnumPropertyItem *gpencil_armatures_enum_itemf(bContext *C, RNA_enum_item_add(&item, &totitem, &item_tmp); i++; - LISTBASE_FOREACH (Base *, base, &view_layer->object_bases) { + BKE_view_layer_synced_ensure(scene, view_layer); + LISTBASE_FOREACH (Base *, base, BKE_view_layer_object_bases_get(view_layer)) { Object *ob = base->object; if (ob->type == OB_ARMATURE) { item_tmp.identifier = item_tmp.name = ob->id.name + 2; diff --git a/source/blender/editors/gpencil/gpencil_bake_animation.cc b/source/blender/editors/gpencil/gpencil_bake_animation.cc index e480852a9bb..28d4e1c6d42 100644 --- a/source/blender/editors/gpencil/gpencil_bake_animation.cc +++ b/source/blender/editors/gpencil/gpencil_bake_animation.cc @@ -327,7 +327,7 @@ static int gpencil_bake_grease_pencil_animation_exec(bContext *C, wmOperator *op /* Reproject stroke. */ if (project_type != GP_REPROJECT_KEEP) { ED_gpencil_stroke_reproject( - depsgraph, &gsc, sctx, gpl_dst, gpf_dst, gps, project_type, false); + depsgraph, &gsc, sctx, gpl_dst, gpf_dst, gps, project_type, false, 0.0f); } else { BKE_gpencil_stroke_geometry_update(gpd_dst, gps); diff --git a/source/blender/editors/gpencil/gpencil_convert.c b/source/blender/editors/gpencil/gpencil_convert.c index e02a82f4555..bf78111a636 100644 --- a/source/blender/editors/gpencil/gpencil_convert.c +++ b/source/blender/editors/gpencil/gpencil_convert.c @@ -1303,6 +1303,7 @@ static void gpencil_layer_to_curve(bContext *C, ob = BKE_object_add_only_object(bmain, OB_CURVES_LEGACY, gpl->info); cu = ob->data = BKE_curve_add(bmain, gpl->info, OB_CURVES_LEGACY); BKE_collection_object_add(bmain, collection, ob); + BKE_view_layer_synced_ensure(scene, view_layer); base_new = BKE_view_layer_base_find(view_layer, ob); DEG_relations_tag_update(bmain); /* added object */ diff --git a/source/blender/editors/gpencil/gpencil_data.c b/source/blender/editors/gpencil/gpencil_data.c index b7ac73b9692..340288b2d74 100644 --- a/source/blender/editors/gpencil/gpencil_data.c +++ b/source/blender/editors/gpencil/gpencil_data.c @@ -2076,6 +2076,9 @@ static void gpencil_brush_delete_mode_brushes(Main *bmain, } BKE_brush_delete(bmain, brush); + if (brush == brush_active) { + brush_active = NULL; + } } } @@ -2109,8 +2112,8 @@ static int gpencil_brush_reset_all_exec(bContext *C, wmOperator *UNUSED(op)) char tool = '0'; if (paint) { - Brush *brush_active = paint->brush; - if (brush_active) { + if (paint->brush) { + Brush *brush_active = paint->brush; switch (mode) { case CTX_MODE_PAINT_GPENCIL: { tool = brush_active->gpencil_tool; diff --git a/source/blender/editors/gpencil/gpencil_edit.c b/source/blender/editors/gpencil/gpencil_edit.c index c05ab8c6b28..837a9390b6c 100644 --- a/source/blender/editors/gpencil/gpencil_edit.c +++ b/source/blender/editors/gpencil/gpencil_edit.c @@ -67,6 +67,7 @@ #include "ED_armature.h" #include "ED_gpencil.h" +#include "ED_keyframing.h" #include "ED_object.h" #include "ED_outliner.h" #include "ED_screen.h" @@ -1713,12 +1714,17 @@ static int gpencil_strokes_paste_exec(bContext *C, wmOperator *op) } } - /* Ensure we have a frame to draw into + /* Ensure we have a frame to draw into. * NOTE: Since this is an op which creates strokes, - * we are obliged to add a new frame if one - * doesn't exist already + * we reuse active frame or add a new frame if one + * doesn't exist already depending on REC button status. */ - gpf = BKE_gpencil_layer_frame_get(gpl, scene->r.cfra, GP_GETFRAME_ADD_NEW); + if (IS_AUTOKEY_ON(scene) || (gpl->actframe == NULL)) { + gpf = BKE_gpencil_layer_frame_get(gpl, scene->r.cfra, GP_GETFRAME_ADD_NEW); + } + else { + gpf = BKE_gpencil_layer_frame_get(gpl, scene->r.cfra, GP_GETFRAME_USE_PREV); + } if (gpf) { /* Create new stroke */ bGPDstroke *new_stroke = BKE_gpencil_stroke_duplicate(gps, true, true); @@ -3650,7 +3656,7 @@ static int gpencil_stroke_join_exec(bContext *C, wmOperator *op) } elem = &strokes_list[i]; /* Join new_stroke and stroke B. */ - BKE_gpencil_stroke_join(gps_new, elem->gps, leave_gaps, true, false); + BKE_gpencil_stroke_join(gps_new, elem->gps, leave_gaps, true, false, true); elem->used = true; } @@ -3791,6 +3797,101 @@ void GPENCIL_OT_stroke_flip(wmOperatorType *ot) /** \} */ /* -------------------------------------------------------------------- */ +/** \name Stroke Start Set Operator + * \{ */ + +static int gpencil_stroke_start_set_exec(bContext *C, wmOperator *op) +{ + Object *ob = CTX_data_active_object(C); + bGPdata *gpd = ob->data; + + /* sanity checks */ + if (ELEM(NULL, ob, gpd)) { + return OPERATOR_CANCELLED; + } + + const bool is_multiedit = (bool)GPENCIL_MULTIEDIT_SESSIONS_ON(gpd); + const bool is_curve_edit = (bool)GPENCIL_CURVE_EDIT_SESSIONS_ON(gpd); + if (is_curve_edit) { + BKE_report(op->reports, RPT_ERROR, "Curve Edit mode not supported"); + return OPERATOR_CANCELLED; + } + + bool changed = false; + /* Read all selected strokes. */ + CTX_DATA_BEGIN (C, bGPDlayer *, gpl, editable_gpencil_layers) { + bGPDframe *init_gpf = (is_multiedit) ? gpl->frames.first : gpl->actframe; + + for (bGPDframe *gpf = init_gpf; gpf; gpf = gpf->next) { + if ((gpf == gpl->actframe) || ((gpf->flag & GP_FRAME_SELECT) && (is_multiedit))) { + if (gpf == NULL) { + continue; + } + LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) { + if (gps->flag & GP_STROKE_SELECT) { + /* skip strokes that are invalid for current view */ + if (ED_gpencil_stroke_can_use(C, gps) == false) { + continue; + } + /* check if the color is editable */ + if (ED_gpencil_stroke_material_editable(ob, gpl, gps) == false) { + continue; + } + + /* Only cyclic strokes. */ + if ((gps->flag & GP_STROKE_CYCLIC) == 0) { + continue; + } + + /* Find first selected point and set start. */ + bGPDspoint *pt; + for (int i = 0; i < gps->totpoints; i++) { + pt = &gps->points[i]; + if (pt->flag & GP_SPOINT_SELECT) { + BKE_gpencil_stroke_start_set(gps, i); + BKE_gpencil_stroke_geometry_update(gpd, gps); + changed = true; + break; + } + } + } + } + } + /* If not multi-edit, exit loop. */ + if (!is_multiedit) { + break; + } + } + } + CTX_DATA_END; + + if (changed) { + /* notifiers */ + DEG_id_tag_update(&gpd->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY); + WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL); + } + + return OPERATOR_FINISHED; +} + +void GPENCIL_OT_stroke_start_set(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Set Start Point"; + ot->idname = "GPENCIL_OT_stroke_start_set"; + ot->description = "Set start point for cyclic strokes"; + + /* api callbacks */ + ot->exec = gpencil_stroke_start_set_exec; + ot->poll = gpencil_active_layer_poll; + + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; +} + +/** \} */ + +/* -------------------------------------------------------------------- */ /** \name Stroke Re-project Operator * \{ */ @@ -3804,6 +3905,7 @@ static int gpencil_strokes_reproject_exec(bContext *C, wmOperator *op) const bool keep_original = RNA_boolean_get(op->ptr, "keep_original"); const bool is_curve_edit = (bool)GPENCIL_CURVE_EDIT_SESSIONS_ON(gpd); const bool is_multiedit = (bool)GPENCIL_MULTIEDIT_SESSIONS_ON(gpd); + const float offset = RNA_float_get(op->ptr, "offset"); /* Init snap context for geometry projection. */ SnapObjectContext *sctx = NULL; @@ -3843,7 +3945,8 @@ static int gpencil_strokes_reproject_exec(bContext *C, wmOperator *op) BKE_scene_graph_update_for_newframe(depsgraph); } - ED_gpencil_stroke_reproject(depsgraph, &gsc, sctx, gpl, gpf, gps, mode, keep_original); + ED_gpencil_stroke_reproject( + depsgraph, &gsc, sctx, gpl, gpf, gps, mode, keep_original, offset); if (is_curve_edit && gps->editcurve != NULL) { BKE_gpencil_stroke_editcurve_update(gpd, gpl, gps); @@ -3883,8 +3986,29 @@ static int gpencil_strokes_reproject_exec(bContext *C, wmOperator *op) return OPERATOR_FINISHED; } +static void gpencil_strokes_reproject_ui(bContext *UNUSED(C), wmOperator *op) +{ + uiLayout *layout = op->layout; + uiLayout *row; + + const eGP_ReprojectModes type = RNA_enum_get(op->ptr, "type"); + + uiLayoutSetPropSep(layout, true); + uiLayoutSetPropDecorate(layout, false); + row = uiLayoutRow(layout, true); + uiItemR(row, op->ptr, "type", 0, NULL, ICON_NONE); + + if (type == GP_REPROJECT_SURFACE) { + row = uiLayoutRow(layout, true); + uiItemR(row, op->ptr, "offset", 0, NULL, ICON_NONE); + } + row = uiLayoutRow(layout, true); + uiItemR(row, op->ptr, "keep_original", 0, NULL, ICON_NONE); +} + void GPENCIL_OT_reproject(wmOperatorType *ot) { + PropertyRNA *prop; static const EnumPropertyItem reproject_type[] = { {GP_REPROJECT_FRONT, "FRONT", 0, "Front", "Reproject the strokes using the X-Z plane"}, {GP_REPROJECT_SIDE, "SIDE", 0, "Side", "Reproject the strokes using the Y-Z plane"}, @@ -3922,6 +4046,7 @@ void GPENCIL_OT_reproject(wmOperatorType *ot) ot->invoke = WM_menu_invoke; ot->exec = gpencil_strokes_reproject_exec; ot->poll = gpencil_strokes_edit3d_poll; + ot->ui = gpencil_strokes_reproject_ui; /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; @@ -3930,12 +4055,15 @@ void GPENCIL_OT_reproject(wmOperatorType *ot) ot->prop = RNA_def_enum( ot->srna, "type", reproject_type, GP_REPROJECT_VIEW, "Projection Type", ""); - RNA_def_boolean( + prop = RNA_def_boolean( ot->srna, "keep_original", 0, "Keep Original", "Keep original strokes and create a copy before reprojecting instead of reproject them"); + RNA_def_property_translation_context(prop, BLT_I18NCONTEXT_ID_MOVIECLIP); + + RNA_def_float(ot->srna, "offset", 0.0f, 0.0f, 10.0f, "Surface Offset", "", 0.0f, 10.0f); } static int gpencil_recalc_geometry_exec(bContext *C, wmOperator *UNUSED(op)) @@ -3960,6 +4088,284 @@ static int gpencil_recalc_geometry_exec(bContext *C, wmOperator *UNUSED(op)) return OPERATOR_FINISHED; } +/* -------------------------------------------------------------------- */ +/** \name Stroke Perimeter from View Operator + * \{ */ + +enum { + GP_PERIMETER_VIEW = 0, + GP_PERIMETER_FRONT = 1, + GP_PERIMETER_SIDE = 2, + GP_PERIMETER_TOP = 3, + GP_PERIMETER_CAMERA = 4, +}; + +enum { + GP_STROKE_USE_ACTIVE_MATERIAL = 0, + GP_STROKE_USE_CURRENT_MATERIAL = 1, + GP_STROKE_USE_NEW_MATERIAL = 2, +}; + +static int gpencil_stroke_outline_exec(bContext *C, wmOperator *op) +{ + Main *bmain = CTX_data_main(C); + RegionView3D *rv3d = CTX_wm_region_view3d(C); + Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C); + Object *ob = CTX_data_active_object(C); + bGPdata *gpd = (bGPdata *)ob->data; + const int subdivisions = RNA_int_get(op->ptr, "subdivisions"); + const float length = RNA_float_get(op->ptr, "length"); + const bool keep = RNA_boolean_get(op->ptr, "keep"); + const int thickness = RNA_int_get(op->ptr, "thickness"); + + const int view_mode = RNA_enum_get(op->ptr, "view_mode"); + const int material_mode = RNA_enum_get(op->ptr, "material_mode"); + const bool is_multiedit = (bool)GPENCIL_MULTIEDIT_SESSIONS_ON(gpd); + + /* sanity checks */ + if (ELEM(NULL, gpd)) { + return OPERATOR_CANCELLED; + } + + bool changed = false; + + float viewmat[4][4]; + copy_m4_m4(viewmat, rv3d->viewmat); + + switch (view_mode) { + case GP_PERIMETER_FRONT: + unit_m4(rv3d->viewmat); + viewmat[1][1] = 0.0f; + viewmat[1][2] = -1.0f; + + viewmat[2][1] = 1.0f; + viewmat[2][2] = 0.0f; + + viewmat[3][2] = -10.0f; + break; + case GP_PERIMETER_SIDE: + zero_m4(viewmat); + viewmat[0][2] = 1.0f; + viewmat[1][0] = 1.0f; + viewmat[2][1] = 1.0f; + viewmat[3][3] = 1.0f; + break; + case GP_PERIMETER_TOP: + unit_m4(viewmat); + break; + case GP_PERIMETER_CAMERA: { + Scene *scene = CTX_data_scene(C); + Object *cam_ob = scene->camera; + if (cam_ob != NULL) { + invert_m4_m4(viewmat, cam_ob->obmat); + } + break; + } + default: + break; + } + + /* Untag strokes to be sure nothing is pending. */ + LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) { + LISTBASE_FOREACH (bGPDframe *, gpf, &gpl->frames) { + LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) { + gps->flag &= ~GP_STROKE_TAG; + } + } + } + /* Create a new material. */ + int mat_idx = 0; + if (material_mode == GP_STROKE_USE_NEW_MATERIAL) { + Material *ma = BKE_gpencil_object_material_new(bmain, ob, "Material", NULL); + MaterialGPencilStyle *gp_style = ma->gp_style; + + gp_style->flag |= GP_MATERIAL_FILL_SHOW; + mat_idx = ob->totcol - 1; + } + + /* loop all selected strokes */ + LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) { + if (gpl->flag & GP_LAYER_HIDE) { + continue; + } + /* Prepare transform matrix. */ + float diff_mat[4][4]; + BKE_gpencil_layer_transform_matrix_get(depsgraph, ob, gpl, diff_mat); + + bGPDframe *init_gpf = (is_multiedit) ? gpl->frames.first : gpl->actframe; + + for (bGPDframe *gpf = init_gpf; gpf; gpf = gpf->next) { + if ((gpf == gpl->actframe) || ((gpf->flag & GP_FRAME_SELECT) && (is_multiedit))) { + if (gpf == NULL) { + continue; + } + + for (bGPDstroke *gps = gpf->strokes.first; gps; gps = gps->next) { + if ((gps->flag & GP_STROKE_SELECT) == 0) { + continue; + } + if (gps->totpoints == 0) { + continue; + } + if (!ED_gpencil_stroke_material_visible(ob, gps)) { + continue; + } + + MaterialGPencilStyle *gp_style = BKE_gpencil_material_settings(ob, gps->mat_nr + 1); + const bool is_stroke = ((gp_style->flag & GP_MATERIAL_STROKE_SHOW) != 0); + + if (!is_stroke) { + continue; + } + + /* Duplicate the stroke to apply any layer thickness change. */ + bGPDstroke *gps_duplicate = BKE_gpencil_stroke_duplicate(gps, true, false); + + /* Apply layer thickness change. */ + gps_duplicate->thickness += gpl->line_change; + /* Apply object scale to thickness. */ + gps_duplicate->thickness *= mat4_to_scale(ob->obmat); + CLAMP_MIN(gps_duplicate->thickness, 1.0f); + + /* Stroke. */ + const float ovr_thickness = keep ? thickness : 0.0f; + bGPDstroke *gps_perimeter = BKE_gpencil_stroke_perimeter_from_view( + viewmat, gpd, gpl, gps_duplicate, subdivisions, diff_mat, ovr_thickness); + gps_perimeter->flag &= ~GP_STROKE_SELECT; + /* Assign material. */ + switch (material_mode) { + case GP_STROKE_USE_ACTIVE_MATERIAL: { + if (ob->actcol - 1 < 0) { + gps_perimeter->mat_nr = 0; + } + else { + gps_perimeter->mat_nr = ob->actcol - 1; + } + break; + } + case GP_STROKE_USE_CURRENT_MATERIAL: + gps_perimeter->mat_nr = gps->mat_nr; + break; + case GP_STROKE_USE_NEW_MATERIAL: + gps_perimeter->mat_nr = mat_idx; + break; + default: + break; + } + + /* Sample stroke. */ + if (length > 0.0f) { + BKE_gpencil_stroke_sample(gpd, gps_perimeter, length, false, 0); + } + /* Set stroke thickness. */ + gps_perimeter->thickness = thickness; + + /* Set pressure constant. */ + bGPDspoint *pt; + for (int i = 0; i < gps_perimeter->totpoints; i++) { + pt = &gps_perimeter->points[i]; + pt->pressure = 1.0f; + } + + /* Add perimeter stroke to frame. */ + BLI_insertlinkafter(&gpf->strokes, gps, gps_perimeter); + + /* Tag original stroke to be removed. */ + gps->flag |= GP_STROKE_TAG; + + /* Free Temp stroke. */ + BKE_gpencil_free_stroke(gps_duplicate); + changed = true; + } + + /* If not multi-edit, exit loop. */ + if (!is_multiedit) { + break; + } + } + } + } + /* Free old strokes. */ + LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) { + LISTBASE_FOREACH (bGPDframe *, gpf, &gpl->frames) { + LISTBASE_FOREACH_MUTABLE (bGPDstroke *, gps, &gpf->strokes) { + if (gps->flag & GP_STROKE_TAG) { + BLI_remlink(&gpf->strokes, gps); + BKE_gpencil_free_stroke(gps); + } + } + } + } + + if (changed) { + /* notifiers */ + DEG_id_tag_update(&gpd->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY); + WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL); + } + + return OPERATOR_FINISHED; +} + +void GPENCIL_OT_stroke_outline(wmOperatorType *ot) +{ + static const EnumPropertyItem view_mode[] = { + {GP_PERIMETER_VIEW, "VIEW", 0, "View", ""}, + {GP_PERIMETER_FRONT, "FRONT", 0, "Front", ""}, + {GP_PERIMETER_SIDE, "SIDE", 0, "Side", ""}, + {GP_PERIMETER_TOP, "TOP", 0, "Top", ""}, + {GP_PERIMETER_CAMERA, "CAMERA", 0, "Camera", ""}, + {0, NULL, 0, NULL, NULL}, + }; + static const EnumPropertyItem material_mode[] = { + {GP_STROKE_USE_ACTIVE_MATERIAL, "ACTIVE", 0, "Active Material", ""}, + {GP_STROKE_USE_CURRENT_MATERIAL, "KEEP", 0, "Keep Material", "Keep current stroke material"}, + {GP_STROKE_USE_NEW_MATERIAL, "NEW", 0, "New Material", ""}, + {0, NULL, 0, NULL, NULL}, + }; + + /* identifiers */ + ot->name = "Convert Stroke to Outline"; + ot->idname = "GPENCIL_OT_stroke_outline"; + ot->description = "Convert stroke to perimeter"; + + /* api callbacks */ + ot->exec = gpencil_stroke_outline_exec; + ot->poll = gpencil_stroke_edit_poll; + + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + + /* properties */ + ot->prop = RNA_def_enum(ot->srna, "view_mode", view_mode, GP_PERIMETER_VIEW, "View", ""); + RNA_def_enum(ot->srna, + "material_mode", + material_mode, + GP_STROKE_USE_ACTIVE_MATERIAL, + "Material Mode", + ""); + + RNA_def_int(ot->srna, + "thickness", + 1, + 1, + 1000, + "Thickness", + "Thickness of the stroke perimeter", + 1, + 1000); + RNA_def_boolean(ot->srna, + "keep", + true, + "Keep Shape", + "Try to keep global shape when the stroke thickness change"); + + RNA_def_int(ot->srna, "subdivisions", 3, 0, 10, "Subdivisions", "", 0, 10); + + RNA_def_float(ot->srna, "length", 0.0f, 0.0f, 100.0f, "Sample Length", "", 0.0f, 100.0f); +} + +/** \} */ + void GPENCIL_OT_recalc_geometry(wmOperatorType *ot) { /* identifiers */ @@ -4483,6 +4889,8 @@ void GPENCIL_OT_stroke_sample(wmOperatorType *ot) /* properties */ prop = RNA_def_float(ot->srna, "length", 0.1f, 0.0f, 100.0f, "Length", "", 0.0f, 100.0f); + prop = RNA_def_float( + ot->srna, "sharp_threshold", 0.1f, 0.0f, M_PI, "Sharp Threshold", "", 0.0f, M_PI); /* avoid re-using last var */ RNA_def_property_flag(prop, PROP_SKIP_SAVE); } diff --git a/source/blender/editors/gpencil/gpencil_fill.c b/source/blender/editors/gpencil/gpencil_fill.c index 5305c764b3a..c173a30a736 100644 --- a/source/blender/editors/gpencil/gpencil_fill.c +++ b/source/blender/editors/gpencil/gpencil_fill.c @@ -67,6 +67,7 @@ #define LEAK_HORZ 0 #define LEAK_VERT 1 +#define FILL_LEAK 3.0f #define MIN_WINDOW_SIZE 128 /* Set to 1 to debug filling internal image. By default, the value must be 0. */ @@ -78,6 +79,20 @@ enum { GP_DRAWFILLS_ONLY3D = (1 << 1), /* only draw 3d-strokes */ }; +/* Temporary stroke data including stroke extensions. */ +typedef struct tStroke { + /* Referenced layer. */ + bGPDlayer *gpl; + /** Referenced frame. */ + bGPDframe *gpf; + /** Referenced stroke. */ + bGPDstroke *gps; + /** Extreme Stroke A. */ + bGPDstroke *gps_ext_a; + /** Extreme Stroke B. */ + bGPDstroke *gps_ext_b; +} tStroke; + /* Temporary fill operation data `op->customdata`. */ typedef struct tGPDfill { bContext *C; @@ -114,7 +129,7 @@ typedef struct tGPDfill { /** For operations that require occlusion testing. */ struct ViewDepths *depths; /** flags */ - short flag; + int flag; /** avoid too fast events */ short oldkey; /** send to back stroke */ @@ -140,6 +155,8 @@ typedef struct tGPDfill { int fill_simplylvl; /** boundary limits drawing mode */ int fill_draw_mode; + /** types of extensions **/ + int fill_extend_mode; /* scaling factor */ float fill_factor; @@ -157,7 +174,7 @@ typedef struct tGPDfill { Image *ima; /** temp points data */ BLI_Stack *stack; - /** handle for drawing strokes while operator is running 3d stuff */ + /** handle for drawing strokes while operator is running 3d stuff. */ void *draw_handle_3d; /* Temporary size x. */ @@ -174,12 +191,28 @@ typedef struct tGPDfill { /** Factor of extension. */ float fill_extend_fac; - + /** Size of stroke_array. */ + int stroke_array_num; + /** Temp strokes array to handle strokes and stroke extensions. */ + tStroke **stroke_array; } tGPDfill; bool skip_layer_check(short fill_layer_mode, int gpl_active_index, int gpl_index); static void gpencil_draw_boundary_lines(const struct bContext *UNUSED(C), struct tGPDfill *tgpf); +/* Free temp stroke array. */ +static void stroke_array_free(tGPDfill *tgpf) +{ + if (tgpf->stroke_array) { + for (int i = 0; i < tgpf->stroke_array_num; i++) { + tStroke *stroke = tgpf->stroke_array[i]; + MEM_freeN(stroke); + } + MEM_SAFE_FREE(tgpf->stroke_array); + } + tgpf->stroke_array_num = 0; +} + /* Delete any temporary stroke. */ static void gpencil_delete_temp_stroke_extension(tGPDfill *tgpf, const bool all_frames) { @@ -197,7 +230,8 @@ static void gpencil_delete_temp_stroke_extension(tGPDfill *tgpf, const bool all_ for (bGPDframe *gpf = init_gpf; gpf; gpf = gpf->next) { LISTBASE_FOREACH_MUTABLE (bGPDstroke *, gps, &gpf->strokes) { /* free stroke */ - if ((gps->flag & GP_STROKE_NOFILL) && (gps->flag & GP_STROKE_TAG)) { + if ((gps->flag & GP_STROKE_NOFILL) && + (gps->flag & GP_STROKE_TAG || gps->flag & GP_STROKE_HELP)) { BLI_remlink(&gpf->strokes, gps); BKE_gpencil_free_stroke(gps); } @@ -209,6 +243,70 @@ static void gpencil_delete_temp_stroke_extension(tGPDfill *tgpf, const bool all_ } } +static bool extended_bbox_overlap( + float min1[3], float max1[3], float min2[3], float max2[3], float extend) +{ + for (int axis = 0; axis < 3; axis++) { + float intersection_min = max_ff(min1[axis], min2[axis]) - extend; + float intersection_max = min_ff(max1[axis], max2[axis]) + extend; + if (intersection_min > intersection_max) { + return false; + } + } + return true; +} + +static void add_stroke_extension(bGPDframe *gpf, bGPDstroke *gps, float p1[3], float p2[3]) +{ + bGPDstroke *gps_new = BKE_gpencil_stroke_new(gps->mat_nr, 2, gps->thickness); + gps_new->flag |= GP_STROKE_NOFILL | GP_STROKE_TAG; + BLI_addtail(&gpf->strokes, gps_new); + + bGPDspoint *pt = &gps_new->points[0]; + copy_v3_v3(&pt->x, p1); + pt->strength = 1.0f; + pt->pressure = 1.0f; + + pt = &gps_new->points[1]; + copy_v3_v3(&pt->x, p2); + pt->strength = 1.0f; + pt->pressure = 1.0f; +} + +static void add_endpoint_radius_help(tGPDfill *tgpf, + bGPDframe *gpf, + bGPDstroke *gps, + const float endpoint[3], + const float radius, + const bool focused) +{ + float circumference = 2.0f * M_PI * radius; + float vertex_spacing = 0.005f; + int num_vertices = min_ii(max_ii((int)ceilf(circumference / vertex_spacing), 3), 40); + + bGPDstroke *gps_new = BKE_gpencil_stroke_new(gps->mat_nr, num_vertices, gps->thickness); + gps_new->flag |= GP_STROKE_NOFILL | GP_STROKE_CYCLIC | GP_STROKE_HELP; + if (focused) { + gps_new->flag |= GP_STROKE_TAG; + } + BLI_addtail(&gpf->strokes, gps_new); + + for (int i = 0; i < num_vertices; i++) { + float angle = ((float)i / (float)num_vertices) * 2.0f * M_PI; + bGPDspoint *pt = &gps_new->points[i]; + pt->x = endpoint[0] + radius * cosf(angle); + pt->y = endpoint[1]; + pt->z = endpoint[2] + radius * sinf(angle); + pt->strength = 1.0f; + pt->pressure = 1.0f; + + /* Rotate to object rotation. */ + sub_v3_v3(&pt->x, endpoint); + mul_mat3_m4_v3(tgpf->ob->obmat, &pt->x); + add_v3_v3(&pt->x, endpoint); + } +} + static void extrapolate_points_by_length(bGPDspoint *a, bGPDspoint *b, float length, @@ -221,8 +319,42 @@ static void extrapolate_points_by_length(bGPDspoint *a, add_v3_v3v3(r_point, &b->x, ab); } -/* Loop all layers create stroke extensions. */ -static void gpencil_create_extensions(tGPDfill *tgpf) +/* Calculate the size of the array for strokes. */ +static void gpencil_strokes_array_size(tGPDfill *tgpf) +{ + bGPdata *gpd = tgpf->gpd; + Brush *brush = tgpf->brush; + BrushGpencilSettings *brush_settings = brush->gpencil_settings; + + bGPDlayer *gpl_active = BKE_gpencil_layer_active_get(gpd); + BLI_assert(gpl_active != NULL); + + const int gpl_active_index = BLI_findindex(&gpd->layers, gpl_active); + BLI_assert(gpl_active_index >= 0); + + tgpf->stroke_array_num = 0; + LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) { + if (gpl->flag & GP_LAYER_HIDE) { + continue; + } + + /* Decide if the strokes of layers are included or not depending on the layer mode. */ + const int gpl_index = BLI_findindex(&gpd->layers, gpl); + bool skip = skip_layer_check(brush_settings->fill_layer_mode, gpl_active_index, gpl_index); + if (skip) { + continue; + } + + bGPDframe *gpf = BKE_gpencil_layer_frame_get(gpl, tgpf->active_cfra, GP_GETFRAME_USE_PREV); + if (gpf == NULL) { + continue; + } + tgpf->stroke_array_num += BLI_listbase_count(&gpf->strokes); + } +} + +/* Load all strokes to be procesed by extend lines. */ +static void gpencil_load_array_strokes(tGPDfill *tgpf) { Object *ob = tgpf->ob; bGPdata *gpd = tgpf->gpd; @@ -235,6 +367,14 @@ static void gpencil_create_extensions(tGPDfill *tgpf) const int gpl_active_index = BLI_findindex(&gpd->layers, gpl_active); BLI_assert(gpl_active_index >= 0); + /* Create array of strokes. */ + gpencil_strokes_array_size(tgpf); + if (tgpf->stroke_array_num == 0) { + return; + } + + tgpf->stroke_array = MEM_callocN(sizeof(tStroke *) * tgpf->stroke_array_num, __func__); + int idx = 0; LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) { if (gpl->flag & GP_LAYER_HIDE) { continue; @@ -257,58 +397,379 @@ static void gpencil_create_extensions(tGPDfill *tgpf) if ((gps->points == NULL) || (gps->totpoints < 2)) { continue; } - if (gps->flag & (GP_STROKE_NOFILL | GP_STROKE_TAG)) { - continue; - } /* Check if the color is visible. */ MaterialGPencilStyle *gp_style = BKE_gpencil_material_settings(ob, gps->mat_nr + 1); if ((gp_style == NULL) || (gp_style->flag & GP_MATERIAL_HIDE)) { continue; } + /* Don't include temp strokes. */ + if ((gps->flag & GP_STROKE_NOFILL) && (gps->flag & GP_STROKE_TAG)) { + continue; + } + + tStroke *stroke = MEM_callocN(sizeof(tStroke), "temp stroke data"); + stroke->gpl = gpl; + stroke->gpf = gpf; + stroke->gps = gps; + + /* Create the extension strokes only for Lines. */ + if (tgpf->fill_extend_mode == GP_FILL_EMODE_EXTEND) { + /* Extend start. */ + bGPDspoint *pt0 = &gps->points[1]; + bGPDspoint *pt1 = &gps->points[0]; + stroke->gps_ext_a = BKE_gpencil_stroke_new(gps->mat_nr, 2, gps->thickness); + stroke->gps_ext_a->flag |= GP_STROKE_NOFILL | GP_STROKE_TAG; + stroke->gps_ext_a->fill_opacity_fac = FLT_MAX; + BLI_addtail(&gpf->strokes, stroke->gps_ext_a); + + bGPDspoint *pt = &stroke->gps_ext_a->points[0]; + copy_v3_v3(&pt->x, &pt1->x); + pt->strength = 1.0f; + pt->pressure = 1.0f; + + pt = &stroke->gps_ext_a->points[1]; + pt->strength = 1.0f; + pt->pressure = 1.0f; + + /* Extend end. */ + pt0 = &gps->points[gps->totpoints - 2]; + pt1 = &gps->points[gps->totpoints - 1]; + stroke->gps_ext_b = BKE_gpencil_stroke_new(gps->mat_nr, 2, gps->thickness); + stroke->gps_ext_b->flag |= GP_STROKE_NOFILL | GP_STROKE_TAG; + stroke->gps_ext_b->fill_opacity_fac = FLT_MAX; + BLI_addtail(&gpf->strokes, stroke->gps_ext_b); + + pt = &stroke->gps_ext_b->points[0]; + copy_v3_v3(&pt->x, &pt1->x); + pt->strength = 1.0f; + pt->pressure = 1.0f; + + pt = &stroke->gps_ext_b->points[1]; + pt->strength = 1.0f; + pt->pressure = 1.0f; + } + else { + stroke->gps_ext_a = NULL; + stroke->gps_ext_b = NULL; + } + + tgpf->stroke_array[idx] = stroke; + + idx++; + } + } + tgpf->stroke_array_num = idx; +} + +static void set_stroke_collide(bGPDstroke *gps_a, bGPDstroke *gps_b, const float connection_dist) +{ + gps_a->flag |= GP_STROKE_COLLIDE; + gps_b->flag |= GP_STROKE_COLLIDE; + + /* It uses `fill_opacity_fac` to store distance because this variable is never + * used by this type of strokes and can be used for these + * temp strokes without adding new variables to the bGPStroke struct. */ + gps_a->fill_opacity_fac = connection_dist; + gps_b->fill_opacity_fac = connection_dist; +} + +/* Cut the extended lines if collide. */ +static void gpencil_cut_extensions(tGPDfill *tgpf) +{ + const float connection_dist = tgpf->fill_extend_fac * 0.1f; + + bGPDlayer *gpl_prev = NULL; + bGPDframe *gpf_prev = NULL; + float diff_mat[4][4], inv_mat[4][4]; + + /* Allocate memory for all extend strokes. */ + bGPDstroke **gps_array = MEM_callocN(sizeof(bGPDstroke *) * tgpf->stroke_array_num * 2, + __func__); + + for (int idx = 0; idx < tgpf->stroke_array_num; idx++) { + tStroke *stroke = tgpf->stroke_array[idx]; + bGPDframe *gpf = stroke->gpf; + if (stroke->gpl != gpl_prev) { + BKE_gpencil_layer_transform_matrix_get(tgpf->depsgraph, tgpf->ob, stroke->gpl, diff_mat); + invert_m4_m4(inv_mat, diff_mat); + gpl_prev = stroke->gpl; + } + + if (gpf == gpf_prev) { + continue; + } + gpf_prev = gpf; + + /* Store all frame extend strokes in an array. */ + int tot_idx = 0; + for (int i = 0; i < tgpf->stroke_array_num; i++) { + tStroke *s = tgpf->stroke_array[i]; + if (s->gpf != gpf) { + continue; + } + if ((s->gps_ext_a) && ((s->gps_ext_a->flag & GP_STROKE_COLLIDE) == 0)) { + gps_array[tot_idx] = s->gps_ext_a; + tot_idx++; + } + if ((s->gps_ext_b) && ((s->gps_ext_b->flag & GP_STROKE_COLLIDE) == 0)) { + gps_array[tot_idx] = s->gps_ext_b; + tot_idx++; + } + } + + /* Compare all strokes. */ + for (int i = 0; i < tot_idx; i++) { + bGPDstroke *gps_a = gps_array[i]; + + bGPDspoint pt2; + float a1xy[2], a2xy[2]; + float b1xy[2], b2xy[2]; + + /* First stroke. */ + bGPDspoint *pt = &gps_a->points[0]; + gpencil_point_to_parent_space(pt, diff_mat, &pt2); + gpencil_point_to_xy_fl(&tgpf->gsc, gps_a, &pt2, &a1xy[0], &a1xy[1]); + + pt = &gps_a->points[1]; + gpencil_point_to_parent_space(pt, diff_mat, &pt2); + gpencil_point_to_xy_fl(&tgpf->gsc, gps_a, &pt2, &a2xy[0], &a2xy[1]); + bGPDspoint *extreme_a = &gps_a->points[1]; + + /* Loop all other strokes and check the intersections. */ + for (int z = 0; z < tot_idx; z++) { + bGPDstroke *gps_b = gps_array[z]; + /* Don't check stroke with itself. */ + if (i == z) { + continue; + } + + /* Don't check strokes unless the bounding boxes of the strokes + * are close enough together that they can plausibly be connected. */ + if (!extended_bbox_overlap(gps_a->boundbox_min, + gps_a->boundbox_max, + gps_b->boundbox_min, + gps_b->boundbox_max, + connection_dist)) { + continue; + } + + pt = &gps_b->points[0]; + gpencil_point_to_parent_space(pt, diff_mat, &pt2); + gpencil_point_to_xy_fl(&tgpf->gsc, gps_b, &pt2, &b1xy[0], &b1xy[1]); + + pt = &gps_b->points[1]; + gpencil_point_to_parent_space(pt, diff_mat, &pt2); + gpencil_point_to_xy_fl(&tgpf->gsc, gps_b, &pt2, &b2xy[0], &b2xy[1]); + bGPDspoint *extreme_b = &gps_b->points[1]; + + /* Check if extreme points are near. This case is when the + * extendend lines are colinear or parallel and close together. */ + const float gap_pixsize_sq = 25.0f; + float intersection3D[3]; + if (len_squared_v2v2(a2xy, b2xy) <= gap_pixsize_sq) { + gpencil_point_xy_to_3d(&tgpf->gsc, tgpf->scene, b2xy, intersection3D); + mul_m4_v3(inv_mat, intersection3D); + copy_v3_v3(&extreme_a->x, intersection3D); + copy_v3_v3(&extreme_b->x, intersection3D); + set_stroke_collide(gps_a, gps_b, connection_dist); + continue; + } + /* Check if extensions cross. */ + if (isect_seg_seg_v2_simple(a1xy, a2xy, b1xy, b2xy)) { + float intersection[2]; + isect_line_line_v2_point(a1xy, a2xy, b1xy, b2xy, intersection); + gpencil_point_xy_to_3d(&tgpf->gsc, tgpf->scene, intersection, intersection3D); + mul_m4_v3(inv_mat, intersection3D); + copy_v3_v3(&extreme_a->x, intersection3D); + copy_v3_v3(&extreme_b->x, intersection3D); + set_stroke_collide(gps_a, gps_b, connection_dist); + continue; + } + /* Check if extension extreme is near of the origin of any other extension. */ + if (len_squared_v2v2(a2xy, b1xy) <= gap_pixsize_sq) { + gpencil_point_xy_to_3d(&tgpf->gsc, tgpf->scene, b1xy, &extreme_a->x); + mul_m4_v3(inv_mat, &extreme_a->x); + set_stroke_collide(gps_a, gps_b, connection_dist); + continue; + } + if (len_squared_v2v2(a1xy, b2xy) <= gap_pixsize_sq) { + gpencil_point_xy_to_3d(&tgpf->gsc, tgpf->scene, a1xy, &extreme_b->x); + mul_m4_v3(inv_mat, &extreme_b->x); + set_stroke_collide(gps_a, gps_b, connection_dist); + } + } + } + } + MEM_SAFE_FREE(gps_array); +} + +/* Loop all strokes and update stroke line extensions. */ +static void gpencil_update_extensions_line(tGPDfill *tgpf) +{ + float connection_dist = tgpf->fill_extend_fac * 0.1f; - /* Extend start. */ + for (int idx = 0; idx < tgpf->stroke_array_num; idx++) { + tStroke *stroke = tgpf->stroke_array[idx]; + bGPDstroke *gps = stroke->gps; + bGPDstroke *gps_a = stroke->gps_ext_a; + bGPDstroke *gps_b = stroke->gps_ext_b; + + /* Extend start. */ + if (((gps_a->flag & GP_STROKE_COLLIDE) == 0) || (gps_a->fill_opacity_fac > connection_dist)) { bGPDspoint *pt0 = &gps->points[1]; bGPDspoint *pt1 = &gps->points[0]; - bGPDstroke *gps_new = BKE_gpencil_stroke_new(gps->mat_nr, 2, gps->thickness); - gps_new->flag |= GP_STROKE_NOFILL | GP_STROKE_TAG; - BLI_addtail(&gpf->strokes, gps_new); - - bGPDspoint *pt = &gps_new->points[0]; - copy_v3_v3(&pt->x, &pt1->x); - pt->strength = 1.0f; - pt->pressure = 1.0f; - - pt = &gps_new->points[1]; - pt->strength = 1.0f; - pt->pressure = 1.0f; - extrapolate_points_by_length(pt0, pt1, tgpf->fill_extend_fac * 0.1f, &pt->x); - - /* Extend end. */ - pt0 = &gps->points[gps->totpoints - 2]; - pt1 = &gps->points[gps->totpoints - 1]; - gps_new = BKE_gpencil_stroke_new(gps->mat_nr, 2, gps->thickness); - gps_new->flag |= GP_STROKE_NOFILL | GP_STROKE_TAG; - BLI_addtail(&gpf->strokes, gps_new); - - pt = &gps_new->points[0]; - copy_v3_v3(&pt->x, &pt1->x); - pt->strength = 1.0f; - pt->pressure = 1.0f; - - pt = &gps_new->points[1]; - pt->strength = 1.0f; - pt->pressure = 1.0f; - extrapolate_points_by_length(pt0, pt1, tgpf->fill_extend_fac * 0.1f, &pt->x); + bGPDspoint *pt = &gps_a->points[1]; + extrapolate_points_by_length(pt0, pt1, connection_dist, &pt->x); + gps_a->flag &= ~GP_STROKE_COLLIDE; + } + + /* Extend end. */ + if (((gps_b->flag & GP_STROKE_COLLIDE) == 0) || (gps_b->fill_opacity_fac > connection_dist)) { + bGPDspoint *pt0 = &gps->points[gps->totpoints - 2]; + bGPDspoint *pt1 = &gps->points[gps->totpoints - 1]; + bGPDspoint *pt = &gps_b->points[1]; + extrapolate_points_by_length(pt0, pt1, connection_dist, &pt->x); + gps_b->flag &= ~GP_STROKE_COLLIDE; } } + + /* Cut overlength strokes. */ + gpencil_cut_extensions(tgpf); +} + +/* Loop all strokes and create stroke radius extensions. */ +static void gpencil_create_extensions_radius(tGPDfill *tgpf) +{ + float connection_dist = tgpf->fill_extend_fac * 0.1f; + GSet *connected_endpoints = BLI_gset_ptr_new(__func__); + + for (int idx = 0; idx < tgpf->stroke_array_num; idx++) { + tStroke *stroke = tgpf->stroke_array[idx]; + bGPDframe *gpf = stroke->gpf; + bGPDstroke *gps = stroke->gps; + + /* Find points of high curvature. */ + float tan1[3]; + float tan2[3]; + float d1; + float d2; + float total_length = 0.f; + for (int i = 1; i < gps->totpoints; i++) { + if (i > 1) { + copy_v3_v3(tan1, tan2); + d1 = d2; + } + bGPDspoint *pt1 = &gps->points[i - 1]; + bGPDspoint *pt2 = &gps->points[i]; + sub_v3_v3v3(tan2, &pt2->x, &pt1->x); + d2 = normalize_v3(tan2); + total_length += d2; + if (i > 1) { + float curvature[3]; + sub_v3_v3v3(curvature, tan2, tan1); + float k = normalize_v3(curvature); + k /= min_ff(d1, d2); + float radius = 1.f / k; + /* + * The smaller the radius of curvature, the sharper the corner. + * The thicker the line, the larger the radius of curvature it + * takes to be visually indistinguishable from an endpoint. + */ + float min_radius = gps->thickness * 0.0001f; + + if (radius < min_radius) { + /* Extend along direction of curvature. */ + bGPDstroke *gps_new = BKE_gpencil_stroke_new(gps->mat_nr, 2, gps->thickness); + gps_new->flag |= GP_STROKE_NOFILL | GP_STROKE_TAG; + BLI_addtail(&gpf->strokes, gps_new); + + bGPDspoint *pt = &gps_new->points[0]; + copy_v3_v3(&pt->x, &pt1->x); + pt->strength = 1.0f; + pt->pressure = 1.0f; + + pt = &gps_new->points[1]; + pt->strength = 1.0f; + pt->pressure = 1.0f; + mul_v3_fl(curvature, -connection_dist); + add_v3_v3v3(&pt->x, &pt1->x, curvature); + } + } + } + + /* Connect endpoints within a radius */ + float *stroke1_start = &gps->points[0].x; + float *stroke1_end = &gps->points[gps->totpoints - 1].x; + /* Connect the start of the stroke to its own end if the whole stroke + * isn't already so short that it's within that distance + */ + if (len_v3v3(stroke1_start, stroke1_end) < connection_dist && total_length > connection_dist) { + add_stroke_extension(gpf, gps, stroke1_start, stroke1_end); + BLI_gset_add(connected_endpoints, stroke1_start); + BLI_gset_add(connected_endpoints, stroke1_end); + } + for (bGPDstroke *gps2 = (bGPDstroke *)(((Link *)gps)->next); gps2 != NULL; + gps2 = (bGPDstroke *)(((Link *)gps2)->next)) { + /* Don't check distance to temporary extensions. */ + if ((gps2->flag & GP_STROKE_NOFILL) && (gps2->flag & GP_STROKE_TAG)) { + continue; + } + + /* Don't check endpoint distances unless the bounding boxes of the strokes + are close enough together that they can plausibly be connected. */ + if (!extended_bbox_overlap(gps->boundbox_min, + gps->boundbox_max, + gps2->boundbox_min, + gps2->boundbox_max, + connection_dist)) { + continue; + } + + float *stroke2_start = &gps2->points[0].x; + float *stroke2_end = &gps2->points[gps2->totpoints - 1].x; + if (len_v3v3(stroke1_start, stroke2_start) < connection_dist) { + add_stroke_extension(gpf, gps, stroke1_start, stroke2_start); + BLI_gset_add(connected_endpoints, stroke1_start); + BLI_gset_add(connected_endpoints, stroke2_start); + } + if (len_v3v3(stroke1_start, stroke2_end) < connection_dist) { + add_stroke_extension(gpf, gps, stroke1_start, stroke2_end); + BLI_gset_add(connected_endpoints, stroke1_start); + BLI_gset_add(connected_endpoints, stroke2_end); + } + if (len_v3v3(stroke1_end, stroke2_start) < connection_dist) { + add_stroke_extension(gpf, gps, stroke1_end, stroke2_start); + BLI_gset_add(connected_endpoints, stroke1_end); + BLI_gset_add(connected_endpoints, stroke2_start); + } + if (len_v3v3(stroke1_end, stroke2_end) < connection_dist) { + add_stroke_extension(gpf, gps, stroke1_end, stroke2_end); + BLI_gset_add(connected_endpoints, stroke1_end); + BLI_gset_add(connected_endpoints, stroke2_end); + } + } + + bool start_connected = BLI_gset_haskey(connected_endpoints, stroke1_start); + bool end_connected = BLI_gset_haskey(connected_endpoints, stroke1_end); + add_endpoint_radius_help(tgpf, gpf, gps, stroke1_start, connection_dist, start_connected); + add_endpoint_radius_help(tgpf, gpf, gps, stroke1_end, connection_dist, end_connected); + } + + BLI_gset_free(connected_endpoints, NULL); } static void gpencil_update_extend(tGPDfill *tgpf) { - gpencil_delete_temp_stroke_extension(tgpf, false); + if (tgpf->stroke_array == NULL) { + gpencil_load_array_strokes(tgpf); + } - if (tgpf->fill_extend_fac > 0.0f) { - gpencil_create_extensions(tgpf); + if (tgpf->fill_extend_mode == GP_FILL_EMODE_EXTEND) { + gpencil_update_extensions_line(tgpf); + } + else { + gpencil_delete_temp_stroke_extension(tgpf, false); + gpencil_create_extensions_radius(tgpf); } WM_event_add_notifier(tgpf->C, NC_GPENCIL | NA_EDITED, NULL); } @@ -322,15 +783,16 @@ static bool gpencil_stroke_is_drawable(tGPDfill *tgpf, bGPDstroke *gps) const bool show_help = (tgpf->flag & GP_BRUSH_FILL_SHOW_HELPLINES) != 0; const bool show_extend = (tgpf->flag & GP_BRUSH_FILL_SHOW_EXTENDLINES) != 0; const bool is_extend = (gps->flag & GP_STROKE_NOFILL) && (gps->flag & GP_STROKE_TAG); + const bool is_extend_help = (gps->flag & GP_STROKE_NOFILL) && (gps->flag & GP_STROKE_HELP); if ((!show_help) && (show_extend)) { - if (!is_extend) { + if (!is_extend && !is_extend_help) { return false; } } if ((show_help) && (!show_extend)) { - if (is_extend) { + if (is_extend || is_extend_help) { return false; } } @@ -357,13 +819,29 @@ static void gpencil_draw_basic_stroke(tGPDfill *tgpf, float fpt[3]; float col[4]; const float extend_col[4] = {0.0f, 1.0f, 1.0f, 1.0f}; - const bool is_extend = (gps->flag & GP_STROKE_NOFILL) && (gps->flag & GP_STROKE_TAG); + const float help_col[4] = {1.0f, 0.0f, 0.5f, 1.0f}; + const bool is_extend = (gps->flag & GP_STROKE_NOFILL) && (gps->flag & GP_STROKE_TAG) && + !(gps->flag & GP_STROKE_HELP); + const bool is_help = gps->flag & GP_STROKE_HELP; if (!gpencil_stroke_is_drawable(tgpf, gps)) { return; } - if ((is_extend) && (!tgpf->is_render)) { + if (is_help && tgpf->is_render) { + /* Help strokes are for display only and shouldn't render. */ + return; + } + else if (is_help) { + /* Color help strokes that won't affect fill or render separately from + * extended strokes, as they will affect them. */ + copy_v4_v4(col, help_col); + + /* If there is contact, hide the circles to avoid noise and keep the focus + * in the pending gaps. */ + col[3] = (gps->flag & GP_STROKE_TAG) ? 0.0f : 0.5f; + } + else if ((is_extend) && (!tgpf->is_render)) { copy_v4_v4(col, extend_col); } else { @@ -379,7 +857,7 @@ static void gpencil_draw_basic_stroke(tGPDfill *tgpf, immBindBuiltinProgram(GPU_SHADER_3D_FLAT_COLOR); /* draw stroke curve */ - GPU_line_width((!is_extend) ? thickness : thickness * 2.0f); + GPU_line_width((!is_extend && !is_help) ? thickness : thickness * 2.0f); immBeginAtMost(GPU_PRIM_LINE_STRIP, totpoints + cyclic_add); const bGPDspoint *pt = points; @@ -390,7 +868,7 @@ static void gpencil_draw_basic_stroke(tGPDfill *tgpf, CLAMP(alpha, 0.0f, 1.0f); col[3] = alpha <= thershold ? 0.0f : 1.0f; } - else { + else if (!is_help) { col[3] = 1.0f; } /* set point */ @@ -582,7 +1060,8 @@ static void gpencil_draw_datablock(tGPDfill *tgpf, const float ink[4]) /* Normal strokes. */ if (ELEM(tgpf->fill_draw_mode, GP_FILL_DMODE_STROKE, GP_FILL_DMODE_BOTH)) { - if (gpencil_stroke_is_drawable(tgpf, gps) && ((gps->flag & GP_STROKE_TAG) == 0)) { + if (gpencil_stroke_is_drawable(tgpf, gps) && ((gps->flag & GP_STROKE_TAG) == 0) && + ((gps->flag & GP_STROKE_HELP) == 0)) { ED_gpencil_draw_fill(&tgpw); } } @@ -1677,7 +2156,8 @@ static void gpencil_stroke_from_buffer(tGPDfill *tgpf) /* Helper: Draw status message while the user is running the operator */ static void gpencil_fill_status_indicators(bContext *C) { - const char *status_str = TIP_("Fill: ESC/RMB cancel, LMB Fill, Shift Draw on Back"); + const char *status_str = TIP_( + "Fill: ESC/RMB cancel, LMB Fill, Shift Draw on Back, S: Switch Mode"); ED_workspace_status_text(C, status_str); } @@ -1777,13 +2257,17 @@ static tGPDfill *gpencil_session_init_fill(bContext *C, wmOperator *op) tgpf->fill_threshold = brush->gpencil_settings->fill_threshold; tgpf->fill_simplylvl = brush->gpencil_settings->fill_simplylvl; tgpf->fill_draw_mode = brush->gpencil_settings->fill_draw_mode; + tgpf->fill_extend_mode = brush->gpencil_settings->fill_extend_mode; tgpf->fill_extend_fac = brush->gpencil_settings->fill_extend_fac; tgpf->fill_factor = max_ff(GPENCIL_MIN_FILL_FAC, min_ff(brush->gpencil_settings->fill_factor, GPENCIL_MAX_FILL_FAC)); - tgpf->fill_leak = (int)ceil((float)brush->gpencil_settings->fill_leak * tgpf->fill_factor); + tgpf->fill_leak = (int)ceil(FILL_LEAK * tgpf->fill_factor); int totcol = tgpf->ob->totcol; + /* Extensions array */ + tgpf->stroke_array = NULL; + /* get color info */ Material *ma = BKE_gpencil_object_material_ensure_from_active_input_brush( bmain, tgpf->ob, brush); @@ -1832,6 +2316,9 @@ static void gpencil_fill_exit(bContext *C, wmOperator *op) MEM_SAFE_FREE(tgpf->sbuffer); MEM_SAFE_FREE(tgpf->depth_arr); + /* Clean temp strokes. */ + stroke_array_free(tgpf); + /* Remove any temp stroke. */ gpencil_delete_temp_stroke_extension(tgpf, true); @@ -1928,9 +2415,8 @@ static int gpencil_fill_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSE tgpf = op->customdata; /* Enable custom drawing handlers to show help lines */ - const bool do_extend = (tgpf->fill_extend_fac > 0.0f); - const bool help_lines = ((tgpf->flag & GP_BRUSH_FILL_SHOW_HELPLINES) || - ((tgpf->flag & GP_BRUSH_FILL_SHOW_EXTENDLINES) && (do_extend))); + const bool do_extend = (tgpf->flag & GP_BRUSH_FILL_SHOW_EXTENDLINES); + const bool help_lines = ((tgpf->flag & GP_BRUSH_FILL_SHOW_HELPLINES) || (do_extend)); if (help_lines) { tgpf->draw_handle_3d = ED_region_draw_cb_activate( @@ -2179,9 +2665,8 @@ static int gpencil_fill_modal(bContext *C, wmOperator *op, const wmEvent *event) const bool is_inverted = (is_brush_inv && (event->modifier & KM_CTRL) == 0) || (!is_brush_inv && (event->modifier & KM_CTRL) != 0); const bool is_multiedit = (bool)GPENCIL_MULTIEDIT_SESSIONS_ON(tgpf->gpd); - const bool do_extend = (tgpf->fill_extend_fac > 0.0f); - const bool help_lines = ((tgpf->flag & GP_BRUSH_FILL_SHOW_HELPLINES) || - ((tgpf->flag & GP_BRUSH_FILL_SHOW_EXTENDLINES) && (do_extend))); + const bool do_extend = (tgpf->flag & GP_BRUSH_FILL_SHOW_EXTENDLINES); + const bool help_lines = ((tgpf->flag & GP_BRUSH_FILL_SHOW_HELPLINES) || (do_extend)); int estate = OPERATOR_RUNNING_MODAL; switch (event->type) { @@ -2315,6 +2800,22 @@ static int gpencil_fill_modal(bContext *C, wmOperator *op, const wmEvent *event) } tgpf->oldkey = event->type; break; + case EVT_SKEY: + if ((do_extend) && (event->val == KM_PRESS)) { + /* Clean temp strokes. */ + stroke_array_free(tgpf); + + /* Toogle mode */ + if (tgpf->fill_extend_mode == GP_FILL_EMODE_EXTEND) { + tgpf->fill_extend_mode = GP_FILL_EMODE_RADIUS; + } + else { + tgpf->fill_extend_mode = GP_FILL_EMODE_EXTEND; + } + gpencil_delete_temp_stroke_extension(tgpf, true); + gpencil_update_extend(tgpf); + } + break; case EVT_PAGEUPKEY: case WHEELUPMOUSE: if (tgpf->oldkey == 1) { diff --git a/source/blender/editors/gpencil/gpencil_intern.h b/source/blender/editors/gpencil/gpencil_intern.h index d656241c463..4d62f834d86 100644 --- a/source/blender/editors/gpencil/gpencil_intern.h +++ b/source/blender/editors/gpencil/gpencil_intern.h @@ -593,6 +593,7 @@ void GPENCIL_OT_stroke_cyclical_set(struct wmOperatorType *ot); */ void GPENCIL_OT_stroke_caps_set(struct wmOperatorType *ot); void GPENCIL_OT_stroke_join(struct wmOperatorType *ot); +void GPENCIL_OT_stroke_start_set(struct wmOperatorType *ot); void GPENCIL_OT_stroke_flip(struct wmOperatorType *ot); void GPENCIL_OT_stroke_subdivide(struct wmOperatorType *ot); void GPENCIL_OT_stroke_simplify(struct wmOperatorType *ot); @@ -608,6 +609,7 @@ void GPENCIL_OT_stroke_merge_by_distance(struct wmOperatorType *ot); void GPENCIL_OT_stroke_merge_material(struct wmOperatorType *ot); void GPENCIL_OT_stroke_reset_vertex_color(struct wmOperatorType *ot); void GPENCIL_OT_stroke_normalize(struct wmOperatorType *ot); +void GPENCIL_OT_stroke_outline(struct wmOperatorType *ot); void GPENCIL_OT_material_to_vertex_color(struct wmOperatorType *ot); void GPENCIL_OT_extract_palette_vertex(struct wmOperatorType *ot); diff --git a/source/blender/editors/gpencil/gpencil_interpolate.c b/source/blender/editors/gpencil/gpencil_interpolate.c index e7a4f2fe2dc..dc63acf5136 100644 --- a/source/blender/editors/gpencil/gpencil_interpolate.c +++ b/source/blender/editors/gpencil/gpencil_interpolate.c @@ -1483,7 +1483,8 @@ void GPENCIL_OT_interpolate_sequence(wmOperatorType *ot) */ static const EnumPropertyItem gpencil_interpolation_type_items[] = { /* Interpolation. */ - RNA_ENUM_ITEM_HEADING(N_("Interpolation"), "Standard transitions between keyframes"), + RNA_ENUM_ITEM_HEADING(CTX_N_(BLT_I18NCONTEXT_ID_GPENCIL, "Interpolation"), + N_("Standard transitions between keyframes")), {GP_IPO_LINEAR, "LINEAR", ICON_IPO_LINEAR, @@ -1496,9 +1497,9 @@ void GPENCIL_OT_interpolate_sequence(wmOperatorType *ot) "Custom interpolation defined using a curve map"}, /* Easing. */ - RNA_ENUM_ITEM_HEADING(N_("Easing (by strength)"), - "Predefined inertial transitions, useful for motion graphics " - "(from least to most \"dramatic\")"), + RNA_ENUM_ITEM_HEADING(CTX_N_(BLT_I18NCONTEXT_ID_GPENCIL, "Easing (by strength)"), + N_("Predefined inertial transitions, useful for motion graphics " + "(from least to most \"dramatic\")")), {GP_IPO_SINE, "SINE", ICON_IPO_SINE, @@ -1515,7 +1516,8 @@ void GPENCIL_OT_interpolate_sequence(wmOperatorType *ot) "Circular", "Circular easing (strongest and most dynamic)"}, - RNA_ENUM_ITEM_HEADING(N_("Dynamic Effects"), "Simple physics-inspired easing effects"), + RNA_ENUM_ITEM_HEADING(CTX_N_(BLT_I18NCONTEXT_ID_GPENCIL, "Dynamic Effects"), + N_("Simple physics-inspired easing effects")), {GP_IPO_BACK, "BACK", ICON_IPO_BACK, "Back", "Cubic easing with overshoot and settle"}, {GP_IPO_BOUNCE, "BOUNCE", @@ -1569,6 +1571,7 @@ void GPENCIL_OT_interpolate_sequence(wmOperatorType *ot) /* identifiers */ ot->name = "Interpolate Sequence"; ot->idname = "GPENCIL_OT_interpolate_sequence"; + ot->translation_context = BLT_I18NCONTEXT_ID_GPENCIL; ot->description = "Generate 'in-betweens' to smoothly interpolate between Grease Pencil frames"; /* api callbacks */ diff --git a/source/blender/editors/gpencil/gpencil_mesh.cc b/source/blender/editors/gpencil/gpencil_mesh.cc index b27e1c75746..739a1b319c3 100644 --- a/source/blender/editors/gpencil/gpencil_mesh.cc +++ b/source/blender/editors/gpencil/gpencil_mesh.cc @@ -213,7 +213,7 @@ static int gpencil_bake_mesh_animation_exec(bContext *C, wmOperator *op) bool newob = false; if (target == GP_TARGET_OB_SELECTED) { - ob_gpencil = BKE_view_layer_non_active_selected_object(CTX_data_view_layer(C), v3d); + ob_gpencil = BKE_view_layer_non_active_selected_object(scene, CTX_data_view_layer(C), v3d); if (ob_gpencil != nullptr) { if (ob_gpencil->type != OB_GPENCIL) { BKE_report(op->reports, RPT_WARNING, "Target object not a grease pencil, ignoring!"); @@ -315,7 +315,7 @@ static int gpencil_bake_mesh_animation_exec(bContext *C, wmOperator *op) LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) { if ((gps->flag & GP_STROKE_TAG) == 0) { ED_gpencil_stroke_reproject( - depsgraph, &gsc, sctx, gpl, gpf, gps, project_type, false); + depsgraph, &gsc, sctx, gpl, gpf, gps, project_type, false, 0.0f); gps->flag |= GP_STROKE_TAG; } } diff --git a/source/blender/editors/gpencil/gpencil_ops.c b/source/blender/editors/gpencil/gpencil_ops.c index 99e28270c3e..85cc281ca90 100644 --- a/source/blender/editors/gpencil/gpencil_ops.c +++ b/source/blender/editors/gpencil/gpencil_ops.c @@ -621,6 +621,7 @@ void ED_operatortypes_gpencil(void) WM_operatortype_append(GPENCIL_OT_stroke_caps_set); WM_operatortype_append(GPENCIL_OT_stroke_join); WM_operatortype_append(GPENCIL_OT_stroke_flip); + WM_operatortype_append(GPENCIL_OT_stroke_start_set); WM_operatortype_append(GPENCIL_OT_stroke_subdivide); WM_operatortype_append(GPENCIL_OT_stroke_simplify); WM_operatortype_append(GPENCIL_OT_stroke_simplify_fixed); @@ -635,6 +636,7 @@ void ED_operatortypes_gpencil(void) WM_operatortype_append(GPENCIL_OT_stroke_merge_material); WM_operatortype_append(GPENCIL_OT_stroke_reset_vertex_color); WM_operatortype_append(GPENCIL_OT_stroke_normalize); + WM_operatortype_append(GPENCIL_OT_stroke_outline); WM_operatortype_append(GPENCIL_OT_material_to_vertex_color); WM_operatortype_append(GPENCIL_OT_extract_palette_vertex); diff --git a/source/blender/editors/gpencil/gpencil_ops_versioning.c b/source/blender/editors/gpencil/gpencil_ops_versioning.c index 8119646137c..50fbafff732 100644 --- a/source/blender/editors/gpencil/gpencil_ops_versioning.c +++ b/source/blender/editors/gpencil/gpencil_ops_versioning.c @@ -92,7 +92,7 @@ static int gpencil_convert_old_files_exec(bContext *C, wmOperator *op) if ((!is_annotation) && (view_layer != NULL)) { Object *ob; ob = BKE_object_add_for_data( - bmain, view_layer, OB_GPENCIL, "GP_Scene", &scene->gpd->id, false); + bmain, scene, view_layer, OB_GPENCIL, "GP_Scene", &scene->gpd->id, false); zero_v3(ob->loc); DEG_relations_tag_update(bmain); /* added object */ diff --git a/source/blender/editors/gpencil/gpencil_paint.c b/source/blender/editors/gpencil/gpencil_paint.c index 13ea5179b23..7446c727a0c 100644 --- a/source/blender/editors/gpencil/gpencil_paint.c +++ b/source/blender/editors/gpencil/gpencil_paint.c @@ -918,6 +918,67 @@ static void gpencil_stroke_unselect(bGPdata *gpd, bGPDstroke *gps) } } +static bGPDstroke *gpencil_stroke_to_outline(tGPsdata *p, bGPDstroke *gps) +{ + bGPDlayer *gpl = p->gpl; + RegionView3D *rv3d = p->region->regiondata; + Brush *brush = p->brush; + BrushGpencilSettings *gpencil_settings = brush->gpencil_settings; + MaterialGPencilStyle *gp_style = BKE_gpencil_material_settings(p->ob, gps->mat_nr + 1); + const bool is_stroke = ((gp_style->flag & GP_MATERIAL_STROKE_SHOW) != 0); + + if (!is_stroke) { + return gps; + } + + /* Duplicate the stroke to apply any layer thickness change. */ + bGPDstroke *gps_duplicate = BKE_gpencil_stroke_duplicate(gps, true, false); + + /* Apply layer thickness change. */ + gps_duplicate->thickness += gpl->line_change; + /* Apply object scale to thickness. */ + gps_duplicate->thickness *= mat4_to_scale(p->ob->obmat); + CLAMP_MIN(gps_duplicate->thickness, 1.0f); + + /* Stroke. */ + float diff_mat[4][4]; + unit_m4(diff_mat); + const float outline_thickness = (float)brush->size * gpencil_settings->outline_fac * 0.5f; + bGPDstroke *gps_perimeter = BKE_gpencil_stroke_perimeter_from_view( + rv3d->viewmat, p->gpd, gpl, gps_duplicate, 3, diff_mat, outline_thickness); + /* Assign material. */ + if (gpencil_settings->material_alt == NULL) { + gps_perimeter->mat_nr = gps->mat_nr; + } + else { + Material *ma = gpencil_settings->material_alt; + int mat_idx = BKE_gpencil_material_find_index_by_name_prefix(p->ob, ma->id.name + 2); + if (mat_idx > -1) { + gps_perimeter->mat_nr = mat_idx; + } + else { + gps_perimeter->mat_nr = gps->mat_nr; + } + } + + /* Set pressure constant. */ + gps_perimeter->thickness = max_ii((int)outline_thickness, 1); + + bGPDspoint *pt; + for (int i = 0; i < gps_perimeter->totpoints; i++) { + pt = &gps_perimeter->points[i]; + pt->pressure = 1.0f; + } + + /* Remove original stroke. */ + BKE_gpencil_free_stroke(gps); + + /* Free Temp stroke. */ + BKE_gpencil_free_stroke(gps_duplicate); + + return gps_perimeter; +} + /* make a new stroke from the buffer data */ static void gpencil_stroke_newfrombuffer(tGPsdata *p) { @@ -1221,6 +1282,23 @@ static void gpencil_stroke_newfrombuffer(tGPsdata *p) BKE_gpencil_stroke_simplify_adaptive(gpd, gps, brush->gpencil_settings->simplify_f); } + /* Set material index. */ + gps->mat_nr = BKE_gpencil_object_material_get_index_from_brush(p->ob, p->brush); + if (gps->mat_nr < 0) { + if (p->ob->actcol - 1 < 0) { + gps->mat_nr = 0; + } + else { + gps->mat_nr = p->ob->actcol - 1; + } + } + + /* Convert to Outline. */ + if ((brush->gpencil_settings->flag & GP_BRUSH_GROUP_SETTINGS) && + (brush->gpencil_settings->flag & GP_BRUSH_OUTLINE_STROKE)) { + gps = gpencil_stroke_to_outline(p, gps); + } + /* reproject to plane (only in 3d space) */ gpencil_reproject_toplane(p, gps); /* change position relative to parent object */ @@ -1235,17 +1313,6 @@ static void gpencil_stroke_newfrombuffer(tGPsdata *p) } } - /* Save material index */ - gps->mat_nr = BKE_gpencil_object_material_get_index_from_brush(p->ob, p->brush); - if (gps->mat_nr < 0) { - if (p->ob->actcol - 1 < 0) { - gps->mat_nr = 0; - } - else { - gps->mat_nr = p->ob->actcol - 1; - } - } - /* add stroke to frame, usually on tail of the listbase, but if on back is enabled the stroke * is added on listbase head because the drawing order is inverse and the head stroke is the * first to draw. This is very useful for artist when drawing the background. @@ -2343,7 +2410,7 @@ static void gpencil_draw_eraser(bContext *UNUSED(C), int x, int y, void *p_ptr) if (p->paintmode == GP_PAINTMODE_ERASER) { GPUVertFormat *format = immVertexFormat(); const uint shdr_pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); - immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); GPU_line_smooth(true); GPU_blend(GPU_BLEND_ALPHA); @@ -2353,7 +2420,7 @@ static void gpencil_draw_eraser(bContext *UNUSED(C), int x, int y, void *p_ptr) immUnbindProgram(); - immBindBuiltinProgram(GPU_SHADER_2D_LINE_DASHED_UNIFORM_COLOR); + immBindBuiltinProgram(GPU_SHADER_3D_LINE_DASHED_UNIFORM_COLOR); float viewport_size[4]; GPU_viewport_size_get_f(viewport_size); @@ -3264,7 +3331,7 @@ static int gpencil_draw_invoke(bContext *C, wmOperator *op, const wmEvent *event return OPERATOR_RUNNING_MODAL; } -/* gpencil modal operator stores area, which can be removed while using it (like fullscreen) */ +/* gpencil modal operator stores area, which can be removed while using it (like full-screen). */ static bool gpencil_area_exists(bContext *C, ScrArea *area_test) { bScreen *screen = CTX_wm_screen(C); @@ -3658,9 +3725,7 @@ static int gpencil_draw_modal(bContext *C, wmOperator *op, const wmEvent *event) } } - /* Exit painting mode (and/or end current stroke). - * - */ + /* Exit painting mode (and/or end current stroke). */ if (ELEM(event->type, EVT_RETKEY, EVT_PADENTER, EVT_ESCKEY, EVT_SPACEKEY)) { p->status = GP_STATUS_DONE; @@ -3823,7 +3888,7 @@ static int gpencil_draw_modal(bContext *C, wmOperator *op, const wmEvent *event) } } - /* gpencil modal operator stores area, which can be removed while using it (like fullscreen) */ + /* gpencil modal operator stores area, which can be removed while using it (like full-screen). */ if (0 == gpencil_area_exists(C, p->area)) { estate = OPERATOR_CANCELLED; } diff --git a/source/blender/editors/gpencil/gpencil_primitive.c b/source/blender/editors/gpencil/gpencil_primitive.c index 70f12151fdd..4a4fffc9638 100644 --- a/source/blender/editors/gpencil/gpencil_primitive.c +++ b/source/blender/editors/gpencil/gpencil_primitive.c @@ -1024,8 +1024,10 @@ static void gpencil_primitive_update_strokes(bContext *C, tGPDprimitive *tgpi) gpd->runtime.sbuffer, &gpd->runtime.sbuffer_size, &gpd->runtime.sbuffer_used, false); /* add small offset to keep stroke over the surface */ - if ((depth_arr) && (gpd->zdepth_offset > 0.0f) && (depth_arr[i] != DEPTH_INVALID)) { - depth_arr[i] *= (1.0f - (gpd->zdepth_offset / 1000.0f)); + if (ts->gpencil_v3d_align & GP_PROJECT_DEPTH_VIEW) { + if ((depth_arr) && (gpd->zdepth_offset > 0.0f) && (depth_arr[i] != DEPTH_INVALID)) { + depth_arr[i] *= (1.0f - (gpd->zdepth_offset / 1000.0f)); + } } /* convert screen-coordinates to 3D coordinates */ diff --git a/source/blender/editors/gpencil/gpencil_sculpt_paint.c b/source/blender/editors/gpencil/gpencil_sculpt_paint.c index e27cd255217..52e6200978c 100644 --- a/source/blender/editors/gpencil/gpencil_sculpt_paint.c +++ b/source/blender/editors/gpencil/gpencil_sculpt_paint.c @@ -516,7 +516,7 @@ static void gpencil_brush_grab_calc_dvec(tGP_BrushEditData *gso) float mval_f[2]; - /* convert from 2D screenspace to 3D... */ + /* Convert from 2D screen-space to 3D. */ mval_f[0] = (float)(gso->mval[0] - gso->mval_prev[0]); mval_f[1] = (float)(gso->mval[1] - gso->mval_prev[1]); @@ -700,8 +700,8 @@ static bool gpencil_brush_pinch_apply(tGP_BrushEditData *gso, /* ----------------------------------------------- */ /* Twist Brush - Rotate Around midpoint */ -/* Take the screenspace coordinates of the point, rotate this around the brush midpoint, - * convert the rotated point and convert it into "data" space +/* Take the screen-space coordinates of the point, rotate this around the brush midpoint, + * convert the rotated point and convert it into "data" space. */ static bool gpencil_brush_twist_apply(tGP_BrushEditData *gso, @@ -807,7 +807,7 @@ static bool gpencil_brush_randomize_apply(tGP_BrushEditData *gso, /* apply random to position */ if (gso->brush->gpencil_settings->sculpt_mode_flag & GP_SCULPT_FLAGMODE_APPLY_POSITION) { /* Jitter is applied perpendicular to the mouse movement vector - * - We compute all effects in screenspace (since it's easier) + * - We compute all effects in screen-space (since it's easier) * and then project these to get the points/distances in * view-space as needed. */ @@ -989,8 +989,8 @@ static void gpencil_brush_clone_add(bContext *C, tGP_BrushEditData *gso) float delta[3]; size_t strokes_added = 0; - /* Compute amount to offset the points by */ - /* NOTE: This assumes that screenspace strokes are NOT used in the 3D view... */ + /* Compute amount to offset the points by. */ + /* NOTE: This assumes that screen-space strokes are NOT used in the 3D view. */ gpencil_brush_calc_midpoint(gso); /* this puts the cursor location into gso->dvec */ sub_v3_v3v3(delta, gso->dvec, data->buffer_midpoint); @@ -1063,7 +1063,7 @@ static void gpencil_brush_clone_adjust(tGP_BrushEditData *gso) /* For each of the stored strokes, apply the offset to each point */ /* NOTE: Again this assumes that in the 3D view, - * we only have 3d space and not screenspace strokes... */ + * we only have 3d space and not screen-space strokes. */ for (snum = 0; snum < data->totitems; snum++) { bGPDstroke *gps = data->new_strokes[snum]; bGPDspoint *pt; diff --git a/source/blender/editors/gpencil/gpencil_select.c b/source/blender/editors/gpencil/gpencil_select.c index a19265720e8..95f43733a36 100644 --- a/source/blender/editors/gpencil/gpencil_select.c +++ b/source/blender/editors/gpencil/gpencil_select.c @@ -2071,7 +2071,7 @@ static bool gpencil_generic_stroke_select(bContext *C, for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) { bGPDspoint *pt_active = (pt->runtime.pt_orig) ? pt->runtime.pt_orig : pt; - /* convert point coords to screenspace */ + /* Convert point coords to screen-space. */ const bool is_inside = is_inside_fn(gsc.region, gpstroke_iter.diff_mat, &pt->x, user_data); if (strokemode == false) { const bool is_select = (pt_active->flag & GP_SPOINT_SELECT) != 0; diff --git a/source/blender/editors/gpencil/gpencil_trace_ops.c b/source/blender/editors/gpencil/gpencil_trace_ops.c index f6e88e05d46..36165c6b7c0 100644 --- a/source/blender/editors/gpencil/gpencil_trace_ops.c +++ b/source/blender/editors/gpencil/gpencil_trace_ops.c @@ -71,6 +71,9 @@ typedef struct TraceJob { int32_t thickness; int32_t turnpolicy; int32_t mode; + /** Frame to render to be used by python API. Not exposed in UI. + * This feature is only used in Studios to run custom video trace for selected frames. */ + int32_t frame_num; bool success; bool was_canceled; @@ -212,7 +215,10 @@ static void trace_start_job(void *customdata, short *stop, short *do_update, flo (trace_job->mode == GPENCIL_TRACE_MODE_SINGLE)) { void *lock; ImageUser *iuser = trace_job->ob_active->iuser; - iuser->framenr = init_frame; + + iuser->framenr = ((trace_job->frame_num == 0) || (trace_job->frame_num > iuser->frames)) ? + init_frame : + trace_job->frame_num; ImBuf *ibuf = BKE_image_acquire_ibuf(trace_job->image, iuser, &lock); if (ibuf) { /* Create frame. */ @@ -300,9 +306,10 @@ static int gpencil_trace_image_exec(bContext *C, wmOperator *op) /* Create a new grease pencil object or reuse selected. */ eGP_TargetObjectMode target = RNA_enum_get(op->ptr, "target"); - job->ob_gpencil = (target == GP_TARGET_OB_SELECTED) ? BKE_view_layer_non_active_selected_object( - CTX_data_view_layer(C), job->v3d) : - NULL; + job->ob_gpencil = (target == GP_TARGET_OB_SELECTED) ? + BKE_view_layer_non_active_selected_object( + scene, CTX_data_view_layer(C), job->v3d) : + NULL; if (job->ob_gpencil != NULL) { if (job->ob_gpencil->type != OB_GPENCIL) { @@ -324,13 +331,14 @@ static int gpencil_trace_image_exec(bContext *C, wmOperator *op) job->thickness = RNA_int_get(op->ptr, "thickness"); job->turnpolicy = RNA_enum_get(op->ptr, "turnpolicy"); job->mode = RNA_enum_get(op->ptr, "mode"); + job->frame_num = RNA_int_get(op->ptr, "frame_number"); trace_initialize_job_data(job); /* Back to active base. */ ED_object_base_activate(job->C, job->base_active); - if (job->image->source == IMA_SRC_FILE) { + if ((job->image->source == IMA_SRC_FILE) || (job->frame_num > 0)) { short stop = 0, do_update = true; float progress; trace_start_job(job, &stop, &do_update, &progress); @@ -364,6 +372,8 @@ static int gpencil_trace_image_invoke(bContext *C, wmOperator *op, const wmEvent void GPENCIL_OT_trace_image(wmOperatorType *ot) { + PropertyRNA *prop; + static const EnumPropertyItem turnpolicy_type[] = { {POTRACE_TURNPOLICY_BLACK, "BLACK", @@ -475,4 +485,15 @@ void GPENCIL_OT_trace_image(wmOperatorType *ot) true, "Start At Current Frame", "Trace Image starting in current image frame"); + prop = RNA_def_int( + ot->srna, + "frame_number", + 0, + 0, + 9999, + "Trace Frame", + "Used to trace only one frame of the image sequence, set to zero to trace all", + 0, + 9999); + RNA_def_property_flag(prop, PROP_SKIP_SAVE); } diff --git a/source/blender/editors/gpencil/gpencil_utils.c b/source/blender/editors/gpencil/gpencil_utils.c index 7b659511aaa..729e8412684 100644 --- a/source/blender/editors/gpencil/gpencil_utils.c +++ b/source/blender/editors/gpencil/gpencil_utils.c @@ -1038,7 +1038,8 @@ void ED_gpencil_stroke_reproject(Depsgraph *depsgraph, bGPDframe *gpf, bGPDstroke *gps, const eGP_ReprojectModes mode, - const bool keep_original) + const bool keep_original, + const float offset) { ToolSettings *ts = gsc->scene->toolsettings; ARegion *region = gsc->region; @@ -1156,7 +1157,13 @@ void ED_gpencil_stroke_reproject(Depsgraph *depsgraph, &depth, &location[0], &normal[0])) { - copy_v3_v3(&pt->x, location); + /* Apply offset over surface. */ + float normal_vector[3]; + sub_v3_v3v3(normal_vector, ray_start, location); + normalize_v3(normal_vector); + mul_v3_fl(normal_vector, offset); + + add_v3_v3v3(&pt->x, location, normal_vector); } else { /* Default to planar */ @@ -1683,7 +1690,7 @@ void ED_gpencil_brush_draw_eraser(Brush *brush, int x, int y) GPUVertFormat *format = immVertexFormat(); const uint shdr_pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); - immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); GPU_line_smooth(true); GPU_blend(GPU_BLEND_ALPHA); @@ -1693,7 +1700,7 @@ void ED_gpencil_brush_draw_eraser(Brush *brush, int x, int y) immUnbindProgram(); - immBindBuiltinProgram(GPU_SHADER_2D_LINE_DASHED_UNIFORM_COLOR); + immBindBuiltinProgram(GPU_SHADER_3D_LINE_DASHED_UNIFORM_COLOR); float viewport_size[4]; GPU_viewport_size_get_f(viewport_size); @@ -1865,7 +1872,7 @@ static void gpencil_brush_cursor_draw(bContext *C, int x, int y, void *customdat /* draw icon */ GPUVertFormat *format = immVertexFormat(); uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); - immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); GPU_line_smooth(true); GPU_blend(GPU_BLEND_ALPHA); @@ -3189,7 +3196,7 @@ bGPDstroke *ED_gpencil_stroke_join_and_trim( /* Join both strokes. */ int totpoint = gps_final->totpoints; - BKE_gpencil_stroke_join(gps_final, gps, false, true, true); + BKE_gpencil_stroke_join(gps_final, gps, false, true, true, true); /* Select the join points and merge if the distance is very small. */ pt = &gps_final->points[totpoint - 1]; diff --git a/source/blender/editors/gpencil/gpencil_vertex_ops.c b/source/blender/editors/gpencil/gpencil_vertex_ops.c index 865c4e360b5..41f939813e4 100644 --- a/source/blender/editors/gpencil/gpencil_vertex_ops.c +++ b/source/blender/editors/gpencil/gpencil_vertex_ops.c @@ -131,7 +131,7 @@ static int gpencil_vertexpaint_brightness_contrast_exec(bContext *C, wmOperator /* * The algorithm is by Werner D. Streidt * (http://visca.com/ffactory/archives/5-99/msg00021.html) - * Extracted of OpenCV demhist.c + * Extracted of OpenCV `demhist.c`. */ if (contrast > 0) { gain = 1.0f - delta * 2.0f; diff --git a/source/blender/editors/include/ED_anim_api.h b/source/blender/editors/include/ED_anim_api.h index ee87de5774a..6079aca0199 100644 --- a/source/blender/editors/include/ED_anim_api.h +++ b/source/blender/editors/include/ED_anim_api.h @@ -101,16 +101,16 @@ typedef struct bAnimContext { /* Main Data container types */ typedef enum eAnimCont_Types { ANIMCONT_NONE = 0, /* invalid or no data */ - ANIMCONT_ACTION = 1, /* action (bAction) */ - ANIMCONT_SHAPEKEY = 2, /* shapekey (Key) */ + ANIMCONT_ACTION = 1, /* action (#bAction) */ + ANIMCONT_SHAPEKEY = 2, /* shape-key (#Key) */ ANIMCONT_GPENCIL = 3, /* grease pencil (screen) */ - ANIMCONT_DOPESHEET = 4, /* dopesheet (bDopesheet) */ - ANIMCONT_FCURVES = 5, /* animation F-Curves (bDopesheet) */ - ANIMCONT_DRIVERS = 6, /* drivers (bDopesheet) */ - ANIMCONT_NLA = 7, /* nla (bDopesheet) */ - ANIMCONT_CHANNEL = 8, /* animation channel (bAnimListElem) */ - ANIMCONT_MASK = 9, /* mask dopesheet */ - ANIMCONT_TIMELINE = 10, /* "timeline" editor (bDopeSheet) */ + ANIMCONT_DOPESHEET = 4, /* dope-sheet (#bDopesheet) */ + ANIMCONT_FCURVES = 5, /* animation F-Curves (#bDopesheet) */ + ANIMCONT_DRIVERS = 6, /* drivers (#bDopesheet) */ + ANIMCONT_NLA = 7, /* NLA (#bDopesheet) */ + ANIMCONT_CHANNEL = 8, /* animation channel (#bAnimListElem) */ + ANIMCONT_MASK = 9, /* mask dope-sheet */ + ANIMCONT_TIMELINE = 10, /* "timeline" editor (#bDopeSheet) */ } eAnimCont_Types; /** \} */ diff --git a/source/blender/editors/include/ED_armature.h b/source/blender/editors/include/ED_armature.h index d969277fef5..8e7f728a3e7 100644 --- a/source/blender/editors/include/ED_armature.h +++ b/source/blender/editors/include/ED_armature.h @@ -312,7 +312,8 @@ void ED_pose_recalculate_paths(struct bContext *C, /** * \return True when pick finds an element or the selection changed. */ -bool ED_armature_pose_select_pick_bone(struct ViewLayer *view_layer, +bool ED_armature_pose_select_pick_bone(const struct Scene *scene, + struct ViewLayer *view_layer, struct View3D *v3d, struct Object *ob, struct Bone *bone, @@ -323,7 +324,8 @@ bool ED_armature_pose_select_pick_bone(struct ViewLayer *view_layer, * * \return True when pick finds an element or the selection changed. */ -bool ED_armature_pose_select_pick_with_buffer(struct ViewLayer *view_layer, +bool ED_armature_pose_select_pick_with_buffer(const struct Scene *scene, + struct ViewLayer *view_layer, struct View3D *v3d, struct Base *base, const struct GPUSelectResult *buffer, @@ -338,7 +340,8 @@ bool ED_armature_pose_select_pick_with_buffer(struct ViewLayer *view_layer, * It can't be set to the active object because we need * to keep this set to the weight paint object. */ -void ED_armature_pose_select_in_wpaint_mode(struct ViewLayer *view_layer, +void ED_armature_pose_select_in_wpaint_mode(const struct Scene *scene, + struct ViewLayer *view_layer, struct Base *base_select); bool ED_pose_deselect_all_multi_ex(struct Base **bases, uint bases_len, diff --git a/source/blender/editors/include/ED_fileselect.h b/source/blender/editors/include/ED_fileselect.h index e9fcd2bd5fe..9d5d8dd54cb 100644 --- a/source/blender/editors/include/ED_fileselect.h +++ b/source/blender/editors/include/ED_fileselect.h @@ -175,6 +175,14 @@ struct ScrArea *ED_fileselect_handler_area_find(const struct wmWindow *win, */ struct ScrArea *ED_fileselect_handler_area_find_any_with_op(const struct wmWindow *win); +/** + * If filepath property is not set on the operator, sets it to + * the blend file path (or untitled if file is not saved yet) with the given extension. + */ +void ED_fileselect_ensure_default_filepath(struct bContext *C, + struct wmOperator *op, + const char *extension); + /* TODO: Maybe we should move this to BLI? * On the other hand, it's using defines from space-file area, so not sure... */ int ED_path_extension_type(const char *path); diff --git a/source/blender/editors/include/ED_gpencil.h b/source/blender/editors/include/ED_gpencil.h index b6488d6da56..45e61592424 100644 --- a/source/blender/editors/include/ED_gpencil.h +++ b/source/blender/editors/include/ED_gpencil.h @@ -403,12 +403,11 @@ void ED_gpencil_stroke_init_data(struct bGPDstroke *gps, */ void ED_gpencil_create_blank(struct bContext *C, struct Object *ob, float mat[4][4]); /** - * Add a 2D Suzanne (original model created by Matias Mendiola). + * Add a 2D Suzanne. */ void ED_gpencil_create_monkey(struct bContext *C, struct Object *ob, float mat[4][4]); /** - * Add a Simple stroke with colors - * (original design created by Daniel M. Lara and Matias Mendiola). + * Add a Simple stroke with colors. */ void ED_gpencil_create_stroke(struct bContext *C, struct Object *ob, float mat[4][4]); /** @@ -476,7 +475,8 @@ void ED_gpencil_stroke_reproject(struct Depsgraph *depsgraph, struct bGPDframe *gpf, struct bGPDstroke *gps, eGP_ReprojectModes mode, - bool keep_original); + bool keep_original, + const float offset); /** * Turn brush cursor in on/off. diff --git a/source/blender/editors/include/ED_image.h b/source/blender/editors/include/ED_image.h index 91ae8286531..da303f3552b 100644 --- a/source/blender/editors/include/ED_image.h +++ b/source/blender/editors/include/ED_image.h @@ -32,14 +32,15 @@ struct wmWindowManager; float ED_space_image_zoom_level(const struct View2D *v2d, int grid_dimension); void ED_space_image_grid_steps(struct SpaceImage *sima, - float grid_steps[SI_GRID_STEPS_LEN], + float grid_steps_x[SI_GRID_STEPS_LEN], + float grid_steps_y[SI_GRID_STEPS_LEN], int grid_dimension); /** * Calculate the increment snapping value for UV/image editor based on the zoom factor * The code in here (except the offset part) is used in `grid_frag.glsl` (see `grid_res`) for * drawing the grid overlay for the UV/Image editor. */ -float ED_space_image_increment_snap_value(int grid_dimesnions, +float ED_space_image_increment_snap_value(int grid_dimensions, const float grid_steps[SI_GRID_STEPS_LEN], float zoom_factor); diff --git a/source/blender/editors/include/ED_keyframes_edit.h b/source/blender/editors/include/ED_keyframes_edit.h index 1d63e01c84b..e5bcdcdd282 100644 --- a/source/blender/editors/include/ED_keyframes_edit.h +++ b/source/blender/editors/include/ED_keyframes_edit.h @@ -235,7 +235,7 @@ typedef enum eKeyPasteError { KEYFRAME_PASTE_OK, /* Nothing was copied */ KEYFRAME_PASTE_NOTHING_TO_PASTE, - /* No F-curves was selected to paste into*/ + /* No F-curves was selected to paste into. */ KEYFRAME_PASTE_NOWHERE_TO_PASTE } eKeyPasteError; diff --git a/source/blender/editors/include/ED_mesh.h b/source/blender/editors/include/ED_mesh.h index a1c1c816d4c..26743a2bd08 100644 --- a/source/blender/editors/include/ED_mesh.h +++ b/source/blender/editors/include/ED_mesh.h @@ -139,13 +139,16 @@ struct UvElementMap *BM_uv_element_map_create(struct BMesh *bm, const struct Scene *scene, bool uv_selected, bool use_winding, + bool use_seams, bool do_islands); void BM_uv_element_map_free(struct UvElementMap *element_map); -struct UvElement *BM_uv_element_get(struct UvElementMap *map, - struct BMFace *efa, - struct BMLoop *l); +struct UvElement *BM_uv_element_get(const struct UvElementMap *map, + const struct BMFace *efa, + const struct BMLoop *l); struct UvElement *BM_uv_element_get_head(struct UvElementMap *map, struct UvElement *child); +struct UvElement **BM_uv_element_map_ensure_head_table(struct UvElementMap *element_map); + /** * Can we edit UV's for this mesh? */ @@ -181,9 +184,13 @@ void EDBM_project_snap_verts(struct bContext *C, /* editmesh_automerge.c */ -void EDBM_automerge(struct Object *ob, bool update, char hflag, float dist); -void EDBM_automerge_and_split( - struct Object *ob, bool split_edges, bool split_faces, bool update, char hflag, float dist); +void EDBM_automerge(struct Object *obedit, bool update, char hflag, float dist); +void EDBM_automerge_and_split(struct Object *obedit, + bool split_edges, + bool split_faces, + bool update, + char hflag, + float dist); /* editmesh_undo.c */ diff --git a/source/blender/editors/include/ED_object.h b/source/blender/editors/include/ED_object.h index 39c7ad3556c..acb0e53aa55 100644 --- a/source/blender/editors/include/ED_object.h +++ b/source/blender/editors/include/ED_object.h @@ -112,6 +112,7 @@ struct XFormObjectSkipChild_Container; struct XFormObjectSkipChild_Container *ED_object_xform_skip_child_container_create(void); void ED_object_xform_skip_child_container_item_ensure_from_array( struct XFormObjectSkipChild_Container *xcs, + const struct Scene *scene, struct ViewLayer *view_layer, struct Object **objects, uint objects_len); @@ -213,16 +214,20 @@ void ED_object_base_free_and_unlink(struct Main *bmain, struct Scene *scene, str void ED_object_base_free_and_unlink_no_indirect_check(struct Main *bmain, struct Scene *scene, struct Object *ob); -bool ED_object_base_deselect_all_ex(struct ViewLayer *view_layer, +bool ED_object_base_deselect_all_ex(const struct Scene *scene, + struct ViewLayer *view_layer, struct View3D *v3d, int action, bool *r_any_visible); -bool ED_object_base_deselect_all(struct ViewLayer *view_layer, struct View3D *v3d, int action); +bool ED_object_base_deselect_all(const struct Scene *scene, + struct ViewLayer *view_layer, + struct View3D *v3d, + int action); /** * Single object duplicate, if `dupflag == 0`, fully linked, else it uses the flags given. * Leaves selection of base/object unaltered. - * \note don't call this within a loop since clear_* funcs loop over the entire database. + * \note don't call this within a loop since clear_* functions loop over the entire database. * \note caller must do `DAG_relations_tag_update(bmain);` * this is not done automatic since we may duplicate many objects in a batch. */ @@ -539,6 +544,7 @@ bool ED_object_modifier_move_to_index(struct ReportList *reports, bool ED_object_modifier_convert_psys_to_mesh(struct ReportList *reports, struct Main *bmain, struct Depsgraph *depsgraph, + struct Scene *scene, struct ViewLayer *view_layer, struct Object *ob, struct ModifierData *md); @@ -662,7 +668,9 @@ void ED_object_check_force_modifiers(struct Main *bmain, * If id is not already an Object, try to find an object that uses it as data. * Prefers active, then selected, then visible/selectable. */ -struct Base *ED_object_find_first_by_data_id(struct ViewLayer *view_layer, struct ID *id); +struct Base *ED_object_find_first_by_data_id(const struct Scene *scene, + struct ViewLayer *view_layer, + struct ID *id); /** * Select and make the target object active in the view layer. diff --git a/source/blender/editors/include/ED_screen.h b/source/blender/editors/include/ED_screen.h index a24c8625a63..144fa4e0b93 100644 --- a/source/blender/editors/include/ED_screen.h +++ b/source/blender/editors/include/ED_screen.h @@ -294,7 +294,7 @@ void ED_screen_refresh(struct wmWindowManager *wm, struct wmWindow *win); void ED_screen_ensure_updated(struct wmWindowManager *wm, struct wmWindow *win, struct bScreen *screen); -void ED_screen_do_listen(struct bContext *C, struct wmNotifier *note); +void ED_screen_do_listen(struct bContext *C, const struct wmNotifier *note); /** * \brief Change the active screen. * @@ -353,8 +353,8 @@ struct ScrArea *ED_screen_state_toggle(struct bContext *C, struct ScrArea *area, short state); /** - * Wrapper to open a temporary space either as fullscreen space, or as separate window, as defined - * by \a display_type. + * Wrapper to open a temporary space either as full-screen space, or as separate window, + * as defined by \a display_type. * * \param title: Title to set for the window, if a window is spawned. * \param x, y: Position of the window, if a window is spawned. diff --git a/source/blender/editors/include/ED_screen_types.h b/source/blender/editors/include/ED_screen_types.h index 21bb412d072..bf64be9f7a7 100644 --- a/source/blender/editors/include/ED_screen_types.h +++ b/source/blender/editors/include/ED_screen_types.h @@ -112,7 +112,7 @@ enum { */ AZONE_REGION, /** - * Used when in editor fullscreen draw a corner to return to normal mode. + * Used when in editor full-screen draw a corner to return to normal mode. */ AZONE_FULLSCREEN, /** diff --git a/source/blender/editors/include/ED_sculpt.h b/source/blender/editors/include/ED_sculpt.h index 550040d2bc6..1e220d33ff4 100644 --- a/source/blender/editors/include/ED_sculpt.h +++ b/source/blender/editors/include/ED_sculpt.h @@ -20,6 +20,7 @@ struct rcti; struct wmMsgSubscribeKey; struct wmMsgSubscribeValue; struct wmRegionMessageSubscribeParams; +struct wmOperator; /* sculpt.c */ @@ -33,7 +34,7 @@ bool ED_sculpt_mask_box_select(struct bContext *C, /* sculpt_transform.c */ void ED_sculpt_update_modal_transform(struct bContext *C, struct Object *ob); -void ED_sculpt_init_transform(struct bContext *C, struct Object *ob); +void ED_sculpt_init_transform(struct bContext *C, struct Object *ob, const char *undo_name); void ED_sculpt_end_transform(struct bContext *C, struct Object *ob); /* sculpt_undo.c */ @@ -41,7 +42,13 @@ void ED_sculpt_end_transform(struct bContext *C, struct Object *ob); /** Export for ED_undo_sys. */ void ED_sculpt_undosys_type(struct UndoType *ut); -void ED_sculpt_undo_geometry_begin(struct Object *ob, const char *name); +/** + * Pushes an undo step using the operator name. This is necessary for + * redo panels to work; operators that do not support that may use + * #ED_sculpt_undo_geometry_begin_ex instead if so desired. + */ +void ED_sculpt_undo_geometry_begin(struct Object *ob, const struct wmOperator *op); +void ED_sculpt_undo_geometry_begin_ex(struct Object *ob, const char *name); void ED_sculpt_undo_geometry_end(struct Object *ob); /* Face sets. */ diff --git a/source/blender/editors/include/ED_space_api.h b/source/blender/editors/include/ED_space_api.h index c69698f3f73..07d4f43bb2b 100644 --- a/source/blender/editors/include/ED_space_api.h +++ b/source/blender/editors/include/ED_space_api.h @@ -50,7 +50,7 @@ void ED_spacetype_spreadsheet(void); /** \} */ /* -------------------------------------------------------------------- */ -/** \name Spacetype Static Data +/** \name Space-type Static Data * Calls for instancing and freeing space-type static data called in #WM_init_exit * \{ */ diff --git a/source/blender/editors/include/ED_transform.h b/source/blender/editors/include/ED_transform.h index 82cc518f029..d7fb108809f 100644 --- a/source/blender/editors/include/ED_transform.h +++ b/source/blender/editors/include/ED_transform.h @@ -94,7 +94,8 @@ bool BIF_createTransformOrientation(struct bContext *C, bool overwrite); void BIF_selectTransformOrientation(struct bContext *C, struct TransformOrientation *target); -void ED_getTransformOrientationMatrix(struct ViewLayer *view_layer, +void ED_getTransformOrientationMatrix(const struct Scene *scene, + struct ViewLayer *view_layer, const struct View3D *v3d, struct Object *ob, struct Object *obedit, diff --git a/source/blender/editors/include/ED_types.h b/source/blender/editors/include/ED_types.h deleted file mode 100644 index eba93ed6744..00000000000 --- a/source/blender/editors/include/ED_types.h +++ /dev/null @@ -1,27 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-or-later - * Copyright 2008 Blender Foundation. All rights reserved. */ - -/** \file - * \ingroup editors - */ - -#pragma once - -#ifdef __cplusplus -extern "C" { -#endif - -/* **************** GENERAL EDITOR-WIDE TYPES AND DEFINES ************************** */ - -/* old blender defines... should be deprecated? */ -#define DESELECT 0 -#define SELECT 1 -#define ACTIVE 2 - -/* proposal = put scene pointers on function calls? */ -// #define BASACT (scene->basact) -// #define OBACT (BASACT ? BASACT->object : NULL) - -#ifdef __cplusplus -} -#endif diff --git a/source/blender/editors/include/ED_undo.h b/source/blender/editors/include/ED_undo.h index 8c5f25e6b67..39bbd8adc75 100644 --- a/source/blender/editors/include/ED_undo.h +++ b/source/blender/editors/include/ED_undo.h @@ -15,6 +15,7 @@ extern "C" { struct Base; struct CLG_LogRef; struct Object; +struct Scene; struct UndoStack; struct ViewLayer; struct bContext; @@ -79,9 +80,12 @@ void ED_undo_object_editmode_restore_helper(struct bContext *C, uint object_array_len, uint object_array_stride); -struct Object **ED_undo_editmode_objects_from_view_layer(struct ViewLayer *view_layer, +struct Object **ED_undo_editmode_objects_from_view_layer(const struct Scene *scene, + struct ViewLayer *view_layer, uint *r_len); -struct Base **ED_undo_editmode_bases_from_view_layer(struct ViewLayer *view_layer, uint *r_len); +struct Base **ED_undo_editmode_bases_from_view_layer(const struct Scene *scene, + struct ViewLayer *view_layer, + uint *r_len); /** * Ideally we won't access the stack directly, diff --git a/source/blender/editors/include/ED_uvedit.h b/source/blender/editors/include/ED_uvedit.h index 24d6819536d..38e542fc0ca 100644 --- a/source/blender/editors/include/ED_uvedit.h +++ b/source/blender/editors/include/ED_uvedit.h @@ -107,7 +107,7 @@ bool uvedit_uv_select_test(const struct Scene *scene, struct BMLoop *l, int cd_l * Changes selection state of a single UV Face. */ void uvedit_face_select_set(const struct Scene *scene, - struct BMEditMesh *em, + struct BMesh *em, struct BMFace *efa, bool select, bool do_history, @@ -118,7 +118,7 @@ void uvedit_face_select_set(const struct Scene *scene, * Changes selection state of a single UV Edge. */ void uvedit_edge_select_set(const struct Scene *scene, - struct BMEditMesh *em, + struct BMesh *em, struct BMLoop *l, bool select, bool do_history, @@ -129,7 +129,7 @@ void uvedit_edge_select_set(const struct Scene *scene, * Changes selection state of a single UV vertex. */ void uvedit_uv_select_set(const struct Scene *scene, - struct BMEditMesh *em, + struct BMesh *em, struct BMLoop *l, bool select, bool do_history, @@ -139,30 +139,30 @@ void uvedit_uv_select_set(const struct Scene *scene, * use. */ void uvedit_face_select_enable(const struct Scene *scene, - struct BMEditMesh *em, + struct BMesh *bm, struct BMFace *efa, bool do_history, int cd_loop_uv_offset); void uvedit_face_select_disable(const struct Scene *scene, - struct BMEditMesh *em, + struct BMesh *bm, struct BMFace *efa, int cd_loop_uv_offset); void uvedit_edge_select_enable(const struct Scene *scene, - struct BMEditMesh *em, + struct BMesh *bm, struct BMLoop *l, bool do_history, int cd_loop_uv_offset); void uvedit_edge_select_disable(const struct Scene *scene, - struct BMEditMesh *em, + struct BMesh *bm, struct BMLoop *l, int cd_loop_uv_offset); void uvedit_uv_select_enable(const struct Scene *scene, - struct BMEditMesh *em, + struct BMesh *bm, struct BMLoop *l, bool do_history, int cd_loop_uv_offset); void uvedit_uv_select_disable(const struct Scene *scene, - struct BMEditMesh *em, + struct BMesh *bm, struct BMLoop *l, int cd_loop_uv_offset); @@ -179,13 +179,13 @@ void uvedit_edge_select_set_with_sticky(const struct Scene *scene, struct BMLoop *l, bool select, bool do_history, - uint cd_loop_uv_offset); + int cd_loop_uv_offset); void uvedit_uv_select_set_with_sticky(const struct Scene *scene, struct BMEditMesh *em, struct BMLoop *l, bool select, bool do_history, - uint cd_loop_uv_offset); + int cd_loop_uv_offset); /* Low level functions for sticky element selection (sticky mode independent). Type of sticky * selection is specified explicitly (using sticky_flag, except for face selection). */ @@ -315,7 +315,7 @@ struct FaceIsland { * \note While this is duplicate information, * it allows islands from multiple meshes to be stored in the same list. */ - uint cd_loop_uv_offset; + int cd_loop_uv_offset; float aspect_y; }; @@ -326,7 +326,7 @@ int bm_mesh_calc_uv_islands(const Scene *scene, const bool only_selected_uvs, const bool use_seams, const float aspect_y, - const uint cd_loop_uv_offset); + const int cd_loop_uv_offset); struct UVMapUDIM_Params { const struct Image *image; diff --git a/source/blender/editors/include/ED_view3d.h b/source/blender/editors/include/ED_view3d.h index bb95ea97c1c..a4857c2b92f 100644 --- a/source/blender/editors/include/ED_view3d.h +++ b/source/blender/editors/include/ED_view3d.h @@ -711,7 +711,7 @@ bool ED_view3d_win_to_segment_clipped(const struct Depsgraph *depsgraph, float r_ray_start[3], float r_ray_end[3], bool do_clip_planes); -void ED_view3d_ob_project_mat_get(const struct RegionView3D *v3d, +void ED_view3d_ob_project_mat_get(const struct RegionView3D *rv3d, const struct Object *ob, float r_pmat[4][4]); void ED_view3d_ob_project_mat_get_from_obmat(const struct RegionView3D *rv3d, @@ -950,7 +950,7 @@ int view3d_opengl_select_with_id_filter(struct ViewContext *vc, eV3DSelectObjectFilter select_filter, uint select_id); -/* view3d_select.c */ +/* view3d_select.cc */ float ED_view3d_select_dist_px(void); void ED_view3d_viewcontext_init(struct bContext *C, @@ -1319,7 +1319,7 @@ void ED_view3d_gizmo_mesh_preselect_get_active(struct bContext *C, struct BMElem **r_ele); void ED_view3d_gizmo_mesh_preselect_clear(struct wmGizmo *gz); -/* space_view3d.c */ +/* space_view3d.cc */ void ED_view3d_buttons_region_layout_ex(const struct bContext *C, struct ARegion *region, diff --git a/source/blender/editors/include/UI_interface.h b/source/blender/editors/include/UI_interface.h index 163ea7e9493..c3376493413 100644 --- a/source/blender/editors/include/UI_interface.h +++ b/source/blender/editors/include/UI_interface.h @@ -354,7 +354,7 @@ typedef enum { UI_BTYPE_LABEL = 20 << 9, UI_BTYPE_KEY_EVENT = 24 << 9, UI_BTYPE_HSVCUBE = 26 << 9, - /** menu (often used in headers), **_MENU /w different draw-type */ + /** Menu (often used in headers), `*_MENU` with different draw-type. */ UI_BTYPE_PULLDOWN = 27 << 9, UI_BTYPE_ROUNDBOX = 28 << 9, UI_BTYPE_COLORBAND = 30 << 9, @@ -532,6 +532,7 @@ typedef struct ARegion *(*uiButSearchTooltipFn)(struct bContext *C, const struct rcti *item_rect, void *arg, void *active); +typedef void (*uiButSearchListenFn)(const struct wmRegionListenerParams *params, void *arg); /* Must return allocated string. */ typedef char *(*uiButToolTipFunc)(struct bContext *C, void *argN, const char *tip); @@ -1659,6 +1660,7 @@ void UI_but_func_search_set(uiBut *but, void *active); void UI_but_func_search_set_context_menu(uiBut *but, uiButSearchContextMenuFn context_menu_fn); void UI_but_func_search_set_tooltip(uiBut *but, uiButSearchTooltipFn tooltip_fn); +void UI_but_func_search_set_listen(uiBut *but, uiButSearchListenFn listen_fn); /** * \param search_sep_string: when not NULL, this string is used as a separator, * showing the icon and highlighted text after the last instance of this string. diff --git a/source/blender/editors/include/UI_interface.hh b/source/blender/editors/include/UI_interface.hh index 82bfdd7e212..6c756984203 100644 --- a/source/blender/editors/include/UI_interface.hh +++ b/source/blender/editors/include/UI_interface.hh @@ -13,7 +13,7 @@ #include "UI_resources.h" -namespace blender::nodes::geometry_nodes_eval_log { +namespace blender::nodes::geo_eval_log { struct GeometryAttributeInfo; } @@ -44,12 +44,11 @@ void context_path_add_generic(Vector<ContextPathItem> &path, void template_breadcrumbs(uiLayout &layout, Span<ContextPathItem> context_path); -void attribute_search_add_items( - StringRefNull str, - bool can_create_attribute, - Span<const nodes::geometry_nodes_eval_log::GeometryAttributeInfo *> infos, - uiSearchItems *items, - bool is_first); +void attribute_search_add_items(StringRefNull str, + bool can_create_attribute, + Span<const nodes::geo_eval_log::GeometryAttributeInfo *> infos, + uiSearchItems *items, + bool is_first); } // namespace blender::ui diff --git a/source/blender/editors/include/UI_resources.h b/source/blender/editors/include/UI_resources.h index 22e747e37ad..9a46728097c 100644 --- a/source/blender/editors/include/UI_resources.h +++ b/source/blender/editors/include/UI_resources.h @@ -291,6 +291,8 @@ typedef enum ThemeColorID { TH_WIDGET_EMBOSS, TH_WIDGET_TEXT_CURSOR, + TH_WIDGET_TEXT_SELECTION, + TH_WIDGET_TEXT_HIGHLIGHT, TH_EDITOR_OUTLINE, TH_TRANSPARENT_CHECKER_PRIMARY, diff --git a/source/blender/editors/include/UI_view2d.h b/source/blender/editors/include/UI_view2d.h index e508c96b4f1..bdd830e0046 100644 --- a/source/blender/editors/include/UI_view2d.h +++ b/source/blender/editors/include/UI_view2d.h @@ -54,7 +54,7 @@ enum eView2D_CommonViewTypes { #define V2D_SCROLL_HEIGHT ((0.45f * U.widget_unit) + (2.0f * U.pixelsize)) #define V2D_SCROLL_WIDTH ((0.45f * U.widget_unit) + (2.0f * U.pixelsize)) -/* Alpha of scrollbar when at minimum size. */ +/* Alpha of scroll-bar when at minimum size. */ #define V2D_SCROLL_MIN_ALPHA (0.4f) /* Minimum size needs to include outline which varies with line width. */ @@ -84,7 +84,7 @@ enum eView2D_CommonViewTypes { /* ------------------------------------------ */ /* Macros: */ -/* test if mouse in a scrollbar (assume that scroller availability has been tested) */ +/* Test if mouse in a scroll-bar (assume that scroller availability has been tested). */ #define IN_2D_VERT_SCROLL(v2d, co) (BLI_rcti_isect_pt_v(&v2d->vert, co)) #define IN_2D_HORIZ_SCROLL(v2d, co) (BLI_rcti_isect_pt_v(&v2d->hor, co)) @@ -350,8 +350,8 @@ struct View2D *UI_view2d_fromcontext(const struct bContext *C); struct View2D *UI_view2d_fromcontext_rwin(const struct bContext *C); /** - * Get scrollbar sizes of the current 2D view. - * The size will be zero if the view has its scrollbars disabled. + * Get scroll-bar sizes of the current 2D view. + * The size will be zero if the view has its scroll-bars disabled. * * \param mapped: whether to use view2d_scroll_mapped which changes flags */ diff --git a/source/blender/editors/interface/CMakeLists.txt b/source/blender/editors/interface/CMakeLists.txt index e4a973a375e..6a531c88762 100644 --- a/source/blender/editors/interface/CMakeLists.txt +++ b/source/blender/editors/interface/CMakeLists.txt @@ -19,7 +19,6 @@ set(INC ../../python ../../render ../../windowmanager - ../../../../intern/glew-mx ../../../../intern/guardedalloc ../../bmesh # RNA_prototypes.h diff --git a/source/blender/editors/interface/eyedroppers/interface_eyedropper.c b/source/blender/editors/interface/eyedroppers/interface_eyedropper.c index c6fb8f0ab68..e49955512a1 100644 --- a/source/blender/editors/interface/eyedroppers/interface_eyedropper.c +++ b/source/blender/editors/interface/eyedroppers/interface_eyedropper.c @@ -41,7 +41,7 @@ wmKeyMap *eyedropper_modal_keymap(wmKeyConfig *keyconf) wmKeyMap *keymap = WM_modalkeymap_find(keyconf, "Eyedropper Modal Map"); - /* this function is called for each spacetype, only needs to add map once */ + /* This function is called for each space-type, only needs to add map once. */ if (keymap && keymap->modal_items) { return NULL; } diff --git a/source/blender/editors/interface/interface.cc b/source/blender/editors/interface/interface.cc index c076845af3c..64f7e035d3f 100644 --- a/source/blender/editors/interface/interface.cc +++ b/source/blender/editors/interface/interface.cc @@ -153,8 +153,8 @@ void ui_block_to_window(const ARegion *region, uiBlock *block, int *r_x, int *r_ ui_block_to_window_fl(region, block, &fx, &fy); - *r_x = (int)(fx + 0.5f); - *r_y = (int)(fy + 0.5f); + *r_x = (int)lround(fx); + *r_y = (int)lround(fy); } void ui_block_to_region_rctf(const ARegion *region, @@ -232,8 +232,8 @@ void ui_window_to_block(const ARegion *region, uiBlock *block, int *r_x, int *r_ ui_window_to_block_fl(region, block, &fx, &fy); - *r_x = (int)(fx + 0.5f); - *r_y = (int)(fy + 0.5f); + *r_x = (int)lround(fx); + *r_y = (int)lround(fy); } void ui_window_to_region(const ARegion *region, int *r_x, int *r_y) @@ -2363,9 +2363,9 @@ void ui_but_v3_set(uiBut *but, const float vec[3]) } else if (but->pointype == UI_BUT_POIN_CHAR) { char *cp = (char *)but->poin; - cp[0] = (char)(0.5f + vec[0] * 255.0f); - cp[1] = (char)(0.5f + vec[1] * 255.0f); - cp[2] = (char)(0.5f + vec[2] * 255.0f); + cp[0] = (char)lround(vec[0] * 255.0f); + cp[1] = (char)lround(vec[1] * 255.0f); + cp[2] = (char)lround(vec[2] * 255.0f); } else if (but->pointype == UI_BUT_POIN_FLOAT) { float *fp = (float *)but->poin; @@ -6321,6 +6321,13 @@ void UI_but_func_search_set_tooltip(uiBut *but, uiButSearchTooltipFn tooltip_fn) but_search->item_tooltip_fn = tooltip_fn; } +void UI_but_func_search_set_listen(uiBut *but, uiButSearchListenFn listen_fn) +{ + uiButSearch *but_search = (uiButSearch *)but; + BLI_assert(but->type == UI_BTYPE_SEARCH_MENU); + but_search->listen_fn = listen_fn; +} + void UI_but_func_search_set_results_are_suggestions(uiBut *but, const bool value) { uiButSearch *but_search = (uiButSearch *)but; @@ -6754,10 +6761,11 @@ void UI_but_extra_icon_string_info_get(struct bContext *C, uiButExtraOpIcon *ext if (ui_but_extra_icon_event_operator_string(C, extra_icon, buf, sizeof(buf))) { tmp = BLI_strdup(buf); } + break; } + default: /* Other types not supported. The caller should expect that outcome, no need to message or * assert here. */ - default: break; } diff --git a/source/blender/editors/interface/interface_context_menu.c b/source/blender/editors/interface/interface_context_menu.c index 518fe65ee09..7ed9488950e 100644 --- a/source/blender/editors/interface/interface_context_menu.c +++ b/source/blender/editors/interface/interface_context_menu.c @@ -952,6 +952,12 @@ bool ui_popup_context_menu_for_button(bContext *C, uiBut *but, const wmEvent *ev uiItemS(layout); } + MenuType *mt_idtemplate_liboverride = WM_menutype_find("UI_MT_idtemplate_liboverride", true); + if (mt_idtemplate_liboverride && mt_idtemplate_liboverride->poll(C, mt_idtemplate_liboverride)) { + uiItemM_ptr(layout, mt_idtemplate_liboverride, IFACE_("Library Override"), ICON_NONE); + uiItemS(layout); + } + /* Pointer properties and string properties with * prop_search support jumping to target object/bone. */ if (but->rnapoin.data && but->rnaprop) { @@ -1224,7 +1230,7 @@ bool ui_popup_context_menu_for_button(bContext *C, uiBut *but, const wmEvent *ev } } - MenuType *mt = WM_menutype_find("WM_MT_button_context", true); + MenuType *mt = WM_menutype_find("UI_MT_button_context_menu", true); if (mt) { UI_menutype_draw(C, mt, uiLayoutColumn(layout, false)); } diff --git a/source/blender/editors/interface/interface_drag.cc b/source/blender/editors/interface/interface_drag.cc index 1db3db32411..4bf2dac4151 100644 --- a/source/blender/editors/interface/interface_drag.cc +++ b/source/blender/editors/interface/interface_drag.cc @@ -37,7 +37,7 @@ void UI_but_drag_set_asset(uiBut *but, { wmDragAsset *asset_drag = WM_drag_create_asset_data(asset, metadata, path, import_type); - /* FIXME: This is temporary evil solution to get scene/viewlayer/etc in the copy callback of the + /* FIXME: This is temporary evil solution to get scene/view-layer/etc in the copy callback of the * #wmDropBox. * TODO: Handle link/append in operator called at the end of the drop process, and NOT in its * copy callback. @@ -130,7 +130,7 @@ void ui_but_drag_start(bContext *C, uiBut *but) (but->dragflag & UI_BUT_DRAGPOIN_FREE) ? WM_DRAG_FREE_DATA : WM_DRAG_NOP); /* wmDrag has ownership over dragpoin now, stop messing with it. */ - but->dragpoin = NULL; + but->dragpoin = nullptr; if (but->imb) { WM_event_drag_image(drag, but->imb, but->imb_scale); @@ -141,6 +141,6 @@ void ui_but_drag_start(bContext *C, uiBut *but) /* Special feature for assets: We add another drag item that supports multiple assets. It * gets the assets from context. */ if (ELEM(but->dragtype, WM_DRAG_ASSET, WM_DRAG_ID)) { - WM_event_start_drag(C, ICON_NONE, WM_DRAG_ASSET_LIST, NULL, 0, WM_DRAG_NOP); + WM_event_start_drag(C, ICON_NONE, WM_DRAG_ASSET_LIST, nullptr, 0, WM_DRAG_NOP); } } diff --git a/source/blender/editors/interface/interface_draw.c b/source/blender/editors/interface/interface_draw.c index d201820fbb6..f1a324c411a 100644 --- a/source/blender/editors/interface/interface_draw.c +++ b/source/blender/editors/interface/interface_draw.c @@ -171,7 +171,7 @@ void UI_draw_text_underline(int pos_x, int pos_y, int len, int height, const flo GPUVertFormat *format = immVertexFormat(); const uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_I32, 2, GPU_FETCH_INT_TO_FLOAT); - immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); immUniformColor4fv(color); immRecti(pos, pos_x, pos_y - ofs_y, pos_x + len, pos_y - ofs_y + (height * U.pixelsize)); @@ -205,7 +205,7 @@ void ui_draw_but_TAB_outline(const rcti *rect, mul_v2_fl(vec[a], rad); } - immBindBuiltinProgram(GPU_SHADER_2D_SMOOTH_COLOR); + immBindBuiltinProgram(GPU_SHADER_3D_SMOOTH_COLOR); immBeginAtMost(GPU_PRIM_LINE_STRIP, 25); immAttr3ubv(col, highlight); @@ -309,7 +309,7 @@ void ui_draw_but_IMAGE(ARegion *UNUSED(region), rgba_uchar_to_float(col, but->col); } - IMMDrawPixelsTexState state = immDrawPixelsTexSetup(GPU_SHADER_2D_IMAGE_COLOR); + IMMDrawPixelsTexState state = immDrawPixelsTexSetup(GPU_SHADER_3D_IMAGE_COLOR); immDrawPixelsTexTiled(&state, (float)rect->xmin, (float)rect->ymin, @@ -490,7 +490,7 @@ void ui_draw_but_HISTOGRAM(ARegion *UNUSED(region), GPUVertFormat *format = immVertexFormat(); const uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); - immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); immUniformColor4f(1.0f, 1.0f, 1.0f, 0.08f); /* draw grid lines here */ @@ -559,7 +559,7 @@ static void waveform_draw_one(float *waveform, int waveform_num, const float col /* TODO: store the #GPUBatch inside the scope. */ GPUBatch *batch = GPU_batch_create_ex(GPU_PRIM_POINTS, vbo, NULL, GPU_BATCH_OWNS_VBO); - GPU_batch_program_set_builtin(batch, GPU_SHADER_2D_UNIFORM_COLOR); + GPU_batch_program_set_builtin(batch, GPU_SHADER_3D_UNIFORM_COLOR); GPU_batch_uniform_4f(batch, "color", col[0], col[1], col[2], 1.0f); GPU_batch_draw(batch); @@ -653,7 +653,7 @@ void ui_draw_but_WAVEFORM(ARegion *UNUSED(region), GPUVertFormat *format = immVertexFormat(); const uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); - immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); immUniformColor4f(1.0f, 1.0f, 1.0f, 0.08f); @@ -977,7 +977,7 @@ void ui_draw_but_VECTORSCOPE(ARegion *UNUSED(region), GPUVertFormat *format = immVertexFormat(); const uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); - immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); immUniformColor4f(1.0f, 1.0f, 1.0f, 0.08f); /* draw grid elements */ @@ -1128,7 +1128,7 @@ static void ui_draw_colorband_handle(uint shdr_pos, if (active || half_width < min_width) { immUnbindProgram(); - immBindBuiltinProgram(GPU_SHADER_2D_LINE_DASHED_UNIFORM_COLOR); + immBindBuiltinProgram(GPU_SHADER_3D_LINE_DASHED_UNIFORM_COLOR); float viewport_size[4]; GPU_viewport_size_get_f(viewport_size); @@ -1147,7 +1147,7 @@ static void ui_draw_colorband_handle(uint shdr_pos, immUnbindProgram(); - immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); /* hide handles when zoomed out too far */ if (half_width < min_width) { @@ -1242,7 +1242,7 @@ void ui_draw_but_COLORBAND(uiBut *but, const uiWidgetColors *UNUSED(wcol), const format = immVertexFormat(); pos_id = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); col_id = GPU_vertformat_attr_add(format, "color", GPU_COMP_F32, 4, GPU_FETCH_FLOAT); - immBindBuiltinProgram(GPU_SHADER_2D_SMOOTH_COLOR); + immBindBuiltinProgram(GPU_SHADER_3D_SMOOTH_COLOR); /* layer: color ramp */ GPU_blend(GPU_BLEND_ALPHA); @@ -1298,7 +1298,7 @@ void ui_draw_but_COLORBAND(uiBut *but, const uiWidgetColors *UNUSED(wcol), const /* New format */ format = immVertexFormat(); pos_id = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); - immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); /* layer: box outline */ immUniformColor4f(0.0f, 0.0f, 0.0f, 1.0f); @@ -1400,7 +1400,7 @@ void ui_draw_but_UNITVEC(uiBut *but, /* AA circle */ GPUVertFormat *format = immVertexFormat(); const uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); - immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); immUniformColor3ubv(wcol->inner); GPU_blend(GPU_BLEND_ALPHA); @@ -1534,7 +1534,7 @@ void ui_draw_but_CURVE(ARegion *region, uiBut *but, const uiWidgetColors *wcol, GPUVertFormat *format = immVertexFormat(); uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); - immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); /* backdrop */ float color_backdrop[4] = {0, 0, 0, 1}; @@ -1657,7 +1657,7 @@ void ui_draw_but_CURVE(ARegion *region, uiBut *but, const uiWidgetColors *wcol, line_range.ymax = rect->ymin + zoomy * (cmp[CM_TABLE].y - offsy - cuma->ext_out[1]); } - immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); GPU_blend(GPU_BLEND_ALPHA); /* Curve filled. */ @@ -1698,7 +1698,7 @@ void ui_draw_but_CURVE(ARegion *region, uiBut *but, const uiWidgetColors *wcol, format = immVertexFormat(); pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); const uint col = GPU_vertformat_attr_add(format, "color", GPU_COMP_F32, 4, GPU_FETCH_FLOAT); - immBindBuiltinProgram(GPU_SHADER_2D_FLAT_COLOR); + immBindBuiltinProgram(GPU_SHADER_3D_FLAT_COLOR); /* Calculate vertex colors based on text theme. */ float color_vert[4], color_vert_select[4]; @@ -1730,7 +1730,7 @@ void ui_draw_but_CURVE(ARegion *region, uiBut *but, const uiWidgetColors *wcol, /* outline */ format = immVertexFormat(); pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); - immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); immUniformColor3ubv(wcol->outline); imm_draw_box_wire_2d(pos, rect->xmin, rect->ymin, rect->xmax, rect->ymax); @@ -1790,7 +1790,7 @@ void ui_draw_but_CURVEPROFILE(ARegion *region, GPUVertFormat *format = immVertexFormat(); uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); - immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); /* Draw the backdrop. */ float color_backdrop[4] = {0, 0, 0, 1}; @@ -1948,7 +1948,7 @@ void ui_draw_but_CURVEPROFILE(ARegion *region, format = immVertexFormat(); pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); const uint col = GPU_vertformat_attr_add(format, "color", GPU_COMP_F32, 4, GPU_FETCH_FLOAT); - immBindBuiltinProgram(GPU_SHADER_2D_FLAT_COLOR); + immBindBuiltinProgram(GPU_SHADER_3D_FLAT_COLOR); /* Calculate vertex colors based on text theme. */ float color_vert[4], color_vert_select[4], color_sample[4]; @@ -2025,7 +2025,7 @@ void ui_draw_but_CURVEPROFILE(ARegion *region, /* Outline */ format = immVertexFormat(); pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); - immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); immUniformColor3ubv((const uchar *)wcol->outline); imm_draw_box_wire_2d(pos, rect->xmin, rect->ymin, rect->xmax, rect->ymax); @@ -2132,7 +2132,7 @@ void ui_draw_but_TRACKPREVIEW(ARegion *UNUSED(region), color); } - IMMDrawPixelsTexState state = immDrawPixelsTexSetup(GPU_SHADER_2D_IMAGE_COLOR); + IMMDrawPixelsTexState state = immDrawPixelsTexSetup(GPU_SHADER_3D_IMAGE_COLOR); immDrawPixelsTexTiled(&state, rect.xmin, rect.ymin + 1, @@ -2152,7 +2152,7 @@ void ui_draw_but_TRACKPREVIEW(ARegion *UNUSED(region), GPUVertFormat *format = immVertexFormat(); const uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); const uint col = GPU_vertformat_attr_add(format, "color", GPU_COMP_F32, 4, GPU_FETCH_FLOAT); - immBindBuiltinProgram(GPU_SHADER_2D_FLAT_COLOR); + immBindBuiltinProgram(GPU_SHADER_3D_FLAT_COLOR); UI_GetThemeColor4fv(TH_SEL_MARKER, col_sel); UI_GetThemeColor4fv(TH_MARKER_OUTLINE, col_outline); @@ -2288,7 +2288,7 @@ void UI_draw_box_shadow(const rctf *rect, uchar alpha) uint color = GPU_vertformat_attr_add( format, "color", GPU_COMP_U8, 4, GPU_FETCH_INT_TO_FLOAT_UNIT); - immBindBuiltinProgram(GPU_SHADER_2D_SMOOTH_COLOR); + immBindBuiltinProgram(GPU_SHADER_3D_SMOOTH_COLOR); immBegin(GPU_PRIM_TRIS, 54); @@ -2307,9 +2307,6 @@ void UI_draw_box_shadow(const rctf *rect, uchar alpha) void ui_draw_dropshadow( const rctf *rct, float radius, float aspect, float alpha, int UNUSED(select)) { - const float max_radius = (BLI_rctf_size_y(rct) - 10.0f) * 0.5f; - const float rad = min_ff(radius, max_radius); - /* This undoes the scale of the view for higher zoom factors to clamp the shadow size. */ const float clamped_aspect = smoothminf(aspect, 1.0f, 0.5f); @@ -2317,6 +2314,9 @@ void ui_draw_dropshadow( const float shadow_offset = 0.5f * U.widget_unit * clamped_aspect; const float shadow_alpha = 0.5f * alpha; + const float max_radius = (BLI_rctf_size_y(rct) - shadow_offset) * 0.5f; + const float rad = min_ff(radius, max_radius); + GPU_blend(GPU_BLEND_ALPHA); uiWidgetBaseParameters widget_params = { diff --git a/source/blender/editors/interface/interface_handlers.c b/source/blender/editors/interface/interface_handlers.c index 6ee421fb4d2..ea1770db6f5 100644 --- a/source/blender/editors/interface/interface_handlers.c +++ b/source/blender/editors/interface/interface_handlers.c @@ -959,7 +959,7 @@ static void ui_apply_but_undo(uiBut *but) str = ""; } - /* delayed, after all other funcs run, popups are closed, etc */ + /* Delayed, after all other functions run, popups are closed, etc. */ uiAfterFunc *after = ui_afterfunc_new(); BLI_strncpy(after->undostr, str, min_zz(str_len_clip + 1, sizeof(after->undostr))); } @@ -991,7 +991,7 @@ static void ui_apply_but_autokey(bContext *C, uiBut *but) static void ui_apply_but_funcs_after(bContext *C) { - /* copy to avoid recursive calls */ + /* Copy to avoid recursive calls. */ ListBase funcs = UIAfterFuncs; BLI_listbase_clear(&UIAfterFuncs); diff --git a/source/blender/editors/interface/interface_icons.c b/source/blender/editors/interface/interface_icons.c index 5bb33576723..ad2c08194aa 100644 --- a/source/blender/editors/interface/interface_icons.c +++ b/source/blender/editors/interface/interface_icons.c @@ -360,7 +360,7 @@ static void vicon_colorset_draw(int index, int x, int y, int w, int h, float UNU uint pos = GPU_vertformat_attr_add( immVertexFormat(), "pos", GPU_COMP_I32, 2, GPU_FETCH_INT_TO_FLOAT); - immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); /* XXX: Include alpha into this... */ /* normal */ @@ -505,7 +505,7 @@ static void vicon_gplayer_color_draw(Icon *icon, int x, int y, int w, int h) */ uint pos = GPU_vertformat_attr_add( immVertexFormat(), "pos", GPU_COMP_I32, 2, GPU_FETCH_INT_TO_FLOAT); - immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); immUniformColor3fv(gpl->color); immRecti(pos, x, y, x + w - 1, y + h - 1); @@ -1546,7 +1546,7 @@ static void icon_draw_rect(float x, shader = GPU_SHADER_2D_IMAGE_DESATURATE_COLOR; } else { - shader = GPU_SHADER_2D_IMAGE_COLOR; + shader = GPU_SHADER_3D_IMAGE_COLOR; } IMMDrawPixelsTexState state = immDrawPixelsTexSetup(shader); diff --git a/source/blender/editors/interface/interface_icons_event.c b/source/blender/editors/interface/interface_icons_event.c index 6ad5fe805ab..e892a989191 100644 --- a/source/blender/editors/interface/interface_icons_event.c +++ b/source/blender/editors/interface/interface_icons_event.c @@ -60,10 +60,8 @@ #include "interface_intern.h" -static void icon_draw_rect_input_text(const rctf *rect, - const float color[4], - const char *str, - float font_size) +static void icon_draw_rect_input_text( + const rctf *rect, const float color[4], const char *str, float font_size, float v_offset) { BLF_batch_draw_flush(); const int font_id = BLF_default(); @@ -71,21 +69,9 @@ static void icon_draw_rect_input_text(const rctf *rect, BLF_size(font_id, font_size * U.pixelsize, U.dpi); float width, height; BLF_width_and_height(font_id, str, BLF_DRAW_STR_DUMMY_MAX, &width, &height); - const float x = rect->xmin + (((rect->xmax - rect->xmin) - width) / 2.0f); - const float y = rect->ymin + (((rect->ymax - rect->ymin) - height) / 2.0f); - BLF_position(font_id, x, y, 0.0f); - BLF_draw(font_id, str, BLF_DRAW_STR_DUMMY_MAX); - BLF_batch_draw_flush(); -} - -static void icon_draw_rect_input_symbol(const rctf *rect, const float color[4], const char *str) -{ - BLF_batch_draw_flush(); - const int font_id = blf_mono_font; - BLF_color4fv(font_id, color); - BLF_size(font_id, 19.0f * U.pixelsize, U.dpi); - const float x = rect->xmin + (2.0f * U.pixelsize); - const float y = rect->ymin + (1.0f * U.pixelsize); + const float x = trunc(rect->xmin + (((rect->xmax - rect->xmin) - width) / 2.0f)); + const float y = rect->ymin + (((rect->ymax - rect->ymin) - height) / 2.0f) + + (v_offset * U.dpi_fac); BLF_position(font_id, x, y, 0.0f); BLF_draw(font_id, str, BLF_DRAW_STR_DUMMY_MAX); BLF_batch_draw_flush(); @@ -99,20 +85,17 @@ void icon_draw_rect_input(float x, short event_type, short UNUSED(event_value)) { + rctf rect = { + .xmin = (int)x - U.pixelsize, + .xmax = (int)(x + w + U.pixelsize), + .ymin = (int)(y), + .ymax = (int)(y + h), + }; float color[4]; GPU_line_width(1.0f); UI_GetThemeColor4fv(TH_TEXT, color); UI_draw_roundbox_corner_set(UI_CNR_ALL); - UI_draw_roundbox_aa( - &(const rctf){ - .xmin = (int)x - U.pixelsize, - .xmax = (int)(x + w), - .ymin = (int)y, - .ymax = (int)(y + h), - }, - false, - 3.0f * U.pixelsize, - color); + UI_draw_roundbox_aa(&rect, false, 3.0f * U.pixelsize, color); const enum { UNIX, @@ -129,94 +112,89 @@ void icon_draw_rect_input(float x, #endif ; - const rctf rect = { - .xmin = x, - .ymin = y, - .xmax = x + w, - .ymax = y + h, - }; - if ((event_type >= EVT_AKEY) && (event_type <= EVT_ZKEY)) { const char str[2] = {'A' + (event_type - EVT_AKEY), '\0'}; - icon_draw_rect_input_text(&rect, color, str, 13.0f); + icon_draw_rect_input_text(&rect, color, str, 13.0f, 0.0f); } - else if ((event_type >= EVT_F1KEY) && (event_type <= EVT_F12KEY)) { + else if ((event_type >= EVT_F1KEY) && (event_type <= EVT_F24KEY)) { char str[4]; SNPRINTF(str, "F%d", 1 + (event_type - EVT_F1KEY)); - icon_draw_rect_input_text(&rect, color, str, event_type > EVT_F9KEY ? 8.0f : 10.0f); + icon_draw_rect_input_text(&rect, color, str, event_type > EVT_F9KEY ? 8.5f : 11.5f, 0.0f); } else if (event_type == EVT_LEFTSHIFTKEY) { /* Right Shift has already been converted to left. */ - icon_draw_rect_input_symbol(&rect, color, (const char[]){0xe2, 0x87, 0xa7, 0x0}); + icon_draw_rect_input_text(&rect, color, (const char[]){0xe2, 0x87, 0xa7, 0x0}, 16.0f, 0.0f); } else if (event_type == EVT_LEFTCTRLKEY) { /* Right Shift has already been converted to left. */ if (platform == MACOS) { - icon_draw_rect_input_symbol(&rect, color, (const char[]){0xe2, 0x8c, 0x83, 0x0}); + icon_draw_rect_input_text(&rect, color, (const char[]){0xe2, 0x8c, 0x83, 0x0}, 21.0f, -8.0f); } else { - icon_draw_rect_input_text(&rect, color, "Ctrl", 9.0f); + icon_draw_rect_input_text(&rect, color, "Ctrl", 9.0f, 0.0f); } } else if (event_type == EVT_LEFTALTKEY) { /* Right Alt has already been converted to left. */ if (platform == MACOS) { - icon_draw_rect_input_symbol(&rect, color, (const char[]){0xe2, 0x8c, 0xa5, 0x0}); + icon_draw_rect_input_text(&rect, color, (const char[]){0xe2, 0x8c, 0xa5, 0x0}, 13.0f, 0.0f); } else { - icon_draw_rect_input_text(&rect, color, "Alt", 10.0f); + icon_draw_rect_input_text(&rect, color, "Alt", 10.0f, 0.0f); } } else if (event_type == EVT_OSKEY) { if (platform == MACOS) { - icon_draw_rect_input_symbol(&rect, color, (const char[]){0xe2, 0x8c, 0x98, 0x0}); + icon_draw_rect_input_text(&rect, color, (const char[]){0xe2, 0x8c, 0x98, 0x0}, 16.0f, 0.0f); } else if (platform == MSWIN) { - icon_draw_rect_input_symbol(&rect, color, (const char[]){0xe2, 0x9d, 0x96, 0x0}); + icon_draw_rect_input_text(&rect, color, (const char[]){0xe2, 0x9d, 0x96, 0x0}, 16.0f, 0.0f); } else { - icon_draw_rect_input_text(&rect, color, "OS", 10.0f); + icon_draw_rect_input_text(&rect, color, "OS", 10.0f, 0.0f); } } else if (event_type == EVT_DELKEY) { - icon_draw_rect_input_text(&rect, color, "Del", 9.0f); + icon_draw_rect_input_text(&rect, color, "Del", 9.0f, 0.0f); } else if (event_type == EVT_TABKEY) { - icon_draw_rect_input_symbol(&rect, color, (const char[]){0xe2, 0xad, 0xbe, 0x0}); + icon_draw_rect_input_text(&rect, color, (const char[]){0xe2, 0xad, 0xbe, 0x0}, 18.0f, -1.5f); } else if (event_type == EVT_HOMEKEY) { - icon_draw_rect_input_text(&rect, color, "Home", 6.0f); + icon_draw_rect_input_text(&rect, color, "Home", 6.0f, 0.0f); } else if (event_type == EVT_ENDKEY) { - icon_draw_rect_input_text(&rect, color, "End", 8.0f); + icon_draw_rect_input_text(&rect, color, "End", 8.0f, 0.0f); } else if (event_type == EVT_RETKEY) { - icon_draw_rect_input_symbol(&rect, color, (const char[]){0xe2, 0x8f, 0x8e, 0x0}); + icon_draw_rect_input_text(&rect, color, (const char[]){0xe2, 0x8f, 0x8e, 0x0}, 17.0f, -1.0f); } else if (event_type == EVT_ESCKEY) { if (platform == MACOS) { - icon_draw_rect_input_symbol(&rect, color, (const char[]){0xe2, 0x8e, 0x8b, 0x0}); + icon_draw_rect_input_text(&rect, color, (const char[]){0xe2, 0x8e, 0x8b, 0x0}, 21.0f, -1.0f); } else { - icon_draw_rect_input_text(&rect, color, "Esc", 8.0f); + icon_draw_rect_input_text(&rect, color, "Esc", 8.5f, 0.0f); } } else if (event_type == EVT_PAGEUPKEY) { - icon_draw_rect_input_text(&rect, color, (const char[]){'P', 0xe2, 0x86, 0x91, 0x0}, 8.0f); + icon_draw_rect_input_text( + &rect, color, (const char[]){'P', 0xe2, 0x86, 0x91, 0x0}, 12.0f, 0.0f); } else if (event_type == EVT_PAGEDOWNKEY) { - icon_draw_rect_input_text(&rect, color, (const char[]){'P', 0xe2, 0x86, 0x93, 0x0}, 8.0f); + icon_draw_rect_input_text( + &rect, color, (const char[]){'P', 0xe2, 0x86, 0x93, 0x0}, 12.0f, 0.0f); } else if (event_type == EVT_LEFTARROWKEY) { - icon_draw_rect_input_symbol(&rect, color, (const char[]){0xe2, 0x86, 0x90, 0x0}); + icon_draw_rect_input_text(&rect, color, (const char[]){0xe2, 0x86, 0x90, 0x0}, 18.0f, -1.5f); } else if (event_type == EVT_UPARROWKEY) { - icon_draw_rect_input_symbol(&rect, color, (const char[]){0xe2, 0x86, 0x91, 0x0}); + icon_draw_rect_input_text(&rect, color, (const char[]){0xe2, 0x86, 0x91, 0x0}, 16.0f, 0.0f); } else if (event_type == EVT_RIGHTARROWKEY) { - icon_draw_rect_input_symbol(&rect, color, (const char[]){0xe2, 0x86, 0x92, 0x0}); + icon_draw_rect_input_text(&rect, color, (const char[]){0xe2, 0x86, 0x92, 0x0}, 18.0f, -1.5f); } else if (event_type == EVT_DOWNARROWKEY) { - icon_draw_rect_input_symbol(&rect, color, (const char[]){0xe2, 0x86, 0x93, 0x0}); + icon_draw_rect_input_text(&rect, color, (const char[]){0xe2, 0x86, 0x93, 0x0}, 16.0f, 0.0f); } else if (event_type == EVT_SPACEKEY) { - icon_draw_rect_input_symbol(&rect, color, (const char[]){0xe2, 0x90, 0xa3, 0x0}); + icon_draw_rect_input_text(&rect, color, (const char[]){0xe2, 0x90, 0xa3, 0x0}, 20.0f, 2.0f); } } diff --git a/source/blender/editors/interface/interface_intern.h b/source/blender/editors/interface/interface_intern.h index d75d86c2665..6ef7d346418 100644 --- a/source/blender/editors/interface/interface_intern.h +++ b/source/blender/editors/interface/interface_intern.h @@ -25,6 +25,7 @@ struct CurveMapping; struct CurveProfile; struct ID; struct ImBuf; +struct Main; struct Scene; struct bContext; struct bContextStore; @@ -306,6 +307,8 @@ typedef struct uiButSearch { uiButSearchCreateFn popup_create_fn; uiButSearchUpdateFn items_update_fn; + uiButSearchListenFn listen_fn; + void *item_active; void *arg; @@ -1543,6 +1546,12 @@ uiButViewItem *ui_block_view_find_matching_view_item_but_in_old_block( struct uiListType *UI_UL_cache_file_layers(void); +struct ID *ui_template_id_liboverride_hierarchy_make(struct bContext *C, + struct Main *bmain, + struct ID *owner_id, + struct ID *id, + const char **r_undo_push_label); + #ifdef __cplusplus } #endif diff --git a/source/blender/editors/interface/interface_layout.c b/source/blender/editors/interface/interface_layout.c index 3465373c85d..d002dd643c3 100644 --- a/source/blender/editors/interface/interface_layout.c +++ b/source/blender/editors/interface/interface_layout.c @@ -694,7 +694,7 @@ static void ui_item_array(uiLayout *layout, else { /* Even if 'expand' is false, we expand anyway. */ - /* layout for known array subtypes */ + /* Layout for known array sub-types. */ char str[3] = {'\0'}; if (!icon_only && show_text) { @@ -3028,7 +3028,14 @@ void uiItemMContents(uiLayout *layout, const char *menuname) if (WM_menutype_poll(C, mt) == false) { return; } + + bContextStore *previous_ctx = CTX_store_get(C); UI_menutype_draw(C, mt, layout); + + /* Restore context that was cleared by `UI_menutype_draw`. */ + if (layout->context) { + CTX_store_set(C, previous_ctx); + } } void uiItemDecoratorR_prop(uiLayout *layout, PointerRNA *ptr, PropertyRNA *prop, int index) diff --git a/source/blender/editors/interface/interface_ops.cc b/source/blender/editors/interface/interface_ops.cc index 2533a5454a5..603b2c96713 100644 --- a/source/blender/editors/interface/interface_ops.cc +++ b/source/blender/editors/interface/interface_ops.cc @@ -21,6 +21,7 @@ #include "BLF_api.h" #include "BLT_lang.h" +#include "BLT_translation.h" #include "BKE_context.h" #include "BKE_global.h" @@ -28,6 +29,7 @@ #include "BKE_layer.h" #include "BKE_lib_id.h" #include "BKE_lib_override.h" +#include "BKE_lib_remap.h" #include "BKE_material.h" #include "BKE_node.h" #include "BKE_report.h" @@ -131,10 +133,10 @@ static int copy_data_path_button_exec(bContext *C, wmOperator *op) if (ptr.owner_id != nullptr) { if (full_path) { if (prop) { - path = RNA_path_full_property_py_ex(bmain, &ptr, prop, index, true); + path = RNA_path_full_property_py_ex(&ptr, prop, index, true); } else { - path = RNA_path_full_struct_py(bmain, &ptr); + path = RNA_path_full_struct_py(&ptr); } } else { @@ -747,6 +749,285 @@ static void UI_OT_override_remove_button(wmOperatorType *ot) ot->srna, "all", true, "All", "Reset to default values all elements of the array"); } +static void override_idtemplate_ids_get( + bContext *C, ID **r_owner_id, ID **r_id, PointerRNA *r_owner_ptr, PropertyRNA **r_prop) +{ + PointerRNA owner_ptr; + PropertyRNA *prop; + UI_context_active_but_prop_get_templateID(C, &owner_ptr, &prop); + + if (owner_ptr.data == nullptr || prop == nullptr) { + *r_owner_id = *r_id = nullptr; + if (r_owner_ptr != nullptr) { + *r_owner_ptr = PointerRNA_NULL; + } + if (r_prop != nullptr) { + *r_prop = nullptr; + } + return; + } + + *r_owner_id = owner_ptr.owner_id; + PointerRNA idptr = RNA_property_pointer_get(&owner_ptr, prop); + *r_id = static_cast<ID *>(idptr.data); + if (r_owner_ptr != nullptr) { + *r_owner_ptr = owner_ptr; + } + if (r_prop != nullptr) { + *r_prop = prop; + } +} + +static bool override_idtemplate_poll(bContext *C, const bool is_create_op) +{ + ID *owner_id, *id; + override_idtemplate_ids_get(C, &owner_id, &id, nullptr, nullptr); + + if (owner_id == nullptr || id == nullptr) { + return false; + } + + if (is_create_op) { + if (!ID_IS_LINKED(id) && !ID_IS_OVERRIDE_LIBRARY_REAL(id)) { + return false; + } + return true; + } + + /* Reset/Clear operations. */ + if (ID_IS_LINKED(id) || !ID_IS_OVERRIDE_LIBRARY_REAL(id)) { + return false; + } + return true; +} + +static bool override_idtemplate_make_poll(bContext *C) +{ + return override_idtemplate_poll(C, true); +} + +static int override_idtemplate_make_exec(bContext *C, wmOperator *UNUSED(op)) +{ + ID *owner_id, *id; + PointerRNA owner_ptr; + PropertyRNA *prop; + override_idtemplate_ids_get(C, &owner_id, &id, &owner_ptr, &prop); + if (ELEM(nullptr, owner_id, id)) { + return OPERATOR_CANCELLED; + } + + ID *id_override = ui_template_id_liboverride_hierarchy_make( + C, CTX_data_main(C), owner_id, id, nullptr); + + if (id_override == nullptr) { + return OPERATOR_CANCELLED; + } + + PointerRNA idptr; + /* `idptr` is re-assigned to owner property to ensure proper updates etc. Here we also use it + * to ensure remapping of the owner property from the linked data to the newly created + * liboverride (note that in theory this remapping has already been done by code above), but + * only in case owner ID was already local ID (override or pure local data). + * + * Otherwise, owner ID will also have been overridden, and remapped already to use it's + * override of the data too. */ + if (!ID_IS_LINKED(owner_id)) { + RNA_id_pointer_create(id_override, &idptr); + RNA_property_pointer_set(&owner_ptr, prop, idptr, nullptr); + } + RNA_property_update(C, &owner_ptr, prop); + + /* 'Security' extra tagging, since this process may also affect the owner ID and not only the + * used ID, relying on the property update code only is not always enough. */ + DEG_id_tag_update(&CTX_data_scene(C)->id, ID_RECALC_BASE_FLAGS | ID_RECALC_COPY_ON_WRITE); + WM_event_add_notifier(C, NC_WINDOW, nullptr); + WM_event_add_notifier(C, NC_WM | ND_LIB_OVERRIDE_CHANGED, nullptr); + WM_event_add_notifier(C, NC_SPACE | ND_SPACE_VIEW3D, nullptr); + + return OPERATOR_FINISHED; +} + +static void UI_OT_override_idtemplate_make(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Make Library Override"; + ot->idname = "UI_OT_override_idtemplate_make"; + ot->description = + "Create a local override of the selected linked data-block, and its hierarchy of " + "dependencies"; + + /* callbacks */ + ot->poll = override_idtemplate_make_poll; + ot->exec = override_idtemplate_make_exec; + + /* flags */ + ot->flag = OPTYPE_UNDO; +} + +static bool override_idtemplate_reset_poll(bContext *C) +{ + return override_idtemplate_poll(C, false); +} + +static int override_idtemplate_reset_exec(bContext *C, wmOperator *UNUSED(op)) +{ + ID *owner_id, *id; + PointerRNA owner_ptr; + PropertyRNA *prop; + override_idtemplate_ids_get(C, &owner_id, &id, &owner_ptr, &prop); + if (ELEM(nullptr, owner_id, id)) { + return OPERATOR_CANCELLED; + } + + if (ID_IS_LINKED(id) || !ID_IS_OVERRIDE_LIBRARY_REAL(id)) { + return OPERATOR_CANCELLED; + } + + BKE_lib_override_library_id_reset(CTX_data_main(C), id, false); + + PointerRNA idptr; + /* `idptr` is re-assigned to owner property to ensure proper updates etc. */ + RNA_id_pointer_create(id, &idptr); + RNA_property_pointer_set(&owner_ptr, prop, idptr, nullptr); + RNA_property_update(C, &owner_ptr, prop); + + /* No need for 'security' extra tagging here, since this process will never affect the owner ID. + */ + + return OPERATOR_FINISHED; +} + +static void UI_OT_override_idtemplate_reset(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Reset Library Override"; + ot->idname = "UI_OT_override_idtemplate_reset"; + ot->description = "Reset the selected local override to its linked reference values"; + + /* callbacks */ + ot->poll = override_idtemplate_reset_poll; + ot->exec = override_idtemplate_reset_exec; + + /* flags */ + ot->flag = OPTYPE_UNDO; +} + +static bool override_idtemplate_clear_poll(bContext *C) +{ + return override_idtemplate_poll(C, false); +} + +static int override_idtemplate_clear_exec(bContext *C, wmOperator *UNUSED(op)) +{ + ID *owner_id, *id; + PointerRNA owner_ptr; + PropertyRNA *prop; + override_idtemplate_ids_get(C, &owner_id, &id, &owner_ptr, &prop); + if (ELEM(nullptr, owner_id, id)) { + return OPERATOR_CANCELLED; + } + + if (ID_IS_LINKED(id)) { + return OPERATOR_CANCELLED; + } + + Main *bmain = CTX_data_main(C); + ViewLayer *view_layer = CTX_data_view_layer(C); + Scene *scene = CTX_data_scene(C); + ID *id_new = id; + + if (BKE_lib_override_library_is_hierarchy_leaf(bmain, id)) { + id_new = id->override_library->reference; + bool do_remap_active = false; + BKE_view_layer_synced_ensure(scene, view_layer); + if (BKE_view_layer_active_object_get(view_layer) == (Object *)id) { + BLI_assert(GS(id->name) == ID_OB); + BLI_assert(GS(id_new->name) == ID_OB); + do_remap_active = true; + } + BKE_libblock_remap(bmain, id, id_new, ID_REMAP_SKIP_INDIRECT_USAGE); + if (do_remap_active) { + Object *ref_object = (Object *)id_new; + Base *basact = BKE_view_layer_base_find(view_layer, ref_object); + if (basact != nullptr) { + view_layer->basact = basact; + } + DEG_id_tag_update(&scene->id, ID_RECALC_SELECT); + } + BKE_id_delete(bmain, id); + } + else { + BKE_lib_override_library_id_reset(bmain, id, true); + } + + /* Here the affected ID may remain the same, or be replaced by its linked reference. In either + * case, the owner ID remains unchanged, and remapping is already handled by internal code, so + * calling `RNA_property_update` on it is enough to ensure proper notifiers are sent. */ + RNA_property_update(C, &owner_ptr, prop); + + /* 'Security' extra tagging, since this process may also affect the owner ID and not only the + * used ID, relying on the property update code only is not always enough. */ + DEG_id_tag_update(&scene->id, ID_RECALC_BASE_FLAGS | ID_RECALC_COPY_ON_WRITE); + WM_event_add_notifier(C, NC_WINDOW, nullptr); + WM_event_add_notifier(C, NC_WM | ND_LIB_OVERRIDE_CHANGED, nullptr); + WM_event_add_notifier(C, NC_SPACE | ND_SPACE_VIEW3D, nullptr); + + return OPERATOR_FINISHED; +} + +static void UI_OT_override_idtemplate_clear(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Clear Library Override"; + ot->idname = "UI_OT_override_idtemplate_clear"; + ot->description = + "Delete the selected local override and relink its usages to the linked data-block if " + "possible, else reset it and mark it as non editable"; + + /* callbacks */ + ot->poll = override_idtemplate_clear_poll; + ot->exec = override_idtemplate_clear_exec; + + /* flags */ + ot->flag = OPTYPE_UNDO; +} + +static bool override_idtemplate_menu_poll(const bContext *C_const, MenuType *UNUSED(mt)) +{ + bContext *C = (bContext *)C_const; + ID *owner_id, *id; + override_idtemplate_ids_get(C, &owner_id, &id, nullptr, nullptr); + + if (owner_id == nullptr || id == nullptr) { + return false; + } + + if (!(ID_IS_LINKED(id) || ID_IS_OVERRIDE_LIBRARY_REAL(id))) { + return false; + } + return true; +} + +static void override_idtemplate_menu_draw(const bContext *UNUSED(C), Menu *menu) +{ + uiLayout *layout = menu->layout; + uiItemO(layout, IFACE_("Make"), ICON_NONE, "UI_OT_override_idtemplate_make"); + uiItemO(layout, IFACE_("Reset"), ICON_NONE, "UI_OT_override_idtemplate_reset"); + uiItemO(layout, IFACE_("Clear"), ICON_NONE, "UI_OT_override_idtemplate_clear"); +} + +static void override_idtemplate_menu() +{ + MenuType *mt; + + mt = MEM_cnew<MenuType>(__func__); + strcpy(mt->idname, "UI_MT_idtemplate_liboverride"); + strcpy(mt->label, N_("Library Override")); + mt->poll = override_idtemplate_menu_poll; + mt->draw = override_idtemplate_menu_draw; + WM_menutype_add(mt); +} + /** \} */ /* -------------------------------------------------------------------- */ @@ -1222,14 +1503,16 @@ static bool jump_to_target_ptr(bContext *C, PointerRNA ptr, const bool poll) } /* Find the containing Object. */ + const Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); Base *base = nullptr; const short id_type = GS(ptr.owner_id->name); if (id_type == ID_OB) { + BKE_view_layer_synced_ensure(scene, view_layer); base = BKE_view_layer_base_find(view_layer, (Object *)ptr.owner_id); } else if (OB_DATA_SUPPORT_ID(id_type)) { - base = ED_object_find_first_by_data_id(view_layer, ptr.owner_id); + base = ED_object_find_first_by_data_id(scene, view_layer, ptr.owner_id); } bool ok = false; @@ -1294,8 +1577,13 @@ static bool jump_to_target_button(bContext *C, bool poll) char *str_ptr = RNA_property_string_get_alloc( &ptr, prop, str_buf, sizeof(str_buf), nullptr); - int found = RNA_property_collection_lookup_string( - &coll_search->search_ptr, coll_search->search_prop, str_ptr, &target_ptr); + int found = 0; + /* Jump to target only works with search properties currently, not search callbacks yet. + * See ui_but_add_search. */ + if (coll_search->search_prop != NULL) { + found = RNA_property_collection_lookup_string( + &coll_search->search_ptr, coll_search->search_prop, str_ptr, &target_ptr); + } if (str_ptr != str_buf) { MEM_freeN(str_ptr); @@ -1347,7 +1635,7 @@ static void UI_OT_jump_to_target_button(wmOperatorType *ot) #ifdef WITH_PYTHON /* ------------------------------------------------------------------------- */ -/* EditSource Utility funcs and operator, +/* EditSource Utility functions and operator, * NOTE: this includes utility functions and button matching checks. */ struct uiEditSourceStore { @@ -1559,7 +1847,7 @@ static void UI_OT_editsource(wmOperatorType *ot) * \{ */ /** - * EditTranslation utility funcs and operator, + * EditTranslation utility functions and operator. * * \note this includes utility functions and button matching checks. * this only works in conjunction with a Python operator! @@ -2073,6 +2361,9 @@ static bool ui_view_drop_poll(bContext *C) { const wmWindow *win = CTX_wm_window(C); const ARegion *region = CTX_wm_region(C); + if (region == nullptr) { + return false; + } const uiViewItemHandle *hovered_item = UI_region_views_find_item_at(region, win->eventstate->xy); return hovered_item != nullptr; @@ -2121,6 +2412,9 @@ static void UI_OT_view_drop(wmOperatorType *ot) static bool ui_view_item_rename_poll(bContext *C) { const ARegion *region = CTX_wm_region(C); + if (region == nullptr) { + return false; + } const uiViewItemHandle *active_item = UI_region_views_find_active_item(region); return active_item != nullptr && UI_view_item_can_rename(active_item); } @@ -2232,8 +2526,6 @@ void ED_operatortypes_ui(void) WM_operatortype_append(UI_OT_reset_default_button); WM_operatortype_append(UI_OT_assign_default_button); WM_operatortype_append(UI_OT_unset_property_button); - WM_operatortype_append(UI_OT_override_type_set_button); - WM_operatortype_append(UI_OT_override_remove_button); WM_operatortype_append(UI_OT_copy_to_selected_button); WM_operatortype_append(UI_OT_jump_to_target_button); WM_operatortype_append(UI_OT_drop_color); @@ -2252,6 +2544,13 @@ void ED_operatortypes_ui(void) WM_operatortype_append(UI_OT_view_drop); WM_operatortype_append(UI_OT_view_item_rename); + WM_operatortype_append(UI_OT_override_type_set_button); + WM_operatortype_append(UI_OT_override_remove_button); + WM_operatortype_append(UI_OT_override_idtemplate_make); + WM_operatortype_append(UI_OT_override_idtemplate_reset); + WM_operatortype_append(UI_OT_override_idtemplate_clear); + override_idtemplate_menu(); + /* external */ WM_operatortype_append(UI_OT_eyedropper_color); WM_operatortype_append(UI_OT_eyedropper_colorramp); diff --git a/source/blender/editors/interface/interface_panel.cc b/source/blender/editors/interface/interface_panel.cc index dc6a0fecb73..745a2201dc1 100644 --- a/source/blender/editors/interface/interface_panel.cc +++ b/source/blender/editors/interface/interface_panel.cc @@ -1160,7 +1160,7 @@ static void panel_draw_aligned_widgets(const uiStyle *style, GPUBatch *batch = GPU_batch_preset_panel_drag_widget( U.pixelsize, color_high, color_dark, drag_widget_size); - GPU_batch_program_set_builtin(batch, GPU_SHADER_2D_FLAT_COLOR); + GPU_batch_program_set_builtin(batch, GPU_SHADER_3D_FLAT_COLOR); GPU_batch_draw(batch); GPU_matrix_pop(); } @@ -1181,7 +1181,7 @@ static void panel_draw_aligned_backdrop(const Panel *panel, const float aspect = panel->runtime.block->aspect; const float radius = btheme->tui.panel_roundness * U.widget_unit * 0.5f / aspect; - immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); GPU_blend(GPU_BLEND_ALPHA); /* Panel backdrop. */ @@ -1384,7 +1384,7 @@ void UI_panel_category_draw_all(ARegion *region, const char *category_id_active) uint pos = GPU_vertformat_attr_add( immVertexFormat(), "pos", GPU_COMP_I32, 2, GPU_FETCH_INT_TO_FLOAT); - immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); /* Draw the background. */ if (is_alpha) { @@ -1429,7 +1429,7 @@ void UI_panel_category_draw_all(ARegion *region, const char *category_id_active) if (is_active == false && is_active_prev == false && pc_dyn->prev) { pos = GPU_vertformat_attr_add( immVertexFormat(), "pos", GPU_COMP_I32, 2, GPU_FETCH_INT_TO_FLOAT); - immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); immUniformColor3fvAlpha(theme_col_tab_outline, 0.3f); immRecti(pos, is_left ? v2d->mask.xmin + (category_tabs_width / 5) : @@ -1463,7 +1463,7 @@ void UI_panel_category_draw_all(ARegion *region, const char *category_id_active) /* Disguise the outline on one side to join the tab to the panel. */ pos = GPU_vertformat_attr_add( immVertexFormat(), "pos", GPU_COMP_I32, 2, GPU_FETCH_INT_TO_FLOAT); - immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); immUniformColor4fv(is_active ? theme_col_tab_active : theme_col_tab_inactive); immRecti(pos, diff --git a/source/blender/editors/interface/interface_region_color_picker.cc b/source/blender/editors/interface/interface_region_color_picker.cc index db1e5e653de..72912b8c7f7 100644 --- a/source/blender/editors/interface/interface_region_color_picker.cc +++ b/source/blender/editors/interface/interface_region_color_picker.cc @@ -52,10 +52,10 @@ static void ui_color_picker_rgb_round(float rgb[3]) * all color space conversions would be expensive, but for the color picker * we can do the extra work. */ for (int i = 0; i < 3; i++) { - if (fabsf(rgb[i]) < 1e-6f) { + if (fabsf(rgb[i]) < 5e-5f) { rgb[i] = 0.0f; } - else if (fabsf(1.0f - rgb[i]) < 1e-6f) { + else if (fabsf(1.0f - rgb[i]) < 5e-5f) { rgb[i] = 1.0f; } } diff --git a/source/blender/editors/interface/interface_region_menu_popup.cc b/source/blender/editors/interface/interface_region_menu_popup.cc index 0647e1a4a70..f88cabb2b70 100644 --- a/source/blender/editors/interface/interface_region_menu_popup.cc +++ b/source/blender/editors/interface/interface_region_menu_popup.cc @@ -322,7 +322,7 @@ uiPopupBlockHandle *ui_popup_menu_create( uiPopupMenu *pup = MEM_cnew<uiPopupMenu>(__func__); pup->block = UI_block_begin(C, nullptr, __func__, UI_EMBOSS_PULLDOWN); - pup->block->flag |= UI_BLOCK_NUMSELECT; /* default menus to numselect */ + pup->block->flag |= UI_BLOCK_NUMSELECT; /* Default menus to numeric-selection. */ pup->layout = UI_block_layout( pup->block, UI_LAYOUT_VERTICAL, UI_LAYOUT_MENU, 0, 0, 200, 0, UI_MENU_PADDING, style); pup->slideout = but ? ui_block_is_menu(but->block) : false; diff --git a/source/blender/editors/interface/interface_region_popup.cc b/source/blender/editors/interface/interface_region_popup.cc index f6b078c033e..daa46b150a3 100644 --- a/source/blender/editors/interface/interface_region_popup.cc +++ b/source/blender/editors/interface/interface_region_popup.cc @@ -397,7 +397,7 @@ static void ui_block_region_draw(const bContext *C, ARegion *region) static void ui_block_region_popup_window_listener(const wmRegionListenerParams *params) { ARegion *region = params->region; - wmNotifier *wmn = params->notifier; + const wmNotifier *wmn = params->notifier; switch (wmn->category) { case NC_WINDOW: { diff --git a/source/blender/editors/interface/interface_region_search.cc b/source/blender/editors/interface/interface_region_search.cc index 6bb47666afd..fb7810792e9 100644 --- a/source/blender/editors/interface/interface_region_search.cc +++ b/source/blender/editors/interface/interface_region_search.cc @@ -10,6 +10,7 @@ #include <cstdarg> #include <cstdlib> #include <cstring> +#include <iostream> #include "DNA_ID.h" #include "MEM_guardedalloc.h" @@ -86,6 +87,10 @@ struct uiSearchboxData { * Used so we can show leading text to menu items less prominently (not related to 'use_sep'). */ const char *sep_string; + + /* Owned by uiButSearch */ + void *search_arg; + uiButSearchListenFn search_listener; }; #define SEARCH_ITEMS 10 @@ -689,6 +694,14 @@ static void ui_searchbox_region_free_fn(ARegion *region) region->regiondata = nullptr; } +static void ui_searchbox_region_listen_fn(const wmRegionListenerParams *params) +{ + uiSearchboxData *data = static_cast<uiSearchboxData *>(params->region->regiondata); + if (data->search_listener) { + data->search_listener(params, data->search_arg); + } +} + static ARegion *ui_searchbox_create_generic_ex(bContext *C, ARegion *butregion, uiButSearch *search_but, @@ -707,11 +720,14 @@ static ARegion *ui_searchbox_create_generic_ex(bContext *C, memset(&type, 0, sizeof(ARegionType)); type.draw = ui_searchbox_region_draw_fn; type.free = ui_searchbox_region_free_fn; + type.listener = ui_searchbox_region_listen_fn; type.regionid = RGN_TYPE_TEMPORARY; region->type = &type; /* Create search-box data. */ uiSearchboxData *data = MEM_cnew<uiSearchboxData>(__func__); + data->search_arg = search_but->arg; + data->search_listener = search_but->listen_fn; /* Set font, get the bounding-box. */ data->fstyle = style->widget; /* copy struct */ diff --git a/source/blender/editors/interface/interface_region_tooltip.cc b/source/blender/editors/interface/interface_region_tooltip.cc index 8d88261c328..a6e37d3f36f 100644 --- a/source/blender/editors/interface/interface_region_tooltip.cc +++ b/source/blender/editors/interface/interface_region_tooltip.cc @@ -952,11 +952,10 @@ static uiTooltipData *ui_tooltip_data_from_button_or_extra_icon(bContext *C, /* never fails */ /* Move ownership (no need for re-allocation). */ if (rnaprop) { - field->text = RNA_path_full_property_py_ex( - CTX_data_main(C), &but->rnapoin, rnaprop, but->rnaindex, true); + field->text = RNA_path_full_property_py_ex(&but->rnapoin, rnaprop, but->rnaindex, true); } else { - field->text = RNA_path_full_struct_py(CTX_data_main(C), &but->rnapoin); + field->text = RNA_path_full_struct_py(&but->rnapoin); } } } diff --git a/source/blender/editors/interface/interface_regions.cc b/source/blender/editors/interface/interface_regions.cc index 1770805cf59..63c4a6f9c42 100644 --- a/source/blender/editors/interface/interface_regions.cc +++ b/source/blender/editors/interface/interface_regions.cc @@ -45,6 +45,6 @@ void ui_region_temp_remove(bContext *C, bScreen *screen, ARegion *region) } ED_region_exit(C, region); - BKE_area_region_free(nullptr, region); /* nullptr: no spacetype */ + BKE_area_region_free(nullptr, region); /* nullptr: no space-type. */ BLI_freelinkN(&screen->regionbase, region); } diff --git a/source/blender/editors/interface/interface_template_attribute_search.cc b/source/blender/editors/interface/interface_template_attribute_search.cc index 0a684903f0f..55ca945671f 100644 --- a/source/blender/editors/interface/interface_template_attribute_search.cc +++ b/source/blender/editors/interface/interface_template_attribute_search.cc @@ -14,13 +14,15 @@ #include "BLT_translation.h" -#include "NOD_geometry_nodes_eval_log.hh" +#include "BKE_attribute.hh" + +#include "NOD_geometry_nodes_log.hh" #include "UI_interface.h" #include "UI_interface.hh" #include "UI_resources.h" -using blender::nodes::geometry_nodes_eval_log::GeometryAttributeInfo; +using blender::nodes::geo_eval_log::GeometryAttributeInfo; namespace blender::ui { diff --git a/source/blender/editors/interface/interface_template_list.cc b/source/blender/editors/interface/interface_template_list.cc index f0c91588f98..d8a9591a021 100644 --- a/source/blender/editors/interface/interface_template_list.cc +++ b/source/blender/editors/interface/interface_template_list.cc @@ -767,7 +767,7 @@ static void ui_template_list_layout_draw(const bContext *C, uiItemL(col, "", ICON_NONE); } - /* add scrollbar */ + /* Add scroll-bar. */ if (items->tot_items > visual_info.visual_items) { uiLayoutColumn(row, false); uiDefButI(block, @@ -916,7 +916,7 @@ static void ui_template_list_layout_draw(const bContext *C, uiItemL(subrow, "", ICON_NONE); } - /* add scrollbar */ + /* Add scroll-bar. */ if (items->tot_items > visual_info.visual_items) { /* col = */ uiLayoutColumn(row, false); uiDefButI(block, @@ -940,7 +940,7 @@ static void ui_template_list_layout_draw(const bContext *C, box = uiLayoutListBox(layout, ui_list, &input_data->active_dataptr, input_data->activeprop); /* For grip button. */ glob = uiLayoutColumn(box, true); - /* For scrollbar. */ + /* For scroll-bar. */ row = uiLayoutRow(glob, false); const bool show_names = (flags & UI_TEMPLATE_LIST_NO_NAMES) == 0; diff --git a/source/blender/editors/interface/interface_template_search_menu.cc b/source/blender/editors/interface/interface_template_search_menu.cc index c3021028b97..c777b7834f2 100644 --- a/source/blender/editors/interface/interface_template_search_menu.cc +++ b/source/blender/editors/interface/interface_template_search_menu.cc @@ -918,6 +918,7 @@ static void menu_search_arg_free_fn(void *data_v) WM_operator_properties_free(item->op.opptr); MEM_freeN(item->op.opptr); } + break; } case MenuSearch_Item::Type::RNA: { break; diff --git a/source/blender/editors/interface/interface_templates.c b/source/blender/editors/interface/interface_templates.c index 5813f1d090c..0b72c358dc9 100644 --- a/source/blender/editors/interface/interface_templates.c +++ b/source/blender/editors/interface/interface_templates.c @@ -571,8 +571,11 @@ static uiBlock *id_search_menu(bContext *C, ARegion *region, void *arg_litem) /** \name ID Template * \{ */ -/* This is for browsing and editing the ID-blocks used */ +static void template_id_cb(bContext *C, void *arg_litem, void *arg_event); +/** + * This is for browsing and editing the ID-blocks used. + */ void UI_context_active_but_prop_get_templateID(bContext *C, PointerRNA *r_ptr, PropertyRNA **r_prop) @@ -582,7 +585,7 @@ void UI_context_active_but_prop_get_templateID(bContext *C, memset(r_ptr, 0, sizeof(*r_ptr)); *r_prop = NULL; - if (but && but->func_argN) { + if (but && (but->funcN == template_id_cb) && but->func_argN) { TemplateID *template_ui = but->func_argN; *r_ptr = template_ui->ptr; *r_prop = template_ui->prop; @@ -650,14 +653,13 @@ static void template_id_liboverride_hierarchy_collections_tag_recursive( } } -static void template_id_liboverride_hierarchy_create(bContext *C, - Main *bmain, - TemplateID *template_ui, - PointerRNA *idptr, - const char **r_undo_push_label) +ID *ui_template_id_liboverride_hierarchy_make( + bContext *C, Main *bmain, ID *owner_id, ID *id, const char **r_undo_push_label) { - ID *id = idptr->data; - ID *owner_id = template_ui->ptr.owner_id; + const char *undo_push_label; + if (r_undo_push_label == NULL) { + r_undo_push_label = &undo_push_label; + } /* If this is called on an already local override, 'toggle' between user-editable state, and * system override with reset. */ @@ -677,14 +679,15 @@ static void template_id_liboverride_hierarchy_create(bContext *C, WM_event_add_notifier(C, NC_WM | ND_DATACHANGED, NULL); WM_event_add_notifier(C, NC_WM | ND_LIB_OVERRIDE_CHANGED, NULL); WM_event_add_notifier(C, NC_SPACE | ND_SPACE_VIEW3D, NULL); - return; + return id; } /* Attempt to perform a hierarchy override, based on contextual data available. * NOTE: do not attempt to perform such hierarchy override at all cost, if there is not enough * context, better to abort than create random overrides all over the place. */ if (!ID_IS_OVERRIDABLE_LIBRARY_HIERARCHY(id)) { - return; + RNA_warning("The data-block %s is not overridable", id->name); + return NULL; } Object *object_active = CTX_data_active_object(C); @@ -762,15 +765,8 @@ static void template_id_liboverride_hierarchy_create(bContext *C, if (object_active != NULL) { object_active->id.tag |= LIB_TAG_DOIT; } - BKE_lib_override_library_create(bmain, - scene, - view_layer, - NULL, - id, - &collection_active->id, - NULL, - &id_override, - U.experimental.use_override_new_fully_editable); + BKE_lib_override_library_create( + bmain, scene, view_layer, NULL, id, &collection_active->id, NULL, &id_override, false); } else if (object_active != NULL && !ID_IS_LINKED(object_active) && &object_active->instance_collection->id == id) { @@ -783,7 +779,7 @@ static void template_id_liboverride_hierarchy_create(bContext *C, &object_active->id, &object_active->id, &id_override, - U.experimental.use_override_new_fully_editable); + false); } break; case ID_OB: @@ -793,15 +789,17 @@ static void template_id_liboverride_hierarchy_create(bContext *C, if (object_active != NULL) { object_active->id.tag |= LIB_TAG_DOIT; } - BKE_lib_override_library_create(bmain, - scene, - view_layer, - NULL, - id, - &collection_active->id, - NULL, - &id_override, - U.experimental.use_override_new_fully_editable); + BKE_lib_override_library_create( + bmain, scene, view_layer, NULL, id, &collection_active->id, NULL, &id_override, false); + } + else { + if (object_active != NULL) { + object_active->id.tag |= LIB_TAG_DOIT; + } + BKE_lib_override_library_create( + bmain, scene, view_layer, NULL, id, NULL, NULL, &id_override, false); + BKE_scene_collections_object_remove(bmain, scene, (Object *)id, true); + WM_event_add_notifier(C, NC_ID | NA_REMOVED, NULL); } break; case ID_ME: @@ -816,7 +814,8 @@ static void template_id_liboverride_hierarchy_create(bContext *C, case ID_CV: case ID_PT: case ID_VO: - if (object_active != NULL && object_active->data == id) { + case ID_NT: /* Essentially geometry nodes from modifier currently. */ + if (object_active != NULL) { if (collection_active != NULL && BKE_collection_has_object_recursive(collection_active, object_active)) { template_id_liboverride_hierarchy_collections_tag_recursive(collection_active, id, true); @@ -831,42 +830,74 @@ static void template_id_liboverride_hierarchy_create(bContext *C, &collection_active->id, NULL, &id_override, - U.experimental.use_override_new_fully_editable); + false); } else { object_active->id.tag |= LIB_TAG_DOIT; - BKE_lib_override_library_create(bmain, - scene, - view_layer, - NULL, - id, - &object_active->id, - NULL, - &id_override, - U.experimental.use_override_new_fully_editable); + BKE_lib_override_library_create( + bmain, scene, view_layer, NULL, id, &object_active->id, NULL, &id_override, false); } } break; case ID_MA: case ID_TE: case ID_IM: + RNA_warning("The type of data-block %s could not yet implemented", id->name); break; case ID_WO: + RNA_warning("The type of data-block %s could not yet implemented", id->name); break; case ID_PA: + RNA_warning("The type of data-block %s could not yet implemented", id->name); break; default: + RNA_warning("The type of data-block %s could not yet implemented", id->name); break; } if (id_override != NULL) { id_override->override_library->flag &= ~IDOVERRIDE_LIBRARY_FLAG_SYSTEM_DEFINED; *r_undo_push_label = "Make Library Override Hierarchy"; - /* Given `idptr` is re-assigned to owner property by caller to ensure proper updates etc. Here - * we also use it to ensure remapping of the owner property from the linked data to the newly - * created liboverride (note that in theory this remapping has already been done by code - * above). */ - RNA_id_pointer_create(id_override, idptr); + /* In theory we could rely on setting/updating the RNA ID pointer property (as done by calling + * code) to be enough. + * + * However, some rare ID pointers properties (like the 'active object in viewlayer' one used + * for the Object templateID in the Object properties) use notifiers that do not enforce a + * rebuild of outliner trees, leading to crashes. + * + * So for now, add some extra notifiers here. */ + WM_event_add_notifier(C, NC_ID | NA_ADDED, NULL); + WM_event_add_notifier(C, NC_SPACE | ND_SPACE_OUTLINER, NULL); + } + return id_override; +} + +static void template_id_liboverride_hierarchy_make(bContext *C, + Main *bmain, + TemplateID *template_ui, + PointerRNA *idptr, + const char **r_undo_push_label) +{ + ID *id = idptr->data; + ID *owner_id = template_ui->ptr.owner_id; + + ID *id_override = ui_template_id_liboverride_hierarchy_make( + C, bmain, owner_id, id, r_undo_push_label); + + if (id_override != NULL) { + /* `idptr` is re-assigned to owner property to ensure proper updates etc. Here we also use it + * to ensure remapping of the owner property from the linked data to the newly created + * liboverride (note that in theory this remapping has already been done by code above), but + * only in case owner ID was already local ID (override or pure local data). + * + * Otherwise, owner ID will also have been overridden, and remapped already to use it's + * override of the data too. */ + if (!ID_IS_LINKED(owner_id)) { + RNA_id_pointer_create(id_override, idptr); + } + } + else { + RNA_warning("The data-block %s could not be overridden", id->name); } } @@ -919,8 +950,7 @@ static void template_id_cb(bContext *C, void *arg_litem, void *arg_event) if (id) { Main *bmain = CTX_data_main(C); if (CTX_wm_window(C)->eventstate->modifier & KM_SHIFT) { - template_id_liboverride_hierarchy_create( - C, bmain, template_ui, &idptr, &undo_push_label); + template_id_liboverride_hierarchy_make(C, bmain, template_ui, &idptr, &undo_push_label); } else { if (BKE_lib_id_make_local(bmain, id, 0)) { @@ -941,8 +971,7 @@ static void template_id_cb(bContext *C, void *arg_litem, void *arg_event) if (id && ID_IS_OVERRIDE_LIBRARY(id)) { Main *bmain = CTX_data_main(C); if (CTX_wm_window(C)->eventstate->modifier & KM_SHIFT) { - template_id_liboverride_hierarchy_create( - C, bmain, template_ui, &idptr, &undo_push_label); + template_id_liboverride_hierarchy_make(C, bmain, template_ui, &idptr, &undo_push_label); } else { BKE_lib_override_library_make_local(id); @@ -1336,20 +1365,22 @@ static void template_ID(const bContext *C, } } else if (ID_IS_OVERRIDE_LIBRARY(id)) { - but = uiDefIconBut(block, - UI_BTYPE_BUT, - 0, - ICON_LIBRARY_DATA_OVERRIDE, - 0, - 0, - UI_UNIT_X, - UI_UNIT_Y, - NULL, - 0, - 0, - 0, - 0, - TIP_("Library override of linked data-block, click to make fully local")); + but = uiDefIconBut( + block, + UI_BTYPE_BUT, + 0, + ICON_LIBRARY_DATA_OVERRIDE, + 0, + 0, + UI_UNIT_X, + UI_UNIT_Y, + NULL, + 0, + 0, + 0, + 0, + TIP_("Library override of linked data-block, click to make fully local, " + "Shift + Click to clear the library override and toggle if it can be edited")); UI_but_funcN_set( but, template_id_cb, MEM_dupallocN(template_ui), POINTER_FROM_INT(UI_ID_OVERRIDE)); } @@ -5175,7 +5206,7 @@ static void CurveProfile_buttons_layout(uiLayout *layout, PointerRNA *ptr, RNAUp 0.0, 0.0, 0.0, - "Reapply and update the preset, removing changes"); + TIP_("Reapply and update the preset, removing changes")); UI_but_funcN_set(bt, CurveProfile_buttons_reset, MEM_dupallocN(cb), profile); } } @@ -6300,7 +6331,7 @@ void uiTemplateReportsBanner(uiLayout *layout, bContext *C) 0, width + UI_UNIT_X, UI_UNIT_Y, - "Show in Info Log"); + TIP_("Show in Info Log")); UI_block_emboss_set(block, previous_emboss); } @@ -6327,8 +6358,10 @@ void uiTemplateInputStatus(uiLayout *layout, struct bContext *C) uiLayout *row = uiLayoutRow(col, true); uiLayoutSetAlignment(row, UI_LAYOUT_ALIGN_LEFT); - const char *msg = TIP_(WM_window_cursor_keymap_status_get(win, i, 0)); - const char *msg_drag = TIP_(WM_window_cursor_keymap_status_get(win, i, 1)); + const char *msg = CTX_TIP_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, + WM_window_cursor_keymap_status_get(win, i, 0)); + const char *msg_drag = CTX_TIP_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, + WM_window_cursor_keymap_status_get(win, i, 1)); if (msg || (msg_drag == NULL)) { uiItemL(row, msg ? msg : "", (ICON_MOUSE_LMB + i)); @@ -6458,13 +6491,13 @@ bool uiTemplateEventFromKeymapItem(struct uiLayout *layout, for (int j = 0; j < ARRAY_SIZE(icon_mod) && icon_mod[j]; j++) { uiItemL(layout, "", icon_mod[j]); } - uiItemL(layout, TIP_(text), icon); + uiItemL(layout, CTX_TIP_(BLT_I18NCONTEXT_ID_WINDOWMANAGER, text), icon); ok = true; } else if (text_fallback) { const char *event_text = WM_key_event_string(kmi->type, true); uiItemL(layout, event_text, ICON_NONE); - uiItemL(layout, TIP_(text), ICON_NONE); + uiItemL(layout, CTX_TIP_(BLT_I18NCONTEXT_ID_WINDOWMANAGER, text), ICON_NONE); ok = true; } return ok; diff --git a/source/blender/editors/interface/interface_utils.cc b/source/blender/editors/interface/interface_utils.cc index b7ca2d9aa11..4b94834ce97 100644 --- a/source/blender/editors/interface/interface_utils.cc +++ b/source/blender/editors/interface/interface_utils.cc @@ -787,7 +787,7 @@ int UI_calc_float_precision(int prec, double value) */ value = fabs(value); if ((value < pow10_neg[prec]) && (value > (1.0 / max_pow))) { - int value_i = (int)((value * max_pow) + 0.5); + int value_i = (int)lround(value * max_pow); if (value_i != 0) { const int prec_span = 3; /* show: 0.01001, 5 would allow 0.0100001 for eg. */ int test_prec; diff --git a/source/blender/editors/interface/interface_widgets.c b/source/blender/editors/interface/interface_widgets.c index 855e72788d2..842201894a3 100644 --- a/source/blender/editors/interface/interface_widgets.c +++ b/source/blender/editors/interface/interface_widgets.c @@ -197,16 +197,16 @@ static void color_mul_hsl_v3(uchar ch[3], float h_factor, float s_factor, float * \{ */ /** - * - in: roundbox codes for corner types and radius - * - return: array of `[size][2][x, y]` points, the edges of the roundbox, + UV coords + * - in: `roundbox` codes for corner types and radius + * - return: array of `[size][2][x, y]` points, the edges of the `roundbox`, + UV coords * - * - draw black box with alpha 0 on exact button boundbox - * - for every AA step: + * - Draw black box with alpha 0 on exact button bounding-box. + * - For every AA step: * - draw the inner part for a round filled box, with color blend codes or texture coords * - draw outline in outline color * - draw outer part, bottom half, extruded 1 pixel to bottom, for emboss shadow * - draw extra decorations - * - draw background color box with alpha 1 on exact button boundbox + * - Draw background color box with alpha 1 on exact button bounding-box. */ /* fill this struct with polygon info to draw AA'ed */ @@ -533,7 +533,7 @@ static void draw_anti_tria( const uint pos = GPU_vertformat_attr_add( immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); - immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); immUniformColor4fv(draw_color); immBegin(GPU_PRIM_TRIS, 3 * WIDGET_AA_JITTER); @@ -693,7 +693,7 @@ static void round_box__edges( { float vec[WIDGET_CURVE_RESOLU][2], veci[WIDGET_CURVE_RESOLU][2]; const float minx = rect->xmin, miny = rect->ymin, maxx = rect->xmax, maxy = rect->ymax; - const float minxi = minx + U.pixelsize; /* boundbox inner */ + const float minxi = minx + U.pixelsize; /* Bounding-box inner. */ const float maxxi = maxx - U.pixelsize; const float minyi = miny + U.pixelsize; const float maxyi = maxy - U.pixelsize; @@ -1524,11 +1524,6 @@ float UI_text_clip_middle_ex(const uiFontStyle *fstyle, const size_t max_len, const char rpart_sep) { - /* Add some epsilon to OK width, avoids 'ellipsing' text that nearly fits! - * Better to have a small piece of the last char cut out, - * than two remaining chars replaced by an ellipsis... */ - okwidth += 1.0f + UI_DPI_FAC; - BLI_assert(str[0]); /* need to set this first */ @@ -1627,7 +1622,7 @@ float UI_text_clip_middle_ex(const uiFontStyle *fstyle, strwidth = BLF_width(fstyle->uifont_id, str, max_len); } - BLI_assert(strwidth <= okwidth); + BLI_assert((strwidth <= okwidth) || (okwidth <= 0.0f)); return strwidth; } @@ -1984,7 +1979,7 @@ static void widget_draw_text(const uiFontStyle *fstyle, uint pos = GPU_vertformat_attr_add( immVertexFormat(), "pos", GPU_COMP_I32, 2, GPU_FETCH_INT_TO_FLOAT); - immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); rcti selection_shape; selection_shape.xmin = rect->xmin + selsta_draw; @@ -2036,7 +2031,7 @@ static void widget_draw_text(const uiFontStyle *fstyle, uint pos = GPU_vertformat_attr_add( immVertexFormat(), "pos", GPU_COMP_I32, 2, GPU_FETCH_INT_TO_FLOAT); - immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); immUniformThemeColor(TH_WIDGET_TEXT_CURSOR); @@ -2779,7 +2774,7 @@ static void widget_softshadow(const rcti *rect, int roundboxalign, const float r const uint pos = GPU_vertformat_attr_add( immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); - immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); for (int step = 1; step <= (int)radout; step++) { const float expfac = sqrtf(step / radout); @@ -2835,7 +2830,7 @@ static void ui_hsv_cursor(const float x, const float y, const float zoom) const uint pos = GPU_vertformat_attr_add( immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); - immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); immUniformColor3f(1.0f, 1.0f, 1.0f); imm_draw_circle_fill_2d(pos, x, y, radius, 8); @@ -2935,7 +2930,7 @@ static void ui_draw_but_HSVCIRCLE(uiBut *but, const uiWidgetColors *wcol, const uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); const uint color = GPU_vertformat_attr_add(format, "color", GPU_COMP_F32, 3, GPU_FETCH_FLOAT); - immBindBuiltinProgram(GPU_SHADER_2D_SMOOTH_COLOR); + immBindBuiltinProgram(GPU_SHADER_3D_SMOOTH_COLOR); immBegin(GPU_PRIM_TRI_FAN, tot + 2); immAttr3fv(color, rgb_center); @@ -2969,7 +2964,7 @@ static void ui_draw_but_HSVCIRCLE(uiBut *but, const uiWidgetColors *wcol, const format = immVertexFormat(); pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); - immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); GPU_blend(GPU_BLEND_ALPHA); GPU_line_smooth(true); @@ -3066,7 +3061,7 @@ void ui_draw_gradient(const rcti *rect, GPUVertFormat *format = immVertexFormat(); const uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); const uint col = GPU_vertformat_attr_add(format, "color", GPU_COMP_F32, 4, GPU_FETCH_FLOAT); - immBindBuiltinProgram(GPU_SHADER_2D_SMOOTH_COLOR); + immBindBuiltinProgram(GPU_SHADER_3D_SMOOTH_COLOR); immBegin(GPU_PRIM_TRIS, steps * 3 * 6); @@ -3231,7 +3226,7 @@ static void ui_draw_but_HSVCUBE(uiBut *but, const rcti *rect) /* outline */ const uint pos = GPU_vertformat_attr_add( immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); - immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); immUniformColor3ub(0, 0, 0); imm_draw_box_wire_2d(pos, (rect->xmin), (rect->ymin), (rect->xmax), (rect->ymax)); immUnbindProgram(); @@ -3307,7 +3302,7 @@ static void ui_draw_separator(const rcti *rect, const uiWidgetColors *wcol) const uint pos = GPU_vertformat_attr_add( immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); - immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); GPU_blend(GPU_BLEND_ALPHA); immUniformColor4ubv(col); @@ -3922,7 +3917,7 @@ static void widget_swatch(uiBut *but, const uint pos = GPU_vertformat_attr_add( immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); - immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); immUniformColor3f(bw, bw, bw); immBegin(GPU_PRIM_TRIS, 3); @@ -4388,7 +4383,7 @@ static void widget_draw_extra_mask(const bContext *C, uiBut *but, uiWidgetType * const uint pos = GPU_vertformat_attr_add( immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); - immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); /* make mask to draw over image */ uchar col[4]; @@ -5084,7 +5079,7 @@ static void ui_draw_popover_back_impl(const uiWidgetColors *wcol, if (ELEM(direction, UI_DIR_UP, UI_DIR_DOWN)) { const uint pos = GPU_vertformat_attr_add( immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); - immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); const bool is_down = (direction == UI_DIR_DOWN); const int sign = is_down ? 1 : -1; @@ -5160,10 +5155,10 @@ static void draw_disk_shaded(float start, const uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); if (shaded) { col = GPU_vertformat_attr_add(format, "color", GPU_COMP_U8, 4, GPU_FETCH_INT_TO_FLOAT_UNIT); - immBindBuiltinProgram(GPU_SHADER_2D_SMOOTH_COLOR); + immBindBuiltinProgram(GPU_SHADER_3D_SMOOTH_COLOR); } else { - immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); immUniformColor4ubv(col1); } @@ -5274,7 +5269,7 @@ void ui_draw_pie_center(uiBlock *block) GPUVertFormat *format = immVertexFormat(); const uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); - immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); immUniformColor4ubv(btheme->tui.wcol_pie_menu.outline); imm_draw_circle_wire_2d(pos, 0.0f, 0.0f, pie_radius_internal, subd); diff --git a/source/blender/editors/interface/resources.c b/source/blender/editors/interface/resources.c index cfdcd08df4a..93b94d42d39 100644 --- a/source/blender/editors/interface/resources.c +++ b/source/blender/editors/interface/resources.c @@ -895,6 +895,12 @@ const uchar *UI_ThemeGetColorPtr(bTheme *btheme, int spacetype, int colorid) case TH_WIDGET_TEXT_CURSOR: cp = btheme->tui.widget_text_cursor; break; + case TH_WIDGET_TEXT_SELECTION: + cp = btheme->tui.wcol_text.item; + break; + case TH_WIDGET_TEXT_HIGHLIGHT: + cp = btheme->tui.wcol_text.text_sel; + break; case TH_TRANSPARENT_CHECKER_PRIMARY: cp = btheme->tui.transparent_checker_primary; diff --git a/source/blender/editors/interface/view2d.cc b/source/blender/editors/interface/view2d.cc index 1bf7e25b154..95e5c0ad7d8 100644 --- a/source/blender/editors/interface/view2d.cc +++ b/source/blender/editors/interface/view2d.cc @@ -87,11 +87,11 @@ BLI_INLINE void clamp_rctf_to_rcti(rcti *dst, const rctf *src) * \{ */ /** - * helper to allow scrollbars to dynamically hide - * - returns a copy of the scrollbar settings with the flags to display - * horizontal/vertical scrollbars removed - * - input scroll value is the v2d->scroll var - * - hide flags are set per region at drawtime + * Helper to allow scroll-bars to dynamically hide: + * - Returns a copy of the scroll-bar settings with the flags to display + * horizontal/vertical scroll-bars removed. + * - Input scroll value is the v2d->scroll var. + * - Hide flags are set per region at draw-time. */ static int view2d_scroll_mapped(int scroll) { @@ -115,7 +115,7 @@ void UI_view2d_mask_from_win(const View2D *v2d, rcti *r_mask) /** * Called each time #View2D.cur changes, to dynamically update masks. * - * \param mask_scroll: Optionally clamp scrollbars by this region. + * \param mask_scroll: Optionally clamp scroll-bars by this region. */ static void view2d_masks(View2D *v2d, const rcti *mask_scroll) { @@ -150,7 +150,7 @@ static void view2d_masks(View2D *v2d, const rcti *mask_scroll) } /* Do not use mapped scroll here because we want to update scroller rects - * even if they are not displayed. For init purposes. See T75003.*/ + * even if they are not displayed. For initialization purposes. See T75003. */ scroll = v2d->scroll; /* Scrollers are based off region-size: @@ -177,7 +177,7 @@ static void view2d_masks(View2D *v2d, const rcti *mask_scroll) /* Currently, all regions that have vertical scale handles, * also have the scrubbing area at the top. - * So the scrollbar has to move down a bit. */ + * So the scroll-bar has to move down a bit. */ if (scroll & V2D_SCROLL_VERTICAL_HANDLES) { v2d->vert.ymax -= UI_TIME_SCRUB_MARGIN_Y; } @@ -193,6 +193,18 @@ static void view2d_masks(View2D *v2d, const rcti *mask_scroll) v2d->hor = *mask_scroll; v2d->hor.ymin = v2d->hor.ymax - scroll_height; } + + /* adjust vertical scroller if there's a horizontal scroller, to leave corner free */ + if (scroll & V2D_SCROLL_VERTICAL) { + if (scroll & V2D_SCROLL_BOTTOM) { + /* on bottom edge of region */ + v2d->vert.ymin = v2d->hor.ymax; + } + else if (scroll & V2D_SCROLL_TOP) { + /* on upper edge of region */ + v2d->vert.ymax = v2d->hor.ymin; + } + } } } @@ -250,7 +262,6 @@ void UI_view2d_region_reinit(View2D *v2d, short type, int winx, int winy) /* tot rect has strictly regulated placement, and must only occur in +/- quadrant */ v2d->align = (V2D_ALIGN_NO_NEG_X | V2D_ALIGN_NO_POS_Y); v2d->keeptot = V2D_KEEPTOT_STRICT; - v2d->keepofs = (V2D_KEEPOFS_X | V2D_KEEPOFS_Y); tot_changed = do_init; /* scroller settings are currently not set here... that is left for regions... */ @@ -267,7 +278,6 @@ void UI_view2d_region_reinit(View2D *v2d, short type, int winx, int winy) /* tot rect has strictly regulated placement, and must only occur in +/+ quadrant */ v2d->align = (V2D_ALIGN_NO_NEG_X | V2D_ALIGN_NO_NEG_Y); v2d->keeptot = V2D_KEEPTOT_STRICT; - v2d->keepofs = (V2D_KEEPOFS_X | V2D_KEEPOFS_Y); tot_changed = do_init; /* scroller settings are currently not set here... that is left for regions... */ @@ -377,7 +387,7 @@ static void ui_view2d_curRect_validate_resize(View2D *v2d, bool resize) rctf *cur, *tot; /* use mask as size of region that View2D resides in, as it takes into account - * scrollbars already - keep in sync with zoomx/zoomy in view_zoomstep_apply_ex! */ + * scroll-bars already - keep in sync with zoomx/zoomy in #view_zoomstep_apply_ex! */ winx = (float)(BLI_rcti_size_x(&v2d->mask) + 1); winy = (float)(BLI_rcti_size_y(&v2d->mask) + 1); @@ -485,7 +495,7 @@ static void ui_view2d_curRect_validate_resize(View2D *v2d, bool resize) } /* check if we should restore aspect ratio (if view size changed) */ - if (v2d->keepzoom & V2D_KEEPASPECT && !(v2d->keeptot == V2D_KEEPTOT_STRICT)) { + if (v2d->keepzoom & V2D_KEEPASPECT) { bool do_x = false, do_y = false, do_cur; float curRatio, winRatio; @@ -524,12 +534,53 @@ static void ui_view2d_curRect_validate_resize(View2D *v2d, bool resize) /* do_win = do_y; */ /* UNUSED */ if (do_cur) { - /* portrait window: correct for x */ - width = height / winRatio; + if ((v2d->keeptot == V2D_KEEPTOT_STRICT) && (winx != v2d->oldwinx)) { + /* Special exception for Outliner (and later channel-lists): + * - The view may be moved left to avoid contents + * being pushed out of view when view shrinks. + * - The keeptot code will make sure cur->xmin will not be less than tot->xmin + * (which cannot be allowed). + * - width is not adjusted for changed ratios here. + */ + if (winx < v2d->oldwinx) { + const float temp = v2d->oldwinx - winx; + + cur->xmin -= temp; + cur->xmax -= temp; + + /* width does not get modified, as keepaspect here is just set to make + * sure visible area adjusts to changing view shape! + */ + } + } + else { + /* portrait window: correct for x */ + width = height / winRatio; + } } else { - /* landscape window: correct for y */ - height = width * winRatio; + if ((v2d->keeptot == V2D_KEEPTOT_STRICT) && (winy != v2d->oldwiny)) { + /* special exception for Outliner (and later channel-lists): + * - Currently, no actions need to be taken here... + */ + + if (winy < v2d->oldwiny) { + const float temp = v2d->oldwiny - winy; + + if (v2d->align & V2D_ALIGN_NO_NEG_Y) { + cur->ymin -= temp; + cur->ymax -= temp; + } + else { /* Assume V2D_ALIGN_NO_POS_Y or combination */ + cur->ymin += temp; + cur->ymax += temp; + } + } + } + else { + /* landscape window: correct for y */ + height = width * winRatio; + } } /* store region size for next time */ @@ -1136,7 +1187,7 @@ void UI_view2d_multi_grid_draw( GPU_line_width(1.0f); - immBindBuiltinProgram(GPU_SHADER_2D_FLAT_COLOR); + immBindBuiltinProgram(GPU_SHADER_3D_FLAT_COLOR); immBeginAtMost(GPU_PRIM_LINES, vertex_count); for (int level = 0; level < totlevels; level++) { @@ -1234,7 +1285,7 @@ void UI_view2d_dot_grid_draw(const View2D *v2d, GPUVertFormat *format = immVertexFormat(); const uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); const uint color_id = GPU_vertformat_attr_add(format, "color", GPU_COMP_F32, 4, GPU_FETCH_FLOAT); - immBindBuiltinProgram(GPU_SHADER_2D_FLAT_COLOR); + immBindBuiltinProgram(GPU_SHADER_3D_FLAT_COLOR); /* Scaling the dots fully with the zoom looks too busy, but a bit of size variation is nice. */ const float min_point_size = 2.0f * UI_DPI_FAC; @@ -1326,8 +1377,8 @@ struct View2DScrollers { /* focus bubbles */ /* focus bubbles */ /* focus bubbles */ - int vert_min, vert_max; /* vertical scrollbar */ - int hor_min, hor_max; /* horizontal scrollbar */ + int vert_min, vert_max; /* vertical scroll-bar */ + int hor_min, hor_max; /* horizontal scroll-bar */ /** Exact size of slider backdrop. */ rcti hor, vert; @@ -1380,7 +1431,7 @@ void UI_view2d_scrollers_calc(View2D *v2d, r_scrollers->hor = hor; /* scroller 'buttons': - * - These should always remain within the visible region of the scrollbar + * - These should always remain within the visible region of the scroll-bar * - They represent the region of 'tot' that is visible in 'cur' */ @@ -1473,14 +1524,14 @@ void UI_view2d_scrollers_draw_ex(View2D *v2d, const rcti *mask_custom, bool use_ uchar scrollers_back_color[4]; - /* Color for scrollbar backs */ + /* Color for scroll-bar backs. */ UI_GetThemeColor4ubv(TH_BACK, scrollers_back_color); /* make copies of rects for less typing */ vert = scrollers.vert; hor = scrollers.hor; - /* horizontal scrollbar */ + /* Horizontal scroll-bar. */ if (scroll & V2D_SCROLL_HORIZONTAL) { uiWidgetColors wcol = btheme->tui.wcol_scroll; /* 0..255 -> min...1 */ @@ -1515,7 +1566,7 @@ void UI_view2d_scrollers_draw_ex(View2D *v2d, const rcti *mask_custom, bool use_ UI_draw_widget_scroll(&wcol, &hor, &slider, state); } - /* vertical scrollbar */ + /* Vertical scroll-bar. */ if (scroll & V2D_SCROLL_VERTICAL) { uiWidgetColors wcol = btheme->tui.wcol_scroll; rcti slider; @@ -2100,12 +2151,22 @@ void UI_view2d_text_cache_draw(ARegion *region) col_pack_prev = v2s->col.pack; } - BLF_enable(font_id, BLF_CLIPPING); - BLF_clipping( - font_id, v2s->rect.xmin - 4, v2s->rect.ymin - 4, v2s->rect.xmax + 4, v2s->rect.ymax + 4); - BLF_draw_default( - v2s->rect.xmin + xofs, v2s->rect.ymin + yofs, 0.0f, v2s->str, BLF_DRAW_STR_DUMMY_MAX); - BLF_disable(font_id, BLF_CLIPPING); + /* Don't use clipping if `v2s->rect` is not set. */ + if (BLI_rcti_size_x(&v2s->rect) == 0 && BLI_rcti_size_y(&v2s->rect) == 0) { + BLF_draw_default((float)(v2s->mval[0] + xofs), + (float)(v2s->mval[1] + yofs), + 0.0, + v2s->str, + BLF_DRAW_STR_DUMMY_MAX); + } + else { + BLF_enable(font_id, BLF_CLIPPING); + BLF_clipping( + font_id, v2s->rect.xmin - 4, v2s->rect.ymin - 4, v2s->rect.xmax + 4, v2s->rect.ymax + 4); + BLF_draw_default( + v2s->rect.xmin + xofs, v2s->rect.ymin + yofs, 0.0f, v2s->str, BLF_DRAW_STR_DUMMY_MAX); + BLF_disable(font_id, BLF_CLIPPING); + } } g_v2d_strings = nullptr; diff --git a/source/blender/editors/interface/view2d_draw.cc b/source/blender/editors/interface/view2d_draw.cc index d76230ba99c..ea4cf399a57 100644 --- a/source/blender/editors/interface/view2d_draw.cc +++ b/source/blender/editors/interface/view2d_draw.cc @@ -202,7 +202,7 @@ static void draw_parallel_lines(const ParallelLinesSet *lines, immUniform1f("lineWidth", U.pixelsize - 1.0f); } else { - immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); } immUniformColor3ubv(color); immBegin(GPU_PRIM_LINES, steps * 2); diff --git a/source/blender/editors/interface/view2d_ops.cc b/source/blender/editors/interface/view2d_ops.cc index ec15c4ffc9f..5f7d82e7b9a 100644 --- a/source/blender/editors/interface/view2d_ops.cc +++ b/source/blender/editors/interface/view2d_ops.cc @@ -1821,11 +1821,11 @@ static bool scroller_activate_poll(bContext *C) View2D *v2d = ®ion->v2d; wmEvent *event = win->eventstate; - /* check if mouse in scrollbars, if they're enabled */ + /* Check if mouse in scroll-bars, if they're enabled. */ return (UI_view2d_mouse_in_scrollers(region, v2d, event->xy) != 0); } -/* initialize customdata for scroller manipulation operator */ +/* Initialize #wmOperator.customdata for scroller manipulation operator. */ static void scroller_activate_init(bContext *C, wmOperator *op, const wmEvent *event, @@ -2065,7 +2065,7 @@ static int scroller_activate_invoke(bContext *C, wmOperator *op, const wmEvent * ARegion *region = CTX_wm_region(C); View2D *v2d = ®ion->v2d; - /* check if mouse in scrollbars, if they're enabled */ + /* check if mouse in scroll-bars, if they're enabled */ const char in_scroller = UI_view2d_mouse_in_scrollers(region, v2d, event->xy); /* if in a scroller, init customdata then set modal handler which will diff --git a/source/blender/editors/io/io_alembic.c b/source/blender/editors/io/io_alembic.c index 0068586730f..d4855f470ff 100644 --- a/source/blender/editors/io/io_alembic.c +++ b/source/blender/editors/io/io_alembic.c @@ -39,6 +39,7 @@ # include "RNA_define.h" # include "RNA_enum_types.h" +# include "ED_fileselect.h" # include "ED_object.h" # include "UI_interface.h" @@ -75,20 +76,7 @@ static int wm_alembic_export_invoke(bContext *C, wmOperator *op, const wmEvent * RNA_boolean_set(op->ptr, "init_scene_frame_range", true); - if (!RNA_struct_property_is_set(op->ptr, "filepath")) { - Main *bmain = CTX_data_main(C); - char filepath[FILE_MAX]; - - if (BKE_main_blendfile_path(bmain)[0] == '\0') { - BLI_strncpy(filepath, "untitled", sizeof(filepath)); - } - else { - BLI_strncpy(filepath, BKE_main_blendfile_path(bmain), sizeof(filepath)); - } - - BLI_path_extension_replace(filepath, sizeof(filepath), ".abc"); - RNA_string_set(op->ptr, "filepath", filepath); - } + ED_fileselect_ensure_default_filepath(C, op, ".abc"); WM_event_add_fileselect(C, op); @@ -99,7 +87,7 @@ static int wm_alembic_export_invoke(bContext *C, wmOperator *op, const wmEvent * static int wm_alembic_export_exec(bContext *C, wmOperator *op) { - if (!RNA_struct_property_is_set(op->ptr, "filepath")) { + if (!RNA_struct_property_is_set_ex(op->ptr, "filepath", false)) { BKE_report(op->reports, RPT_ERROR, "No filename given"); return OPERATOR_CANCELLED; } @@ -619,7 +607,7 @@ static int wm_alembic_import_invoke(bContext *C, wmOperator *op, const wmEvent * static int wm_alembic_import_exec(bContext *C, wmOperator *op) { - if (!RNA_struct_property_is_set(op->ptr, "filepath")) { + if (!RNA_struct_property_is_set_ex(op->ptr, "filepath", false)) { BKE_report(op->reports, RPT_ERROR, "No filename given"); return OPERATOR_CANCELLED; } @@ -651,16 +639,16 @@ static int wm_alembic_import_exec(bContext *C, wmOperator *op) ED_object_mode_set(C, OB_MODE_OBJECT); } - bool ok = ABC_import(C, - filename, - scale, - is_sequence, - set_frame_range, - sequence_len, - offset, - validate_meshes, - always_add_cache_reader, - as_background_job); + struct AlembicImportParams params = {0}; + params.global_scale = scale; + params.sequence_len = sequence_len; + params.sequence_offset = offset; + params.is_sequence = is_sequence; + params.set_frame_range = set_frame_range; + params.validate_meshes = validate_meshes; + params.always_add_cache_reader = always_add_cache_reader; + + bool ok = ABC_import(C, filename, ¶ms, as_background_job); return as_background_job || ok ? OPERATOR_FINISHED : OPERATOR_CANCELLED; } diff --git a/source/blender/editors/io/io_collada.c b/source/blender/editors/io/io_collada.c index c491e7a5815..1048d0eca32 100644 --- a/source/blender/editors/io/io_collada.c +++ b/source/blender/editors/io/io_collada.c @@ -19,6 +19,7 @@ # include "DEG_depsgraph.h" +# include "ED_fileselect.h" # include "ED_object.h" # include "RNA_access.h" @@ -36,22 +37,7 @@ static int wm_collada_export_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) { - Main *bmain = CTX_data_main(C); - - if (!RNA_struct_property_is_set(op->ptr, "filepath")) { - char filepath[FILE_MAX]; - const char *blendfile_path = BKE_main_blendfile_path(bmain); - - if (blendfile_path[0] == '\0') { - BLI_strncpy(filepath, "untitled", sizeof(filepath)); - } - else { - BLI_strncpy(filepath, blendfile_path, sizeof(filepath)); - } - - BLI_path_extension_replace(filepath, sizeof(filepath), ".dae"); - RNA_string_set(op->ptr, "filepath", filepath); - } + ED_fileselect_ensure_default_filepath(C, op, ".dae"); WM_event_add_fileselect(C, op); @@ -98,7 +84,7 @@ static int wm_collada_export_exec(bContext *C, wmOperator *op) int export_count; int sample_animations; - if (!RNA_struct_property_is_set(op->ptr, "filepath")) { + if (!RNA_struct_property_is_set_ex(op->ptr, "filepath", false)) { BKE_report(op->reports, RPT_ERROR, "No filename given"); return OPERATOR_CANCELLED; } @@ -707,15 +693,17 @@ static int wm_collada_import_exec(bContext *C, wmOperator *op) int min_chain_length; int keep_bind_info; + int custom_normals; ImportSettings import_settings; - if (!RNA_struct_property_is_set(op->ptr, "filepath")) { + if (!RNA_struct_property_is_set_ex(op->ptr, "filepath", false)) { BKE_report(op->reports, RPT_ERROR, "No filename given"); return OPERATOR_CANCELLED; } /* Options panel */ import_units = RNA_boolean_get(op->ptr, "import_units"); + custom_normals = RNA_boolean_get(op->ptr, "custom_normals"); find_chains = RNA_boolean_get(op->ptr, "find_chains"); auto_connect = RNA_boolean_get(op->ptr, "auto_connect"); fix_orientation = RNA_boolean_get(op->ptr, "fix_orientation"); @@ -728,6 +716,7 @@ static int wm_collada_import_exec(bContext *C, wmOperator *op) import_settings.filepath = filename; import_settings.import_units = import_units != 0; + import_settings.custom_normals = custom_normals != 0; import_settings.auto_connect = auto_connect != 0; import_settings.find_chains = find_chains != 0; import_settings.fix_orientation = fix_orientation != 0; @@ -755,6 +744,7 @@ static void uiCollada_importSettings(uiLayout *layout, PointerRNA *imfptr) uiItemL(box, IFACE_("Import Data Options"), ICON_MESH_DATA); uiItemR(box, imfptr, "import_units", 0, NULL, ICON_NONE); + uiItemR(box, imfptr, "custom_normals", 0, NULL, ICON_NONE); box = uiLayoutBox(layout); uiItemL(box, IFACE_("Armature Options"), ICON_ARMATURE_DATA); @@ -806,6 +796,12 @@ void WM_OT_collada_import(wmOperatorType *ot) "otherwise use the settings from the Imported scene"); RNA_def_boolean(ot->srna, + "custom_normals", + 1, + "Custom Normals", + "Import custom normals, if available (otherwise Blender will compute them)"); + + RNA_def_boolean(ot->srna, "fix_orientation", 0, "Fix Leaf Bones", diff --git a/source/blender/editors/io/io_gpencil_export.c b/source/blender/editors/io/io_gpencil_export.c index 3f905dd7de0..662a372b608 100644 --- a/source/blender/editors/io/io_gpencil_export.c +++ b/source/blender/editors/io/io_gpencil_export.c @@ -20,6 +20,8 @@ # include "BLT_translation.h" +# include "ED_fileselect.h" + # include "RNA_access.h" # include "RNA_define.h" @@ -71,24 +73,6 @@ static void gpencil_export_common_props_definition(wmOperatorType *ot) "Normalize", "Export strokes with constant thickness"); } - -static void set_export_filepath(bContext *C, wmOperator *op, const char *extension) -{ - if (!RNA_struct_property_is_set(op->ptr, "filepath")) { - Main *bmain = CTX_data_main(C); - char filepath[FILE_MAX]; - - if (BKE_main_blendfile_path(bmain)[0] == '\0') { - BLI_strncpy(filepath, "untitled", sizeof(filepath)); - } - else { - BLI_strncpy(filepath, BKE_main_blendfile_path(bmain), sizeof(filepath)); - } - - BLI_path_extension_replace(filepath, sizeof(filepath), extension); - RNA_string_set(op->ptr, "filepath", filepath); - } -} # endif /* <-------- SVG single frame export. --------> */ @@ -109,7 +93,7 @@ static bool wm_gpencil_export_svg_common_check(bContext *UNUSED(C), wmOperator * static int wm_gpencil_export_svg_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) { - set_export_filepath(C, op, ".svg"); + ED_fileselect_ensure_default_filepath(C, op, ".svg"); WM_event_add_fileselect(C, op); @@ -121,7 +105,7 @@ static int wm_gpencil_export_svg_exec(bContext *C, wmOperator *op) Scene *scene = CTX_data_scene(C); Object *ob = CTX_data_active_object(C); - if (!RNA_struct_property_is_set(op->ptr, "filepath")) { + if (!RNA_struct_property_is_set_ex(op->ptr, "filepath", false)) { BKE_report(op->reports, RPT_ERROR, "No filename given"); return OPERATOR_CANCELLED; } @@ -233,7 +217,7 @@ void WM_OT_gpencil_export_svg(wmOperatorType *ot) FILE_SAVE, WM_FILESEL_FILEPATH | WM_FILESEL_SHOW_PROPS, FILE_DEFAULTDISPLAY, - FILE_SORT_ALPHA); + FILE_SORT_DEFAULT); gpencil_export_common_props_definition(ot); @@ -264,7 +248,7 @@ static bool wm_gpencil_export_pdf_common_check(bContext *UNUSED(C), wmOperator * static int wm_gpencil_export_pdf_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) { - set_export_filepath(C, op, ".pdf"); + ED_fileselect_ensure_default_filepath(C, op, ".pdf"); WM_event_add_fileselect(C, op); @@ -276,7 +260,7 @@ static int wm_gpencil_export_pdf_exec(bContext *C, wmOperator *op) Scene *scene = CTX_data_scene(C); Object *ob = CTX_data_active_object(C); - if (!RNA_struct_property_is_set(op->ptr, "filepath")) { + if (!RNA_struct_property_is_set_ex(op->ptr, "filepath", false)) { BKE_report(op->reports, RPT_ERROR, "No filename given"); return OPERATOR_CANCELLED; } @@ -391,7 +375,7 @@ void WM_OT_gpencil_export_pdf(wmOperatorType *ot) FILE_SAVE, WM_FILESEL_FILEPATH | WM_FILESEL_SHOW_PROPS, FILE_DEFAULTDISPLAY, - FILE_SORT_ALPHA); + FILE_SORT_DEFAULT); static const EnumPropertyItem gpencil_export_frame_items[] = { {GP_EXPORT_FRAME_ACTIVE, "ACTIVE", 0, "Active", "Include only active frame"}, diff --git a/source/blender/editors/io/io_gpencil_import.c b/source/blender/editors/io/io_gpencil_import.c index b6fecfaf94e..eb53f66d8b8 100644 --- a/source/blender/editors/io/io_gpencil_import.c +++ b/source/blender/editors/io/io_gpencil_import.c @@ -65,7 +65,7 @@ static int wm_gpencil_import_svg_exec(bContext *C, wmOperator *op) { Scene *scene = CTX_data_scene(C); - if (!RNA_struct_property_is_set(op->ptr, "filepath") || + if (!RNA_struct_property_is_set_ex(op->ptr, "filepath", false) || !(RNA_struct_find_property(op->ptr, "directory"))) { BKE_report(op->reports, RPT_ERROR, "No filename given"); return OPERATOR_CANCELLED; diff --git a/source/blender/editors/io/io_obj.c b/source/blender/editors/io/io_obj.c index c151baf13ef..cb8eafeb52d 100644 --- a/source/blender/editors/io/io_obj.c +++ b/source/blender/editors/io/io_obj.c @@ -18,6 +18,7 @@ # include "BLT_translation.h" +# include "ED_fileselect.h" # include "ED_outliner.h" # include "MEM_guardedalloc.h" @@ -58,20 +59,7 @@ static const EnumPropertyItem io_obj_path_mode[] = { static int wm_obj_export_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) { - if (!RNA_struct_property_is_set(op->ptr, "filepath")) { - Main *bmain = CTX_data_main(C); - char filepath[FILE_MAX]; - - if (BKE_main_blendfile_path(bmain)[0] == '\0') { - BLI_strncpy(filepath, "untitled", sizeof(filepath)); - } - else { - BLI_strncpy(filepath, BKE_main_blendfile_path(bmain), sizeof(filepath)); - } - - BLI_path_extension_replace(filepath, sizeof(filepath), ".obj"); - RNA_string_set(op->ptr, "filepath", filepath); - } + ED_fileselect_ensure_default_filepath(C, op, ".obj"); WM_event_add_fileselect(C, op); return OPERATOR_RUNNING_MODAL; @@ -79,7 +67,7 @@ static int wm_obj_export_invoke(bContext *C, wmOperator *op, const wmEvent *UNUS static int wm_obj_export_exec(bContext *C, wmOperator *op) { - if (!RNA_struct_property_is_set(op->ptr, "filepath")) { + if (!RNA_struct_property_is_set_ex(op->ptr, "filepath", false)) { BKE_report(op->reports, RPT_ERROR, "No filename given"); return OPERATOR_CANCELLED; } @@ -105,6 +93,7 @@ static int wm_obj_export_exec(bContext *C, wmOperator *op) export_params.path_mode = RNA_enum_get(op->ptr, "path_mode"); export_params.export_triangulated_mesh = RNA_boolean_get(op->ptr, "export_triangulated_mesh"); export_params.export_curves_as_nurbs = RNA_boolean_get(op->ptr, "export_curves_as_nurbs"); + export_params.export_pbr_extensions = RNA_boolean_get(op->ptr, "export_pbr_extensions"); export_params.export_object_groups = RNA_boolean_get(op->ptr, "export_object_groups"); export_params.export_material_groups = RNA_boolean_get(op->ptr, "export_material_groups"); @@ -126,51 +115,50 @@ static void ui_obj_export_settings(uiLayout *layout, PointerRNA *imfptr) uiLayoutSetPropSep(layout, true); uiLayoutSetPropDecorate(layout, false); - /* Animation options. */ - uiLayout *box = uiLayoutBox(layout); - uiItemL(box, IFACE_("Animation"), ICON_ANIM); - uiLayout *col = uiLayoutColumn(box, false); - uiLayout *sub = uiLayoutColumn(col, false); - uiItemR(sub, imfptr, "export_animation", 0, NULL, ICON_NONE); - sub = uiLayoutColumn(sub, true); - uiItemR(sub, imfptr, "start_frame", 0, IFACE_("Frame Start"), ICON_NONE); - uiItemR(sub, imfptr, "end_frame", 0, IFACE_("End"), ICON_NONE); - uiLayoutSetEnabled(sub, export_animation); + uiLayout *box, *col, *sub, *row; /* Object Transform options. */ box = uiLayoutBox(layout); - uiItemL(box, IFACE_("Object Properties"), ICON_OBJECT_DATA); col = uiLayoutColumn(box, false); - sub = uiLayoutColumn(col, false); - uiItemR(sub, imfptr, "forward_axis", 0, IFACE_("Axis Forward"), ICON_NONE); - uiItemR(sub, imfptr, "up_axis", 0, IFACE_("Up"), ICON_NONE); - sub = uiLayoutColumn(col, false); + sub = uiLayoutColumnWithHeading(col, false, IFACE_("Limit to")); + uiItemR(sub, imfptr, "export_selected_objects", 0, IFACE_("Selected Only"), ICON_NONE); uiItemR(sub, imfptr, "scaling_factor", 0, NULL, ICON_NONE); + + row = uiLayoutRow(box, false); + uiItemR(row, imfptr, "forward_axis", UI_ITEM_R_EXPAND, IFACE_("Forward Axis"), ICON_NONE); + row = uiLayoutRow(box, false); + uiItemR(row, imfptr, "up_axis", UI_ITEM_R_EXPAND, IFACE_("Up Axis"), ICON_NONE); + + col = uiLayoutColumn(box, false); + sub = uiLayoutColumn(col, false); sub = uiLayoutColumnWithHeading(col, false, IFACE_("Objects")); - uiItemR(sub, imfptr, "export_selected_objects", 0, IFACE_("Selected Only"), ICON_NONE); uiItemR(sub, imfptr, "apply_modifiers", 0, IFACE_("Apply Modifiers"), ICON_NONE); uiItemR(sub, imfptr, "export_eval_mode", 0, IFACE_("Properties"), ICON_NONE); - sub = uiLayoutColumn(sub, false); - uiLayoutSetEnabled(sub, export_materials); - uiItemR(sub, imfptr, "path_mode", 0, IFACE_("Path Mode"), ICON_NONE); - /* Options for what to write. */ + /* Geometry options. */ box = uiLayoutBox(layout); - uiItemL(box, IFACE_("Geometry Export"), ICON_EXPORT); col = uiLayoutColumn(box, false); - sub = uiLayoutColumnWithHeading(col, false, IFACE_("Export")); + sub = uiLayoutColumnWithHeading(col, false, IFACE_("Geometry")); uiItemR(sub, imfptr, "export_uv", 0, IFACE_("UV Coordinates"), ICON_NONE); uiItemR(sub, imfptr, "export_normals", 0, IFACE_("Normals"), ICON_NONE); uiItemR(sub, imfptr, "export_colors", 0, IFACE_("Colors"), ICON_NONE); - uiItemR(sub, imfptr, "export_materials", 0, IFACE_("Materials"), ICON_NONE); uiItemR(sub, imfptr, "export_triangulated_mesh", 0, IFACE_("Triangulated Mesh"), ICON_NONE); uiItemR(sub, imfptr, "export_curves_as_nurbs", 0, IFACE_("Curves as NURBS"), ICON_NONE); + /* Material options. */ + box = uiLayoutBox(layout); + col = uiLayoutColumn(box, false); + sub = uiLayoutColumnWithHeading(col, false, IFACE_("Materials")); + uiItemR(sub, imfptr, "export_materials", 0, IFACE_("Export"), ICON_NONE); + sub = uiLayoutColumn(sub, false); + uiLayoutSetEnabled(sub, export_materials); + uiItemR(sub, imfptr, "export_pbr_extensions", 0, IFACE_("PBR Extensions"), ICON_NONE); + uiItemR(sub, imfptr, "path_mode", 0, IFACE_("Path Mode"), ICON_NONE); + /* Grouping options. */ box = uiLayoutBox(layout); - uiItemL(box, IFACE_("Grouping"), ICON_GROUP); col = uiLayoutColumn(box, false); - sub = uiLayoutColumnWithHeading(col, false, IFACE_("Export")); + sub = uiLayoutColumnWithHeading(col, false, IFACE_("Grouping")); uiItemR(sub, imfptr, "export_object_groups", 0, IFACE_("Object Groups"), ICON_NONE); uiItemR(sub, imfptr, "export_material_groups", 0, IFACE_("Material Groups"), ICON_NONE); uiItemR(sub, imfptr, "export_vertex_groups", 0, IFACE_("Vertex Groups"), ICON_NONE); @@ -178,6 +166,16 @@ static void ui_obj_export_settings(uiLayout *layout, PointerRNA *imfptr) sub = uiLayoutColumn(sub, false); uiLayoutSetEnabled(sub, export_smooth_groups); uiItemR(sub, imfptr, "smooth_group_bitflags", 0, IFACE_("Smooth Group Bitflags"), ICON_NONE); + + /* Animation options. */ + box = uiLayoutBox(layout); + col = uiLayoutColumn(box, false); + sub = uiLayoutColumnWithHeading(col, false, IFACE_("Animation")); + uiItemR(sub, imfptr, "export_animation", 0, IFACE_("Export"), ICON_NONE); + sub = uiLayoutColumn(sub, true); + uiLayoutSetEnabled(sub, export_animation); + uiItemR(sub, imfptr, "start_frame", 0, IFACE_("Frame Start"), ICON_NONE); + uiItemR(sub, imfptr, "end_frame", 0, IFACE_("End"), ICON_NONE); } static void wm_obj_export_draw(bContext *UNUSED(C), wmOperator *op) @@ -223,15 +221,30 @@ static bool wm_obj_export_check(bContext *C, wmOperator *op) RNA_int_set(op->ptr, "start_frame", start); RNA_int_set(op->ptr, "end_frame", end); } + return changed; +} - /* Both forward and up axes cannot be the same (or same except opposite sign). */ - if (RNA_enum_get(op->ptr, "forward_axis") % TOTAL_AXES == - (RNA_enum_get(op->ptr, "up_axis") % TOTAL_AXES)) { - /* TODO(@ankitm): Show a warning here. */ - RNA_enum_set(op->ptr, "up_axis", RNA_enum_get(op->ptr, "up_axis") % TOTAL_AXES + 1); - changed = true; +/* Both forward and up axes cannot be along the same direction. */ +static void forward_axis_update(struct Main *UNUSED(main), + struct Scene *UNUSED(scene), + struct PointerRNA *ptr) +{ + int forward = RNA_enum_get(ptr, "forward_axis"); + int up = RNA_enum_get(ptr, "up_axis"); + if ((forward % 3) == (up % 3)) { + RNA_enum_set(ptr, "up_axis", (up + 1) % 6); + } +} + +static void up_axis_update(struct Main *UNUSED(main), + struct Scene *UNUSED(scene), + struct PointerRNA *ptr) +{ + int forward = RNA_enum_get(ptr, "forward_axis"); + int up = RNA_enum_get(ptr, "up_axis"); + if ((forward % 3) == (up % 3)) { + RNA_enum_set(ptr, "forward_axis", (forward + 1) % 6); } - return changed; } void WM_OT_obj_export(struct wmOperatorType *ot) @@ -256,7 +269,7 @@ void WM_OT_obj_export(struct wmOperatorType *ot) FILE_SAVE, WM_FILESEL_FILEPATH | WM_FILESEL_SHOW_PROPS, FILE_DEFAULTDISPLAY, - FILE_SORT_ALPHA); + FILE_SORT_DEFAULT); /* Animation options. */ RNA_def_boolean(ot->srna, @@ -283,9 +296,11 @@ void WM_OT_obj_export(struct wmOperatorType *ot) INT_MIN, INT_MAX); /* Object transform options. */ - RNA_def_enum( + prop = RNA_def_enum( ot->srna, "forward_axis", io_transform_axis, IO_AXIS_NEGATIVE_Z, "Forward Axis", ""); - RNA_def_enum(ot->srna, "up_axis", io_transform_axis, IO_AXIS_Y, "Up Axis", ""); + RNA_def_property_update_runtime(prop, (void *)forward_axis_update); + prop = RNA_def_enum(ot->srna, "up_axis", io_transform_axis, IO_AXIS_Y, "Up Axis", ""); + RNA_def_property_update_runtime(prop, (void *)up_axis_update); RNA_def_float(ot->srna, "scaling_factor", 1.0f, @@ -324,6 +339,12 @@ void WM_OT_obj_export(struct wmOperatorType *ot) "Export Materials", "Export MTL library. There must be a Principled-BSDF node for image textures to " "be exported to the MTL file"); + RNA_def_boolean(ot->srna, + "export_pbr_extensions", + false, + "Export Materials with PBR Extensions", + "Export MTL library using PBR extensions (roughness, metallic, sheen, " + "clearcoat, anisotropy, transmission)"); RNA_def_enum(ot->srna, "path_mode", io_obj_path_mode, @@ -410,7 +431,7 @@ static int wm_obj_import_exec(bContext *C, wmOperator *op) OBJ_import(C, &import_params); } } - else if (RNA_struct_property_is_set(op->ptr, "filepath")) { + else if (RNA_struct_property_is_set_ex(op->ptr, "filepath", false)) { /* Importing one file. */ RNA_string_get(op->ptr, "filepath", import_params.filepath); OBJ_import(C, &import_params); @@ -440,8 +461,11 @@ static void ui_obj_import_settings(uiLayout *layout, PointerRNA *imfptr) uiLayout *sub = uiLayoutColumn(col, false); uiItemR(sub, imfptr, "clamp_size", 0, NULL, ICON_NONE); sub = uiLayoutColumn(col, false); - uiItemR(sub, imfptr, "forward_axis", 0, IFACE_("Axis Forward"), ICON_NONE); - uiItemR(sub, imfptr, "up_axis", 0, IFACE_("Up"), ICON_NONE); + + uiLayout *row = uiLayoutRow(box, false); + uiItemR(row, imfptr, "forward_axis", UI_ITEM_R_EXPAND, IFACE_("Forward Axis"), ICON_NONE); + row = uiLayoutRow(box, false); + uiItemR(row, imfptr, "up_axis", UI_ITEM_R_EXPAND, IFACE_("Up Axis"), ICON_NONE); box = uiLayoutBox(layout); uiItemL(box, IFACE_("Options"), ICON_EXPORT); @@ -479,7 +503,7 @@ void WM_OT_obj_import(struct wmOperatorType *ot) WM_FILESEL_FILEPATH | WM_FILESEL_SHOW_PROPS | WM_FILESEL_DIRECTORY | WM_FILESEL_FILES, FILE_DEFAULTDISPLAY, - FILE_SORT_ALPHA); + FILE_SORT_DEFAULT); RNA_def_float( ot->srna, "clamp_size", @@ -490,9 +514,11 @@ void WM_OT_obj_import(struct wmOperatorType *ot) "Resize the objects to keep bounding box under this value. Value 0 disables clamping", 0.0f, 1000.0f); - RNA_def_enum( + prop = RNA_def_enum( ot->srna, "forward_axis", io_transform_axis, IO_AXIS_NEGATIVE_Z, "Forward Axis", ""); - RNA_def_enum(ot->srna, "up_axis", io_transform_axis, IO_AXIS_Y, "Up Axis", ""); + RNA_def_property_update_runtime(prop, (void *)forward_axis_update); + prop = RNA_def_enum(ot->srna, "up_axis", io_transform_axis, IO_AXIS_Y, "Up Axis", ""); + RNA_def_property_update_runtime(prop, (void *)up_axis_update); RNA_def_boolean(ot->srna, "import_vertex_groups", false, diff --git a/source/blender/editors/io/io_stl_ops.c b/source/blender/editors/io/io_stl_ops.c index 7db32cd6f18..c98e5beaf3b 100644 --- a/source/blender/editors/io/io_stl_ops.c +++ b/source/blender/editors/io/io_stl_ops.c @@ -53,7 +53,7 @@ static int wm_stl_import_execute(bContext *C, wmOperator *op) STL_import(C, ¶ms); } } - else if (RNA_struct_property_is_set(op->ptr, "filepath")) { + else if (RNA_struct_property_is_set_ex(op->ptr, "filepath", false)) { RNA_string_get(op->ptr, "filepath", params.filepath); STL_import(C, ¶ms); } @@ -104,7 +104,7 @@ void WM_OT_stl_import(struct wmOperatorType *ot) WM_FILESEL_FILEPATH | WM_FILESEL_FILES | WM_FILESEL_DIRECTORY | WM_FILESEL_SHOW_PROPS, FILE_DEFAULTDISPLAY, - FILE_SORT_ALPHA); + FILE_SORT_DEFAULT); RNA_def_float(ot->srna, "global_scale", 1.0f, 1e-6f, 1e6f, "Scale", "", 0.001f, 1000.0f); RNA_def_boolean(ot->srna, diff --git a/source/blender/editors/io/io_usd.c b/source/blender/editors/io/io_usd.c index fd8caf6836e..1496eac0027 100644 --- a/source/blender/editors/io/io_usd.c +++ b/source/blender/editors/io/io_usd.c @@ -21,6 +21,7 @@ # include "BLT_translation.h" +# include "ED_fileselect.h" # include "ED_object.h" # include "MEM_guardedalloc.h" @@ -106,21 +107,7 @@ static int wm_usd_export_invoke(bContext *C, wmOperator *op, const wmEvent *UNUS options->as_background_job = true; op->customdata = options; - if (!RNA_struct_property_is_set(op->ptr, "filepath")) { - Main *bmain = CTX_data_main(C); - char filepath[FILE_MAX]; - const char *main_blendfile_path = BKE_main_blendfile_path(bmain); - - if (main_blendfile_path[0] == '\0') { - BLI_strncpy(filepath, "untitled", sizeof(filepath)); - } - else { - BLI_strncpy(filepath, main_blendfile_path, sizeof(filepath)); - } - - BLI_path_extension_replace(filepath, sizeof(filepath), ".usdc"); - RNA_string_set(op->ptr, "filepath", filepath); - } + ED_fileselect_ensure_default_filepath(C, op, ".usdc"); WM_event_add_fileselect(C, op); @@ -129,7 +116,7 @@ static int wm_usd_export_invoke(bContext *C, wmOperator *op, const wmEvent *UNUS static int wm_usd_export_exec(bContext *C, wmOperator *op) { - if (!RNA_struct_property_is_set(op->ptr, "filepath")) { + if (!RNA_struct_property_is_set_ex(op->ptr, "filepath", false)) { BKE_report(op->reports, RPT_ERROR, "No filename given"); return OPERATOR_CANCELLED; } @@ -226,6 +213,19 @@ static void wm_usd_export_draw(bContext *UNUSED(C), wmOperator *op) uiItemR(box, ptr, "use_instancing", 0, NULL, ICON_NONE); } +static void free_operator_customdata(wmOperator *op) +{ + if (op->customdata) { + MEM_freeN(op->customdata); + op->customdata = NULL; + } +} + +static void wm_usd_export_cancel(bContext *UNUSED(C), wmOperator *op) +{ + free_operator_customdata(op); +} + static bool wm_usd_export_check(bContext *UNUSED(C), wmOperator *op) { char filepath[FILE_MAX]; @@ -250,6 +250,7 @@ void WM_OT_usd_export(struct wmOperatorType *ot) ot->exec = wm_usd_export_exec; ot->poll = WM_operator_winactive; ot->ui = wm_usd_export_draw; + ot->cancel = wm_usd_export_cancel; ot->check = wm_usd_export_check; ot->flag = OPTYPE_REGISTER | OPTYPE_PRESET; /* No UNDO possible. */ @@ -353,7 +354,7 @@ static int wm_usd_import_invoke(bContext *C, wmOperator *op, const wmEvent *even static int wm_usd_import_exec(bContext *C, wmOperator *op) { - if (!RNA_struct_property_is_set(op->ptr, "filepath")) { + if (!RNA_struct_property_is_set_ex(op->ptr, "filepath", false)) { BKE_report(op->reports, RPT_ERROR, "No filename given"); return OPERATOR_CANCELLED; } @@ -395,7 +396,7 @@ static int wm_usd_import_exec(bContext *C, wmOperator *op) const bool create_collection = RNA_boolean_get(op->ptr, "create_collection"); - char *prim_path_mask = malloc(1024); + char prim_path_mask[1024]; RNA_string_get(op->ptr, "prim_path_mask", prim_path_mask); const bool import_guide = RNA_boolean_get(op->ptr, "import_guide"); @@ -439,7 +440,6 @@ static int wm_usd_import_exec(bContext *C, wmOperator *op) .import_materials = import_materials, .import_meshes = import_meshes, .import_volumes = import_volumes, - .prim_path_mask = prim_path_mask, .import_subdiv = import_subdiv, .import_instance_proxies = import_instance_proxies, .create_collection = create_collection, @@ -454,11 +454,18 @@ static int wm_usd_import_exec(bContext *C, wmOperator *op) .mtl_name_collision_mode = mtl_name_collision_mode, .mtl_purpose = mtl_purpose}; + STRNCPY(params.prim_path_mask, prim_path_mask); + const bool ok = USD_import(C, filename, ¶ms, as_background_job); return as_background_job || ok ? OPERATOR_FINISHED : OPERATOR_CANCELLED; } +static void wm_usd_import_cancel(bContext *UNUSED(C), wmOperator *op) +{ + free_operator_customdata(op); +} + static void wm_usd_import_draw(bContext *UNUSED(C), wmOperator *op) { uiLayout *layout = op->layout; @@ -516,6 +523,7 @@ void WM_OT_usd_import(struct wmOperatorType *ot) ot->invoke = wm_usd_import_invoke; ot->exec = wm_usd_import_exec; + ot->cancel = wm_usd_import_cancel; ot->poll = WM_operator_winactive; ot->ui = wm_usd_import_draw; @@ -527,7 +535,7 @@ void WM_OT_usd_import(struct wmOperatorType *ot) FILE_OPENFILE, WM_FILESEL_FILEPATH | WM_FILESEL_RELPATH | WM_FILESEL_SHOW_PROPS, FILE_DEFAULTDISPLAY, - FILE_SORT_ALPHA); + FILE_SORT_DEFAULT); RNA_def_float( ot->srna, diff --git a/source/blender/editors/lattice/editlattice_select.c b/source/blender/editors/lattice/editlattice_select.c index 54a72c7ea5d..22a9d41fcf7 100644 --- a/source/blender/editors/lattice/editlattice_select.c +++ b/source/blender/editors/lattice/editlattice_select.c @@ -78,7 +78,7 @@ bool ED_lattice_deselect_all_multi(struct bContext *C) ED_view3d_viewcontext_init(C, &vc, depsgraph); uint bases_len = 0; Base **bases = BKE_view_layer_array_from_bases_in_edit_mode_unique_data( - vc.view_layer, vc.v3d, &bases_len); + vc.scene, vc.view_layer, vc.v3d, &bases_len); bool changed_multi = ED_lattice_deselect_all_multi_ex(bases, bases_len); MEM_freeN(bases); return changed_multi; @@ -96,10 +96,11 @@ static int lattice_select_random_exec(bContext *C, wmOperator *op) const float randfac = RNA_float_get(op->ptr, "ratio"); const int seed = WM_operator_properties_select_random_seed_increment_get(op); + const Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); uint objects_len = 0; Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data( - view_layer, CTX_wm_view3d(C), &objects_len); + scene, view_layer, CTX_wm_view3d(C), &objects_len); for (uint ob_index = 0; ob_index < objects_len; ob_index++) { Object *obedit = objects[ob_index]; Lattice *lt = ((Lattice *)obedit->data)->editlatt->latt; @@ -205,10 +206,11 @@ static int lattice_select_mirror_exec(bContext *C, wmOperator *op) const int axis_flag = RNA_enum_get(op->ptr, "axis"); const bool extend = RNA_boolean_get(op->ptr, "extend"); + const Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); uint objects_len = 0; Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data( - view_layer, CTX_wm_view3d(C), &objects_len); + scene, view_layer, CTX_wm_view3d(C), &objects_len); for (uint ob_index = 0; ob_index < objects_len; ob_index++) { Object *obedit = objects[ob_index]; @@ -271,12 +273,13 @@ static bool lattice_test_bitmap_uvw( static int lattice_select_more_less(bContext *C, const bool select) { + const Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); uint objects_len; bool changed = false; Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data( - view_layer, CTX_wm_view3d(C), &objects_len); + scene, view_layer, CTX_wm_view3d(C), &objects_len); for (uint ob_index = 0; ob_index < objects_len; ob_index++) { Object *obedit = objects[ob_index]; Lattice *lt = ((Lattice *)obedit->data)->editlatt->latt; @@ -396,12 +399,13 @@ bool ED_lattice_flags_set(Object *obedit, int flag) static int lattice_select_all_exec(bContext *C, wmOperator *op) { + const Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); int action = RNA_enum_get(op->ptr, "action"); uint objects_len = 0; Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data( - view_layer, CTX_wm_view3d(C), &objects_len); + scene, view_layer, CTX_wm_view3d(C), &objects_len); if (action == SEL_TOGGLE) { action = SEL_SELECT; @@ -484,13 +488,14 @@ void LATTICE_OT_select_all(wmOperatorType *ot) static int lattice_select_ungrouped_exec(bContext *C, wmOperator *op) { + const Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); uint objects_len; const bool is_extend = RNA_boolean_get(op->ptr, "extend"); bool changed = false; Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data( - view_layer, CTX_wm_view3d(C), &objects_len); + scene, view_layer, CTX_wm_view3d(C), &objects_len); for (uint ob_index = 0; ob_index < objects_len; ob_index++) { Object *obedit = objects[ob_index]; Lattice *lt = ((Lattice *)obedit->data)->editlatt->latt; @@ -592,7 +597,7 @@ static BPoint *findnearestLattvert(ViewContext *vc, bool select, Base **r_base) uint bases_len; Base **bases = BKE_view_layer_array_from_bases_in_edit_mode_unique_data( - vc->view_layer, vc->v3d, &bases_len); + vc->scene, vc->view_layer, vc->v3d, &bases_len); for (uint base_index = 0; base_index < bases_len; base_index++) { Base *base = bases[base_index]; data.is_changed = false; @@ -633,7 +638,7 @@ bool ED_lattice_select_pick(bContext *C, const int mval[2], const struct SelectP /* Deselect everything. */ uint objects_len = 0; Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data( - vc.view_layer, vc.v3d, &objects_len); + vc.scene, vc.view_layer, vc.v3d, &objects_len); for (uint ob_index = 0; ob_index < objects_len; ob_index++) { Object *ob = objects[ob_index]; if (ED_lattice_flags_set(ob, 0)) { @@ -680,7 +685,8 @@ bool ED_lattice_select_pick(bContext *C, const int mval[2], const struct SelectP lt->actbp = LT_ACTBP_NONE; } - if (vc.view_layer->basact != basact) { + BKE_view_layer_synced_ensure(vc.scene, vc.view_layer); + if (BKE_view_layer_active_base_get(vc.view_layer) != basact) { ED_object_base_activate(C, basact); } diff --git a/source/blender/editors/lattice/editlattice_tools.c b/source/blender/editors/lattice/editlattice_tools.c index bb68b244d35..cee39ff7d70 100644 --- a/source/blender/editors/lattice/editlattice_tools.c +++ b/source/blender/editors/lattice/editlattice_tools.c @@ -49,6 +49,7 @@ static bool make_regular_poll(bContext *C) static int make_regular_exec(bContext *C, wmOperator *UNUSED(op)) { + const Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); View3D *v3d = CTX_wm_view3d(C); const bool is_editmode = CTX_data_edit_object(C) != NULL; @@ -56,7 +57,7 @@ static int make_regular_exec(bContext *C, wmOperator *UNUSED(op)) if (is_editmode) { uint objects_len; Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data( - view_layer, CTX_wm_view3d(C), &objects_len); + scene, view_layer, CTX_wm_view3d(C), &objects_len); for (uint ob_index = 0; ob_index < objects_len; ob_index++) { Object *ob = objects[ob_index]; Lattice *lt = ob->data; @@ -195,13 +196,14 @@ static void lattice_swap_point_pairs( static int lattice_flip_exec(bContext *C, wmOperator *op) { + const Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); uint objects_len; bool changed = false; const eLattice_FlipAxes axis = RNA_enum_get(op->ptr, "axis"); Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data( - view_layer, CTX_wm_view3d(C), &objects_len); + scene, view_layer, CTX_wm_view3d(C), &objects_len); for (uint ob_index = 0; ob_index < objects_len; ob_index++) { Object *obedit = objects[ob_index]; Lattice *lt; diff --git a/source/blender/editors/lattice/editlattice_undo.c b/source/blender/editors/lattice/editlattice_undo.c index 8265225e08a..b77786b2421 100644 --- a/source/blender/editors/lattice/editlattice_undo.c +++ b/source/blender/editors/lattice/editlattice_undo.c @@ -131,8 +131,10 @@ static int validate_undoLatt(void *data, void *edata) static Object *editlatt_object_from_context(bContext *C) { + Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); - Object *obedit = OBEDIT_FROM_VIEW_LAYER(view_layer); + BKE_view_layer_synced_ensure(scene, view_layer); + Object *obedit = BKE_view_layer_edit_object_get(view_layer); if (obedit && obedit->type == OB_LATTICE) { Lattice *lt = obedit->data; if (lt->editlatt != NULL) { @@ -173,9 +175,10 @@ static bool lattice_undosys_step_encode(struct bContext *C, Main *bmain, UndoSte /* Important not to use the 3D view when getting objects because all objects * outside of this list will be moved out of edit-mode when reading back undo steps. */ + const Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); uint objects_len = 0; - Object **objects = ED_undo_editmode_objects_from_view_layer(view_layer, &objects_len); + Object **objects = ED_undo_editmode_objects_from_view_layer(scene, view_layer, &objects_len); us->elems = MEM_callocN(sizeof(*us->elems) * objects_len, __func__); us->elems_len = objects_len; diff --git a/source/blender/editors/mask/CMakeLists.txt b/source/blender/editors/mask/CMakeLists.txt index fdb0d13f364..593eeb6c69d 100644 --- a/source/blender/editors/mask/CMakeLists.txt +++ b/source/blender/editors/mask/CMakeLists.txt @@ -10,7 +10,6 @@ set(INC ../../makesdna ../../makesrna ../../windowmanager - ../../../../intern/glew-mx ../../../../intern/guardedalloc ) diff --git a/source/blender/editors/mask/mask_draw.c b/source/blender/editors/mask/mask_draw.c index 4c01154ba49..3b16497f09f 100644 --- a/source/blender/editors/mask/mask_draw.c +++ b/source/blender/editors/mask/mask_draw.c @@ -110,7 +110,7 @@ static void draw_single_handle(const MaskLayer *mask_layer, uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); const uchar rgb_gray[4] = {0x60, 0x60, 0x60, 0xff}; - immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); immUniformColor3ubv(rgb_gray); /* this could be split into its own loop */ @@ -408,7 +408,7 @@ static void mask_draw_curve_type(const bContext *C, /* TODO(merwin): use fancy line shader here * probably better with geometry shader (after core profile switch) */ - immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); GPU_line_width(3.0f); @@ -427,7 +427,7 @@ static void mask_draw_curve_type(const bContext *C, case MASK_DT_BLACK: case MASK_DT_WHITE: - immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); GPU_line_width(1.0f); if (draw_type == MASK_DT_BLACK) { @@ -465,7 +465,7 @@ static void mask_draw_curve_type(const bContext *C, mask_color_active_tint(rgb_tmp, rgb_black, is_active); rgba_uchar_to_float(colors[1], rgb_tmp); - immBindBuiltinProgram(GPU_SHADER_2D_LINE_DASHED_UNIFORM_COLOR); + immBindBuiltinProgram(GPU_SHADER_3D_LINE_DASHED_UNIFORM_COLOR); float viewport_size[4]; GPU_viewport_size_get_f(viewport_size); @@ -792,7 +792,7 @@ void ED_mask_draw_frames( uint pos = GPU_vertformat_attr_add( immVertexFormat(), "pos", GPU_COMP_I32, 2, GPU_FETCH_INT_TO_FLOAT); - immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); immUniformColor4ub(255, 175, 0, 255); immBegin(GPU_PRIM_LINES, 2 * num_lines); diff --git a/source/blender/editors/mask/mask_shapekey.c b/source/blender/editors/mask/mask_shapekey.c index 48944c081a8..77595aa0694 100644 --- a/source/blender/editors/mask/mask_shapekey.c +++ b/source/blender/editors/mask/mask_shapekey.c @@ -136,9 +136,9 @@ static int mask_shape_key_feather_reset_exec(bContext *C, wmOperator *UNUSED(op) MaskLayerShape *mask_layer_shape_reset; MaskLayerShape *mask_layer_shape; - /* get the shapekey of the current state */ + /* Get the shape-key of the current state. */ mask_layer_shape_reset = BKE_mask_layer_shape_alloc(mask_layer, frame); - /* initialize from mask - as if inseting a keyframe */ + /* Initialize from mask - as if inserting a keyframe. */ BKE_mask_layer_shape_from_mask(mask_layer, mask_layer_shape_reset); for (mask_layer_shape = mask_layer->splines_shapes.first; mask_layer_shape; diff --git a/source/blender/editors/mesh/CMakeLists.txt b/source/blender/editors/mesh/CMakeLists.txt index 28ac913a3e3..218564eaf30 100644 --- a/source/blender/editors/mesh/CMakeLists.txt +++ b/source/blender/editors/mesh/CMakeLists.txt @@ -17,7 +17,6 @@ set(INC ../../render ../../windowmanager ../../../../intern/clog - ../../../../intern/glew-mx ../../../../intern/guardedalloc # RNA_prototypes.h ${CMAKE_BINARY_DIR}/source/blender/makesrna diff --git a/source/blender/editors/mesh/editface.cc b/source/blender/editors/mesh/editface.cc index c55d96bac55..ac8dd87bed6 100644 --- a/source/blender/editors/mesh/editface.cc +++ b/source/blender/editors/mesh/editface.cc @@ -44,9 +44,7 @@ void paintface_flush_flags(bContext *C, { using namespace blender; Mesh *me = BKE_mesh_from_object(ob); - MPoly *polys, *mp_orig; const int *index_array = nullptr; - int totpoly; BLI_assert(flush_selection || flush_hidden); @@ -69,18 +67,15 @@ void paintface_flush_flags(bContext *C, return; } - bke::AttributeAccessor attributes_me = bke::mesh_attributes(*me); + bke::AttributeAccessor attributes_me = me->attributes(); Mesh *me_orig = (Mesh *)ob_eval->runtime.data_orig; - bke::MutableAttributeAccessor attributes_orig = bke::mesh_attributes_for_write(*me_orig); + bke::MutableAttributeAccessor attributes_orig = me_orig->attributes_for_write(); Mesh *me_eval = (Mesh *)ob_eval->runtime.data_eval; - bke::MutableAttributeAccessor attributes_eval = bke::mesh_attributes_for_write(*me_eval); + bke::MutableAttributeAccessor attributes_eval = me_eval->attributes_for_write(); bool updated = false; if (me_orig != nullptr && me_eval != nullptr && me_orig->totpoly == me->totpoly) { /* Update the COW copy of the mesh. */ - for (int i = 0; i < me->totpoly; i++) { - me_orig->mpoly[i].flag = me->mpoly[i].flag; - } if (flush_hidden) { const VArray<bool> hide_poly_me = attributes_me.lookup_or_default<bool>( ".hide_poly", ATTR_DOMAIN_FACE, false); @@ -89,31 +84,46 @@ void paintface_flush_flags(bContext *C, hide_poly_me.materialize(hide_poly_orig.span); hide_poly_orig.finish(); } + if (flush_selection) { + const VArray<bool> select_poly_me = attributes_me.lookup_or_default<bool>( + ".select_poly", ATTR_DOMAIN_FACE, false); + bke::SpanAttributeWriter<bool> select_poly_orig = + attributes_orig.lookup_or_add_for_write_only_span<bool>(".select_poly", + ATTR_DOMAIN_FACE); + select_poly_me.materialize(select_poly_orig.span); + select_poly_orig.finish(); + } /* Mesh polys => Final derived polys */ if ((index_array = (const int *)CustomData_get_layer(&me_eval->pdata, CD_ORIGINDEX))) { - polys = me_eval->mpoly; - totpoly = me_eval->totpoly; - - /* loop over final derived polys */ - for (int i = 0; i < totpoly; i++) { - if (index_array[i] != ORIGINDEX_NONE) { - /* Copy flags onto the final derived poly from the original mesh poly */ - mp_orig = me->mpoly + index_array[i]; - polys[i].flag = mp_orig->flag; + if (flush_hidden) { + const VArray<bool> hide_poly_orig = attributes_orig.lookup_or_default<bool>( + ".hide_poly", ATTR_DOMAIN_FACE, false); + bke::SpanAttributeWriter<bool> hide_poly_eval = + attributes_eval.lookup_or_add_for_write_only_span<bool>(".hide_poly", + ATTR_DOMAIN_FACE); + for (const int i : IndexRange(me_eval->totpoly)) { + const int orig_poly_index = index_array[i]; + if (orig_poly_index != ORIGINDEX_NONE) { + hide_poly_eval.span[i] = hide_poly_orig[orig_poly_index]; + } } + hide_poly_eval.finish(); } - const VArray<bool> hide_poly_orig = attributes_orig.lookup_or_default<bool>( - ".hide_poly", ATTR_DOMAIN_FACE, false); - bke::SpanAttributeWriter<bool> hide_poly_eval = - attributes_eval.lookup_or_add_for_write_only_span<bool>(".hide_poly", ATTR_DOMAIN_FACE); - for (const int i : IndexRange(me_eval->totpoly)) { - const int orig_poly_index = index_array[i]; - if (orig_poly_index != ORIGINDEX_NONE) { - hide_poly_eval.span[i] = hide_poly_orig[orig_poly_index]; + if (flush_selection) { + const VArray<bool> select_poly_orig = attributes_orig.lookup_or_default<bool>( + ".select_poly", ATTR_DOMAIN_FACE, false); + bke::SpanAttributeWriter<bool> select_poly_eval = + attributes_eval.lookup_or_add_for_write_only_span<bool>(".select_poly", + ATTR_DOMAIN_FACE); + for (const int i : IndexRange(me_eval->totpoly)) { + const int orig_poly_index = index_array[i]; + if (orig_poly_index != ORIGINDEX_NONE) { + select_poly_eval.span[i] = select_poly_orig[orig_poly_index]; + } } + select_poly_eval.finish(); } - hide_poly_eval.finish(); updated = true; } @@ -144,24 +154,26 @@ void paintface_hide(bContext *C, Object *ob, const bool unselected) return; } - bke::MutableAttributeAccessor attributes = bke::mesh_attributes_for_write(*me); + bke::MutableAttributeAccessor attributes = me->attributes_for_write(); bke::SpanAttributeWriter<bool> hide_poly = attributes.lookup_or_add_for_write_span<bool>( ".hide_poly", ATTR_DOMAIN_FACE); + bke::SpanAttributeWriter<bool> select_poly = attributes.lookup_or_add_for_write_span<bool>( + ".select_poly", ATTR_DOMAIN_FACE); for (int i = 0; i < me->totpoly; i++) { - MPoly *mpoly = &me->mpoly[i]; if (!hide_poly.span[i]) { - if (((mpoly->flag & ME_FACE_SEL) == 0) == unselected) { + if (!select_poly.span[i] == unselected) { hide_poly.span[i] = true; } } if (hide_poly.span[i]) { - mpoly->flag &= ~ME_FACE_SEL; + select_poly.span[i] = false; } } hide_poly.finish(); + select_poly.finish(); BKE_mesh_flush_hidden_from_polys(me); @@ -176,17 +188,19 @@ void paintface_reveal(bContext *C, Object *ob, const bool select) return; } - bke::MutableAttributeAccessor attributes = bke::mesh_attributes_for_write(*me); + bke::MutableAttributeAccessor attributes = me->attributes_for_write(); if (select) { const VArray<bool> hide_poly = attributes.lookup_or_default<bool>( ".hide_poly", ATTR_DOMAIN_FACE, false); - for (int i = 0; i < me->totpoly; i++) { - MPoly *mpoly = &me->mpoly[i]; + bke::SpanAttributeWriter<bool> select_poly = attributes.lookup_or_add_for_write_span<bool>( + ".select_poly", ATTR_DOMAIN_FACE); + for (const int i : hide_poly.index_range()) { if (hide_poly[i]) { - mpoly->flag |= ME_FACE_SEL; + select_poly.span[i] = true; } } + select_poly.finish(); } attributes.remove(".hide_poly"); @@ -207,25 +221,30 @@ static void select_linked_tfaces_with_seams(Mesh *me, const uint index, const bo BLI_bitmap *edge_tag = BLI_BITMAP_NEW(me->totedge, __func__); BLI_bitmap *poly_tag = BLI_BITMAP_NEW(me->totpoly, __func__); - bke::AttributeAccessor attributes = bke::mesh_attributes(*me); + const Span<MEdge> edges = me->edges(); + const Span<MPoly> polys = me->polys(); + const Span<MLoop> loops = me->loops(); + bke::MutableAttributeAccessor attributes = me->attributes_for_write(); const VArray<bool> hide_poly = attributes.lookup_or_default<bool>( ".hide_poly", ATTR_DOMAIN_FACE, false); + bke::SpanAttributeWriter<bool> select_poly = attributes.lookup_or_add_for_write_span<bool>( + ".select_poly", ATTR_DOMAIN_FACE); if (index != (uint)-1) { /* only put face under cursor in array */ - MPoly *mp = &me->mpoly[index]; - BKE_mesh_poly_edgebitmap_insert(edge_tag, mp, me->mloop + mp->loopstart); + const MPoly &poly = polys[index]; + BKE_mesh_poly_edgebitmap_insert(edge_tag, &poly, &loops[poly.loopstart]); BLI_BITMAP_ENABLE(poly_tag, index); } else { /* fill array by selection */ for (int i = 0; i < me->totpoly; i++) { - MPoly *mp = &me->mpoly[i]; if (hide_poly[i]) { /* pass */ } - else if (mp->flag & ME_FACE_SEL) { - BKE_mesh_poly_edgebitmap_insert(edge_tag, mp, me->mloop + mp->loopstart); + else if (select_poly.span[i]) { + const MPoly &poly = polys[i]; + BKE_mesh_poly_edgebitmap_insert(edge_tag, &poly, &loops[poly.loopstart]); BLI_BITMAP_ENABLE(poly_tag, i); } } @@ -236,7 +255,6 @@ static void select_linked_tfaces_with_seams(Mesh *me, const uint index, const bo /* expand selection */ for (int i = 0; i < me->totpoly; i++) { - MPoly *mp = &me->mpoly[i]; if (hide_poly[i]) { continue; } @@ -244,9 +262,10 @@ static void select_linked_tfaces_with_seams(Mesh *me, const uint index, const bo if (!BLI_BITMAP_TEST(poly_tag, i)) { mark = false; - MLoop *ml = me->mloop + mp->loopstart; - for (int b = 0; b < mp->totloop; b++, ml++) { - if ((me->medge[ml->e].flag & ME_SEAM) == 0) { + const MPoly &poly = polys[i]; + const MLoop *ml = &loops[poly.loopstart]; + for (int b = 0; b < poly.totloop; b++, ml++) { + if ((edges[ml->e].flag & ME_SEAM) == 0) { if (BLI_BITMAP_TEST(edge_tag, ml->e)) { mark = true; break; @@ -256,7 +275,7 @@ static void select_linked_tfaces_with_seams(Mesh *me, const uint index, const bo if (mark) { BLI_BITMAP_ENABLE(poly_tag, i); - BKE_mesh_poly_edgebitmap_insert(edge_tag, mp, me->mloop + mp->loopstart); + BKE_mesh_poly_edgebitmap_insert(edge_tag, &poly, &loops[poly.loopstart]); do_it = true; } } @@ -266,9 +285,8 @@ static void select_linked_tfaces_with_seams(Mesh *me, const uint index, const bo MEM_freeN(edge_tag); for (int i = 0; i < me->totpoly; i++) { - MPoly *mp = &me->mpoly[i]; if (BLI_BITMAP_TEST(poly_tag, i)) { - SET_FLAG_FROM_TEST(mp->flag, select, ME_FACE_SEL); + select_poly.span[i] = select; } } @@ -303,16 +321,17 @@ bool paintface_deselect_all_visible(bContext *C, Object *ob, int action, bool fl return false; } - bke::AttributeAccessor attributes = bke::mesh_attributes(*me); + bke::MutableAttributeAccessor attributes = me->attributes_for_write(); const VArray<bool> hide_poly = attributes.lookup_or_default<bool>( ".hide_poly", ATTR_DOMAIN_FACE, false); + bke::SpanAttributeWriter<bool> select_poly = attributes.lookup_or_add_for_write_span<bool>( + ".select_poly", ATTR_DOMAIN_FACE); if (action == SEL_TOGGLE) { action = SEL_SELECT; for (int i = 0; i < me->totpoly; i++) { - MPoly *mpoly = &me->mpoly[i]; - if (!hide_poly[i] && mpoly->flag & ME_FACE_SEL) { + if (!hide_poly[i] && select_poly.span[i]) { action = SEL_DESELECT; break; } @@ -322,29 +341,29 @@ bool paintface_deselect_all_visible(bContext *C, Object *ob, int action, bool fl bool changed = false; for (int i = 0; i < me->totpoly; i++) { - MPoly *mpoly = &me->mpoly[i]; - if (!hide_poly[i]) { - switch (action) { - case SEL_SELECT: - if ((mpoly->flag & ME_FACE_SEL) == 0) { - mpoly->flag |= ME_FACE_SEL; - changed = true; - } - break; - case SEL_DESELECT: - if ((mpoly->flag & ME_FACE_SEL) != 0) { - mpoly->flag &= ~ME_FACE_SEL; - changed = true; - } - break; - case SEL_INVERT: - mpoly->flag ^= ME_FACE_SEL; - changed = true; - break; - } + if (hide_poly[i]) { + continue; + } + const bool old_selection = select_poly.span[i]; + switch (action) { + case SEL_SELECT: + select_poly.span[i] = true; + break; + case SEL_DESELECT: + select_poly.span[i] = false; + break; + case SEL_INVERT: + select_poly.span[i] = !select_poly.span[i]; + changed = true; + break; + } + if (old_selection != select_poly.span[i]) { + changed = true; } } + select_poly.finish(); + if (changed) { if (flush_flags) { paintface_flush_flags(C, ob, true, false); @@ -360,26 +379,30 @@ bool paintface_minmax(Object *ob, float r_min[3], float r_max[3]) float vec[3], bmat[3][3]; const Mesh *me = BKE_mesh_from_object(ob); - if (!me || !me->mloopuv) { + if (!me || !CustomData_has_layer(&me->ldata, CD_MLOOPUV)) { return ok; } - const MVert *mvert = me->mvert; copy_m3_m4(bmat, ob->obmat); - bke::AttributeAccessor attributes = bke::mesh_attributes(*me); + const Span<MVert> verts = me->verts(); + const Span<MPoly> polys = me->polys(); + const Span<MLoop> loops = me->loops(); + bke::AttributeAccessor attributes = me->attributes(); const VArray<bool> hide_poly = attributes.lookup_or_default<bool>( ".hide_poly", ATTR_DOMAIN_FACE, false); + const VArray<bool> select_poly = attributes.lookup_or_default<bool>( + ".select_poly", ATTR_DOMAIN_FACE, false); for (int i = 0; i < me->totpoly; i++) { - MPoly *mp = &me->mpoly[i]; - if (hide_poly[i] || !(mp->flag & ME_FACE_SEL)) { + if (hide_poly[i] || !select_poly[i]) { continue; } - const MLoop *ml = me->mloop + mp->loopstart; - for (int b = 0; b < mp->totloop; b++, ml++) { - mul_v3_m3v3(vec, bmat, mvert[ml->v].co); + const MPoly &poly = polys[i]; + const MLoop *ml = &loops[poly.loopstart]; + for (int b = 0; b < poly.totloop; b++, ml++) { + mul_v3_m3v3(vec, bmat, verts[ml->v].co); add_v3_v3v3(vec, vec, ob->obmat[3]); minmax_v3v3_v3(r_min, r_max, vec); } @@ -396,7 +419,6 @@ bool paintface_mouse_select(bContext *C, Object *ob) { using namespace blender; - MPoly *mpoly_sel = nullptr; uint index; bool changed = false; bool found = false; @@ -404,13 +426,14 @@ bool paintface_mouse_select(bContext *C, /* Get the face under the cursor */ Mesh *me = BKE_mesh_from_object(ob); - bke::AttributeAccessor attributes = bke::mesh_attributes(*me); + bke::MutableAttributeAccessor attributes = me->attributes_for_write(); const VArray<bool> hide_poly = attributes.lookup_or_default<bool>( ".hide_poly", ATTR_DOMAIN_FACE, false); + bke::AttributeWriter<bool> select_poly = attributes.lookup_or_add_for_write<bool>( + ".select_poly", ATTR_DOMAIN_FACE); if (ED_mesh_pick_face(C, ob, mval, ED_MESH_PICK_DEFAULT_FACE_DIST, &index)) { if (index < me->totpoly) { - mpoly_sel = me->mpoly + index; if (!hide_poly[index]) { found = true; } @@ -418,7 +441,7 @@ bool paintface_mouse_select(bContext *C, } if (params->sel_op == SEL_OP_SET) { - if ((found && params->select_passthrough) && (mpoly_sel->flag & ME_FACE_SEL)) { + if ((found && params->select_passthrough) && select_poly.varray[index]) { found = false; } else if (found || params->deselect_all) { @@ -431,31 +454,19 @@ bool paintface_mouse_select(bContext *C, me->act_face = (int)index; switch (params->sel_op) { - case SEL_OP_ADD: { - mpoly_sel->flag |= ME_FACE_SEL; + case SEL_OP_SET: + case SEL_OP_ADD: + select_poly.varray.set(index, true); break; - } - case SEL_OP_SUB: { - mpoly_sel->flag &= ~ME_FACE_SEL; + case SEL_OP_SUB: + select_poly.varray.set(index, false); break; - } - case SEL_OP_XOR: { - if (mpoly_sel->flag & ME_FACE_SEL) { - mpoly_sel->flag &= ~ME_FACE_SEL; - } - else { - mpoly_sel->flag |= ME_FACE_SEL; - } + case SEL_OP_XOR: + select_poly.varray.set(index, !select_poly.varray[index]); break; - } - case SEL_OP_SET: { - mpoly_sel->flag |= ME_FACE_SEL; - break; - } - case SEL_OP_AND: { + case SEL_OP_AND: BLI_assert_unreachable(); /* Doesn't make sense for picking. */ break; - } } /* image window redraw */ @@ -469,13 +480,10 @@ bool paintface_mouse_select(bContext *C, void paintvert_flush_flags(Object *ob) { + using namespace blender; + using namespace blender; Mesh *me = BKE_mesh_from_object(ob); Mesh *me_eval = BKE_object_get_evaluated_mesh(ob); - MVert *mvert_eval, *mv; - const int *index_array = nullptr; - int totvert; - int i; - if (me == nullptr) { return; } @@ -488,27 +496,42 @@ void paintvert_flush_flags(Object *ob) return; } - index_array = (const int *)CustomData_get_layer(&me_eval->vdata, CD_ORIGINDEX); + const bke::AttributeAccessor attributes_orig = me->attributes(); + bke::MutableAttributeAccessor attributes_eval = me_eval->attributes_for_write(); - mvert_eval = me_eval->mvert; - totvert = me_eval->totvert; + const int *orig_indices = (const int *)CustomData_get_layer(&me_eval->vdata, CD_ORIGINDEX); - mv = mvert_eval; - - if (index_array) { - int orig_index; - for (i = 0; i < totvert; i++, mv++) { - orig_index = index_array[i]; - if (orig_index != ORIGINDEX_NONE) { - mv->flag = me->mvert[index_array[i]].flag; + const VArray<bool> hide_vert_orig = attributes_orig.lookup_or_default<bool>( + ".hide_vert", ATTR_DOMAIN_POINT, false); + bke::SpanAttributeWriter<bool> hide_vert_eval = + attributes_eval.lookup_or_add_for_write_only_span<bool>(".hide_vert", ATTR_DOMAIN_POINT); + if (orig_indices) { + for (const int i : hide_vert_eval.span.index_range()) { + if (orig_indices[i] != ORIGINDEX_NONE) { + hide_vert_eval.span[i] = hide_vert_orig[orig_indices[i]]; } } } else { - for (i = 0; i < totvert; i++, mv++) { - mv->flag = me->mvert[i].flag; + hide_vert_orig.materialize(hide_vert_eval.span); + } + hide_vert_eval.finish(); + + const VArray<bool> select_vert_orig = attributes_orig.lookup_or_default<bool>( + ".select_vert", ATTR_DOMAIN_POINT, false); + bke::SpanAttributeWriter<bool> select_vert_eval = + attributes_eval.lookup_or_add_for_write_only_span<bool>(".select_vert", ATTR_DOMAIN_POINT); + if (orig_indices) { + for (const int i : select_vert_eval.span.index_range()) { + if (orig_indices[i] != ORIGINDEX_NONE) { + select_vert_eval.span[i] = select_vert_orig[orig_indices[i]]; + } } } + else { + select_vert_orig.materialize(select_vert_eval.span); + } + select_vert_eval.finish(); BKE_mesh_batch_cache_dirty_tag(me, BKE_MESH_BATCH_DIRTY_ALL); } @@ -527,16 +550,17 @@ bool paintvert_deselect_all_visible(Object *ob, int action, bool flush_flags) return false; } - bke::AttributeAccessor attributes = bke::mesh_attributes(*me); + bke::MutableAttributeAccessor attributes = me->attributes_for_write(); const VArray<bool> hide_vert = attributes.lookup_or_default<bool>( ".hide_vert", ATTR_DOMAIN_POINT, false); + bke::SpanAttributeWriter<bool> select_vert = attributes.lookup_or_add_for_write_span<bool>( + ".select_vert", ATTR_DOMAIN_POINT); if (action == SEL_TOGGLE) { action = SEL_SELECT; for (int i = 0; i < me->totvert; i++) { - MVert *mvert = &me->mvert[i]; - if (!hide_vert[i] && mvert->flag & SELECT) { + if (!hide_vert[i] && select_vert.span[i]) { action = SEL_DESELECT; break; } @@ -545,29 +569,28 @@ bool paintvert_deselect_all_visible(Object *ob, int action, bool flush_flags) bool changed = false; for (int i = 0; i < me->totvert; i++) { - MVert *mvert = &me->mvert[i]; - if (!hide_vert[i]) { - switch (action) { - case SEL_SELECT: - if ((mvert->flag & SELECT) == 0) { - mvert->flag |= SELECT; - changed = true; - } - break; - case SEL_DESELECT: - if ((mvert->flag & SELECT) != 0) { - mvert->flag &= ~SELECT; - changed = true; - } - break; - case SEL_INVERT: - mvert->flag ^= SELECT; - changed = true; - break; - } + if (hide_vert[i]) { + continue; + } + const bool old_selection = select_vert.span[i]; + switch (action) { + case SEL_SELECT: + select_vert.span[i] = true; + break; + case SEL_DESELECT: + select_vert.span[i] = false; + break; + case SEL_INVERT: + select_vert.span[i] = !select_vert.span[i]; + break; + } + if (old_selection != select_vert.span[i]) { + changed = true; } } + select_vert.finish(); + if (changed) { /* handle mselect */ if (action == SEL_SELECT) { @@ -591,8 +614,11 @@ void paintvert_select_ungrouped(Object *ob, bool extend, bool flush_flags) { using namespace blender; Mesh *me = BKE_mesh_from_object(ob); - - if (me == nullptr || me->dvert == nullptr) { + if (me == nullptr) { + return; + } + const Span<MDeformVert> dverts = me->deform_verts(); + if (dverts.is_empty()) { return; } @@ -600,21 +626,23 @@ void paintvert_select_ungrouped(Object *ob, bool extend, bool flush_flags) paintvert_deselect_all_visible(ob, SEL_DESELECT, false); } - bke::AttributeAccessor attributes = bke::mesh_attributes(*me); + bke::MutableAttributeAccessor attributes = me->attributes_for_write(); const VArray<bool> hide_vert = attributes.lookup_or_default<bool>( ".hide_vert", ATTR_DOMAIN_POINT, false); + bke::SpanAttributeWriter<bool> select_vert = attributes.lookup_or_add_for_write_span<bool>( + ".select_vert", ATTR_DOMAIN_POINT); - for (int i = 0; i < me->totvert; i++) { - MVert *mv = &me->mvert[i]; - MDeformVert *dv = &me->dvert[i]; + for (const int i : select_vert.span.index_range()) { if (!hide_vert[i]) { - if (dv->dw == nullptr) { + if (dverts[i].dw == nullptr) { /* if null weight then not grouped */ - mv->flag |= SELECT; + select_vert.span[i] = true; } } } + select_vert.finish(); + if (flush_flags) { paintvert_flush_flags(ob); } @@ -624,28 +652,29 @@ void paintvert_hide(bContext *C, Object *ob, const bool unselected) { using namespace blender; Mesh *me = BKE_mesh_from_object(ob); - if (me == NULL || me->totvert == 0) { + if (me == nullptr || me->totvert == 0) { return; } - bke::MutableAttributeAccessor attributes = bke::mesh_attributes_for_write(*me); + bke::MutableAttributeAccessor attributes = me->attributes_for_write(); bke::SpanAttributeWriter<bool> hide_vert = attributes.lookup_or_add_for_write_span<bool>( ".hide_vert", ATTR_DOMAIN_POINT); - MutableSpan<MVert> verts(me->mvert, me->totvert); + bke::SpanAttributeWriter<bool> select_vert = attributes.lookup_or_add_for_write_span<bool>( + ".select_vert", ATTR_DOMAIN_POINT); - for (const int i : verts.index_range()) { - MVert &vert = verts[i]; + for (const int i : hide_vert.span.index_range()) { if (!hide_vert.span[i]) { - if (((vert.flag & SELECT) == 0) == unselected) { + if (!select_vert.span[i] == unselected) { hide_vert.span[i] = true; } } if (hide_vert.span[i]) { - vert.flag &= ~SELECT; + select_vert.span[i] = false; } } hide_vert.finish(); + select_vert.finish(); BKE_mesh_flush_hidden_from_verts(me); @@ -657,22 +686,24 @@ void paintvert_reveal(bContext *C, Object *ob, const bool select) { using namespace blender; Mesh *me = BKE_mesh_from_object(ob); - if (me == NULL || me->totvert == 0) { + if (me == nullptr || me->totvert == 0) { return; } - bke::MutableAttributeAccessor attributes = bke::mesh_attributes_for_write(*me); + bke::MutableAttributeAccessor attributes = me->attributes_for_write(); const VArray<bool> hide_vert = attributes.lookup_or_default<bool>( ".hide_vert", ATTR_DOMAIN_POINT, false); - MutableSpan<MVert> verts(me->mvert, me->totvert); + bke::SpanAttributeWriter<bool> select_vert = attributes.lookup_or_add_for_write_span<bool>( + ".select_vert", ATTR_DOMAIN_POINT); - for (const int i : verts.index_range()) { - MVert &vert = verts[i]; + for (const int i : select_vert.span.index_range()) { if (hide_vert[i]) { - SET_FLAG_FROM_TEST(vert.flag, select, SELECT); + select_vert.span[i] = select; } } + select_vert.finish(); + /* Remove the hide attribute to reveal all vertices. */ attributes.remove(".hide_vert"); diff --git a/source/blender/editors/mesh/editmesh_bevel.c b/source/blender/editors/mesh/editmesh_bevel.c index e7891450bd6..0a6feeb3665 100644 --- a/source/blender/editors/mesh/editmesh_bevel.c +++ b/source/blender/editors/mesh/editmesh_bevel.c @@ -240,7 +240,7 @@ static bool edbm_bevel_init(bContext *C, wmOperator *op, const bool is_modal) { uint ob_store_len = 0; Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data( - view_layer, v3d, &ob_store_len); + scene, view_layer, v3d, &ob_store_len); opdata->ob_store = MEM_malloc_arrayN(ob_store_len, sizeof(*opdata->ob_store), __func__); for (uint ob_index = 0; ob_index < ob_store_len; ob_index++) { Object *obedit = objects[ob_index]; @@ -649,7 +649,7 @@ wmKeyMap *bevel_modal_keymap(wmKeyConfig *keyconf) wmKeyMap *keymap = WM_modalkeymap_find(keyconf, "Bevel Modal Map"); - /* This function is called for each spacetype, only needs to add map once */ + /* This function is called for each space-type, only needs to add map once. */ if (keymap && keymap->modal_items) { return NULL; } diff --git a/source/blender/editors/mesh/editmesh_bisect.c b/source/blender/editors/mesh/editmesh_bisect.c index 7b251b77750..5c5a12b3e64 100644 --- a/source/blender/editors/mesh/editmesh_bisect.c +++ b/source/blender/editors/mesh/editmesh_bisect.c @@ -99,6 +99,7 @@ static void mesh_bisect_interactive_calc(bContext *C, static int mesh_bisect_invoke(bContext *C, wmOperator *op, const wmEvent *event) { + const Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); int valid_objects = 0; @@ -111,7 +112,7 @@ static int mesh_bisect_invoke(bContext *C, wmOperator *op, const wmEvent *event) uint objects_len = 0; Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data( - view_layer, CTX_wm_view3d(C), &objects_len); + scene, view_layer, CTX_wm_view3d(C), &objects_len); for (uint ob_index = 0; ob_index < objects_len; ob_index++) { Object *obedit = objects[ob_index]; BMEditMesh *em = BKE_editmesh_from_object(obedit); @@ -284,7 +285,7 @@ static int mesh_bisect_exec(bContext *C, wmOperator *op) uint objects_len = 0; Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data( - CTX_data_view_layer(C), CTX_wm_view3d(C), &objects_len); + CTX_data_scene(C), CTX_data_view_layer(C), CTX_wm_view3d(C), &objects_len); for (uint ob_index = 0; ob_index < objects_len; ob_index++) { Object *obedit = objects[ob_index]; diff --git a/source/blender/editors/mesh/editmesh_extrude.c b/source/blender/editors/mesh/editmesh_extrude.c index 330008d92d1..55e9c32e41b 100644 --- a/source/blender/editors/mesh/editmesh_extrude.c +++ b/source/blender/editors/mesh/editmesh_extrude.c @@ -281,10 +281,11 @@ static int edbm_extrude_repeat_exec(bContext *C, wmOperator *op) mul_v3_fl(offset, scale_offset); + const Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); uint objects_len = 0; Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data( - view_layer, CTX_wm_view3d(C), &objects_len); + scene, view_layer, CTX_wm_view3d(C), &objects_len); for (uint ob_index = 0; ob_index < objects_len; ob_index++) { float offset_local[3], tmat[3][3]; @@ -418,10 +419,11 @@ static bool edbm_extrude_mesh(Object *obedit, BMEditMesh *em, wmOperator *op) /* extrude without transform */ static int edbm_extrude_region_exec(bContext *C, wmOperator *op) { + const Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); uint objects_len = 0; Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data( - view_layer, CTX_wm_view3d(C), &objects_len); + scene, view_layer, CTX_wm_view3d(C), &objects_len); for (uint ob_index = 0; ob_index < objects_len; ob_index++) { Object *obedit = objects[ob_index]; @@ -477,10 +479,11 @@ void MESH_OT_extrude_region(wmOperatorType *ot) /* extrude without transform */ static int edbm_extrude_context_exec(bContext *C, wmOperator *op) { + const Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); uint objects_len = 0; Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data( - view_layer, CTX_wm_view3d(C), &objects_len); + scene, view_layer, CTX_wm_view3d(C), &objects_len); for (uint ob_index = 0; ob_index < objects_len; ob_index++) { Object *obedit = objects[ob_index]; @@ -531,10 +534,11 @@ void MESH_OT_extrude_context(wmOperatorType *ot) static int edbm_extrude_verts_exec(bContext *C, wmOperator *op) { + const Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); uint objects_len = 0; Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data( - view_layer, CTX_wm_view3d(C), &objects_len); + scene, view_layer, CTX_wm_view3d(C), &objects_len); for (uint ob_index = 0; ob_index < objects_len; ob_index++) { Object *obedit = objects[ob_index]; @@ -584,10 +588,11 @@ void MESH_OT_extrude_verts_indiv(wmOperatorType *ot) static int edbm_extrude_edges_exec(bContext *C, wmOperator *op) { const bool use_normal_flip = RNA_boolean_get(op->ptr, "use_normal_flip"); + const Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); uint objects_len = 0; Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data( - view_layer, CTX_wm_view3d(C), &objects_len); + scene, view_layer, CTX_wm_view3d(C), &objects_len); for (uint ob_index = 0; ob_index < objects_len; ob_index++) { Object *obedit = objects[ob_index]; @@ -637,10 +642,11 @@ void MESH_OT_extrude_edges_indiv(wmOperatorType *ot) static int edbm_extrude_faces_exec(bContext *C, wmOperator *op) { + const Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); uint objects_len = 0; Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data( - view_layer, CTX_wm_view3d(C), &objects_len); + scene, view_layer, CTX_wm_view3d(C), &objects_len); for (uint ob_index = 0; ob_index < objects_len; ob_index++) { Object *obedit = objects[ob_index]; @@ -710,7 +716,7 @@ static int edbm_dupli_extrude_cursor_invoke(bContext *C, wmOperator *op, const w uint objects_len = 0; Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data( - vc.view_layer, vc.v3d, &objects_len); + vc.scene, vc.view_layer, vc.v3d, &objects_len); for (uint ob_index = 0; ob_index < objects_len; ob_index++) { Object *obedit = objects[ob_index]; ED_view3d_viewcontext_init_object(&vc, obedit); @@ -785,8 +791,8 @@ static int edbm_dupli_extrude_cursor_invoke(bContext *C, wmOperator *op, const w /* 2D rotate by 90d while adding. * (x, y) = (y, -x) * - * accumulate the screenspace normal in 2D, - * with screenspace edge length weighting the result. */ + * Accumulate the screen-space normal in 2D, + * with screen-space edge length weighting the result. */ if (line_point_side_v2(co1, co2, mval_f) >= 0.0f) { nor[0] += (co1[1] - co2[1]); nor[1] += -(co1[0] - co2[0]); diff --git a/source/blender/editors/mesh/editmesh_extrude_screw.c b/source/blender/editors/mesh/editmesh_extrude_screw.c index cc493cab0f9..be2d04b14a1 100644 --- a/source/blender/editors/mesh/editmesh_extrude_screw.c +++ b/source/blender/editors/mesh/editmesh_extrude_screw.c @@ -41,7 +41,7 @@ static int edbm_screw_exec(bContext *C, wmOperator *op) int valence; uint objects_empty_len = 0; uint failed_axis_len = 0; - uint failed_vertices_len = 0; + uint failed_verts_len = 0; turns = RNA_int_get(op->ptr, "turns"); steps = RNA_int_get(op->ptr, "steps"); @@ -49,9 +49,10 @@ static int edbm_screw_exec(bContext *C, wmOperator *op) RNA_float_get_array(op->ptr, "axis", axis); uint objects_len = 0; + const Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data( - view_layer, CTX_wm_view3d(C), &objects_len); + scene, view_layer, CTX_wm_view3d(C), &objects_len); for (uint ob_index = 0; ob_index < objects_len; ob_index++) { Object *obedit = objects[ob_index]; @@ -97,7 +98,7 @@ static int edbm_screw_exec(bContext *C, wmOperator *op) } if (v1 == NULL || v2 == NULL) { - failed_vertices_len++; + failed_verts_len++; continue; } @@ -151,7 +152,7 @@ static int edbm_screw_exec(bContext *C, wmOperator *op) if (failed_axis_len == objects_len - objects_empty_len) { BKE_report(op->reports, RPT_ERROR, "Invalid/unset axis"); } - else if (failed_vertices_len == objects_len - objects_empty_len) { + else if (failed_verts_len == objects_len - objects_empty_len) { BKE_report(op->reports, RPT_ERROR, "You have to select a string of connected vertices too"); } diff --git a/source/blender/editors/mesh/editmesh_extrude_spin.c b/source/blender/editors/mesh/editmesh_extrude_spin.c index ec04ece6569..9e2b7aa7f4d 100644 --- a/source/blender/editors/mesh/editmesh_extrude_spin.c +++ b/source/blender/editors/mesh/editmesh_extrude_spin.c @@ -36,6 +36,7 @@ static int edbm_spin_exec(bContext *C, wmOperator *op) { + const Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); float cent[3], axis[3]; const float d[3] = {0.0f, 0.0f, 0.0f}; @@ -56,7 +57,7 @@ static int edbm_spin_exec(bContext *C, wmOperator *op) uint objects_len = 0; Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data( - view_layer, CTX_wm_view3d(C), &objects_len); + scene, view_layer, CTX_wm_view3d(C), &objects_len); for (uint ob_index = 0; ob_index < objects_len; ob_index++) { Object *obedit = objects[ob_index]; diff --git a/source/blender/editors/mesh/editmesh_inset.c b/source/blender/editors/mesh/editmesh_inset.c index ae21e6143f6..068e6215c26 100644 --- a/source/blender/editors/mesh/editmesh_inset.c +++ b/source/blender/editors/mesh/editmesh_inset.c @@ -132,7 +132,7 @@ static bool edbm_inset_init(bContext *C, wmOperator *op, const bool is_modal) { uint ob_store_len = 0; Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data( - view_layer, CTX_wm_view3d(C), &ob_store_len); + scene, view_layer, CTX_wm_view3d(C), &ob_store_len); opdata->ob_store = MEM_malloc_arrayN(ob_store_len, sizeof(*opdata->ob_store), __func__); for (uint ob_index = 0; ob_index < ob_store_len; ob_index++) { Object *obedit = objects[ob_index]; diff --git a/source/blender/editors/mesh/editmesh_intersect.c b/source/blender/editors/mesh/editmesh_intersect.c index 166eb40a7db..83cefd1c09d 100644 --- a/source/blender/editors/mesh/editmesh_intersect.c +++ b/source/blender/editors/mesh/editmesh_intersect.c @@ -180,11 +180,12 @@ static int edbm_intersect_exec(bContext *C, wmOperator *op) default: /* ISECT_SEPARATE_NONE */ break; } + const Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); uint objects_len = 0; uint isect_len = 0; Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data( - view_layer, CTX_wm_view3d(C), &objects_len); + scene, view_layer, CTX_wm_view3d(C), &objects_len); for (uint ob_index = 0; ob_index < objects_len; ob_index++) { Object *obedit = objects[ob_index]; BMEditMesh *em = BKE_editmesh_from_object(obedit); @@ -350,11 +351,12 @@ static int edbm_intersect_boolean_exec(bContext *C, wmOperator *op) bool has_isect; test_fn = use_swap ? bm_face_isect_pair_swap : bm_face_isect_pair; + const Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); uint objects_len = 0; uint isect_len = 0; Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data( - view_layer, CTX_wm_view3d(C), &objects_len); + scene, view_layer, CTX_wm_view3d(C), &objects_len); for (uint ob_index = 0; ob_index < objects_len; ob_index++) { Object *obedit = objects[ob_index]; BMEditMesh *em = BKE_editmesh_from_object(obedit); @@ -815,10 +817,11 @@ static int edbm_face_split_by_edges_exec(bContext *C, wmOperator *UNUSED(op)) BLI_SMALLSTACK_DECLARE(loop_stack, BMLoop *); + const Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); uint objects_len = 0; Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data( - view_layer, CTX_wm_view3d(C), &objects_len); + scene, view_layer, CTX_wm_view3d(C), &objects_len); for (uint ob_index = 0; ob_index < objects_len; ob_index++) { Object *obedit = objects[ob_index]; BMEditMesh *em = BKE_editmesh_from_object(obedit); diff --git a/source/blender/editors/mesh/editmesh_knife.c b/source/blender/editors/mesh/editmesh_knife.c index d4c5504615a..156698be567 100644 --- a/source/blender/editors/mesh/editmesh_knife.c +++ b/source/blender/editors/mesh/editmesh_knife.c @@ -489,7 +489,7 @@ static void knifetool_draw_visible_distances(const KnifeTool_OpData *kcd) wmOrtho2_region_pixelspace(kcd->region); uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); - immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); char numstr[256]; float numstr_size[2]; @@ -629,7 +629,7 @@ static void knifetool_draw_angle(const KnifeTool_OpData *kcd, uint pos_2d = GPU_vertformat_attr_add( immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); - immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); /* Angle as string. */ char numstr[256]; @@ -4102,7 +4102,7 @@ static void knifetool_init(ViewContext *vc, kcd->region = vc->region; kcd->objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data( - vc->view_layer, vc->v3d, &kcd->objects_len); + vc->scene, vc->view_layer, vc->v3d, &kcd->objects_len); Object *ob; BMEditMesh *em; @@ -4378,7 +4378,7 @@ wmKeyMap *knifetool_modal_keymap(wmKeyConfig *keyconf) wmKeyMap *keymap = WM_modalkeymap_find(keyconf, "Knife Tool Modal Map"); - /* This function is called for each spacetype, only needs to add map once. */ + /* This function is called for each space-type, only needs to add map once. */ if (keymap && keymap->modal_items) { return NULL; } @@ -4893,12 +4893,13 @@ void MESH_OT_knife_tool(wmOperatorType *ot) KNF_MEASUREMENT_NONE, "Measurements", "Visible distance and angle measurements"); - RNA_def_enum(ot->srna, - "angle_snapping", - angle_snapping_items, - KNF_CONSTRAIN_ANGLE_MODE_NONE, - "Angle Snapping", - "Angle snapping mode"); + prop = RNA_def_enum(ot->srna, + "angle_snapping", + angle_snapping_items, + KNF_CONSTRAIN_ANGLE_MODE_NONE, + "Angle Snapping", + "Angle snapping mode"); + RNA_def_property_translation_context(prop, BLT_I18NCONTEXT_ID_MESH); prop = RNA_def_float(ot->srna, "angle_snapping_increment", diff --git a/source/blender/editors/mesh/editmesh_knife_project.c b/source/blender/editors/mesh/editmesh_knife_project.c index c32b1fa99c0..e27d19ab000 100644 --- a/source/blender/editors/mesh/editmesh_knife_project.c +++ b/source/blender/editors/mesh/editmesh_knife_project.c @@ -136,7 +136,7 @@ static int knifeproject_exec(bContext *C, wmOperator *op) * since each knife-project runs as a separate operation. */ uint objects_len; Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data( - vc.view_layer, vc.v3d, &objects_len); + vc.scene, vc.view_layer, vc.v3d, &objects_len); for (uint ob_index = 0; ob_index < objects_len; ob_index++) { Object *obedit = objects[ob_index]; ED_view3d_viewcontext_init_object(&vc, obedit); diff --git a/source/blender/editors/mesh/editmesh_loopcut.c b/source/blender/editors/mesh/editmesh_loopcut.c index 5a4b12c2209..591e06be80c 100644 --- a/source/blender/editors/mesh/editmesh_loopcut.c +++ b/source/blender/editors/mesh/editmesh_loopcut.c @@ -376,11 +376,12 @@ static int loopcut_init(bContext *C, wmOperator *op, const wmEvent *event) .e_index = (uint)RNA_int_get(op->ptr, "edge_index"), }; + const Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); uint bases_len; Base **bases = BKE_view_layer_array_from_bases_in_edit_mode( - view_layer, CTX_wm_view3d(C), &bases_len); + scene, view_layer, CTX_wm_view3d(C), &bases_len); if (is_interactive) { for (uint base_index = 0; base_index < bases_len; base_index++) { @@ -446,7 +447,6 @@ static int loopcut_init(bContext *C, wmOperator *op, const wmEvent *event) #ifdef USE_LOOPSLIDE_HACK /* for use in macro so we can restore, HACK */ { - Scene *scene = CTX_data_scene(C); ToolSettings *settings = scene->toolsettings; const bool mesh_select_mode[3] = { (settings->selectmode & SCE_SELECT_VERTEX) != 0, diff --git a/source/blender/editors/mesh/editmesh_mask_extract.c b/source/blender/editors/mesh/editmesh_mask_extract.c index 7634ce6af9e..fdf4746ab09 100644 --- a/source/blender/editors/mesh/editmesh_mask_extract.c +++ b/source/blender/editors/mesh/editmesh_mask_extract.c @@ -204,12 +204,12 @@ static int geometry_extract_apply(bContext *C, local_view_bits = v3d->local_view_uuid; } Object *new_ob = ED_object_add_type(C, OB_MESH, NULL, ob->loc, ob->rot, false, local_view_bits); - BKE_mesh_nomain_to_mesh(new_mesh, new_ob->data, new_ob, &CD_MASK_EVERYTHING, true); + BKE_mesh_nomain_to_mesh(new_mesh, new_ob->data, new_ob); /* Remove the Face Sets as they need to be recreated when entering Sculpt Mode in the new object. * TODO(pablodobarro): In the future we can try to preserve them from the original mesh. */ Mesh *new_ob_mesh = new_ob->data; - CustomData_free_layers(&new_ob_mesh->pdata, CD_SCULPT_FACE_SETS, new_ob_mesh->totpoly); + CustomData_free_layer_named(&new_ob_mesh->pdata, ".sculpt_face_set", new_ob_mesh->totpoly); /* Remove the mask from the new object so it can be sculpted directly after extracting. */ CustomData_free_layers(&new_ob_mesh->vdata, CD_PAINT_MASK, new_ob_mesh->totvert); @@ -268,7 +268,8 @@ static void geometry_extract_tag_face_set(BMesh *bm, GeometryExtractParams *para const int tag_face_set_id = params->active_face_set; BM_mesh_elem_hflag_disable_all(bm, BM_VERT | BM_EDGE | BM_FACE, BM_ELEM_TAG, false); - const int cd_face_sets_offset = CustomData_get_offset(&bm->pdata, CD_SCULPT_FACE_SETS); + const int cd_face_sets_offset = CustomData_get_offset_named( + &bm->pdata, CD_PROP_INT32, ".sculpt_face_set"); BMFace *f; BMIter iter; @@ -486,7 +487,7 @@ static int paint_mask_slice_exec(bContext *C, wmOperator *op) Mesh *new_mesh = (Mesh *)BKE_id_copy(bmain, &mesh->id); if (ob->mode == OB_MODE_SCULPT) { - ED_sculpt_undo_geometry_begin(ob, "mask slice"); + ED_sculpt_undo_geometry_begin(ob, op); } BMesh *bm; @@ -548,7 +549,7 @@ static int paint_mask_slice_exec(bContext *C, wmOperator *op) /* Remove the mask from the new object so it can be sculpted directly after slicing. */ CustomData_free_layers(&new_ob_mesh->vdata, CD_PAINT_MASK, new_ob_mesh->totvert); - BKE_mesh_nomain_to_mesh(new_ob_mesh, new_ob->data, new_ob, &CD_MASK_MESH, true); + BKE_mesh_nomain_to_mesh(new_ob_mesh, new_ob->data, new_ob); BKE_mesh_copy_parameters_for_eval(new_ob->data, mesh); WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, new_ob); BKE_mesh_batch_cache_dirty_tag(new_ob->data, BKE_MESH_BATCH_DIRTY_ALL); @@ -557,11 +558,12 @@ static int paint_mask_slice_exec(bContext *C, wmOperator *op) WM_event_add_notifier(C, NC_GEOM | ND_DATA, new_ob->data); } - BKE_mesh_nomain_to_mesh(new_mesh, ob->data, ob, &CD_MASK_MESH, true); + BKE_mesh_nomain_to_mesh(new_mesh, ob->data, ob); if (ob->mode == OB_MODE_SCULPT) { SculptSession *ss = ob->sculpt; - ss->face_sets = CustomData_get_layer(&((Mesh *)ob->data)->pdata, CD_SCULPT_FACE_SETS); + ss->face_sets = CustomData_get_layer_named( + &((Mesh *)ob->data)->pdata, CD_PROP_INT32, ".sculpt_face_set"); if (ss->face_sets) { /* Assign a new Face Set ID to the new faces created by the slice operation. */ const int next_face_set_id = ED_sculpt_face_sets_find_next_available_id(ob->data); diff --git a/source/blender/editors/mesh/editmesh_path.c b/source/blender/editors/mesh/editmesh_path.c index f2e7150e791..5db12db0e46 100644 --- a/source/blender/editors/mesh/editmesh_path.c +++ b/source/blender/editors/mesh/editmesh_path.c @@ -21,6 +21,7 @@ #include "BLI_math.h" #include "BKE_context.h" +#include "BKE_customdata.h" #include "BKE_editmesh.h" #include "BKE_layer.h" #include "BKE_report.h" @@ -345,10 +346,14 @@ static void edgetag_ensure_cd_flag(Mesh *me, const char edge_mode) switch (edge_mode) { case EDGE_MODE_TAG_CREASE: - BM_mesh_cd_flag_ensure(bm, me, ME_CDFLAG_EDGE_CREASE); + if (!CustomData_has_layer(&bm->edata, CD_CREASE)) { + BM_data_layer_add(bm, &bm->edata, CD_CREASE); + } break; case EDGE_MODE_TAG_BEVEL: - BM_mesh_cd_flag_ensure(bm, me, ME_CDFLAG_EDGE_BWEIGHT); + if (!CustomData_has_layer(&bm->edata, CD_BWEIGHT)) { + BM_data_layer_add(bm, &bm->edata, CD_BWEIGHT); + } break; #ifdef WITH_FREESTYLE case EDGE_MODE_TAG_FREESTYLE: @@ -679,7 +684,8 @@ static int edbm_shortest_path_pick_invoke(bContext *C, wmOperator *op, const wmE em_setup_viewcontext(C, &vc); copy_v2_v2_int(vc.mval, event->mval); - Base *basact = BASACT(vc.view_layer); + BKE_view_layer_synced_ensure(vc.scene, vc.view_layer); + Base *basact = BKE_view_layer_active_base_get(vc.view_layer); BMEditMesh *em = vc.em; view3d_operator_needs_opengl(C); @@ -687,7 +693,8 @@ static int edbm_shortest_path_pick_invoke(bContext *C, wmOperator *op, const wmE { int base_index = -1; uint bases_len = 0; - Base **bases = BKE_view_layer_array_from_bases_in_edit_mode(vc.view_layer, vc.v3d, &bases_len); + Base **bases = BKE_view_layer_array_from_bases_in_edit_mode( + vc.scene, vc.view_layer, vc.v3d, &bases_len); if (EDBM_unified_findnearest(&vc, bases, bases_len, &base_index, &eve, &eed, &efa)) { basact = bases[base_index]; ED_view3d_viewcontext_init_object(&vc, basact->object); @@ -732,7 +739,8 @@ static int edbm_shortest_path_pick_invoke(bContext *C, wmOperator *op, const wmE return OPERATOR_PASS_THROUGH; } - if (vc.view_layer->basact != basact) { + BKE_view_layer_synced_ensure(vc.scene, vc.view_layer); + if (BKE_view_layer_active_base_get(vc.view_layer) != basact) { ED_object_base_activate(C, basact); } @@ -814,7 +822,7 @@ static int edbm_shortest_path_select_exec(bContext *C, wmOperator *op) ViewLayer *view_layer = CTX_data_view_layer(C); uint objects_len = 0; Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data( - view_layer, CTX_wm_view3d(C), &objects_len); + scene, view_layer, CTX_wm_view3d(C), &objects_len); for (uint ob_index = 0; ob_index < objects_len; ob_index++) { Object *obedit = objects[ob_index]; BMEditMesh *em = BKE_editmesh_from_object(obedit); diff --git a/source/blender/editors/mesh/editmesh_polybuild.c b/source/blender/editors/mesh/editmesh_polybuild.c index 493e476ba4f..17580dbe7d1 100644 --- a/source/blender/editors/mesh/editmesh_polybuild.c +++ b/source/blender/editors/mesh/editmesh_polybuild.c @@ -53,11 +53,14 @@ static void edbm_selectmode_ensure(Scene *scene, BMEditMesh *em, short selectmod } /* Could make public, for now just keep here. */ -static void edbm_flag_disable_all_multi(ViewLayer *view_layer, View3D *v3d, const char hflag) +static void edbm_flag_disable_all_multi(const Scene *scene, + ViewLayer *view_layer, + View3D *v3d, + const char hflag) { uint objects_len = 0; Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data( - view_layer, v3d, &objects_len); + scene, view_layer, v3d, &objects_len); for (uint ob_index = 0; ob_index < objects_len; ob_index++) { Object *ob_iter = objects[ob_index]; BMEditMesh *em_iter = BKE_editmesh_from_object(ob_iter); @@ -84,8 +87,10 @@ static bool edbm_preselect_or_active(bContext *C, const View3D *v3d, Base **r_ba ED_view3d_gizmo_mesh_preselect_get_active(C, gz, r_base, r_ele); } else { + const Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); - Base *base = view_layer->basact; + BKE_view_layer_synced_ensure(scene, view_layer); + Base *base = BKE_view_layer_active_base_get(view_layer); Object *obedit = base->object; BMEditMesh *em = BKE_editmesh_from_object(obedit); BMesh *bm = em->bm; @@ -128,7 +133,7 @@ static int edbm_polybuild_transform_at_cursor_invoke(bContext *C, edbm_selectmode_ensure(vc.scene, vc.em, SCE_SELECT_VERTEX); - edbm_flag_disable_all_multi(vc.view_layer, vc.v3d, BM_ELEM_SELECT); + edbm_flag_disable_all_multi(vc.scene, vc.view_layer, vc.v3d, BM_ELEM_SELECT); if (ele_act->head.htype == BM_VERT) { BM_vert_select_set(bm, (BMVert *)ele_act, true); @@ -147,7 +152,8 @@ static int edbm_polybuild_transform_at_cursor_invoke(bContext *C, .is_destructive = true, }); if (basact != NULL) { - if (vc.view_layer->basact != basact) { + BKE_view_layer_synced_ensure(vc.scene, vc.view_layer); + if (BKE_view_layer_active_base_get(vc.view_layer) != basact) { ED_object_base_activate(C, basact); } } @@ -234,7 +240,8 @@ static int edbm_polybuild_delete_at_cursor_invoke(bContext *C, .is_destructive = true, }); if (basact != NULL) { - if (vc.view_layer->basact != basact) { + BKE_view_layer_synced_ensure(vc.scene, vc.view_layer); + if (BKE_view_layer_active_base_get(vc.view_layer) != basact) { ED_object_base_activate(C, basact); } } @@ -292,7 +299,7 @@ static int edbm_polybuild_face_at_cursor_invoke(bContext *C, wmOperator *op, con mul_m4_v3(vc.obedit->imat, center); BMVert *v_new = BM_vert_create(bm, center, NULL, BM_CREATE_NOP); - edbm_flag_disable_all_multi(vc.view_layer, vc.v3d, BM_ELEM_SELECT); + edbm_flag_disable_all_multi(vc.scene, vc.view_layer, vc.v3d, BM_ELEM_SELECT); BM_vert_select_set(bm, v_new, true); BM_select_history_store(bm, v_new); changed = true; @@ -309,7 +316,7 @@ static int edbm_polybuild_face_at_cursor_invoke(bContext *C, wmOperator *op, con const float fac = line_point_factor_v3(center, e_act->v1->co, e_act->v2->co); BMVert *v_new = BM_edge_split(bm, e_act, e_act->v1, NULL, CLAMPIS(fac, 0.0f, 1.0f)); copy_v3_v3(v_new->co, center); - edbm_flag_disable_all_multi(vc.view_layer, vc.v3d, BM_ELEM_SELECT); + edbm_flag_disable_all_multi(vc.scene, vc.view_layer, vc.v3d, BM_ELEM_SELECT); BM_vert_select_set(bm, v_new, true); BM_select_history_store(bm, v_new); } @@ -322,7 +329,7 @@ static int edbm_polybuild_face_at_cursor_invoke(bContext *C, wmOperator *op, con SWAP(BMVert *, v_tri[0], v_tri[1]); } BM_face_create_verts(bm, v_tri, 3, f_reference, BM_CREATE_NOP, true); - edbm_flag_disable_all_multi(vc.view_layer, vc.v3d, BM_ELEM_SELECT); + edbm_flag_disable_all_multi(vc.scene, vc.view_layer, vc.v3d, BM_ELEM_SELECT); BM_vert_select_set(bm, v_tri[2], true); BM_select_history_store(bm, v_tri[2]); } @@ -372,7 +379,7 @@ static int edbm_polybuild_face_at_cursor_invoke(bContext *C, wmOperator *op, con // BMFace *f_new = BM_face_create_verts(bm, v_quad, 4, f_reference, BM_CREATE_NOP, true); - edbm_flag_disable_all_multi(vc.view_layer, vc.v3d, BM_ELEM_SELECT); + edbm_flag_disable_all_multi(vc.scene, vc.view_layer, vc.v3d, BM_ELEM_SELECT); BM_vert_select_set(bm, v_quad[2], true); BM_select_history_store(bm, v_quad[2]); changed = true; @@ -402,7 +409,8 @@ static int edbm_polybuild_face_at_cursor_invoke(bContext *C, wmOperator *op, con }); if (basact != NULL) { - if (vc.view_layer->basact != basact) { + BKE_view_layer_synced_ensure(vc.scene, vc.view_layer); + if (BKE_view_layer_active_base_get(vc.view_layer) != basact) { ED_object_base_activate(C, basact); } } @@ -475,7 +483,7 @@ static int edbm_polybuild_split_at_cursor_invoke(bContext *C, BMVert *v_new = BM_edge_split(bm, e_act, e_act->v1, NULL, CLAMPIS(fac, 0.0f, 1.0f)); copy_v3_v3(v_new->co, center); - edbm_flag_disable_all_multi(vc.view_layer, vc.v3d, BM_ELEM_SELECT); + edbm_flag_disable_all_multi(vc.scene, vc.view_layer, vc.v3d, BM_ELEM_SELECT); BM_vert_select_set(bm, v_new, true); BM_select_history_store(bm, v_new); changed = true; @@ -495,7 +503,8 @@ static int edbm_polybuild_split_at_cursor_invoke(bContext *C, WM_event_add_mousemove(vc.win); - if (vc.view_layer->basact != basact) { + BKE_view_layer_synced_ensure(vc.scene, vc.view_layer); + if (BKE_view_layer_active_base_get(vc.view_layer) != basact) { ED_object_base_activate(C, basact); } @@ -578,7 +587,7 @@ static int edbm_polybuild_dissolve_at_cursor_invoke(bContext *C, } if (changed) { - edbm_flag_disable_all_multi(vc.view_layer, vc.v3d, BM_ELEM_SELECT); + edbm_flag_disable_all_multi(vc.scene, vc.view_layer, vc.v3d, BM_ELEM_SELECT); EDBM_update(vc.obedit->data, &(const struct EDBMUpdate_Params){ @@ -587,7 +596,8 @@ static int edbm_polybuild_dissolve_at_cursor_invoke(bContext *C, .is_destructive = true, }); - if (vc.view_layer->basact != basact) { + BKE_view_layer_synced_ensure(vc.scene, vc.view_layer); + if (BKE_view_layer_active_base_get(vc.view_layer) != basact) { ED_object_base_activate(C, basact); } diff --git a/source/blender/editors/mesh/editmesh_rip.c b/source/blender/editors/mesh/editmesh_rip.c index 6b4edea498e..0c137c94d57 100644 --- a/source/blender/editors/mesh/editmesh_rip.c +++ b/source/blender/editors/mesh/editmesh_rip.c @@ -987,10 +987,11 @@ static int edbm_rip_invoke__edge(bContext *C, const wmEvent *event, Object *obed /* based on mouse cursor position, it defines how is being ripped */ static int edbm_rip_invoke(bContext *C, wmOperator *op, const wmEvent *event) { + const Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); uint objects_len = 0; Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data( - view_layer, CTX_wm_view3d(C), &objects_len); + scene, view_layer, CTX_wm_view3d(C), &objects_len); const bool do_fill = RNA_boolean_get(op->ptr, "use_fill"); bool no_vertex_selected = true; diff --git a/source/blender/editors/mesh/editmesh_rip_edge.c b/source/blender/editors/mesh/editmesh_rip_edge.c index 85426acb905..dd4b247a06f 100644 --- a/source/blender/editors/mesh/editmesh_rip_edge.c +++ b/source/blender/editors/mesh/editmesh_rip_edge.c @@ -35,10 +35,11 @@ static int edbm_rip_edge_invoke(bContext *C, wmOperator *UNUSED(op), const wmEve { ARegion *region = CTX_wm_region(C); RegionView3D *rv3d = CTX_wm_region_view3d(C); + const Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); uint objects_len = 0; Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data( - view_layer, CTX_wm_view3d(C), &objects_len); + scene, view_layer, CTX_wm_view3d(C), &objects_len); for (uint ob_index = 0; ob_index < objects_len; ob_index++) { Object *obedit = objects[ob_index]; diff --git a/source/blender/editors/mesh/editmesh_select.c b/source/blender/editors/mesh/editmesh_select.c index 9c8c5c45cb7..b66fe84e84e 100644 --- a/source/blender/editors/mesh/editmesh_select.c +++ b/source/blender/editors/mesh/editmesh_select.c @@ -358,6 +358,7 @@ BMVert *EDBM_vert_find_nearest_ex(ViewContext *vc, BMVert *EDBM_vert_find_nearest(ViewContext *vc, float *dist_px_manhattan_p) { + BKE_view_layer_synced_ensure(vc->scene, vc->view_layer); Base *base = BKE_view_layer_base_find(vc->view_layer, vc->obact); return EDBM_vert_find_nearest_ex(vc, dist_px_manhattan_p, false, false, &base, 1, NULL); } @@ -612,6 +613,7 @@ BMEdge *EDBM_edge_find_nearest_ex(ViewContext *vc, BMEdge *EDBM_edge_find_nearest(ViewContext *vc, float *dist_px_manhattan_p) { + BKE_view_layer_synced_ensure(vc->scene, vc->view_layer); Base *base = BKE_view_layer_base_find(vc->view_layer, vc->obact); return EDBM_edge_find_nearest_ex( vc, dist_px_manhattan_p, NULL, false, false, NULL, &base, 1, NULL); @@ -831,6 +833,7 @@ BMFace *EDBM_face_find_nearest_ex(ViewContext *vc, BMFace *EDBM_face_find_nearest(ViewContext *vc, float *dist_px_manhattan_p) { + BKE_view_layer_synced_ensure(vc->scene, vc->view_layer); Base *base = BKE_view_layer_base_find(vc->view_layer, vc->obact); return EDBM_face_find_nearest_ex( vc, dist_px_manhattan_p, NULL, false, false, false, NULL, &base, 1, NULL); @@ -1512,10 +1515,11 @@ static void walker_select(BMEditMesh *em, int walkercode, void *start, const boo static int edbm_loop_multiselect_exec(bContext *C, wmOperator *op) { const bool is_ring = RNA_boolean_get(op->ptr, "ring"); + const Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); uint objects_len = 0; Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data( - view_layer, CTX_wm_view3d(C), &objects_len); + scene, view_layer, CTX_wm_view3d(C), &objects_len); for (uint ob_index = 0; ob_index < objects_len; ob_index++) { Object *obedit = objects[ob_index]; BMEditMesh *em = BKE_editmesh_from_object(obedit); @@ -1681,7 +1685,8 @@ static bool mouse_mesh_loop( em_original->selectmode = SCE_SELECT_EDGE; uint bases_len; - Base **bases = BKE_view_layer_array_from_bases_in_edit_mode(vc.view_layer, vc.v3d, &bases_len); + Base **bases = BKE_view_layer_array_from_bases_in_edit_mode( + vc.scene, vc.view_layer, vc.v3d, &bases_len); { int base_index = -1; @@ -1903,12 +1908,13 @@ void MESH_OT_edgering_select(wmOperatorType *ot) static int edbm_select_all_exec(bContext *C, wmOperator *op) { + const Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); int action = RNA_enum_get(op->ptr, "action"); uint objects_len = 0; Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data( - view_layer, CTX_wm_view3d(C), &objects_len); + scene, view_layer, CTX_wm_view3d(C), &objects_len); if (action == SEL_TOGGLE) { action = SEL_SELECT; @@ -1971,10 +1977,11 @@ void MESH_OT_select_all(wmOperatorType *ot) static int edbm_faces_select_interior_exec(bContext *C, wmOperator *UNUSED(op)) { + const Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); uint objects_len = 0; Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data( - view_layer, CTX_wm_view3d(C), &objects_len); + scene, view_layer, CTX_wm_view3d(C), &objects_len); for (uint ob_index = 0; ob_index < objects_len; ob_index++) { Object *obedit = objects[ob_index]; @@ -2031,7 +2038,8 @@ bool EDBM_select_pick(bContext *C, const int mval[2], const struct SelectPick_Pa vc.mval[1] = mval[1]; uint bases_len = 0; - Base **bases = BKE_view_layer_array_from_bases_in_edit_mode(vc.view_layer, vc.v3d, &bases_len); + Base **bases = BKE_view_layer_array_from_bases_in_edit_mode( + vc.scene, vc.view_layer, vc.v3d, &bases_len); bool changed = false; bool found = unified_findnearest(&vc, bases, bases_len, &base_index_active, &eve, &eed, &efa); @@ -2214,7 +2222,8 @@ bool EDBM_select_pick(bContext *C, const int mval[2], const struct SelectPick_Pa /* Changing active object is handy since it allows us to * switch UV layers, vgroups for eg. */ - if (vc.view_layer->basact != basact) { + BKE_view_layer_synced_ensure(vc.scene, vc.view_layer); + if (BKE_view_layer_active_base_get(vc.view_layer) != basact) { ED_object_base_activate(C, basact); } @@ -2488,7 +2497,7 @@ bool EDBM_selectmode_toggle_multi(bContext *C, uint objects_len = 0; Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data( - view_layer, CTX_wm_view3d(C), &objects_len); + scene, view_layer, CTX_wm_view3d(C), &objects_len); for (uint ob_index = 0; ob_index < objects_len; ob_index++) { Object *ob_iter = objects[ob_index]; @@ -2584,7 +2593,7 @@ bool EDBM_selectmode_set_multi(bContext *C, const short selectmode) uint objects_len = 0; Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data( - view_layer, CTX_wm_view3d(C), &objects_len); + scene, view_layer, CTX_wm_view3d(C), &objects_len); for (uint ob_index = 0; ob_index < objects_len; ob_index++) { Object *ob_iter = objects[ob_index]; @@ -2723,7 +2732,7 @@ bool EDBM_mesh_deselect_all_multi(struct bContext *C) ED_view3d_viewcontext_init(C, &vc, depsgraph); uint bases_len = 0; Base **bases = BKE_view_layer_array_from_bases_in_edit_mode_unique_data( - vc.view_layer, vc.v3d, &bases_len); + vc.scene, vc.view_layer, vc.v3d, &bases_len); bool changed_multi = EDBM_mesh_deselect_all_multi_ex(bases, bases_len); MEM_freeN(bases); return changed_multi; @@ -2758,7 +2767,7 @@ bool EDBM_selectmode_disable_multi(struct bContext *C, ED_view3d_viewcontext_init(C, &vc, depsgraph); uint bases_len = 0; Base **bases = BKE_view_layer_array_from_bases_in_edit_mode_unique_data( - vc.view_layer, NULL, &bases_len); + vc.scene, vc.view_layer, NULL, &bases_len); bool changed_multi = EDBM_selectmode_disable_multi_ex( scene, bases, bases_len, selectmode_disable, selectmode_fallback); MEM_freeN(bases); @@ -3245,7 +3254,7 @@ static int edbm_select_linked_exec(bContext *C, wmOperator *op) uint objects_len = 0; Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data( - view_layer, CTX_wm_view3d(C), &objects_len); + scene, view_layer, CTX_wm_view3d(C), &objects_len); for (uint ob_index = 0; ob_index < objects_len; ob_index++) { Object *obedit = objects[ob_index]; @@ -3612,7 +3621,8 @@ static int edbm_select_linked_pick_invoke(bContext *C, wmOperator *op, const wmE em_setup_viewcontext(C, &vc); uint bases_len; - Base **bases = BKE_view_layer_array_from_bases_in_edit_mode(vc.view_layer, vc.v3d, &bases_len); + Base **bases = BKE_view_layer_array_from_bases_in_edit_mode( + vc.scene, vc.view_layer, vc.v3d, &bases_len); { bool has_edges = false; @@ -3663,7 +3673,7 @@ static int edbm_select_linked_pick_invoke(bContext *C, wmOperator *op, const wmE * which might not be available on redo. */ BM_mesh_elem_index_ensure(bm, ele->head.htype); int object_index; - index = EDBM_elem_to_index_any_multi(vc.view_layer, em, ele, &object_index); + index = EDBM_elem_to_index_any_multi(vc.scene, vc.view_layer, em, ele, &object_index); BLI_assert(object_index >= 0); RNA_int_set(op->ptr, "object_index", object_index); RNA_int_set(op->ptr, "index", index); @@ -3682,11 +3692,12 @@ static int edbm_select_linked_pick_exec(bContext *C, wmOperator *op) BMElem *ele; { + const Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); /* Intentionally wrap negative values so the lookup fails. */ const uint object_index = (uint)RNA_int_get(op->ptr, "object_index"); const uint index = (uint)RNA_int_get(op->ptr, "index"); - ele = EDBM_elem_from_index_any_multi(view_layer, object_index, index, &obedit); + ele = EDBM_elem_from_index_any_multi(scene, view_layer, object_index, index, &obedit); } if (ele == NULL) { @@ -3753,13 +3764,14 @@ void MESH_OT_select_linked_pick(wmOperatorType *ot) static int edbm_select_face_by_sides_exec(bContext *C, wmOperator *op) { + const Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); uint objects_len = 0; const bool extend = RNA_boolean_get(op->ptr, "extend"); const int numverts = RNA_int_get(op->ptr, "number"); const int type = RNA_enum_get(op->ptr, "type"); Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data( - view_layer, CTX_wm_view3d(C), &objects_len); + scene, view_layer, CTX_wm_view3d(C), &objects_len); for (uint ob_index = 0; ob_index < objects_len; ob_index++) { Object *obedit = objects[ob_index]; @@ -3844,12 +3856,13 @@ void MESH_OT_select_face_by_sides(wmOperatorType *ot) static int edbm_select_loose_exec(bContext *C, wmOperator *op) { + const Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); const bool extend = RNA_boolean_get(op->ptr, "extend"); uint objects_len = 0; Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data( - view_layer, CTX_wm_view3d(C), &objects_len); + scene, view_layer, CTX_wm_view3d(C), &objects_len); for (uint ob_index = 0; ob_index < objects_len; ob_index++) { Object *obedit = objects[ob_index]; @@ -3934,6 +3947,7 @@ void MESH_OT_select_loose(wmOperatorType *ot) static int edbm_select_mirror_exec(bContext *C, wmOperator *op) { + const Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); const int axis_flag = RNA_enum_get(op->ptr, "axis"); const bool extend = RNA_boolean_get(op->ptr, "extend"); @@ -3944,7 +3958,7 @@ static int edbm_select_mirror_exec(bContext *C, wmOperator *op) uint objects_len = 0; Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data( - view_layer, CTX_wm_view3d(C), &objects_len); + scene, view_layer, CTX_wm_view3d(C), &objects_len); for (uint ob_index = 0; ob_index < objects_len; ob_index++) { Object *obedit = objects[ob_index]; @@ -4008,12 +4022,13 @@ void MESH_OT_select_mirror(wmOperatorType *ot) static int edbm_select_more_exec(bContext *C, wmOperator *op) { + const Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); const bool use_face_step = RNA_boolean_get(op->ptr, "use_face_step"); uint objects_len = 0; Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data( - view_layer, CTX_wm_view3d(C), &objects_len); + scene, view_layer, CTX_wm_view3d(C), &objects_len); for (uint ob_index = 0; ob_index < objects_len; ob_index++) { Object *obedit = objects[ob_index]; BMEditMesh *em = BKE_editmesh_from_object(obedit); @@ -4058,12 +4073,13 @@ void MESH_OT_select_more(wmOperatorType *ot) static int edbm_select_less_exec(bContext *C, wmOperator *op) { + const Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); const bool use_face_step = RNA_boolean_get(op->ptr, "use_face_step"); uint objects_len = 0; Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data( - view_layer, CTX_wm_view3d(C), &objects_len); + scene, view_layer, CTX_wm_view3d(C), &objects_len); for (uint ob_index = 0; ob_index < objects_len; ob_index++) { Object *obedit = objects[ob_index]; BMEditMesh *em = BKE_editmesh_from_object(obedit); @@ -4296,6 +4312,7 @@ static bool edbm_deselect_nth(BMEditMesh *em, const struct CheckerIntervalParams static int edbm_select_nth_exec(bContext *C, wmOperator *op) { + const Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); struct CheckerIntervalParams op_params; WM_operator_properties_checker_interval_from_op(op, &op_params); @@ -4303,7 +4320,7 @@ static int edbm_select_nth_exec(bContext *C, wmOperator *op) uint objects_len = 0; Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data( - view_layer, CTX_wm_view3d(C), &objects_len); + scene, view_layer, CTX_wm_view3d(C), &objects_len); for (uint ob_index = 0; ob_index < objects_len; ob_index++) { Object *obedit = objects[ob_index]; @@ -4374,10 +4391,11 @@ static int edbm_select_sharp_edges_exec(bContext *C, wmOperator *op) */ const float angle_limit_cos = cosf(RNA_float_get(op->ptr, "sharpness")); + const Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); uint objects_len = 0; Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data( - view_layer, CTX_wm_view3d(C), &objects_len); + scene, view_layer, CTX_wm_view3d(C), &objects_len); for (uint ob_index = 0; ob_index < objects_len; ob_index++) { Object *obedit = objects[ob_index]; @@ -4450,10 +4468,11 @@ void MESH_OT_edges_select_sharp(wmOperatorType *ot) static int edbm_select_linked_flat_faces_exec(bContext *C, wmOperator *op) { + const Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); uint objects_len = 0; Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data( - view_layer, CTX_wm_view3d(C), &objects_len); + scene, view_layer, CTX_wm_view3d(C), &objects_len); const float angle_limit_cos = cosf(RNA_float_get(op->ptr, "sharpness")); for (uint ob_index = 0; ob_index < objects_len; ob_index++) { @@ -4563,10 +4582,11 @@ static int edbm_select_non_manifold_exec(bContext *C, wmOperator *op) const bool use_non_contiguous = RNA_boolean_get(op->ptr, "use_non_contiguous"); const bool use_verts = RNA_boolean_get(op->ptr, "use_verts"); + const Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); uint objects_len = 0; Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data( - view_layer, CTX_wm_view3d(C), &objects_len); + scene, view_layer, CTX_wm_view3d(C), &objects_len); for (uint ob_index = 0; ob_index < objects_len; ob_index++) { Object *obedit = objects[ob_index]; @@ -4667,11 +4687,12 @@ static int edbm_select_random_exec(bContext *C, wmOperator *op) const float randfac = RNA_float_get(op->ptr, "ratio"); const int seed = WM_operator_properties_select_random_seed_increment_get(op); + const Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); uint objects_len = 0; Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data( - view_layer, CTX_wm_view3d(C), &objects_len); + scene, view_layer, CTX_wm_view3d(C), &objects_len); for (uint ob_index = 0; ob_index < objects_len; ob_index++) { Object *obedit = objects[ob_index]; BMEditMesh *em = BKE_editmesh_from_object(obedit); @@ -4797,11 +4818,12 @@ static bool edbm_select_ungrouped_poll(bContext *C) static int edbm_select_ungrouped_exec(bContext *C, wmOperator *op) { const bool extend = RNA_boolean_get(op->ptr, "extend"); + const Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); uint objects_len = 0; Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data( - view_layer, CTX_wm_view3d(C), &objects_len); + scene, view_layer, CTX_wm_view3d(C), &objects_len); for (uint ob_index = 0; ob_index < objects_len; ob_index++) { Object *obedit = objects[ob_index]; @@ -4925,7 +4947,7 @@ static int edbm_select_axis_exec(bContext *C, wmOperator *op) uint objects_len = 0; Object **objects = BKE_view_layer_array_from_objects_in_edit_mode( - view_layer, CTX_wm_view3d(C), &objects_len); + scene, view_layer, CTX_wm_view3d(C), &objects_len); for (uint ob_index = 0; ob_index < objects_len; ob_index++) { Object *obedit_iter = objects[ob_index]; BMEditMesh *em_iter = BKE_editmesh_from_object(obedit_iter); @@ -5023,10 +5045,11 @@ void MESH_OT_select_axis(wmOperatorType *ot) static int edbm_region_to_loop_exec(bContext *C, wmOperator *UNUSED(op)) { + const Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); uint objects_len = 0; Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data( - view_layer, CTX_wm_view3d(C), &objects_len); + scene, view_layer, CTX_wm_view3d(C), &objects_len); for (uint ob_index = 0; ob_index < objects_len; ob_index++) { Object *obedit = objects[ob_index]; BMEditMesh *em = BKE_editmesh_from_object(obedit); @@ -5255,10 +5278,11 @@ static int edbm_loop_to_region_exec(bContext *C, wmOperator *op) { const bool select_bigger = RNA_boolean_get(op->ptr, "select_bigger"); + const Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); uint objects_len = 0; Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data( - view_layer, CTX_wm_view3d(C), &objects_len); + scene, view_layer, CTX_wm_view3d(C), &objects_len); for (uint ob_index = 0; ob_index < objects_len; ob_index++) { Object *obedit = objects[ob_index]; BMEditMesh *em = BKE_editmesh_from_object(obedit); diff --git a/source/blender/editors/mesh/editmesh_select_similar.c b/source/blender/editors/mesh/editmesh_select_similar.c index c931cb4948b..47c76b7709b 100644 --- a/source/blender/editors/mesh/editmesh_select_similar.c +++ b/source/blender/editors/mesh/editmesh_select_similar.c @@ -12,6 +12,8 @@ #include "BLI_listbase.h" #include "BLI_math.h" +#include "BLT_translation.h" + #include "BKE_context.h" #include "BKE_customdata.h" #include "BKE_deform.h" @@ -145,6 +147,7 @@ static void face_to_plane(const Object *ob, BMFace *face, float r_plane[4]) */ static int similar_face_select_exec(bContext *C, wmOperator *op) { + const Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); const int type = RNA_enum_get(op->ptr, "type"); @@ -155,7 +158,7 @@ static int similar_face_select_exec(bContext *C, wmOperator *op) int tot_faces_selected_all = 0; uint objects_len = 0; Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data( - view_layer, CTX_wm_view3d(C), &objects_len); + scene, view_layer, CTX_wm_view3d(C), &objects_len); for (uint ob_index = 0; ob_index < objects_len; ob_index++) { Object *ob = objects[ob_index]; @@ -618,6 +621,7 @@ static bool edge_data_value_set(BMEdge *edge, const int hflag, int *r_value) */ static int similar_edge_select_exec(bContext *C, wmOperator *op) { + const Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); const int type = RNA_enum_get(op->ptr, "type"); @@ -629,7 +633,7 @@ static int similar_edge_select_exec(bContext *C, wmOperator *op) int tot_edges_selected_all = 0; uint objects_len = 0; Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data( - view_layer, CTX_wm_view3d(C), &objects_len); + scene, view_layer, CTX_wm_view3d(C), &objects_len); for (uint ob_index = 0; ob_index < objects_len; ob_index++) { Object *ob = objects[ob_index]; @@ -968,6 +972,7 @@ static int similar_edge_select_exec(bContext *C, wmOperator *op) static int similar_vert_select_exec(bContext *C, wmOperator *op) { + const Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); /* get the type from RNA */ @@ -979,7 +984,7 @@ static int similar_vert_select_exec(bContext *C, wmOperator *op) int tot_verts_selected_all = 0; uint objects_len = 0; Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data( - view_layer, CTX_wm_view3d(C), &objects_len); + scene, view_layer, CTX_wm_view3d(C), &objects_len); for (uint ob_index = 0; ob_index < objects_len; ob_index++) { Object *ob = objects[ob_index]; @@ -1416,6 +1421,7 @@ void MESH_OT_select_similar(wmOperatorType *ot) /* properties */ prop = ot->prop = RNA_def_enum(ot->srna, "type", prop_similar_types, SIMVERT_NORMAL, "Type", ""); + RNA_def_property_translation_context(prop, BLT_I18NCONTEXT_ID_MESH); RNA_def_enum_funcs(prop, select_similar_type_itemf); RNA_def_enum(ot->srna, "compare", prop_similar_compare_types, SIM_CMP_EQ, "Compare", ""); diff --git a/source/blender/editors/mesh/editmesh_tools.c b/source/blender/editors/mesh/editmesh_tools.c index 7de5ad9f151..9f3ef8af17d 100644 --- a/source/blender/editors/mesh/editmesh_tools.c +++ b/source/blender/editors/mesh/editmesh_tools.c @@ -93,10 +93,11 @@ static int edbm_subdivide_exec(bContext *C, wmOperator *op) const int quad_corner_type = RNA_enum_get(op->ptr, "quadcorner"); const int seed = RNA_int_get(op->ptr, "seed"); + const Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); uint objects_len = 0; Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data( - view_layer, CTX_wm_view3d(C), &objects_len); + scene, view_layer, CTX_wm_view3d(C), &objects_len); for (uint ob_index = 0; ob_index < objects_len; ob_index++) { Object *obedit = objects[ob_index]; @@ -289,11 +290,11 @@ static void mesh_operator_edgering_props_get(wmOperator *op, struct EdgeRingOpSu static int edbm_subdivide_edge_ring_exec(bContext *C, wmOperator *op) { - + const Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); uint objects_len = 0; Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data( - view_layer, CTX_wm_view3d(C), &objects_len); + scene, view_layer, CTX_wm_view3d(C), &objects_len); struct EdgeRingOpSubdProps op_props; mesh_operator_edgering_props_get(op, &op_props); @@ -358,10 +359,11 @@ void MESH_OT_subdivide_edgering(wmOperatorType *ot) static int edbm_unsubdivide_exec(bContext *C, wmOperator *op) { const int iterations = RNA_int_get(op->ptr, "iterations"); + const Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); uint objects_len = 0; Object **objects = BKE_view_layer_array_from_objects_in_edit_mode( - view_layer, CTX_wm_view3d(C), &objects_len); + scene, view_layer, CTX_wm_view3d(C), &objects_len); for (uint ob_index = 0; ob_index < objects_len; ob_index++) { Object *obedit = objects[ob_index]; BMEditMesh *em = BKE_editmesh_from_object(obedit); @@ -444,11 +446,12 @@ static void edbm_report_delete_info(ReportList *reports, static int edbm_delete_exec(bContext *C, wmOperator *op) { + const Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); uint objects_len = 0; Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data( - view_layer, CTX_wm_view3d(C), &objects_len); + scene, view_layer, CTX_wm_view3d(C), &objects_len); bool changed_multi = false; for (uint ob_index = 0; ob_index < objects_len; ob_index++) { @@ -587,13 +590,14 @@ static bool bm_face_is_loose(BMFace *f) static int edbm_delete_loose_exec(bContext *C, wmOperator *op) { + const Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); int totelem_old_sel[3]; int totelem_old[3]; uint objects_len = 0; Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data( - view_layer, CTX_wm_view3d(C), &objects_len); + scene, view_layer, CTX_wm_view3d(C), &objects_len); EDBM_mesh_stats_multi(objects, objects_len, totelem_old, totelem_old_sel); @@ -695,10 +699,11 @@ void MESH_OT_delete_loose(wmOperatorType *ot) static int edbm_collapse_edge_exec(bContext *C, wmOperator *op) { + const Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); uint objects_len = 0; Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data( - view_layer, CTX_wm_view3d(C), &objects_len); + scene, view_layer, CTX_wm_view3d(C), &objects_len); for (uint ob_index = 0; ob_index < objects_len; ob_index++) { Object *obedit = objects[ob_index]; BMEditMesh *em = BKE_editmesh_from_object(obedit); @@ -928,10 +933,11 @@ static int edbm_add_edge_face_exec(bContext *C, wmOperator *op) { /* When this is used to dissolve we could avoid this, but checking isn't too slow. */ bool changed_multi = false; + const Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); uint objects_len = 0; Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data( - view_layer, CTX_wm_view3d(C), &objects_len); + scene, view_layer, CTX_wm_view3d(C), &objects_len); for (uint ob_index = 0; ob_index < objects_len; ob_index++) { Object *obedit = objects[ob_index]; BMEditMesh *em = BKE_editmesh_from_object(obedit); @@ -1049,7 +1055,7 @@ static int edbm_mark_seam_exec(bContext *C, wmOperator *op) uint objects_len = 0; Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data( - view_layer, CTX_wm_view3d(C), &objects_len); + scene, view_layer, CTX_wm_view3d(C), &objects_len); for (uint ob_index = 0; ob_index < objects_len; ob_index++) { Object *obedit = objects[ob_index]; BMEditMesh *em = BKE_editmesh_from_object(obedit); @@ -1129,11 +1135,12 @@ static int edbm_mark_sharp_exec(bContext *C, wmOperator *op) BMIter iter; const bool clear = RNA_boolean_get(op->ptr, "clear"); const bool use_verts = RNA_boolean_get(op->ptr, "use_verts"); + const Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); uint objects_len = 0; Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data( - view_layer, CTX_wm_view3d(C), &objects_len); + scene, view_layer, CTX_wm_view3d(C), &objects_len); for (uint ob_index = 0; ob_index < objects_len; ob_index++) { Object *obedit = objects[ob_index]; BMEditMesh *em = BKE_editmesh_from_object(obedit); @@ -1312,11 +1319,12 @@ static bool edbm_connect_vert_pair(BMEditMesh *em, struct Mesh *me, wmOperator * static int edbm_vert_connect_exec(bContext *C, wmOperator *op) { + const Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); uint objects_len = 0; uint failed_objects_len = 0; Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data( - view_layer, CTX_wm_view3d(C), &objects_len); + scene, view_layer, CTX_wm_view3d(C), &objects_len); for (uint ob_index = 0; ob_index < objects_len; ob_index++) { Object *obedit = objects[ob_index]; @@ -1559,12 +1567,13 @@ static bool bm_vert_connect_select_history_edge_to_vert_path(BMesh *bm, ListBase static int edbm_vert_connect_path_exec(bContext *C, wmOperator *op) { + const Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); uint objects_len = 0; uint failed_selection_order_len = 0; uint failed_connect_len = 0; Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data( - view_layer, CTX_wm_view3d(C), &objects_len); + scene, view_layer, CTX_wm_view3d(C), &objects_len); for (uint ob_index = 0; ob_index < objects_len; ob_index++) { Object *obedit = objects[ob_index]; @@ -1655,10 +1664,11 @@ void MESH_OT_vert_connect_path(wmOperatorType *ot) static int edbm_vert_connect_concave_exec(bContext *C, wmOperator *op) { + const Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); uint objects_len = 0; Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data( - view_layer, CTX_wm_view3d(C), &objects_len); + scene, view_layer, CTX_wm_view3d(C), &objects_len); for (uint ob_index = 0; ob_index < objects_len; ob_index++) { Object *obedit = objects[ob_index]; BMEditMesh *em = BKE_editmesh_from_object(obedit); @@ -1706,11 +1716,12 @@ void MESH_OT_vert_connect_concave(wmOperatorType *ot) static int edbm_vert_connect_nonplaner_exec(bContext *C, wmOperator *op) { + const Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); const float angle_limit = RNA_float_get(op->ptr, "angle_limit"); uint objects_len = 0; Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data( - view_layer, CTX_wm_view3d(C), &objects_len); + scene, view_layer, CTX_wm_view3d(C), &objects_len); for (uint ob_index = 0; ob_index < objects_len; ob_index++) { Object *obedit = objects[ob_index]; @@ -1780,10 +1791,11 @@ void MESH_OT_vert_connect_nonplanar(wmOperatorType *ot) static int edbm_face_make_planar_exec(bContext *C, wmOperator *op) { + const Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); uint objects_len = 0; Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data( - view_layer, CTX_wm_view3d(C), &objects_len); + scene, view_layer, CTX_wm_view3d(C), &objects_len); const int repeat = RNA_int_get(op->ptr, "repeat"); const float fac = RNA_float_get(op->ptr, "factor"); @@ -1947,10 +1959,11 @@ static int edbm_edge_split_exec(bContext *C, wmOperator *op) { const int type = RNA_enum_get(op->ptr, "type"); + const Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); uint objects_len = 0; Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data( - view_layer, CTX_wm_view3d(C), &objects_len); + scene, view_layer, CTX_wm_view3d(C), &objects_len); for (uint ob_index = 0; ob_index < objects_len; ob_index++) { Object *obedit = objects[ob_index]; BMEditMesh *em = BKE_editmesh_from_object(obedit); @@ -2012,10 +2025,11 @@ void MESH_OT_edge_split(wmOperatorType *ot) static int edbm_duplicate_exec(bContext *C, wmOperator *op) { + const Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); uint objects_len = 0; Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data( - view_layer, CTX_wm_view3d(C), &objects_len); + scene, view_layer, CTX_wm_view3d(C), &objects_len); bool changed = false; for (uint ob_index = 0; ob_index < objects_len; ob_index++) { @@ -2243,10 +2257,11 @@ static int edbm_flip_normals_exec(bContext *C, wmOperator *op) { const bool only_clnors = RNA_boolean_get(op->ptr, "only_clnors"); + const Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); uint objects_len = 0; Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data( - view_layer, CTX_wm_view3d(C), &objects_len); + scene, view_layer, CTX_wm_view3d(C), &objects_len); for (uint ob_index = 0; ob_index < objects_len; ob_index++) { Object *obedit = objects[ob_index]; @@ -2309,10 +2324,11 @@ static int edbm_edge_rotate_selected_exec(bContext *C, wmOperator *op) int tot_failed_all = 0; bool no_selected_edges = true, invalid_selected_edges = true; + const Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); uint objects_len = 0; Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data( - view_layer, CTX_wm_view3d(C), &objects_len); + scene, view_layer, CTX_wm_view3d(C), &objects_len); for (uint ob_index = 0; ob_index < objects_len; ob_index++) { Object *obedit = objects[ob_index]; BMEditMesh *em = BKE_editmesh_from_object(obedit); @@ -2435,12 +2451,13 @@ void MESH_OT_edge_rotate(wmOperatorType *ot) static int edbm_hide_exec(bContext *C, wmOperator *op) { const bool unselected = RNA_boolean_get(op->ptr, "unselected"); + const Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); bool changed = false; uint objects_len = 0; Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data( - view_layer, CTX_wm_view3d(C), &objects_len); + scene, view_layer, CTX_wm_view3d(C), &objects_len); for (uint ob_index = 0; ob_index < objects_len; ob_index++) { Object *obedit = objects[ob_index]; BMEditMesh *em = BKE_editmesh_from_object(obedit); @@ -2516,11 +2533,12 @@ void MESH_OT_hide(wmOperatorType *ot) static int edbm_reveal_exec(bContext *C, wmOperator *op) { const bool select = RNA_boolean_get(op->ptr, "select"); + const Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); uint objects_len = 0; Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data( - view_layer, CTX_wm_view3d(C), &objects_len); + scene, view_layer, CTX_wm_view3d(C), &objects_len); for (uint ob_index = 0; ob_index < objects_len; ob_index++) { Object *obedit = objects[ob_index]; BMEditMesh *em = BKE_editmesh_from_object(obedit); @@ -2564,12 +2582,13 @@ void MESH_OT_reveal(wmOperatorType *ot) static int edbm_normals_make_consistent_exec(bContext *C, wmOperator *op) { + const Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); const bool inside = RNA_boolean_get(op->ptr, "inside"); uint objects_len = 0; Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data( - view_layer, CTX_wm_view3d(C), &objects_len); + scene, view_layer, CTX_wm_view3d(C), &objects_len); for (uint ob_index = 0; ob_index < objects_len; ob_index++) { Object *obedit = objects[ob_index]; BMEditMesh *em = BKE_editmesh_from_object(obedit); @@ -2645,10 +2664,11 @@ static int edbm_do_smooth_vertex_exec(bContext *C, wmOperator *op) repeat = 1; } + const Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); uint objects_len = 0; Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data( - view_layer, CTX_wm_view3d(C), &objects_len); + scene, view_layer, CTX_wm_view3d(C), &objects_len); for (uint ob_index = 0; ob_index < objects_len; ob_index++) { Object *obedit = objects[ob_index]; Mesh *me = obedit->data; @@ -2764,6 +2784,7 @@ void MESH_OT_vertices_smooth(wmOperatorType *ot) static int edbm_do_smooth_laplacian_vertex_exec(bContext *C, wmOperator *op) { int tot_unselected = 0; + const Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); const float lambda_factor = RNA_float_get(op->ptr, "lambda_factor"); @@ -2780,7 +2801,7 @@ static int edbm_do_smooth_laplacian_vertex_exec(bContext *C, wmOperator *op) uint objects_len = 0; Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data( - view_layer, CTX_wm_view3d(C), &objects_len); + scene, view_layer, CTX_wm_view3d(C), &objects_len); for (uint ob_index = 0; ob_index < objects_len; ob_index++) { Object *obedit = objects[ob_index]; BMEditMesh *em = BKE_editmesh_from_object(obedit); @@ -2905,10 +2926,11 @@ static void mesh_set_smooth_faces(BMEditMesh *em, short smooth) static int edbm_faces_shade_smooth_exec(bContext *C, wmOperator *UNUSED(op)) { + const Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); uint objects_len = 0; Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data( - view_layer, CTX_wm_view3d(C), &objects_len); + scene, view_layer, CTX_wm_view3d(C), &objects_len); for (uint ob_index = 0; ob_index < objects_len; ob_index++) { Object *obedit = objects[ob_index]; BMEditMesh *em = BKE_editmesh_from_object(obedit); @@ -2953,10 +2975,11 @@ void MESH_OT_faces_shade_smooth(wmOperatorType *ot) static int edbm_faces_shade_flat_exec(bContext *C, wmOperator *UNUSED(op)) { + const Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); uint objects_len = 0; Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data( - view_layer, CTX_wm_view3d(C), &objects_len); + scene, view_layer, CTX_wm_view3d(C), &objects_len); for (uint ob_index = 0; ob_index < objects_len; ob_index++) { Object *obedit = objects[ob_index]; BMEditMesh *em = BKE_editmesh_from_object(obedit); @@ -3004,10 +3027,11 @@ static int edbm_rotate_uvs_exec(bContext *C, wmOperator *op) /* get the direction from RNA */ const bool use_ccw = RNA_boolean_get(op->ptr, "use_ccw"); + const Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); uint objects_len = 0; Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data( - view_layer, CTX_wm_view3d(C), &objects_len); + scene, view_layer, CTX_wm_view3d(C), &objects_len); for (uint ob_index = 0; ob_index < objects_len; ob_index++) { Object *obedit = objects[ob_index]; BMEditMesh *em = BKE_editmesh_from_object(obedit); @@ -3040,10 +3064,11 @@ static int edbm_rotate_uvs_exec(bContext *C, wmOperator *op) static int edbm_reverse_uvs_exec(bContext *C, wmOperator *op) { + const Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); uint objects_len = 0; Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data( - view_layer, CTX_wm_view3d(C), &objects_len); + scene, view_layer, CTX_wm_view3d(C), &objects_len); for (uint ob_index = 0; ob_index < objects_len; ob_index++) { Object *obedit = objects[ob_index]; BMEditMesh *em = BKE_editmesh_from_object(obedit); @@ -3078,10 +3103,11 @@ static int edbm_rotate_colors_exec(bContext *C, wmOperator *op) /* get the direction from RNA */ const bool use_ccw = RNA_boolean_get(op->ptr, "use_ccw"); + const Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); uint objects_len = 0; Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data( - view_layer, CTX_wm_view3d(C), &objects_len); + scene, view_layer, CTX_wm_view3d(C), &objects_len); for (uint ob_index = 0; ob_index < objects_len; ob_index++) { Object *ob = objects[ob_index]; @@ -3131,10 +3157,11 @@ static int edbm_rotate_colors_exec(bContext *C, wmOperator *op) static int edbm_reverse_colors_exec(bContext *C, wmOperator *op) { + const Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); uint objects_len = 0; Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data( - view_layer, CTX_wm_view3d(C), &objects_len); + scene, view_layer, CTX_wm_view3d(C), &objects_len); for (uint ob_index = 0; ob_index < objects_len; ob_index++) { Object *obedit = objects[ob_index]; @@ -3376,7 +3403,7 @@ static int edbm_merge_exec(bContext *C, wmOperator *op) ViewLayer *view_layer = CTX_data_view_layer(C); uint objects_len = 0; Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data( - view_layer, CTX_wm_view3d(C), &objects_len); + scene, view_layer, CTX_wm_view3d(C), &objects_len); const int type = RNA_enum_get(op->ptr, "type"); const bool uvs = RNA_boolean_get(op->ptr, "uvs"); @@ -3540,10 +3567,11 @@ static int edbm_remove_doubles_exec(bContext *C, wmOperator *op) int count_multi = 0; + const Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); uint objects_len = 0; Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data( - view_layer, CTX_wm_view3d(C), &objects_len); + scene, view_layer, CTX_wm_view3d(C), &objects_len); for (uint ob_index = 0; ob_index < objects_len; ob_index++) { Object *obedit = objects[ob_index]; @@ -3686,13 +3714,14 @@ static bool shape_propagate(BMEditMesh *em) static int edbm_shape_propagate_to_all_exec(bContext *C, wmOperator *op) { + const Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); int tot_shapekeys = 0; int tot_selected_verts_objects = 0; uint objects_len = 0; Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data( - view_layer, CTX_wm_view3d(C), &objects_len); + scene, view_layer, CTX_wm_view3d(C), &objects_len); for (uint ob_index = 0; ob_index < objects_len; ob_index++) { Object *obedit = objects[ob_index]; Mesh *me = obedit->data; @@ -3759,6 +3788,7 @@ static int edbm_blend_from_shape_exec(bContext *C, wmOperator *op) BMEditMesh *em_ref = me_ref->edit_mesh; BMVert *eve; BMIter iter; + const Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); float co[3], *sco; int totshape_ref = 0; @@ -3787,7 +3817,7 @@ static int edbm_blend_from_shape_exec(bContext *C, wmOperator *op) int tot_selected_verts_objects = 0; uint objects_len = 0; Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data( - view_layer, CTX_wm_view3d(C), &objects_len); + scene, view_layer, CTX_wm_view3d(C), &objects_len); for (uint ob_index = 0; ob_index < objects_len; ob_index++) { Object *obedit = objects[ob_index]; Mesh *me = obedit->data; @@ -3938,10 +3968,11 @@ static int edbm_solidify_exec(bContext *C, wmOperator *op) { const float thickness = RNA_float_get(op->ptr, "thickness"); + const Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); uint objects_len = 0; Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data( - view_layer, CTX_wm_view3d(C), &objects_len); + scene, view_layer, CTX_wm_view3d(C), &objects_len); for (uint ob_index = 0; ob_index < objects_len; ob_index++) { Object *obedit = objects[ob_index]; BMEditMesh *em = BKE_editmesh_from_object(obedit); @@ -4686,7 +4717,7 @@ static int edbm_separate_exec(bContext *C, wmOperator *op) uint bases_len = 0; uint empty_selection_len = 0; Base **bases = BKE_view_layer_array_from_bases_in_edit_mode_unique_data( - view_layer, CTX_wm_view3d(C), &bases_len); + scene, view_layer, CTX_wm_view3d(C), &bases_len); for (uint bs_index = 0; bs_index < bases_len; bs_index++) { Base *base = bases[bs_index]; BMEditMesh *em = BKE_editmesh_from_object(base->object); @@ -4835,10 +4866,11 @@ static int edbm_fill_exec(bContext *C, wmOperator *op) bool has_selected_edges = false, has_faces_filled = false; + const Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); uint objects_len = 0; Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data( - view_layer, CTX_wm_view3d(C), &objects_len); + scene, view_layer, CTX_wm_view3d(C), &objects_len); for (uint ob_index = 0; ob_index < objects_len; ob_index++) { Object *obedit = objects[ob_index]; BMEditMesh *em = BKE_editmesh_from_object(obedit); @@ -5090,10 +5122,11 @@ static int edbm_fill_grid_exec(bContext *C, wmOperator *op) { const bool use_interp_simple = RNA_boolean_get(op->ptr, "use_interp_simple"); + const Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); uint objects_len = 0; Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data( - view_layer, CTX_wm_view3d(C), &objects_len); + scene, view_layer, CTX_wm_view3d(C), &objects_len); for (uint ob_index = 0; ob_index < objects_len; ob_index++) { Object *obedit = objects[ob_index]; @@ -5231,10 +5264,11 @@ static int edbm_fill_holes_exec(bContext *C, wmOperator *op) { const int sides = RNA_int_get(op->ptr, "sides"); + const Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); uint objects_len = 0; Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data( - view_layer, CTX_wm_view3d(C), &objects_len); + scene, view_layer, CTX_wm_view3d(C), &objects_len); for (uint ob_index = 0; ob_index < objects_len; ob_index++) { Object *obedit = objects[ob_index]; @@ -5294,10 +5328,11 @@ void MESH_OT_fill_holes(wmOperatorType *ot) static int edbm_beautify_fill_exec(bContext *C, wmOperator *op) { + const Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); uint objects_len = 0; Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data( - view_layer, CTX_wm_view3d(C), &objects_len); + scene, view_layer, CTX_wm_view3d(C), &objects_len); const float angle_max = M_PI; const float angle_limit = RNA_float_get(op->ptr, "angle_limit"); @@ -5392,10 +5427,11 @@ static int edbm_poke_face_exec(bContext *C, wmOperator *op) const bool use_relative_offset = RNA_boolean_get(op->ptr, "use_relative_offset"); const int center_mode = RNA_enum_get(op->ptr, "center_mode"); + const Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); uint objects_len = 0; Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data( - view_layer, CTX_wm_view3d(C), &objects_len); + scene, view_layer, CTX_wm_view3d(C), &objects_len); for (uint ob_index = 0; ob_index < objects_len; ob_index++) { Object *obedit = objects[ob_index]; BMEditMesh *em = BKE_editmesh_from_object(obedit); @@ -5488,11 +5524,12 @@ static int edbm_quads_convert_to_tris_exec(bContext *C, wmOperator *op) { const int quad_method = RNA_enum_get(op->ptr, "quad_method"); const int ngon_method = RNA_enum_get(op->ptr, "ngon_method"); + const Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); uint objects_len = 0; Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data( - view_layer, CTX_wm_view3d(C), &objects_len); + scene, view_layer, CTX_wm_view3d(C), &objects_len); for (uint ob_index = 0; ob_index < objects_len; ob_index++) { Object *obedit = objects[ob_index]; BMEditMesh *em = BKE_editmesh_from_object(obedit); @@ -5582,11 +5619,12 @@ void MESH_OT_quads_convert_to_tris(wmOperatorType *ot) static int edbm_tris_convert_to_quads_exec(bContext *C, wmOperator *op) { + const Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); uint objects_len = 0; Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data( - view_layer, CTX_wm_view3d(C), &objects_len); + scene, view_layer, CTX_wm_view3d(C), &objects_len); const bool do_seam = RNA_boolean_get(op->ptr, "seam"); const bool do_sharp = RNA_boolean_get(op->ptr, "sharp"); @@ -5743,10 +5781,11 @@ static int edbm_decimate_exec(bContext *C, wmOperator *op) return OPERATOR_FINISHED; } + const Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); uint objects_len = 0; Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data( - view_layer, CTX_wm_view3d(C), &objects_len); + scene, view_layer, CTX_wm_view3d(C), &objects_len); for (uint ob_index = 0; ob_index < objects_len; ob_index++) { Object *obedit = objects[ob_index]; @@ -5960,10 +5999,11 @@ static int edbm_dissolve_verts_exec(bContext *C, wmOperator *op) const bool use_face_split = RNA_boolean_get(op->ptr, "use_face_split"); const bool use_boundary_tear = RNA_boolean_get(op->ptr, "use_boundary_tear"); + const Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); uint objects_len = 0; Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data( - view_layer, CTX_wm_view3d(C), &objects_len); + scene, view_layer, CTX_wm_view3d(C), &objects_len); for (uint ob_index = 0; ob_index < objects_len; ob_index++) { Object *obedit = objects[ob_index]; @@ -6027,10 +6067,11 @@ static int edbm_dissolve_edges_exec(bContext *C, wmOperator *op) const bool use_verts = RNA_boolean_get(op->ptr, "use_verts"); const bool use_face_split = RNA_boolean_get(op->ptr, "use_face_split"); + const Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); uint objects_len = 0; Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data( - view_layer, CTX_wm_view3d(C), &objects_len); + scene, view_layer, CTX_wm_view3d(C), &objects_len); for (uint ob_index = 0; ob_index < objects_len; ob_index++) { Object *obedit = objects[ob_index]; BMEditMesh *em = BKE_editmesh_from_object(obedit); @@ -6092,10 +6133,11 @@ void MESH_OT_dissolve_edges(wmOperatorType *ot) static int edbm_dissolve_faces_exec(bContext *C, wmOperator *op) { const bool use_verts = RNA_boolean_get(op->ptr, "use_verts"); + const Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); uint objects_len = 0; Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data( - view_layer, CTX_wm_view3d(C), &objects_len); + scene, view_layer, CTX_wm_view3d(C), &objects_len); for (uint ob_index = 0; ob_index < objects_len; ob_index++) { Object *obedit = objects[ob_index]; BMEditMesh *em = BKE_editmesh_from_object(obedit); @@ -6208,10 +6250,11 @@ static int edbm_dissolve_limited_exec(bContext *C, wmOperator *op) const int delimit = RNA_enum_get(op->ptr, "delimit"); char dissolve_flag; + const Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); uint objects_len = 0; Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data( - view_layer, CTX_wm_view3d(C), &objects_len); + scene, view_layer, CTX_wm_view3d(C), &objects_len); for (uint ob_index = 0; ob_index < objects_len; ob_index++) { Object *obedit = objects[ob_index]; BMEditMesh *em = BKE_editmesh_from_object(obedit); @@ -6329,13 +6372,14 @@ void MESH_OT_dissolve_limited(wmOperatorType *ot) static int edbm_dissolve_degenerate_exec(bContext *C, wmOperator *op) { + const Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); int totelem_old[3] = {0, 0, 0}; int totelem_new[3] = {0, 0, 0}; uint objects_len = 0; Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data( - view_layer, CTX_wm_view3d(C), &objects_len); + scene, view_layer, CTX_wm_view3d(C), &objects_len); for (uint ob_index = 0; ob_index < objects_len; ob_index++) { Object *obedit = objects[ob_index]; @@ -6413,11 +6457,12 @@ void MESH_OT_dissolve_degenerate(wmOperatorType *ot) static int edbm_delete_edgeloop_exec(bContext *C, wmOperator *op) { const bool use_face_split = RNA_boolean_get(op->ptr, "use_face_split"); + const Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); uint objects_len = 0; Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data( - view_layer, CTX_wm_view3d(C), &objects_len); + scene, view_layer, CTX_wm_view3d(C), &objects_len); for (uint ob_index = 0; ob_index < objects_len; ob_index++) { Object *obedit = objects[ob_index]; BMEditMesh *em = BKE_editmesh_from_object(obedit); @@ -6497,10 +6542,11 @@ void MESH_OT_delete_edgeloop(wmOperatorType *ot) static int edbm_split_exec(bContext *C, wmOperator *op) { + const Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); uint objects_len = 0; Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data( - view_layer, CTX_wm_view3d(C), &objects_len); + scene, view_layer, CTX_wm_view3d(C), &objects_len); for (uint ob_index = 0; ob_index < objects_len; ob_index++) { Object *obedit = objects[ob_index]; BMEditMesh *em = BKE_editmesh_from_object(obedit); @@ -7092,7 +7138,7 @@ static int edbm_sort_elements_exec(bContext *C, wmOperator *op) uint objects_len = 0; Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data( - view_layer, CTX_wm_view3d(C), &objects_len); + scene, view_layer, CTX_wm_view3d(C), &objects_len); for (uint ob_index = 0; ob_index < objects_len; ob_index++) { Object *ob = objects[ob_index]; @@ -7396,11 +7442,12 @@ static int edbm_bridge_edge_loops_exec(bContext *C, wmOperator *op) const bool use_merge = RNA_boolean_get(op->ptr, "use_merge"); const float merge_factor = RNA_float_get(op->ptr, "merge_factor"); const int twist_offset = RNA_int_get(op->ptr, "twist_offset"); + const Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); uint objects_len = 0; Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data( - view_layer, CTX_wm_view3d(C), &objects_len); + scene, view_layer, CTX_wm_view3d(C), &objects_len); for (uint ob_index = 0; ob_index < objects_len; ob_index++) { Object *obedit = objects[ob_index]; BMEditMesh *em = BKE_editmesh_from_object(obedit); @@ -7476,10 +7523,11 @@ static int edbm_wireframe_exec(bContext *C, wmOperator *op) const float thickness = RNA_float_get(op->ptr, "thickness"); const float offset = RNA_float_get(op->ptr, "offset"); + const Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); uint objects_len = 0; Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data( - view_layer, CTX_wm_view3d(C), &objects_len); + scene, view_layer, CTX_wm_view3d(C), &objects_len); for (uint ob_index = 0; ob_index < objects_len; ob_index++) { Object *obedit = objects[ob_index]; BMEditMesh *em = BKE_editmesh_from_object(obedit); @@ -7587,7 +7635,7 @@ static int edbm_offset_edgeloop_exec(bContext *C, wmOperator *op) ViewLayer *view_layer = CTX_data_view_layer(C); uint bases_len = 0; Base **bases = BKE_view_layer_array_from_bases_in_edit_mode_unique_data( - view_layer, CTX_wm_view3d(C), &bases_len); + scene, view_layer, CTX_wm_view3d(C), &bases_len); for (uint base_index = 0; base_index < bases_len; base_index++) { Object *obedit = bases[base_index]->object; BMEditMesh *em = BKE_editmesh_from_object(obedit); @@ -7676,10 +7724,11 @@ static int edbm_convex_hull_exec(bContext *C, wmOperator *op) float angle_face_threshold = RNA_float_get(op->ptr, "face_threshold"); float angle_shape_threshold = RNA_float_get(op->ptr, "shape_threshold"); + const Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); uint objects_len = 0; Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data( - view_layer, CTX_wm_view3d(C), &objects_len); + scene, view_layer, CTX_wm_view3d(C), &objects_len); for (uint ob_index = 0; ob_index < objects_len; ob_index++) { Object *obedit = objects[ob_index]; BMEditMesh *em = BKE_editmesh_from_object(obedit); @@ -7809,10 +7858,11 @@ void MESH_OT_convex_hull(wmOperatorType *ot) static int mesh_symmetrize_exec(bContext *C, wmOperator *op) { const float thresh = RNA_float_get(op->ptr, "threshold"); + const Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); uint objects_len = 0; Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data( - view_layer, CTX_wm_view3d(C), &objects_len); + scene, view_layer, CTX_wm_view3d(C), &objects_len); for (uint ob_index = 0; ob_index < objects_len; ob_index++) { Object *obedit = objects[ob_index]; @@ -7908,10 +7958,11 @@ static int mesh_symmetry_snap_exec(bContext *C, wmOperator *op) int axis = axis_dir % 3; bool axis_sign = axis != axis_dir; + const Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); uint objects_len = 0; Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data( - view_layer, CTX_wm_view3d(C), &objects_len); + scene, view_layer, CTX_wm_view3d(C), &objects_len); for (uint ob_index = 0; ob_index < objects_len; ob_index++) { Object *obedit = objects[ob_index]; @@ -8074,11 +8125,12 @@ static int edbm_mark_freestyle_edge_exec(bContext *C, wmOperator *op) BMIter iter; FreestyleEdge *fed; const bool clear = RNA_boolean_get(op->ptr, "clear"); + const Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); uint objects_len = 0; Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data( - view_layer, CTX_wm_view3d(C), &objects_len); + scene, view_layer, CTX_wm_view3d(C), &objects_len); for (uint ob_index = 0; ob_index < objects_len; ob_index++) { Object *obedit = objects[ob_index]; BMEditMesh *em = BKE_editmesh_from_object(obedit); @@ -8154,11 +8206,12 @@ static int edbm_mark_freestyle_face_exec(bContext *C, wmOperator *op) BMIter iter; FreestyleFace *ffa; const bool clear = RNA_boolean_get(op->ptr, "clear"); + const Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); uint objects_len = 0; Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data( - view_layer, CTX_wm_view3d(C), &objects_len); + scene, view_layer, CTX_wm_view3d(C), &objects_len); for (uint ob_index = 0; ob_index < objects_len; ob_index++) { Object *obedit = objects[ob_index]; BMEditMesh *em = BKE_editmesh_from_object(obedit); @@ -8952,10 +9005,11 @@ static void normals_split(BMesh *bm) static int normals_split_merge(bContext *C, const bool do_merge) { + const Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); uint objects_len = 0; Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data( - view_layer, CTX_wm_view3d(C), &objects_len); + scene, view_layer, CTX_wm_view3d(C), &objects_len); for (uint ob_index = 0; ob_index < objects_len; ob_index++) { Object *obedit = objects[ob_index]; @@ -9081,10 +9135,11 @@ static EnumPropertyItem average_method_items[] = { static int edbm_average_normals_exec(bContext *C, wmOperator *op) { + const Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); uint objects_len = 0; Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data( - view_layer, CTX_wm_view3d(C), &objects_len); + scene, view_layer, CTX_wm_view3d(C), &objects_len); const int average_type = RNA_enum_get(op->ptr, "average_type"); const float absweight = (float)RNA_int_get(op->ptr, "weight"); const float threshold = RNA_float_get(op->ptr, "threshold"); @@ -9332,7 +9387,7 @@ static int edbm_normals_tools_exec(bContext *C, wmOperator *op) ViewLayer *view_layer = CTX_data_view_layer(C); uint objects_len = 0; Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data( - view_layer, CTX_wm_view3d(C), &objects_len); + scene, view_layer, CTX_wm_view3d(C), &objects_len); const int mode = RNA_enum_get(op->ptr, "mode"); const bool absolute = RNA_boolean_get(op->ptr, "absolute"); float *normal_vector = scene->toolsettings->normal_vector; @@ -9547,10 +9602,11 @@ void MESH_OT_normals_tools(struct wmOperatorType *ot) static int edbm_set_normals_from_faces_exec(bContext *C, wmOperator *op) { + const Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); uint objects_len = 0; Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data( - view_layer, CTX_wm_view3d(C), &objects_len); + scene, view_layer, CTX_wm_view3d(C), &objects_len); for (uint ob_index = 0; ob_index < objects_len; ob_index++) { Object *obedit = objects[ob_index]; @@ -9662,10 +9718,11 @@ void MESH_OT_set_normals_from_faces(struct wmOperatorType *ot) static int edbm_smooth_normals_exec(bContext *C, wmOperator *op) { + const Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); uint objects_len = 0; Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data( - view_layer, CTX_wm_view3d(C), &objects_len); + scene, view_layer, CTX_wm_view3d(C), &objects_len); for (uint ob_index = 0; ob_index < objects_len; ob_index++) { Object *obedit = objects[ob_index]; @@ -9783,10 +9840,11 @@ void MESH_OT_smooth_normals(struct wmOperatorType *ot) static int edbm_mod_weighted_strength_exec(bContext *C, wmOperator *op) { + const Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); uint objects_len = 0; Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data( - view_layer, CTX_wm_view3d(C), &objects_len); + scene, view_layer, CTX_wm_view3d(C), &objects_len); for (uint ob_index = 0; ob_index < objects_len; ob_index++) { Object *obedit = objects[ob_index]; diff --git a/source/blender/editors/mesh/editmesh_undo.c b/source/blender/editors/mesh/editmesh_undo.c index af8084e16c4..44fab751de2 100644 --- a/source/blender/editors/mesh/editmesh_undo.c +++ b/source/blender/editors/mesh/editmesh_undo.c @@ -361,8 +361,6 @@ static void um_arraystore_compact_ex(UndoMesh *um, const UndoMesh *um_ref, bool if (create) { um_arraystore.users += 1; } - - BKE_mesh_update_customdata_pointers(me, false); } /** @@ -465,9 +463,6 @@ static void um_arraystore_expand(UndoMesh *um) BLI_assert(me->totselect == (state_len / stride)); UNUSED_VARS_NDEBUG(stride); } - - /* not essential, but prevents accidental dangling pointer access */ - BKE_mesh_update_customdata_pointers(me, false); } static void um_arraystore_free(UndoMesh *um) @@ -735,8 +730,10 @@ static void undomesh_free_data(UndoMesh *um) static Object *editmesh_object_from_context(bContext *C) { + Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); - Object *obedit = OBEDIT_FROM_VIEW_LAYER(view_layer); + BKE_view_layer_synced_ensure(scene, view_layer); + Object *obedit = BKE_view_layer_edit_object_get(view_layer); if (obedit && obedit->type == OB_MESH) { Mesh *me = obedit->data; if (me->edit_mesh != NULL) { @@ -776,10 +773,11 @@ static bool mesh_undosys_step_encode(struct bContext *C, struct Main *bmain, Und /* Important not to use the 3D view when getting objects because all objects * outside of this list will be moved out of edit-mode when reading back undo steps. */ + const Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); ToolSettings *ts = CTX_data_tool_settings(C); uint objects_len = 0; - Object **objects = ED_undo_editmode_objects_from_view_layer(view_layer, &objects_len); + Object **objects = ED_undo_editmode_objects_from_view_layer(scene, view_layer, &objects_len); us->elems = MEM_callocN(sizeof(*us->elems) * objects_len, __func__); us->elems_len = objects_len; diff --git a/source/blender/editors/mesh/editmesh_utils.c b/source/blender/editors/mesh/editmesh_utils.c index e931dd02a9e..5c8ff930eb8 100644 --- a/source/blender/editors/mesh/editmesh_utils.c +++ b/source/blender/editors/mesh/editmesh_utils.c @@ -593,10 +593,10 @@ UvMapVert *BM_uv_vert_map_at_index(UvVertMap *vmap, uint v) return vmap->vert[v]; } -static void bm_uv_ensure_head_table(UvElementMap *element_map) +struct UvElement **BM_uv_element_map_ensure_head_table(struct UvElementMap *element_map) { if (element_map->head_table) { - return; + return element_map->head_table; } /* For each UvElement, locate the "separate" UvElement that precedes it in the linked list. */ @@ -616,6 +616,7 @@ static void bm_uv_ensure_head_table(UvElementMap *element_map) } } } + return element_map->head_table; } #define INVALID_ISLAND ((unsigned int)-1) @@ -643,9 +644,9 @@ static int bm_uv_edge_select_build_islands(UvElementMap *element_map, UvElement *islandbuf, uint *map, bool uv_selected, - int cd_loop_uv_offset) + const int cd_loop_uv_offset) { - bm_uv_ensure_head_table(element_map); + BM_uv_element_map_ensure_head_table(element_map); int total_uvs = element_map->total_uvs; @@ -850,10 +851,99 @@ static void bm_uv_build_islands(UvElementMap *element_map, MEM_SAFE_FREE(map); } +/* return true if `loop` has UV co-ordinates which match `luv_a` and `luv_b` */ +static bool loop_uv_match(BMLoop *loop, MLoopUV *luv_a, MLoopUV *luv_b, int cd_loop_uv_offset) +{ + MLoopUV *luv_c = BM_ELEM_CD_GET_VOID_P(loop, cd_loop_uv_offset); + MLoopUV *luv_d = BM_ELEM_CD_GET_VOID_P(loop->next, cd_loop_uv_offset); + return compare_v2v2(luv_a->uv, luv_c->uv, STD_UV_CONNECT_LIMIT) && + compare_v2v2(luv_b->uv, luv_d->uv, STD_UV_CONNECT_LIMIT); +} + +/* Given `anchor` and `edge`, return true if there are edges that fan between them that are + * seam-free. */ +static bool seam_connected_recursive(BMVert *anchor, + BMEdge *edge, + MLoopUV *luv_anchor, + MLoopUV *luv_fan, + BMLoop *needle, + GSet *visited, + int cd_loop_uv_offset) +{ + BLI_assert(edge->v1 == anchor || edge->v2 == anchor); + BLI_assert(needle->v == anchor || needle->next->v == anchor); + + if (BM_elem_flag_test(edge, BM_ELEM_SEAM)) { + return false; /* Edge is a seam, don't traverse. */ + } + + if (!BLI_gset_add(visited, edge)) { + return false; /* Already visited. */ + } + + BMLoop *loop; + BMIter liter; + BM_ITER_ELEM (loop, &liter, edge, BM_LOOPS_OF_EDGE) { + if (loop->v == anchor) { + if (!loop_uv_match(loop, luv_anchor, luv_fan, cd_loop_uv_offset)) { + continue; /* `loop` is disjoint in UV space. */ + } + + if (loop->prev == needle) { + return true; /* Success. */ + } + + MLoopUV *luv_far = BM_ELEM_CD_GET_VOID_P(loop->prev, cd_loop_uv_offset); + if (seam_connected_recursive( + anchor, loop->prev->e, luv_anchor, luv_far, needle, visited, cd_loop_uv_offset)) { + return true; + } + } + else { + BLI_assert(loop->next->v == anchor); + if (!loop_uv_match(loop, luv_fan, luv_anchor, cd_loop_uv_offset)) { + continue; /* `loop` is disjoint in UV space. */ + } + + if (loop->next == needle) { + return true; /* Success. */ + } + + MLoopUV *luv_far = BM_ELEM_CD_GET_VOID_P(loop->next->next, cd_loop_uv_offset); + if (seam_connected_recursive( + anchor, loop->next->e, luv_anchor, luv_far, needle, visited, cd_loop_uv_offset)) { + return true; + } + } + } + + return false; +} + +/* Given `loop_a` and `loop_b` originate from the same vertex and share a UV, + * return true if there are edges that fan between them that are seam-free. + * return false otherwise. + */ +static bool seam_connected(BMLoop *loop_a, BMLoop *loop_b, GSet *visited, int cd_loop_uv_offset) +{ + BLI_assert(loop_a && loop_b); + BLI_assert(loop_a != loop_b); + BLI_assert(loop_a->v == loop_b->v); + + BLI_gset_clear(visited, NULL); + + MLoopUV *luv_anchor = BM_ELEM_CD_GET_VOID_P(loop_a, cd_loop_uv_offset); + MLoopUV *luv_fan = BM_ELEM_CD_GET_VOID_P(loop_a->next, cd_loop_uv_offset); + const bool result = seam_connected_recursive( + loop_a->v, loop_a->e, luv_anchor, luv_fan, loop_b, visited, cd_loop_uv_offset); + return result; +} + UvElementMap *BM_uv_element_map_create(BMesh *bm, const Scene *scene, const bool uv_selected, const bool use_winding, + const bool use_seams, const bool do_islands) { /* In uv sync selection, all UVs are visible. */ @@ -955,6 +1045,8 @@ UvElementMap *BM_uv_element_map_create(BMesh *bm, } BLI_buffer_free(&tf_uv_buf); + GSet *seam_visited_gset = use_seams ? BLI_gset_ptr_new(__func__) : NULL; + /* For each BMVert, sort associated linked list into unique uvs. */ int ev_index; BM_ITER_MESH_INDEX (ev, &iter, bm, BM_VERTS_OF_MESH, ev_index) { @@ -1000,6 +1092,10 @@ UvElementMap *BM_uv_element_map_create(BMesh *bm, winding[BM_elem_index_get(v->l->f)]; } + if (connected && use_seams) { + connected = seam_connected(iterv->l, v->l, seam_visited_gset, cd_loop_uv_offset); + } + if (connected) { if (lastv) { lastv->next = next; @@ -1025,6 +1121,10 @@ UvElementMap *BM_uv_element_map_create(BMesh *bm, element_map->vertex[ev_index] = newvlist; } + if (seam_visited_gset) { + BLI_gset_free(seam_visited_gset, NULL); + seam_visited_gset = NULL; + } MEM_SAFE_FREE(winding); /* at this point, every UvElement in vert points to a UvElement sharing the same vertex. @@ -1070,7 +1170,7 @@ void BM_uv_element_map_free(UvElementMap *element_map) } } -UvElement *BM_uv_element_get(UvElementMap *element_map, BMFace *efa, BMLoop *l) +UvElement *BM_uv_element_get(const UvElementMap *element_map, const BMFace *efa, const BMLoop *l) { UvElement *element = element_map->vertex[BM_elem_index_get(l->v)]; while (element) { @@ -1673,15 +1773,13 @@ BMElem *EDBM_elem_from_index_any(BMEditMesh *em, uint index) return NULL; } -int EDBM_elem_to_index_any_multi(ViewLayer *view_layer, - BMEditMesh *em, - BMElem *ele, - int *r_object_index) +int EDBM_elem_to_index_any_multi( + const Scene *scene, ViewLayer *view_layer, BMEditMesh *em, BMElem *ele, int *r_object_index) { uint bases_len; int elem_index = -1; *r_object_index = -1; - Base **bases = BKE_view_layer_array_from_bases_in_edit_mode(view_layer, NULL, &bases_len); + Base **bases = BKE_view_layer_array_from_bases_in_edit_mode(scene, view_layer, NULL, &bases_len); for (uint base_index = 0; base_index < bases_len; base_index++) { Base *base_iter = bases[base_index]; if (BKE_editmesh_from_object(base_iter->object) == em) { @@ -1694,13 +1792,14 @@ int EDBM_elem_to_index_any_multi(ViewLayer *view_layer, return elem_index; } -BMElem *EDBM_elem_from_index_any_multi(ViewLayer *view_layer, +BMElem *EDBM_elem_from_index_any_multi(const Scene *scene, + ViewLayer *view_layer, uint object_index, uint elem_index, Object **r_obedit) { uint bases_len; - Base **bases = BKE_view_layer_array_from_bases_in_edit_mode(view_layer, NULL, &bases_len); + Base **bases = BKE_view_layer_array_from_bases_in_edit_mode(scene, view_layer, NULL, &bases_len); *r_obedit = NULL; Object *obedit = (object_index < bases_len) ? bases[object_index]->object : NULL; MEM_freeN(bases); diff --git a/source/blender/editors/mesh/mesh_data.cc b/source/blender/editors/mesh/mesh_data.cc index 971fab1508e..dc3389844b8 100644 --- a/source/blender/editors/mesh/mesh_data.cc +++ b/source/blender/editors/mesh/mesh_data.cc @@ -18,6 +18,7 @@ #include "BLI_utildefines.h" #include "BKE_attribute.h" +#include "BKE_attribute.hh" #include "BKE_context.h" #include "BKE_customdata.h" #include "BKE_editmesh.h" @@ -44,6 +45,8 @@ #include "mesh_intern.h" /* own include */ using blender::Array; +using blender::MutableSpan; +using blender::Span; static CustomData *mesh_customdata_get_type(Mesh *me, const char htype, int *r_tot) { @@ -128,7 +131,6 @@ static void delete_customdata_layer(Mesh *me, CustomDataLayer *layer) } else { CustomData_free_layer(data, type, tot, layer_index + n); - BKE_mesh_update_customdata_pointers(me, true); } } @@ -186,7 +188,7 @@ static void mesh_uv_reset_bmface(BMFace *f, const int cd_loop_uv_offset) mesh_uv_reset_array(fuv.data(), f->len); } -static void mesh_uv_reset_mface(MPoly *mp, MLoopUV *mloopuv) +static void mesh_uv_reset_mface(const MPoly *mp, MLoopUV *mloopuv) { Array<float *, BM_DEFAULT_NGON_STACK_SIZE> fuv(mp->totloop); @@ -208,7 +210,7 @@ void ED_mesh_uv_loop_reset_ex(Mesh *me, const int layernum) BMFace *efa; BMIter iter; - BLI_assert(cd_loop_uv_offset != -1); + BLI_assert(cd_loop_uv_offset >= 0); BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { if (!BM_elem_flag_test(efa, BM_ELEM_SELECT)) { @@ -223,8 +225,9 @@ void ED_mesh_uv_loop_reset_ex(Mesh *me, const int layernum) BLI_assert(CustomData_has_layer(&me->ldata, CD_MLOOPUV)); MLoopUV *mloopuv = (MLoopUV *)CustomData_get_layer_n(&me->ldata, CD_MLOOPUV, layernum); + const MPoly *polys = BKE_mesh_polys(me); for (int i = 0; i < me->totpoly; i++) { - mesh_uv_reset_mface(&me->mpoly[i], mloopuv); + mesh_uv_reset_mface(&polys[i], mloopuv); } } @@ -280,20 +283,23 @@ int ED_mesh_uv_add( return -1; } - if (me->mloopuv && do_init) { - CustomData_add_layer_named( - &me->ldata, CD_MLOOPUV, CD_DUPLICATE, me->mloopuv, me->totloop, name); + if (CustomData_has_layer(&me->ldata, CD_MLOOPUV) && do_init) { + CustomData_add_layer_named(&me->ldata, + CD_MLOOPUV, + CD_DUPLICATE, + CustomData_get_layer(&me->ldata, CD_MLOOPUV), + me->totloop, + name); is_init = true; } else { - CustomData_add_layer_named(&me->ldata, CD_MLOOPUV, CD_DEFAULT, nullptr, me->totloop, name); + CustomData_add_layer_named( + &me->ldata, CD_MLOOPUV, CD_SET_DEFAULT, nullptr, me->totloop, name); } if (active_set || layernum_dst == 0) { CustomData_set_layer_active(&me->ldata, CD_MLOOPUV, layernum_dst); } - - BKE_mesh_update_customdata_pointers(me, true); } /* don't overwrite our copied coords */ @@ -368,8 +374,11 @@ bool ED_mesh_uv_remove_named(Mesh *me, const char *name) return false; } -int ED_mesh_color_add( - Mesh *me, const char *name, const bool active_set, const bool do_init, ReportList *reports) +int ED_mesh_color_add(Mesh *me, + const char *name, + const bool active_set, + const bool do_init, + ReportList *UNUSED(reports)) { /* NOTE: keep in sync with #ED_mesh_uv_add. */ @@ -380,10 +389,6 @@ int ED_mesh_color_add( em = me->edit_mesh; layernum = CustomData_number_of_layers(&em->bm->ldata, CD_PROP_BYTE_COLOR); - if (layernum >= MAX_MCOL) { - BKE_reportf(reports, RPT_WARNING, "Cannot add more than %i vertex color layers", MAX_MCOL); - return -1; - } /* CD_PROP_BYTE_COLOR */ BM_data_layer_add_named(em->bm, &em->bm->ldata, CD_PROP_BYTE_COLOR, name); @@ -398,25 +403,25 @@ int ED_mesh_color_add( } else { layernum = CustomData_number_of_layers(&me->ldata, CD_PROP_BYTE_COLOR); - if (layernum >= MAX_MCOL) { - BKE_reportf(reports, RPT_WARNING, "Cannot add more than %i vertex color layers", MAX_MCOL); - return -1; - } - if (me->mloopcol && do_init) { - CustomData_add_layer_named( - &me->ldata, CD_PROP_BYTE_COLOR, CD_DUPLICATE, me->mloopcol, me->totloop, name); + if (CustomData_get_active_layer(&me->ldata, CD_PROP_BYTE_COLOR) != -1 && do_init) { + CustomData_add_layer_named(&me->ldata, + CD_PROP_BYTE_COLOR, + CD_DUPLICATE, + CustomData_get_layer(&me->ldata, CD_PROP_BYTE_COLOR), + me->totloop, + name); } else { CustomData_add_layer_named( - &me->ldata, CD_PROP_BYTE_COLOR, CD_DEFAULT, nullptr, me->totloop, name); + &me->ldata, CD_PROP_BYTE_COLOR, CD_SET_DEFAULT, nullptr, me->totloop, name); } if (active_set || layernum == 0) { CustomData_set_layer_active(&me->ldata, CD_PROP_BYTE_COLOR, layernum); } - BKE_mesh_update_customdata_pointers(me, true); + BKE_mesh_tessface_clear(me); } DEG_id_tag_update(&me->id, 0); @@ -432,11 +437,11 @@ bool ED_mesh_color_ensure(Mesh *me, const char *name) if (!layer) { CustomData_add_layer_named( - &me->ldata, CD_PROP_BYTE_COLOR, CD_DEFAULT, nullptr, me->totloop, name); + &me->ldata, CD_PROP_BYTE_COLOR, CD_SET_DEFAULT, nullptr, me->totloop, name); layer = me->ldata.layers + CustomData_get_layer_index(&me->ldata, CD_PROP_BYTE_COLOR); BKE_id_attributes_active_color_set(&me->id, layer); - BKE_mesh_update_customdata_pointers(me, true); + BKE_mesh_tessface_clear(me); } DEG_id_tag_update(&me->id, 0); @@ -456,7 +461,10 @@ static bool layers_poll(bContext *C) /*********************** Sculpt Vertex colors operators ************************/ -int ED_mesh_sculpt_color_add(Mesh *me, const char *name, const bool do_init, ReportList *reports) +int ED_mesh_sculpt_color_add(Mesh *me, + const char *name, + const bool do_init, + ReportList *UNUSED(reports)) { /* NOTE: keep in sync with #ED_mesh_uv_add. */ @@ -467,11 +475,6 @@ int ED_mesh_sculpt_color_add(Mesh *me, const char *name, const bool do_init, Rep em = me->edit_mesh; layernum = CustomData_number_of_layers(&em->bm->vdata, CD_PROP_COLOR); - if (layernum >= MAX_MCOL) { - BKE_reportf( - reports, RPT_WARNING, "Cannot add more than %i sculpt vertex color layers", MAX_MCOL); - return -1; - } /* CD_PROP_COLOR */ BM_data_layer_add_named(em->bm, &em->bm->vdata, CD_PROP_COLOR, name); @@ -486,11 +489,6 @@ int ED_mesh_sculpt_color_add(Mesh *me, const char *name, const bool do_init, Rep } else { layernum = CustomData_number_of_layers(&me->vdata, CD_PROP_COLOR); - if (layernum >= MAX_MCOL) { - BKE_reportf( - reports, RPT_WARNING, "Cannot add more than %i sculpt vertex color layers", MAX_MCOL); - return -1; - } if (CustomData_has_layer(&me->vdata, CD_PROP_COLOR) && do_init) { const MPropCol *color_data = (const MPropCol *)CustomData_get_layer(&me->vdata, @@ -500,14 +498,14 @@ int ED_mesh_sculpt_color_add(Mesh *me, const char *name, const bool do_init, Rep } else { CustomData_add_layer_named( - &me->vdata, CD_PROP_COLOR, CD_DEFAULT, nullptr, me->totvert, name); + &me->vdata, CD_PROP_COLOR, CD_SET_DEFAULT, nullptr, me->totvert, name); } if (layernum == 0) { CustomData_set_layer_active(&me->vdata, CD_PROP_COLOR, layernum); } - BKE_mesh_update_customdata_pointers(me, true); + BKE_mesh_tessface_clear(me); } DEG_id_tag_update(&me->id, 0); @@ -628,6 +626,28 @@ static int mesh_customdata_clear_exec__internal(bContext *C, char htype, int typ return OPERATOR_CANCELLED; } +static int mesh_customdata_add_exec__internal(bContext *C, char htype, int type) +{ + Mesh *mesh = ED_mesh_context(C); + + int tot; + CustomData *data = mesh_customdata_get_type(mesh, htype, &tot); + + BLI_assert(CustomData_layertype_is_singleton(type) == true); + + if (mesh->edit_mesh) { + BM_data_layer_add(mesh->edit_mesh->bm, data, type); + } + else { + CustomData_add_layer(data, type, CD_SET_DEFAULT, NULL, tot); + } + + DEG_id_tag_update(&mesh->id, 0); + WM_event_add_notifier(C, NC_GEOM | ND_DATA, mesh); + + return CustomData_has_layer(data, type) ? OPERATOR_FINISHED : OPERATOR_CANCELLED; +} + /* Clear Mask */ static bool mesh_customdata_mask_clear_poll(bContext *C) { @@ -778,19 +798,24 @@ static int mesh_customdata_custom_splitnormals_add_exec(bContext *C, wmOperator /* Tag edges as sharp according to smooth threshold if needed, * to preserve autosmooth shading. */ if (me->flag & ME_AUTOSMOOTH) { - BKE_edges_sharp_from_angle_set(me->mvert, - me->totvert, - me->medge, - me->totedge, - me->mloop, - me->totloop, - me->mpoly, + const Span<MVert> verts = me->verts(); + MutableSpan<MEdge> edges = me->edges_for_write(); + const Span<MPoly> polys = me->polys(); + const Span<MLoop> loops = me->loops(); + + BKE_edges_sharp_from_angle_set(verts.data(), + verts.size(), + edges.data(), + edges.size(), + loops.data(), + loops.size(), + polys.data(), BKE_mesh_poly_normals_ensure(me), - me->totpoly, + polys.size(), me->smoothresh); } - CustomData_add_layer(data, CD_CUSTOMLOOPNORMAL, CD_DEFAULT, nullptr, me->totloop); + CustomData_add_layer(data, CD_CUSTOMLOOPNORMAL, CD_SET_DEFAULT, nullptr, me->totloop); } DEG_id_tag_update(&me->id, 0); @@ -845,6 +870,246 @@ void MESH_OT_customdata_custom_splitnormals_clear(wmOperatorType *ot) ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } +/* Vertex bevel weight. */ + +static int mesh_customdata_bevel_weight_vertex_state(bContext *C) +{ + const Object *object = ED_object_context(C); + + if (object && object->type == OB_MESH) { + const Mesh *mesh = static_cast<Mesh *>(object->data); + if (!ID_IS_LINKED(mesh)) { + const CustomData *data = GET_CD_DATA(mesh, vdata); + return CustomData_has_layer(data, CD_BWEIGHT); + } + } + return -1; +} + +static bool mesh_customdata_bevel_weight_vertex_add_poll(bContext *C) +{ + return mesh_customdata_bevel_weight_vertex_state(C) == 0; +} + +static int mesh_customdata_bevel_weight_vertex_add_exec(bContext *C, wmOperator *UNUSED(op)) +{ + return mesh_customdata_add_exec__internal(C, BM_VERT, CD_BWEIGHT); +} + +void MESH_OT_customdata_bevel_weight_vertex_add(wmOperatorType *ot) +{ + ot->name = "Add Vertex Bevel Weight"; + ot->idname = "MESH_OT_customdata_bevel_weight_vertex_add"; + ot->description = "Add a vertex bevel weight layer"; + + ot->exec = mesh_customdata_bevel_weight_vertex_add_exec; + ot->poll = mesh_customdata_bevel_weight_vertex_add_poll; + + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; +} + +static bool mesh_customdata_bevel_weight_vertex_clear_poll(bContext *C) +{ + return (mesh_customdata_bevel_weight_vertex_state(C) == 1); +} + +static int mesh_customdata_bevel_weight_vertex_clear_exec(bContext *C, wmOperator *UNUSED(op)) +{ + return mesh_customdata_clear_exec__internal(C, BM_VERT, CD_BWEIGHT); +} + +void MESH_OT_customdata_bevel_weight_vertex_clear(wmOperatorType *ot) +{ + ot->name = "Clear Vertex Bevel Weight"; + ot->idname = "MESH_OT_customdata_bevel_weight_vertex_clear"; + ot->description = "Clear the vertex bevel weight layer"; + + ot->exec = mesh_customdata_bevel_weight_vertex_clear_exec; + ot->poll = mesh_customdata_bevel_weight_vertex_clear_poll; + + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; +} + +/* Edge bevel weight. */ + +static int mesh_customdata_bevel_weight_edge_state(bContext *C) +{ + const Object *ob = ED_object_context(C); + + if (ob && ob->type == OB_MESH) { + const Mesh *mesh = static_cast<Mesh *>(ob->data); + if (!ID_IS_LINKED(mesh)) { + const CustomData *data = GET_CD_DATA(mesh, edata); + return CustomData_has_layer(data, CD_BWEIGHT); + } + } + return -1; +} + +static bool mesh_customdata_bevel_weight_edge_add_poll(bContext *C) +{ + return mesh_customdata_bevel_weight_edge_state(C) == 0; +} + +static int mesh_customdata_bevel_weight_edge_add_exec(bContext *C, wmOperator *UNUSED(op)) +{ + return mesh_customdata_add_exec__internal(C, BM_EDGE, CD_BWEIGHT); +} + +void MESH_OT_customdata_bevel_weight_edge_add(wmOperatorType *ot) +{ + ot->name = "Add Edge Bevel Weight"; + ot->idname = "MESH_OT_customdata_bevel_weight_edge_add"; + ot->description = "Add an edge bevel weight layer"; + + ot->exec = mesh_customdata_bevel_weight_edge_add_exec; + ot->poll = mesh_customdata_bevel_weight_edge_add_poll; + + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; +} + +static bool mesh_customdata_bevel_weight_edge_clear_poll(bContext *C) +{ + return mesh_customdata_bevel_weight_edge_state(C) == 1; +} + +static int mesh_customdata_bevel_weight_edge_clear_exec(bContext *C, wmOperator *UNUSED(op)) +{ + return mesh_customdata_clear_exec__internal(C, BM_EDGE, CD_BWEIGHT); +} + +void MESH_OT_customdata_bevel_weight_edge_clear(wmOperatorType *ot) +{ + ot->name = "Clear Edge Bevel Weight"; + ot->idname = "MESH_OT_customdata_bevel_weight_edge_clear"; + ot->description = "Clear the edge bevel weight layer"; + + ot->exec = mesh_customdata_bevel_weight_edge_clear_exec; + ot->poll = mesh_customdata_bevel_weight_edge_clear_poll; + + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; +} + +/* Edge crease. */ + +static int mesh_customdata_crease_edge_state(bContext *C) +{ + const Object *ob = ED_object_context(C); + + if (ob && ob->type == OB_MESH) { + const Mesh *mesh = static_cast<Mesh *>(ob->data); + if (!ID_IS_LINKED(mesh)) { + const CustomData *data = GET_CD_DATA(mesh, edata); + return CustomData_has_layer(data, CD_CREASE); + } + } + return -1; +} + +static bool mesh_customdata_crease_edge_add_poll(bContext *C) +{ + return mesh_customdata_crease_edge_state(C) == 0; +} + +static int mesh_customdata_crease_edge_add_exec(bContext *C, wmOperator *UNUSED(op)) +{ + return mesh_customdata_add_exec__internal(C, BM_EDGE, CD_CREASE); +} + +void MESH_OT_customdata_crease_edge_add(wmOperatorType *ot) +{ + ot->name = "Add Edge Crease"; + ot->idname = "MESH_OT_customdata_crease_edge_add"; + ot->description = "Add an edge crease layer"; + + ot->exec = mesh_customdata_crease_edge_add_exec; + ot->poll = mesh_customdata_crease_edge_add_poll; + + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; +} + +static bool mesh_customdata_crease_edge_clear_poll(bContext *C) +{ + return mesh_customdata_crease_edge_state(C) == 1; +} + +static int mesh_customdata_crease_edge_clear_exec(bContext *C, wmOperator *UNUSED(op)) +{ + return mesh_customdata_clear_exec__internal(C, BM_EDGE, CD_CREASE); +} + +void MESH_OT_customdata_crease_edge_clear(wmOperatorType *ot) +{ + ot->name = "Clear Edge Crease"; + ot->idname = "MESH_OT_customdata_crease_edge_clear"; + ot->description = "Clear the edge crease layer"; + + ot->exec = mesh_customdata_crease_edge_clear_exec; + ot->poll = mesh_customdata_crease_edge_clear_poll; + + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; +} + +/* Vertex crease. */ + +static int mesh_customdata_crease_vertex_state(bContext *C) +{ + const Object *object = ED_object_context(C); + + if (object && object->type == OB_MESH) { + const Mesh *mesh = static_cast<Mesh *>(object->data); + if (!ID_IS_LINKED(mesh)) { + const CustomData *data = GET_CD_DATA(mesh, vdata); + return CustomData_has_layer(data, CD_CREASE); + } + } + return -1; +} + +static bool mesh_customdata_crease_vertex_add_poll(bContext *C) +{ + return mesh_customdata_crease_vertex_state(C) == 0; +} + +static int mesh_customdata_crease_vertex_add_exec(bContext *C, wmOperator *UNUSED(op)) +{ + return mesh_customdata_add_exec__internal(C, BM_VERT, CD_CREASE); +} + +void MESH_OT_customdata_crease_vertex_add(wmOperatorType *ot) +{ + ot->name = "Add Vertex Crease"; + ot->idname = "MESH_OT_customdata_crease_vertex_add"; + ot->description = "Add a vertex crease layer"; + + ot->exec = mesh_customdata_crease_vertex_add_exec; + ot->poll = mesh_customdata_crease_vertex_add_poll; + + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; +} + +static bool mesh_customdata_crease_vertex_clear_poll(bContext *C) +{ + return (mesh_customdata_crease_vertex_state(C) == 1); +} + +static int mesh_customdata_crease_vertex_clear_exec(bContext *C, wmOperator *UNUSED(op)) +{ + return mesh_customdata_clear_exec__internal(C, BM_VERT, CD_CREASE); +} + +void MESH_OT_customdata_crease_vertex_clear(wmOperatorType *ot) +{ + ot->name = "Clear Vertex Crease"; + ot->idname = "MESH_OT_customdata_crease_vertex_clear"; + ot->description = "Clear the vertex crease layer"; + + ot->exec = mesh_customdata_crease_vertex_clear_exec; + ot->poll = mesh_customdata_crease_vertex_clear_poll; + + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; +} + /************************** Add Geometry Layers *************************/ void ED_mesh_update(Mesh *mesh, bContext *C, bool calc_edges, bool calc_edges_loose) @@ -869,42 +1134,39 @@ void ED_mesh_update(Mesh *mesh, bContext *C, bool calc_edges, bool calc_edges_lo static void mesh_add_verts(Mesh *mesh, int len) { + using namespace blender; if (len == 0) { return; } int totvert = mesh->totvert + len; CustomData vdata; - CustomData_copy(&mesh->vdata, &vdata, CD_MASK_MESH.vmask, CD_DEFAULT, totvert); + CustomData_copy(&mesh->vdata, &vdata, CD_MASK_MESH.vmask, CD_SET_DEFAULT, totvert); CustomData_copy_data(&mesh->vdata, &vdata, 0, 0, mesh->totvert); if (!CustomData_has_layer(&vdata, CD_MVERT)) { - CustomData_add_layer(&vdata, CD_MVERT, CD_CALLOC, nullptr, totvert); + CustomData_add_layer(&vdata, CD_MVERT, CD_SET_DEFAULT, nullptr, totvert); } CustomData_free(&mesh->vdata, mesh->totvert); mesh->vdata = vdata; - BKE_mesh_update_customdata_pointers(mesh, false); BKE_mesh_runtime_clear_cache(mesh); - /* scan the input list and insert the new vertices */ - - /* set default flags */ - MVert *mvert = &mesh->mvert[mesh->totvert]; - for (int i = 0; i < len; i++, mvert++) { - mvert->flag |= SELECT; - } - - /* set final vertex list size */ mesh->totvert = totvert; + + bke::MutableAttributeAccessor attributes = mesh->attributes_for_write(); + bke::SpanAttributeWriter<bool> select_vert = attributes.lookup_or_add_for_write_span<bool>( + ".select_vert", ATTR_DOMAIN_POINT); + select_vert.span.take_back(len).fill(true); + select_vert.finish(); } static void mesh_add_edges(Mesh *mesh, int len) { + using namespace blender; CustomData edata; - MEdge *medge; - int i, totedge; + int totedge; if (len == 0) { return; @@ -913,26 +1175,30 @@ static void mesh_add_edges(Mesh *mesh, int len) totedge = mesh->totedge + len; /* Update custom-data. */ - CustomData_copy(&mesh->edata, &edata, CD_MASK_MESH.emask, CD_DEFAULT, totedge); + CustomData_copy(&mesh->edata, &edata, CD_MASK_MESH.emask, CD_SET_DEFAULT, totedge); CustomData_copy_data(&mesh->edata, &edata, 0, 0, mesh->totedge); if (!CustomData_has_layer(&edata, CD_MEDGE)) { - CustomData_add_layer(&edata, CD_MEDGE, CD_CALLOC, nullptr, totedge); + CustomData_add_layer(&edata, CD_MEDGE, CD_SET_DEFAULT, nullptr, totedge); } CustomData_free(&mesh->edata, mesh->totedge); mesh->edata = edata; - BKE_mesh_update_customdata_pointers(mesh, false); /* new edges don't change tessellation */ BKE_mesh_runtime_clear_cache(mesh); - /* set default flags */ - medge = &mesh->medge[mesh->totedge]; - for (i = 0; i < len; i++, medge++) { - medge->flag = ME_EDGEDRAW | ME_EDGERENDER | SELECT; + mesh->totedge = totedge; + + MutableSpan<MEdge> edges = mesh->edges_for_write(); + for (MEdge &edge : edges.take_back(len)) { + edge.flag = ME_EDGEDRAW | ME_EDGERENDER; } - mesh->totedge = totedge; + bke::MutableAttributeAccessor attributes = mesh->attributes_for_write(); + bke::SpanAttributeWriter<bool> select_edge = attributes.lookup_or_add_for_write_span<bool>( + ".select_edge", ATTR_DOMAIN_EDGE); + select_edge.span.take_back(len).fill(true); + select_edge.finish(); } static void mesh_add_loops(Mesh *mesh, int len) @@ -947,27 +1213,26 @@ static void mesh_add_loops(Mesh *mesh, int len) totloop = mesh->totloop + len; /* new face count */ /* update customdata */ - CustomData_copy(&mesh->ldata, &ldata, CD_MASK_MESH.lmask, CD_DEFAULT, totloop); + CustomData_copy(&mesh->ldata, &ldata, CD_MASK_MESH.lmask, CD_SET_DEFAULT, totloop); CustomData_copy_data(&mesh->ldata, &ldata, 0, 0, mesh->totloop); if (!CustomData_has_layer(&ldata, CD_MLOOP)) { - CustomData_add_layer(&ldata, CD_MLOOP, CD_CALLOC, nullptr, totloop); + CustomData_add_layer(&ldata, CD_MLOOP, CD_SET_DEFAULT, nullptr, totloop); } BKE_mesh_runtime_clear_cache(mesh); CustomData_free(&mesh->ldata, mesh->totloop); mesh->ldata = ldata; - BKE_mesh_update_customdata_pointers(mesh, true); mesh->totloop = totloop; } static void mesh_add_polys(Mesh *mesh, int len) { + using namespace blender; CustomData pdata; - MPoly *mpoly; - int i, totpoly; + int totpoly; if (len == 0) { return; @@ -976,26 +1241,25 @@ static void mesh_add_polys(Mesh *mesh, int len) totpoly = mesh->totpoly + len; /* new face count */ /* update customdata */ - CustomData_copy(&mesh->pdata, &pdata, CD_MASK_MESH.pmask, CD_DEFAULT, totpoly); + CustomData_copy(&mesh->pdata, &pdata, CD_MASK_MESH.pmask, CD_SET_DEFAULT, totpoly); CustomData_copy_data(&mesh->pdata, &pdata, 0, 0, mesh->totpoly); if (!CustomData_has_layer(&pdata, CD_MPOLY)) { - CustomData_add_layer(&pdata, CD_MPOLY, CD_CALLOC, nullptr, totpoly); + CustomData_add_layer(&pdata, CD_MPOLY, CD_SET_DEFAULT, nullptr, totpoly); } CustomData_free(&mesh->pdata, mesh->totpoly); mesh->pdata = pdata; - BKE_mesh_update_customdata_pointers(mesh, true); BKE_mesh_runtime_clear_cache(mesh); - /* set default flags */ - mpoly = &mesh->mpoly[mesh->totpoly]; - for (i = 0; i < len; i++, mpoly++) { - mpoly->flag = ME_FACE_SEL; - } - mesh->totpoly = totpoly; + + bke::MutableAttributeAccessor attributes = mesh->attributes_for_write(); + bke::SpanAttributeWriter<bool> select_poly = attributes.lookup_or_add_for_write_span<bool>( + ".select_poly", ATTR_DOMAIN_FACE); + select_poly.span.take_back(len).fill(true); + select_poly.finish(); } /* -------------------------------------------------------------------- */ diff --git a/source/blender/editors/mesh/mesh_intern.h b/source/blender/editors/mesh/mesh_intern.h index 7c8dbffeb31..9f90ccc30ab 100644 --- a/source/blender/editors/mesh/mesh_intern.h +++ b/source/blender/editors/mesh/mesh_intern.h @@ -84,11 +84,13 @@ struct BMElem *EDBM_elem_from_selectmode(struct BMEditMesh *em, int EDBM_elem_to_index_any(struct BMEditMesh *em, struct BMElem *ele); struct BMElem *EDBM_elem_from_index_any(struct BMEditMesh *em, uint index); -int EDBM_elem_to_index_any_multi(struct ViewLayer *view_layer, +int EDBM_elem_to_index_any_multi(const struct Scene *scene, + struct ViewLayer *view_layer, struct BMEditMesh *em, struct BMElem *ele, int *r_object_index); -struct BMElem *EDBM_elem_from_index_any_multi(struct ViewLayer *view_layer, +struct BMElem *EDBM_elem_from_index_any_multi(const struct Scene *scene, + struct ViewLayer *view_layer, uint object_index, uint elem_index, struct Object **r_obedit); @@ -313,6 +315,14 @@ void MESH_OT_customdata_skin_add(struct wmOperatorType *ot); void MESH_OT_customdata_skin_clear(struct wmOperatorType *ot); void MESH_OT_customdata_custom_splitnormals_add(struct wmOperatorType *ot); void MESH_OT_customdata_custom_splitnormals_clear(struct wmOperatorType *ot); +void MESH_OT_customdata_bevel_weight_vertex_add(struct wmOperatorType *ot); +void MESH_OT_customdata_bevel_weight_vertex_clear(struct wmOperatorType *ot); +void MESH_OT_customdata_bevel_weight_edge_add(struct wmOperatorType *ot); +void MESH_OT_customdata_bevel_weight_edge_clear(struct wmOperatorType *ot); +void MESH_OT_customdata_crease_vertex_add(struct wmOperatorType *ot); +void MESH_OT_customdata_crease_vertex_clear(struct wmOperatorType *ot); +void MESH_OT_customdata_crease_edge_add(struct wmOperatorType *ot); +void MESH_OT_customdata_crease_edge_clear(struct wmOperatorType *ot); #ifdef __cplusplus } diff --git a/source/blender/editors/mesh/mesh_mirror.c b/source/blender/editors/mesh/mesh_mirror.c index 82e77a88a57..ad5a5d362f1 100644 --- a/source/blender/editors/mesh/mesh_mirror.c +++ b/source/blender/editors/mesh/mesh_mirror.c @@ -55,11 +55,9 @@ void ED_mesh_mirror_spatial_table_begin(Object *ob, BMEditMesh *em, Mesh *me_eva } } else { - MVert *mvert = me_eval ? me_eval->mvert : me->mvert; - int i; - - for (i = 0; i < totvert; i++, mvert++) { - BLI_kdtree_3d_insert(MirrKdStore.tree, i, mvert->co); + const MVert *verts = BKE_mesh_verts(me_eval ? me_eval : me); + for (int i = 0; i < totvert; i++) { + BLI_kdtree_3d_insert(MirrKdStore.tree, i, verts[i].co); } } @@ -164,7 +162,7 @@ void ED_mesh_mirrtopo_init(BMEditMesh *em, BLI_assert(me == NULL); } const bool is_editmode = (em != NULL); - MEdge *medge = NULL, *med; + const MEdge *medge = NULL, *med; /* Edit-mode variables. */ BMEdge *eed; @@ -210,8 +208,7 @@ void ED_mesh_mirrtopo_init(BMEditMesh *em, } else { totedge = me->totedge; - medge = me->medge; - + medge = BKE_mesh_edges(me); for (a = 0, med = medge; a < totedge; a++, med++) { const uint i1 = med->v1, i2 = med->v2; topo_hash[i1]++; diff --git a/source/blender/editors/mesh/mesh_ops.c b/source/blender/editors/mesh/mesh_ops.c index b9e78740e3c..c3c3abd46a1 100644 --- a/source/blender/editors/mesh/mesh_ops.c +++ b/source/blender/editors/mesh/mesh_ops.c @@ -139,6 +139,14 @@ void ED_operatortypes_mesh(void) WM_operatortype_append(MESH_OT_customdata_skin_clear); WM_operatortype_append(MESH_OT_customdata_custom_splitnormals_add); WM_operatortype_append(MESH_OT_customdata_custom_splitnormals_clear); + WM_operatortype_append(MESH_OT_customdata_bevel_weight_vertex_add); + WM_operatortype_append(MESH_OT_customdata_bevel_weight_vertex_clear); + WM_operatortype_append(MESH_OT_customdata_bevel_weight_edge_add); + WM_operatortype_append(MESH_OT_customdata_bevel_weight_edge_clear); + WM_operatortype_append(MESH_OT_customdata_crease_vertex_add); + WM_operatortype_append(MESH_OT_customdata_crease_vertex_clear); + WM_operatortype_append(MESH_OT_customdata_crease_edge_add); + WM_operatortype_append(MESH_OT_customdata_crease_edge_clear); WM_operatortype_append(MESH_OT_edgering_select); WM_operatortype_append(MESH_OT_loopcut); diff --git a/source/blender/editors/mesh/meshtools.cc b/source/blender/editors/mesh/meshtools.cc index b1004b23a21..93754e2ef87 100644 --- a/source/blender/editors/mesh/meshtools.cc +++ b/source/blender/editors/mesh/meshtools.cc @@ -10,6 +10,8 @@ #include "MEM_guardedalloc.h" +#include "BLI_virtual_array.hh" + #include "DNA_key_types.h" #include "DNA_material_types.h" #include "DNA_mesh_types.h" @@ -21,6 +23,7 @@ #include "DNA_view3d_types.h" #include "DNA_workspace_types.h" +#include "BKE_attribute.hh" #include "BKE_context.h" #include "BKE_customdata.h" #include "BKE_deform.h" @@ -52,6 +55,9 @@ #include "WM_api.h" #include "WM_types.h" +using blender::MutableSpan; +using blender::Span; + /* * ********************** no editmode!!! *********** */ /*********************** JOIN ***************************/ @@ -96,11 +102,8 @@ static void join_mesh_single(Depsgraph *depsgraph, MPoly *mpoly = *mpoly_pp; if (me->totvert) { - /* merge customdata flag */ - ((Mesh *)ob_dst->data)->cd_flag |= me->cd_flag; - /* standard data */ - CustomData_merge(&me->vdata, vdata, CD_MASK_MESH.vmask, CD_DEFAULT, totvert); + CustomData_merge(&me->vdata, vdata, CD_MASK_MESH.vmask, CD_SET_DEFAULT, totvert); CustomData_copy_data_named(&me->vdata, vdata, 0, *vertofs, me->totvert); /* vertex groups */ @@ -199,7 +202,7 @@ static void join_mesh_single(Depsgraph *depsgraph, } if (me->totedge) { - CustomData_merge(&me->edata, edata, CD_MASK_MESH.emask, CD_DEFAULT, totedge); + CustomData_merge(&me->edata, edata, CD_MASK_MESH.emask, CD_SET_DEFAULT, totedge); CustomData_copy_data_named(&me->edata, edata, 0, *edgeofs, me->totedge); for (a = 0; a < me->totedge; a++, medge++) { @@ -220,7 +223,7 @@ static void join_mesh_single(Depsgraph *depsgraph, } } - CustomData_merge(&me->ldata, ldata, CD_MASK_MESH.lmask, CD_DEFAULT, totloop); + CustomData_merge(&me->ldata, ldata, CD_MASK_MESH.lmask, CD_SET_DEFAULT, totloop); CustomData_copy_data_named(&me->ldata, ldata, 0, *loopofs, me->totloop); for (a = 0; a < me->totloop; a++, mloop++) { @@ -244,12 +247,25 @@ static void join_mesh_single(Depsgraph *depsgraph, } } - CustomData_merge(&me->pdata, pdata, CD_MASK_MESH.pmask, CD_DEFAULT, totpoly); + CustomData_merge(&me->pdata, pdata, CD_MASK_MESH.pmask, CD_SET_DEFAULT, totpoly); CustomData_copy_data_named(&me->pdata, pdata, 0, *polyofs, me->totpoly); + /* Apply matmap. In case we don't have material indices yet, create them if more than one + * material is the result of joining. */ + int *material_indices = static_cast<int *>( + CustomData_get_layer_named(pdata, CD_PROP_INT32, "material_index")); + if (!material_indices && totcol > 1) { + material_indices = (int *)CustomData_add_layer_named( + pdata, CD_PROP_INT32, CD_SET_DEFAULT, NULL, totpoly, "material_index"); + } + if (material_indices) { + for (a = 0; a < me->totpoly; a++) { + material_indices[a + *polyofs] = matmap ? matmap[material_indices[a + *polyofs]] : 0; + } + } + for (a = 0; a < me->totpoly; a++, mpoly++) { mpoly->loopstart += *loopofs; - mpoly->mat_nr = matmap ? matmap[mpoly->mat_nr] : 0; } /* Face maps. */ @@ -289,7 +305,8 @@ static void mesh_join_offset_face_sets_ID(const Mesh *mesh, int *face_set_offset return; } - int *face_sets = (int *)CustomData_get_layer(&mesh->pdata, CD_SCULPT_FACE_SETS); + int *face_sets = (int *)CustomData_get_layer_named( + &mesh->pdata, CD_PROP_INT32, ".sculpt_face_set"); if (!face_sets) { return; } @@ -298,15 +315,10 @@ static void mesh_join_offset_face_sets_ID(const Mesh *mesh, int *face_set_offset for (int f = 0; f < mesh->totpoly; f++) { /* As face sets encode the visibility in the integer sign, the offset needs to be added or * subtracted depending on the initial sign of the integer to get the new ID. */ - if (abs(face_sets[f]) <= *face_set_offset) { - if (face_sets[f] > 0) { - face_sets[f] += *face_set_offset; - } - else { - face_sets[f] -= *face_set_offset; - } + if (face_sets[f] <= *face_set_offset) { + face_sets[f] += *face_set_offset; } - max_face_set = max_ii(max_face_set, abs(face_sets[f])); + max_face_set = max_ii(max_face_set, face_sets[f]); } *face_set_offset = max_face_set; } @@ -328,7 +340,7 @@ int ED_mesh_join_objects_exec(bContext *C, wmOperator *op) int totloop = 0, totpoly = 0, vertofs, *matmap = nullptr; int i, haskey = 0, edgeofs, loopofs, polyofs; bool ok = false, join_parent = false; - CustomData vdata, edata, fdata, ldata, pdata; + CustomData vdata, edata, ldata, pdata; if (ob->mode & OB_MODE_EDIT) { BKE_report(op->reports, RPT_WARNING, "Cannot join while in edit mode"); @@ -567,14 +579,13 @@ int ED_mesh_join_objects_exec(bContext *C, wmOperator *op) /* setup new data for destination mesh */ CustomData_reset(&vdata); CustomData_reset(&edata); - CustomData_reset(&fdata); CustomData_reset(&ldata); CustomData_reset(&pdata); - mvert = (MVert *)CustomData_add_layer(&vdata, CD_MVERT, CD_CALLOC, nullptr, totvert); - medge = (MEdge *)CustomData_add_layer(&edata, CD_MEDGE, CD_CALLOC, nullptr, totedge); - mloop = (MLoop *)CustomData_add_layer(&ldata, CD_MLOOP, CD_CALLOC, nullptr, totloop); - mpoly = (MPoly *)CustomData_add_layer(&pdata, CD_MPOLY, CD_CALLOC, nullptr, totpoly); + mvert = (MVert *)CustomData_add_layer(&vdata, CD_MVERT, CD_SET_DEFAULT, nullptr, totvert); + medge = (MEdge *)CustomData_add_layer(&edata, CD_MEDGE, CD_SET_DEFAULT, nullptr, totedge); + mloop = (MLoop *)CustomData_add_layer(&ldata, CD_MLOOP, CD_SET_DEFAULT, nullptr, totloop); + mpoly = (MPoly *)CustomData_add_layer(&pdata, CD_MPOLY, CD_SET_DEFAULT, nullptr, totpoly); vertofs = 0; edgeofs = 0; @@ -678,9 +689,6 @@ int ED_mesh_join_objects_exec(bContext *C, wmOperator *op) me->ldata = ldata; me->pdata = pdata; - /* tessface data removed above, no need to update */ - BKE_mesh_update_customdata_pointers(me, false); - /* Tag normals dirty because vertex positions could be changed from the original. */ BKE_mesh_normals_tag_dirty(me); @@ -893,13 +901,13 @@ static bool ed_mesh_mirror_topo_table_update(Object *ob, Mesh *me_eval) static int mesh_get_x_mirror_vert_spatial(Object *ob, Mesh *me_eval, int index) { Mesh *me = static_cast<Mesh *>(ob->data); - MVert *mvert = me_eval ? me_eval->mvert : me->mvert; + const Span<MVert> verts = me_eval ? me_eval->verts() : me->verts(); + float vec[3]; - mvert = &mvert[index]; - vec[0] = -mvert->co[0]; - vec[1] = mvert->co[1]; - vec[2] = mvert->co[2]; + vec[0] = -verts[index].co[0]; + vec[1] = verts[index].co[1]; + vec[2] = verts[index].co[2]; return ED_mesh_mirror_spatial_table_lookup(ob, nullptr, me_eval, vec); } @@ -1115,8 +1123,8 @@ static bool mirror_facecmp(const void *a, const void *b) int *mesh_get_x_mirror_faces(Object *ob, BMEditMesh *em, Mesh *me_eval) { Mesh *me = static_cast<Mesh *>(ob->data); - MVert *mv, *mvert; - MFace mirrormf, *mf, *hashmf, *mface; + const MVert *mv; + MFace mirrormf, *mf, *hashmf; GHash *fhash; int *mirrorverts, *mirrorfaces; @@ -1130,12 +1138,12 @@ int *mesh_get_x_mirror_faces(Object *ob, BMEditMesh *em, Mesh *me_eval) mirrorverts = static_cast<int *>(MEM_callocN(sizeof(int) * totvert, "MirrorVerts")); mirrorfaces = static_cast<int *>(MEM_callocN(sizeof(int[2]) * totface, "MirrorFaces")); - mvert = me_eval ? me_eval->mvert : me->mvert; - mface = me_eval ? me_eval->mface : me->mface; + const Span<MVert> verts = me_eval ? me_eval->verts() : me->verts(); + MFace *mface = (MFace *)CustomData_get_layer(&(me_eval ? me_eval : me)->fdata, CD_MFACE); ED_mesh_mirror_spatial_table_begin(ob, em, me_eval); - for (a = 0, mv = mvert; a < totvert; a++, mv++) { + for (a = 0, mv = verts.data(); a < totvert; a++, mv++) { mirrorverts[a] = mesh_get_x_mirror_vert(ob, me_eval, a, use_topology); } @@ -1262,42 +1270,28 @@ bool ED_mesh_pick_face_vert( const float mval_f[2] = {(float)mval[0], (float)mval[1]}; float len_best = FLT_MAX; - MPoly *me_eval_mpoly; - MLoop *me_eval_mloop; - MVert *me_eval_mvert; - uint me_eval_mpoly_len; - - me_eval_mpoly = me_eval->mpoly; - me_eval_mloop = me_eval->mloop; - me_eval_mvert = me_eval->mvert; - - me_eval_mpoly_len = me_eval->totpoly; + const Span<MVert> verts = me_eval->verts(); + const Span<MPoly> polys = me_eval->polys(); + const Span<MLoop> loops = me_eval->loops(); const int *index_mp_to_orig = (const int *)CustomData_get_layer(&me_eval->pdata, CD_ORIGINDEX); /* tag all verts using this face */ if (index_mp_to_orig) { - uint i; - - for (i = 0; i < me_eval_mpoly_len; i++) { + for (const int i : polys.index_range()) { if (index_mp_to_orig[i] == poly_index) { - ed_mesh_pick_face_vert__mpoly_find(region, - mval_f, - &me_eval_mpoly[i], - me_eval_mvert, - me_eval_mloop, - &len_best, - &v_idx_best); + ed_mesh_pick_face_vert__mpoly_find( + region, mval_f, &polys[i], verts.data(), loops.data(), &len_best, &v_idx_best); } } } else { - if (poly_index < me_eval_mpoly_len) { + if (poly_index < polys.size()) { ed_mesh_pick_face_vert__mpoly_find(region, mval_f, - &me_eval_mpoly[poly_index], - me_eval_mvert, - me_eval_mloop, + &polys[poly_index], + verts.data(), + loops.data(), &len_best, &v_idx_best); } @@ -1412,7 +1406,8 @@ bool ED_mesh_pick_vert( } /* setup data */ - data.mvert = me->mvert; + const Span<MVert> verts = me->verts(); + data.mvert = verts.data(); data.region = region; data.mval_f = mval_f; data.len_best = FLT_MAX; @@ -1466,10 +1461,11 @@ MDeformVert *ED_mesh_active_dvert_get_ob(Object *ob, int *r_index) if (r_index) { *r_index = index; } - if (index == -1 || me->dvert == nullptr) { + if (index == -1 || me->deform_verts().is_empty()) { return nullptr; } - return me->dvert + index; + MutableSpan<MDeformVert> dverts = me->deform_verts_for_write(); + return &dverts[index]; } MDeformVert *ED_mesh_active_dvert_get_only(Object *ob) diff --git a/source/blender/editors/metaball/editmball_undo.c b/source/blender/editors/metaball/editmball_undo.c index 5f13e822f84..0f9049ad70c 100644 --- a/source/blender/editors/metaball/editmball_undo.c +++ b/source/blender/editors/metaball/editmball_undo.c @@ -109,8 +109,10 @@ static void undomball_free_data(UndoMBall *umb) static Object *editmball_object_from_context(bContext *C) { + Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); - Object *obedit = OBEDIT_FROM_VIEW_LAYER(view_layer); + BKE_view_layer_synced_ensure(scene, view_layer); + Object *obedit = BKE_view_layer_edit_object_get(view_layer); if (obedit && obedit->type == OB_MBALL) { MetaBall *mb = obedit->data; if (mb->editelems != NULL) { @@ -150,9 +152,10 @@ static bool mball_undosys_step_encode(struct bContext *C, struct Main *bmain, Un /* Important not to use the 3D view when getting objects because all objects * outside of this list will be moved out of edit-mode when reading back undo steps. */ + const Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); uint objects_len = 0; - Object **objects = ED_undo_editmode_objects_from_view_layer(view_layer, &objects_len); + Object **objects = ED_undo_editmode_objects_from_view_layer(scene, view_layer, &objects_len); us->elems = MEM_callocN(sizeof(*us->elems) * objects_len, __func__); us->elems_len = objects_len; diff --git a/source/blender/editors/metaball/mball_edit.c b/source/blender/editors/metaball/mball_edit.c index 6a5d620b546..9515306a26c 100644 --- a/source/blender/editors/metaball/mball_edit.c +++ b/source/blender/editors/metaball/mball_edit.c @@ -90,7 +90,7 @@ bool ED_mball_deselect_all_multi(bContext *C) ED_view3d_viewcontext_init(C, &vc, depsgraph); uint bases_len = 0; Base **bases = BKE_view_layer_array_from_bases_in_edit_mode_unique_data( - vc.view_layer, vc.v3d, &bases_len); + vc.scene, vc.view_layer, vc.v3d, &bases_len); bool changed_multi = BKE_mball_deselect_all_multi_ex(bases, bases_len); MEM_freeN(bases); return changed_multi; @@ -145,10 +145,11 @@ static int mball_select_all_exec(bContext *C, wmOperator *op) { int action = RNA_enum_get(op->ptr, "action"); + const Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); uint bases_len = 0; Base **bases = BKE_view_layer_array_from_bases_in_edit_mode_unique_data( - view_layer, CTX_wm_view3d(C), &bases_len); + scene, view_layer, CTX_wm_view3d(C), &bases_len); if (action == SEL_TOGGLE) { action = BKE_mball_is_any_selected_multi(bases, bases_len) ? SEL_DESELECT : SEL_SELECT; @@ -330,10 +331,11 @@ static int mball_select_similar_exec(bContext *C, wmOperator *op) const float thresh = RNA_float_get(op->ptr, "threshold"); int tot_mball_selected_all = 0; + const Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); uint bases_len = 0; Base **bases = BKE_view_layer_array_from_bases_in_edit_mode_unique_data( - view_layer, CTX_wm_view3d(C), &bases_len); + scene, view_layer, CTX_wm_view3d(C), &bases_len); tot_mball_selected_all = BKE_mball_select_count_multi(bases, bases_len); @@ -463,10 +465,11 @@ static int select_random_metaelems_exec(bContext *C, wmOperator *op) const float randfac = RNA_float_get(op->ptr, "ratio"); const int seed = WM_operator_properties_select_random_seed_increment_get(op); + const Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); uint objects_len = 0; Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data( - view_layer, CTX_wm_view3d(C), &objects_len); + scene, view_layer, CTX_wm_view3d(C), &objects_len); for (uint ob_index = 0; ob_index < objects_len; ob_index++) { Object *obedit = objects[ob_index]; MetaBall *mb = (MetaBall *)obedit->data; @@ -529,10 +532,11 @@ void MBALL_OT_select_random_metaelems(struct wmOperatorType *ot) /* Duplicate selected MetaElements */ static int duplicate_metaelems_exec(bContext *C, wmOperator *UNUSED(op)) { + const Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); uint objects_len = 0; Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data( - view_layer, CTX_wm_view3d(C), &objects_len); + scene, view_layer, CTX_wm_view3d(C), &objects_len); for (uint ob_index = 0; ob_index < objects_len; ob_index++) { Object *obedit = objects[ob_index]; MetaBall *mb = (MetaBall *)obedit->data; @@ -586,10 +590,11 @@ void MBALL_OT_duplicate_metaelems(wmOperatorType *ot) static int delete_metaelems_exec(bContext *C, wmOperator *UNUSED(op)) { + const Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); uint objects_len = 0; Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data( - view_layer, CTX_wm_view3d(C), &objects_len); + scene, view_layer, CTX_wm_view3d(C), &objects_len); for (uint ob_index = 0; ob_index < objects_len; ob_index++) { Object *obedit = objects[ob_index]; MetaBall *mb = (MetaBall *)obedit->data; @@ -790,7 +795,8 @@ static bool ed_mball_findnearest_metaelem(bContext *C, } uint bases_len = 0; - Base **bases = BKE_view_layer_array_from_bases_in_edit_mode(vc.view_layer, vc.v3d, &bases_len); + Base **bases = BKE_view_layer_array_from_bases_in_edit_mode( + vc.scene, vc.view_layer, vc.v3d, &bases_len); int hit_cycle_offset = 0; if (use_cycle) { @@ -900,7 +906,7 @@ bool ED_mball_select_pick(bContext *C, const int mval[2], const struct SelectPic break; } } - + const Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); MetaBall *mb = (MetaBall *)base->object->data; mb->lastelem = ml; @@ -908,7 +914,8 @@ bool ED_mball_select_pick(bContext *C, const int mval[2], const struct SelectPic DEG_id_tag_update(&mb->id, ID_RECALC_SELECT); WM_event_add_notifier(C, NC_GEOM | ND_SELECT, mb); - if (view_layer->basact != base) { + BKE_view_layer_synced_ensure(scene, view_layer); + if (BKE_view_layer_active_base_get(view_layer) != base) { ED_object_base_activate(C, base); } diff --git a/source/blender/editors/object/CMakeLists.txt b/source/blender/editors/object/CMakeLists.txt index d05738ca27c..17365cc5488 100644 --- a/source/blender/editors/object/CMakeLists.txt +++ b/source/blender/editors/object/CMakeLists.txt @@ -21,7 +21,6 @@ set(INC ../../shader_fx ../../windowmanager ../../../../intern/clog - ../../../../intern/glew-mx ../../../../intern/guardedalloc # dna_type_offsets.h in BLO_read_write.h diff --git a/source/blender/editors/object/object_add.cc b/source/blender/editors/object/object_add.cc index acd7a8e3c13..9d06a6d5f40 100644 --- a/source/blender/editors/object/object_add.cc +++ b/source/blender/editors/object/object_add.cc @@ -609,7 +609,8 @@ Object *ED_object_add_type_with_obdata(bContext *C, ViewLayer *view_layer = CTX_data_view_layer(C); { - Object *obedit = OBEDIT_FROM_VIEW_LAYER(view_layer); + BKE_view_layer_synced_ensure(scene, view_layer); + Object *obedit = BKE_view_layer_edit_object_get(view_layer); if (obedit != nullptr) { ED_object_editmode_exit_ex(bmain, scene, obedit, EM_FREEDATA); } @@ -619,17 +620,18 @@ Object *ED_object_add_type_with_obdata(bContext *C, Object *ob; if (obdata != nullptr) { BLI_assert(type == BKE_object_obdata_to_type(obdata)); - ob = BKE_object_add_for_data(bmain, view_layer, type, name, obdata, true); + ob = BKE_object_add_for_data(bmain, scene, view_layer, type, name, obdata, true); const short *materials_len_p = BKE_id_material_len_p(obdata); if (materials_len_p && *materials_len_p > 0) { BKE_object_materials_test(bmain, ob, static_cast<ID *>(ob->data)); } } else { - ob = BKE_object_add(bmain, view_layer, type, name); + ob = BKE_object_add(bmain, scene, view_layer, type, name); } - Base *ob_base_act = BASACT(view_layer); + BKE_view_layer_synced_ensure(scene, view_layer); + Base *ob_base_act = BKE_view_layer_active_base_get(view_layer); /* While not getting a valid base is not a good thing, it can happen in convoluted corner cases, * better not crash on it in releases. */ BLI_assert(ob_base_act != nullptr); @@ -657,8 +659,7 @@ Object *ED_object_add_type_with_obdata(bContext *C, WM_event_add_notifier(C, NC_SCENE | ND_LAYER_CONTENT, scene); - /* TODO(sergey): Use proper flag for tagging here. */ - DEG_id_tag_update(&scene->id, 0); + DEG_id_tag_update(&scene->id, ID_RECALC_BASE_FLAGS); ED_outliner_select_sync_from_object_tag(C); @@ -991,7 +992,8 @@ static int object_metaball_add_exec(bContext *C, wmOperator *op) } bool newob = false; - Object *obedit = OBEDIT_FROM_VIEW_LAYER(view_layer); + BKE_view_layer_synced_ensure(scene, view_layer); + Object *obedit = BKE_view_layer_edit_object_get(view_layer); if (obedit == nullptr || obedit->type != OB_MBALL) { obedit = ED_object_add_type(C, OB_MBALL, nullptr, loc, rot, true, local_view_bits); newob = true; @@ -1100,7 +1102,8 @@ static int object_armature_add_exec(bContext *C, wmOperator *op) Main *bmain = CTX_data_main(C); Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); - Object *obedit = OBEDIT_FROM_VIEW_LAYER(view_layer); + BKE_view_layer_synced_ensure(scene, view_layer); + Object *obedit = BKE_view_layer_edit_object_get(view_layer); RegionView3D *rv3d = CTX_wm_region_view3d(C); bool newob = false; @@ -2535,6 +2538,7 @@ static void make_object_duplilist_real(bContext *C, } BKE_collection_object_add_from(bmain, scene, base->object, ob_dst); + BKE_view_layer_synced_ensure(scene, view_layer); Base *base_dst = BKE_view_layer_base_find(view_layer, ob_dst); BLI_assert(base_dst != nullptr); @@ -2771,25 +2775,6 @@ static const EnumPropertyItem convert_target_items[] = { {0, nullptr, 0, nullptr, nullptr}, }; -static void object_data_convert_ensure_curve_cache(Depsgraph *depsgraph, Scene *scene, Object *ob) -{ - if (ob->runtime.curve_cache == nullptr) { - /* Force creation. This is normally not needed but on operator - * redo we might end up with an object which isn't evaluated yet. - * Also happens in case we are working on a copy of the object - * (all its caches have been nuked then). - */ - if (ELEM(ob->type, OB_SURF, OB_CURVES_LEGACY, OB_FONT)) { - /* We need 'for render' ON here, to enable computing bevel #DispList if needed. - * Also makes sense anyway, we would not want e.g. to lose hidden parts etc. */ - BKE_displist_make_curveTypes(depsgraph, scene, ob, true); - } - else if (ob->type == OB_MBALL) { - BKE_displist_make_mball(depsgraph, scene, ob); - } - } -} - static void object_data_convert_curve_to_mesh(Main *bmain, Depsgraph *depsgraph, Object *ob) { Object *object_eval = DEG_get_evaluated_object(depsgraph, ob); @@ -2851,6 +2836,7 @@ static Base *duplibase_for_convert( DEG_id_tag_update(&obn->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY | ID_RECALC_ANIMATION); BKE_collection_object_add_from(bmain, scene, ob, obn); + BKE_view_layer_synced_ensure(scene, view_layer); Base *basen = BKE_view_layer_base_find(view_layer, obn); ED_object_base_select(basen, BA_SELECT); ED_object_base_select(base, BA_DESELECT); @@ -2908,7 +2894,7 @@ static int object_convert_exec(bContext *C, wmOperator *op) const bool use_faces = RNA_boolean_get(op->ptr, "faces"); const float offset = RNA_float_get(op->ptr, "offset"); - int a, mballConverted = 0; + int mballConverted = 0; bool gpencilConverted = false; bool gpencilCurveConverted = false; @@ -3171,14 +3157,14 @@ static int object_convert_exec(bContext *C, wmOperator *op) BKE_mesh_edges_set_draw_render(me_eval); BKE_object_material_from_eval_data(bmain, newob, &me_eval->id); Mesh *new_mesh = (Mesh *)newob->data; - BKE_mesh_nomain_to_mesh(me_eval, new_mesh, newob, &CD_MASK_MESH, true); + BKE_mesh_nomain_to_mesh(me_eval, new_mesh, newob); if (do_merge_customdata) { BKE_mesh_merge_customdata_for_apply_modifier(new_mesh); } /* Anonymous attributes shouldn't be available on the applied geometry. */ - blender::bke::mesh_attributes_for_write(*new_mesh).remove_anonymous(); + new_mesh->attributes_for_write().remove_anonymous(); BKE_object_free_modifiers(newob, 0); /* after derivedmesh calls! */ } @@ -3256,7 +3242,7 @@ static int object_convert_exec(bContext *C, wmOperator *op) /* No assumption should be made that the resulting objects is a mesh, as conversion can * fail. */ object_data_convert_curve_to_mesh(bmain, depsgraph, newob); - /* meshes doesn't use displist */ + /* Meshes doesn't use the "curve cache". */ BKE_object_free_curve_cache(newob); } else if (target == OB_GPENCIL) { @@ -3291,7 +3277,7 @@ static int object_convert_exec(bContext *C, wmOperator *op) /* No assumption should be made that the resulting objects is a mesh, as conversion can * fail. */ object_data_convert_curve_to_mesh(bmain, depsgraph, newob); - /* meshes doesn't use displist */ + /* Meshes don't use the "curve cache". */ BKE_object_free_curve_cache(newob); } else if (target == OB_GPENCIL) { @@ -3321,7 +3307,7 @@ static int object_convert_exec(bContext *C, wmOperator *op) baseob = BKE_mball_basis_find(scene, ob); if (ob != baseob) { - /* if motherball is converting it would be marked as done later */ + /* If mother-ball is converting it would be marked as done later. */ ob->flag |= OB_DONE; } @@ -3332,21 +3318,13 @@ static int object_convert_exec(bContext *C, wmOperator *op) MetaBall *mb = static_cast<MetaBall *>(newob->data); id_us_min(&mb->id); - newob->data = BKE_mesh_add(bmain, "Mesh"); - newob->type = OB_MESH; - - Mesh *me = static_cast<Mesh *>(newob->data); - me->totcol = mb->totcol; - if (newob->totcol) { - me->mat = static_cast<Material **>(MEM_dupallocN(mb->mat)); - for (a = 0; a < newob->totcol; a++) { - id_us_plus((ID *)me->mat[a]); - } - } + /* Find the evaluated mesh of the basis metaball object. */ + Object *object_eval = DEG_get_evaluated_object(depsgraph, baseob); + Mesh *mesh = BKE_mesh_new_from_object_to_bmain(bmain, depsgraph, object_eval, true); - object_data_convert_ensure_curve_cache(depsgraph, scene, baseob); - BKE_mesh_from_metaball(&baseob->runtime.curve_cache->disp, - static_cast<Mesh *>(newob->data)); + id_us_plus(&mesh->id); + newob->data = mesh; + newob->type = OB_MESH; if (obact->type == OB_MBALL) { basact = basen; @@ -3395,7 +3373,7 @@ static int object_convert_exec(bContext *C, wmOperator *op) /* If the original object is active then make this object active */ if (basen) { if (ob == obact) { - /* store new active base to update BASACT */ + /* Store new active base to update view layer. */ basact = basen; } @@ -3469,11 +3447,15 @@ static int object_convert_exec(bContext *C, wmOperator *op) if (basact) { /* active base was changed */ ED_object_base_activate(C, basact); - BASACT(view_layer) = basact; + view_layer->basact = basact; } - else if (BASACT(view_layer)->object->flag & OB_DONE) { - WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, BASACT(view_layer)->object); - WM_event_add_notifier(C, NC_OBJECT | ND_DATA, BASACT(view_layer)->object); + else { + BKE_view_layer_synced_ensure(scene, view_layer); + Object *object = BKE_view_layer_active_object_get(view_layer); + if (object->flag & OB_DONE) { + WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, object); + WM_event_add_notifier(C, NC_OBJECT | ND_DATA, object); + } } DEG_relations_tag_update(bmain); @@ -3528,11 +3510,12 @@ void OBJECT_OT_convert(wmOperatorType *ot) /* properties */ ot->prop = RNA_def_enum( ot->srna, "target", convert_target_items, OB_MESH, "Target", "Type of object to convert to"); - RNA_def_boolean(ot->srna, - "keep_original", - false, - "Keep Original", - "Keep original objects instead of replacing them"); + prop = RNA_def_boolean(ot->srna, + "keep_original", + false, + "Keep Original", + "Keep original objects instead of replacing them"); + RNA_def_property_translation_context(prop, BLT_I18NCONTEXT_ID_OBJECT); RNA_def_boolean( ot->srna, @@ -3600,8 +3583,9 @@ static Base *object_add_duplicate_internal(Main *bmain, } DEG_id_tag_update(&obn->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY); + BKE_view_layer_synced_ensure(scene, view_layer); base = BKE_view_layer_base_find(view_layer, ob); - if ((base != nullptr) && (base->flag & BASE_VISIBLE_DEPSGRAPH)) { + if ((base != nullptr) && (base->flag & BASE_ENABLED_AND_MAYBE_VISIBLE_IN_VIEWPORT)) { BKE_collection_object_add_from(bmain, scene, ob, obn); } else { @@ -3609,6 +3593,7 @@ static Base *object_add_duplicate_internal(Main *bmain, BKE_collection_object_add(bmain, layer_collection->collection, obn); } + BKE_view_layer_synced_ensure(scene, view_layer); basen = BKE_view_layer_base_find(view_layer, obn); if (base != nullptr && basen != nullptr) { basen->local_view_bits = base->local_view_bits; @@ -3692,7 +3677,7 @@ static int duplicate_exec(bContext *C, wmOperator *op) Object *ob_new_active = nullptr; CTX_DATA_BEGIN (C, Base *, base, selected_bases) { - Object *ob_new = NULL; + Object *ob_new = nullptr; object_add_duplicate_internal(bmain, scene, view_layer, @@ -3710,7 +3695,8 @@ static int duplicate_exec(bContext *C, wmOperator *op) ED_object_base_select(base, BA_DESELECT); /* new object will become active */ - if (BASACT(view_layer) == base) { + BKE_view_layer_synced_ensure(scene, view_layer); + if (BKE_view_layer_active_base_get(view_layer) == base) { ob_new_active = ob_new; } } @@ -3728,6 +3714,7 @@ static int duplicate_exec(bContext *C, wmOperator *op) for (const auto &item : source_bases_new_objects) { Object *ob_new = item.second; Base *base_source = item.first; + BKE_view_layer_synced_ensure(scene, view_layer); Base *base_new = BKE_view_layer_base_find(view_layer, ob_new); if (base_new == nullptr) { continue; @@ -3839,7 +3826,7 @@ static int object_add_named_exec(bContext *C, wmOperator *op) /* object_add_duplicate_internal() doesn't deselect other objects, unlike object_add_common() or * BKE_view_layer_base_deselect_all(). */ - ED_object_base_deselect_all(view_layer, nullptr, SEL_DESELECT); + ED_object_base_deselect_all(scene, view_layer, nullptr, SEL_DESELECT); ED_object_base_select(basen, BA_SELECT); ED_object_base_activate(C, basen); @@ -3916,13 +3903,15 @@ void OBJECT_OT_add_named(wmOperatorType *ot) static int object_transform_to_mouse_exec(bContext *C, wmOperator *op) { Main *bmain = CTX_data_main(C); + const Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); Object *ob = reinterpret_cast<Object *>( WM_operator_properties_id_lookup_from_name_or_session_uuid(bmain, op->ptr, ID_OB)); if (!ob) { - ob = OBACT(view_layer); + BKE_view_layer_synced_ensure(scene, view_layer); + ob = BKE_view_layer_active_object_get(view_layer); } if (ob == nullptr) { diff --git a/source/blender/editors/object/object_bake.c b/source/blender/editors/object/object_bake.c index effbde41c38..8d505bbca3e 100644 --- a/source/blender/editors/object/object_bake.c +++ b/source/blender/editors/object/object_bake.c @@ -155,15 +155,16 @@ static bool multiresbake_check(bContext *C, wmOperator *op) break; } - if (!me->mloopuv) { + if (!CustomData_has_layer(&me->ldata, CD_MLOOPUV)) { BKE_report(op->reports, RPT_ERROR, "Mesh should be unwrapped before multires data baking"); ok = false; } else { + const int *material_indices = BKE_mesh_material_indices(me); a = me->totpoly; while (ok && a--) { - Image *ima = bake_object_image_get(ob, me->mpoly[a].mat_nr); + Image *ima = bake_object_image_get(ob, material_indices ? material_indices[a] : 0); if (!ima) { BKE_report( diff --git a/source/blender/editors/object/object_bake_api.c b/source/blender/editors/object/object_bake_api.c index 708f1d02656..bdaa3523402 100644 --- a/source/blender/editors/object/object_bake_api.c +++ b/source/blender/editors/object/object_bake_api.c @@ -419,11 +419,13 @@ static bool is_noncolor_pass(eScenePassType pass_type) } /* if all is good tag image and return true */ -static bool bake_object_check(ViewLayer *view_layer, +static bool bake_object_check(const Scene *scene, + ViewLayer *view_layer, Object *ob, const eBakeTarget target, ReportList *reports) { + BKE_view_layer_synced_ensure(scene, view_layer); Base *base = BKE_view_layer_base_find(view_layer, ob); if (base == NULL) { @@ -591,6 +593,7 @@ static bool bake_pass_filter_check(eScenePassType pass_type, /* before even getting in the bake function we check for some basic errors */ static bool bake_objects_check(Main *bmain, + const Scene *scene, ViewLayer *view_layer, Object *ob, ListBase *selected_objects, @@ -606,7 +609,7 @@ static bool bake_objects_check(Main *bmain, if (is_selected_to_active) { int tot_objects = 0; - if (!bake_object_check(view_layer, ob, target, reports)) { + if (!bake_object_check(scene, view_layer, ob, target, reports)) { return false; } @@ -640,7 +643,7 @@ static bool bake_objects_check(Main *bmain, } for (link = selected_objects->first; link; link = link->next) { - if (!bake_object_check(view_layer, link->ptr.data, target, reports)) { + if (!bake_object_check(scene, view_layer, link->ptr.data, target, reports)) { return false; } } @@ -971,7 +974,8 @@ static bool bake_targets_init_vertex_colors(Main *bmain, return true; } -static int find_original_loop(const Mesh *me_orig, +static int find_original_loop(const MPoly *orig_polys, + const MLoop *orig_loops, const int *vert_origindex, const int *poly_origindex, const int poly_eval, @@ -987,8 +991,8 @@ static int find_original_loop(const Mesh *me_orig, } /* Find matching loop with original vertex in original polygon. */ - MPoly *mpoly_orig = me_orig->mpoly + poly_orig; - MLoop *mloop_orig = me_orig->mloop + mpoly_orig->loopstart; + const MPoly *mpoly_orig = orig_polys + poly_orig; + const MLoop *mloop_orig = orig_loops + mpoly_orig->loopstart; for (int j = 0; j < mpoly_orig->totloop; ++j, ++mloop_orig) { if (mloop_orig->v == vert_orig) { return mpoly_orig->loopstart + j; @@ -1025,23 +1029,31 @@ static void bake_targets_populate_pixels_color_attributes(BakeTargets *targets, const int tottri = poly_to_tri_count(me_eval->totpoly, me_eval->totloop); MLoopTri *looptri = MEM_mallocN(sizeof(*looptri) * tottri, __func__); - BKE_mesh_recalc_looptri( - me_eval->mloop, me_eval->mpoly, me_eval->mvert, me_eval->totloop, me_eval->totpoly, looptri); + const MLoop *loops = BKE_mesh_loops(me_eval); + BKE_mesh_recalc_looptri(loops, + BKE_mesh_polys(me_eval), + BKE_mesh_verts(me_eval), + me_eval->totloop, + me_eval->totpoly, + looptri); /* For mapping back to original mesh in case there are modifiers. */ const int *vert_origindex = CustomData_get_layer(&me_eval->vdata, CD_ORIGINDEX); const int *poly_origindex = CustomData_get_layer(&me_eval->pdata, CD_ORIGINDEX); + const MPoly *orig_polys = BKE_mesh_polys(me); + const MLoop *orig_loops = BKE_mesh_loops(me); for (int i = 0; i < tottri; i++) { const MLoopTri *lt = &looptri[i]; for (int j = 0; j < 3; j++) { unsigned int l = lt->tri[j]; - unsigned int v = me_eval->mloop[l].v; + unsigned int v = loops[l].v; /* Map back to original loop if there are modifiers. */ if (vert_origindex != NULL && poly_origindex != NULL) { - l = find_original_loop(me, vert_origindex, poly_origindex, lt->poly, v); + l = find_original_loop( + orig_polys, orig_loops, vert_origindex, poly_origindex, lt->poly, v); if (l == ORIGINDEX_NONE || l >= me->totloop) { continue; } @@ -1135,7 +1147,7 @@ static bool bake_targets_output_vertex_colors(BakeTargets *targets, Object *ob) int *num_loops_for_vertex = MEM_callocN(sizeof(int) * me->totvert, "num_loops_for_vertex"); memset(mcol, 0, sizeof(MPropCol) * me->totvert); - MLoop *mloop = me->mloop; + const MLoop *mloop = BKE_mesh_loops(me); for (int i = 0; i < totloop; i++, mloop++) { const int v = mloop->v; bake_result_add_to_rgba(mcol[v].color, &result[i * channels_num], channels_num); @@ -1400,7 +1412,8 @@ static int bake(const BakeAPIRender *bkr, else { ob_cage_eval = DEG_get_evaluated_object(depsgraph, ob_cage); ob_cage_eval->visibility_flag |= OB_HIDE_RENDER; - ob_cage_eval->base_flag &= ~(BASE_VISIBLE_DEPSGRAPH | BASE_ENABLED_RENDER); + ob_cage_eval->base_flag &= ~(BASE_ENABLED_AND_MAYBE_VISIBLE_IN_VIEWPORT | + BASE_ENABLED_RENDER); } } } @@ -1500,7 +1513,8 @@ static int bake(const BakeAPIRender *bkr, highpoly[i].ob = ob_iter; highpoly[i].ob_eval = DEG_get_evaluated_object(depsgraph, ob_iter); highpoly[i].ob_eval->visibility_flag &= ~OB_HIDE_RENDER; - highpoly[i].ob_eval->base_flag |= (BASE_VISIBLE_DEPSGRAPH | BASE_ENABLED_RENDER); + highpoly[i].ob_eval->base_flag |= (BASE_ENABLED_AND_MAYBE_VISIBLE_IN_VIEWPORT | + BASE_ENABLED_RENDER); highpoly[i].me = BKE_mesh_new_from_object(NULL, highpoly[i].ob_eval, false, false); /* Low-poly to high-poly transformation matrix. */ @@ -1516,10 +1530,11 @@ static int bake(const BakeAPIRender *bkr, if (ob_cage != NULL) { ob_cage_eval->visibility_flag |= OB_HIDE_RENDER; - ob_cage_eval->base_flag &= ~(BASE_VISIBLE_DEPSGRAPH | BASE_ENABLED_RENDER); + ob_cage_eval->base_flag &= ~(BASE_ENABLED_AND_MAYBE_VISIBLE_IN_VIEWPORT | + BASE_ENABLED_RENDER); } ob_low_eval->visibility_flag |= OB_HIDE_RENDER; - ob_low_eval->base_flag &= ~(BASE_VISIBLE_DEPSGRAPH | BASE_ENABLED_RENDER); + ob_low_eval->base_flag &= ~(BASE_ENABLED_AND_MAYBE_VISIBLE_IN_VIEWPORT | BASE_ENABLED_RENDER); /* populate the pixel arrays with the corresponding face data for each high poly object */ pixel_array_high = MEM_mallocN(sizeof(BakePixel) * targets.pixels_num, @@ -1800,6 +1815,7 @@ static int bake_exec(bContext *C, wmOperator *op) } if (!bake_objects_check(bkr.main, + bkr.scene, bkr.view_layer, bkr.ob, &bkr.selected_objects, @@ -1853,6 +1869,7 @@ static void bake_startjob(void *bkv, short *UNUSED(stop), short *do_update, floa } if (!bake_objects_check(bkr->main, + bkr->scene, bkr->view_layer, bkr->ob, &bkr->selected_objects, diff --git a/source/blender/editors/object/object_collection.c b/source/blender/editors/object/object_collection.c index 39951c2ab6e..53e1a75cba0 100644 --- a/source/blender/editors/object/object_collection.c +++ b/source/blender/editors/object/object_collection.c @@ -16,6 +16,7 @@ #include "BKE_collection.h" #include "BKE_context.h" +#include "BKE_layer.h" #include "BKE_lib_id.h" #include "BKE_main.h" #include "BKE_object.h" @@ -202,7 +203,8 @@ static int objects_remove_active_exec(bContext *C, wmOperator *op) Main *bmain = CTX_data_main(C); Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); - Object *ob = OBACT(view_layer); + BKE_view_layer_synced_ensure(scene, view_layer); + Object *ob = BKE_view_layer_active_object_get(view_layer); int single_collection_index = RNA_enum_get(op->ptr, "collection"); Collection *single_collection = collection_object_active_find_index( bmain, scene, ob, single_collection_index); diff --git a/source/blender/editors/object/object_constraint.c b/source/blender/editors/object/object_constraint.c index abf286afa0c..3c3b66b4b1d 100644 --- a/source/blender/editors/object/object_constraint.c +++ b/source/blender/editors/object/object_constraint.c @@ -31,6 +31,7 @@ #include "BKE_constraint.h" #include "BKE_context.h" #include "BKE_fcurve.h" +#include "BKE_layer.h" #include "BKE_main.h" #include "BKE_object.h" #include "BKE_report.h" @@ -296,10 +297,9 @@ static void test_constraint( if (con->type == CONSTRAINT_TYPE_KINEMATIC) { bKinematicConstraint *data = con->data; - /* bad: we need a separate set of checks here as poletarget is - * optional... otherwise poletarget must exist too or else - * the constraint is deemed invalid - */ + /* Bad: we need a separate set of checks here as pole-target is optional... + * otherwise pole-target must exist too or else the constraint is deemed invalid. */ + /* default IK check ... */ if (BKE_object_exists_check(bmain, data->tar) == 0) { data->tar = NULL; @@ -2313,12 +2313,14 @@ static bool get_new_constraint_target( /* if still not found, add a new empty to act as a target (if allowed) */ if ((found == false) && (add)) { Main *bmain = CTX_data_main(C); + Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); - Base *base = BASACT(view_layer); + BKE_view_layer_synced_ensure(scene, view_layer); + Base *base = BKE_view_layer_active_base_get(view_layer); Object *obt; /* add new target object */ - obt = BKE_object_add(bmain, view_layer, OB_EMPTY, NULL); + obt = BKE_object_add(bmain, scene, view_layer, OB_EMPTY, NULL); /* transform cent to global coords for loc */ if (pchanact) { @@ -2336,7 +2338,7 @@ static bool get_new_constraint_target( } /* restore, BKE_object_add sets active */ - BASACT(view_layer) = base; + view_layer->basact = base; ED_object_base_select(base, BA_SELECT); /* make our new target the new object */ diff --git a/source/blender/editors/object/object_data_transfer.c b/source/blender/editors/object/object_data_transfer.c index 4837b538bf6..78b059d5514 100644 --- a/source/blender/editors/object/object_data_transfer.c +++ b/source/blender/editors/object/object_data_transfer.c @@ -45,7 +45,7 @@ * Note some are 'fake' ones, i.e. they are not hold by real CDLayers. */ /* Not shared with modifier, since we use a usual enum here, not a multi-choice one. */ static const EnumPropertyItem DT_layer_items[] = { - RNA_ENUM_ITEM_HEADING("Vertex Data", NULL), + RNA_ENUM_ITEM_HEADING(N_("Vertex Data"), NULL), {DT_TYPE_MDEFORMVERT, "VGROUP_WEIGHTS", 0, @@ -61,7 +61,7 @@ static const EnumPropertyItem DT_layer_items[] = { #endif {DT_TYPE_BWEIGHT_VERT, "BEVEL_WEIGHT_VERT", 0, "Bevel Weight", "Transfer bevel weights"}, - RNA_ENUM_ITEM_HEADING("Edge Data", NULL), + RNA_ENUM_ITEM_HEADING(N_("Edge Data"), NULL), {DT_TYPE_SHARP_EDGE, "SHARP_EDGE", 0, "Sharp", "Transfer sharp mark"}, {DT_TYPE_SEAM, "SEAM", 0, "UV Seam", "Transfer UV seam mark"}, {DT_TYPE_CREASE, "CREASE", 0, "Subdivision Crease", "Transfer crease values"}, @@ -72,12 +72,12 @@ static const EnumPropertyItem DT_layer_items[] = { "Freestyle Mark", "Transfer Freestyle edge mark"}, - RNA_ENUM_ITEM_HEADING("Face Corner Data", NULL), + RNA_ENUM_ITEM_HEADING(N_("Face Corner Data"), NULL), {DT_TYPE_LNOR, "CUSTOM_NORMAL", 0, "Custom Normals", "Transfer custom normals"}, {DT_TYPE_MPROPCOL_LOOP | DT_TYPE_MLOOPCOL_LOOP, "VCOL", 0, "Colors", "Color Attributes"}, {DT_TYPE_UV, "UV", 0, "UVs", "Transfer UV layers"}, - RNA_ENUM_ITEM_HEADING("Face Data", NULL), + RNA_ENUM_ITEM_HEADING(N_("Face Data"), NULL), {DT_TYPE_SHARP_FACE, "SMOOTH", 0, "Smooth", "Transfer flat/smooth mark"}, {DT_TYPE_FREESTYLE_FACE, "FREESTYLE_FACE", diff --git a/source/blender/editors/object/object_data_transform.c b/source/blender/editors/object/object_data_transform.c index 63513eac965..cb66010c497 100644 --- a/source/blender/editors/object/object_data_transform.c +++ b/source/blender/editors/object/object_data_transform.c @@ -7,7 +7,7 @@ * Use to transform object origins only. * * This is a small API to store & apply transformations to object data, - * where a transformation matrix can be continually applied ontop of the original values + * where a transformation matrix can be continually applied on top of the original values * so we don't lose precision over time. */ diff --git a/source/blender/editors/object/object_edit.c b/source/blender/editors/object/object_edit.c index 4896ddb5258..c3482b13db6 100644 --- a/source/blender/editors/object/object_edit.c +++ b/source/blender/editors/object/object_edit.c @@ -140,8 +140,10 @@ Object **ED_object_array_in_mode_or_selected(bContext *C, uint *r_objects_len) { ScrArea *area = CTX_wm_area(C); + const Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); - Object *ob_active = OBACT(view_layer); + BKE_view_layer_synced_ensure(scene, view_layer); + Object *ob_active = BKE_view_layer_active_object_get(view_layer); ID *id_pin = NULL; const bool use_objects_in_mode = (ob_active != NULL) && (ob_active->mode & (OB_MODE_EDIT | OB_MODE_POSE)); @@ -194,13 +196,13 @@ Object **ED_object_array_in_mode_or_selected(bContext *C, /* When in a mode that supports multiple active objects, use "objects in mode" * instead of the object's selection. */ if (use_objects_in_mode) { - objects = BKE_view_layer_array_from_objects_in_mode(view_layer, - v3d, - r_objects_len, - {.object_mode = ob_active->mode, - .no_dup_data = true, - .filter_fn = filter_fn, - .filter_userdata = filter_user_data}); + struct ObjectsInModeParams params = {0}; + params.object_mode = ob_active->mode; + params.no_dup_data = true; + params.filter_fn = filter_fn; + params.filter_userdata = filter_user_data; + objects = BKE_view_layer_array_from_objects_in_mode_params( + scene, view_layer, v3d, r_objects_len, ¶ms); } else { objects = BKE_view_layer_array_selected_objects( @@ -234,7 +236,8 @@ static int object_hide_view_clear_exec(bContext *C, wmOperator *op) const bool select = RNA_boolean_get(op->ptr, "select"); bool changed = false; - LISTBASE_FOREACH (Base *, base, &view_layer->object_bases) { + BKE_view_layer_synced_ensure(scene, view_layer); + LISTBASE_FOREACH (Base *, base, BKE_view_layer_object_bases_get(view_layer)) { if (base->flag & BASE_HIDDEN) { base->flag &= ~BASE_HIDDEN; changed = true; @@ -252,7 +255,7 @@ static int object_hide_view_clear_exec(bContext *C, wmOperator *op) return OPERATOR_CANCELLED; } - BKE_layer_collection_sync(scene, view_layer); + BKE_view_layer_need_resync_tag(view_layer); DEG_id_tag_update(&scene->id, ID_RECALC_BASE_FLAGS); WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene); WM_event_add_notifier(C, NC_SCENE | ND_OB_VISIBLE, scene); @@ -286,8 +289,9 @@ static int object_hide_view_set_exec(bContext *C, wmOperator *op) bool changed = false; /* Hide selected or unselected objects. */ - LISTBASE_FOREACH (Base *, base, &view_layer->object_bases) { - if (!(base->flag & BASE_VISIBLE_VIEWLAYER)) { + BKE_view_layer_synced_ensure(scene, view_layer); + LISTBASE_FOREACH (Base *, base, BKE_view_layer_object_bases_get(view_layer)) { + if (!(base->flag & BASE_ENABLED_AND_VISIBLE_IN_DEFAULT_VIEWPORT)) { continue; } @@ -310,7 +314,7 @@ static int object_hide_view_set_exec(bContext *C, wmOperator *op) return OPERATOR_CANCELLED; } - BKE_layer_collection_sync(scene, view_layer); + BKE_view_layer_need_resync_tag(view_layer); DEG_id_tag_update(&scene->id, ID_RECALC_BASE_FLAGS); WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene); WM_event_add_notifier(C, NC_SCENE | ND_OB_VISIBLE, scene); @@ -362,10 +366,10 @@ static int object_hide_collection_exec(bContext *C, wmOperator *op) } if (toggle) { lc->local_collections_bits ^= v3d->local_collections_uuid; - BKE_layer_collection_local_sync(view_layer, v3d); + BKE_layer_collection_local_sync(scene, view_layer, v3d); } else { - BKE_layer_collection_isolate_local(view_layer, v3d, lc, extend); + BKE_layer_collection_isolate_local(scene, view_layer, v3d, lc, extend); } } else { @@ -381,6 +385,7 @@ static int object_hide_collection_exec(bContext *C, wmOperator *op) void ED_collection_hide_menu_draw(const bContext *C, uiLayout *layout) { + const Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); LayerCollection *lc_scene = view_layer->layer_collections.first; @@ -399,7 +404,7 @@ void ED_collection_hide_menu_draw(const bContext *C, uiLayout *layout) } int icon = ICON_NONE; - if (BKE_layer_collection_has_selected_objects(view_layer, lc)) { + if (BKE_layer_collection_has_selected_objects(scene, view_layer, lc)) { icon = ICON_LAYER_ACTIVE; } else if (lc->runtime_flag & LAYER_COLLECTION_HAS_OBJECTS) { @@ -701,14 +706,16 @@ bool ED_object_editmode_free_ex(Main *bmain, Object *obedit) bool ED_object_editmode_exit_multi_ex(Main *bmain, Scene *scene, ViewLayer *view_layer, int flag) { - Object *obedit = OBEDIT_FROM_VIEW_LAYER(view_layer); + BKE_view_layer_synced_ensure(scene, view_layer); + Object *obedit = BKE_view_layer_edit_object_get(view_layer); if (obedit == NULL) { return false; } bool changed = false; const short obedit_type = obedit->type; - LISTBASE_FOREACH (Base *, base, &view_layer->object_bases) { + BKE_view_layer_synced_ensure(scene, view_layer); + LISTBASE_FOREACH (Base *, base, BKE_view_layer_object_bases_get(view_layer)) { Object *ob = base->object; if ((ob->type == obedit_type) && (ob->mode & OB_MODE_EDIT)) { changed |= ED_object_editmode_exit_ex(bmain, scene, base->object, flag); @@ -841,7 +848,8 @@ static int editmode_toggle_exec(bContext *C, wmOperator *op) Scene *scene = CTX_data_scene(C); View3D *v3d = CTX_wm_view3d(C); ViewLayer *view_layer = CTX_data_view_layer(C); - Object *obact = OBACT(view_layer); + BKE_view_layer_synced_ensure(scene, view_layer); + Object *obact = BKE_view_layer_active_object_get(view_layer); const int mode_flag = OB_MODE_EDIT; const bool is_mode_set = (obact->mode & mode_flag) != 0; struct wmMsgBus *mbus = CTX_wm_message_bus(C); @@ -867,7 +875,7 @@ static int editmode_toggle_exec(bContext *C, wmOperator *op) ED_object_editmode_exit_ex(bmain, scene, obact, EM_FREEDATA); if ((obact->mode & mode_flag) == 0) { - FOREACH_OBJECT_BEGIN (view_layer, ob) { + FOREACH_OBJECT_BEGIN (scene, view_layer, ob) { if ((ob != obact) && (ob->type == obact->type)) { ED_object_editmode_exit_ex(bmain, scene, ob, EM_FREEDATA); } @@ -889,13 +897,13 @@ static bool editmode_toggle_poll(bContext *C) { Object *ob = CTX_data_active_object(C); - /* covers proxies too */ + /* Covers liboverrides too. */ if (ELEM(NULL, ob, ob->data) || ID_IS_LINKED(ob->data) || ID_IS_OVERRIDE_LIBRARY(ob) || ID_IS_OVERRIDE_LIBRARY(ob->data)) { return false; } - /* if hidden but in edit mode, we still display */ + /* If hidden but in edit mode, we still display. */ if ((ob->visibility_flag & OB_HIDE_VIEWPORT) && !(ob->mode & OB_MODE_EDIT)) { return false; } @@ -953,7 +961,8 @@ static int posemode_exec(bContext *C, wmOperator *op) } { - Object *obedit = OBEDIT_FROM_VIEW_LAYER(view_layer); + BKE_view_layer_synced_ensure(scene, view_layer); + Object *obedit = BKE_view_layer_edit_object_get(view_layer); if (obact == obedit) { ED_object_editmode_exit_ex(bmain, scene, obedit, EM_FREEDATA); is_mode_set = false; @@ -963,7 +972,7 @@ static int posemode_exec(bContext *C, wmOperator *op) if (is_mode_set) { bool ok = ED_object_posemode_exit(C, obact); if (ok) { - FOREACH_OBJECT_BEGIN (view_layer, ob) { + FOREACH_OBJECT_BEGIN (scene, view_layer, ob) { if ((ob != obact) && (ob->type == OB_ARMATURE) && (ob->mode & mode_flag)) { ED_object_posemode_exit_ex(bmain, ob); } @@ -1477,8 +1486,10 @@ static int shade_smooth_exec(bContext *C, wmOperator *op) /* For modes that only use an active object, don't handle the whole selection. */ { + Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); - Object *obact = OBACT(view_layer); + BKE_view_layer_synced_ensure(scene, view_layer); + Object *obact = BKE_view_layer_active_object_get(view_layer); if (obact && ((obact->mode & OB_MODE_ALL_PAINT))) { ctx_ob_single_active.ptr.data = obact; BLI_addtail(&ctx_objects, &ctx_ob_single_active); @@ -1550,8 +1561,10 @@ static int shade_smooth_exec(bContext *C, wmOperator *op) static bool shade_poll(bContext *C) { + const Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); - Object *obact = OBACT(view_layer); + BKE_view_layer_synced_ensure(scene, view_layer); + Object *obact = BKE_view_layer_active_object_get(view_layer); if (obact != NULL) { /* Doesn't handle edit-data, sculpt dynamic-topology, or their undo systems. */ if (obact->mode & (OB_MODE_EDIT | OB_MODE_SCULPT) || obact->data == NULL || diff --git a/source/blender/editors/object/object_facemap_ops.c b/source/blender/editors/object/object_facemap_ops.c index dddf5e40e87..4364375a4e3 100644 --- a/source/blender/editors/object/object_facemap_ops.c +++ b/source/blender/editors/object/object_facemap_ops.c @@ -53,7 +53,7 @@ void ED_object_facemap_face_add(Object *ob, bFaceMap *fmap, int facenum) /* if there's is no facemap layer then create one */ if ((facemap = CustomData_get_layer(&me->pdata, CD_FACEMAP)) == NULL) { - facemap = CustomData_add_layer(&me->pdata, CD_FACEMAP, CD_DEFAULT, NULL, me->totpoly); + facemap = CustomData_add_layer(&me->pdata, CD_FACEMAP, CD_SET_DEFAULT, NULL, me->totpoly); } facemap[facenum] = fmap_nr; diff --git a/source/blender/editors/object/object_gpencil_modifier.c b/source/blender/editors/object/object_gpencil_modifier.c index 573f048e6b6..42ac6d166b4 100644 --- a/source/blender/editors/object/object_gpencil_modifier.c +++ b/source/blender/editors/object/object_gpencil_modifier.c @@ -680,8 +680,7 @@ static int gpencil_modifier_move_to_index_exec(bContext *C, wmOperator *op) Object *ob = ED_object_active_context(C); GpencilModifierData *md = gpencil_edit_modifier_property_get(op, ob, 0); int index = RNA_int_get(op->ptr, "index"); - - if (!ED_object_gpencil_modifier_move_to_index(op->reports, ob, md, index)) { + if (!(md && ED_object_gpencil_modifier_move_to_index(op->reports, ob, md, index))) { return OPERATOR_CANCELLED; } diff --git a/source/blender/editors/object/object_hook.c b/source/blender/editors/object/object_hook.c index b3f62f3fc0f..27659042f50 100644 --- a/source/blender/editors/object/object_hook.c +++ b/source/blender/editors/object/object_hook.c @@ -484,22 +484,22 @@ static bool hook_op_edit_poll(bContext *C) return false; } -static Object *add_hook_object_new(Main *bmain, ViewLayer *view_layer, View3D *v3d, Object *obedit) +static Object *add_hook_object_new( + Main *bmain, Scene *scene, ViewLayer *view_layer, View3D *v3d, Object *obedit) { Base *basedit; Object *ob; - - ob = BKE_object_add(bmain, view_layer, OB_EMPTY, NULL); - - basedit = BKE_view_layer_base_find(view_layer, obedit); - BLI_assert(view_layer->basact->object == ob); - + ob = BKE_object_add(bmain, scene, view_layer, OB_EMPTY, NULL); + BKE_view_layer_synced_ensure(scene, view_layer); + Base *basact = BKE_view_layer_active_base_get(view_layer); + BLI_assert(basact->object == ob); if (v3d && v3d->localvd) { - view_layer->basact->local_view_bits |= v3d->local_view_uuid; + basact->local_view_bits |= v3d->local_view_uuid; } /* icky, BKE_object_add sets new base as active. * so set it back to the original edit object */ + basedit = BKE_view_layer_base_find(view_layer, obedit); view_layer->basact = basedit; return ob; @@ -532,7 +532,7 @@ static int add_hook_object(const bContext *C, if (mode == OBJECT_ADDHOOK_NEWOB && !ob) { - ob = add_hook_object_new(bmain, view_layer, v3d, obedit); + ob = add_hook_object_new(bmain, scene, view_layer, v3d, obedit); /* transform cent to global coords for loc */ mul_v3_m4v3(ob->loc, obedit->obmat, cent); diff --git a/source/blender/editors/object/object_intern.h b/source/blender/editors/object/object_intern.h index 229f8aace5a..63f010cd526 100644 --- a/source/blender/editors/object/object_intern.h +++ b/source/blender/editors/object/object_intern.h @@ -49,10 +49,14 @@ void OBJECT_OT_vertex_parent_set(struct wmOperatorType *ot); void OBJECT_OT_track_set(struct wmOperatorType *ot); void OBJECT_OT_track_clear(struct wmOperatorType *ot); void OBJECT_OT_make_local(struct wmOperatorType *ot); -void OBJECT_OT_make_override_library(struct wmOperatorType *ot); void OBJECT_OT_make_single_user(struct wmOperatorType *ot); void OBJECT_OT_make_links_scene(struct wmOperatorType *ot); void OBJECT_OT_make_links_data(struct wmOperatorType *ot); + +void OBJECT_OT_make_override_library(struct wmOperatorType *ot); +void OBJECT_OT_reset_override_library(struct wmOperatorType *ot); +void OBJECT_OT_clear_override_library(struct wmOperatorType *ot); + /** * Used for drop-box. * Assigns to object under cursor, only first material slot. diff --git a/source/blender/editors/object/object_modes.c b/source/blender/editors/object/object_modes.c index 0055cdf9ea1..6525f2d6027 100644 --- a/source/blender/editors/object/object_modes.c +++ b/source/blender/editors/object/object_modes.c @@ -190,8 +190,11 @@ bool ED_object_mode_compat_set(bContext *C, Object *ob, eObjectMode mode, Report bool ED_object_mode_set_ex(bContext *C, eObjectMode mode, bool use_undo, ReportList *reports) { wmWindowManager *wm = CTX_wm_manager(C); + const Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); - Object *ob = OBACT(view_layer); + + BKE_view_layer_synced_ensure(scene, view_layer); + Object *ob = BKE_view_layer_active_object_get(view_layer); if (ob == NULL) { return (mode == OB_MODE_OBJECT); } @@ -327,9 +330,11 @@ static void ed_object_posemode_set_for_weight_paint_ex(bContext *C, const bool is_mode_set) { View3D *v3d = CTX_wm_view3d(C); + const Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); if (ob_arm != NULL) { + BKE_view_layer_synced_ensure(scene, view_layer); const Base *base_arm = BKE_view_layer_base_find(view_layer, ob_arm); if (base_arm && BASE_VISIBLE(v3d, base_arm)) { if (is_mode_set) { @@ -464,8 +469,9 @@ static bool object_transfer_mode_to_base(bContext *C, wmOperator *op, Base *base if (ED_object_mode_set_ex(C, OB_MODE_OBJECT, true, op->reports)) { Object *ob_dst_orig = DEG_get_original_object(ob_dst); + BKE_view_layer_synced_ensure(scene, view_layer); Base *base = BKE_view_layer_base_find(view_layer, ob_dst_orig); - BKE_view_layer_base_deselect_all(view_layer); + BKE_view_layer_base_deselect_all(scene, view_layer); BKE_view_layer_base_select_and_set_active(view_layer, base); DEG_id_tag_update(&scene->id, ID_RECALC_SELECT); diff --git a/source/blender/editors/object/object_modifier.cc b/source/blender/editors/object/object_modifier.cc index e7cfcf48fd3..3d995c84639 100644 --- a/source/blender/editors/object/object_modifier.cc +++ b/source/blender/editors/object/object_modifier.cc @@ -47,9 +47,11 @@ #include "BKE_gpencil_modifier.h" #include "BKE_key.h" #include "BKE_lattice.h" +#include "BKE_layer.h" #include "BKE_lib_id.h" #include "BKE_main.h" #include "BKE_material.h" +#include "BKE_mball.h" #include "BKE_mesh.h" #include "BKE_mesh_mapping.h" #include "BKE_mesh_runtime.h" @@ -92,6 +94,8 @@ #include "object_intern.h" +using blender::Span; + static void modifier_skin_customdata_delete(struct Object *ob); /* ------------------------------------------------------------------- */ @@ -111,7 +115,7 @@ static void object_force_modifier_update_for_bind(Depsgraph *depsgraph, Object * BKE_lattice_modifiers_calc(depsgraph, scene_eval, ob_eval); } else if (ob->type == OB_MBALL) { - BKE_displist_make_mball(depsgraph, scene_eval, ob_eval); + BKE_mball_data_update(depsgraph, scene_eval, ob_eval); } else if (ELEM(ob->type, OB_CURVES_LEGACY, OB_SURF, OB_FONT)) { BKE_displist_make_curveTypes(depsgraph, scene_eval, ob_eval, false); @@ -486,6 +490,9 @@ bool ED_object_modifier_move_to_index(ReportList *reports, } } + /* NOTE: Dependency graph only uses modifier nodes for visibility updates, and exact order of + * modifier nodes in the graph does not matter. */ + DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY); WM_main_add_notifier(NC_OBJECT | ND_MODIFIER, ob); @@ -518,10 +525,12 @@ void ED_object_modifier_copy_to_object(bContext *C, bool ED_object_modifier_convert_psys_to_mesh(ReportList *UNUSED(reports), Main *bmain, Depsgraph *depsgraph, + Scene *scene, ViewLayer *view_layer, Object *ob, ModifierData *md) { + using namespace blender; int cvert = 0; if (md->type != eModifierType_ParticleSystem) { @@ -576,26 +585,33 @@ bool ED_object_modifier_convert_psys_to_mesh(ReportList *UNUSED(reports), } /* add new mesh */ - Object *obn = BKE_object_add(bmain, view_layer, OB_MESH, nullptr); + Object *obn = BKE_object_add(bmain, scene, view_layer, OB_MESH, nullptr); Mesh *me = static_cast<Mesh *>(obn->data); me->totvert = verts_num; me->totedge = edges_num; - me->mvert = (MVert *)CustomData_add_layer(&me->vdata, CD_MVERT, CD_CALLOC, nullptr, verts_num); - me->medge = (MEdge *)CustomData_add_layer(&me->edata, CD_MEDGE, CD_CALLOC, nullptr, edges_num); - me->mface = (MFace *)CustomData_add_layer(&me->fdata, CD_MFACE, CD_CALLOC, nullptr, 0); + CustomData_add_layer(&me->vdata, CD_MVERT, CD_SET_DEFAULT, nullptr, verts_num); + CustomData_add_layer(&me->edata, CD_MEDGE, CD_SET_DEFAULT, nullptr, edges_num); + CustomData_add_layer(&me->fdata, CD_MFACE, CD_SET_DEFAULT, nullptr, 0); - MVert *mvert = me->mvert; - MEdge *medge = me->medge; + blender::MutableSpan<MVert> verts = me->verts_for_write(); + blender::MutableSpan<MEdge> edges = me->edges_for_write(); + MVert *mvert = verts.data(); + MEdge *medge = edges.data(); + + bke::MutableAttributeAccessor attributes = me->attributes_for_write(); + bke::SpanAttributeWriter<bool> select_vert = attributes.lookup_or_add_for_write_span<bool>( + ".select_vert", ATTR_DOMAIN_POINT); /* copy coordinates */ + int vert_index = 0; cache = psys_eval->pathcache; for (int a = 0; a < part_num; a++) { ParticleCacheKey *key = cache[a]; int kmax = key->segments; - for (int k = 0; k <= kmax; k++, key++, cvert++, mvert++) { - copy_v3_v3(mvert->co, key->co); + for (int k = 0; k <= kmax; k++, key++, cvert++, vert_index++) { + copy_v3_v3(mvert[vert_index].co, key->co); if (k) { medge->v1 = cvert - 1; medge->v2 = cvert; @@ -604,7 +620,7 @@ bool ED_object_modifier_convert_psys_to_mesh(ReportList *UNUSED(reports), } else { /* cheap trick to select the roots */ - mvert->flag |= SELECT; + select_vert.span[vert_index] = true; } } } @@ -613,8 +629,8 @@ bool ED_object_modifier_convert_psys_to_mesh(ReportList *UNUSED(reports), for (int a = 0; a < child_num; a++) { ParticleCacheKey *key = cache[a]; int kmax = key->segments; - for (int k = 0; k <= kmax; k++, key++, cvert++, mvert++) { - copy_v3_v3(mvert->co, key->co); + for (int k = 0; k <= kmax; k++, key++, cvert++, vert_index++) { + copy_v3_v3(mvert[vert_index].co, key->co); if (k) { medge->v1 = cvert - 1; medge->v2 = cvert; @@ -623,11 +639,13 @@ bool ED_object_modifier_convert_psys_to_mesh(ReportList *UNUSED(reports), } else { /* cheap trick to select the roots */ - mvert->flag |= SELECT; + select_vert.span[vert_index] = true; } } } + select_vert.finish(); + DEG_relations_tag_update(bmain); return true; @@ -754,10 +772,10 @@ static bool modifier_apply_obdata( Main *bmain = DEG_get_bmain(depsgraph); BKE_object_material_from_eval_data(bmain, ob, &mesh_applied->id); - BKE_mesh_nomain_to_mesh(mesh_applied, me, ob, &CD_MASK_MESH, true); + BKE_mesh_nomain_to_mesh(mesh_applied, me, ob); /* Anonymous attributes shouldn't be available on the applied geometry. */ - blender::bke::mesh_attributes_for_write(*me).remove_anonymous(); + me->attributes_for_write().remove_anonymous(); if (md_eval->type == eModifierType_Multires) { multires_customdata_delete(me); @@ -1223,7 +1241,8 @@ static int modifier_remove_exec(bContext *C, wmOperator *op) /* if cloth/softbody was removed, particle mode could be cleared */ if (mode_orig & OB_MODE_PARTICLE_EDIT) { if ((ob->mode & OB_MODE_PARTICLE_EDIT) == 0) { - if (ob == OBACT(view_layer)) { + BKE_view_layer_synced_ensure(scene, view_layer); + if (ob == BKE_view_layer_active_object_get(view_layer)) { WM_event_add_notifier(C, NC_SCENE | ND_MODE | NS_MODE_OBJECT, nullptr); } } @@ -1363,7 +1382,7 @@ static int modifier_move_to_index_exec(bContext *C, wmOperator *op) ModifierData *md = edit_modifier_property_get(op, ob, 0); int index = RNA_int_get(op->ptr, "index"); - if (!ED_object_modifier_move_to_index(op->reports, ob, md, index)) { + if (!(md && ED_object_modifier_move_to_index(op->reports, ob, md, index))) { return OPERATOR_CANCELLED; } @@ -1545,7 +1564,7 @@ void OBJECT_OT_modifier_apply(wmOperatorType *ot) /** \} */ /* ------------------------------------------------------------------- */ -/** \name Apply Modifier As Shapekey Operator +/** \name Apply Modifier As Shape-Key Operator * \{ */ static bool modifier_apply_as_shapekey_poll(bContext *C) @@ -1612,12 +1631,13 @@ static int modifier_convert_exec(bContext *C, wmOperator *op) { Main *bmain = CTX_data_main(C); Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C); + Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); Object *ob = ED_object_active_context(C); ModifierData *md = edit_modifier_property_get(op, ob, 0); if (!md || !ED_object_modifier_convert_psys_to_mesh( - op->reports, bmain, depsgraph, view_layer, ob, md)) { + op->reports, bmain, depsgraph, scene, view_layer, ob, md)) { return OPERATOR_CANCELLED; } @@ -1668,6 +1688,7 @@ static int modifier_copy_exec(bContext *C, wmOperator *op) } DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY); + DEG_relations_tag_update(bmain); WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob); return OPERATOR_FINISHED; @@ -2583,8 +2604,8 @@ void OBJECT_OT_skin_radii_equalize(wmOperatorType *ot) } static void skin_armature_bone_create(Object *skin_ob, - MVert *mvert, - MEdge *medge, + const MVert *mvert, + const MEdge *medge, bArmature *arm, BLI_bitmap *edges_visited, const MeshElemMap *emap, @@ -2629,18 +2650,22 @@ static void skin_armature_bone_create(Object *skin_ob, static Object *modifier_skin_armature_create(Depsgraph *depsgraph, Main *bmain, Object *skin_ob) { Mesh *me = static_cast<Mesh *>(skin_ob->data); + const Span<MVert> me_verts = me->verts(); + const Span<MEdge> me_edges = me->edges(); Scene *scene_eval = DEG_get_evaluated_scene(depsgraph); Object *ob_eval = DEG_get_evaluated_object(depsgraph, skin_ob); - Mesh *me_eval_deform = mesh_get_eval_deform(depsgraph, scene_eval, ob_eval, &CD_MASK_BAREMESH); - MVert *mvert = me_eval_deform->mvert; + const Mesh *me_eval_deform = mesh_get_eval_deform( + depsgraph, scene_eval, ob_eval, &CD_MASK_BAREMESH); + const Span<MVert> verts_eval = me_eval_deform->verts(); /* add vertex weights to original mesh */ - CustomData_add_layer(&me->vdata, CD_MDEFORMVERT, CD_CALLOC, nullptr, me->totvert); + CustomData_add_layer(&me->vdata, CD_MDEFORMVERT, CD_SET_DEFAULT, nullptr, me->totvert); + Scene *scene = DEG_get_input_scene(depsgraph); ViewLayer *view_layer = DEG_get_input_view_layer(depsgraph); - Object *arm_ob = BKE_object_add(bmain, view_layer, OB_ARMATURE, nullptr); + Object *arm_ob = BKE_object_add(bmain, scene, view_layer, OB_ARMATURE, nullptr); BKE_object_transform_copy(arm_ob, skin_ob); bArmature *arm = static_cast<bArmature *>(arm_ob->data); arm->layer = 1; @@ -2652,7 +2677,7 @@ static Object *modifier_skin_armature_create(Depsgraph *depsgraph, Main *bmain, CustomData_get_layer(&me->vdata, CD_MVERT_SKIN)); int *emap_mem; MeshElemMap *emap; - BKE_mesh_vert_edge_map_create(&emap, &emap_mem, me->medge, me->totvert, me->totedge); + BKE_mesh_vert_edge_map_create(&emap, &emap_mem, me_edges.data(), me->totvert, me->totedge); BLI_bitmap *edges_visited = BLI_BITMAP_NEW(me->totedge, "edge_visited"); @@ -2668,15 +2693,16 @@ static Object *modifier_skin_armature_create(Depsgraph *depsgraph, Main *bmain, if (emap[v].count > 1) { bone = ED_armature_ebone_add(arm, "Bone"); - copy_v3_v3(bone->head, me->mvert[v].co); - copy_v3_v3(bone->tail, me->mvert[v].co); + copy_v3_v3(bone->head, me_verts[v].co); + copy_v3_v3(bone->tail, me_verts[v].co); bone->head[1] = 1.0f; bone->rad_head = bone->rad_tail = 0.25; } if (emap[v].count >= 1) { - skin_armature_bone_create(skin_ob, mvert, me->medge, arm, edges_visited, emap, bone, v); + skin_armature_bone_create( + skin_ob, verts_eval.data(), me_edges.data(), arm, edges_visited, emap, bone, v); } } } @@ -3344,6 +3370,7 @@ void OBJECT_OT_geometry_nodes_input_attribute_toggle(wmOperatorType *ot) ot->idname = "OBJECT_OT_geometry_nodes_input_attribute_toggle"; ot->exec = geometry_nodes_input_attribute_toggle_exec; + ot->poll = ED_operator_object_active; ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL; @@ -3361,9 +3388,8 @@ static int geometry_node_tree_copy_assign_exec(bContext *C, wmOperator *UNUSED(o { Main *bmain = CTX_data_main(C); Object *ob = ED_object_active_context(C); - ModifierData *md = BKE_object_active_modifier(ob); - if (md->type != eModifierType_Nodes) { + if (!(md && md->type == eModifierType_Nodes)) { return OPERATOR_CANCELLED; } @@ -3383,6 +3409,7 @@ static int geometry_node_tree_copy_assign_exec(bContext *C, wmOperator *UNUSED(o nmd->node_group = new_tree; id_us_min(&tree->id); + DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY); DEG_relations_tag_update(bmain); WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob); return OPERATOR_FINISHED; @@ -3395,6 +3422,7 @@ void OBJECT_OT_geometry_node_tree_copy_assign(wmOperatorType *ot) ot->idname = "OBJECT_OT_geometry_node_tree_copy_assign"; ot->exec = geometry_node_tree_copy_assign_exec; + ot->poll = ED_operator_object_active; ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } diff --git a/source/blender/editors/object/object_ops.c b/source/blender/editors/object/object_ops.c index 8a0d380ff2f..24a4556b075 100644 --- a/source/blender/editors/object/object_ops.c +++ b/source/blender/editors/object/object_ops.c @@ -58,11 +58,14 @@ void ED_operatortypes_object(void) WM_operatortype_append(OBJECT_OT_track_set); WM_operatortype_append(OBJECT_OT_track_clear); WM_operatortype_append(OBJECT_OT_make_local); - WM_operatortype_append(OBJECT_OT_make_override_library); WM_operatortype_append(OBJECT_OT_make_single_user); WM_operatortype_append(OBJECT_OT_make_links_scene); WM_operatortype_append(OBJECT_OT_make_links_data); + WM_operatortype_append(OBJECT_OT_make_override_library); + WM_operatortype_append(OBJECT_OT_reset_override_library); + WM_operatortype_append(OBJECT_OT_clear_override_library); + WM_operatortype_append(OBJECT_OT_select_random); WM_operatortype_append(OBJECT_OT_select_all); WM_operatortype_append(OBJECT_OT_select_same_collection); diff --git a/source/blender/editors/object/object_random.c b/source/blender/editors/object/object_random.c index 7d670d3f452..3117cbb0166 100644 --- a/source/blender/editors/object/object_random.c +++ b/source/blender/editors/object/object_random.c @@ -9,6 +9,7 @@ #include "DNA_layer_types.h" #include "DNA_object_types.h" +#include "DNA_scene_types.h" #include "BLI_math.h" #include "BLI_rand.h" @@ -77,6 +78,7 @@ static bool object_rand_transverts(TransVertStore *tvs, static int object_rand_verts_exec(bContext *C, wmOperator *op) { + const Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); Object *ob_active = CTX_data_edit_object(C); const int ob_mode = ob_active->mode; @@ -89,7 +91,7 @@ static int object_rand_verts_exec(bContext *C, wmOperator *op) bool changed_multi = false; uint objects_len = 0; Object **objects = BKE_view_layer_array_from_objects_in_mode_unique_data( - view_layer, CTX_wm_view3d(C), &objects_len, ob_mode); + scene, view_layer, CTX_wm_view3d(C), &objects_len, ob_mode); for (uint ob_index = 0; ob_index < objects_len; ob_index++) { Object *ob_iter = objects[ob_index]; diff --git a/source/blender/editors/object/object_relations.c b/source/blender/editors/object/object_relations.c index f136d3302df..4a523997473 100644 --- a/source/blender/editors/object/object_relations.c +++ b/source/blender/editors/object/object_relations.c @@ -262,8 +262,8 @@ static int vertex_parent_set_exec(bContext *C, wmOperator *op) } else { Object workob; - - ob->parent = BASACT(view_layer)->object; + BKE_view_layer_synced_ensure(scene, view_layer); + ob->parent = BKE_view_layer_active_object_get(view_layer); if (par3 != INDEX_UNSET) { ob->partype = PARVERT3; ob->par1 = par1; @@ -2073,6 +2073,7 @@ static void tag_localizable_objects(bContext *C, const int mode) * otherwise they're lost on reload, see T40595. */ static bool make_local_all__instance_indirect_unused(Main *bmain, + const Scene *scene, ViewLayer *view_layer, Collection *collection) { @@ -2086,6 +2087,7 @@ static bool make_local_all__instance_indirect_unused(Main *bmain, id_us_plus(&ob->id); BKE_collection_object_add(bmain, collection, ob); + BKE_view_layer_synced_ensure(scene, view_layer); base = BKE_view_layer_base_find(view_layer, ob); ED_object_base_select(base, BA_SELECT); DEG_id_tag_update(&ob->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY | ID_RECALC_ANIMATION); @@ -2153,15 +2155,16 @@ static int make_local_exec(bContext *C, wmOperator *op) /* NOTE: we (ab)use LIB_TAG_PRE_EXISTING to cherry pick which ID to make local... */ if (mode == MAKE_LOCAL_ALL) { + const Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); Collection *collection = CTX_data_collection(C); BKE_main_id_tag_all(bmain, LIB_TAG_PRE_EXISTING, false); /* De-select so the user can differentiate newly instanced from existing objects. */ - BKE_view_layer_base_deselect_all(view_layer); + BKE_view_layer_base_deselect_all(scene, view_layer); - if (make_local_all__instance_indirect_unused(bmain, view_layer, collection)) { + if (make_local_all__instance_indirect_unused(bmain, scene, view_layer, collection)) { BKE_report(op->reports, RPT_INFO, "Orphan library objects added to the current scene to avoid loss"); @@ -2280,12 +2283,6 @@ static int make_override_library_exec(bContext *C, wmOperator *op) ID *id_root = NULL; bool is_override_instancing_object = false; - const bool do_fully_editable = U.experimental.use_override_new_fully_editable; - - GSet *user_overrides_objects_uids = do_fully_editable ? NULL : - BLI_gset_new(BLI_ghashutil_inthash_p, - BLI_ghashutil_intcmp, - __func__); bool user_overrides_from_selected_objects = false; if (!ID_IS_LINKED(obact) && obact->instance_collection != NULL && @@ -2325,6 +2322,21 @@ static int make_override_library_exec(bContext *C, wmOperator *op) user_overrides_from_selected_objects = true; } + const bool do_fully_editable = !user_overrides_from_selected_objects; + + GSet *user_overrides_objects_uids = do_fully_editable ? NULL : + BLI_gset_new(BLI_ghashutil_inthash_p, + BLI_ghashutil_intcmp, + __func__); + + /* Make already existing selected liboverrides editable. */ + FOREACH_SELECTED_OBJECT_BEGIN (view_layer, CTX_wm_view3d(C), ob_iter) { + if (ID_IS_OVERRIDE_LIBRARY_REAL(ob_iter) && !ID_IS_LINKED(ob_iter)) { + ob_iter->id.override_library->flag &= ~IDOVERRIDE_LIBRARY_FLAG_SYSTEM_DEFINED; + } + } + FOREACH_SELECTED_OBJECT_END; + if (do_fully_editable) { /* Pass. */ } @@ -2347,6 +2359,25 @@ static int make_override_library_exec(bContext *C, wmOperator *op) BKE_main_id_tag_all(bmain, LIB_TAG_DOIT, false); + /* For the time being, replace selected linked objects by their overrides in all collections. + * While this may not be the absolute best behavior in all cases, in most common one this should + * match the expected result. */ + if (user_overrides_objects_uids != NULL) { + LISTBASE_FOREACH (Collection *, coll_iter, &bmain->collections) { + if (ID_IS_LINKED(coll_iter)) { + continue; + } + LISTBASE_FOREACH (CollectionObject *, coll_ob_iter, &coll_iter->gobject) { + if (BLI_gset_haskey(user_overrides_objects_uids, + POINTER_FROM_UINT(coll_ob_iter->ob->id.session_uuid))) { + /* Tag for remapping when creating overrides. */ + coll_iter->id.tag |= LIB_TAG_DOIT; + break; + } + } + } + } + ID *id_root_override; const bool success = BKE_lib_override_library_create(bmain, scene, @@ -2411,6 +2442,8 @@ static int make_override_library_exec(bContext *C, wmOperator *op) DEG_id_tag_update(&CTX_data_scene(C)->id, ID_RECALC_BASE_FLAGS | ID_RECALC_COPY_ON_WRITE); WM_event_add_notifier(C, NC_WINDOW, NULL); + WM_event_add_notifier(C, NC_WM | ND_LIB_OVERRIDE_CHANGED, NULL); + WM_event_add_notifier(C, NC_SPACE | ND_SPACE_VIEW3D, NULL); return success ? OPERATOR_FINISHED : OPERATOR_CANCELLED; } @@ -2435,6 +2468,9 @@ static int make_override_library_invoke(bContext *C, wmOperator *op, const wmEve } if (!ID_IS_LINKED(obact)) { + if (ID_IS_OVERRIDE_LIBRARY_REAL(obact)) { + return make_override_library_exec(C, op); + } BKE_report(op->reports, RPT_ERROR, "Cannot make library override from a local object"); return OPERATOR_CANCELLED; } @@ -2473,17 +2509,20 @@ static bool make_override_library_poll(bContext *C) Object *obact = CTX_data_active_object(C); /* Object must be directly linked to be overridable. */ - return (ED_operator_objectmode(C) && obact != NULL && - (ID_IS_LINKED(obact) || (obact->instance_collection != NULL && - ID_IS_OVERRIDABLE_LIBRARY(obact->instance_collection) && - !ID_IS_OVERRIDE_LIBRARY(obact)))); + return ( + ED_operator_objectmode(C) && obact != NULL && + (ID_IS_LINKED(obact) || ID_IS_OVERRIDE_LIBRARY(obact) || + (obact->instance_collection != NULL && + ID_IS_OVERRIDABLE_LIBRARY(obact->instance_collection) && !ID_IS_OVERRIDE_LIBRARY(obact)))); } void OBJECT_OT_make_override_library(wmOperatorType *ot) { /* identifiers */ ot->name = "Make Library Override"; - ot->description = "Make a local override of this library linked data-block"; + ot->description = + "Create a local override of the selected linked objects, and their hierarchy of " + "dependencies"; ot->idname = "OBJECT_OT_make_override_library"; /* api callbacks */ @@ -2513,6 +2552,130 @@ void OBJECT_OT_make_override_library(wmOperatorType *ot) /** \} */ /* ------------------------------------------------------------------- */ +/** \name Reset Library Override Operator + * \{ */ + +static bool reset_clear_override_library_poll(bContext *C) +{ + Object *obact = CTX_data_active_object(C); + + /* Object must be local and an override. */ + return (ED_operator_objectmode(C) && obact != NULL && !ID_IS_LINKED(obact) && + ID_IS_OVERRIDE_LIBRARY(obact)); +} + +static int reset_override_library_exec(bContext *C, wmOperator *UNUSED(op)) +{ + Main *bmain = CTX_data_main(C); + + /* Make already existing selected liboverrides editable. */ + FOREACH_SELECTED_OBJECT_BEGIN (CTX_data_view_layer(C), CTX_wm_view3d(C), ob_iter) { + if (ID_IS_OVERRIDE_LIBRARY_REAL(ob_iter) && !ID_IS_LINKED(ob_iter)) { + BKE_lib_override_library_id_reset(bmain, &ob_iter->id, false); + } + } + FOREACH_SELECTED_OBJECT_END; + + WM_event_add_notifier(C, NC_WINDOW, NULL); + WM_event_add_notifier(C, NC_WM | ND_LIB_OVERRIDE_CHANGED, NULL); + WM_event_add_notifier(C, NC_SPACE | ND_SPACE_VIEW3D, NULL); + + return OPERATOR_FINISHED; +} + +void OBJECT_OT_reset_override_library(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Reset Library Override"; + ot->description = "Reset the selected local overrides to their linked references values"; + ot->idname = "OBJECT_OT_reset_override_library"; + + /* api callbacks */ + ot->exec = reset_override_library_exec; + ot->poll = reset_clear_override_library_poll; + + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; +} + +/** \} */ + +/* ------------------------------------------------------------------- */ +/** \name Clear Library Override Operator + * \{ */ + +static int clear_override_library_exec(bContext *C, wmOperator *UNUSED(op)) +{ + Main *bmain = CTX_data_main(C); + ViewLayer *view_layer = CTX_data_view_layer(C); + Scene *scene = CTX_data_scene(C); + LinkNode *todo_objects = NULL, *todo_object_iter; + + /* Make already existing selected liboverrides editable. */ + FOREACH_SELECTED_OBJECT_BEGIN (view_layer, CTX_wm_view3d(C), ob_iter) { + if (ID_IS_LINKED(ob_iter)) { + continue; + } + BLI_linklist_prepend_alloca(&todo_objects, ob_iter); + } + FOREACH_SELECTED_OBJECT_END; + + for (todo_object_iter = todo_objects; todo_object_iter != NULL; + todo_object_iter = todo_object_iter->next) { + Object *ob_iter = todo_object_iter->link; + if (BKE_lib_override_library_is_hierarchy_leaf(bmain, &ob_iter->id)) { + bool do_remap_active = false; + BKE_view_layer_synced_ensure(scene, view_layer); + if (BKE_view_layer_active_object_get(view_layer) == ob_iter) { + do_remap_active = true; + } + BKE_libblock_remap(bmain, + &ob_iter->id, + ob_iter->id.override_library->reference, + ID_REMAP_SKIP_INDIRECT_USAGE); + if (do_remap_active) { + Object *ref_object = (Object *)ob_iter->id.override_library->reference; + Base *basact = BKE_view_layer_base_find(view_layer, ref_object); + if (basact != NULL) { + view_layer->basact = basact; + } + DEG_id_tag_update(&scene->id, ID_RECALC_SELECT); + } + BKE_id_delete(bmain, &ob_iter->id); + } + else { + BKE_lib_override_library_id_reset(bmain, &ob_iter->id, true); + } + } + + DEG_id_tag_update(&scene->id, ID_RECALC_BASE_FLAGS | ID_RECALC_COPY_ON_WRITE); + WM_event_add_notifier(C, NC_WINDOW, NULL); + WM_event_add_notifier(C, NC_WM | ND_LIB_OVERRIDE_CHANGED, NULL); + WM_event_add_notifier(C, NC_SPACE | ND_SPACE_VIEW3D, NULL); + + return OPERATOR_FINISHED; +} + +void OBJECT_OT_clear_override_library(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Clear Library Override"; + ot->description = + "Delete the selected local overrides and relink their usages to the linked data-blocks if " + "possible, else reset them and mark them as non editable"; + ot->idname = "OBJECT_OT_clear_override_library"; + + /* api callbacks */ + ot->exec = clear_override_library_exec; + ot->poll = reset_clear_override_library_poll; + + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; +} + +/** \} */ + +/* ------------------------------------------------------------------- */ /** \name Make Single User Operator * \{ */ @@ -2533,7 +2696,7 @@ static int make_single_user_exec(bContext *C, wmOperator *op) if (RNA_boolean_get(op->ptr, "object")) { if (flag == SELECT) { - BKE_view_layer_selected_objects_tag(view_layer, OB_DONE); + BKE_view_layer_selected_objects_tag(scene, view_layer, OB_DONE); single_object_users(bmain, scene, v3d, OB_DONE, copy_collections); } else { diff --git a/source/blender/editors/object/object_remesh.cc b/source/blender/editors/object/object_remesh.cc index ac4fb40d832..adc07d0b411 100644 --- a/source/blender/editors/object/object_remesh.cc +++ b/source/blender/editors/object/object_remesh.cc @@ -73,6 +73,9 @@ #include "object_intern.h" /* own include */ +using blender::IndexRange; +using blender::Span; + /* TODO(sebpa): unstable, can lead to unrecoverable errors. */ // #define USE_MESH_CURVATURE @@ -128,7 +131,8 @@ static int voxel_remesh_exec(bContext *C, wmOperator *op) } /* Output mesh will be all smooth or all flat shading. */ - const bool smooth_normals = mesh->mpoly[0].flag & ME_SMOOTH; + const Span<MPoly> polys = mesh->polys(); + const bool smooth_normals = polys.first().flag & ME_SMOOTH; float isovalue = 0.0f; if (mesh->flag & ME_REMESH_REPROJECT_VOLUME) { @@ -144,7 +148,7 @@ static int voxel_remesh_exec(bContext *C, wmOperator *op) } if (ob->mode == OB_MODE_SCULPT) { - ED_sculpt_undo_geometry_begin(ob, op->type->name); + ED_sculpt_undo_geometry_begin(ob, op); } if (mesh->flag & ME_REMESH_FIX_POLES && mesh->remesh_voxel_adaptivity <= 0.0f) { @@ -175,14 +179,13 @@ static int voxel_remesh_exec(bContext *C, wmOperator *op) BKE_remesh_reproject_vertex_paint(new_mesh, mesh); } - BKE_mesh_nomain_to_mesh(new_mesh, mesh, ob, &CD_MASK_MESH, true); + BKE_mesh_nomain_to_mesh(new_mesh, mesh, ob); if (smooth_normals) { BKE_mesh_smooth_flag_set(static_cast<Mesh *>(ob->data), true); } if (ob->mode == OB_MODE_SCULPT) { - BKE_sculpt_ensure_orig_mesh_data(CTX_data_scene(C), ob); ED_sculpt_undo_geometry_end(ob); } @@ -654,6 +657,7 @@ struct QuadriFlowJob { short *stop, *do_update; float *progress; + const struct wmOperator *op; Scene *scene; int target_faces; int seed; @@ -677,9 +681,11 @@ static bool mesh_is_manifold_consistent(Mesh *mesh) * check that the direction of the faces are consistent and doesn't suddenly * flip */ + const Span<MVert> verts = mesh->verts(); + const Span<MEdge> edges = mesh->edges(); + const Span<MLoop> loops = mesh->loops(); bool is_manifold_consistent = true; - const MLoop *mloop = mesh->mloop; char *edge_faces = (char *)MEM_callocN(mesh->totedge * sizeof(char), "remesh_manifold_check"); int *edge_vert = (int *)MEM_malloc_arrayN( mesh->totedge, sizeof(uint), "remesh_consistent_check"); @@ -688,18 +694,17 @@ static bool mesh_is_manifold_consistent(Mesh *mesh) edge_vert[i] = -1; } - for (uint loop_idx = 0; loop_idx < mesh->totloop; loop_idx++) { - const MLoop *loop = &mloop[loop_idx]; - edge_faces[loop->e] += 1; - if (edge_faces[loop->e] > 2) { + for (const MLoop &loop : loops) { + edge_faces[loop.e] += 1; + if (edge_faces[loop.e] > 2) { is_manifold_consistent = false; break; } - if (edge_vert[loop->e] == -1) { - edge_vert[loop->e] = loop->v; + if (edge_vert[loop.e] == -1) { + edge_vert[loop.e] = loop.v; } - else if (edge_vert[loop->e] == loop->v) { + else if (edge_vert[loop.e] == loop.v) { /* Mesh has flips in the surface so it is non consistent */ is_manifold_consistent = false; break; @@ -707,16 +712,16 @@ static bool mesh_is_manifold_consistent(Mesh *mesh) } if (is_manifold_consistent) { - for (uint i = 0; i < mesh->totedge; i++) { + for (const int i : edges.index_range()) { /* Check for wire edges. */ if (edge_faces[i] == 0) { is_manifold_consistent = false; break; } /* Check for zero length edges */ - MVert *v1 = &mesh->mvert[mesh->medge[i].v1]; - MVert *v2 = &mesh->mvert[mesh->medge[i].v2]; - if (compare_v3v3(v1->co, v2->co, 1e-4f)) { + const MVert &v1 = verts[edges[i].v1]; + const MVert &v2 = verts[edges[i].v2]; + if (compare_v3v3(v1.co, v2.co, 1e-4f)) { is_manifold_consistent = false; break; } @@ -891,7 +896,7 @@ static void quadriflow_start_job(void *customdata, short *stop, short *do_update new_mesh = remesh_symmetry_mirror(qj->owner, new_mesh, qj->symmetry_axes); if (ob->mode == OB_MODE_SCULPT) { - ED_sculpt_undo_geometry_begin(ob, "QuadriFlow Remesh"); + ED_sculpt_undo_geometry_begin(ob, qj->op); } if (qj->preserve_paint_mask) { @@ -899,14 +904,13 @@ static void quadriflow_start_job(void *customdata, short *stop, short *do_update BKE_mesh_remesh_reproject_paint_mask(new_mesh, mesh); } - BKE_mesh_nomain_to_mesh(new_mesh, mesh, ob, &CD_MASK_MESH, true); + BKE_mesh_nomain_to_mesh(new_mesh, mesh, ob); if (qj->smooth_normals) { BKE_mesh_smooth_flag_set(static_cast<Mesh *>(ob->data), true); } if (ob->mode == OB_MODE_SCULPT) { - BKE_sculpt_ensure_orig_mesh_data(qj->scene, ob); ED_sculpt_undo_geometry_end(ob); } @@ -949,6 +953,7 @@ static int quadriflow_remesh_exec(bContext *C, wmOperator *op) { QuadriFlowJob *job = (QuadriFlowJob *)MEM_mallocN(sizeof(QuadriFlowJob), "QuadriFlowJob"); + job->op = op; job->owner = CTX_data_active_object(C); job->scene = CTX_data_scene(C); diff --git a/source/blender/editors/object/object_select.c b/source/blender/editors/object/object_select.c index 6f7fc2efa61..43867877fdb 100644 --- a/source/blender/editors/object/object_select.c +++ b/source/blender/editors/object/object_select.c @@ -117,29 +117,28 @@ void ED_object_base_activate(bContext *C, Base *base) void ED_object_base_activate_with_mode_exit_if_needed(bContext *C, Base *base) { + Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); /* Currently we only need to be concerned with edit-mode. */ - Object *obedit = OBEDIT_FROM_VIEW_LAYER(view_layer); + BKE_view_layer_synced_ensure(scene, view_layer); + Object *obedit = BKE_view_layer_edit_object_get(view_layer); if (obedit) { Object *ob = base->object; if (((ob->mode & OB_MODE_EDIT) == 0) || (obedit->type != ob->type)) { Main *bmain = CTX_data_main(C); - Scene *scene = CTX_data_scene(C); ED_object_editmode_exit_multi_ex(bmain, scene, view_layer, EM_FREEDATA); } } ED_object_base_activate(C, base); } -bool ED_object_base_deselect_all_ex(ViewLayer *view_layer, - View3D *v3d, - int action, - bool *r_any_visible) +bool ED_object_base_deselect_all_ex( + const Scene *scene, ViewLayer *view_layer, View3D *v3d, int action, bool *r_any_visible) { if (action == SEL_TOGGLE) { action = SEL_SELECT; - FOREACH_VISIBLE_BASE_BEGIN (view_layer, v3d, base) { + FOREACH_VISIBLE_BASE_BEGIN (scene, view_layer, v3d, base) { if (v3d && ((v3d->object_type_exclude_select & (1 << base->object->type)) != 0)) { continue; } @@ -153,7 +152,7 @@ bool ED_object_base_deselect_all_ex(ViewLayer *view_layer, bool any_visible = false; bool changed = false; - FOREACH_VISIBLE_BASE_BEGIN (view_layer, v3d, base) { + FOREACH_VISIBLE_BASE_BEGIN (scene, view_layer, v3d, base) { if (v3d && ((v3d->object_type_exclude_select & (1 << base->object->type)) != 0)) { continue; } @@ -190,9 +189,12 @@ bool ED_object_base_deselect_all_ex(ViewLayer *view_layer, return changed; } -bool ED_object_base_deselect_all(ViewLayer *view_layer, View3D *v3d, int action) +bool ED_object_base_deselect_all(const Scene *scene, + ViewLayer *view_layer, + View3D *v3d, + int action) { - return ED_object_base_deselect_all_ex(view_layer, v3d, action, NULL); + return ED_object_base_deselect_all_ex(scene, view_layer, v3d, action, NULL); } /** \} */ @@ -203,7 +205,7 @@ bool ED_object_base_deselect_all(ViewLayer *view_layer, View3D *v3d, int action) static int get_base_select_priority(Base *base) { - if (base->flag & BASE_VISIBLE_DEPSGRAPH) { + if (base->flag & BASE_ENABLED_AND_MAYBE_VISIBLE_IN_VIEWPORT) { if (base->flag & BASE_SELECTABLE) { return 3; } @@ -212,12 +214,13 @@ static int get_base_select_priority(Base *base) return 1; } -Base *ED_object_find_first_by_data_id(ViewLayer *view_layer, ID *id) +Base *ED_object_find_first_by_data_id(const Scene *scene, ViewLayer *view_layer, ID *id) { BLI_assert(OB_DATA_SUPPORT_ID(GS(id->name))); /* Try active object. */ - Base *basact = view_layer->basact; + BKE_view_layer_synced_ensure(scene, view_layer); + Base *basact = BKE_view_layer_active_base_get(view_layer); if (basact && basact->object && basact->object->data == id) { return basact; @@ -227,7 +230,7 @@ Base *ED_object_find_first_by_data_id(ViewLayer *view_layer, ID *id) Base *base_best = NULL; int priority_best = 0; - LISTBASE_FOREACH (Base *, base, &view_layer->object_bases) { + LISTBASE_FOREACH (Base *, base, BKE_view_layer_object_bases_get(view_layer)) { if (base->object && base->object->data == id) { if (base->flag & BASE_SELECTED) { return base; @@ -247,8 +250,10 @@ Base *ED_object_find_first_by_data_id(ViewLayer *view_layer, ID *id) bool ED_object_jump_to_object(bContext *C, Object *ob, const bool UNUSED(reveal_hidden)) { + const Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); View3D *v3d = CTX_wm_view3d(C); + BKE_view_layer_synced_ensure(scene, view_layer); Base *base = BKE_view_layer_base_find(view_layer, ob); if (base == NULL) { @@ -257,10 +262,10 @@ bool ED_object_jump_to_object(bContext *C, Object *ob, const bool UNUSED(reveal_ /* TODO: use 'reveal_hidden', as is done with bones. */ - if (view_layer->basact != base || !(base->flag & BASE_SELECTED)) { + if (BKE_view_layer_active_base_get(view_layer) != base || !(base->flag & BASE_SELECTED)) { /* Select if not selected. */ if (!(base->flag & BASE_SELECTED)) { - ED_object_base_deselect_all(view_layer, v3d, SEL_DESELECT); + ED_object_base_deselect_all(scene, view_layer, v3d, SEL_DESELECT); if (BASE_VISIBLE(v3d, base)) { ED_object_base_select(base, BA_SELECT); @@ -382,6 +387,7 @@ static bool objects_selectable_poll(bContext *C) static int object_select_by_type_exec(bContext *C, wmOperator *op) { + Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); View3D *v3d = CTX_wm_view3d(C); short obtype, extend; @@ -390,7 +396,7 @@ static int object_select_by_type_exec(bContext *C, wmOperator *op) extend = RNA_boolean_get(op->ptr, "extend"); if (extend == 0) { - ED_object_base_deselect_all(view_layer, v3d, SEL_DESELECT); + ED_object_base_deselect_all(scene, view_layer, v3d, SEL_DESELECT); } CTX_DATA_BEGIN (C, Base *, base, visible_bases) { @@ -400,7 +406,6 @@ static int object_select_by_type_exec(bContext *C, wmOperator *op) } CTX_DATA_END; - Scene *scene = CTX_data_scene(C); DEG_id_tag_update(&scene->id, ID_RECALC_SELECT); WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene); @@ -623,10 +628,11 @@ static int object_select_linked_exec(bContext *C, wmOperator *op) extend = RNA_boolean_get(op->ptr, "extend"); if (extend == 0) { - ED_object_base_deselect_all(view_layer, v3d, SEL_DESELECT); + ED_object_base_deselect_all(scene, view_layer, v3d, SEL_DESELECT); } - ob = OBACT(view_layer); + BKE_view_layer_synced_ensure(scene, view_layer); + ob = BKE_view_layer_active_object_get(view_layer); if (ob == NULL) { BKE_report(op->reports, RPT_ERROR, "No active object"); return OPERATOR_CANCELLED; @@ -777,17 +783,21 @@ static bool select_grouped_children(bContext *C, Object *ob, const bool recursiv return changed; } -static bool select_grouped_parent(bContext *C) /* Makes parent active and de-selected OBACT */ +/* Makes parent active and de-selected BKE_view_layer_active_object_get. */ +static bool select_grouped_parent(bContext *C) { + Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); View3D *v3d = CTX_wm_view3d(C); Base *baspar, *basact = CTX_data_active_base(C); bool changed = false; if (!basact || !(basact->object->parent)) { - return 0; /* we know OBACT is valid */ + /* We know BKE_view_layer_active_object_get is valid. */ + return 0; } + BKE_view_layer_synced_ensure(scene, view_layer); baspar = BKE_view_layer_base_find(view_layer, basact->object->parent); /* can be NULL if parent in other scene */ @@ -856,6 +866,7 @@ static bool select_grouped_collection(bContext *C, Object *ob) static bool select_grouped_object_hooks(bContext *C, Object *ob) { + const Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); View3D *v3d = CTX_wm_view3d(C); @@ -868,6 +879,7 @@ static bool select_grouped_object_hooks(bContext *C, Object *ob) if (md->type == eModifierType_Hook) { hmd = (HookModifierData *)md; if (hmd->object) { + BKE_view_layer_synced_ensure(scene, view_layer); base = BKE_view_layer_base_find(view_layer, hmd->object); if (base && ((base->flag & BASE_SELECTED) == 0) && (BASE_SELECTABLE(v3d, base))) { ED_object_base_select(base, BA_SELECT); @@ -1018,10 +1030,11 @@ static int object_select_grouped_exec(bContext *C, wmOperator *op) extend = RNA_boolean_get(op->ptr, "extend"); if (extend == 0) { - changed = ED_object_base_deselect_all(view_layer, v3d, SEL_DESELECT); + changed = ED_object_base_deselect_all(scene, view_layer, v3d, SEL_DESELECT); } - ob = OBACT(view_layer); + BKE_view_layer_synced_ensure(scene, view_layer); + ob = BKE_view_layer_active_object_get(view_layer); if (ob == NULL) { BKE_report(op->reports, RPT_ERROR, "No active object"); return OPERATOR_CANCELLED; @@ -1111,15 +1124,15 @@ void OBJECT_OT_select_grouped(wmOperatorType *ot) static int object_select_all_exec(bContext *C, wmOperator *op) { + Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); View3D *v3d = CTX_wm_view3d(C); int action = RNA_enum_get(op->ptr, "action"); bool any_visible = false; - bool changed = ED_object_base_deselect_all_ex(view_layer, v3d, action, &any_visible); + bool changed = ED_object_base_deselect_all_ex(scene, view_layer, v3d, action, &any_visible); if (changed) { - Scene *scene = CTX_data_scene(C); DEG_id_tag_update(&scene->id, ID_RECALC_SELECT); WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene); @@ -1238,6 +1251,7 @@ static int object_select_mirror_exec(bContext *C, wmOperator *op) if (!STREQ(name_flip, primbase->object->id.name + 2)) { Object *ob = (Object *)BKE_libblock_find_name(bmain, ID_OB, name_flip); if (ob) { + BKE_view_layer_synced_ensure(scene, view_layer); Base *secbase = BKE_view_layer_base_find(view_layer, ob); if (secbase) { @@ -1289,9 +1303,11 @@ void OBJECT_OT_select_mirror(wmOperatorType *ot) static bool object_select_more_less(bContext *C, const bool select) { + Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); - LISTBASE_FOREACH (Base *, base, &view_layer->object_bases) { + BKE_view_layer_synced_ensure(scene, view_layer); + LISTBASE_FOREACH (Base *, base, BKE_view_layer_object_bases_get(view_layer)) { Object *ob = base->object; ob->flag &= ~OB_DONE; ob->id.tag &= ~LIB_TAG_DOIT; diff --git a/source/blender/editors/object/object_shader_fx.c b/source/blender/editors/object/object_shader_fx.c index dd7fc192dc1..4b721cb65a1 100644 --- a/source/blender/editors/object/object_shader_fx.c +++ b/source/blender/editors/object/object_shader_fx.c @@ -481,12 +481,15 @@ static int shaderfx_remove_exec(bContext *C, wmOperator *op) Main *bmain = CTX_data_main(C); Object *ob = ED_object_active_context(C); ShaderFxData *fx = edit_shaderfx_property_get(op, ob, 0); + if (!fx) { + return OPERATOR_CANCELLED; + } /* Store name temporarily for report. */ char name[MAX_NAME]; strcpy(name, fx->name); - if (!fx || !ED_object_shaderfx_remove(op->reports, bmain, ob, fx)) { + if (!ED_object_shaderfx_remove(op->reports, bmain, ob, fx)) { return OPERATOR_CANCELLED; } @@ -671,7 +674,9 @@ static int shaderfx_copy_exec(bContext *C, wmOperator *op) { Object *ob = ED_object_active_context(C); ShaderFxData *fx = edit_shaderfx_property_get(op, ob, 0); - + if (!fx) { + return OPERATOR_CANCELLED; + } ShaderFxData *nfx = BKE_shaderfx_new(fx->type); if (!nfx) { return OPERATOR_CANCELLED; diff --git a/source/blender/editors/object/object_shapekey.c b/source/blender/editors/object/object_shapekey.c index 0e3945bff15..0328f6a6230 100644 --- a/source/blender/editors/object/object_shapekey.c +++ b/source/blender/editors/object/object_shapekey.c @@ -114,14 +114,13 @@ static bool object_shape_key_mirror( if (ob->type == OB_MESH) { Mesh *me = ob->data; - MVert *mv; int i1, i2; float *fp1, *fp2; float tvec[3]; ED_mesh_mirror_spatial_table_begin(ob, NULL, NULL); - for (i1 = 0, mv = me->mvert; i1 < me->totvert; i1++, mv++) { + for (i1 = 0; i1 < me->totvert; i1++) { i2 = mesh_get_x_mirror_vert(ob, NULL, i1, use_topology); if (i2 == i1) { fp1 = ((float *)kb->data) + i1 * 3; diff --git a/source/blender/editors/object/object_transform.cc b/source/blender/editors/object/object_transform.cc index c612a84a631..0a86ae28b3e 100644 --- a/source/blender/editors/object/object_transform.cc +++ b/source/blender/editors/object/object_transform.cc @@ -321,7 +321,7 @@ static int object_clear_transform_generic_exec(bContext *C, BKE_scene_graph_evaluated_ensure(depsgraph, bmain); xcs = ED_object_xform_skip_child_container_create(); ED_object_xform_skip_child_container_item_ensure_from_array( - xcs, view_layer, objects.data(), objects.size()); + xcs, scene, view_layer, objects.data(), objects.size()); } if (use_transform_data_origin) { BKE_scene_graph_evaluated_ensure(depsgraph, bmain); @@ -1033,7 +1033,9 @@ static int apply_objects_internal(bContext *C, zero_v3(ob->rot); zero_v3(ob->drot); unit_qt(ob->quat); + unit_qt(ob->dquat); unit_axis_angle(ob->rotAxis, &ob->rotAngle); + unit_axis_angle(ob->drotAxis, &ob->drotAngle); } } diff --git a/source/blender/editors/object/object_utils.c b/source/blender/editors/object/object_utils.c index cb9c8a92abe..50ba5b8af5f 100644 --- a/source/blender/editors/object/object_utils.c +++ b/source/blender/editors/object/object_utils.c @@ -22,6 +22,7 @@ #include "BKE_armature.h" #include "BKE_editmesh.h" #include "BKE_lattice.h" +#include "BKE_layer.h" #include "BKE_object.h" #include "BKE_scene.h" @@ -169,6 +170,7 @@ struct XFormObjectSkipChild_Container *ED_object_xform_skip_child_container_crea void ED_object_xform_skip_child_container_item_ensure_from_array( struct XFormObjectSkipChild_Container *xcs, + const Scene *scene, ViewLayer *view_layer, Object **objects, uint objects_len) @@ -178,8 +180,9 @@ void ED_object_xform_skip_child_container_item_ensure_from_array( Object *ob = objects[ob_index]; BLI_gset_add(objects_in_transdata, ob); } - - LISTBASE_FOREACH (Base *, base, &view_layer->object_bases) { + BKE_view_layer_synced_ensure(scene, view_layer); + ListBase *object_bases = BKE_view_layer_object_bases_get(view_layer); + LISTBASE_FOREACH (Base *, base, object_bases) { Object *ob = base->object; if (ob->parent != NULL) { if (!BLI_gset_haskey(objects_in_transdata, ob)) { @@ -209,7 +212,7 @@ void ED_object_xform_skip_child_container_item_ensure_from_array( } } - LISTBASE_FOREACH (Base *, base, &view_layer->object_bases) { + LISTBASE_FOREACH (Base *, base, object_bases) { Object *ob = base->object; if (BLI_gset_haskey(objects_in_transdata, ob)) { diff --git a/source/blender/editors/object/object_vgroup.cc b/source/blender/editors/object/object_vgroup.cc index f4f5b31e86a..44fea0b32f0 100644 --- a/source/blender/editors/object/object_vgroup.cc +++ b/source/blender/editors/object/object_vgroup.cc @@ -31,6 +31,7 @@ #include "BLI_utildefines_stack.h" #include "BLI_vector.hh" +#include "BKE_attribute.hh" #include "BKE_context.h" #include "BKE_customdata.h" #include "BKE_deform.h" @@ -67,6 +68,9 @@ #include "object_intern.h" +using blender::MutableSpan; +using blender::Span; + static bool vertex_group_supported_poll_ex(bContext *C, const Object *ob); /* -------------------------------------------------------------------- */ @@ -151,6 +155,7 @@ bool ED_vgroup_parray_alloc(ID *id, int *dvert_tot, const bool use_vert_sel) { + using namespace blender; *dvert_tot = 0; *dvert_arr = nullptr; @@ -196,22 +201,25 @@ bool ED_vgroup_parray_alloc(ID *id, return true; } - if (me->dvert) { - MVert *mvert = me->mvert; - MDeformVert *dvert = me->dvert; + if (!me->deform_verts().is_empty()) { + MutableSpan<MDeformVert> dverts = me->deform_verts_for_write(); *dvert_tot = me->totvert; *dvert_arr = static_cast<MDeformVert **>( MEM_mallocN(sizeof(void *) * me->totvert, __func__)); if (use_vert_sel) { + const bke::AttributeAccessor attributes = me->attributes(); + const VArray<bool> select_vert = attributes.lookup_or_default<bool>( + ".select_vert", ATTR_DOMAIN_POINT, false); + for (int i = 0; i < me->totvert; i++) { - (*dvert_arr)[i] = (mvert[i].flag & SELECT) ? &dvert[i] : nullptr; + (*dvert_arr)[i] = select_vert[i] ? &dverts[i] : nullptr; } } else { for (int i = 0; i < me->totvert; i++) { - (*dvert_arr)[i] = me->dvert + i; + (*dvert_arr)[i] = &dverts[i]; } } @@ -274,7 +282,7 @@ void ED_vgroup_parray_mirror_sync(Object *ob, } int flip_map_len; - const int *flip_map = BKE_object_defgroup_flip_map(ob, &flip_map_len, true); + const int *flip_map = BKE_object_defgroup_flip_map(ob, true, &flip_map_len); for (int i_src = 0; i_src < dvert_tot; i_src++) { if (dvert_array[i_src] != nullptr) { @@ -503,14 +511,14 @@ static void mesh_defvert_mirror_update_internal(Object *ob, if (def_nr == -1) { /* All vgroups, add groups where needed. */ int flip_map_len; - int *flip_map = BKE_object_defgroup_flip_map(ob, &flip_map_len, true); + int *flip_map = BKE_object_defgroup_flip_map_unlocked(ob, true, &flip_map_len); BKE_defvert_sync_mapped(dvert_dst, dvert_src, flip_map, flip_map_len, true); MEM_freeN(flip_map); } else { /* Single vgroup. */ MDeformWeight *dw = BKE_defvert_ensure_index(dvert_dst, - BKE_object_defgroup_flip_index(ob, def_nr, 1)); + BKE_object_defgroup_flip_index(ob, def_nr, true)); if (dw) { dw->weight = BKE_defvert_find_weight(dvert_src, def_nr); } @@ -548,9 +556,10 @@ static void ED_mesh_defvert_mirror_update_ob(Object *ob, int def_nr, int vidx) vidx_mirr = mesh_get_x_mirror_vert(ob, nullptr, vidx, use_topology); + MutableSpan<MDeformVert> dverts = me->deform_verts_for_write(); if ((vidx_mirr) >= 0 && (vidx_mirr != vidx)) { - MDeformVert *dvert_src = &me->dvert[vidx]; - MDeformVert *dvert_dst = &me->dvert[vidx_mirr]; + MDeformVert *dvert_src = &dverts[vidx]; + MDeformVert *dvert_dst = &dverts[vidx_mirr]; mesh_defvert_mirror_update_internal(ob, dvert_dst, dvert_src, def_nr); } } @@ -632,6 +641,7 @@ static bool vgroup_normalize_active_vertex(Object *ob, eVGroupSelect subset_type static void vgroup_copy_active_to_sel(Object *ob, eVGroupSelect subset_type) { + using namespace blender; Mesh *me = static_cast<Mesh *>(ob->data); BMEditMesh *em = me->edit_mesh; MDeformVert *dvert_act; @@ -659,15 +669,18 @@ static void vgroup_copy_active_to_sel(Object *ob, eVGroupSelect subset_type) } } else { - MDeformVert *dv; + const bke::AttributeAccessor attributes = me->attributes(); + const VArray<bool> select_vert = attributes.lookup_or_default<bool>( + ".select_vert", ATTR_DOMAIN_POINT, false); + int v_act; dvert_act = ED_mesh_active_dvert_get_ob(ob, &v_act); if (dvert_act) { - dv = me->dvert; - for (i = 0; i < me->totvert; i++, dv++) { - if ((me->mvert[i].flag & SELECT) && dv != dvert_act) { - BKE_defvert_copy_subset(dv, dvert_act, vgroup_validmap, vgroup_tot); + MutableSpan<MDeformVert> dverts = me->deform_verts_for_write(); + for (i = 0; i < me->totvert; i++) { + if (select_vert[i] && &dverts[i] != dvert_act) { + BKE_defvert_copy_subset(&dverts[i], dvert_act, vgroup_validmap, vgroup_tot); if (me->symmetry & ME_SYMMETRY_X) { ED_mesh_defvert_mirror_update_ob(ob, -1, i); } @@ -927,7 +940,7 @@ void ED_vgroup_vert_remove(Object *ob, bDeformGroup *dg, int vertnum) static float get_vert_def_nr(Object *ob, const int def_nr, const int vertnum) { - MDeformVert *dv = nullptr; + const MDeformVert *dv = nullptr; /* get the deform vertices corresponding to the vertnum */ if (ob->type == OB_MESH) { @@ -942,18 +955,19 @@ static float get_vert_def_nr(Object *ob, const int def_nr, const int vertnum) BMVert *eve; BM_mesh_elem_table_ensure(em->bm, BM_VERT); eve = BM_vert_at_index(em->bm, vertnum); - dv = static_cast<MDeformVert *>(BM_ELEM_CD_GET_VOID_P(eve, cd_dvert_offset)); + dv = static_cast<const MDeformVert *>(BM_ELEM_CD_GET_VOID_P(eve, cd_dvert_offset)); } else { return 0.0f; } } else { - if (me->dvert) { + const Span<MDeformVert> dverts = me->deform_verts(); + if (!dverts.is_empty()) { if (vertnum >= me->totvert) { return 0.0f; } - dv = &me->dvert[vertnum]; + dv = &dverts[vertnum]; } } } @@ -1006,6 +1020,7 @@ void ED_vgroup_select_by_name(Object *ob, const char *name) /* only in editmode */ static void vgroup_select_verts(Object *ob, int select) { + using namespace blender; const int def_nr = BKE_object_defgroup_active_index_get(ob) - 1; const ListBase *defbase = BKE_object_defgroup_list(ob); @@ -1044,29 +1059,23 @@ static void vgroup_select_verts(Object *ob, int select) } } else { - if (me->dvert) { - const bool *hide_vert = (const bool *)CustomData_get_layer_named( - &me->vdata, CD_PROP_BOOL, ".hide_vert"); - MVert *mv; - MDeformVert *dv; - int i; - - mv = me->mvert; - dv = me->dvert; - - for (i = 0; i < me->totvert; i++, mv++, dv++) { - if (hide_vert != nullptr && !hide_vert[i]) { - if (BKE_defvert_find_index(dv, def_nr)) { - if (select) { - mv->flag |= SELECT; - } - else { - mv->flag &= ~SELECT; - } + const Span<MDeformVert> dverts = me->deform_verts(); + if (!dverts.is_empty()) { + bke::MutableAttributeAccessor attributes = me->attributes_for_write(); + const VArray<bool> hide_vert = attributes.lookup_or_default<bool>( + ".hide_vert", ATTR_DOMAIN_POINT, false); + bke::SpanAttributeWriter<bool> select_vert = + attributes.lookup_or_add_for_write_only_span<bool>(".select_vert", ATTR_DOMAIN_POINT); + + for (const int i : select_vert.span.index_range()) { + if (!hide_vert[i]) { + if (BKE_defvert_find_index(&dverts[i], def_nr)) { + select_vert.span[i] = select; } } } + select_vert.finish(); paintvert_flush_flags(ob); } } @@ -1214,7 +1223,8 @@ static bool vgroup_normalize(Object *ob) * count is an int passed by reference so it can be assigned the value of the length here. */ static blender::Vector<int> getSurroundingVerts(Mesh *me, int vert) { - MPoly *mp = me->mpoly; + const MPoly *mp = me->polys().data(); + const MLoop *loops = me->loops().data(); int i = me->totpoly; blender::Vector<int> verts; @@ -1222,7 +1232,7 @@ static blender::Vector<int> getSurroundingVerts(Mesh *me, int vert) while (i--) { int j = mp->totloop; int first_l = mp->totloop - 1; - MLoop *ml = &me->mloop[mp->loopstart]; + const MLoop *ml = &loops[mp->loopstart]; while (j--) { /* XXX This assume a vert can only be once in a poly, even though * it seems logical to me, not totally sure of that. */ @@ -1236,7 +1246,7 @@ static blender::Vector<int> getSurroundingVerts(Mesh *me, int vert) else if (!j) { /* We are on the last corner. */ a = (ml - 1)->v; - b = me->mloop[mp->loopstart].v; + b = loops[mp->loopstart].v; } else { a = (ml - 1)->v; @@ -1319,14 +1329,15 @@ static void getVerticalAndHorizontalChange(const float norm[3], changes[index][1] = len_v3v3(projA, projB); } -/* by changing nonzero weights, try to move a vertex in me->mverts with index 'index' to - * distToBe distance away from the provided plane strength can change distToBe so that it moves - * towards distToBe by that percentage cp changes how much the weights are adjusted +/** + * By changing nonzero weights, try to move a vertex in `me->mverts` with index 'index' to + * `distToBe` distance away from the provided plane strength can change `distToBe` so that it moves + * towards `distToBe` by that percentage `cp` changes how much the weights are adjusted * to check the distance * - * index is the index of the vertex being moved - * norm and d are the plane's properties for the equation: ax + by + cz + d = 0 - * coord is a point on the plane + * `index` is the index of the vertex being moved. + * `norm` and `d` are the plane's properties for the equation: `ax + by + cz + d = 0`. + * `coord` is a point on the plane. */ static void moveCloserToDistanceFromPlane(Depsgraph *depsgraph, Scene *UNUSED(scene), @@ -1347,8 +1358,8 @@ static void moveCloserToDistanceFromPlane(Depsgraph *depsgraph, Mesh *me_deform; MDeformWeight *dw, *dw_eval; MVert m; - MDeformVert *dvert = me->dvert + index; - MDeformVert *dvert_eval = mesh_eval->dvert + index; + MDeformVert *dvert = me->deform_verts_for_write().data() + index; + MDeformVert *dvert_eval = mesh_eval->deform_verts_for_write().data() + index; int totweight = dvert->totweight; float oldw = 0; float oldPos[3] = {0}; @@ -1371,7 +1382,8 @@ static void moveCloserToDistanceFromPlane(Depsgraph *depsgraph, do { wasChange = false; me_deform = mesh_get_eval_deform(depsgraph, scene_eval, object_eval, &CD_MASK_BAREMESH); - m = me_deform->mvert[index]; + const Span<MVert> verts = me_deform->verts(); + m = verts[index]; copy_v3_v3(oldPos, m.co); distToStart = dot_v3v3(norm, oldPos) + d; @@ -1413,7 +1425,7 @@ static void moveCloserToDistanceFromPlane(Depsgraph *depsgraph, } dw_eval->weight = dw->weight; me_deform = mesh_get_eval_deform(depsgraph, scene_eval, object_eval, &CD_MASK_BAREMESH); - m = me_deform->mvert[index]; + m = verts[index]; getVerticalAndHorizontalChange( norm, d, coord, oldPos, distToStart, m.co, changes, dists, i); dw->weight = oldw; @@ -1512,18 +1524,22 @@ static void moveCloserToDistanceFromPlane(Depsgraph *depsgraph, static void vgroup_fix( const bContext *C, Scene *UNUSED(scene), Object *ob, float distToBe, float strength, float cp) { + using namespace blender; Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C); Scene *scene_eval = DEG_get_evaluated_scene(depsgraph); Object *object_eval = DEG_get_evaluated_object(depsgraph, ob); int i; Mesh *me = static_cast<Mesh *>(ob->data); - MVert *mvert = me->mvert; + MVert *mvert = me->verts_for_write().data(); if (!(me->editflag & ME_EDIT_PAINT_VERT_SEL)) { return; } + const bke::AttributeAccessor attributes = me->attributes(); + const VArray<bool> select_vert = attributes.lookup_or_default<bool>( + ".select_vert", ATTR_DOMAIN_POINT, false); for (i = 0; i < me->totvert && mvert; i++, mvert++) { - if (mvert->flag & SELECT) { + if (select_vert[i]) { blender::Vector<int> verts = getSurroundingVerts(me, i); const int count = verts.size(); if (!verts.is_empty()) { @@ -1533,9 +1549,10 @@ static void vgroup_fix( Mesh *me_deform = mesh_get_eval_deform( depsgraph, scene_eval, object_eval, &CD_MASK_BAREMESH); + const Span<MVert> verts_deform = me_deform->verts(); k = count; while (k--) { - p[k] = me_deform->mvert[verts[k]]; + p[k] = verts_deform[verts[k]]; } if (count >= 3) { @@ -1543,7 +1560,7 @@ static void vgroup_fix( float coord[3]; float norm[3]; getSingleCoordinate(p, count, coord); - m = me_deform->mvert[i]; + m = verts_deform[i]; sub_v3_v3v3(norm, m.co, coord); mag = normalize_v3(norm); if (mag) { /* zeros fix */ @@ -1772,7 +1789,8 @@ static void vgroup_lock_all(Object *ob, int action, int mask) continue; } break; - default:; + default: + break; } if (dg->flag & DG_LOCK_WEIGHT) { @@ -1794,7 +1812,8 @@ static void vgroup_lock_all(Object *ob, int action, int mask) continue; } break; - default:; + default: + break; } switch (action) { @@ -1883,6 +1902,7 @@ static void vgroup_smooth_subset(Object *ob, const int repeat, const float fac_expand) { + using namespace blender; const float ifac = 1.0f - fac; MDeformVert **dvert_array = nullptr; int dvert_tot = 0; @@ -1902,6 +1922,10 @@ static void vgroup_smooth_subset(Object *ob, BMesh *bm = em ? em->bm : nullptr; Mesh *me = em ? nullptr : static_cast<Mesh *>(ob->data); + const bke::AttributeAccessor attributes = me->attributes(); + const VArray<bool> select_vert = attributes.lookup_or_default<bool>( + ".select_vert", ATTR_DOMAIN_POINT, false); + MeshElemMap *emap; int *emap_mem; @@ -1926,7 +1950,7 @@ static void vgroup_smooth_subset(Object *ob, emap_mem = nullptr; } else { - BKE_mesh_vert_edge_map_create(&emap, &emap_mem, me->medge, me->totvert, me->totedge); + BKE_mesh_vert_edge_map_create(&emap, &emap_mem, me->edges().data(), me->totvert, me->totedge); } weight_accum_prev = static_cast<float *>( @@ -1944,8 +1968,8 @@ static void vgroup_smooth_subset(Object *ob, &me->vdata, CD_PROP_BOOL, ".hide_vert") : nullptr; -#define IS_ME_VERT_READ(v) (use_hide ? (hide_vert && hide_vert[v]) : true) -#define IS_ME_VERT_WRITE(v) (use_select ? (((v)->flag & SELECT) != 0) : true) +#define IS_ME_VERT_READ(v) (use_hide ? !(hide_vert && hide_vert[v]) : true) +#define IS_ME_VERT_WRITE(v) (use_select ? select_vert[v] : true) /* initialize used verts */ if (bm) { @@ -1965,11 +1989,11 @@ static void vgroup_smooth_subset(Object *ob, } } else { + const blender::Span<MEdge> edges = me->edges(); for (int i = 0; i < dvert_tot; i++) { - const MVert *v = &me->mvert[i]; - if (IS_ME_VERT_WRITE(v)) { + if (IS_ME_VERT_WRITE(i)) { for (int j = 0; j < emap[i].count; j++) { - const MEdge *e = &me->medge[emap[i].indices[j]]; + const MEdge *e = &edges[emap[i].indices[j]]; const int i_other = (e->v1 == i) ? e->v2 : e->v1; if (IS_ME_VERT_READ(i_other)) { STACK_PUSH(verts_used, i); @@ -2038,12 +2062,13 @@ static void vgroup_smooth_subset(Object *ob, } else { int j; + const blender::Span<MEdge> edges = me->edges(); /* checked already */ - BLI_assert(IS_ME_VERT_WRITE(&me->mvert[i])); + BLI_assert(IS_ME_VERT_WRITE(i)); for (j = 0; j < emap[i].count; j++) { - MEdge *e = &me->medge[emap[i].indices[j]]; + const MEdge *e = &edges[emap[i].indices[j]]; const int i_other = (e->v1 == i ? e->v2 : e->v1); if (IS_ME_VERT_READ(i_other)) { WEIGHT_ACCUMULATE; @@ -2347,6 +2372,7 @@ void ED_vgroup_mirror(Object *ob, int *r_totmirr, int *r_totfail) { + using namespace blender; /* TODO: vgroup locking. * TODO: face masking. */ @@ -2363,7 +2389,7 @@ void ED_vgroup_mirror(Object *ob, def_nr) BMVert *eve, *eve_mirr; - MDeformVert *dvert, *dvert_mirr; + MDeformVert *dvert_mirr; char sel, sel_mirr; int *flip_map = nullptr, flip_map_len; const int def_nr = BKE_object_defgroup_active_index_get(ob) - 1; @@ -2379,8 +2405,8 @@ void ED_vgroup_mirror(Object *ob, } if (flip_vgroups) { - flip_map = all_vgroups ? BKE_object_defgroup_flip_map(ob, &flip_map_len, false) : - BKE_object_defgroup_flip_map_single(ob, &flip_map_len, false, def_nr); + flip_map = all_vgroups ? BKE_object_defgroup_flip_map(ob, false, &flip_map_len) : + BKE_object_defgroup_flip_map_single(ob, false, def_nr, &flip_map_len); BLI_assert(flip_map != nullptr); @@ -2421,7 +2447,8 @@ void ED_vgroup_mirror(Object *ob, sel_mirr = BM_elem_flag_test(eve_mirr, BM_ELEM_SELECT); if ((sel || sel_mirr) && (eve != eve_mirr)) { - dvert = static_cast<MDeformVert *>(BM_ELEM_CD_GET_VOID_P(eve, cd_dvert_offset)); + MDeformVert *dvert = static_cast<MDeformVert *>( + BM_ELEM_CD_GET_VOID_P(eve, cd_dvert_offset)); dvert_mirr = static_cast<MDeformVert *>( BM_ELEM_CD_GET_VOID_P(eve_mirr, cd_dvert_offset)); @@ -2444,11 +2471,10 @@ void ED_vgroup_mirror(Object *ob, } else { /* object mode / weight paint */ - MVert *mv, *mv_mirr; int vidx, vidx_mirr; const bool use_vert_sel = (me->editflag & ME_EDIT_PAINT_VERT_SEL) != 0; - if (me->dvert == nullptr) { + if (me->deform_verts().is_empty()) { goto cleanup; } @@ -2457,22 +2483,25 @@ void ED_vgroup_mirror(Object *ob, } BLI_bitmap *vert_tag = BLI_BITMAP_NEW(me->totvert, __func__); + MutableSpan<MDeformVert> dverts = me->deform_verts_for_write(); + const bke::AttributeAccessor attributes = me->attributes(); + const VArray<bool> select_vert = attributes.lookup_or_default<bool>( + ".select_vert", ATTR_DOMAIN_POINT, false); - for (vidx = 0, mv = me->mvert; vidx < me->totvert; vidx++, mv++) { + for (vidx = 0; vidx < me->totvert; vidx++) { if (!BLI_BITMAP_TEST(vert_tag, vidx)) { if ((vidx_mirr = mesh_get_x_mirror_vert(ob, nullptr, vidx, use_topology)) != -1) { if (vidx != vidx_mirr) { - mv_mirr = &me->mvert[vidx_mirr]; if (!BLI_BITMAP_TEST(vert_tag, vidx_mirr)) { if (use_vert_sel) { - sel = mv->flag & SELECT; - sel_mirr = mv_mirr->flag & SELECT; + sel = select_vert[vidx]; + sel_mirr = select_vert[vidx_mirr]; } if (sel || sel_mirr) { - dvert = &me->dvert[vidx]; - dvert_mirr = &me->dvert[vidx_mirr]; + MDeformVert *dvert = &dverts[vidx]; + dvert_mirr = &dvert[vidx_mirr]; VGROUP_MIRR_OP; totmirr++; @@ -2525,7 +2554,7 @@ void ED_vgroup_mirror(Object *ob, sel_mirr = bp_mirr->f1 & SELECT; if (sel || sel_mirr) { - dvert = <->dvert[i1]; + MDeformVert *dvert = <->dvert[i1]; dvert_mirr = <->dvert[i2]; VGROUP_MIRR_OP; @@ -2571,6 +2600,7 @@ static void vgroup_delete_active(Object *ob) /* only in editmode */ static void vgroup_assign_verts(Object *ob, const float weight) { + using namespace blender; const int def_nr = BKE_object_defgroup_active_index_get(ob) - 1; const ListBase *defbase = BKE_object_defgroup_list(ob); @@ -2609,17 +2639,16 @@ static void vgroup_assign_verts(Object *ob, const float weight) } } else { - if (!me->dvert) { - BKE_object_defgroup_data_create(&me->id); - } + const bke::AttributeAccessor attributes = me->attributes(); + const VArray<bool> select_vert = attributes.lookup_or_default<bool>( + ".select_vert", ATTR_DOMAIN_POINT, false); - MVert *mv = me->mvert; - MDeformVert *dv = me->dvert; + MutableSpan<MDeformVert> dverts = me->deform_verts_for_write(); - for (int i = 0; i < me->totvert; i++, mv++, dv++) { - if (mv->flag & SELECT) { + for (int i = 0; i < me->totvert; i++) { + if (select_vert[i]) { MDeformWeight *dw; - dw = BKE_defvert_ensure_index(dv, def_nr); + dw = BKE_defvert_ensure_index(&dverts[i], def_nr); if (dw) { dw->weight = weight; } @@ -2730,7 +2759,7 @@ static bool vertex_group_mesh_with_dvert_poll(bContext *C) } Mesh *me = static_cast<Mesh *>(ob->data); - if (me->dvert == nullptr) { + if (me->deform_verts().is_empty()) { CTX_wm_operator_poll_msg_set(C, "The active mesh object has no vertex group data"); return false; } @@ -2924,10 +2953,10 @@ void OBJECT_OT_vertex_group_remove(wmOperatorType *ot) ot->flag = /*OPTYPE_REGISTER|*/ OPTYPE_UNDO; /* properties */ - PropertyRNA *prop = RNA_def_boolean(ot->srna, "all", 0, "All", "Remove all vertex groups"); + PropertyRNA *prop = RNA_def_boolean(ot->srna, "all", false, "All", "Remove all vertex groups"); RNA_def_property_flag(prop, PROP_SKIP_SAVE); prop = RNA_def_boolean( - ot->srna, "all_unlocked", 0, "All Unlocked", "Remove all unlocked vertex groups"); + ot->srna, "all_unlocked", false, "All Unlocked", "Remove all unlocked vertex groups"); RNA_def_property_flag(prop, PROP_SKIP_SAVE); } @@ -3054,9 +3083,11 @@ void OBJECT_OT_vertex_group_remove_from(wmOperatorType *ot) ot->flag = /*OPTYPE_REGISTER|*/ OPTYPE_UNDO; /* properties */ - prop = RNA_def_boolean(ot->srna, "use_all_groups", 0, "All Groups", "Remove from all groups"); + prop = RNA_def_boolean( + ot->srna, "use_all_groups", false, "All Groups", "Remove from all groups"); RNA_def_property_flag(prop, PROP_SKIP_SAVE); - prop = RNA_def_boolean(ot->srna, "use_all_verts", 0, "All Vertices", "Clear the active group"); + prop = RNA_def_boolean( + ot->srna, "use_all_verts", false, "All Vertices", "Clear the active group"); RNA_def_property_flag(prop, PROP_SKIP_SAVE); } @@ -3856,7 +3887,7 @@ void OBJECT_OT_vertex_group_mirror(wmOperatorType *ot) RNA_def_boolean( ot->srna, "use_topology", - 0, + false, "Topology Mirror", "Use topology based mirroring (for when both sides of mesh have matching, unique topology)"); } @@ -4298,6 +4329,7 @@ void OBJECT_OT_vertex_group_move(wmOperatorType *ot) static void vgroup_copy_active_to_sel_single(Object *ob, const int def_nr) { + using namespace blender; MDeformVert *dvert_act; Mesh *me = static_cast<Mesh *>(ob->data); @@ -4332,7 +4364,6 @@ static void vgroup_copy_active_to_sel_single(Object *ob, const int def_nr) } } else { - MDeformVert *dv; int v_act; dvert_act = ED_mesh_active_dvert_get_ob(ob, &v_act); @@ -4340,11 +4371,14 @@ static void vgroup_copy_active_to_sel_single(Object *ob, const int def_nr) return; } - dv = me->dvert; - for (i = 0; i < me->totvert; i++, dv++) { - if ((me->mvert[i].flag & SELECT) && (dv != dvert_act)) { + MutableSpan<MDeformVert> dverts = me->deform_verts_for_write(); + const bke::AttributeAccessor attributes = me->attributes(); + const VArray<bool> select_vert = attributes.lookup_or_default<bool>( + ".select_vert", ATTR_DOMAIN_POINT, false); - BKE_defvert_copy_index(dv, def_nr, dvert_act, def_nr); + for (i = 0; i < me->totvert; i++) { + if (select_vert[i] && (&dverts[i] != dvert_act)) { + BKE_defvert_copy_index(&dverts[i], def_nr, dvert_act, def_nr); if (me->symmetry & ME_SYMMETRY_X) { ED_mesh_defvert_mirror_update_ob(ob, -1, i); diff --git a/source/blender/editors/physics/CMakeLists.txt b/source/blender/editors/physics/CMakeLists.txt index ee59efbc925..e56d58c2135 100644 --- a/source/blender/editors/physics/CMakeLists.txt +++ b/source/blender/editors/physics/CMakeLists.txt @@ -11,7 +11,6 @@ set(INC ../../makesrna ../../windowmanager ../../../../intern/clog - ../../../../intern/glew-mx ../../../../intern/guardedalloc ../../../../intern/mantaflow/extern # RNA_prototypes.h diff --git a/source/blender/editors/physics/particle_edit.c b/source/blender/editors/physics/particle_edit.c index 03f9b4eb867..99e42710b49 100644 --- a/source/blender/editors/physics/particle_edit.c +++ b/source/blender/editors/physics/particle_edit.c @@ -30,6 +30,7 @@ #include "BKE_bvhutils.h" #include "BKE_context.h" #include "BKE_global.h" +#include "BKE_layer.h" #include "BKE_main.h" #include "BKE_mesh.h" #include "BKE_mesh_legacy_convert.h" @@ -168,7 +169,8 @@ void PE_free_ptcache_edit(PTCacheEdit *edit) int PE_minmax( Depsgraph *depsgraph, Scene *scene, ViewLayer *view_layer, float min[3], float max[3]) { - Object *ob = OBACT(view_layer); + BKE_view_layer_synced_ensure(scene, view_layer); + Object *ob = BKE_view_layer_active_object_get(view_layer); PTCacheEdit *edit = PE_get_current(depsgraph, scene, ob); ParticleSystem *psys; ParticleSystemModifierData *psmd_eval = NULL; @@ -1450,26 +1452,27 @@ void recalc_emitter_field(Depsgraph *UNUSED(depsgraph), Object *UNUSED(ob), Part vec = edit->emitter_cosnos; nor = vec + 3; + const MVert *verts = BKE_mesh_verts(mesh); const float(*vert_normals)[3] = BKE_mesh_vertex_normals_ensure(mesh); - + MFace *mfaces = (MFace *)CustomData_get_layer(&mesh->fdata, CD_MFACE); for (i = 0; i < totface; i++, vec += 6, nor += 6) { - MFace *mface = &mesh->mface[i]; - MVert *mvert; + MFace *mface = &mfaces[i]; + const MVert *mvert; - mvert = &mesh->mvert[mface->v1]; + mvert = &verts[mface->v1]; copy_v3_v3(vec, mvert->co); copy_v3_v3(nor, vert_normals[mface->v1]); - mvert = &mesh->mvert[mface->v2]; + mvert = &verts[mface->v2]; add_v3_v3v3(vec, vec, mvert->co); add_v3_v3(nor, vert_normals[mface->v2]); - mvert = &mesh->mvert[mface->v3]; + mvert = &verts[mface->v3]; add_v3_v3v3(vec, vec, mvert->co); add_v3_v3(nor, vert_normals[mface->v3]); if (mface->v4) { - mvert = &mesh->mvert[mface->v4]; + mvert = &verts[mface->v4]; add_v3_v3v3(vec, vec, mvert->co); add_v3_v3(nor, vert_normals[mface->v4]); @@ -3391,7 +3394,7 @@ static void brush_drawcursor(bContext *C, int x, int y, void *UNUSED(customdata) if (brush) { uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); - immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); immUniformColor4ub(255, 255, 255, 128); @@ -3567,7 +3570,9 @@ static void PE_mirror_x(Depsgraph *depsgraph, Scene *scene, Object *ob, int tagg } if (newtotpart != psys->totpart) { - MFace *mtessface = use_dm_final_indices ? psmd_eval->mesh_final->mface : me->mface; + MFace *mtessface = use_dm_final_indices ? + (MFace *)CustomData_get_layer(&psmd_eval->mesh_final->fdata, CD_MFACE) : + (MFace *)CustomData_get_layer(&me->fdata, CD_MFACE); /* allocate new arrays and copy existing */ new_pars = MEM_callocN(newtotpart * sizeof(ParticleData), "ParticleData new"); @@ -3983,7 +3988,7 @@ static void brush_puff(PEData *data, int point_index, float mouse_distance) /* Translate (not rotate) the rest of the hair if its not selected. */ { /* NOLINTNEXTLINE: readability-redundant-preprocessor */ -# if 0 /* kindof works but looks worse than what's below */ +# if 0 /* Kind of works but looks worse than what's below. */ /* Move the unselected point on a vector based on the * hair direction and the offset */ @@ -4175,8 +4180,8 @@ static int particle_intersect_mesh(Depsgraph *depsgraph, } totface = mesh->totface; - mface = mesh->mface; - mvert = mesh->mvert; + mface = (MFace *)CustomData_get_layer(&mesh->fdata, CD_MFACE); + mvert = BKE_mesh_verts_for_write(mesh); /* lets intersect the faces */ for (i = 0; i < totface; i++, mface++) { diff --git a/source/blender/editors/physics/particle_edit_undo.c b/source/blender/editors/physics/particle_edit_undo.c index 54d28b49e0c..bc9a90b5b3f 100644 --- a/source/blender/editors/physics/particle_edit_undo.c +++ b/source/blender/editors/physics/particle_edit_undo.c @@ -21,6 +21,7 @@ #include "BLI_utildefines.h" #include "BKE_context.h" +#include "BKE_layer.h" #include "BKE_particle.h" #include "BKE_pointcache.h" #include "BKE_undo_system.h" @@ -211,7 +212,8 @@ static bool particle_undosys_poll(struct bContext *C) Depsgraph *depsgraph = CTX_data_depsgraph_pointer(C); Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); - Object *ob = OBACT(view_layer); + BKE_view_layer_synced_ensure(scene, view_layer); + Object *ob = BKE_view_layer_active_object_get(view_layer); PTCacheEdit *edit = PE_get_current(depsgraph, scene, ob); return (edit != NULL); @@ -225,7 +227,8 @@ static bool particle_undosys_step_encode(struct bContext *C, ParticleUndoStep *us = (ParticleUndoStep *)us_p; ViewLayer *view_layer = CTX_data_view_layer(C); us->scene_ref.ptr = CTX_data_scene(C); - us->object_ref.ptr = OBACT(view_layer); + BKE_view_layer_synced_ensure(us->scene_ref.ptr, view_layer); + us->object_ref.ptr = BKE_view_layer_active_object_get(view_layer); PTCacheEdit *edit = PE_get_current(depsgraph, us->scene_ref.ptr, us->object_ref.ptr); undoptcache_from_editcache(&us->data, edit); return true; diff --git a/source/blender/editors/physics/particle_object.c b/source/blender/editors/physics/particle_object.c index 96aea0ededf..08db03db0e9 100644 --- a/source/blender/editors/physics/particle_object.c +++ b/source/blender/editors/physics/particle_object.c @@ -23,6 +23,7 @@ #include "BKE_bvhutils.h" #include "BKE_context.h" #include "BKE_global.h" +#include "BKE_layer.h" #include "BKE_lib_id.h" #include "BKE_main.h" #include "BKE_mesh.h" @@ -118,7 +119,8 @@ static int particle_system_remove_exec(bContext *C, wmOperator *UNUSED(op)) */ if (mode_orig & OB_MODE_PARTICLE_EDIT) { if ((ob->mode & OB_MODE_PARTICLE_EDIT) == 0) { - if (view_layer->basact && view_layer->basact->object == ob) { + BKE_view_layer_synced_ensure(scene, view_layer); + if (BKE_view_layer_active_object_get(view_layer) == ob) { WM_event_add_notifier(C, NC_SCENE | ND_MODE | NS_MODE_OBJECT, NULL); } } @@ -704,7 +706,7 @@ static bool remap_hair_emitter(Depsgraph *depsgraph, PTCacheEditKey *ekey; BVHTreeFromMesh bvhtree = {NULL}; MFace *mface = NULL, *mf; - MEdge *medge = NULL, *me; + const MEdge *medge = NULL, *me; MVert *mvert; Mesh *mesh, *target_mesh; int numverts; @@ -750,7 +752,7 @@ static bool remap_hair_emitter(Depsgraph *depsgraph, BKE_mesh_tessface_ensure(mesh); numverts = mesh->totvert; - mvert = mesh->mvert; + mvert = BKE_mesh_verts_for_write(mesh); /* convert to global coordinates */ for (int i = 0; i < numverts; i++) { @@ -758,11 +760,11 @@ static bool remap_hair_emitter(Depsgraph *depsgraph, } if (mesh->totface != 0) { - mface = mesh->mface; + mface = CustomData_get_layer(&mesh->fdata, CD_MFACE); BKE_bvhtree_from_mesh_get(&bvhtree, mesh, BVHTREE_FROM_FACES, 2); } else if (mesh->totedge != 0) { - medge = mesh->medge; + medge = BKE_mesh_edges(mesh); BKE_bvhtree_from_mesh_get(&bvhtree, mesh, BVHTREE_FROM_EDGES, 2); } else { diff --git a/source/blender/editors/physics/physics_fluid.c b/source/blender/editors/physics/physics_fluid.c index 80de8fae072..1d3cf7c36af 100644 --- a/source/blender/editors/physics/physics_fluid.c +++ b/source/blender/editors/physics/physics_fluid.c @@ -502,6 +502,7 @@ static void fluid_free_startjob(void *customdata, short *stop, short *do_update, BKE_fluid_cache_free(fds, job->ob, cache_map); #else UNUSED_VARS(fds); + UNUSED_VARS(cache_map); #endif *do_update = true; diff --git a/source/blender/editors/physics/rigidbody_constraint.c b/source/blender/editors/physics/rigidbody_constraint.c index 66ae2d323fd..10d97b02066 100644 --- a/source/blender/editors/physics/rigidbody_constraint.c +++ b/source/blender/editors/physics/rigidbody_constraint.c @@ -16,6 +16,7 @@ #include "BKE_collection.h" #include "BKE_context.h" +#include "BKE_layer.h" #include "BKE_lib_id.h" #include "BKE_main.h" #include "BKE_report.h" @@ -88,7 +89,7 @@ bool ED_rigidbody_constraint_add( /* create constraint group if it doesn't already exits */ if (rbw->constraints == NULL) { rbw->constraints = BKE_collection_add(bmain, NULL, "RigidBodyConstraints"); - id_fake_user_set(&rbw->constraints->id); + id_us_plus(&rbw->constraints->id); } /* make rigidbody constraint settings */ ob->rigidbody_constraint = BKE_rigidbody_create_constraint(scene, ob, type); @@ -122,7 +123,8 @@ static int rigidbody_con_add_exec(bContext *C, wmOperator *op) Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); RigidBodyWorld *rbw = BKE_rigidbody_get_world(scene); - Object *ob = OBACT(view_layer); + BKE_view_layer_synced_ensure(scene, view_layer); + Object *ob = BKE_view_layer_active_object_get(view_layer); int type = RNA_enum_get(op->ptr, "type"); bool changed; @@ -174,7 +176,8 @@ static int rigidbody_con_remove_exec(bContext *C, wmOperator *op) Main *bmain = CTX_data_main(C); Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); - Object *ob = OBACT(view_layer); + BKE_view_layer_synced_ensure(scene, view_layer); + Object *ob = BKE_view_layer_active_object_get(view_layer); /* apply to active object */ if (ELEM(NULL, ob, ob->rigidbody_constraint)) { diff --git a/source/blender/editors/render/CMakeLists.txt b/source/blender/editors/render/CMakeLists.txt index 4b644ae826f..a91a63201c4 100644 --- a/source/blender/editors/render/CMakeLists.txt +++ b/source/blender/editors/render/CMakeLists.txt @@ -17,7 +17,6 @@ set(INC ../../render ../../sequencer ../../windowmanager - ../../../../intern/glew-mx ../../../../intern/guardedalloc # RNA_prototypes.h ${CMAKE_BINARY_DIR}/source/blender/makesrna diff --git a/source/blender/editors/render/render_internal.cc b/source/blender/editors/render/render_internal.cc index 157c9bc7222..7f6a14126e0 100644 --- a/source/blender/editors/render/render_internal.cc +++ b/source/blender/editors/render/render_internal.cc @@ -32,6 +32,7 @@ #include "BKE_global.h" #include "BKE_image.h" #include "BKE_image_format.h" +#include "BKE_layer.h" #include "BKE_lib_id.h" #include "BKE_main.h" #include "BKE_node.h" @@ -856,7 +857,7 @@ static void screen_render_cancel(bContext *C, wmOperator *op) static void clean_viewport_memory_base(Base *base) { - if ((base->flag & BASE_VISIBLE_DEPSGRAPH) == 0) { + if ((base->flag & BASE_ENABLED_AND_MAYBE_VISIBLE_IN_VIEWPORT) == 0) { return; } @@ -885,9 +886,10 @@ static void clean_viewport_memory(Main *bmain, Scene *scene) wm = static_cast<wmWindowManager *>(wm->id.next)) { LISTBASE_FOREACH (wmWindow *, win, &wm->windows) { ViewLayer *view_layer = WM_window_get_active_view_layer(win); + BKE_view_layer_synced_ensure(scene, view_layer); - for (base = static_cast<Base *>(view_layer->object_bases.first); base; base = base->next) { - clean_viewport_memory_base(base); + LISTBASE_FOREACH (Base *, b, BKE_view_layer_object_bases_get(view_layer)) { + clean_viewport_memory_base(b); } } } diff --git a/source/blender/editors/render/render_preview.cc b/source/blender/editors/render/render_preview.cc index cd0a05f02bc..10de7063bbc 100644 --- a/source/blender/editors/render/render_preview.cc +++ b/source/blender/editors/render/render_preview.cc @@ -307,7 +307,8 @@ static void switch_preview_floor_visibility(Main *pr_main, const ePreviewRenderMethod pr_method) { /* Hide floor for icon renders. */ - LISTBASE_FOREACH (Base *, base, &view_layer->object_bases) { + BKE_view_layer_synced_ensure(scene, view_layer); + LISTBASE_FOREACH (Base *, base, BKE_view_layer_object_bases_get(view_layer)) { if (STREQ(base->object->id.name + 2, "Floor")) { base->object->visibility_flag &= ~OB_HIDE_RENDER; if (pr_method == PR_ICON_RENDER) { @@ -533,8 +534,8 @@ static Scene *preview_prepare_scene( else { sce->display.render_aa = SCE_DISPLAY_AA_OFF; } - - LISTBASE_FOREACH (Base *, base, &view_layer->object_bases) { + BKE_view_layer_synced_ensure(sce, view_layer); + LISTBASE_FOREACH (Base *, base, BKE_view_layer_object_bases_get(view_layer)) { if (base->object->id.name[2] == 'p') { /* copy over object color, in case material uses it */ copy_v4_v4(base->object->color, sp->color); @@ -550,7 +551,7 @@ static Scene *preview_prepare_scene( } } else if (base->object->type == OB_LAMP) { - base->flag |= BASE_VISIBLE_DEPSGRAPH; + base->flag |= BASE_ENABLED_AND_MAYBE_VISIBLE_IN_VIEWPORT; } } } @@ -586,7 +587,8 @@ static Scene *preview_prepare_scene( sce->world->horb = 0.0f; } - LISTBASE_FOREACH (Base *, base, &view_layer->object_bases) { + BKE_view_layer_synced_ensure(sce, view_layer); + LISTBASE_FOREACH (Base *, base, BKE_view_layer_object_bases_get(view_layer)) { if (base->object->id.name[2] == 'p') { if (base->object->type == OB_LAMP) { base->object->data = la; @@ -679,7 +681,7 @@ static bool ed_preview_draw_rect(ScrArea *area, int split, int first, rcti *rect /* material preview only needs monoscopy (view 0) */ RE_AcquiredResultGet32(re, &rres, (uint *)rect_byte, 0); - IMMDrawPixelsTexState state = immDrawPixelsTexSetup(GPU_SHADER_2D_IMAGE_COLOR); + IMMDrawPixelsTexState state = immDrawPixelsTexSetup(GPU_SHADER_3D_IMAGE_COLOR); immDrawPixelsTexTiled(&state, fx, fy, @@ -775,10 +777,11 @@ static bool object_preview_is_type_supported(const Object *ob) } static Object *object_preview_camera_create(Main *preview_main, + Scene *scene, ViewLayer *view_layer, Object *preview_object) { - Object *camera = BKE_object_add(preview_main, view_layer, OB_CAMERA, "Preview Camera"); + Object *camera = BKE_object_add(preview_main, scene, view_layer, OB_CAMERA, "Preview Camera"); float rotmat[3][3]; float dummyscale[3]; @@ -817,13 +820,14 @@ static Scene *object_preview_scene_create(const struct ObjectPreviewData *previe BKE_collection_object_add(preview_data->pr_main, scene->master_collection, preview_data->object); Object *camera_object = object_preview_camera_create( - preview_data->pr_main, view_layer, preview_data->object); + preview_data->pr_main, scene, view_layer, preview_data->object); scene->camera = camera_object; scene->r.xsch = preview_data->sizex; scene->r.ysch = preview_data->sizey; scene->r.size = 100; + BKE_view_layer_synced_ensure(scene, view_layer); Base *preview_base = BKE_view_layer_base_find(view_layer, preview_data->object); /* For 'view selected' below. */ preview_base->flag |= BASE_SELECTED; @@ -1304,41 +1308,33 @@ static void shader_preview_free(void *customdata) static ImBuf *icon_preview_imbuf_from_brush(Brush *brush) { - static const int flags = IB_rect | IB_multilayer | IB_metadata; + if (!brush->icon_imbuf && (brush->flag & BRUSH_CUSTOM_ICON) && brush->icon_filepath[0]) { + const int flags = IB_rect | IB_multilayer | IB_metadata; - char filepath[FILE_MAX]; - const char *folder; + /* First use the path directly to try and load the file. */ + char filepath[FILE_MAX]; - if (!(brush->icon_imbuf)) { - if (brush->flag & BRUSH_CUSTOM_ICON) { + BLI_strncpy(filepath, brush->icon_filepath, sizeof(brush->icon_filepath)); + BLI_path_abs(filepath, ID_BLEND_PATH_FROM_GLOBAL(&brush->id)); - if (brush->icon_filepath[0]) { - /* First use the path directly to try and load the file. */ + /* Use default color-spaces for brushes. */ + brush->icon_imbuf = IMB_loadiffname(filepath, flags, nullptr); - BLI_strncpy(filepath, brush->icon_filepath, sizeof(brush->icon_filepath)); - BLI_path_abs(filepath, ID_BLEND_PATH_FROM_GLOBAL(&brush->id)); + /* Otherwise lets try to find it in other directories. */ + if (!(brush->icon_imbuf)) { + const char *brushicons_dir = BKE_appdir_folder_id(BLENDER_DATAFILES, "brushicons"); + /* Expected to be found, but don't crash if it's not. */ + if (brushicons_dir) { + BLI_join_dirfile(filepath, sizeof(filepath), brushicons_dir, brush->icon_filepath); - /* Use default color-spaces for brushes. */ + /* Use default color spaces. */ brush->icon_imbuf = IMB_loadiffname(filepath, flags, nullptr); - - /* otherwise lets try to find it in other directories */ - if (!(brush->icon_imbuf)) { - folder = BKE_appdir_folder_id(BLENDER_DATAFILES, "brushicons"); - - BLI_make_file_string( - BKE_main_blendfile_path_from_global(), filepath, folder, brush->icon_filepath); - - if (filepath[0]) { - /* Use default color spaces. */ - brush->icon_imbuf = IMB_loadiffname(filepath, flags, nullptr); - } - } - - if (brush->icon_imbuf) { - BKE_icon_changed(BKE_icon_id_ensure(&brush->id)); - } } } + + if (brush->icon_imbuf) { + BKE_icon_changed(BKE_icon_id_ensure(&brush->id)); + } } if (!(brush->icon_imbuf)) { diff --git a/source/blender/editors/render/render_shading.cc b/source/blender/editors/render/render_shading.cc index da2290f7372..f784346ec8f 100644 --- a/source/blender/editors/render/render_shading.cc +++ b/source/blender/editors/render/render_shading.cc @@ -934,7 +934,7 @@ static int view_layer_add_exec(bContext *C, wmOperator *op) WM_window_set_active_view_layer(win, view_layer_new); } - DEG_id_tag_update(&scene->id, 0); + DEG_id_tag_update(&scene->id, ID_RECALC_BASE_FLAGS); DEG_relations_tag_update(CTX_data_main(C)); WM_event_add_notifier(C, NC_SCENE | ND_LAYER, scene); @@ -1039,7 +1039,7 @@ static int view_layer_add_aov_exec(bContext *C, wmOperator *UNUSED(op)) ntreeCompositUpdateRLayers(scene->nodetree); } - DEG_id_tag_update(&scene->id, 0); + DEG_id_tag_update(&scene->id, ID_RECALC_COPY_ON_WRITE); DEG_relations_tag_update(CTX_data_main(C)); WM_event_add_notifier(C, NC_SCENE | ND_LAYER, scene); @@ -1091,7 +1091,7 @@ static int view_layer_remove_aov_exec(bContext *C, wmOperator *UNUSED(op)) ntreeCompositUpdateRLayers(scene->nodetree); } - DEG_id_tag_update(&scene->id, 0); + DEG_id_tag_update(&scene->id, ID_RECALC_COPY_ON_WRITE); DEG_relations_tag_update(CTX_data_main(C)); WM_event_add_notifier(C, NC_SCENE | ND_LAYER, scene); @@ -1143,7 +1143,7 @@ static int view_layer_add_lightgroup_exec(bContext *C, wmOperator *op) ntreeCompositUpdateRLayers(scene->nodetree); } - DEG_id_tag_update(&scene->id, 0); + DEG_id_tag_update(&scene->id, ID_RECALC_COPY_ON_WRITE); DEG_relations_tag_update(CTX_data_main(C)); WM_event_add_notifier(C, NC_SCENE | ND_LAYER, scene); @@ -1193,7 +1193,7 @@ static int view_layer_remove_lightgroup_exec(bContext *C, wmOperator *UNUSED(op) ntreeCompositUpdateRLayers(scene->nodetree); } - DEG_id_tag_update(&scene->id, 0); + DEG_id_tag_update(&scene->id, ID_RECALC_COPY_ON_WRITE); DEG_relations_tag_update(CTX_data_main(C)); WM_event_add_notifier(C, NC_SCENE | ND_LAYER, scene); @@ -1257,7 +1257,7 @@ static int view_layer_add_used_lightgroups_exec(bContext *C, wmOperator *UNUSED( ntreeCompositUpdateRLayers(scene->nodetree); } - DEG_id_tag_update(&scene->id, 0); + DEG_id_tag_update(&scene->id, ID_RECALC_COPY_ON_WRITE); DEG_relations_tag_update(CTX_data_main(C)); WM_event_add_notifier(C, NC_SCENE | ND_LAYER, scene); @@ -1301,7 +1301,7 @@ static int view_layer_remove_unused_lightgroups_exec(bContext *C, wmOperator *UN ntreeCompositUpdateRLayers(scene->nodetree); } - DEG_id_tag_update(&scene->id, 0); + DEG_id_tag_update(&scene->id, ID_RECALC_COPY_ON_WRITE); DEG_relations_tag_update(CTX_data_main(C)); WM_event_add_notifier(C, NC_SCENE | ND_LAYER, scene); @@ -1692,7 +1692,7 @@ static int freestyle_module_remove_exec(bContext *C, wmOperator *UNUSED(op)) BKE_freestyle_module_delete(&view_layer->freestyle_config, module); - DEG_id_tag_update(&scene->id, 0); + DEG_id_tag_update(&scene->id, ID_RECALC_COPY_ON_WRITE); WM_event_add_notifier(C, NC_SCENE | ND_RENDER_OPTIONS, scene); return OPERATOR_FINISHED; @@ -1722,7 +1722,7 @@ static int freestyle_module_move_exec(bContext *C, wmOperator *op) int dir = RNA_enum_get(op->ptr, "direction"); if (BKE_freestyle_module_move(&view_layer->freestyle_config, module, dir)) { - DEG_id_tag_update(&scene->id, 0); + DEG_id_tag_update(&scene->id, ID_RECALC_COPY_ON_WRITE); WM_event_add_notifier(C, NC_SCENE | ND_RENDER_OPTIONS, scene); } @@ -1778,7 +1778,7 @@ static int freestyle_lineset_add_exec(bContext *C, wmOperator *UNUSED(op)) BKE_freestyle_lineset_add(bmain, &view_layer->freestyle_config, nullptr); - DEG_id_tag_update(&scene->id, 0); + DEG_id_tag_update(&scene->id, ID_RECALC_COPY_ON_WRITE); WM_event_add_notifier(C, NC_SCENE | ND_RENDER_OPTIONS, scene); return OPERATOR_FINISHED; @@ -1852,7 +1852,7 @@ static int freestyle_lineset_paste_exec(bContext *C, wmOperator *UNUSED(op)) FRS_paste_active_lineset(&view_layer->freestyle_config); - DEG_id_tag_update(&scene->id, 0); + DEG_id_tag_update(&scene->id, ID_RECALC_COPY_ON_WRITE); WM_event_add_notifier(C, NC_SCENE | ND_RENDER_OPTIONS, scene); return OPERATOR_FINISHED; @@ -1886,7 +1886,7 @@ static int freestyle_lineset_remove_exec(bContext *C, wmOperator *UNUSED(op)) FRS_delete_active_lineset(&view_layer->freestyle_config); - DEG_id_tag_update(&scene->id, 0); + DEG_id_tag_update(&scene->id, ID_RECALC_COPY_ON_WRITE); WM_event_add_notifier(C, NC_SCENE | ND_RENDER_OPTIONS, scene); return OPERATOR_FINISHED; @@ -1920,7 +1920,7 @@ static int freestyle_lineset_move_exec(bContext *C, wmOperator *op) int dir = RNA_enum_get(op->ptr, "direction"); if (FRS_move_active_lineset(&view_layer->freestyle_config, dir)) { - DEG_id_tag_update(&scene->id, 0); + DEG_id_tag_update(&scene->id, ID_RECALC_COPY_ON_WRITE); WM_event_add_notifier(C, NC_SCENE | ND_RENDER_OPTIONS, scene); } diff --git a/source/blender/editors/render/render_view.cc b/source/blender/editors/render/render_view.cc index 9a16c910205..7569b3600a1 100644 --- a/source/blender/editors/render/render_view.cc +++ b/source/blender/editors/render/render_view.cc @@ -74,7 +74,7 @@ static ScrArea *find_area_showing_r_result(bContext *C, Scene *scene, wmWindow * ScrArea *area = nullptr; SpaceImage *sima; - /* find an imagewindow showing render result */ + /* find an image-window showing render result */ for (*win = static_cast<wmWindow *>(wm->windows.first); *win; *win = (*win)->next) { if (WM_window_get_active_scene(*win) == scene) { const bScreen *screen = WM_window_get_active_screen(*win); @@ -102,7 +102,7 @@ static ScrArea *find_area_image_empty(bContext *C) ScrArea *area; SpaceImage *sima; - /* find an imagewindow showing render result */ + /* find an image-window showing render result */ for (area = static_cast<ScrArea *>(screen->areabase.first); area; area = area->next) { if (area->spacetype == SPACE_IMAGE) { sima = static_cast<SpaceImage *>(area->spacedata.first); diff --git a/source/blender/editors/scene/scene_edit.c b/source/blender/editors/scene/scene_edit.c index 57a9e6be917..07a93d3907a 100644 --- a/source/blender/editors/scene/scene_edit.c +++ b/source/blender/editors/scene/scene_edit.c @@ -229,7 +229,7 @@ bool ED_scene_view_layer_delete(Main *bmain, Scene *scene, ViewLayer *layer, Rep BKE_view_layer_free(layer); - DEG_id_tag_update(&scene->id, 0); + DEG_id_tag_update(&scene->id, ID_RECALC_BASE_FLAGS); DEG_relations_tag_update(bmain); WM_main_add_notifier(NC_SCENE | ND_LAYER | NA_REMOVED, scene); diff --git a/source/blender/editors/screen/CMakeLists.txt b/source/blender/editors/screen/CMakeLists.txt index f9b1e2b5d4c..119758f3335 100644 --- a/source/blender/editors/screen/CMakeLists.txt +++ b/source/blender/editors/screen/CMakeLists.txt @@ -15,7 +15,6 @@ set(INC ../../makesrna ../../sequencer ../../windowmanager - ../../../../intern/glew-mx ../../../../intern/guardedalloc # RNA_prototypes.h ${CMAKE_BINARY_DIR}/source/blender/makesrna diff --git a/source/blender/editors/screen/area.c b/source/blender/editors/screen/area.c index def6c38f5ca..25e16bee558 100644 --- a/source/blender/editors/screen/area.c +++ b/source/blender/editors/screen/area.c @@ -16,6 +16,7 @@ #include "BLI_linklist_stack.h" #include "BLI_math.h" #include "BLI_rand.h" +#include "BLI_string_utils.h" #include "BLI_utildefines.h" #include "BKE_context.h" @@ -83,7 +84,7 @@ static void region_draw_emboss(const ARegion *region, const rcti *scirct, int si GPUVertFormat *format = immVertexFormat(); uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); - immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); immUniformColor4fv(color); immBeginAtMost(GPU_PRIM_LINES, 8); @@ -127,7 +128,7 @@ void ED_region_pixelspace(const ARegion *region) void ED_region_do_listen(wmRegionListenerParams *params) { ARegion *region = params->region; - wmNotifier *notifier = params->notifier; + const wmNotifier *notifier = params->notifier; /* generic notes first */ switch (notifier->category) { @@ -174,7 +175,7 @@ void ED_area_do_refresh(bContext *C, ScrArea *area) } /** - * \brief Corner widget use for quitting fullscreen. + * \brief Corner widget use for quitting full-screen. */ static void area_draw_azone_fullscreen( short UNUSED(x1), short UNUSED(y1), short x2, short y2, float alpha) @@ -238,8 +239,6 @@ static void draw_azone_arrow(float x1, float y1, float x2, float y2, AZEdge edge uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); GPU_blend(GPU_BLEND_ALPHA); - /* NOTE(fclem): There is something strange going on with Mesa and GPU_SHADER_2D_UNIFORM_COLOR - * that causes a crash on some GPUs (see T76113). Using 3D variant avoid the issue. */ immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); immUniformColor4f(0.8f, 0.8f, 0.8f, 0.4f); @@ -563,7 +562,7 @@ void ED_region_do_draw(bContext *C, ARegion *region) GPU_blend(GPU_BLEND_ALPHA); GPUVertFormat *format = immVertexFormat(); uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); - immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); immUniformColor4f(BLI_thread_frand(0), BLI_thread_frand(0), BLI_thread_frand(0), 0.1f); immRectf(pos, region->drawrct.xmin - region->winrct.xmin, @@ -593,7 +592,7 @@ void ED_region_do_draw(bContext *C, ARegion *region) UI_GetThemeColor3fv(TH_EDITOR_OUTLINE, color); GPUVertFormat *format = immVertexFormat(); uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); - immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); immUniformColor4fv(color); GPU_line_width(1.0f); imm_draw_box_wire_2d(pos, @@ -846,7 +845,7 @@ void ED_workspace_status_text(bContext *C, const char *str) static void area_azone_init(wmWindow *win, const bScreen *screen, ScrArea *area) { - /* reinitialize entirely, regions and fullscreen add azones too */ + /* reinitialize entirely, regions and full-screen add azones too */ BLI_freelistN(&area->actionzones); if (screen->state != SCREENNORMAL) { @@ -1903,6 +1902,7 @@ void ED_area_init(wmWindowManager *wm, wmWindow *win, ScrArea *area) { WorkSpace *workspace = WM_window_get_active_workspace(win); const bScreen *screen = BKE_workspace_active_screen_get(win->workspace_hook); + const Scene *scene = WM_window_get_active_scene(win); ViewLayer *view_layer = WM_window_get_active_view_layer(win); if (ED_area_is_global(area) && (area->global->flag & GLOBAL_AREA_IS_HIDDEN)) { @@ -1967,7 +1967,7 @@ void ED_area_init(wmWindowManager *wm, wmWindow *win, ScrArea *area) /* Avoid re-initializing tools while resizing the window. */ if ((G.moving & G_TRANSFORM_WM) == 0) { if ((1 << area->spacetype) & WM_TOOLSYSTEM_SPACE_MASK) { - WM_toolsystem_refresh_screen_area(workspace, view_layer, area); + WM_toolsystem_refresh_screen_area(workspace, scene, view_layer, area); area->flag |= AREA_FLAG_ACTIVE_TOOL_UPDATE; } else { @@ -2578,8 +2578,8 @@ void ED_area_prevspace(bContext *C, ScrArea *area) /* no change */ return; } - /* If this is a stacked fullscreen, changing to previous area exits it (meaning we're still in a - * fullscreen, but not in a stacked one). */ + /* If this is a stacked full-screen, changing to previous area exits it (meaning we're still in a + * full-screen, but not in a stacked one). */ area->flag &= ~AREA_FLAG_STACKED_FULLSCREEN; ED_area_tag_redraw(area); @@ -2689,12 +2689,13 @@ static void ed_panel_draw(const bContext *C, const uiStyle *style = UI_style_get_dpi(); /* Draw panel. */ - char block_name[BKE_ST_MAXNAME + INSTANCED_PANEL_UNIQUE_STR_LEN]; - strncpy(block_name, pt->idname, BKE_ST_MAXNAME); - if (unique_panel_str != NULL) { + if (unique_panel_str) { /* Instanced panels should have already been added at this point. */ - strncat(block_name, unique_panel_str, INSTANCED_PANEL_UNIQUE_STR_LEN); + BLI_string_join(block_name, sizeof(block_name), pt->idname, unique_panel_str); + } + else { + STRNCPY(block_name, pt->idname); } uiBlock *block = UI_block_begin(C, region, block_name, UI_EMBOSS); @@ -3558,7 +3559,7 @@ void ED_region_info_draw_multiline(ARegion *region, GPU_blend(GPU_BLEND_ALPHA); GPUVertFormat *format = immVertexFormat(); uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_I32, 2, GPU_FETCH_INT_TO_FLOAT); - immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); immUniformColor4fv(fill_color); immRecti(pos, rect.xmin, rect.ymin, rect.xmax + 1, rect.ymax + 1); immUnbindProgram(); @@ -3629,7 +3630,7 @@ void ED_region_grid_draw(ARegion *region, float zoomx, float zoomy, float x0, fl float gridcolor[4]; UI_GetThemeColor4fv(TH_GRID, gridcolor); - immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); /* To fake alpha-blending, color shading is reduced when alpha is nearing 0. */ immUniformThemeColorBlendShade(TH_BACK, TH_GRID, gridcolor[3], 20 * gridcolor[3]); immRectf(pos, x1, y1, x2, y2); @@ -3666,7 +3667,7 @@ void ED_region_grid_draw(ARegion *region, float zoomx, float zoomy, float x0, fl pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); uint color = GPU_vertformat_attr_add(format, "color", GPU_COMP_F32, 3, GPU_FETCH_FLOAT); - immBindBuiltinProgram(GPU_SHADER_2D_FLAT_COLOR); + immBindBuiltinProgram(GPU_SHADER_3D_FLAT_COLOR); immBegin(GPU_PRIM_LINES, 4 * count_fine + 4 * count_large); float theme_color[3]; @@ -3779,7 +3780,7 @@ void ED_region_cache_draw_background(ARegion *region) uint pos = GPU_vertformat_attr_add( immVertexFormat(), "pos", GPU_COMP_I32, 2, GPU_FETCH_INT_TO_FLOAT); - immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); immUniformColor4ub(128, 128, 255, 64); immRecti(pos, 0, region_bottom, region->winx, region_bottom + 8 * UI_DPI_FAC); immUnbindProgram(); @@ -3800,7 +3801,7 @@ void ED_region_cache_draw_curfra_label(const int framenr, const float x, const f uint pos = GPU_vertformat_attr_add( immVertexFormat(), "pos", GPU_COMP_I32, 2, GPU_FETCH_INT_TO_FLOAT); - immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); immUniformThemeColor(TH_CFRAME); immRecti(pos, x, y, x + font_dims[0] + 6.0f, y + font_dims[1] + 4.0f); immUnbindProgram(); @@ -3820,7 +3821,7 @@ void ED_region_cache_draw_cached_segments( uint pos = GPU_vertformat_attr_add( immVertexFormat(), "pos", GPU_COMP_I32, 2, GPU_FETCH_INT_TO_FLOAT); - immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); immUniformColor4ub(128, 128, 255, 128); for (int a = 0; a < num_segments; a++) { diff --git a/source/blender/editors/screen/glutil.c b/source/blender/editors/screen/glutil.c index 8a84f4cf079..4382fd3d1c2 100644 --- a/source/blender/editors/screen/glutil.c +++ b/source/blender/editors/screen/glutil.c @@ -77,9 +77,10 @@ void immDrawPixelsTexScaledFullSize(const IMMDrawPixelsTexState *state, * filtering results. Mipmaps can be used to get better results (i.e. #GL_LINEAR_MIPMAP_LINEAR), * so always use mipmaps when filtering. */ const bool use_mipmap = use_filter && ((draw_width < img_w) || (draw_height < img_h)); - const int mips = use_mipmap ? 9999 : 1; + const int mip_len = use_mipmap ? 9999 : 1; - GPUTexture *tex = GPU_texture_create_2d("immDrawPixels", img_w, img_h, mips, gpu_format, NULL); + GPUTexture *tex = GPU_texture_create_2d( + "immDrawPixels", img_w, img_h, mip_len, gpu_format, NULL); const bool use_float_data = ELEM(gpu_format, GPU_RGBA16F, GPU_RGB16F, GPU_R16F); eGPUDataFormat gpu_data_format = (use_float_data) ? GPU_DATA_FLOAT : GPU_DATA_UBYTE; @@ -514,7 +515,7 @@ void ED_draw_imbuf_clipping(ImBuf *ibuf, ibuf, view_settings, display_settings, &cache_handle); if (display_buffer) { - IMMDrawPixelsTexState state = immDrawPixelsTexSetup(GPU_SHADER_2D_IMAGE_COLOR); + IMMDrawPixelsTexState state = immDrawPixelsTexSetup(GPU_SHADER_3D_IMAGE_COLOR); immDrawPixelsTexTiled_clipping(&state, x, y, diff --git a/source/blender/editors/screen/screen_context.c b/source/blender/editors/screen/screen_context.c index 83e6c837eac..ffd76e70eb8 100644 --- a/source/blender/editors/screen/screen_context.c +++ b/source/blender/editors/screen/screen_context.c @@ -129,9 +129,11 @@ static eContextResult screen_ctx_visible_objects(const bContext *C, bContextData { wmWindow *win = CTX_wm_window(C); View3D *v3d = CTX_wm_view3d(C); /* This may be NULL in a lot of cases. */ + Scene *scene = WM_window_get_active_scene(win); ViewLayer *view_layer = WM_window_get_active_view_layer(win); + BKE_view_layer_synced_ensure(scene, view_layer); - LISTBASE_FOREACH (Base *, base, &view_layer->object_bases) { + LISTBASE_FOREACH (Base *, base, BKE_view_layer_object_bases_get(view_layer)) { if (BASE_VISIBLE(v3d, base)) { CTX_data_id_list_add(result, &base->object->id); } @@ -143,9 +145,11 @@ static eContextResult screen_ctx_selectable_objects(const bContext *C, bContextD { wmWindow *win = CTX_wm_window(C); View3D *v3d = CTX_wm_view3d(C); /* This may be NULL in a lot of cases. */ + Scene *scene = WM_window_get_active_scene(win); ViewLayer *view_layer = WM_window_get_active_view_layer(win); + BKE_view_layer_synced_ensure(scene, view_layer); - LISTBASE_FOREACH (Base *, base, &view_layer->object_bases) { + LISTBASE_FOREACH (Base *, base, BKE_view_layer_object_bases_get(view_layer)) { if (BASE_SELECTABLE(v3d, base)) { CTX_data_id_list_add(result, &base->object->id); } @@ -157,9 +161,11 @@ static eContextResult screen_ctx_selected_objects(const bContext *C, bContextDat { wmWindow *win = CTX_wm_window(C); View3D *v3d = CTX_wm_view3d(C); /* This may be NULL in a lot of cases. */ + Scene *scene = WM_window_get_active_scene(win); ViewLayer *view_layer = WM_window_get_active_view_layer(win); + BKE_view_layer_synced_ensure(scene, view_layer); - LISTBASE_FOREACH (Base *, base, &view_layer->object_bases) { + LISTBASE_FOREACH (Base *, base, BKE_view_layer_object_bases_get(view_layer)) { if (BASE_SELECTED(v3d, base)) { CTX_data_id_list_add(result, &base->object->id); } @@ -172,9 +178,11 @@ static eContextResult screen_ctx_selected_editable_objects(const bContext *C, { wmWindow *win = CTX_wm_window(C); View3D *v3d = CTX_wm_view3d(C); /* This may be NULL in a lot of cases. */ + Scene *scene = WM_window_get_active_scene(win); ViewLayer *view_layer = WM_window_get_active_view_layer(win); + BKE_view_layer_synced_ensure(scene, view_layer); - LISTBASE_FOREACH (Base *, base, &view_layer->object_bases) { + LISTBASE_FOREACH (Base *, base, BKE_view_layer_object_bases_get(view_layer)) { if (BASE_SELECTED_EDITABLE(v3d, base)) { CTX_data_id_list_add(result, &base->object->id); } @@ -186,10 +194,12 @@ static eContextResult screen_ctx_editable_objects(const bContext *C, bContextDat { wmWindow *win = CTX_wm_window(C); View3D *v3d = CTX_wm_view3d(C); /* This may be NULL in a lot of cases. */ + Scene *scene = WM_window_get_active_scene(win); ViewLayer *view_layer = WM_window_get_active_view_layer(win); + BKE_view_layer_synced_ensure(scene, view_layer); /* Visible + Editable, but not necessarily selected */ - LISTBASE_FOREACH (Base *, base, &view_layer->object_bases) { + LISTBASE_FOREACH (Base *, base, BKE_view_layer_object_bases_get(view_layer)) { if (BASE_EDITABLE(v3d, base)) { CTX_data_id_list_add(result, &base->object->id); } @@ -201,11 +211,13 @@ static eContextResult screen_ctx_objects_in_mode(const bContext *C, bContextData { wmWindow *win = CTX_wm_window(C); View3D *v3d = CTX_wm_view3d(C); /* This may be NULL in a lot of cases. */ + const Scene *scene = WM_window_get_active_scene(win); ViewLayer *view_layer = WM_window_get_active_view_layer(win); - Object *obact = view_layer->basact ? view_layer->basact->object : NULL; + BKE_view_layer_synced_ensure(scene, view_layer); + Object *obact = BKE_view_layer_active_object_get(view_layer); if (obact && (obact->mode != OB_MODE_OBJECT)) { - FOREACH_OBJECT_IN_MODE_BEGIN (view_layer, v3d, obact->type, obact->mode, ob_iter) { + FOREACH_OBJECT_IN_MODE_BEGIN (scene, view_layer, v3d, obact->type, obact->mode, ob_iter) { CTX_data_id_list_add(result, &ob_iter->id); } FOREACH_OBJECT_IN_MODE_END; @@ -218,15 +230,17 @@ static eContextResult screen_ctx_objects_in_mode_unique_data(const bContext *C, { wmWindow *win = CTX_wm_window(C); View3D *v3d = CTX_wm_view3d(C); /* This may be NULL in a lot of cases. */ + const Scene *scene = WM_window_get_active_scene(win); ViewLayer *view_layer = WM_window_get_active_view_layer(win); - Object *obact = view_layer->basact ? view_layer->basact->object : NULL; + BKE_view_layer_synced_ensure(scene, view_layer); + Object *obact = BKE_view_layer_active_object_get(view_layer); if (obact && (obact->mode != OB_MODE_OBJECT)) { - FOREACH_OBJECT_IN_MODE_BEGIN (view_layer, v3d, obact->type, obact->mode, ob_iter) { + FOREACH_OBJECT_IN_MODE_BEGIN (scene, view_layer, v3d, obact->type, obact->mode, ob_iter) { ob_iter->id.tag |= LIB_TAG_DOIT; } FOREACH_OBJECT_IN_MODE_END; - FOREACH_OBJECT_IN_MODE_BEGIN (view_layer, v3d, obact->type, obact->mode, ob_iter) { + FOREACH_OBJECT_IN_MODE_BEGIN (scene, view_layer, v3d, obact->type, obact->mode, ob_iter) { if (ob_iter->id.tag & LIB_TAG_DOIT) { ob_iter->id.tag &= ~LIB_TAG_DOIT; CTX_data_id_list_add(result, &ob_iter->id); @@ -242,8 +256,10 @@ static eContextResult screen_ctx_visible_or_editable_bones_(const bContext *C, const bool editable_bones) { wmWindow *win = CTX_wm_window(C); + const Scene *scene = WM_window_get_active_scene(win); ViewLayer *view_layer = WM_window_get_active_view_layer(win); - Object *obedit = OBEDIT_FROM_VIEW_LAYER(view_layer); + BKE_view_layer_synced_ensure(scene, view_layer); + Object *obedit = BKE_view_layer_edit_object_get(view_layer); bArmature *arm = (obedit && obedit->type == OB_ARMATURE) ? obedit->data : NULL; EditBone *flipbone = NULL; @@ -251,7 +267,7 @@ static eContextResult screen_ctx_visible_or_editable_bones_(const bContext *C, if (arm && arm->edbo) { uint objects_len; Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data( - view_layer, CTX_wm_view3d(C), &objects_len); + scene, view_layer, CTX_wm_view3d(C), &objects_len); for (uint i = 0; i < objects_len; i++) { Object *ob = objects[i]; arm = ob->data; @@ -313,15 +329,17 @@ static eContextResult screen_ctx_selected_bones_(const bContext *C, const bool selected_editable_bones) { wmWindow *win = CTX_wm_window(C); + const Scene *scene = WM_window_get_active_scene(win); ViewLayer *view_layer = WM_window_get_active_view_layer(win); - Object *obedit = OBEDIT_FROM_VIEW_LAYER(view_layer); + BKE_view_layer_synced_ensure(scene, view_layer); + Object *obedit = BKE_view_layer_edit_object_get(view_layer); bArmature *arm = (obedit && obedit->type == OB_ARMATURE) ? obedit->data : NULL; EditBone *flipbone = NULL; if (arm && arm->edbo) { uint objects_len; Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data( - view_layer, CTX_wm_view3d(C), &objects_len); + scene, view_layer, CTX_wm_view3d(C), &objects_len); for (uint i = 0; i < objects_len; i++) { Object *ob = objects[i]; arm = ob->data; @@ -383,8 +401,10 @@ static eContextResult screen_ctx_visible_pose_bones(const bContext *C, bContextD { wmWindow *win = CTX_wm_window(C); View3D *v3d = CTX_wm_view3d(C); /* This may be NULL in a lot of cases. */ + const Scene *scene = WM_window_get_active_scene(win); ViewLayer *view_layer = WM_window_get_active_view_layer(win); - Object *obact = view_layer->basact ? view_layer->basact->object : NULL; + BKE_view_layer_synced_ensure(scene, view_layer); + Object *obact = BKE_view_layer_active_object_get(view_layer); Object *obpose = BKE_object_pose_armature_get(obact); if (obpose && obpose->pose && obpose->data) { if (obpose != obact) { @@ -394,7 +414,7 @@ static eContextResult screen_ctx_visible_pose_bones(const bContext *C, bContextD FOREACH_PCHAN_SELECTED_IN_OBJECT_END; } else if (obact->mode & OB_MODE_POSE) { - FOREACH_OBJECT_IN_MODE_BEGIN (view_layer, v3d, OB_ARMATURE, OB_MODE_POSE, ob_iter) { + FOREACH_OBJECT_IN_MODE_BEGIN (scene, view_layer, v3d, OB_ARMATURE, OB_MODE_POSE, ob_iter) { FOREACH_PCHAN_VISIBLE_IN_OBJECT_BEGIN (ob_iter, pchan) { CTX_data_list_add(result, &ob_iter->id, &RNA_PoseBone, pchan); } @@ -411,8 +431,9 @@ static eContextResult screen_ctx_selected_pose_bones(const bContext *C, bContext { wmWindow *win = CTX_wm_window(C); View3D *v3d = CTX_wm_view3d(C); /* This may be NULL in a lot of cases. */ + const Scene *scene = WM_window_get_active_scene(win); ViewLayer *view_layer = WM_window_get_active_view_layer(win); - Object *obact = view_layer->basact ? view_layer->basact->object : NULL; + Object *obact = BKE_view_layer_active_object_get(view_layer); Object *obpose = BKE_object_pose_armature_get(obact); if (obpose && obpose->pose && obpose->data) { if (obpose != obact) { @@ -422,7 +443,7 @@ static eContextResult screen_ctx_selected_pose_bones(const bContext *C, bContext FOREACH_PCHAN_SELECTED_IN_OBJECT_END; } else if (obact->mode & OB_MODE_POSE) { - FOREACH_OBJECT_IN_MODE_BEGIN (view_layer, v3d, OB_ARMATURE, OB_MODE_POSE, ob_iter) { + FOREACH_OBJECT_IN_MODE_BEGIN (scene, view_layer, v3d, OB_ARMATURE, OB_MODE_POSE, ob_iter) { FOREACH_PCHAN_SELECTED_IN_OBJECT_BEGIN (ob_iter, pchan) { CTX_data_list_add(result, &ob_iter->id, &RNA_PoseBone, pchan); } @@ -439,8 +460,10 @@ static eContextResult screen_ctx_selected_pose_bones_from_active_object(const bC bContextDataResult *result) { wmWindow *win = CTX_wm_window(C); + const Scene *scene = WM_window_get_active_scene(win); ViewLayer *view_layer = WM_window_get_active_view_layer(win); - Object *obact = view_layer->basact ? view_layer->basact->object : NULL; + BKE_view_layer_synced_ensure(scene, view_layer); + Object *obact = BKE_view_layer_active_object_get(view_layer); Object *obpose = BKE_object_pose_armature_get(obact); if (obpose && obpose->pose && obpose->data) { if (obpose != obact) { @@ -463,8 +486,10 @@ static eContextResult screen_ctx_selected_pose_bones_from_active_object(const bC static eContextResult screen_ctx_active_bone(const bContext *C, bContextDataResult *result) { wmWindow *win = CTX_wm_window(C); + const Scene *scene = WM_window_get_active_scene(win); ViewLayer *view_layer = WM_window_get_active_view_layer(win); - Object *obact = view_layer->basact ? view_layer->basact->object : NULL; + BKE_view_layer_synced_ensure(scene, view_layer); + Object *obact = BKE_view_layer_active_object_get(view_layer); if (obact && obact->type == OB_ARMATURE) { bArmature *arm = obact->data; if (arm->edbo) { @@ -485,8 +510,10 @@ static eContextResult screen_ctx_active_bone(const bContext *C, bContextDataResu static eContextResult screen_ctx_active_pose_bone(const bContext *C, bContextDataResult *result) { wmWindow *win = CTX_wm_window(C); + const Scene *scene = WM_window_get_active_scene(win); ViewLayer *view_layer = WM_window_get_active_view_layer(win); - Object *obact = view_layer->basact ? view_layer->basact->object : NULL; + BKE_view_layer_synced_ensure(scene, view_layer); + Object *obact = BKE_view_layer_active_object_get(view_layer); Object *obpose = BKE_object_pose_armature_get(obact); bPoseChannel *pchan = BKE_pose_channel_active_if_layer_visible(obpose); @@ -499,8 +526,10 @@ static eContextResult screen_ctx_active_pose_bone(const bContext *C, bContextDat static eContextResult screen_ctx_active_object(const bContext *C, bContextDataResult *result) { wmWindow *win = CTX_wm_window(C); + const Scene *scene = WM_window_get_active_scene(win); ViewLayer *view_layer = WM_window_get_active_view_layer(win); - Object *obact = view_layer->basact ? view_layer->basact->object : NULL; + BKE_view_layer_synced_ensure(scene, view_layer); + Object *obact = BKE_view_layer_active_object_get(view_layer); if (obact) { CTX_data_id_pointer_set(result, &obact->id); @@ -511,8 +540,10 @@ static eContextResult screen_ctx_active_object(const bContext *C, bContextDataRe static eContextResult screen_ctx_object(const bContext *C, bContextDataResult *result) { wmWindow *win = CTX_wm_window(C); + const Scene *scene = WM_window_get_active_scene(win); ViewLayer *view_layer = WM_window_get_active_view_layer(win); - Object *obact = view_layer->basact ? view_layer->basact->object : NULL; + BKE_view_layer_synced_ensure(scene, view_layer); + Object *obact = BKE_view_layer_active_object_get(view_layer); if (obact) { CTX_data_id_pointer_set(result, &obact->id); @@ -523,8 +554,10 @@ static eContextResult screen_ctx_object(const bContext *C, bContextDataResult *r static eContextResult screen_ctx_edit_object(const bContext *C, bContextDataResult *result) { wmWindow *win = CTX_wm_window(C); + Scene *scene = WM_window_get_active_scene(win); ViewLayer *view_layer = WM_window_get_active_view_layer(win); - Object *obedit = OBEDIT_FROM_VIEW_LAYER(view_layer); + BKE_view_layer_synced_ensure(scene, view_layer); + Object *obedit = BKE_view_layer_edit_object_get(view_layer); /* convenience for now, 1 object per scene in editmode */ if (obedit) { CTX_data_id_pointer_set(result, &obedit->id); @@ -535,8 +568,10 @@ static eContextResult screen_ctx_edit_object(const bContext *C, bContextDataResu static eContextResult screen_ctx_sculpt_object(const bContext *C, bContextDataResult *result) { wmWindow *win = CTX_wm_window(C); + const Scene *scene = WM_window_get_active_scene(win); ViewLayer *view_layer = WM_window_get_active_view_layer(win); - Object *obact = view_layer->basact ? view_layer->basact->object : NULL; + BKE_view_layer_synced_ensure(scene, view_layer); + Object *obact = BKE_view_layer_active_object_get(view_layer); if (obact && (obact->mode & OB_MODE_SCULPT)) { CTX_data_id_pointer_set(result, &obact->id); @@ -547,8 +582,10 @@ static eContextResult screen_ctx_sculpt_object(const bContext *C, bContextDataRe static eContextResult screen_ctx_vertex_paint_object(const bContext *C, bContextDataResult *result) { wmWindow *win = CTX_wm_window(C); + const Scene *scene = WM_window_get_active_scene(win); ViewLayer *view_layer = WM_window_get_active_view_layer(win); - Object *obact = view_layer->basact ? view_layer->basact->object : NULL; + BKE_view_layer_synced_ensure(scene, view_layer); + Object *obact = BKE_view_layer_active_object_get(view_layer); if (obact && (obact->mode & OB_MODE_VERTEX_PAINT)) { CTX_data_id_pointer_set(result, &obact->id); } @@ -558,8 +595,10 @@ static eContextResult screen_ctx_vertex_paint_object(const bContext *C, bContext static eContextResult screen_ctx_weight_paint_object(const bContext *C, bContextDataResult *result) { wmWindow *win = CTX_wm_window(C); + const Scene *scene = WM_window_get_active_scene(win); ViewLayer *view_layer = WM_window_get_active_view_layer(win); - Object *obact = view_layer->basact ? view_layer->basact->object : NULL; + BKE_view_layer_synced_ensure(scene, view_layer); + Object *obact = BKE_view_layer_active_object_get(view_layer); if (obact && (obact->mode & OB_MODE_ALL_WEIGHT_PAINT)) { CTX_data_id_pointer_set(result, &obact->id); } @@ -569,8 +608,10 @@ static eContextResult screen_ctx_weight_paint_object(const bContext *C, bContext static eContextResult screen_ctx_image_paint_object(const bContext *C, bContextDataResult *result) { wmWindow *win = CTX_wm_window(C); + const Scene *scene = WM_window_get_active_scene(win); ViewLayer *view_layer = WM_window_get_active_view_layer(win); - Object *obact = view_layer->basact ? view_layer->basact->object : NULL; + BKE_view_layer_synced_ensure(scene, view_layer); + Object *obact = BKE_view_layer_active_object_get(view_layer); if (obact && (obact->mode & OB_MODE_TEXTURE_PAINT)) { CTX_data_id_pointer_set(result, &obact->id); } @@ -581,8 +622,10 @@ static eContextResult screen_ctx_particle_edit_object(const bContext *C, bContextDataResult *result) { wmWindow *win = CTX_wm_window(C); + const Scene *scene = WM_window_get_active_scene(win); ViewLayer *view_layer = WM_window_get_active_view_layer(win); - Object *obact = view_layer->basact ? view_layer->basact->object : NULL; + BKE_view_layer_synced_ensure(scene, view_layer); + Object *obact = BKE_view_layer_active_object_get(view_layer); if (obact && (obact->mode & OB_MODE_PARTICLE_EDIT)) { CTX_data_id_pointer_set(result, &obact->id); } @@ -592,8 +635,10 @@ static eContextResult screen_ctx_particle_edit_object(const bContext *C, static eContextResult screen_ctx_pose_object(const bContext *C, bContextDataResult *result) { wmWindow *win = CTX_wm_window(C); + const Scene *scene = WM_window_get_active_scene(win); ViewLayer *view_layer = WM_window_get_active_view_layer(win); - Object *obact = view_layer->basact ? view_layer->basact->object : NULL; + BKE_view_layer_synced_ensure(scene, view_layer); + Object *obact = BKE_view_layer_active_object_get(view_layer); Object *obpose = BKE_object_pose_armature_get(obact); if (obpose) { CTX_data_id_pointer_set(result, &obpose->id); @@ -736,8 +781,10 @@ static eContextResult screen_ctx_gpencil_data(const bContext *C, bContextDataRes { wmWindow *win = CTX_wm_window(C); ScrArea *area = CTX_wm_area(C); + const Scene *scene = WM_window_get_active_scene(win); ViewLayer *view_layer = WM_window_get_active_view_layer(win); - Object *obact = view_layer->basact ? view_layer->basact->object : NULL; + BKE_view_layer_synced_ensure(scene, view_layer); + Object *obact = BKE_view_layer_active_object_get(view_layer); /* FIXME: for some reason, CTX_data_active_object(C) returns NULL when called from these * situations (as outlined above - see Campbell's #ifdefs). * That causes the get_active function to fail when called from context. @@ -755,8 +802,10 @@ static eContextResult screen_ctx_gpencil_data_owner(const bContext *C, bContextD { wmWindow *win = CTX_wm_window(C); ScrArea *area = CTX_wm_area(C); + const Scene *scene = WM_window_get_active_scene(win); ViewLayer *view_layer = WM_window_get_active_view_layer(win); - Object *obact = view_layer->basact ? view_layer->basact->object : NULL; + BKE_view_layer_synced_ensure(scene, view_layer); + Object *obact = BKE_view_layer_active_object_get(view_layer); /* Pointer to which data/datablock owns the reference to the Grease Pencil data being used * (as gpencil_data). */ @@ -806,8 +855,10 @@ static eContextResult screen_ctx_active_gpencil_layer(const bContext *C, { wmWindow *win = CTX_wm_window(C); ScrArea *area = CTX_wm_area(C); + const Scene *scene = WM_window_get_active_scene(win); ViewLayer *view_layer = WM_window_get_active_view_layer(win); - Object *obact = view_layer->basact ? view_layer->basact->object : NULL; + BKE_view_layer_synced_ensure(scene, view_layer); + Object *obact = BKE_view_layer_active_object_get(view_layer); bGPdata *gpd = ED_gpencil_data_get_active_direct(area, obact); if (gpd) { @@ -844,8 +895,10 @@ static eContextResult screen_ctx_active_gpencil_frame(const bContext *C, { wmWindow *win = CTX_wm_window(C); ScrArea *area = CTX_wm_area(C); + const Scene *scene = WM_window_get_active_scene(win); ViewLayer *view_layer = WM_window_get_active_view_layer(win); - Object *obact = view_layer->basact ? view_layer->basact->object : NULL; + BKE_view_layer_synced_ensure(scene, view_layer); + Object *obact = BKE_view_layer_active_object_get(view_layer); bGPdata *gpd = ED_gpencil_data_get_active_direct(area, obact); if (gpd) { @@ -863,8 +916,10 @@ static eContextResult screen_ctx_visible_gpencil_layers(const bContext *C, { wmWindow *win = CTX_wm_window(C); ScrArea *area = CTX_wm_area(C); + const Scene *scene = WM_window_get_active_scene(win); ViewLayer *view_layer = WM_window_get_active_view_layer(win); - Object *obact = view_layer->basact ? view_layer->basact->object : NULL; + BKE_view_layer_synced_ensure(scene, view_layer); + Object *obact = BKE_view_layer_active_object_get(view_layer); bGPdata *gpd = ED_gpencil_data_get_active_direct(area, obact); if (gpd) { @@ -883,8 +938,10 @@ static eContextResult screen_ctx_editable_gpencil_layers(const bContext *C, { wmWindow *win = CTX_wm_window(C); ScrArea *area = CTX_wm_area(C); + const Scene *scene = WM_window_get_active_scene(win); ViewLayer *view_layer = WM_window_get_active_view_layer(win); - Object *obact = view_layer->basact ? view_layer->basact->object : NULL; + BKE_view_layer_synced_ensure(scene, view_layer); + Object *obact = BKE_view_layer_active_object_get(view_layer); bGPdata *gpd = ED_gpencil_data_get_active_direct(area, obact); if (gpd) { @@ -903,8 +960,10 @@ static eContextResult screen_ctx_editable_gpencil_strokes(const bContext *C, { wmWindow *win = CTX_wm_window(C); ScrArea *area = CTX_wm_area(C); + const Scene *scene = WM_window_get_active_scene(win); ViewLayer *view_layer = WM_window_get_active_view_layer(win); - Object *obact = view_layer->basact ? view_layer->basact->object : NULL; + BKE_view_layer_synced_ensure(scene, view_layer); + Object *obact = BKE_view_layer_active_object_get(view_layer); bGPdata *gpd = ED_gpencil_data_get_active_direct(area, obact); const bool is_multiedit = (bool)GPENCIL_MULTIEDIT_SESSIONS_ON(gpd); diff --git a/source/blender/editors/screen/screen_draw.c b/source/blender/editors/screen/screen_draw.c index 6406b0d9d52..065cb3a61a2 100644 --- a/source/blender/editors/screen/screen_draw.c +++ b/source/blender/editors/screen/screen_draw.c @@ -236,7 +236,7 @@ void screen_draw_join_highlight(ScrArea *sa1, ScrArea *sa2) uint pos_id = GPU_vertformat_attr_add( immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); - immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); GPU_blend(GPU_BLEND_ALPHA); /* Highlight source (sa1) within combined area. */ @@ -302,7 +302,7 @@ void screen_draw_join_highlight(ScrArea *sa1, ScrArea *sa2) void screen_draw_split_preview(ScrArea *area, const eScreenAxis dir_axis, const float fac) { uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); - immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); /* Split-point. */ GPU_blend(GPU_BLEND_ALPHA); @@ -380,7 +380,7 @@ static void screen_preview_draw_areas(const bScreen *screen, const float ofs_h = ofs_between_areas * 0.5f; uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); - immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); immUniformColor4fv(col); LISTBASE_FOREACH (ScrArea *, area, &screen->areabase) { diff --git a/source/blender/editors/screen/screen_edit.c b/source/blender/editors/screen/screen_edit.c index 73195168d38..bc7006d2ac7 100644 --- a/source/blender/editors/screen/screen_edit.c +++ b/source/blender/editors/screen/screen_edit.c @@ -580,7 +580,7 @@ static void region_cursor_set(wmWindow *win, bool swin_changed) } } -void ED_screen_do_listen(bContext *C, wmNotifier *note) +void ED_screen_do_listen(bContext *C, const wmNotifier *note) { wmWindow *win = CTX_wm_window(C); bScreen *screen = CTX_wm_screen(C); @@ -1163,8 +1163,9 @@ static void screen_set_3dview_camera(Scene *scene, /* fix any cameras that are used in the 3d view but not in the scene */ BKE_screen_view3d_sync(v3d, scene); + BKE_view_layer_synced_ensure(scene, view_layer); if (!v3d->camera || !BKE_view_layer_base_find(view_layer, v3d->camera)) { - v3d->camera = BKE_view_layer_camera_find(view_layer); + v3d->camera = BKE_view_layer_camera_find(scene, view_layer); // XXX if (screen == curscreen) handle_view3d_lock(); if (!v3d->camera) { ListBase *regionbase; @@ -1212,10 +1213,10 @@ void ED_screen_scene_change(bContext *C, /* Mode Syncing. */ if (view_layer_old) { WorkSpace *workspace = CTX_wm_workspace(C); - Object *obact_new = OBACT(view_layer); + Object *obact_new = BKE_view_layer_active_object_get(view_layer); UNUSED_VARS(obact_new); eObjectMode object_mode_old = workspace->object_mode; - Object *obact_old = OBACT(view_layer_old); + Object *obact_old = BKE_view_layer_active_object_get(view_layer_old); UNUSED_VARS(obact_old, object_mode_old); } #endif @@ -1274,7 +1275,7 @@ void ED_screen_full_prevspace(bContext *C, ScrArea *area) BLI_assert(area->full); if (area->flag & AREA_FLAG_STACKED_FULLSCREEN) { - /* stacked fullscreen -> only go back to previous area and don't toggle out of fullscreen */ + /* Stacked full-screen -> only go back to previous area and don't toggle out of full-screen. */ ED_area_prevspace(C, area); } else { @@ -1305,8 +1306,8 @@ void ED_screen_full_restore(bContext *C, ScrArea *area) bScreen *screen = CTX_wm_screen(C); short state = (screen ? screen->state : SCREENMAXIMIZED); - /* if fullscreen area has a temporary space (such as a file browser or fullscreen render - * overlaid on top of an existing setup) then return to the previous space */ + /* If full-screen area has a temporary space (such as a file browser or full-screen render + * overlaid on top of an existing setup) then return to the previous space. */ if (sl->next) { if (sl->link_flag & SPACE_FLAG_TYPE_TEMPORARY) { diff --git a/source/blender/editors/screen/screen_geometry.c b/source/blender/editors/screen/screen_geometry.c index 3486ea8b466..3ad3fa7892c 100644 --- a/source/blender/editors/screen/screen_geometry.c +++ b/source/blender/editors/screen/screen_geometry.c @@ -284,7 +284,7 @@ short screen_geom_find_area_split_point(const ScrArea *area, { const int cur_area_width = screen_geom_area_width(area); const int cur_area_height = screen_geom_area_height(area); - const short area_min_x = AREAMINX; + const short area_min_x = AREAMINX * U.dpi_fac; const short area_min_y = ED_area_headersize(); /* area big enough? */ diff --git a/source/blender/editors/screen/screen_intern.h b/source/blender/editors/screen/screen_intern.h index 4c2d94e2018..feda68a51a7 100644 --- a/source/blender/editors/screen/screen_intern.h +++ b/source/blender/editors/screen/screen_intern.h @@ -53,7 +53,7 @@ typedef enum eScreenAxis { /* area.c */ /** - * we swap spaces for fullscreen to keep all allocated data area vertices were set + * We swap spaces for full-screen to keep all allocated data area vertices were set. */ void ED_area_data_copy(ScrArea *area_dst, ScrArea *area_src, bool do_free); void ED_area_data_swap(ScrArea *area_dst, ScrArea *area_src); diff --git a/source/blender/editors/screen/screen_ops.c b/source/blender/editors/screen/screen_ops.c index 3618b933443..29f78b2a0ef 100644 --- a/source/blender/editors/screen/screen_ops.c +++ b/source/blender/editors/screen/screen_ops.c @@ -723,15 +723,16 @@ typedef struct sActionzoneData { static bool actionzone_area_poll(bContext *C) { wmWindow *win = CTX_wm_window(C); - bScreen *screen = WM_window_get_active_screen(win); - - if (screen && win && win->eventstate) { - const int *xy = &win->eventstate->xy[0]; + if (win && win->eventstate) { + bScreen *screen = WM_window_get_active_screen(win); + if (screen) { + const int *xy = &win->eventstate->xy[0]; - LISTBASE_FOREACH (ScrArea *, area, &screen->areabase) { - LISTBASE_FOREACH (AZone *, az, &area->actionzones) { - if (BLI_rcti_isect_pt_v(&az->rect, xy)) { - return true; + LISTBASE_FOREACH (ScrArea *, area, &screen->areabase) { + LISTBASE_FOREACH (AZone *, az, &area->actionzones) { + if (BLI_rcti_isect_pt_v(&az->rect, xy)) { + return true; + } } } } @@ -858,7 +859,7 @@ static AZone *area_actionzone_refresh_xy(ScrArea *area, const int xy[2], const b /* Check if we even have scroll bars. */ if (((az->direction == AZ_SCROLL_HOR) && !(scroll_flag & V2D_SCROLL_HORIZONTAL)) || ((az->direction == AZ_SCROLL_VERT) && !(scroll_flag & V2D_SCROLL_VERTICAL))) { - /* no scrollbars, do nothing. */ + /* No scroll-bars, do nothing. */ } else if (test_only) { if (isect_value != 0) { @@ -1638,7 +1639,7 @@ static void area_move_set_limits(wmWindow *win, } } else { - int areamin = AREAMINX; + int areamin = AREAMINX * U.dpi_fac; if (area->v1->vec.x > window_rect.xmin) { areamin += U.pixelsize; @@ -2061,7 +2062,7 @@ static bool area_split_allowed(const ScrArea *area, const eScreenAxis dir_axis) return false; } - if ((dir_axis == SCREEN_AXIS_V && area->winx <= 2 * AREAMINX) || + if ((dir_axis == SCREEN_AXIS_V && area->winx <= 2 * AREAMINX * U.dpi_fac) || (dir_axis == SCREEN_AXIS_H && area->winy <= 2 * ED_area_headersize())) { /* Must be at least double minimum sizes to split into two. */ return false; @@ -3266,7 +3267,7 @@ static int screen_maximize_area_exec(bContext *C, wmOperator *op) BLI_assert(!screen->temp); - /* search current screen for 'fullscreen' areas */ + /* search current screen for 'full-screen' areas */ /* prevents restoring info header, when mouse is over it */ LISTBASE_FOREACH (ScrArea *, area_iter, &screen->areabase) { if (area_iter->full) { diff --git a/source/blender/editors/screen/screendump.c b/source/blender/editors/screen/screendump.c index 5464d0a347d..38a9d8ba7ab 100644 --- a/source/blender/editors/screen/screendump.c +++ b/source/blender/editors/screen/screendump.c @@ -54,13 +54,12 @@ static int screenshot_data_create(bContext *C, wmOperator *op, ScrArea *area) { int dumprect_size[2]; - wmWindowManager *wm = CTX_wm_manager(C); wmWindow *win = CTX_wm_window(C); /* do redraw so we don't show popups/menus */ WM_redraw_windows(C); - uint *dumprect = WM_window_pixels_read(wm, win, dumprect_size); + uint *dumprect = WM_window_pixels_read_offscreen(C, win, dumprect_size); if (dumprect) { ScreenshotData *scd = MEM_callocN(sizeof(ScreenshotData), "screenshot"); diff --git a/source/blender/editors/screen/workspace_edit.c b/source/blender/editors/screen/workspace_edit.c index fc3ac53ef0b..9a6bdc98d76 100644 --- a/source/blender/editors/screen/workspace_edit.c +++ b/source/blender/editors/screen/workspace_edit.c @@ -359,6 +359,12 @@ static int workspace_append_activate_exec(bContext *C, wmOperator *op) BLO_LIBLINK_APPEND_RECURSIVE); if (appended_workspace) { + if (BLT_translate_new_dataname()) { + /* Translate workspace name */ + BKE_libblock_rename( + bmain, &appended_workspace->id, CTX_DATA_(BLT_I18NCONTEXT_ID_WORKSPACE, idname)); + } + /* Set defaults. */ BLO_update_defaults_workspace(appended_workspace, NULL); @@ -441,8 +447,14 @@ static void workspace_append_button(uiLayout *layout, BLI_assert(STREQ(ot_append->idname, "WORKSPACE_OT_append_activate")); PointerRNA opptr; - uiItemFullO_ptr( - layout, ot_append, workspace->id.name + 2, ICON_NONE, NULL, WM_OP_EXEC_DEFAULT, 0, &opptr); + uiItemFullO_ptr(layout, + ot_append, + CTX_DATA_(BLT_I18NCONTEXT_ID_WORKSPACE, workspace->id.name + 2), + ICON_NONE, + NULL, + WM_OP_EXEC_DEFAULT, + 0, + &opptr); RNA_string_set(&opptr, "idname", id->name + 2); RNA_string_set(&opptr, "filepath", filepath); } @@ -495,7 +507,8 @@ static void workspace_add_menu(bContext *UNUSED(C), uiLayout *layout, void *temp static int workspace_add_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) { - uiPopupMenu *pup = UI_popup_menu_begin(C, op->type->name, ICON_ADD); + uiPopupMenu *pup = UI_popup_menu_begin( + C, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, op->type->name), ICON_ADD); uiLayout *layout = UI_popup_menu_layout(pup); uiItemMenuF(layout, IFACE_("General"), ICON_NONE, workspace_add_menu, NULL); @@ -507,7 +520,7 @@ static int workspace_add_invoke(bContext *C, wmOperator *op, const wmEvent *UNUS char *template = link->data; char display_name[FILE_MAX]; - BLI_path_to_display_name(display_name, sizeof(display_name), template); + BLI_path_to_display_name(display_name, sizeof(display_name), IFACE_(template)); /* Steals ownership of link data string. */ uiItemMenuFN(layout, display_name, ICON_NONE, workspace_add_menu, template); diff --git a/source/blender/editors/sculpt_paint/CMakeLists.txt b/source/blender/editors/sculpt_paint/CMakeLists.txt index b170280ccf3..2709ac3fd91 100644 --- a/source/blender/editors/sculpt_paint/CMakeLists.txt +++ b/source/blender/editors/sculpt_paint/CMakeLists.txt @@ -21,7 +21,6 @@ set(INC ../../../../intern/atomic ../../../../intern/clog ../../../../intern/eigen - ../../../../intern/glew-mx ../../../../intern/guardedalloc # RNA_prototypes.h ${CMAKE_BINARY_DIR}/source/blender/makesrna @@ -69,7 +68,7 @@ set(SRC sculpt_detail.c sculpt_dyntopo.c sculpt_expand.c - sculpt_face_set.c + sculpt_face_set.cc sculpt_filter_color.c sculpt_filter_mask.c sculpt_filter_mesh.c diff --git a/source/blender/editors/sculpt_paint/curves_sculpt_add.cc b/source/blender/editors/sculpt_paint/curves_sculpt_add.cc index f6539284f74..b5d739ae08e 100644 --- a/source/blender/editors/sculpt_paint/curves_sculpt_add.cc +++ b/source/blender/editors/sculpt_paint/curves_sculpt_add.cc @@ -90,6 +90,8 @@ struct AddOperationExecutor { Object *surface_ob_eval_ = nullptr; Mesh *surface_eval_ = nullptr; + Span<MVert> surface_verts_eval_; + Span<MLoop> surface_loops_eval_; Span<MLoopTri> surface_looptris_eval_; VArraySpan<float2> surface_uv_map_eval_; BVHTreeFromMesh surface_bvh_eval_; @@ -140,6 +142,12 @@ struct AddOperationExecutor { report_empty_evaluated_surface(stroke_extension.reports); return; } + surface_verts_eval_ = surface_eval_->verts(); + surface_loops_eval_ = surface_eval_->loops(); + surface_looptris_eval_ = {BKE_mesh_runtime_looptri_ensure(surface_eval_), + BKE_mesh_runtime_looptri_len(surface_eval_)}; + BKE_bvhtree_from_mesh_get(&surface_bvh_eval_, surface_eval_, BVHTREE_FROM_LOOPTRI, 2); + BLI_SCOPED_DEFER([&]() { free_bvhtree_from_mesh(&surface_bvh_eval_); }); curves_sculpt_ = ctx_.scene->toolsettings->curves_sculpt; brush_ = BKE_paint_brush_for_read(&curves_sculpt_->paint); @@ -159,11 +167,10 @@ struct AddOperationExecutor { /* Find UV map. */ VArraySpan<float2> surface_uv_map; if (curves_id_orig_->surface_uv_map != nullptr) { - surface_uv_map = bke::mesh_attributes(surface_orig) - .lookup<float2>(curves_id_orig_->surface_uv_map, ATTR_DOMAIN_CORNER); - surface_uv_map_eval_ = bke::mesh_attributes(*surface_eval_) - .lookup<float2>(curves_id_orig_->surface_uv_map, - ATTR_DOMAIN_CORNER); + surface_uv_map = surface_orig.attributes().lookup<float2>(curves_id_orig_->surface_uv_map, + ATTR_DOMAIN_CORNER); + surface_uv_map_eval_ = surface_eval_->attributes().lookup<float2>( + curves_id_orig_->surface_uv_map, ATTR_DOMAIN_CORNER); } if (surface_uv_map.is_empty()) { @@ -179,12 +186,6 @@ struct AddOperationExecutor { /* Use a pointer cast to avoid overflow warnings. */ RandomNumberGenerator rng{*(uint32_t *)(&time)}; - BKE_bvhtree_from_mesh_get(&surface_bvh_eval_, surface_eval_, BVHTREE_FROM_LOOPTRI, 2); - BLI_SCOPED_DEFER([&]() { free_bvhtree_from_mesh(&surface_bvh_eval_); }); - - surface_looptris_eval_ = {BKE_mesh_runtime_looptri_ensure(surface_eval_), - BKE_mesh_runtime_looptri_len(surface_eval_)}; - /* Sample points on the surface using one of multiple strategies. */ Vector<float2> sampled_uvs; if (add_amount_ == 1) { @@ -296,7 +297,7 @@ struct AddOperationExecutor { const MLoopTri &looptri = surface_looptris_eval_[looptri_index]; const float3 brush_pos_su = ray_hit.co; const float3 bary_coords = bke::mesh_surface_sample::compute_bary_coord_in_triangle( - *surface_eval_, looptri, brush_pos_su); + surface_verts_eval_, surface_loops_eval_, looptri, brush_pos_su); const float2 uv = bke::mesh_surface_sample::sample_corner_attrribute_with_bary_coords( bary_coords, looptri, surface_uv_map_eval_); @@ -421,9 +422,9 @@ struct AddOperationExecutor { brush_radius_su, [&](const int index, const float3 &UNUSED(co), const float UNUSED(dist_sq)) { const MLoopTri &looptri = surface_looptris_eval_[index]; - const float3 v0_su = surface_eval_->mvert[surface_eval_->mloop[looptri.tri[0]].v].co; - const float3 v1_su = surface_eval_->mvert[surface_eval_->mloop[looptri.tri[1]].v].co; - const float3 v2_su = surface_eval_->mvert[surface_eval_->mloop[looptri.tri[2]].v].co; + const float3 v0_su = surface_verts_eval_[surface_loops_eval_[looptri.tri[0]].v].co; + const float3 v1_su = surface_verts_eval_[surface_loops_eval_[looptri.tri[1]].v].co; + const float3 v2_su = surface_verts_eval_[surface_loops_eval_[looptri.tri[2]].v].co; float3 normal_su; normal_tri_v3(normal_su, v0_su, v1_su, v2_su); if (math::dot(normal_su, view_direction_su) >= 0.0f) { diff --git a/source/blender/editors/sculpt_paint/curves_sculpt_brush.cc b/source/blender/editors/sculpt_paint/curves_sculpt_brush.cc index 95261f29914..02bf7aacd93 100644 --- a/source/blender/editors/sculpt_paint/curves_sculpt_brush.cc +++ b/source/blender/editors/sculpt_paint/curves_sculpt_brush.cc @@ -352,33 +352,37 @@ float transform_brush_radius(const float4x4 &transform, return math::distance(new_position, new_offset_position); } -void move_last_point_and_resample(MutableSpan<float3> positions, const float3 &new_last_position) +void move_last_point_and_resample(MoveAndResampleBuffers &buffer, + MutableSpan<float3> positions, + const float3 &new_last_position) { /* Find the accumulated length of each point in the original curve, * treating it as a poly curve for performance reasons and simplicity. */ - Array<float> orig_lengths(length_parameterize::segments_num(positions.size(), false)); - length_parameterize::accumulate_lengths<float3>(positions, false, orig_lengths); - const float orig_total_length = orig_lengths.last(); + buffer.orig_lengths.reinitialize(length_parameterize::segments_num(positions.size(), false)); + length_parameterize::accumulate_lengths<float3>(positions, false, buffer.orig_lengths); + const float orig_total_length = buffer.orig_lengths.last(); /* Find the factor by which the new curve is shorter or longer than the original. */ const float new_last_segment_length = math::distance(positions.last(1), new_last_position); - const float new_total_length = orig_lengths.last(1) + new_last_segment_length; + const float new_total_length = buffer.orig_lengths.last(1) + new_last_segment_length; const float length_factor = safe_divide(new_total_length, orig_total_length); /* Calculate the lengths to sample the original curve with by scaling the original lengths. */ - Array<float> new_lengths(positions.size() - 1); - new_lengths.first() = 0.0f; - for (const int i : new_lengths.index_range().drop_front(1)) { - new_lengths[i] = orig_lengths[i - 1] * length_factor; + buffer.new_lengths.reinitialize(positions.size() - 1); + buffer.new_lengths.first() = 0.0f; + for (const int i : buffer.new_lengths.index_range().drop_front(1)) { + buffer.new_lengths[i] = buffer.orig_lengths[i - 1] * length_factor; } - Array<int> indices(positions.size() - 1); - Array<float> factors(positions.size() - 1); - length_parameterize::sample_at_lengths(orig_lengths, new_lengths, indices, factors); + buffer.sample_indices.reinitialize(positions.size() - 1); + buffer.sample_factors.reinitialize(positions.size() - 1); + length_parameterize::sample_at_lengths( + buffer.orig_lengths, buffer.new_lengths, buffer.sample_indices, buffer.sample_factors); - Array<float3> new_positions(positions.size() - 1); - length_parameterize::interpolate<float3>(positions, indices, factors, new_positions); - positions.drop_back(1).copy_from(new_positions); + buffer.new_positions.reinitialize(positions.size() - 1); + length_parameterize::interpolate<float3>( + positions, buffer.sample_indices, buffer.sample_factors, buffer.new_positions); + positions.drop_back(1).copy_from(buffer.new_positions); positions.last() = new_last_position; } diff --git a/source/blender/editors/sculpt_paint/curves_sculpt_density.cc b/source/blender/editors/sculpt_paint/curves_sculpt_density.cc index 2e03e907e34..a37eb4bb560 100644 --- a/source/blender/editors/sculpt_paint/curves_sculpt_density.cc +++ b/source/blender/editors/sculpt_paint/curves_sculpt_density.cc @@ -137,11 +137,10 @@ struct DensityAddOperationExecutor { /* Find UV map. */ VArraySpan<float2> surface_uv_map; if (curves_id_orig_->surface_uv_map != nullptr) { - surface_uv_map = bke::mesh_attributes(*surface_orig_) - .lookup<float2>(curves_id_orig_->surface_uv_map, ATTR_DOMAIN_CORNER); - surface_uv_map_eval_ = bke::mesh_attributes(*surface_eval_) - .lookup<float2>(curves_id_orig_->surface_uv_map, - ATTR_DOMAIN_CORNER); + surface_uv_map = surface_orig_->attributes().lookup<float2>(curves_id_orig_->surface_uv_map, + ATTR_DOMAIN_CORNER); + surface_uv_map_eval_ = surface_eval_->attributes().lookup<float2>( + curves_id_orig_->surface_uv_map, ATTR_DOMAIN_CORNER); } if (surface_uv_map.is_empty()) { report_missing_uv_map_on_original_surface(stroke_extension.reports); diff --git a/source/blender/editors/sculpt_paint/curves_sculpt_grow_shrink.cc b/source/blender/editors/sculpt_paint/curves_sculpt_grow_shrink.cc index 1ee43d98e6f..bc354ed66f4 100644 --- a/source/blender/editors/sculpt_paint/curves_sculpt_grow_shrink.cc +++ b/source/blender/editors/sculpt_paint/curves_sculpt_grow_shrink.cc @@ -141,24 +141,23 @@ class ExtrapolateCurvesEffect : public CurvesEffect { { MutableSpan<float3> positions_cu = curves.positions_for_write(); threading::parallel_for(curve_indices.index_range(), 256, [&](const IndexRange range) { + MoveAndResampleBuffers resample_buffer; for (const int influence_i : range) { const int curve_i = curve_indices[influence_i]; const float move_distance_cu = move_distances_cu[influence_i]; - const IndexRange curve_points = curves.points_for_curve(curve_i); - - if (curve_points.size() <= 1) { + const IndexRange points = curves.points_for_curve(curve_i); + if (points.size() <= 1) { continue; } - const float3 old_last_pos_cu = positions_cu[curve_points.last()]; + const float3 old_last_pos_cu = positions_cu[points.last()]; /* Use some point within the curve rather than the end point to smooth out some random * variation. */ - const float3 direction_reference_point = - positions_cu[curve_points[curve_points.size() / 2]]; + const float3 direction_reference_point = positions_cu[points[points.size() / 2]]; const float3 direction = math::normalize(old_last_pos_cu - direction_reference_point); const float3 new_last_pos_cu = old_last_pos_cu + direction * move_distance_cu; - move_last_point_and_resample(positions_cu.slice(curve_points), new_last_pos_cu); + move_last_point_and_resample(resample_buffer, positions_cu.slice(points), new_last_pos_cu); } }); } @@ -351,7 +350,7 @@ struct CurvesEffectOperationExecutor { const Vector<float4x4> symmetry_brush_transforms = get_symmetry_brush_transforms( eCurvesSymmetryType(curves_id_->symmetry)); Vector<float4x4> symmetry_brush_transforms_inv; - for (const float4x4 brush_transform : symmetry_brush_transforms) { + for (const float4x4 &brush_transform : symmetry_brush_transforms) { symmetry_brush_transforms_inv.append(brush_transform.inverted()); } diff --git a/source/blender/editors/sculpt_paint/curves_sculpt_intern.hh b/source/blender/editors/sculpt_paint/curves_sculpt_intern.hh index 5c8c0cedc6f..61e2559f303 100644 --- a/source/blender/editors/sculpt_paint/curves_sculpt_intern.hh +++ b/source/blender/editors/sculpt_paint/curves_sculpt_intern.hh @@ -102,7 +102,23 @@ VArray<float> get_curves_selection(const Curves &curves_id); */ VArray<float> get_point_selection(const Curves &curves_id); -void move_last_point_and_resample(MutableSpan<float3> positions, const float3 &new_last_position); +/** See #move_last_point_and_resample. */ +struct MoveAndResampleBuffers { + Array<float> orig_lengths; + Array<float> new_lengths; + + Array<int> sample_indices; + Array<float> sample_factors; + + Array<float3> new_positions; +}; + +/** + * \param buffer: Reused memory to avoid reallocations when the function is called many times. + */ +void move_last_point_and_resample(MoveAndResampleBuffers &buffer, + MutableSpan<float3> positions, + const float3 &new_last_position); class CurvesSculptCommonContext { public: diff --git a/source/blender/editors/sculpt_paint/curves_sculpt_ops.cc b/source/blender/editors/sculpt_paint/curves_sculpt_ops.cc index 4ae4149a2a0..423fd70e1e2 100644 --- a/source/blender/editors/sculpt_paint/curves_sculpt_ops.cc +++ b/source/blender/editors/sculpt_paint/curves_sculpt_ops.cc @@ -914,7 +914,7 @@ static void SCULPT_CURVES_OT_select_grow(wmOperatorType *ot) "Distance", "By how much to grow the selection", -10.0f, - 10.f); + 10.0f); RNA_def_property_subtype(prop, PROP_DISTANCE); } @@ -1098,7 +1098,7 @@ static void min_distance_edit_draw(bContext *C, int UNUSED(x), int UNUSED(y), vo GPUVertFormat *format = immVertexFormat(); uint pos2d = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); - immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); immUniformColor3fvAlpha(circle_col, circle_alpha); imm_draw_circle_wire_2d(pos2d, 0.0f, 0.0f, brush_radius_re, 80); diff --git a/source/blender/editors/sculpt_paint/curves_sculpt_puff.cc b/source/blender/editors/sculpt_paint/curves_sculpt_puff.cc index 139e0d67e89..ec69aae372c 100644 --- a/source/blender/editors/sculpt_paint/curves_sculpt_puff.cc +++ b/source/blender/editors/sculpt_paint/curves_sculpt_puff.cc @@ -70,6 +70,8 @@ struct PuffOperationExecutor { Object *surface_ob_ = nullptr; Mesh *surface_ = nullptr; + Span<MVert> surface_verts_; + Span<MLoop> surface_loops_; Span<MLoopTri> surface_looptris_; Span<float3> corner_normals_su_; BVHTreeFromMesh surface_bvh_; @@ -117,11 +119,12 @@ struct PuffOperationExecutor { reinterpret_cast<const float3 *>(CustomData_get_layer(&surface_->ldata, CD_NORMAL)), surface_->totloop}; - BKE_bvhtree_from_mesh_get(&surface_bvh_, surface_, BVHTREE_FROM_LOOPTRI, 2); - BLI_SCOPED_DEFER([&]() { free_bvhtree_from_mesh(&surface_bvh_); }); - + surface_verts_ = surface_->verts(); + surface_loops_ = surface_->loops(); surface_looptris_ = {BKE_mesh_runtime_looptri_ensure(surface_), BKE_mesh_runtime_looptri_len(surface_)}; + BKE_bvhtree_from_mesh_get(&surface_bvh_, surface_, BVHTREE_FROM_LOOPTRI, 2); + BLI_SCOPED_DEFER([&]() { free_bvhtree_from_mesh(&surface_bvh_); }); if (stroke_extension.is_first) { this->initialize_segment_lengths(); @@ -289,9 +292,9 @@ struct PuffOperationExecutor { const MLoopTri &looptri = surface_looptris_[nearest.index]; const float3 closest_pos_su = nearest.co; - const float3 &v0_su = surface_->mvert[surface_->mloop[looptri.tri[0]].v].co; - const float3 &v1_su = surface_->mvert[surface_->mloop[looptri.tri[1]].v].co; - const float3 &v2_su = surface_->mvert[surface_->mloop[looptri.tri[2]].v].co; + const float3 &v0_su = surface_verts_[surface_loops_[looptri.tri[0]].v].co; + const float3 &v1_su = surface_verts_[surface_loops_[looptri.tri[1]].v].co; + const float3 &v2_su = surface_verts_[surface_loops_[looptri.tri[2]].v].co; float3 bary_coords; interp_weights_tri_v3(bary_coords, v0_su, v1_su, v2_su, closest_pos_su); const float3 normal_su = geometry::compute_surface_point_normal( diff --git a/source/blender/editors/sculpt_paint/curves_sculpt_slide.cc b/source/blender/editors/sculpt_paint/curves_sculpt_slide.cc index ebdff8a6c4b..1108f5c72a9 100644 --- a/source/blender/editors/sculpt_paint/curves_sculpt_slide.cc +++ b/source/blender/editors/sculpt_paint/curves_sculpt_slide.cc @@ -112,6 +112,8 @@ struct SlideOperationExecutor { Object *surface_ob_eval_ = nullptr; Mesh *surface_eval_ = nullptr; + Span<MVert> surface_verts_eval_; + Span<MLoop> surface_loops_eval_; Span<MLoopTri> surface_looptris_eval_; VArraySpan<float2> surface_uv_map_eval_; BVHTreeFromMesh surface_bvh_eval_; @@ -149,6 +151,12 @@ struct SlideOperationExecutor { report_missing_uv_map_on_original_surface(stroke_extension.reports); return; } + if (curves_orig_->surface_uv_coords().is_empty()) { + BKE_report(stroke_extension.reports, + RPT_WARNING, + TIP_("Curves do not have surface attachment information")); + return; + } const StringRefNull uv_map_name = curves_id_orig_->surface_uv_map; curves_sculpt_ = ctx_.scene->toolsettings->curves_sculpt; @@ -172,8 +180,8 @@ struct SlideOperationExecutor { } surface_looptris_orig_ = {BKE_mesh_runtime_looptri_ensure(surface_orig_), BKE_mesh_runtime_looptri_len(surface_orig_)}; - surface_uv_map_orig_ = - bke::mesh_attributes(*surface_orig_).lookup<float2>(uv_map_name, ATTR_DOMAIN_CORNER); + surface_uv_map_orig_ = surface_orig_->attributes().lookup<float2>(uv_map_name, + ATTR_DOMAIN_CORNER); if (surface_uv_map_orig_.is_empty()) { report_missing_uv_map_on_original_surface(stroke_extension.reports); return; @@ -199,8 +207,10 @@ struct SlideOperationExecutor { } surface_looptris_eval_ = {BKE_mesh_runtime_looptri_ensure(surface_eval_), BKE_mesh_runtime_looptri_len(surface_eval_)}; - surface_uv_map_eval_ = - bke::mesh_attributes(*surface_eval_).lookup<float2>(uv_map_name, ATTR_DOMAIN_CORNER); + surface_verts_eval_ = surface_eval_->verts(); + surface_loops_eval_ = surface_eval_->loops(); + surface_uv_map_eval_ = surface_eval_->attributes().lookup<float2>(uv_map_name, + ATTR_DOMAIN_CORNER); if (surface_uv_map_eval_.is_empty()) { report_missing_uv_map_on_evaluated_surface(stroke_extension.reports); return; @@ -313,8 +323,8 @@ struct SlideOperationExecutor { { const float4x4 brush_transform_inv = brush_transform.inverted(); - const Span<MVert> verts_orig_su{surface_orig_->mvert, surface_orig_->totvert}; - const Span<MLoop> loops_orig{surface_orig_->mloop, surface_orig_->totloop}; + const Span<MVert> verts_orig_su = surface_orig_->verts(); + const Span<MLoop> loops_orig = surface_orig_->loops(); MutableSpan<float3> positions_orig_cu = curves_orig_->positions_for_write(); MutableSpan<float2> surface_uv_coords = curves_orig_->surface_uv_coords_for_write(); @@ -377,7 +387,7 @@ struct SlideOperationExecutor { /* Compute the uv of the new surface position on the evaluated mesh. */ const MLoopTri &looptri_eval = surface_looptris_eval_[looptri_index_eval]; const float3 bary_weights_eval = bke::mesh_surface_sample::compute_bary_coord_in_triangle( - *surface_eval_, looptri_eval, hit_pos_eval_su); + surface_verts_eval_, surface_loops_eval_, looptri_eval, hit_pos_eval_su); const float2 uv = attribute_math::mix3(bary_weights_eval, surface_uv_map_eval_[looptri_eval.tri[0]], surface_uv_map_eval_[looptri_eval.tri[1]], diff --git a/source/blender/editors/sculpt_paint/curves_sculpt_snake_hook.cc b/source/blender/editors/sculpt_paint/curves_sculpt_snake_hook.cc index 54b81fa221d..67757ce5f4a 100644 --- a/source/blender/editors/sculpt_paint/curves_sculpt_snake_hook.cc +++ b/source/blender/editors/sculpt_paint/curves_sculpt_snake_hook.cc @@ -188,6 +188,7 @@ struct SnakeHookOperatorExecutor { const float brush_radius_sq_re = pow2f(brush_radius_re); threading::parallel_for(curves_->curves_range(), 256, [&](const IndexRange curves_range) { + MoveAndResampleBuffers resample_buffer; for (const int curve_i : curves_range) { const IndexRange points = curves_->points_for_curve(curve_i); const int last_point_i = points.last(); @@ -221,8 +222,8 @@ struct SnakeHookOperatorExecutor { const float3 translation_orig = deformation.translation_from_deformed_to_original( last_point_i, translation_eval); - move_last_point_and_resample(positions_cu.slice(points), - positions_cu[last_point_i] + translation_orig); + const float3 last_point_cu = positions_cu[last_point_i] + translation_orig; + move_last_point_and_resample(resample_buffer, positions_cu.slice(points), last_point_cu); } }); } @@ -268,6 +269,7 @@ struct SnakeHookOperatorExecutor { const float brush_radius_sq_cu = pow2f(brush_radius_cu); threading::parallel_for(curves_->curves_range(), 256, [&](const IndexRange curves_range) { + MoveAndResampleBuffers resample_buffer; for (const int curve_i : curves_range) { const IndexRange points = curves_->points_for_curve(curve_i); const int last_point_i = points.last(); @@ -289,8 +291,8 @@ struct SnakeHookOperatorExecutor { const float3 translation_orig = deformation.translation_from_deformed_to_original( last_point_i, translation_eval); - move_last_point_and_resample(positions_cu.slice(points), - positions_cu[last_point_i] + translation_orig); + const float3 last_point_cu = positions_cu[last_point_i] + translation_orig; + move_last_point_and_resample(resample_buffer, positions_cu.slice(points), last_point_cu); } }); } diff --git a/source/blender/editors/sculpt_paint/paint_cursor.c b/source/blender/editors/sculpt_paint/paint_cursor.c index 577540725af..164e13ac3c9 100644 --- a/source/blender/editors/sculpt_paint/paint_cursor.c +++ b/source/blender/editors/sculpt_paint/paint_cursor.c @@ -628,7 +628,7 @@ static bool paint_draw_tex_overlay(UnifiedPaintSettings *ups, /* Premultiplied alpha blending. */ GPU_blend(GPU_BLEND_ALPHA_PREMULT); - immBindBuiltinProgram(GPU_SHADER_2D_IMAGE_COLOR); + immBindBuiltinProgram(GPU_SHADER_3D_IMAGE_COLOR); float final_color[4] = {1.0f, 1.0f, 1.0f, 1.0f}; if (!col) { @@ -720,7 +720,7 @@ static bool paint_draw_cursor_overlay( GPU_blend(GPU_BLEND_ALPHA_PREMULT); - immBindBuiltinProgram(GPU_SHADER_2D_IMAGE_COLOR); + immBindBuiltinProgram(GPU_SHADER_3D_IMAGE_COLOR); float final_color[4] = {UNPACK3(U.sculpt_paint_overlay_col), 1.0f}; mul_v4_fl(final_color, brush->cursor_overlay_alpha * 0.01f); @@ -915,7 +915,7 @@ static void paint_draw_curve_cursor(Brush *brush, ViewContext *vc) /* Draw the bezier handles and the curve segment between the current and next point. */ uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); - immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); float selec_col[4], handle_col[4], pivot_col[4]; UI_GetThemeColorType4fv(TH_VERTEX_SELECT, SPACE_VIEW3D, selec_col); @@ -1869,7 +1869,7 @@ static void paint_cursor_setup_2D_drawing(PaintCursorContext *pcontext) GPU_line_smooth(true); pcontext->pos = GPU_vertformat_attr_add( immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); - immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); } static void paint_cursor_setup_3D_drawing(PaintCursorContext *pcontext) diff --git a/source/blender/editors/sculpt_paint/paint_hide.c b/source/blender/editors/sculpt_paint/paint_hide.c index c904d533db8..9e435ee0748 100644 --- a/source/blender/editors/sculpt_paint/paint_hide.c +++ b/source/blender/editors/sculpt_paint/paint_hide.c @@ -81,7 +81,7 @@ static void partialvis_update_mesh(Object *ob, bool *hide_vert = CustomData_get_layer_named(&me->vdata, CD_PROP_BOOL, ".hide_vert"); if (hide_vert == NULL) { hide_vert = CustomData_add_layer_named( - &me->vdata, CD_PROP_BOOL, CD_CALLOC, NULL, me->totvert, ".hide_vert"); + &me->vdata, CD_PROP_BOOL, CD_SET_DEFAULT, NULL, me->totvert, ".hide_vert"); } SCULPT_undo_push_node(ob, node, SCULPT_UNDO_HIDDEN); @@ -351,10 +351,10 @@ static int hide_show_exec(bContext *C, wmOperator *op) /* Start undo. */ switch (action) { case PARTIALVIS_HIDE: - SCULPT_undo_push_begin(ob, "Hide area"); + SCULPT_undo_push_begin_ex(ob, "Hide area"); break; case PARTIALVIS_SHOW: - SCULPT_undo_push_begin(ob, "Show area"); + SCULPT_undo_push_begin_ex(ob, "Show area"); break; } @@ -383,10 +383,9 @@ static int hide_show_exec(bContext *C, wmOperator *op) * sculpt but it looks wrong when entering editmode otherwise). */ if (pbvh_type == PBVH_FACES) { BKE_mesh_flush_hidden_from_verts(me); + BKE_pbvh_update_hide_attributes_from_mesh(pbvh); } - SCULPT_visibility_sync_all_vertex_to_face_sets(ob->sculpt); - DEG_id_tag_update(&ob->id, ID_RECALC_SHADING); ED_region_tag_redraw(region); diff --git a/source/blender/editors/sculpt_paint/paint_image.cc b/source/blender/editors/sculpt_paint/paint_image.cc index 24290fed323..c852fd25bc4 100644 --- a/source/blender/editors/sculpt_paint/paint_image.cc +++ b/source/blender/editors/sculpt_paint/paint_image.cc @@ -158,11 +158,21 @@ void imapaint_image_update( imapaintpartial.dirty_region.xmax, imapaintpartial.dirty_region.ymax); + /* When buffer is partial updated the planes should be set to a larger value than 8. This will + * make sure that partial updating is working but uses more GPU memory as the gpu texture will + * have 4 channels. When so the whole texture needs to be reuploaded to the GPU using the new + * texture format. */ + if (ibuf != nullptr && ibuf->planes == 8) { + ibuf->planes = 32; + BKE_image_partial_update_mark_full_update(image); + return; + } + /* TODO: should set_tpage create ->rect? */ if (texpaint || (sima && sima->lock)) { const int w = BLI_rcti_size_x(&imapaintpartial.dirty_region); const int h = BLI_rcti_size_y(&imapaintpartial.dirty_region); - /* Testing with partial update in uv editor too */ + /* Testing with partial update in uv editor too. */ BKE_image_update_gputexture( image, iuser, imapaintpartial.dirty_region.xmin, imapaintpartial.dirty_region.ymin, w, h); } diff --git a/source/blender/editors/sculpt_paint/paint_image_ops_paint.cc b/source/blender/editors/sculpt_paint/paint_image_ops_paint.cc index a671c24c514..5d50cdb4d1f 100644 --- a/source/blender/editors/sculpt_paint/paint_image_ops_paint.cc +++ b/source/blender/editors/sculpt_paint/paint_image_ops_paint.cc @@ -13,6 +13,7 @@ #include "BKE_brush.h" #include "BKE_context.h" +#include "BKE_layer.h" #include "BKE_paint.h" #include "BKE_undo_system.h" @@ -252,7 +253,7 @@ static void gradient_draw_line(bContext *UNUSED(C), int x, int y, void *customda ARegion *region = pop->vc.region; - immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); GPU_line_width(4.0); immUniformColor4ub(0, 0, 0, 255); @@ -293,7 +294,8 @@ static PaintOperation *texture_paint_init(bContext *C, wmOperator *op, const flo copy_v2_v2(pop->startmouse, mouse); ViewLayer *view_layer = CTX_data_view_layer(C); - Object *ob = OBACT(view_layer); + BKE_view_layer_synced_ensure(scene, view_layer); + Object *ob = BKE_view_layer_active_object_get(view_layer); /* initialize from context */ if (CTX_wm_region_view3d(C)) { diff --git a/source/blender/editors/sculpt_paint/paint_image_proj.c b/source/blender/editors/sculpt_paint/paint_image_proj.c index 3e5ad9bdc2d..bae5050f0ac 100644 --- a/source/blender/editors/sculpt_paint/paint_image_proj.c +++ b/source/blender/editors/sculpt_paint/paint_image_proj.c @@ -56,6 +56,7 @@ #include "BKE_global.h" #include "BKE_idprop.h" #include "BKE_image.h" +#include "BKE_layer.h" #include "BKE_lib_id.h" #include "BKE_main.h" #include "BKE_material.h" @@ -414,6 +415,8 @@ typedef struct ProjPaintState { const float (*vert_normals)[3]; const MEdge *medge_eval; const MPoly *mpoly_eval; + const bool *select_poly_eval; + const int *material_indices; const MLoop *mloop_eval; const MLoopTri *mlooptri_eval; @@ -542,8 +545,8 @@ static int project_paint_face_paint_tile(Image *ima, const float *uv) 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->mat_array[mp->mat_nr]; + const int poly_i = ps->mlooptri_eval[tri_index].poly; + Material *ma = ps->mat_array[ps->material_indices == NULL ? 0 : ps->material_indices[poly_i]]; return ma ? ma->texpaintslot + ma->paint_active_slot : NULL; } @@ -553,23 +556,23 @@ static Image *project_paint_face_paint_image(const ProjPaintState *ps, int tri_i return ps->stencil_ima; } - const MPoly *mp = ps_tri_index_to_mpoly(ps, tri_index); - Material *ma = ps->mat_array[mp->mat_nr]; + const int poly_i = ps->mlooptri_eval[tri_index].poly; + Material *ma = ps->mat_array[ps->material_indices == NULL ? 0 : ps->material_indices[poly_i]]; TexPaintSlot *slot = ma ? ma->texpaintslot + ma->paint_active_slot : NULL; return slot ? slot->ima : ps->canvas_ima; } 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->mat_array[mp->mat_nr]; + const int poly_i = ps->mlooptri_eval[tri_index].poly; + Material *ma = ps->mat_array[ps->material_indices == NULL ? 0 : ps->material_indices[poly_i]]; 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->mat_array[mp->mat_nr]; + const int poly_i = ps->mlooptri_eval[tri_index].poly; + Material *ma = ps->mat_array[ps->material_indices == NULL ? 0 : ps->material_indices[poly_i]]; TexPaintSlot *slot = ma ? ma->texpaintslot + ma->paint_clone_slot : NULL; return slot ? slot->ima : ps->clone_ima; } @@ -1231,12 +1234,12 @@ static VertSeam *find_adjacent_seam(const ProjPaintState *ps, LISTBASE_CIRCULAR_BACKWARD_END(VertSeam *, vert_seams, adjacent, seam); } else { - LISTBASE_CIRCULAR_FORWARD_BEGIN (vert_seams, adjacent, seam) { + LISTBASE_CIRCULAR_FORWARD_BEGIN (VertSeam *, vert_seams, adjacent, seam) { if ((adjacent->normal_cw != seam->normal_cw) && cmp_uv(adjacent->uv, seam->uv)) { break; } } - LISTBASE_CIRCULAR_FORWARD_END(vert_seams, adjacent, seam); + LISTBASE_CIRCULAR_FORWARD_END(VertSeam *, vert_seams, adjacent, seam); } BLI_assert(adjacent); @@ -1521,7 +1524,7 @@ static void project_face_seams_init(const ProjPaintState *ps, static void screen_px_from_ortho(const float uv[2], const float v1co[3], const float v2co[3], - const float v3co[3], /* Screenspace coords */ + const float v3co[3], /* Screen-space coords */ const float uv1co[2], const float uv2co[2], const float uv3co[2], @@ -4053,13 +4056,17 @@ static bool proj_paint_state_mesh_eval_init(const bContext *C, ProjPaintState *p } ps->mat_array[totmat - 1] = NULL; - ps->mvert_eval = ps->me_eval->mvert; + ps->mvert_eval = BKE_mesh_verts(ps->me_eval); ps->vert_normals = BKE_mesh_vertex_normals_ensure(ps->me_eval); if (ps->do_mask_cavity) { - ps->medge_eval = ps->me_eval->medge; + ps->medge_eval = BKE_mesh_edges(ps->me_eval); } - ps->mloop_eval = ps->me_eval->mloop; - ps->mpoly_eval = ps->me_eval->mpoly; + ps->mloop_eval = BKE_mesh_loops(ps->me_eval); + ps->mpoly_eval = BKE_mesh_polys(ps->me_eval); + ps->select_poly_eval = (const bool *)CustomData_get_layer_named( + &ps->me_eval->pdata, CD_PROP_BOOL, ".select_poly"); + ps->material_indices = (const int *)CustomData_get_layer_named( + &ps->me_eval->pdata, CD_PROP_INT32, "material_index"); ps->totvert_eval = ps->me_eval->totvert; ps->totedge_eval = ps->me_eval->totedge; @@ -4141,7 +4148,7 @@ static bool project_paint_clone_face_skip(ProjPaintState *ps, } typedef struct { - const MPoly *mpoly_orig; + const bool *select_poly_orig; const int *index_mp_to_orig; } ProjPaintFaceLookup; @@ -4150,8 +4157,10 @@ static void proj_paint_face_lookup_init(const ProjPaintState *ps, ProjPaintFaceL { memset(face_lookup, 0, sizeof(*face_lookup)); if (ps->do_face_sel) { + Mesh *orig_mesh = (Mesh *)ps->ob->data; face_lookup->index_mp_to_orig = CustomData_get_layer(&ps->me_eval->pdata, CD_ORIGINDEX); - face_lookup->mpoly_orig = ((Mesh *)ps->ob->data)->mpoly; + face_lookup->select_poly_orig = CustomData_get_layer_named( + &orig_mesh->pdata, CD_PROP_BOOL, ".select_poly"); } } @@ -4162,17 +4171,12 @@ static bool project_paint_check_face_sel(const ProjPaintState *ps, { if (ps->do_face_sel) { int orig_index; - const MPoly *mp; if ((face_lookup->index_mp_to_orig != NULL) && (((orig_index = (face_lookup->index_mp_to_orig[lt->poly]))) != ORIGINDEX_NONE)) { - mp = &face_lookup->mpoly_orig[orig_index]; + return face_lookup->select_poly_orig && face_lookup->select_poly_orig[orig_index]; } - else { - mp = &ps->mpoly_eval[lt->poly]; - } - - return ((mp->flag & ME_FACE_SEL) != 0); + return ps->select_poly_eval && ps->select_poly_eval[lt->poly]; } return true; } @@ -6038,7 +6042,8 @@ static int texture_paint_camera_project_exec(bContext *C, wmOperator *op) int orig_brush_size; IDProperty *idgroup; IDProperty *view_data = NULL; - Object *ob = OBACT(view_layer); + BKE_view_layer_synced_ensure(scene, view_layer); + Object *ob = BKE_view_layer_active_object_get(view_layer); bool uvs, mat, tex; if (ob == NULL || ob->type != OB_MESH) { diff --git a/source/blender/editors/sculpt_paint/paint_mask.c b/source/blender/editors/sculpt_paint/paint_mask.c index 2e57886fd95..ca1e5489460 100644 --- a/source/blender/editors/sculpt_paint/paint_mask.c +++ b/source/blender/editors/sculpt_paint/paint_mask.c @@ -134,6 +134,7 @@ static void mask_flood_fill_task_cb(void *__restrict userdata, static int mask_flood_fill_exec(bContext *C, wmOperator *op) { + const Scene *scene = CTX_data_scene(C); Object *ob = CTX_data_active_object(C); Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C); PaintMaskFloodMode mode; @@ -146,13 +147,16 @@ static int mask_flood_fill_exec(bContext *C, wmOperator *op) mode = RNA_enum_get(op->ptr, "mode"); value = RNA_float_get(op->ptr, "value"); + MultiresModifierData *mmd = BKE_sculpt_multires_active(scene, ob); + BKE_sculpt_mask_layers_ensure(ob, mmd); + BKE_sculpt_update_object_for_edit(depsgraph, ob, false, true, false); pbvh = ob->sculpt->pbvh; multires = (BKE_pbvh_type(pbvh) == PBVH_GRIDS); BKE_pbvh_search_gather(pbvh, NULL, NULL, &nodes, &totnode); - SCULPT_undo_push_begin(ob, "Mask flood fill"); + SCULPT_undo_push_begin(ob, op); MaskTaskData data = { .ob = ob, @@ -687,10 +691,10 @@ static bool sculpt_gesture_is_vertex_effected(SculptGestureContext *sgcontext, P return false; } -static void sculpt_gesture_apply(bContext *C, SculptGestureContext *sgcontext) +static void sculpt_gesture_apply(bContext *C, SculptGestureContext *sgcontext, wmOperator *op) { SculptGestureOperation *operation = sgcontext->operation; - SCULPT_undo_push_begin(CTX_data_active_object(C), "Sculpt Gesture Apply"); + SCULPT_undo_push_begin(CTX_data_active_object(C), op); operation->sculpt_gesture_begin(C, sgcontext); @@ -774,6 +778,8 @@ static void sculpt_gesture_init_face_set_properties(SculptGestureContext *sgcont struct Mesh *mesh = BKE_mesh_from_object(sgcontext->vc.obact); sgcontext->operation = MEM_callocN(sizeof(SculptGestureFaceSetOperation), "Face Set Operation"); + sgcontext->ss->face_sets = BKE_sculpt_face_sets_ensure(mesh); + SculptGestureFaceSetOperation *face_set_operation = (SculptGestureFaceSetOperation *) sgcontext->operation; @@ -817,7 +823,7 @@ static void mask_gesture_apply_task_cb(void *__restrict userdata, BKE_pbvh_vertex_iter_begin (sgcontext->ss->pbvh, node, vd, PBVH_ITER_UNIQUE) { if (sculpt_gesture_is_vertex_effected(sgcontext, &vd)) { - float prevmask = *vd.mask; + float prevmask = vd.mask ? *vd.mask : 0.0f; if (!any_masked) { any_masked = true; @@ -863,6 +869,10 @@ static void sculpt_gesture_init_mask_properties(SculptGestureContext *sgcontext, SculptGestureMaskOperation *mask_operation = (SculptGestureMaskOperation *)sgcontext->operation; + Object *object = sgcontext->vc.obact; + MultiresModifierData *mmd = BKE_sculpt_multires_active(sgcontext->vc.scene, object); + BKE_sculpt_mask_layers_ensure(sgcontext->vc.obact, mmd); + mask_operation->op.sculpt_gesture_begin = sculpt_gesture_mask_begin; mask_operation->op.sculpt_gesture_apply_for_symmetry_pass = sculpt_gesture_mask_apply_for_symmetry_pass; @@ -1123,6 +1133,7 @@ static void sculpt_gesture_trim_geometry_generate(SculptGestureContext *sgcontex const float(*ob_imat)[4] = vc->obact->imat; /* Write vertices coordinates for the front face. */ + MVert *verts = BKE_mesh_verts_for_write(trim_operation->mesh); float depth_point[3]; madd_v3_v3v3fl(depth_point, shape_origin, shape_normal, depth_front); for (int i = 0; i < tot_screen_points; i++) { @@ -1134,7 +1145,7 @@ static void sculpt_gesture_trim_geometry_generate(SculptGestureContext *sgcontex ED_view3d_win_to_3d_on_plane(region, shape_plane, screen_points[i], false, new_point); madd_v3_v3fl(new_point, shape_normal, depth_front); } - mul_v3_m4v3(trim_operation->mesh->mvert[i].co, ob_imat, new_point); + mul_v3_m4v3(verts[i].co, ob_imat, new_point); mul_v3_m4v3(trim_operation->true_mesh_co[i], ob_imat, new_point); } @@ -1149,7 +1160,7 @@ static void sculpt_gesture_trim_geometry_generate(SculptGestureContext *sgcontex ED_view3d_win_to_3d_on_plane(region, shape_plane, screen_points[i], false, new_point); madd_v3_v3fl(new_point, shape_normal, depth_back); } - mul_v3_m4v3(trim_operation->mesh->mvert[i + tot_screen_points].co, ob_imat, new_point); + mul_v3_m4v3(verts[i + tot_screen_points].co, ob_imat, new_point); mul_v3_m4v3(trim_operation->true_mesh_co[i + tot_screen_points], ob_imat, new_point); } @@ -1159,10 +1170,12 @@ static void sculpt_gesture_trim_geometry_generate(SculptGestureContext *sgcontex BLI_polyfill_calc(screen_points, tot_screen_points, 0, r_tris); /* Write the front face triangle indices. */ - MPoly *mp = trim_operation->mesh->mpoly; - MLoop *ml = trim_operation->mesh->mloop; + MPoly *polys = BKE_mesh_polys_for_write(trim_operation->mesh); + MLoop *loops = BKE_mesh_loops_for_write(trim_operation->mesh); + MPoly *mp = polys; + MLoop *ml = loops; for (int i = 0; i < tot_tris_face; i++, mp++, ml += 3) { - mp->loopstart = (int)(ml - trim_operation->mesh->mloop); + mp->loopstart = (int)(ml - loops); mp->totloop = 3; ml[0].v = r_tris[i][0]; ml[1].v = r_tris[i][1]; @@ -1171,7 +1184,7 @@ static void sculpt_gesture_trim_geometry_generate(SculptGestureContext *sgcontex /* Write the back face triangle indices. */ for (int i = 0; i < tot_tris_face; i++, mp++, ml += 3) { - mp->loopstart = (int)(ml - trim_operation->mesh->mloop); + mp->loopstart = (int)(ml - loops); mp->totloop = 3; ml[0].v = r_tris[i][0] + tot_screen_points; ml[1].v = r_tris[i][1] + tot_screen_points; @@ -1182,7 +1195,7 @@ static void sculpt_gesture_trim_geometry_generate(SculptGestureContext *sgcontex /* Write the indices for the lateral triangles. */ for (int i = 0; i < tot_screen_points; i++, mp++, ml += 3) { - mp->loopstart = (int)(ml - trim_operation->mesh->mloop); + mp->loopstart = (int)(ml - loops); mp->totloop = 3; int current_index = i; int next_index = current_index + 1; @@ -1195,7 +1208,7 @@ static void sculpt_gesture_trim_geometry_generate(SculptGestureContext *sgcontex } for (int i = 0; i < tot_screen_points; i++, mp++, ml += 3) { - mp->loopstart = (int)(ml - trim_operation->mesh->mloop); + mp->loopstart = (int)(ml - loops); mp->totloop = 3; int current_index = i; int next_index = current_index + 1; @@ -1312,8 +1325,7 @@ static void sculpt_gesture_apply_trim(SculptGestureContext *sgcontext) }), sculpt_mesh); BM_mesh_free(bm); - BKE_mesh_nomain_to_mesh( - result, sgcontext->vc.obact->data, sgcontext->vc.obact, &CD_MASK_MESH, true); + BKE_mesh_nomain_to_mesh(result, sgcontext->vc.obact->data, sgcontext->vc.obact); } static void sculpt_gesture_trim_begin(bContext *C, SculptGestureContext *sgcontext) @@ -1330,8 +1342,9 @@ static void sculpt_gesture_trim_apply_for_symmetry_pass(bContext *UNUSED(C), { SculptGestureTrimOperation *trim_operation = (SculptGestureTrimOperation *)sgcontext->operation; Mesh *trim_mesh = trim_operation->mesh; + MVert *verts = BKE_mesh_verts_for_write(trim_mesh); for (int i = 0; i < trim_mesh->totvert; i++) { - flip_v3_v3(trim_mesh->mvert[i].co, trim_operation->true_mesh_co[i], sgcontext->symmpass); + flip_v3_v3(verts[i].co, trim_operation->true_mesh_co[i], sgcontext->symmpass); } sculpt_gesture_trim_normals_update(sgcontext); sculpt_gesture_apply_trim(sgcontext); @@ -1341,7 +1354,9 @@ static void sculpt_gesture_trim_end(bContext *UNUSED(C), SculptGestureContext *s { Object *object = sgcontext->vc.obact; SculptSession *ss = object->sculpt; - ss->face_sets = CustomData_get_layer(&((Mesh *)object->data)->pdata, CD_SCULPT_FACE_SETS); + + ss->face_sets = CustomData_get_layer_named( + &((Mesh *)object->data)->pdata, CD_PROP_INT32, ".sculpt_face_set"); if (ss->face_sets) { /* Assign a new Face Set ID to the new faces created by the trim operation. */ const int next_face_set_id = ED_sculpt_face_sets_find_next_available_id(object->data); @@ -1502,7 +1517,7 @@ static int paint_mask_gesture_box_exec(bContext *C, wmOperator *op) return OPERATOR_CANCELLED; } sculpt_gesture_init_mask_properties(sgcontext, op); - sculpt_gesture_apply(C, sgcontext); + sculpt_gesture_apply(C, sgcontext, op); sculpt_gesture_context_free(sgcontext); return OPERATOR_FINISHED; } @@ -1514,7 +1529,7 @@ static int paint_mask_gesture_lasso_exec(bContext *C, wmOperator *op) return OPERATOR_CANCELLED; } sculpt_gesture_init_mask_properties(sgcontext, op); - sculpt_gesture_apply(C, sgcontext); + sculpt_gesture_apply(C, sgcontext, op); sculpt_gesture_context_free(sgcontext); return OPERATOR_FINISHED; } @@ -1526,7 +1541,7 @@ static int paint_mask_gesture_line_exec(bContext *C, wmOperator *op) return OPERATOR_CANCELLED; } sculpt_gesture_init_mask_properties(sgcontext, op); - sculpt_gesture_apply(C, sgcontext); + sculpt_gesture_apply(C, sgcontext, op); sculpt_gesture_context_free(sgcontext); return OPERATOR_FINISHED; } @@ -1538,7 +1553,7 @@ static int face_set_gesture_box_exec(bContext *C, wmOperator *op) return OPERATOR_CANCELLED; } sculpt_gesture_init_face_set_properties(sgcontext, op); - sculpt_gesture_apply(C, sgcontext); + sculpt_gesture_apply(C, sgcontext, op); sculpt_gesture_context_free(sgcontext); return OPERATOR_FINISHED; } @@ -1550,7 +1565,7 @@ static int face_set_gesture_lasso_exec(bContext *C, wmOperator *op) return OPERATOR_CANCELLED; } sculpt_gesture_init_face_set_properties(sgcontext, op); - sculpt_gesture_apply(C, sgcontext); + sculpt_gesture_apply(C, sgcontext, op); sculpt_gesture_context_free(sgcontext); return OPERATOR_FINISHED; } @@ -1575,7 +1590,7 @@ static int sculpt_trim_gesture_box_exec(bContext *C, wmOperator *op) } sculpt_gesture_init_trim_properties(sgcontext, op); - sculpt_gesture_apply(C, sgcontext); + sculpt_gesture_apply(C, sgcontext, op); sculpt_gesture_context_free(sgcontext); return OPERATOR_FINISHED; } @@ -1616,7 +1631,7 @@ static int sculpt_trim_gesture_lasso_exec(bContext *C, wmOperator *op) return OPERATOR_CANCELLED; } sculpt_gesture_init_trim_properties(sgcontext, op); - sculpt_gesture_apply(C, sgcontext); + sculpt_gesture_apply(C, sgcontext, op); sculpt_gesture_context_free(sgcontext); return OPERATOR_FINISHED; } @@ -1645,7 +1660,7 @@ static int project_gesture_line_exec(bContext *C, wmOperator *op) return OPERATOR_CANCELLED; } sculpt_gesture_init_project_properties(sgcontext, op); - sculpt_gesture_apply(C, sgcontext); + sculpt_gesture_apply(C, sgcontext, op); sculpt_gesture_context_free(sgcontext); return OPERATOR_FINISHED; } diff --git a/source/blender/editors/sculpt_paint/paint_ops.c b/source/blender/editors/sculpt_paint/paint_ops.c index 994ae4011b4..b78c60e7964 100644 --- a/source/blender/editors/sculpt_paint/paint_ops.c +++ b/source/blender/editors/sculpt_paint/paint_ops.c @@ -361,7 +361,6 @@ static int palette_color_add_exec(bContext *C, wmOperator *UNUSED(op)) { Scene *scene = CTX_data_scene(C); Paint *paint = BKE_paint_get_active_from_context(C); - Brush *brush = paint->brush; ePaintMode mode = BKE_paintmode_get_active_from_context(C); Palette *palette = paint->palette; PaletteColor *color; @@ -369,17 +368,20 @@ static int palette_color_add_exec(bContext *C, wmOperator *UNUSED(op)) color = BKE_palette_color_add(palette); palette->active_color = BLI_listbase_count(&palette->colors) - 1; - if (ELEM(mode, - PAINT_MODE_TEXTURE_3D, - PAINT_MODE_TEXTURE_2D, - PAINT_MODE_VERTEX, - PAINT_MODE_SCULPT)) { - copy_v3_v3(color->rgb, BKE_brush_color_get(scene, brush)); - color->value = 0.0; - } - else if (mode == PAINT_MODE_WEIGHT) { - zero_v3(color->rgb); - color->value = brush->weight; + if (paint->brush) { + const Brush *brush = paint->brush; + if (ELEM(mode, + PAINT_MODE_TEXTURE_3D, + PAINT_MODE_TEXTURE_2D, + PAINT_MODE_VERTEX, + PAINT_MODE_SCULPT)) { + copy_v3_v3(color->rgb, BKE_brush_color_get(scene, brush)); + color->value = 0.0; + } + else if (mode == PAINT_MODE_WEIGHT) { + zero_v3(color->rgb); + color->value = brush->weight; + } } return OPERATOR_FINISHED; diff --git a/source/blender/editors/sculpt_paint/paint_stroke.c b/source/blender/editors/sculpt_paint/paint_stroke.c index 97fa2b936e0..73d52febfc6 100644 --- a/source/blender/editors/sculpt_paint/paint_stroke.c +++ b/source/blender/editors/sculpt_paint/paint_stroke.c @@ -140,7 +140,7 @@ static void paint_draw_smooth_cursor(bContext *C, int x, int y, void *customdata ARegion *region = stroke->vc.region; uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); - immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); immUniformColor4ubv(paint->paint_cursor_col); immBegin(GPU_PRIM_LINES, 2); @@ -168,7 +168,7 @@ static void paint_draw_line_cursor(bContext *C, int x, int y, void *customdata) uint shdr_pos = GPU_vertformat_attr_add( immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); - immBindBuiltinProgram(GPU_SHADER_2D_LINE_DASHED_UNIFORM_COLOR); + immBindBuiltinProgram(GPU_SHADER_3D_LINE_DASHED_UNIFORM_COLOR); float viewport_size[4]; GPU_viewport_size_get_f(viewport_size); @@ -1140,7 +1140,7 @@ struct wmKeyMap *paint_stroke_modal_keymap(struct wmKeyConfig *keyconf) struct wmKeyMap *keymap = WM_modalkeymap_find(keyconf, name); - /* this function is called for each spacetype, only needs to add map once */ + /* This function is called for each space-type, only needs to add map once. */ if (!keymap) { keymap = WM_modalkeymap_ensure(keyconf, name, modal_items); } diff --git a/source/blender/editors/sculpt_paint/paint_utils.c b/source/blender/editors/sculpt_paint/paint_utils.c index 1f272882100..cb981a3bfb1 100644 --- a/source/blender/editors/sculpt_paint/paint_utils.c +++ b/source/blender/editors/sculpt_paint/paint_utils.c @@ -28,7 +28,9 @@ #include "BKE_context.h" #include "BKE_customdata.h" #include "BKE_image.h" +#include "BKE_layer.h" #include "BKE_material.h" +#include "BKE_mesh.h" #include "BKE_mesh_runtime.h" #include "BKE_paint.h" #include "BKE_report.h" @@ -286,9 +288,8 @@ static void imapaint_pick_uv( const MLoopTri *lt = BKE_mesh_runtime_looptri_ensure(me_eval); const int tottri = me_eval->runtime.looptris.len; - const MVert *mvert = me_eval->mvert; - const MPoly *mpoly = me_eval->mpoly; - const MLoop *mloop = me_eval->mloop; + const MVert *mvert = BKE_mesh_verts(me_eval); + const MLoop *mloop = BKE_mesh_loops(me_eval); const int *index_mp_to_orig = CustomData_get_layer(&me_eval->pdata, CD_ORIGINDEX); /* get the needed opengl matrices */ @@ -302,6 +303,9 @@ static void imapaint_pick_uv( minabsw = 1e10; uv[0] = uv[1] = 0.0; + const int *material_indices = (const int *)CustomData_get_layer_named( + &me_eval->pdata, CD_PROP_INT32, "material_index"); + /* test all faces in the derivedmesh with the original index of the picked face */ /* face means poly here, not triangle, indeed */ for (i = 0; i < tottri; i++, lt++) { @@ -309,7 +313,6 @@ static void imapaint_pick_uv( if (findex == faceindex) { const MLoopUV *mloopuv; - const MPoly *mp = &mpoly[lt->poly]; const MLoopUV *tri_uv[3]; float tri_co[3][3]; @@ -321,7 +324,8 @@ static void imapaint_pick_uv( const Material *ma; const TexPaintSlot *slot; - ma = BKE_object_material_get(ob_eval, mp->mat_nr + 1); + ma = BKE_object_material_get( + ob_eval, material_indices == NULL ? 1 : material_indices[lt->poly] + 1); slot = &ma->texpaintslot[ma->paint_active_slot]; if (!(slot && slot->uvname && @@ -400,7 +404,8 @@ void paint_sample_color( if (v3d && texpaint_proj) { /* first try getting a color directly from the mesh faces if possible */ ViewLayer *view_layer = CTX_data_view_layer(C); - Object *ob = OBACT(view_layer); + BKE_view_layer_synced_ensure(scene, view_layer); + Object *ob = BKE_view_layer_active_object_get(view_layer); Object *ob_eval = DEG_get_evaluated_object(depsgraph, ob); ImagePaintSettings *imapaint = &scene->toolsettings->imapaint; bool use_material = (imapaint->mode == IMAGEPAINT_MODE_MATERIAL); @@ -410,6 +415,8 @@ void paint_sample_color( cddata_masks.pmask |= CD_MASK_ORIGINDEX; Mesh *me = (Mesh *)ob->data; Mesh *me_eval = mesh_get_eval_final(depsgraph, scene, ob_eval, &cddata_masks); + const int *material_indices = (const int *)CustomData_get_layer_named( + &me_eval->pdata, CD_PROP_INT32, "material_index"); ViewContext vc; const int mval[2] = {x, y}; @@ -427,8 +434,8 @@ void paint_sample_color( if (use_material) { /* Image and texture interpolation from material. */ - MPoly *mp = me_eval->mpoly + faceindex; - Material *ma = BKE_object_material_get(ob_eval, mp->mat_nr + 1); + Material *ma = BKE_object_material_get( + ob_eval, material_indices ? material_indices[faceindex] + 1 : 1); /* Force refresh since paint slots are not updated when changing interpolation. */ BKE_texpaint_slot_refresh_cache(scene, ma, ob); @@ -697,7 +704,7 @@ static int vert_select_ungrouped_exec(bContext *C, wmOperator *op) Object *ob = CTX_data_active_object(C); Mesh *me = ob->data; - if (BLI_listbase_is_empty(&me->vertex_group_names) || (me->dvert == NULL)) { + if (BLI_listbase_is_empty(&me->vertex_group_names) || (BKE_mesh_deform_verts(me) == NULL)) { BKE_report(op->reports, RPT_ERROR, "No weights/vertex groups on object"); return OPERATOR_CANCELLED; } diff --git a/source/blender/editors/sculpt_paint/paint_vertex.cc b/source/blender/editors/sculpt_paint/paint_vertex.cc index 6dc8375bb0d..9abc3c5112e 100644 --- a/source/blender/editors/sculpt_paint/paint_vertex.cc +++ b/source/blender/editors/sculpt_paint/paint_vertex.cc @@ -32,6 +32,7 @@ #include "RNA_prototypes.h" #include "BKE_attribute.h" +#include "BKE_attribute.hh" #include "BKE_brush.h" #include "BKE_colortools.h" #include "BKE_context.h" @@ -773,6 +774,8 @@ struct WeightPaintGroupData { * paint stroke update - campbell */ struct WeightPaintInfo { + MutableSpan<MDeformVert> dvert; + int defbase_tot; /* both must add up to 'defbase_tot' */ @@ -815,7 +818,7 @@ static void do_weight_paint_vertex_single( float paintweight) { Mesh *me = (Mesh *)ob->data; - MDeformVert *dv = &me->dvert[index]; + MDeformVert *dv = &wpi->dvert[index]; bool topology = (me->editflag & ME_EDIT_MIRROR_TOPO) != 0; MDeformWeight *dw; @@ -875,7 +878,7 @@ static void do_weight_paint_vertex_single( /* get the mirror def vars */ if (index_mirr != -1) { - dv_mirr = &me->dvert[index_mirr]; + dv_mirr = &wpi->dvert[index_mirr]; if (wp->flag & VP_FLAG_VGROUP_RESTRICT) { dw_mirr = BKE_defvert_find_index(dv_mirr, vgroup_mirr); @@ -915,9 +918,9 @@ static void do_weight_paint_vertex_single( if (!brush_use_accumulate(wp)) { MDeformVert *dvert_prev = ob->sculpt->mode.wpaint.dvert_prev; - MDeformVert *dv_prev = defweight_prev_init(dvert_prev, me->dvert, index); + MDeformVert *dv_prev = defweight_prev_init(dvert_prev, wpi->dvert.data(), index); if (index_mirr != -1) { - defweight_prev_init(dvert_prev, me->dvert, index_mirr); + defweight_prev_init(dvert_prev, wpi->dvert.data(), index_mirr); } weight_prev = BKE_defvert_find_weight(dv_prev, wpi->active.index); @@ -1028,7 +1031,7 @@ static void do_weight_paint_vertex_multi( float paintweight) { Mesh *me = (Mesh *)ob->data; - MDeformVert *dv = &me->dvert[index]; + MDeformVert *dv = &wpi->dvert[index]; bool topology = (me->editflag & ME_EDIT_MIRROR_TOPO) != 0; /* mirror vars */ @@ -1044,7 +1047,7 @@ static void do_weight_paint_vertex_multi( index_mirr = mesh_get_x_mirror_vert(ob, nullptr, index, topology); if (!ELEM(index_mirr, -1, index)) { - dv_mirr = &me->dvert[index_mirr]; + dv_mirr = &wpi->dvert[index_mirr]; } else { index_mirr = -1; @@ -1071,9 +1074,9 @@ static void do_weight_paint_vertex_multi( if (!brush_use_accumulate(wp)) { MDeformVert *dvert_prev = ob->sculpt->mode.wpaint.dvert_prev; - MDeformVert *dv_prev = defweight_prev_init(dvert_prev, me->dvert, index); + MDeformVert *dv_prev = defweight_prev_init(dvert_prev, wpi->dvert.data(), index); if (index_mirr != -1) { - defweight_prev_init(dvert_prev, me->dvert, index_mirr); + defweight_prev_init(dvert_prev, wpi->dvert.data(), index_mirr); } oldw = BKE_defvert_multipaint_collective_weight( @@ -1235,6 +1238,8 @@ static void vertex_paint_init_session_data(const ToolSettings *ts, Object *ob) } Mesh *me = (Mesh *)ob->data; + const Span<MPoly> polys = me->polys(); + const Span<MLoop> loops = me->loops(); if (gmap->vert_to_loop == nullptr) { gmap->vert_map_mem = nullptr; @@ -1243,15 +1248,15 @@ static void vertex_paint_init_session_data(const ToolSettings *ts, Object *ob) gmap->vert_to_poly = nullptr; BKE_mesh_vert_loop_map_create(&gmap->vert_to_loop, &gmap->vert_map_mem, - me->mpoly, - me->mloop, + polys.data(), + loops.data(), me->totvert, me->totpoly, me->totloop); BKE_mesh_vert_poly_map_create(&gmap->vert_to_poly, &gmap->poly_map_mem, - me->mpoly, - me->mloop, + polys.data(), + loops.data(), me->totvert, me->totpoly, me->totloop); @@ -1900,7 +1905,7 @@ static void do_wpaint_precompute_weight_cb_ex(void *__restrict userdata, const TaskParallelTLS *__restrict UNUSED(tls)) { SculptThreadedTaskData *data = (SculptThreadedTaskData *)userdata; - const MDeformVert *dv = &data->me->dvert[n]; + const MDeformVert *dv = &data->wpi->dvert[n]; data->wpd->precomputed_weight[n] = wpaint_get_active_weight(dv, data->wpi); } @@ -1954,6 +1959,10 @@ static void do_wpaint_brush_blur_task_cb_ex(void *__restrict userdata, const float *sculpt_normal_frontface = SCULPT_brush_frontface_normal_from_falloff_shape( ss, data->brush->falloff_shape); + const blender::bke::AttributeAccessor attributes = data->me->attributes(); + const blender::VArray<bool> select_vert = attributes.lookup_or_default<bool>( + ".select_vert", ATTR_DOMAIN_POINT, false); + /* For each vertex */ PBVHVertexIter vd; BKE_pbvh_vertex_iter_begin (ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) { @@ -1961,23 +1970,21 @@ static void do_wpaint_brush_blur_task_cb_ex(void *__restrict userdata, if (sculpt_brush_test_sq_fn(&test, vd.co)) { /* For grid based pbvh, take the vert whose loop corresponds to the current grid. * Otherwise, take the current vert. */ - const int v_index = has_grids ? data->me->mloop[vd.grid_indices[vd.g]].v : - vd.vert_indices[vd.i]; + const int v_index = has_grids ? ss->mloop[vd.grid_indices[vd.g]].v : vd.vert_indices[vd.i]; const float grid_alpha = has_grids ? 1.0f / vd.gridsize : 1.0f; - const char v_flag = data->me->mvert[v_index].flag; /* If the vertex is selected */ - if (!(use_face_sel || use_vert_sel) || v_flag & SELECT) { + if (!(use_face_sel || use_vert_sel) || select_vert[v_index]) { /* Get the average poly weight */ int total_hit_loops = 0; float weight_final = 0.0f; for (int j = 0; j < gmap->vert_to_poly[v_index].count; j++) { const int p_index = gmap->vert_to_poly[v_index].indices[j]; - const MPoly *mp = &data->me->mpoly[p_index]; + const MPoly *mp = &ss->mpoly[p_index]; total_hit_loops += mp->totloop; for (int k = 0; k < mp->totloop; k++) { const int l_index = mp->loopstart + k; - const MLoop *ml = &data->me->mloop[l_index]; + const MLoop *ml = &ss->mloop[l_index]; weight_final += data->wpd->precomputed_weight[ml->v]; } } @@ -2042,6 +2049,10 @@ static void do_wpaint_brush_smear_task_cb_ex(void *__restrict userdata, sub_v3_v3v3(brush_dir, cache->location, cache->last_location); project_plane_v3_v3v3(brush_dir, brush_dir, cache->view_normal); + const blender::bke::AttributeAccessor attributes = data->me->attributes(); + const blender::VArray<bool> select_vert = attributes.lookup_or_default<bool>( + ".select_vert", ATTR_DOMAIN_POINT, false); + if (cache->is_last_valid && (normalize_v3(brush_dir) != 0.0f)) { SculptBrushTest test; @@ -2057,13 +2068,12 @@ static void do_wpaint_brush_smear_task_cb_ex(void *__restrict userdata, if (sculpt_brush_test_sq_fn(&test, vd.co)) { /* For grid based pbvh, take the vert whose loop corresponds to the current grid. * Otherwise, take the current vert. */ - const int v_index = has_grids ? data->me->mloop[vd.grid_indices[vd.g]].v : - vd.vert_indices[vd.i]; + const int v_index = has_grids ? ss->mloop[vd.grid_indices[vd.g]].v : vd.vert_indices[vd.i]; const float grid_alpha = has_grids ? 1.0f / vd.gridsize : 1.0f; - const MVert *mv_curr = &data->me->mvert[v_index]; + const MVert *mv_curr = &ss->mvert[v_index]; /* If the vertex is selected */ - if (!(use_face_sel || use_vert_sel) || mv_curr->flag & SELECT) { + if (!(use_face_sel || use_vert_sel) || select_vert[v_index]) { float brush_strength = cache->bstrength; const float angle_cos = (use_normal && vd.no) ? dot_v3v3(sculpt_normal_frontface, vd.no) : @@ -2082,12 +2092,12 @@ static void do_wpaint_brush_smear_task_cb_ex(void *__restrict userdata, float weight_final = 0.0; for (int j = 0; j < gmap->vert_to_poly[v_index].count; j++) { const int p_index = gmap->vert_to_poly[v_index].indices[j]; - const MPoly *mp = &data->me->mpoly[p_index]; - const MLoop *ml_other = &data->me->mloop[mp->loopstart]; + const MPoly *mp = &ss->mpoly[p_index]; + const MLoop *ml_other = &ss->mloop[mp->loopstart]; for (int k = 0; k < mp->totloop; k++, ml_other++) { const uint v_other_index = ml_other->v; if (v_other_index != v_index) { - const MVert *mv_other = &data->me->mvert[v_other_index]; + const MVert *mv_other = &ss->mvert[v_other_index]; /* Get the direction from the selected vert to the neighbor. */ float other_dir[3]; @@ -2156,6 +2166,10 @@ static void do_wpaint_brush_draw_task_cb_ex(void *__restrict userdata, const float *sculpt_normal_frontface = SCULPT_brush_frontface_normal_from_falloff_shape( ss, data->brush->falloff_shape); + const blender::bke::AttributeAccessor attributes = data->me->attributes(); + const blender::VArray<bool> select_vert = attributes.lookup_or_default<bool>( + ".select_vert", ATTR_DOMAIN_POINT, false); + /* For each vertex */ PBVHVertexIter vd; BKE_pbvh_vertex_iter_begin (ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) { @@ -2164,13 +2178,11 @@ static void do_wpaint_brush_draw_task_cb_ex(void *__restrict userdata, /* NOTE: grids are 1:1 with corners (aka loops). * For multires, take the vert whose loop corresponds to the current grid. * Otherwise, take the current vert. */ - const int v_index = has_grids ? data->me->mloop[vd.grid_indices[vd.g]].v : - vd.vert_indices[vd.i]; + const int v_index = has_grids ? ss->mloop[vd.grid_indices[vd.g]].v : vd.vert_indices[vd.i]; const float grid_alpha = has_grids ? 1.0f / vd.gridsize : 1.0f; - const char v_flag = data->me->mvert[v_index].flag; /* If the vertex is selected */ - if (!(use_face_sel || use_vert_sel) || v_flag & SELECT) { + if (!(use_face_sel || use_vert_sel) || select_vert[v_index]) { float brush_strength = cache->bstrength; const float angle_cos = (use_normal && vd.no) ? dot_v3v3(sculpt_normal_frontface, vd.no) : 1.0f; @@ -2223,6 +2235,10 @@ static void do_wpaint_brush_calc_average_weight_cb_ex( const float *sculpt_normal_frontface = SCULPT_brush_frontface_normal_from_falloff_shape( ss, data->brush->falloff_shape); + const blender::bke::AttributeAccessor attributes = data->me->attributes(); + const blender::VArray<bool> select_vert = attributes.lookup_or_default<bool>( + ".select_vert", ATTR_DOMAIN_POINT, false); + /* For each vertex */ PBVHVertexIter vd; BKE_pbvh_vertex_iter_begin (ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) { @@ -2232,13 +2248,11 @@ static void do_wpaint_brush_calc_average_weight_cb_ex( 1.0f; if (angle_cos > 0.0 && BKE_brush_curve_strength(data->brush, sqrtf(test.dist), cache->radius) > 0.0) { - const int v_index = has_grids ? data->me->mloop[vd.grid_indices[vd.g]].v : - vd.vert_indices[vd.i]; - const char v_flag = data->me->mvert[v_index].flag; + const int v_index = has_grids ? ss->mloop[vd.grid_indices[vd.g]].v : vd.vert_indices[vd.i]; /* If the vertex is selected. */ - if (!(use_face_sel || use_vert_sel) || v_flag & SELECT) { - const MDeformVert *dv = &data->me->dvert[v_index]; + if (!(use_face_sel || use_vert_sel) || select_vert[v_index]) { + const MDeformVert *dv = &data->wpi->dvert[v_index]; accum->len += 1; accum->value += wpaint_get_active_weight(dv, data->wpi); } @@ -2510,7 +2524,11 @@ static void wpaint_stroke_update_step(bContext *C, /* load projection matrix */ mul_m4_m4m4(mat, vc->rv3d->persmat, ob->obmat); + Mesh *mesh = static_cast<Mesh *>(ob->data); + /* *** setup WeightPaintInfo - pass onto do_weight_paint_vertex *** */ + wpi.dvert = mesh->deform_verts_for_write(); + wpi.defbase_tot = wpd->defbase_tot; wpi.defbase_sel = wpd->defbase_sel; wpi.defbase_tot_sel = wpd->defbase_tot_sel; @@ -2532,7 +2550,7 @@ static void wpaint_stroke_update_step(bContext *C, /* *** done setting up WeightPaintInfo *** */ if (wpd->precomputed_weight) { - precompute_weight_values(C, ob, brush, wpd, &wpi, (Mesh *)ob->data); + precompute_weight_values(C, ob, brush, wpd, &wpi, mesh); } wpaint_do_symmetrical_brush_actions(C, ob, wp, sd, wpd, &wpi); @@ -2545,9 +2563,9 @@ static void wpaint_stroke_update_step(bContext *C, mul_v3_m4v3(loc_world, ob->obmat, ss->cache->true_location); paint_last_stroke_update(scene, loc_world); - BKE_mesh_batch_cache_dirty_tag((Mesh *)ob->data, BKE_MESH_BATCH_DIRTY_ALL); + BKE_mesh_batch_cache_dirty_tag(mesh, BKE_MESH_BATCH_DIRTY_ALL); - DEG_id_tag_update((ID *)ob->data, 0); + DEG_id_tag_update(&mesh->id, 0); WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob); swap_m4m4(wpd->vc.rv3d->persmat, mat); @@ -2952,6 +2970,11 @@ static void do_vpaint_brush_blur_loops(bContext *C, Color *previous_color = static_cast<Color *>(ss->cache->prev_colors_vpaint); + const blender::VArray<bool> select_vert = me->attributes().lookup_or_default<bool>( + ".select_vert", ATTR_DOMAIN_POINT, false); + const blender::VArray<bool> select_poly = me->attributes().lookup_or_default<bool>( + ".select_poly", ATTR_DOMAIN_FACE, false); + blender::threading::parallel_for(IndexRange(totnode), 1LL, [&](IndexRange range) { for (int n : range) { const PBVHType pbvh_type = BKE_pbvh_type(ss->pbvh); @@ -2980,13 +3003,12 @@ static void do_vpaint_brush_blur_loops(bContext *C, if (sculpt_brush_test_sq_fn(&test, vd.co)) { /* For grid based pbvh, take the vert whose loop corresponds to the current grid. * Otherwise, take the current vert. */ - const int v_index = has_grids ? me->mloop[vd.grid_indices[vd.g]].v : + const int v_index = has_grids ? ss->mloop[vd.grid_indices[vd.g]].v : vd.vert_indices[vd.i]; const float grid_alpha = has_grids ? 1.0f / vd.gridsize : 1.0f; - const MVert *mv = &me->mvert[v_index]; /* If the vertex is selected for painting. */ - if (!use_vert_sel || mv->flag & SELECT) { + if (!use_vert_sel || select_vert[v_index]) { float brush_strength = cache->bstrength; const float angle_cos = (use_normal && vd.no) ? dot_v3v3(sculpt_normal_frontface, vd.no) : @@ -3006,8 +3028,8 @@ static void do_vpaint_brush_blur_loops(bContext *C, for (int j = 0; j < gmap->vert_to_poly[v_index].count; j++) { int p_index = gmap->vert_to_poly[v_index].indices[j]; - const MPoly *mp = &me->mpoly[p_index]; - if (!use_face_sel || mp->flag & ME_FACE_SEL) { + const MPoly *mp = &ss->mpoly[p_index]; + if (!use_face_sel || select_poly[p_index]) { total_hit_loops += mp->totloop; for (int k = 0; k < mp->totloop; k++) { const uint l_index = mp->loopstart + k; @@ -3040,9 +3062,8 @@ static void do_vpaint_brush_blur_loops(bContext *C, for (int j = 0; j < gmap->vert_to_poly[v_index].count; j++) { const int p_index = gmap->vert_to_poly[v_index].indices[j]; const int l_index = gmap->vert_to_loop[v_index].indices[j]; - BLI_assert(me->mloop[l_index].v == v_index); - const MPoly *mp = &me->mpoly[p_index]; - if (!use_face_sel || mp->flag & ME_FACE_SEL) { + BLI_assert(ss->mloop[l_index].v == v_index); + if (!use_face_sel || select_poly[p_index]) { Color color_orig(0, 0, 0, 0); /* unused when array is nullptr */ if (previous_color != nullptr) { @@ -3094,6 +3115,11 @@ static void do_vpaint_brush_blur_verts(bContext *C, Color *previous_color = static_cast<Color *>(ss->cache->prev_colors_vpaint); + const blender::VArray<bool> select_vert = me->attributes().lookup_or_default<bool>( + ".select_vert", ATTR_DOMAIN_POINT, false); + const blender::VArray<bool> select_poly = me->attributes().lookup_or_default<bool>( + ".select_poly", ATTR_DOMAIN_FACE, false); + blender::threading::parallel_for(IndexRange(totnode), 1LL, [&](IndexRange range) { for (int n : range) { const PBVHType pbvh_type = BKE_pbvh_type(ss->pbvh); @@ -3122,13 +3148,12 @@ static void do_vpaint_brush_blur_verts(bContext *C, if (sculpt_brush_test_sq_fn(&test, vd.co)) { /* For grid based pbvh, take the vert whose loop corresponds to the current grid. * Otherwise, take the current vert. */ - const int v_index = has_grids ? me->mloop[vd.grid_indices[vd.g]].v : + const int v_index = has_grids ? ss->mloop[vd.grid_indices[vd.g]].v : vd.vert_indices[vd.i]; const float grid_alpha = has_grids ? 1.0f / vd.gridsize : 1.0f; - const MVert *mv = &me->mvert[v_index]; /* If the vertex is selected for painting. */ - if (!use_vert_sel || mv->flag & SELECT) { + if (!use_vert_sel || select_vert[v_index]) { float brush_strength = cache->bstrength; const float angle_cos = (use_normal && vd.no) ? dot_v3v3(sculpt_normal_frontface, vd.no) : @@ -3148,12 +3173,12 @@ static void do_vpaint_brush_blur_verts(bContext *C, for (int j = 0; j < gmap->vert_to_poly[v_index].count; j++) { int p_index = gmap->vert_to_poly[v_index].indices[j]; - const MPoly *mp = &me->mpoly[p_index]; - if (!use_face_sel || mp->flag & ME_FACE_SEL) { + const MPoly *mp = &ss->mpoly[p_index]; + if (!use_face_sel || select_poly[p_index]) { total_hit_loops += mp->totloop; for (int k = 0; k < mp->totloop; k++) { const uint l_index = mp->loopstart + k; - const uint v_index = me->mloop[l_index].v; + const uint v_index = ss->mloop[l_index].v; Color *col = lcol + v_index; @@ -3184,10 +3209,9 @@ static void do_vpaint_brush_blur_verts(bContext *C, for (int j = 0; j < gmap->vert_to_poly[v_index].count; j++) { const int p_index = gmap->vert_to_poly[v_index].indices[j]; - BLI_assert(me->mloop[gmap->vert_to_loop[v_index].indices[j]].v == v_index); + BLI_assert(ss->mloop[gmap->vert_to_loop[v_index].indices[j]].v == v_index); - const MPoly *mp = &me->mpoly[p_index]; - if (!use_face_sel || mp->flag & ME_FACE_SEL) { + if (!use_face_sel || select_poly[p_index]) { Color color_orig(0, 0, 0, 0); /* unused when array is nullptr */ if (previous_color != nullptr) { @@ -3243,6 +3267,11 @@ static void do_vpaint_brush_smear(bContext *C, Color *color_prev_smear = static_cast<Color *>(vpd->smear.color_prev); Color *color_prev = reinterpret_cast<Color *>(ss->cache->prev_colors_vpaint); + const blender::VArray<bool> select_vert = me->attributes().lookup_or_default<bool>( + ".select_vert", ATTR_DOMAIN_POINT, false); + const blender::VArray<bool> select_poly = me->attributes().lookup_or_default<bool>( + ".select_poly", ATTR_DOMAIN_FACE, false); + blender::threading::parallel_for(IndexRange(totnode), 1LL, [&](IndexRange range) { for (int n : range) { float brush_size_pressure, brush_alpha_value, brush_alpha_pressure; @@ -3273,13 +3302,13 @@ static void do_vpaint_brush_smear(bContext *C, if (sculpt_brush_test_sq_fn(&test, vd.co)) { /* For grid based pbvh, take the vert whose loop corresponds to the current grid. * Otherwise, take the current vert. */ - const int v_index = has_grids ? me->mloop[vd.grid_indices[vd.g]].v : + const int v_index = has_grids ? ss->mloop[vd.grid_indices[vd.g]].v : vd.vert_indices[vd.i]; const float grid_alpha = has_grids ? 1.0f / vd.gridsize : 1.0f; - const MVert *mv_curr = &me->mvert[v_index]; + const MVert *mv_curr = &ss->mvert[v_index]; /* if the vertex is selected for painting. */ - if (!use_vert_sel || mv_curr->flag & SELECT) { + if (!use_vert_sel || select_vert[v_index]) { /* Calc the dot prod. between ray norm on surf and current vert * (ie splash prevention factor), and only paint front facing verts. */ float brush_strength = cache->bstrength; @@ -3305,15 +3334,15 @@ static void do_vpaint_brush_smear(bContext *C, for (int j = 0; j < gmap->vert_to_poly[v_index].count; j++) { const int p_index = gmap->vert_to_poly[v_index].indices[j]; const int l_index = gmap->vert_to_loop[v_index].indices[j]; - BLI_assert(me->mloop[l_index].v == v_index); + BLI_assert(ss->mloop[l_index].v == v_index); UNUSED_VARS_NDEBUG(l_index); - const MPoly *mp = &me->mpoly[p_index]; - if (!use_face_sel || mp->flag & ME_FACE_SEL) { - const MLoop *ml_other = &me->mloop[mp->loopstart]; + const MPoly *mp = &ss->mpoly[p_index]; + if (!use_face_sel || select_poly[p_index]) { + const MLoop *ml_other = &ss->mloop[mp->loopstart]; for (int k = 0; k < mp->totloop; k++, ml_other++) { const uint v_other_index = ml_other->v; if (v_other_index != v_index) { - const MVert *mv_other = &me->mvert[v_other_index]; + const MVert *mv_other = &ss->mvert[v_other_index]; /* Get the direction from the * selected vert to the neighbor. */ @@ -3359,11 +3388,10 @@ static void do_vpaint_brush_smear(bContext *C, else { const int l_index = gmap->vert_to_loop[v_index].indices[j]; elem_index = l_index; - BLI_assert(me->mloop[l_index].v == v_index); + BLI_assert(ss->mloop[l_index].v == v_index); } - const MPoly *mp = &me->mpoly[p_index]; - if (!use_face_sel || mp->flag & ME_FACE_SEL) { + if (!use_face_sel || select_poly[p_index]) { /* Get the previous element color */ Color color_orig(0, 0, 0, 0); /* unused when array is nullptr */ @@ -3409,6 +3437,9 @@ static void calculate_average_color(VPaintData<Color, Traits, domain> *vpd, { using Blend = typename Traits::BlendType; + const blender::VArray<bool> select_vert = me->attributes().lookup_or_default<bool>( + ".select_vert", ATTR_DOMAIN_POINT, false); + VPaintAverageAccum<Blend> *accum = (VPaintAverageAccum<Blend> *)MEM_mallocN( sizeof(*accum) * totnode, __func__); blender::threading::parallel_for(IndexRange(totnode), 1LL, [&](IndexRange range) { @@ -3435,12 +3466,11 @@ static void calculate_average_color(VPaintData<Color, Traits, domain> *vpd, BKE_pbvh_vertex_iter_begin (ss->pbvh, nodes[n], vd, PBVH_ITER_UNIQUE) { /* Test to see if the vertex coordinates are within the spherical brush region. */ if (sculpt_brush_test_sq_fn(&test, vd.co)) { - const int v_index = has_grids ? me->mloop[vd.grid_indices[vd.g]].v : + const int v_index = has_grids ? ss->mloop[vd.grid_indices[vd.g]].v : vd.vert_indices[vd.i]; if (BKE_brush_curve_strength(brush, 0.0, cache->radius) > 0.0) { /* If the vertex is selected for painting. */ - const MVert *mv = &me->mvert[v_index]; - if (!use_vert_sel || mv->flag & SELECT) { + if (!use_vert_sel || select_vert[v_index]) { accum2->len += gmap->vert_to_loop[v_index].count; /* if a vertex is within the brush region, then add its color to the blend. */ for (int j = 0; j < gmap->vert_to_loop[v_index].count; j++) { @@ -3525,6 +3555,11 @@ static void vpaint_do_draw(bContext *C, Color *previous_color = static_cast<Color *>(ss->cache->prev_colors_vpaint); + const blender::VArray<bool> select_vert = me->attributes().lookup_or_default<bool>( + ".select_vert", ATTR_DOMAIN_POINT, false); + const blender::VArray<bool> select_poly = me->attributes().lookup_or_default<bool>( + ".select_poly", ATTR_DOMAIN_FACE, false); + blender::threading::parallel_for(IndexRange(totnode), 1LL, [&](IndexRange range) { for (int n : range) { const bool has_grids = (pbvh_type == PBVH_GRIDS); @@ -3555,13 +3590,12 @@ static void vpaint_do_draw(bContext *C, /* NOTE: Grids are 1:1 with corners (aka loops). * For grid based pbvh, take the vert whose loop corresponds to the current grid. * Otherwise, take the current vert. */ - const int v_index = has_grids ? me->mloop[vd.grid_indices[vd.g]].v : + const int v_index = has_grids ? ss->mloop[vd.grid_indices[vd.g]].v : vd.vert_indices[vd.i]; const float grid_alpha = has_grids ? 1.0f / vd.gridsize : 1.0f; - const MVert *mv = &me->mvert[v_index]; /* If the vertex is selected for painting. */ - if (!use_vert_sel || mv->flag & SELECT) { + if (!use_vert_sel || select_vert[v_index]) { /* Calc the dot prod. between ray norm on surf and current vert * (ie splash prevention factor), and only paint front facing verts. */ float brush_strength = cache->bstrength; @@ -3612,9 +3646,8 @@ static void vpaint_do_draw(bContext *C, for (int j = 0; j < gmap->vert_to_poly[v_index].count; j++) { const int p_index = gmap->vert_to_poly[v_index].indices[j]; const int l_index = gmap->vert_to_loop[v_index].indices[j]; - BLI_assert(me->mloop[l_index].v == v_index); - const MPoly *mp = &me->mpoly[p_index]; - if (!use_face_sel || mp->flag & ME_FACE_SEL) { + BLI_assert(ss->mloop[l_index].v == v_index); + if (!use_face_sel || select_poly[p_index]) { Color color_orig = Color(0, 0, 0, 0); /* unused when array is nullptr */ if (previous_color != nullptr) { @@ -3957,7 +3990,7 @@ static int vpaint_invoke(bContext *C, wmOperator *op, const wmEvent *event) BKE_pbvh_ensure_node_loops(ob->sculpt->pbvh); } - SCULPT_undo_push_begin(ob, "Vertex Paint"); + SCULPT_undo_push_begin_ex(ob, "Vertex Paint"); if ((retval = op->type->modal(C, op, event)) == OPERATOR_FINISHED) { paint_stroke_free(C, op, (PaintStroke *)op->customdata); @@ -4041,6 +4074,11 @@ static bool vertex_color_set(Object *ob, ColorPaint4f paintcol_in, CustomDataLay return false; } + const blender::VArray<bool> select_vert = me->attributes().lookup_or_default<bool>( + ".select_vert", ATTR_DOMAIN_POINT, false); + const blender::VArray<bool> select_poly = me->attributes().lookup_or_default<bool>( + ".select_poly", ATTR_DOMAIN_FACE, false); + Color paintcol = fromFloat<Color>(paintcol_in); const bool use_face_sel = (me->editflag & ME_EDIT_PAINT_FACE_SEL) != 0; @@ -4084,27 +4122,29 @@ static bool vertex_color_set(Object *ob, ColorPaint4f paintcol_in, CustomDataLay } else { Color *color_layer = static_cast<Color *>(layer->data); + const Span<MPoly> polys = me->polys(); + const Span<MLoop> loops = me->loops(); - const MPoly *mp = me->mpoly; - for (int i = 0; i < me->totpoly; i++, mp++) { - if (use_face_sel && !(mp->flag & ME_FACE_SEL)) { + for (const int i : polys.index_range()) { + if (use_face_sel && !select_poly[i]) { continue; } + const MPoly &poly = polys[i]; int j = 0; do { - uint vidx = me->mloop[mp->loopstart + j].v; + uint vidx = loops[poly.loopstart + j].v; - if (!(use_vert_sel && !(me->mvert[vidx].flag & SELECT))) { + if (!(use_vert_sel && !(select_vert[vidx]))) { if constexpr (domain == ATTR_DOMAIN_CORNER) { - color_layer[mp->loopstart + j] = paintcol; + color_layer[poly.loopstart + j] = paintcol; } else { color_layer[vidx] = paintcol; } } j++; - } while (j < mp->totloop); + } while (j < poly.totloop); } /* remove stale me->mcol, will be added later */ @@ -4134,7 +4174,7 @@ static bool paint_object_attributes_active_color_fill_ex(Object *ob, if (!layer) { return false; } - /* Store original #Mesh.editflag.*/ + /* Store original #Mesh.editflag. */ const decltype(me->editflag) editflag = me->editflag; if (!only_selected) { me->editflag &= ~ME_EDIT_PAINT_FACE_SEL; diff --git a/source/blender/editors/sculpt_paint/paint_vertex_color_ops.cc b/source/blender/editors/sculpt_paint/paint_vertex_color_ops.cc index 8b726c7b942..a284d1608cb 100644 --- a/source/blender/editors/sculpt_paint/paint_vertex_color_ops.cc +++ b/source/blender/editors/sculpt_paint/paint_vertex_color_ops.cc @@ -50,7 +50,7 @@ static bool vertex_weight_paint_mode_poll(bContext *C) Object *ob = CTX_data_active_object(C); Mesh *me = BKE_mesh_from_object(ob); return (ob && (ELEM(ob->mode, OB_MODE_VERTEX_PAINT, OB_MODE_WEIGHT_PAINT))) && - (me && me->totpoly && me->dvert); + (me && me->totpoly && !me->deform_verts().is_empty()); } static void tag_object_after_update(Object *object) @@ -92,7 +92,7 @@ static bool vertex_paint_from_weight(Object *ob) return false; } - bke::MutableAttributeAccessor attributes = bke::mesh_attributes_for_write(*me); + bke::MutableAttributeAccessor attributes = me->attributes_for_write(); bke::GAttributeWriter color_attribute = attributes.lookup_for_write(active_color_layer->name); if (!color_attribute) { @@ -159,34 +159,24 @@ static IndexMask get_selected_indices(const Mesh &mesh, Vector<int64_t> &indices) { using namespace blender; - Span<MVert> verts(mesh.mvert, mesh.totvert); - Span<MPoly> faces(mesh.mpoly, mesh.totpoly); - - bke::AttributeAccessor attributes = bke::mesh_attributes(mesh); + const bke::AttributeAccessor attributes = mesh.attributes(); if (mesh.editflag & ME_EDIT_PAINT_FACE_SEL) { - const VArray<bool> selection = attributes.adapt_domain( - VArray<bool>::ForFunc(faces.size(), - [&](const int i) { return faces[i].flag & ME_FACE_SEL; }), - ATTR_DOMAIN_FACE, - domain); - + const VArray<bool> selection = attributes.lookup_or_default<bool>( + ".select_poly", ATTR_DOMAIN_FACE, false); return index_mask_ops::find_indices_from_virtual_array( - IndexMask(attributes.domain_size(domain)), selection, 4096, indices); + selection.index_range(), selection, 4096, indices); } if (mesh.editflag & ME_EDIT_PAINT_VERT_SEL) { - const VArray<bool> selection = attributes.adapt_domain( - VArray<bool>::ForFunc(verts.size(), [&](const int i) { return verts[i].flag & SELECT; }), - ATTR_DOMAIN_POINT, - domain); - + const VArray<bool> selection = attributes.lookup_or_default<bool>( + ".select_vert", ATTR_DOMAIN_POINT, false); return index_mask_ops::find_indices_from_virtual_array( - IndexMask(attributes.domain_size(domain)), selection, 4096, indices); + selection.index_range(), selection, 4096, indices); } return IndexMask(attributes.domain_size(domain)); } -static void face_corner_color_equalize_vertices(Mesh &mesh, const IndexMask selection) +static void face_corner_color_equalize_verts(Mesh &mesh, const IndexMask selection) { using namespace blender; @@ -196,7 +186,7 @@ static void face_corner_color_equalize_vertices(Mesh &mesh, const IndexMask sele return; } - bke::AttributeAccessor attributes = bke::mesh_attributes(mesh); + bke::AttributeAccessor attributes = mesh.attributes(); if (attributes.lookup_meta_data(active_color_layer->name)->domain == ATTR_DOMAIN_POINT) { return; @@ -221,7 +211,7 @@ static bool vertex_color_smooth(Object *ob) Vector<int64_t> indices; const IndexMask selection = get_selected_indices(*me, ATTR_DOMAIN_CORNER, indices); - face_corner_color_equalize_vertices(*me, selection); + face_corner_color_equalize_verts(*me, selection); tag_object_after_update(ob); @@ -270,7 +260,7 @@ static bool transform_active_color(Mesh &mesh, const TransformFn &transform_fn) return false; } - bke::MutableAttributeAccessor attributes = bke::mesh_attributes_for_write(mesh); + bke::MutableAttributeAccessor attributes = mesh.attributes_for_write(); bke::GAttributeWriter color_attribute = attributes.lookup_for_write(active_color_layer->name); if (!color_attribute) { @@ -320,7 +310,7 @@ static int vertex_color_brightness_contrast_exec(bContext *C, wmOperator *op) /* * The algorithm is by Werner D. Streidt * (http://visca.com/ffactory/archives/5-99/msg00021.html) - * Extracted of OpenCV demhist.c + * Extracted of OpenCV `demhist.c`. */ if (contrast > 0) { gain = 1.0f - delta * 2.0f; 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 d98660d8939..a7f43830e6b 100644 --- a/source/blender/editors/sculpt_paint/paint_vertex_weight_ops.c +++ b/source/blender/editors/sculpt_paint/paint_vertex_weight_ops.c @@ -168,8 +168,9 @@ static int weight_sample_invoke(bContext *C, wmOperator *op, const wmEvent *even ED_view3d_viewcontext_init(C, &vc, depsgraph); me = BKE_mesh_from_object(vc.obact); + const MDeformVert *dvert = BKE_mesh_deform_verts(me); - if (me && me->dvert && vc.v3d && vc.rv3d && (me->vertex_group_active_index != 0)) { + if (me && dvert && vc.v3d && vc.rv3d && (me->vertex_group_active_index != 0)) { const bool use_vert_sel = (me->editflag & ME_EDIT_PAINT_VERT_SEL) != 0; int v_idx_best = -1; uint index; @@ -200,7 +201,7 @@ static int weight_sample_invoke(bContext *C, wmOperator *op, const wmEvent *even ToolSettings *ts = vc.scene->toolsettings; Brush *brush = BKE_paint_brush(&ts->wpaint->paint); const int vgroup_active = me->vertex_group_active_index - 1; - float vgroup_weight = BKE_defvert_find_weight(&me->dvert[v_idx_best], vgroup_active); + float vgroup_weight = BKE_defvert_find_weight(&dvert[v_idx_best], vgroup_active); const int defbase_tot = BLI_listbase_count(&me->vertex_group_names); bool use_lock_relative = ts->wpaint_lock_relative; bool *defbase_locked = NULL, *defbase_unlocked = NULL; @@ -232,7 +233,7 @@ static int weight_sample_invoke(bContext *C, wmOperator *op, const wmEvent *even bool is_normalized = ts->auto_normalize || use_lock_relative; vgroup_weight = BKE_defvert_multipaint_collective_weight( - &me->dvert[v_idx_best], defbase_tot, defbase_sel, defbase_tot_sel, is_normalized); + &dvert[v_idx_best], defbase_tot, defbase_sel, defbase_tot_sel, is_normalized); } MEM_freeN(defbase_sel); @@ -243,7 +244,7 @@ static int weight_sample_invoke(bContext *C, wmOperator *op, const wmEvent *even defbase_tot, defbase_locked, defbase_unlocked, defbase_locked, defbase_unlocked); vgroup_weight = BKE_defvert_lock_relative_weight( - vgroup_weight, &me->dvert[v_idx_best], defbase_tot, defbase_locked, defbase_unlocked); + vgroup_weight, &dvert[v_idx_best], defbase_tot, defbase_locked, defbase_unlocked); } MEM_SAFE_FREE(defbase_locked); @@ -316,8 +317,11 @@ static const EnumPropertyItem *weight_paint_sample_enum_itemf(bContext *C, ED_view3d_viewcontext_init(C, &vc, depsgraph); me = BKE_mesh_from_object(vc.obact); + const MPoly *polys = BKE_mesh_polys(me); + const MLoop *loops = BKE_mesh_loops(me); + const MDeformVert *dverts = BKE_mesh_deform_verts(me); - if (me && me->dvert && vc.v3d && vc.rv3d && me->vertex_group_names.first) { + if (me && dverts && vc.v3d && vc.rv3d && me->vertex_group_names.first) { const int defbase_tot = BLI_listbase_count(&me->vertex_group_names); const bool use_vert_sel = (me->editflag & ME_EDIT_PAINT_VERT_SEL) != 0; int *groups = MEM_callocN(defbase_tot * sizeof(int), "groups"); @@ -334,17 +338,17 @@ static const EnumPropertyItem *weight_paint_sample_enum_itemf(bContext *C, if (use_vert_sel) { if (ED_mesh_pick_vert(C, vc.obact, mval, ED_MESH_PICK_DEFAULT_VERT_DIST, true, &index)) { - MDeformVert *dvert = &me->dvert[index]; + const MDeformVert *dvert = &dverts[index]; found |= weight_paint_sample_enum_itemf__helper(dvert, defbase_tot, groups); } } else { if (ED_mesh_pick_face(C, vc.obact, mval, ED_MESH_PICK_DEFAULT_FACE_DIST, &index)) { - const MPoly *mp = &me->mpoly[index]; + const MPoly *mp = &polys[index]; uint fidx = mp->totloop - 1; do { - MDeformVert *dvert = &me->dvert[me->mloop[mp->loopstart + fidx].v]; + const MDeformVert *dvert = &dverts[loops[mp->loopstart + fidx].v]; found |= weight_paint_sample_enum_itemf__helper(dvert, defbase_tot, groups); } while (fidx--); } @@ -441,7 +445,11 @@ static bool weight_paint_set(Object *ob, float paintweight) /* mutually exclusive, could be made into a */ const short paint_selmode = ME_EDIT_PAINT_SEL_MODE(me); - if (me->totpoly == 0 || me->dvert == NULL || !me->mpoly) { + const MPoly *polys = BKE_mesh_polys(me); + const MLoop *loops = BKE_mesh_loops(me); + MDeformVert *dvert = BKE_mesh_deform_verts_for_write(me); + + if (me->totpoly == 0 || dvert == NULL) { return false; } @@ -453,24 +461,29 @@ static bool weight_paint_set(Object *ob, float paintweight) } struct WPaintPrev wpp; - wpaint_prev_create(&wpp, me->dvert, me->totvert); + wpaint_prev_create(&wpp, dvert, me->totvert); + + const bool *select_vert = (const bool *)CustomData_get_layer_named( + &me->vdata, CD_PROP_BOOL, ".select_vert"); + const bool *select_poly = (const bool *)CustomData_get_layer_named( + &me->pdata, CD_PROP_BOOL, ".select_poly"); - for (index = 0, mp = me->mpoly; index < me->totpoly; index++, mp++) { + for (index = 0, mp = polys; index < me->totpoly; index++, mp++) { uint fidx = mp->totloop - 1; - if ((paint_selmode == SCE_SELECT_FACE) && !(mp->flag & ME_FACE_SEL)) { + if ((paint_selmode == SCE_SELECT_FACE) && !(select_poly && select_poly[index])) { continue; } do { - uint vidx = me->mloop[mp->loopstart + fidx].v; + uint vidx = loops[mp->loopstart + fidx].v; - if (!me->dvert[vidx].flag) { - if ((paint_selmode == SCE_SELECT_VERTEX) && !(me->mvert[vidx].flag & SELECT)) { + if (!dvert[vidx].flag) { + if ((paint_selmode == SCE_SELECT_VERTEX) && !(select_vert && select_vert[vidx])) { continue; } - dw = BKE_defvert_ensure_index(&me->dvert[vidx], vgroup_active); + dw = BKE_defvert_ensure_index(&dvert[vidx], vgroup_active); if (dw) { dw_prev = BKE_defvert_ensure_index(wpp.wpaint_prev + vidx, vgroup_active); dw_prev->weight = dw->weight; /* set the undo weight */ @@ -482,11 +495,11 @@ static bool weight_paint_set(Object *ob, float paintweight) if (j >= 0) { /* copy, not paint again */ if (vgroup_mirror != -1) { - dw = BKE_defvert_ensure_index(me->dvert + j, vgroup_mirror); + dw = BKE_defvert_ensure_index(dvert + j, vgroup_mirror); dw_prev = BKE_defvert_ensure_index(wpp.wpaint_prev + j, vgroup_mirror); } else { - dw = BKE_defvert_ensure_index(me->dvert + j, vgroup_active); + dw = BKE_defvert_ensure_index(dvert + j, vgroup_active); dw_prev = BKE_defvert_ensure_index(wpp.wpaint_prev + j, vgroup_active); } dw_prev->weight = dw->weight; /* set the undo weight */ @@ -494,14 +507,14 @@ static bool weight_paint_set(Object *ob, float paintweight) } } } - me->dvert[vidx].flag = 1; + dvert[vidx].flag = 1; } } while (fidx--); } { - MDeformVert *dv = me->dvert; + MDeformVert *dv = dvert; for (index = me->totvert; index != 0; index--, dv++) { dv->flag = 0; } @@ -574,6 +587,7 @@ typedef struct WPGradient_userData { struct ARegion *region; Scene *scene; Mesh *me; + MDeformVert *dvert; Brush *brush; const float *sco_start; /* [2] */ const float *sco_end; /* [2] */ @@ -593,7 +607,6 @@ typedef struct WPGradient_userData { static void gradientVert_update(WPGradient_userData *grad_data, int index) { - Mesh *me = grad_data->me; WPGradient_vertStore *vs = &grad_data->vert_cache->elem[index]; /* Optionally restrict to assigned vertices only. */ @@ -617,7 +630,7 @@ static void gradientVert_update(WPGradient_userData *grad_data, int index) alpha = BKE_brush_curve_strength_clamped(grad_data->brush, alpha, 1.0f); if (alpha != 0.0f) { - MDeformVert *dv = &me->dvert[index]; + MDeformVert *dv = &grad_data->dvert[index]; MDeformWeight *dw = BKE_defvert_ensure_index(dv, grad_data->def_nr); // dw->weight = alpha; // testing int tool = grad_data->brush->blend; @@ -631,7 +644,7 @@ static void gradientVert_update(WPGradient_userData *grad_data, int index) vs->flag |= VGRAD_STORE_IS_MODIFIED; } else { - MDeformVert *dv = &me->dvert[index]; + MDeformVert *dv = &grad_data->dvert[index]; if (vs->flag & VGRAD_STORE_DW_EXIST) { /* normally we NULL check, but in this case we know it exists */ MDeformWeight *dw = BKE_defvert_find_index(dv, grad_data->def_nr); @@ -669,10 +682,9 @@ static void gradientVertInit__mapFunc(void *userData, const float UNUSED(no[3])) { WPGradient_userData *grad_data = userData; - Mesh *me = grad_data->me; WPGradient_vertStore *vs = &grad_data->vert_cache->elem[index]; - if (grad_data->use_select && !(me->mvert[index].flag & SELECT)) { + if (grad_data->use_select && !(grad_data->dvert[index].flag & SELECT)) { copy_v2_fl(vs->sco, FLT_MAX); return; } @@ -693,7 +705,7 @@ static void gradientVertInit__mapFunc(void *userData, return; } - MDeformVert *dv = &me->dvert[index]; + MDeformVert *dv = &grad_data->dvert[index]; const MDeformWeight *dw = BKE_defvert_find_index(dv, grad_data->def_nr); if (dw) { vs->weight_orig = dw->weight; @@ -727,8 +739,9 @@ static int paint_weight_gradient_modal(bContext *C, wmOperator *op, const wmEven if (vert_cache != NULL) { Mesh *me = ob->data; if (vert_cache->wpp.wpaint_prev) { - BKE_defvert_array_free_elems(me->dvert, me->totvert); - BKE_defvert_array_copy(me->dvert, vert_cache->wpp.wpaint_prev, me->totvert); + MDeformVert *dvert = BKE_mesh_deform_verts_for_write(me); + BKE_defvert_array_free_elems(dvert, me->totvert); + BKE_defvert_array_copy(dvert, vert_cache->wpp.wpaint_prev, me->totvert); wpaint_prev_destroy(&vert_cache->wpp); } MEM_freeN(vert_cache); @@ -753,6 +766,7 @@ static int paint_weight_gradient_exec(bContext *C, wmOperator *op) Scene *scene = CTX_data_scene(C); Object *ob = CTX_data_active_object(C); Mesh *me = ob->data; + MDeformVert *dverts = BKE_mesh_deform_verts_for_write(me); int x_start = RNA_int_get(op->ptr, "xstart"); int y_start = RNA_int_get(op->ptr, "ystart"); int x_end = RNA_int_get(op->ptr, "xend"); @@ -774,7 +788,7 @@ static int paint_weight_gradient_exec(bContext *C, wmOperator *op) data.is_init = true; wpaint_prev_create( - &((WPGradient_vertStoreBase *)gesture->user_data.data)->wpp, me->dvert, me->totvert); + &((WPGradient_vertStoreBase *)gesture->user_data.data)->wpp, dverts, me->totvert); /* On initialization only, convert face -> vert sel. */ if (me->editflag & ME_EDIT_PAINT_FACE_SEL) { @@ -797,6 +811,7 @@ static int paint_weight_gradient_exec(bContext *C, wmOperator *op) data.region = region; data.scene = scene; data.me = ob->data; + data.dvert = dverts; data.sco_start = sco_start; data.sco_end = sco_end; data.sco_line_div = 1.0f / len_v2v2(sco_start, sco_end); @@ -851,7 +866,7 @@ static int paint_weight_gradient_exec(bContext *C, wmOperator *op) const int vgroup_num = BLI_listbase_count(&me->vertex_group_names); bool *vgroup_validmap = BKE_object_defgroup_validmap_get(ob, vgroup_num); if (vgroup_validmap != NULL) { - MDeformVert *dvert = me->dvert; + MDeformVert *dvert = dverts; for (int i = 0; i < me->totvert; i++) { if ((data.vert_cache->elem[i].flag & VGRAD_STORE_IS_MODIFIED) != 0) { BKE_defvert_normalize_lock_single(&dvert[i], vgroup_validmap, vgroup_num, data.def_nr); diff --git a/source/blender/editors/sculpt_paint/paint_vertex_weight_utils.c b/source/blender/editors/sculpt_paint/paint_vertex_weight_utils.c index 5a63af4149a..ac16631f115 100644 --- a/source/blender/editors/sculpt_paint/paint_vertex_weight_utils.c +++ b/source/blender/editors/sculpt_paint/paint_vertex_weight_utils.c @@ -59,7 +59,7 @@ bool ED_wpaint_ensure_data(bContext *C, } /* if nothing was added yet, we make dverts and a vertex deform group */ - if (!me->dvert) { + if (BKE_mesh_deform_verts(me) == NULL) { BKE_object_defgroup_data_create(&me->id); WM_event_add_notifier(C, NC_GEOM | ND_DATA, me); } diff --git a/source/blender/editors/sculpt_paint/sculpt.c b/source/blender/editors/sculpt_paint/sculpt.c index ffa931268fd..688573d78a6 100644 --- a/source/blender/editors/sculpt_paint/sculpt.c +++ b/source/blender/editors/sculpt_paint/sculpt.c @@ -116,7 +116,7 @@ int SCULPT_vertex_count_get(SculptSession *ss) case PBVH_BMESH: return BM_mesh_elem_count(BKE_pbvh_get_bmesh(ss->pbvh), BM_VERT); case PBVH_GRIDS: - return BKE_pbvh_get_grid_num_vertices(ss->pbvh); + return BKE_pbvh_get_grid_num_verts(ss->pbvh); } return 0; @@ -194,9 +194,10 @@ void SCULPT_vertex_normal_get(SculptSession *ss, PBVHVertRef vertex, float no[3] const float *SCULPT_vertex_persistent_co_get(SculptSession *ss, PBVHVertRef vertex) { - if (ss->persistent_base) { - return ss->persistent_base[BKE_pbvh_vertex_to_index(ss->pbvh, vertex)].co; + if (ss->attrs.persistent_co) { + return (const float *)SCULPT_vertex_attr_get(vertex, ss->attrs.persistent_co); } + return SCULPT_vertex_co_get(ss, vertex); } @@ -240,8 +241,8 @@ void SCULPT_vertex_limit_surface_get(SculptSession *ss, PBVHVertRef vertex, floa void SCULPT_vertex_persistent_normal_get(SculptSession *ss, PBVHVertRef vertex, float no[3]) { - if (ss->persistent_base) { - copy_v3_v3(no, ss->persistent_base[vertex.i].no); + if (ss->attrs.persistent_no) { + copy_v3_v3(no, (float *)SCULPT_vertex_attr_get(vertex, ss->attrs.persistent_no)); return; } SCULPT_vertex_normal_get(ss, vertex, no); @@ -249,15 +250,16 @@ void SCULPT_vertex_persistent_normal_get(SculptSession *ss, PBVHVertRef vertex, float SCULPT_vertex_mask_get(SculptSession *ss, PBVHVertRef vertex) { - BMVert *v; - float *mask; switch (BKE_pbvh_type(ss->pbvh)) { case PBVH_FACES: - return ss->vmask[vertex.i]; - case PBVH_BMESH: + return ss->vmask ? ss->vmask[vertex.i] : 0.0f; + case PBVH_BMESH: { + BMVert *v; + int cd_mask = CustomData_get_offset(&ss->bm->vdata, CD_PAINT_MASK); + v = (BMVert *)vertex.i; - mask = BM_ELEM_CD_GET_VOID_P(v, CustomData_get_offset(&ss->bm->vdata, CD_PAINT_MASK)); - return *mask; + return cd_mask != -1 ? BM_ELEM_CD_GET_FLOAT(v, cd_mask) : 0.0f; + } case PBVH_GRIDS: { const CCGKey *key = BKE_pbvh_get_grid_key(ss->pbvh); const int grid_index = vertex.i / key->grid_area; @@ -329,8 +331,14 @@ int SCULPT_active_face_set_get(SculptSession *ss) { switch (BKE_pbvh_type(ss->pbvh)) { case PBVH_FACES: + if (!ss->face_sets) { + return SCULPT_FACE_SET_NONE; + } return ss->face_sets[ss->active_face_index]; case PBVH_GRIDS: { + if (!ss->face_sets) { + return SCULPT_FACE_SET_NONE; + } const int face_index = BKE_subdiv_ccg_grid_to_face_index(ss->subdiv_ccg, ss->active_grid_index); return ss->face_sets[face_index]; @@ -383,19 +391,16 @@ bool SCULPT_vertex_visible_get(SculptSession *ss, PBVHVertRef vertex) void SCULPT_face_set_visibility_set(SculptSession *ss, int face_set, bool visible) { + BLI_assert(ss->face_sets != NULL); + BLI_assert(ss->hide_poly != NULL); switch (BKE_pbvh_type(ss->pbvh)) { case PBVH_FACES: case PBVH_GRIDS: for (int i = 0; i < ss->totfaces; i++) { - if (abs(ss->face_sets[i]) != face_set) { + if (ss->face_sets[i] != face_set) { continue; } - if (visible) { - ss->face_sets[i] = abs(ss->face_sets[i]); - } - else { - ss->face_sets[i] = -abs(ss->face_sets[i]); - } + ss->hide_poly[i] = !visible; } break; case PBVH_BMESH: @@ -403,13 +408,15 @@ void SCULPT_face_set_visibility_set(SculptSession *ss, int face_set, bool visibl } } -void SCULPT_face_sets_visibility_invert(SculptSession *ss) +void SCULPT_face_visibility_all_invert(SculptSession *ss) { + BLI_assert(ss->face_sets != NULL); + BLI_assert(ss->hide_poly != NULL); switch (BKE_pbvh_type(ss->pbvh)) { case PBVH_FACES: case PBVH_GRIDS: for (int i = 0; i < ss->totfaces; i++) { - ss->face_sets[i] *= -1; + ss->hide_poly[i] = !ss->hide_poly[i]; } break; case PBVH_BMESH: @@ -417,40 +424,29 @@ void SCULPT_face_sets_visibility_invert(SculptSession *ss) } } -void SCULPT_face_sets_visibility_all_set(SculptSession *ss, bool visible) +void SCULPT_face_visibility_all_set(SculptSession *ss, bool visible) { switch (BKE_pbvh_type(ss->pbvh)) { case PBVH_FACES: case PBVH_GRIDS: - for (int i = 0; i < ss->totfaces; i++) { - - /* This can run on geometry without a face set assigned, so its ID sign can't be changed to - * modify the visibility. Force that geometry to the ID 1 to enable changing the visibility - * here. */ - if (ss->face_sets[i] == SCULPT_FACE_SET_NONE) { - ss->face_sets[i] = 1; - } - - if (visible) { - ss->face_sets[i] = abs(ss->face_sets[i]); - } - else { - ss->face_sets[i] = -abs(ss->face_sets[i]); - } - } + BLI_assert(ss->hide_poly != NULL); + memset(ss->hide_poly, !visible, sizeof(bool) * ss->totfaces); break; case PBVH_BMESH: break; } } -bool SCULPT_vertex_any_face_set_visible_get(SculptSession *ss, PBVHVertRef vertex) +bool SCULPT_vertex_any_face_visible_get(SculptSession *ss, PBVHVertRef vertex) { switch (BKE_pbvh_type(ss->pbvh)) { case PBVH_FACES: { + if (!ss->hide_poly) { + return true; + } MeshElemMap *vert_map = &ss->pmap[vertex.i]; for (int j = 0; j < ss->pmap[vertex.i].count; j++) { - if (ss->face_sets[vert_map->indices[j]] > 0) { + if (!ss->hide_poly[vert_map->indices[j]]) { return true; } } @@ -464,13 +460,16 @@ bool SCULPT_vertex_any_face_set_visible_get(SculptSession *ss, PBVHVertRef verte return true; } -bool SCULPT_vertex_all_face_sets_visible_get(const SculptSession *ss, PBVHVertRef vertex) +bool SCULPT_vertex_all_faces_visible_get(const SculptSession *ss, PBVHVertRef vertex) { switch (BKE_pbvh_type(ss->pbvh)) { case PBVH_FACES: { + if (!ss->hide_poly) { + return true; + } MeshElemMap *vert_map = &ss->pmap[vertex.i]; for (int j = 0; j < ss->pmap[vertex.i].count; j++) { - if (ss->face_sets[vert_map->indices[j]] < 0) { + if (ss->hide_poly[vert_map->indices[j]]) { return false; } } @@ -479,10 +478,13 @@ bool SCULPT_vertex_all_face_sets_visible_get(const SculptSession *ss, PBVHVertRe case PBVH_BMESH: return true; case PBVH_GRIDS: { + if (!ss->hide_poly) { + return true; + } const CCGKey *key = BKE_pbvh_get_grid_key(ss->pbvh); const int grid_index = vertex.i / key->grid_area; const int face_index = BKE_subdiv_ccg_grid_to_face_index(ss->subdiv_ccg, grid_index); - return ss->face_sets[face_index] > 0; + return !ss->hide_poly[face_index]; } } return true; @@ -492,24 +494,32 @@ void SCULPT_vertex_face_set_set(SculptSession *ss, PBVHVertRef vertex, int face_ { switch (BKE_pbvh_type(ss->pbvh)) { case PBVH_FACES: { + BLI_assert(ss->face_sets != NULL); MeshElemMap *vert_map = &ss->pmap[vertex.i]; for (int j = 0; j < ss->pmap[vertex.i].count; j++) { - if (ss->face_sets[vert_map->indices[j]] > 0) { - ss->face_sets[vert_map->indices[j]] = abs(face_set); + const int poly_index = vert_map->indices[j]; + if (ss->hide_poly && ss->hide_poly[poly_index]) { + /* Skip hidden faces connected to the vertex. */ + continue; } + ss->face_sets[poly_index] = face_set; } - } break; + break; + } case PBVH_BMESH: break; case PBVH_GRIDS: { + BLI_assert(ss->face_sets != NULL); const CCGKey *key = BKE_pbvh_get_grid_key(ss->pbvh); const int grid_index = vertex.i / key->grid_area; const int face_index = BKE_subdiv_ccg_grid_to_face_index(ss->subdiv_ccg, grid_index); - if (ss->face_sets[face_index] > 0) { - ss->face_sets[face_index] = abs(face_set); + if (ss->hide_poly && ss->hide_poly[face_index]) { + /* Skip the vertex if it's in a hidden face. */ + return; } - - } break; + ss->face_sets[face_index] = face_set; + break; + } } } @@ -517,6 +527,9 @@ int SCULPT_vertex_face_set_get(SculptSession *ss, PBVHVertRef vertex) { switch (BKE_pbvh_type(ss->pbvh)) { case PBVH_FACES: { + if (!ss->face_sets) { + return SCULPT_FACE_SET_NONE; + } MeshElemMap *vert_map = &ss->pmap[vertex.i]; int face_set = 0; for (int i = 0; i < ss->pmap[vertex.i].count; i++) { @@ -529,6 +542,9 @@ int SCULPT_vertex_face_set_get(SculptSession *ss, PBVHVertRef vertex) case PBVH_BMESH: return 0; case PBVH_GRIDS: { + if (!ss->face_sets) { + return SCULPT_FACE_SET_NONE; + } const CCGKey *key = BKE_pbvh_get_grid_key(ss->pbvh); const int grid_index = vertex.i / key->grid_area; const int face_index = BKE_subdiv_ccg_grid_to_face_index(ss->subdiv_ccg, grid_index); @@ -542,6 +558,9 @@ bool SCULPT_vertex_has_face_set(SculptSession *ss, PBVHVertRef vertex, int face_ { switch (BKE_pbvh_type(ss->pbvh)) { case PBVH_FACES: { + if (!ss->face_sets) { + return face_set == SCULPT_FACE_SET_NONE; + } MeshElemMap *vert_map = &ss->pmap[vertex.i]; for (int i = 0; i < ss->pmap[vertex.i].count; i++) { if (ss->face_sets[vert_map->indices[i]] == face_set) { @@ -553,6 +572,9 @@ bool SCULPT_vertex_has_face_set(SculptSession *ss, PBVHVertRef vertex, int face_ case PBVH_BMESH: return true; case PBVH_GRIDS: { + if (!ss->face_sets) { + return face_set == SCULPT_FACE_SET_NONE; + } const CCGKey *key = BKE_pbvh_get_grid_key(ss->pbvh); const int grid_index = vertex.i / key->grid_area; const int face_index = BKE_subdiv_ccg_grid_to_face_index(ss->subdiv_ccg, grid_index); @@ -562,18 +584,23 @@ bool SCULPT_vertex_has_face_set(SculptSession *ss, PBVHVertRef vertex, int face_ return true; } -void SCULPT_visibility_sync_all_face_sets_to_vertices(Object *ob) +void SCULPT_visibility_sync_all_from_faces(Object *ob) { SculptSession *ss = ob->sculpt; Mesh *mesh = BKE_object_get_original_mesh(ob); switch (BKE_pbvh_type(ss->pbvh)) { case PBVH_FACES: { - BKE_sculpt_sync_face_sets_visibility_to_base_mesh(mesh); + /* We may have adjusted the ".hide_poly" attribute, now make the hide status attributes for + * vertices and edges consistent. */ + BKE_mesh_flush_hidden_from_polys(mesh); + BKE_pbvh_update_hide_attributes_from_mesh(ss->pbvh); break; } case PBVH_GRIDS: { - BKE_sculpt_sync_face_sets_visibility_to_base_mesh(mesh); - BKE_sculpt_sync_face_sets_visibility_to_grids(mesh, ss->subdiv_ccg); + /* In addition to making the hide status of the base mesh consistent, we also have to + * propagate the status to the Multires grids. */ + BKE_mesh_flush_hidden_from_polys(mesh); + BKE_sculpt_sync_face_visibility_to_grids(mesh, ss->subdiv_ccg); break; } case PBVH_BMESH: @@ -581,53 +608,19 @@ void SCULPT_visibility_sync_all_face_sets_to_vertices(Object *ob) } } -static void UNUSED_FUNCTION(sculpt_visibility_sync_vertex_to_face_sets)(SculptSession *ss, - PBVHVertRef vertex) -{ - MeshElemMap *vert_map = &ss->pmap[vertex.i]; - const bool visible = SCULPT_vertex_visible_get(ss, vertex); - for (int i = 0; i < ss->pmap[vertex.i].count; i++) { - if (visible) { - ss->face_sets[vert_map->indices[i]] = abs(ss->face_sets[vert_map->indices[i]]); - } - else { - ss->face_sets[vert_map->indices[i]] = -abs(ss->face_sets[vert_map->indices[i]]); - } - } -} - -void SCULPT_visibility_sync_all_vertex_to_face_sets(SculptSession *ss) -{ - if (BKE_pbvh_type(ss->pbvh) == PBVH_FACES) { - for (int i = 0; i < ss->totfaces; i++) { - MPoly *poly = &ss->mpoly[i]; - bool poly_visible = true; - for (int l = 0; l < poly->totloop; l++) { - MLoop *loop = &ss->mloop[poly->loopstart + l]; - if (!SCULPT_vertex_visible_get(ss, BKE_pbvh_make_vref(loop->v))) { - poly_visible = false; - } - } - if (poly_visible) { - ss->face_sets[i] = abs(ss->face_sets[i]); - } - else { - ss->face_sets[i] = -abs(ss->face_sets[i]); - } - } - } -} - static bool sculpt_check_unique_face_set_in_base_mesh(SculptSession *ss, int index) { + if (!ss->face_sets) { + return true; + } MeshElemMap *vert_map = &ss->pmap[index]; int face_set = -1; for (int i = 0; i < ss->pmap[index].count; i++) { if (face_set == -1) { - face_set = abs(ss->face_sets[vert_map->indices[i]]); + face_set = ss->face_sets[vert_map->indices[i]]; } else { - if (abs(ss->face_sets[vert_map->indices[i]]) != face_set) { + if (ss->face_sets[vert_map->indices[i]] != face_set) { return false; } } @@ -644,9 +637,9 @@ static bool sculpt_check_unique_face_set_for_edge_in_base_mesh(SculptSession *ss MeshElemMap *vert_map = &ss->pmap[v1]; int p1 = -1, p2 = -1; for (int i = 0; i < ss->pmap[v1].count; i++) { - MPoly *p = &ss->mpoly[vert_map->indices[i]]; + const MPoly *p = &ss->mpoly[vert_map->indices[i]]; for (int l = 0; l < p->totloop; l++) { - MLoop *loop = &ss->mloop[p->loopstart + l]; + const MLoop *loop = &ss->mloop[p->loopstart + l]; if (loop->v == v2) { if (p1 == -1) { p1 = vert_map->indices[i]; @@ -676,6 +669,9 @@ bool SCULPT_vertex_has_unique_face_set(SculptSession *ss, PBVHVertRef vertex) case PBVH_BMESH: return true; case PBVH_GRIDS: { + if (!ss->face_sets) { + return true; + } const CCGKey *key = BKE_pbvh_get_grid_key(ss->pbvh); const int grid_index = vertex.i / key->grid_area; const int vertex_index = vertex.i - grid_index * key->grid_area; @@ -703,10 +699,13 @@ int SCULPT_face_set_next_available_get(SculptSession *ss) switch (BKE_pbvh_type(ss->pbvh)) { case PBVH_FACES: case PBVH_GRIDS: { + if (!ss->face_sets) { + return 0; + } int next_face_set = 0; for (int i = 0; i < ss->totfaces; i++) { - if (abs(ss->face_sets[i]) > next_face_set) { - next_face_set = abs(ss->face_sets[i]); + if (ss->face_sets[i] > next_face_set) { + next_face_set = ss->face_sets[i]; } } next_face_set++; @@ -792,9 +791,10 @@ static void sculpt_vertex_neighbors_get_faces(SculptSession *ss, iter->capacity = SCULPT_VERTEX_NEIGHBOR_FIXED_CAPACITY; iter->neighbors = iter->neighbors_fixed; iter->neighbor_indices = iter->neighbor_indices_fixed; + const bool *hide_poly = BKE_pbvh_get_vert_hide(ss->pbvh); for (int i = 0; i < ss->pmap[vertex.i].count; i++) { - if (ss->face_sets[vert_map->indices[i]] < 0) { + if (hide_poly && hide_poly[vert_map->indices[i]]) { /* Skip connectivity from hidden faces. */ continue; } @@ -893,7 +893,7 @@ bool SCULPT_vertex_is_boundary(const SculptSession *ss, const PBVHVertRef vertex { switch (BKE_pbvh_type(ss->pbvh)) { case PBVH_FACES: { - if (!SCULPT_vertex_all_face_sets_visible_get(ss, vertex)) { + if (!SCULPT_vertex_all_faces_visible_get(ss, vertex)) { return true; } return sculpt_check_boundary_vertex_in_base_mesh(ss, vertex.i); @@ -1102,7 +1102,7 @@ void SCULPT_floodfill_init(SculptSession *ss, SculptFloodFill *flood) SCULPT_vertex_random_access_ensure(ss); flood->queue = BLI_gsqueue_new(sizeof(intptr_t)); - flood->visited_vertices = BLI_BITMAP_NEW(vertex_count, "visited vertices"); + flood->visited_verts = BLI_BITMAP_NEW(vertex_count, "visited verts"); } void SCULPT_floodfill_add_initial(SculptFloodFill *flood, PBVHVertRef vertex) @@ -1113,7 +1113,7 @@ void SCULPT_floodfill_add_initial(SculptFloodFill *flood, PBVHVertRef vertex) void SCULPT_floodfill_add_and_skip_initial(SculptFloodFill *flood, PBVHVertRef vertex) { BLI_gsqueue_push(flood->queue, &vertex); - BLI_BITMAP_ENABLE(flood->visited_vertices, vertex.i); + BLI_BITMAP_ENABLE(flood->visited_verts, vertex.i); } void SCULPT_floodfill_add_initial_with_symmetry(Sculpt *sd, @@ -1192,7 +1192,7 @@ void SCULPT_floodfill_execute(SculptSession *ss, const PBVHVertRef to_v = ni.vertex; int to_v_i = BKE_pbvh_vertex_to_index(ss->pbvh, to_v); - if (BLI_BITMAP_TEST(flood->visited_vertices, to_v_i)) { + if (BLI_BITMAP_TEST(flood->visited_verts, to_v_i)) { continue; } @@ -1200,7 +1200,7 @@ void SCULPT_floodfill_execute(SculptSession *ss, continue; } - BLI_BITMAP_ENABLE(flood->visited_vertices, BKE_pbvh_vertex_to_index(ss->pbvh, to_v)); + BLI_BITMAP_ENABLE(flood->visited_verts, BKE_pbvh_vertex_to_index(ss->pbvh, to_v)); if (func(ss, from_v, to_v, ni.is_duplicate, userdata)) { BLI_gsqueue_push(flood->queue, &to_v); @@ -1212,7 +1212,7 @@ void SCULPT_floodfill_execute(SculptSession *ss, void SCULPT_floodfill_free(SculptFloodFill *flood) { - MEM_SAFE_FREE(flood->visited_vertices); + MEM_SAFE_FREE(flood->visited_verts); BLI_gsqueue_free(flood->queue); flood->queue = NULL; } @@ -1406,16 +1406,13 @@ static void paint_mesh_restore_co_task_cb(void *__restrict userdata, switch (data->brush->sculpt_tool) { case SCULPT_TOOL_MASK: type = SCULPT_UNDO_MASK; - BKE_pbvh_node_mark_update_mask(data->nodes[n]); break; case SCULPT_TOOL_PAINT: case SCULPT_TOOL_SMEAR: type = SCULPT_UNDO_COLOR; - BKE_pbvh_node_mark_update_color(data->nodes[n]); break; default: type = SCULPT_UNDO_COORDS; - BKE_pbvh_node_mark_update(data->nodes[n]); break; } @@ -1430,6 +1427,20 @@ static void paint_mesh_restore_co_task_cb(void *__restrict userdata, return; } + switch (type) { + case SCULPT_UNDO_MASK: + BKE_pbvh_node_mark_update_mask(data->nodes[n]); + break; + case SCULPT_UNDO_COLOR: + BKE_pbvh_node_mark_update_color(data->nodes[n]); + break; + case SCULPT_UNDO_COORDS: + BKE_pbvh_node_mark_update(data->nodes[n]); + break; + default: + break; + } + PBVHVertexIter vd; SculptOrigVertData orig_data; @@ -3151,10 +3162,10 @@ void SCULPT_vertcos_to_key(Object *ob, KeyBlock *kb, const float (*vertCos)[3]) /* Modifying of basis key should update mesh. */ if (kb == me->key->refkey) { - MVert *mvert = me->mvert; + MVert *verts = BKE_mesh_verts_for_write(me); - for (a = 0; a < me->totvert; a++, mvert++) { - copy_v3_v3(mvert->co, vertCos[a]); + for (a = 0; a < me->totvert; a++) { + copy_v3_v3(verts[a].co, vertCos[a]); } BKE_mesh_tag_coords_changed(me); } @@ -3578,8 +3589,9 @@ static void sculpt_flush_pbvhvert_deform(Object *ob, PBVHVertexIter *vd) copy_v3_v3(ss->deform_cos[index], vd->co); copy_v3_v3(ss->orig_cos[index], newco); + MVert *verts = BKE_mesh_verts_for_write(me); if (!ss->shapekey_active) { - copy_v3_v3(me->mvert[index].co, newco); + copy_v3_v3(verts[index].co, newco); } } @@ -5303,6 +5315,8 @@ void SCULPT_flush_update_done(const bContext *C, Object *ob, SculptUpdateType up BKE_pbvh_update_vertex_data(ss->pbvh, PBVH_UpdateColor); } + BKE_sculpt_attributes_destroy_temporary_stroke(ob); + if (BKE_pbvh_type(ss->pbvh) == PBVH_BMESH) { BKE_pbvh_bmesh_after_stroke(ss->pbvh); } @@ -5382,7 +5396,7 @@ static bool sculpt_stroke_test_start(bContext *C, struct wmOperator *op, const f ED_image_undo_push_begin(op->type->name, PAINT_MODE_SCULPT); } else { - SCULPT_undo_push_begin(ob, sculpt_tool_name(sd)); + SCULPT_undo_push_begin_ex(ob, sculpt_tool_name(sd)); } return true; @@ -5548,7 +5562,7 @@ static int sculpt_brush_stroke_invoke(bContext *C, wmOperator *op, const wmEvent * to avoid falling through to the translate operator in the * global view3d keymap. * - * Note: BKE_object_is_visible_in_viewport is not working here (it returns false + * NOTE: #BKE_object_is_visible_in_viewport is not working here (it returns false * if the object is in local view); instead, test for OB_HIDE_VIEWPORT directly. */ @@ -5560,11 +5574,20 @@ static int sculpt_brush_stroke_invoke(bContext *C, wmOperator *op, const wmEvent Sculpt *sd = CTX_data_tool_settings(C)->sculpt; Brush *brush = BKE_paint_brush(&sd->paint); + SculptSession *ss = ob->sculpt; if (SCULPT_tool_is_paint(brush->sculpt_tool) && !SCULPT_handles_colors_report(ob->sculpt, op->reports)) { return OPERATOR_CANCELLED; } + if (SCULPT_tool_is_mask(brush->sculpt_tool)) { + MultiresModifierData *mmd = BKE_sculpt_multires_active(ss->scene, ob); + BKE_sculpt_mask_layers_ensure(ob, mmd); + } + if (SCULPT_tool_is_face_sets(brush->sculpt_tool)) { + Mesh *mesh = BKE_object_get_original_mesh(ob); + ss->face_sets = BKE_sculpt_face_sets_ensure(mesh); + } stroke = paint_stroke_new(C, op, @@ -5645,6 +5668,10 @@ static int sculpt_brush_stroke_modal(bContext *C, wmOperator *op, const wmEvent return paint_stroke_modal(C, op, event, (struct PaintStroke **)&op->customdata); } +static void sculpt_redo_empty_ui(bContext *UNUSED(C), wmOperator *UNUSED(op)) +{ +} + void SCULPT_OT_brush_stroke(wmOperatorType *ot) { /* Identifiers. */ @@ -5658,6 +5685,7 @@ void SCULPT_OT_brush_stroke(wmOperatorType *ot) ot->exec = sculpt_brush_stroke_exec; ot->poll = SCULPT_poll; ot->cancel = sculpt_brush_stroke_cancel; + ot->ui = sculpt_redo_empty_ui; /* Flags (sculpt does own undo? (ton)). */ ot->flag = OPTYPE_BLOCKING | OPTYPE_REGISTER | OPTYPE_UNDO; @@ -5892,21 +5920,25 @@ void SCULPT_boundary_info_ensure(Object *object) } Mesh *base_mesh = BKE_mesh_from_object(object); + const MEdge *edges = BKE_mesh_edges(base_mesh); + const MPoly *polys = BKE_mesh_polys(base_mesh); + const MLoop *loops = BKE_mesh_loops(base_mesh); + ss->vertex_info.boundary = BLI_BITMAP_NEW(base_mesh->totvert, "Boundary info"); int *adjacent_faces_edge_count = MEM_calloc_arrayN( base_mesh->totedge, sizeof(int), "Adjacent face edge count"); for (int p = 0; p < base_mesh->totpoly; p++) { - MPoly *poly = &base_mesh->mpoly[p]; + const MPoly *poly = &polys[p]; for (int l = 0; l < poly->totloop; l++) { - MLoop *loop = &base_mesh->mloop[l + poly->loopstart]; + const MLoop *loop = &loops[l + poly->loopstart]; adjacent_faces_edge_count[loop->e]++; } } for (int e = 0; e < base_mesh->totedge; e++) { if (adjacent_faces_edge_count[e] < 2) { - MEdge *edge = &base_mesh->medge[e]; + const MEdge *edge = &edges[e]; BLI_BITMAP_SET(ss->vertex_info.boundary, edge->v1, true); BLI_BITMAP_SET(ss->vertex_info.boundary, edge->v2, true); } diff --git a/source/blender/editors/sculpt_paint/sculpt_automasking.cc b/source/blender/editors/sculpt_paint/sculpt_automasking.cc index a9fe8cc4b2f..f4da70faad7 100644 --- a/source/blender/editors/sculpt_paint/sculpt_automasking.cc +++ b/source/blender/editors/sculpt_paint/sculpt_automasking.cc @@ -122,13 +122,11 @@ float SCULPT_automasking_factor_get(AutomaskingCache *automasking, return 1.0f; } - int index = BKE_pbvh_vertex_to_index(ss->pbvh, vert); - /* If the cache is initialized with valid info, use the cache. This is used when the * automasking information can't be computed in real time per vertex and needs to be * initialized for the whole mesh when the stroke starts. */ - if (automasking->factor) { - return automasking->factor[index]; + if (ss->attrs.automasking_factor) { + return *(float *)SCULPT_vertex_attr_get(vert, ss->attrs.automasking_factor); } if (automasking->settings.flags & BRUSH_AUTOMASKING_FACE_SETS) { @@ -158,7 +156,6 @@ void SCULPT_automasking_cache_free(AutomaskingCache *automasking) return; } - MEM_SAFE_FREE(automasking->factor); MEM_SAFE_FREE(automasking); } @@ -176,7 +173,6 @@ static bool sculpt_automasking_is_constrained_by_radius(Brush *br) } struct AutomaskFloodFillData { - float *automask_factor; float radius; bool use_radius; float location[3]; @@ -190,29 +186,29 @@ static bool automask_floodfill_cb(SculptSession *ss, void *userdata) { AutomaskFloodFillData *data = (AutomaskFloodFillData *)userdata; - int from_v_i = BKE_pbvh_vertex_to_index(ss->pbvh, from_v); - int to_v_i = BKE_pbvh_vertex_to_index(ss->pbvh, to_v); - data->automask_factor[to_v_i] = 1.0f; - data->automask_factor[from_v_i] = 1.0f; + *(float *)SCULPT_vertex_attr_get(to_v, ss->attrs.automasking_factor) = 1.0f; + *(float *)SCULPT_vertex_attr_get(from_v, ss->attrs.automasking_factor) = 1.0f; return (!data->use_radius || SCULPT_is_vertex_inside_brush_radius_symm( SCULPT_vertex_co_get(ss, to_v), data->location, data->radius, data->symm)); } -static float *SCULPT_topology_automasking_init(Sculpt *sd, Object *ob, float *automask_factor) +static void SCULPT_topology_automasking_init(Sculpt *sd, Object *ob) { SculptSession *ss = ob->sculpt; Brush *brush = BKE_paint_brush(&sd->paint); if (BKE_pbvh_type(ss->pbvh) == PBVH_FACES && !ss->pmap) { BLI_assert_msg(0, "Topology masking: pmap missing"); - return nullptr; + return; } const int totvert = SCULPT_vertex_count_get(ss); for (int i : IndexRange(totvert)) { - automask_factor[i] = 0.0f; + PBVHVertRef vertex = BKE_pbvh_index_to_vertex(ss->pbvh, i); + + (*(float *)SCULPT_vertex_attr_get(vertex, ss->attrs.automasking_factor)) = 0.0f; } /* Flood fill automask to connected vertices. Limited to vertices inside @@ -222,9 +218,8 @@ static float *SCULPT_topology_automasking_init(Sculpt *sd, Object *ob, float *au const float radius = ss->cache ? ss->cache->radius : FLT_MAX; SCULPT_floodfill_add_active(sd, ob, ss, &flood, radius); - AutomaskFloodFillData fdata = {nullptr}; + AutomaskFloodFillData fdata = {0}; - fdata.automask_factor = automask_factor; fdata.radius = radius; fdata.use_radius = ss->cache && sculpt_automasking_is_constrained_by_radius(brush); fdata.symm = SCULPT_mesh_symmetry_xyz_get(ob); @@ -232,22 +227,20 @@ static float *SCULPT_topology_automasking_init(Sculpt *sd, Object *ob, float *au copy_v3_v3(fdata.location, SCULPT_active_vertex_co_get(ss)); SCULPT_floodfill_execute(ss, &flood, automask_floodfill_cb, &fdata); SCULPT_floodfill_free(&flood); - - return automask_factor; } -static float *sculpt_face_sets_automasking_init(Sculpt *sd, Object *ob, float *automask_factor) +static void sculpt_face_sets_automasking_init(Sculpt *sd, Object *ob) { SculptSession *ss = ob->sculpt; Brush *brush = BKE_paint_brush(&sd->paint); if (!SCULPT_is_automasking_enabled(sd, ss, brush)) { - return nullptr; + return; } if (BKE_pbvh_type(ss->pbvh) == PBVH_FACES && !ss->pmap) { BLI_assert_msg(0, "Face Sets automasking: pmap missing"); - return nullptr; + return; } int tot_vert = SCULPT_vertex_count_get(ss); @@ -256,25 +249,22 @@ static float *sculpt_face_sets_automasking_init(Sculpt *sd, Object *ob, float *a PBVHVertRef vertex = BKE_pbvh_index_to_vertex(ss->pbvh, i); if (!SCULPT_vertex_has_face_set(ss, vertex, active_face_set)) { - automask_factor[i] *= 0.0f; + *(float *)SCULPT_vertex_attr_get(vertex, ss->attrs.automasking_factor) = 0.0f; } } - - return automask_factor; } #define EDGE_DISTANCE_INF -1 -float *SCULPT_boundary_automasking_init(Object *ob, - eBoundaryAutomaskMode mode, - int propagation_steps, - float *automask_factor) +static void SCULPT_boundary_automasking_init(Object *ob, + eBoundaryAutomaskMode mode, + int propagation_steps) { SculptSession *ss = ob->sculpt; if (!ss->pmap) { BLI_assert_msg(0, "Boundary Edges masking: pmap missing"); - return nullptr; + return; } const int totvert = SCULPT_vertex_count_get(ss); @@ -316,16 +306,19 @@ float *SCULPT_boundary_automasking_init(Object *ob, } for (int i : IndexRange(totvert)) { + PBVHVertRef vertex = BKE_pbvh_index_to_vertex(ss->pbvh, i); + if (edge_distance[i] == EDGE_DISTANCE_INF) { continue; } const float p = 1.0f - ((float)edge_distance[i] / (float)propagation_steps); const float edge_boundary_automask = pow2f(p); - automask_factor[i] *= (1.0f - edge_boundary_automask); + + *(float *)SCULPT_vertex_attr_get( + vertex, ss->attrs.automasking_factor) *= (1.0f - edge_boundary_automask); } MEM_SAFE_FREE(edge_distance); - return automask_factor; } static void SCULPT_automasking_cache_settings_update(AutomaskingCache *automasking, @@ -355,9 +348,16 @@ AutomaskingCache *SCULPT_automasking_cache_init(Sculpt *sd, Brush *brush, Object return automasking; } - automasking->factor = (float *)MEM_malloc_arrayN(totvert, sizeof(float), "automask_factor"); + SculptAttributeParams params = {0}; + params.stroke_only = true; + + ss->attrs.automasking_factor = BKE_sculpt_attribute_ensure( + ob, ATTR_DOMAIN_POINT, CD_PROP_FLOAT, SCULPT_ATTRIBUTE_NAME(automasking_factor), ¶ms); + for (int i : IndexRange(totvert)) { - automasking->factor[i] = 1.0f; + PBVHVertRef vertex = BKE_pbvh_index_to_vertex(ss->pbvh, i); + + (*(float *)SCULPT_vertex_attr_get(vertex, ss->attrs.automasking_factor)) = 0.0f; } const int boundary_propagation_steps = brush ? @@ -366,22 +366,21 @@ AutomaskingCache *SCULPT_automasking_cache_init(Sculpt *sd, Brush *brush, Object if (SCULPT_is_automasking_mode_enabled(sd, brush, BRUSH_AUTOMASKING_TOPOLOGY)) { SCULPT_vertex_random_access_ensure(ss); - SCULPT_topology_automasking_init(sd, ob, automasking->factor); + SCULPT_topology_automasking_init(sd, ob); } if (SCULPT_is_automasking_mode_enabled(sd, brush, BRUSH_AUTOMASKING_FACE_SETS)) { SCULPT_vertex_random_access_ensure(ss); - sculpt_face_sets_automasking_init(sd, ob, automasking->factor); + sculpt_face_sets_automasking_init(sd, ob); } if (SCULPT_is_automasking_mode_enabled(sd, brush, BRUSH_AUTOMASKING_BOUNDARY_EDGES)) { SCULPT_vertex_random_access_ensure(ss); - SCULPT_boundary_automasking_init( - ob, AUTOMASK_INIT_BOUNDARY_EDGES, boundary_propagation_steps, automasking->factor); + SCULPT_boundary_automasking_init(ob, AUTOMASK_INIT_BOUNDARY_EDGES, boundary_propagation_steps); } if (SCULPT_is_automasking_mode_enabled(sd, brush, BRUSH_AUTOMASKING_BOUNDARY_FACE_SETS)) { SCULPT_vertex_random_access_ensure(ss); SCULPT_boundary_automasking_init( - ob, AUTOMASK_INIT_BOUNDARY_FACE_SETS, boundary_propagation_steps, automasking->factor); + ob, AUTOMASK_INIT_BOUNDARY_FACE_SETS, boundary_propagation_steps); } return automasking; diff --git a/source/blender/editors/sculpt_paint/sculpt_boundary.c b/source/blender/editors/sculpt_paint/sculpt_boundary.c index 8d08c338b93..005892b88a0 100644 --- a/source/blender/editors/sculpt_paint/sculpt_boundary.c +++ b/source/blender/editors/sculpt_paint/sculpt_boundary.c @@ -128,22 +128,22 @@ static void sculpt_boundary_index_add(SculptBoundary *boundary, const PBVHVertRef new_vertex, const int new_index, const float distance, - GSet *included_vertices) + GSet *included_verts) { - boundary->vertices[boundary->num_vertices] = new_vertex; + boundary->verts[boundary->verts_num] = new_vertex; if (boundary->distance) { boundary->distance[new_index] = distance; } - if (included_vertices) { - BLI_gset_add(included_vertices, POINTER_FROM_INT(new_index)); + if (included_verts) { + BLI_gset_add(included_verts, POINTER_FROM_INT(new_index)); } - boundary->num_vertices++; - if (boundary->num_vertices >= boundary->vertices_capacity) { - boundary->vertices_capacity += BOUNDARY_INDICES_BLOCK_SIZE; - boundary->vertices = MEM_reallocN_id( - boundary->vertices, boundary->vertices_capacity * sizeof(PBVHVertRef), "boundary indices"); + boundary->verts_num++; + if (boundary->verts_num >= boundary->verts_capacity) { + boundary->verts_capacity += BOUNDARY_INDICES_BLOCK_SIZE; + boundary->verts = MEM_reallocN_id( + boundary->verts, boundary->verts_capacity * sizeof(PBVHVertRef), "boundary indices"); } }; @@ -152,11 +152,11 @@ static void sculpt_boundary_preview_edge_add(SculptBoundary *boundary, const PBVHVertRef v2) { - boundary->edges[boundary->num_edges].v1 = v1; - boundary->edges[boundary->num_edges].v2 = v2; - boundary->num_edges++; + boundary->edges[boundary->edges_num].v1 = v1; + boundary->edges[boundary->edges_num].v2 = v2; + boundary->edges_num++; - if (boundary->num_edges >= boundary->edges_capacity) { + if (boundary->edges_num >= boundary->edges_capacity) { boundary->edges_capacity += BOUNDARY_INDICES_BLOCK_SIZE; boundary->edges = MEM_reallocN_id(boundary->edges, boundary->edges_capacity * sizeof(SculptBoundaryPreviewEdge), @@ -209,7 +209,7 @@ static bool sculpt_boundary_is_vertex_in_editable_boundary(SculptSession *ss, typedef struct BoundaryFloodFillData { SculptBoundary *boundary; - GSet *included_vertices; + GSet *included_verts; EdgeSet *preview_edges; PBVHVertRef last_visited_vertex; @@ -233,7 +233,7 @@ static bool boundary_floodfill_cb( boundary->distance[from_v_i] + edge_len : 0.0f; sculpt_boundary_index_add( - boundary, to_v, to_v_i, distance_boundary_to_dst, data->included_vertices); + boundary, to_v, to_v_i, distance_boundary_to_dst, data->included_verts); if (!is_duplicate) { sculpt_boundary_preview_edge_add(boundary, from_v, to_v); } @@ -247,7 +247,7 @@ static void sculpt_boundary_indices_init(SculptSession *ss, { const int totvert = SCULPT_vertex_count_get(ss); - boundary->vertices = MEM_malloc_arrayN( + boundary->verts = MEM_malloc_arrayN( BOUNDARY_INDICES_BLOCK_SIZE, sizeof(PBVHVertRef), "boundary indices"); if (init_boundary_distances) { @@ -256,7 +256,7 @@ static void sculpt_boundary_indices_init(SculptSession *ss, boundary->edges = MEM_malloc_arrayN( BOUNDARY_INDICES_BLOCK_SIZE, sizeof(SculptBoundaryPreviewEdge), "boundary edges"); - GSet *included_vertices = BLI_gset_int_new_ex("included vertices", BOUNDARY_INDICES_BLOCK_SIZE); + GSet *included_verts = BLI_gset_int_new_ex("included verts", BOUNDARY_INDICES_BLOCK_SIZE); SculptFloodFill flood; SCULPT_floodfill_init(ss, &flood); @@ -268,12 +268,12 @@ static void sculpt_boundary_indices_init(SculptSession *ss, copy_v3_v3(boundary->initial_vertex_position, SCULPT_vertex_co_get(ss, boundary->initial_vertex)); sculpt_boundary_index_add( - boundary, initial_boundary_vertex, initial_boundary_index, 0.0f, included_vertices); + boundary, initial_boundary_vertex, initial_boundary_index, 0.0f, included_verts); SCULPT_floodfill_add_initial(&flood, boundary->initial_vertex); BoundaryFloodFillData fdata = { .boundary = boundary, - .included_vertices = included_vertices, + .included_verts = included_verts, .last_visited_vertex = {BOUNDARY_VERTEX_NONE}, }; @@ -286,7 +286,7 @@ static void sculpt_boundary_indices_init(SculptSession *ss, sculpt_boundary_is_vertex_in_editable_boundary(ss, fdata.last_visited_vertex)) { SculptVertexNeighborIter ni; SCULPT_VERTEX_NEIGHBORS_ITER_BEGIN (ss, fdata.last_visited_vertex, ni) { - if (BLI_gset_haskey(included_vertices, POINTER_FROM_INT(ni.index)) && + if (BLI_gset_haskey(included_verts, POINTER_FROM_INT(ni.index)) && sculpt_boundary_is_vertex_in_editable_boundary(ss, ni.vertex)) { sculpt_boundary_preview_edge_add(boundary, fdata.last_visited_vertex, ni.vertex); boundary->forms_loop = true; @@ -295,7 +295,7 @@ static void sculpt_boundary_indices_init(SculptSession *ss, SCULPT_VERTEX_NEIGHBORS_ITER_END(ni); } - BLI_gset_free(included_vertices, NULL); + BLI_gset_free(included_verts, NULL); } /** @@ -318,7 +318,7 @@ static void sculpt_boundary_edit_data_init(SculptSession *ss, for (int i = 0; i < totvert; i++) { boundary->edit_info[i].original_vertex_i = BOUNDARY_VERTEX_NONE; - boundary->edit_info[i].num_propagation_steps = BOUNDARY_STEPS_NONE; + boundary->edit_info[i].propagation_steps_num = BOUNDARY_STEPS_NONE; } GSQueue *current_iteration = BLI_gsqueue_new(sizeof(PBVHVertRef)); @@ -326,38 +326,38 @@ static void sculpt_boundary_edit_data_init(SculptSession *ss, /* Initialized the first iteration with the vertices already in the boundary. This is propagation * step 0. */ - BLI_bitmap *visited_vertices = BLI_BITMAP_NEW(SCULPT_vertex_count_get(ss), "visited_vertices"); - for (int i = 0; i < boundary->num_vertices; i++) { - int index = BKE_pbvh_vertex_to_index(ss->pbvh, boundary->vertices[i]); + BLI_bitmap *visited_verts = BLI_BITMAP_NEW(SCULPT_vertex_count_get(ss), "visited_verts"); + for (int i = 0; i < boundary->verts_num; i++) { + int index = BKE_pbvh_vertex_to_index(ss->pbvh, boundary->verts[i]); boundary->edit_info[index].original_vertex_i = BKE_pbvh_vertex_to_index(ss->pbvh, - boundary->vertices[i]); - boundary->edit_info[index].num_propagation_steps = 0; + boundary->verts[i]); + boundary->edit_info[index].propagation_steps_num = 0; /* This ensures that all duplicate vertices in the boundary have the same original_vertex * index, so the deformation for them will be the same. */ if (has_duplicates) { SculptVertexNeighborIter ni_duplis; - SCULPT_VERTEX_DUPLICATES_AND_NEIGHBORS_ITER_BEGIN (ss, boundary->vertices[i], ni_duplis) { + SCULPT_VERTEX_DUPLICATES_AND_NEIGHBORS_ITER_BEGIN (ss, boundary->verts[i], ni_duplis) { if (ni_duplis.is_duplicate) { boundary->edit_info[ni_duplis.index].original_vertex_i = BKE_pbvh_vertex_to_index( - ss->pbvh, boundary->vertices[i]); + ss->pbvh, boundary->verts[i]); } } SCULPT_VERTEX_NEIGHBORS_ITER_END(ni_duplis); } - BLI_gsqueue_push(current_iteration, &boundary->vertices[i]); + BLI_gsqueue_push(current_iteration, &boundary->verts[i]); } - int num_propagation_steps = 0; + int propagation_steps_num = 0; float accum_distance = 0.0f; while (true) { /* Stop adding steps to edit info. This happens when a steps is further away from the boundary * than the brush radius or when the entire mesh was already processed. */ if (accum_distance > radius || BLI_gsqueue_is_empty(current_iteration)) { - boundary->max_propagation_steps = num_propagation_steps; + boundary->max_propagation_steps = propagation_steps_num; break; } @@ -371,22 +371,22 @@ static void sculpt_boundary_edit_data_init(SculptSession *ss, SCULPT_VERTEX_DUPLICATES_AND_NEIGHBORS_ITER_BEGIN (ss, from_v, ni) { const bool is_visible = SCULPT_vertex_visible_get(ss, ni.vertex); if (!is_visible || - boundary->edit_info[ni.index].num_propagation_steps != BOUNDARY_STEPS_NONE) { + boundary->edit_info[ni.index].propagation_steps_num != BOUNDARY_STEPS_NONE) { continue; } boundary->edit_info[ni.index].original_vertex_i = boundary->edit_info[from_v_i].original_vertex_i; - BLI_BITMAP_ENABLE(visited_vertices, ni.index); + BLI_BITMAP_ENABLE(visited_verts, ni.index); if (ni.is_duplicate) { /* Grids duplicates handling. */ - boundary->edit_info[ni.index].num_propagation_steps = - boundary->edit_info[from_v_i].num_propagation_steps; + boundary->edit_info[ni.index].propagation_steps_num = + boundary->edit_info[from_v_i].propagation_steps_num; } else { - boundary->edit_info[ni.index].num_propagation_steps = - boundary->edit_info[from_v_i].num_propagation_steps + 1; + boundary->edit_info[ni.index].propagation_steps_num = + boundary->edit_info[from_v_i].propagation_steps_num + 1; BLI_gsqueue_push(next_iteration, &ni.vertex); @@ -400,8 +400,8 @@ static void sculpt_boundary_edit_data_init(SculptSession *ss, if (ni_duplis.is_duplicate) { boundary->edit_info[ni_duplis.index].original_vertex_i = boundary->edit_info[from_v_i].original_vertex_i; - boundary->edit_info[ni_duplis.index].num_propagation_steps = - boundary->edit_info[from_v_i].num_propagation_steps + 1; + boundary->edit_info[ni_duplis.index].propagation_steps_num = + boundary->edit_info[from_v_i].propagation_steps_num + 1; } } SCULPT_VERTEX_NEIGHBORS_ITER_END(ni_duplis); @@ -423,15 +423,15 @@ static void sculpt_boundary_edit_data_init(SculptSession *ss, /* Copy the new vertices to the queue to be processed in the next iteration. */ while (!BLI_gsqueue_is_empty(next_iteration)) { - int next_v; + PBVHVertRef next_v; BLI_gsqueue_pop(next_iteration, &next_v); BLI_gsqueue_push(current_iteration, &next_v); } - num_propagation_steps++; + propagation_steps_num++; } - MEM_SAFE_FREE(visited_vertices); + MEM_SAFE_FREE(visited_verts); BLI_gsqueue_free(current_iteration); BLI_gsqueue_free(next_iteration); @@ -449,9 +449,9 @@ static void sculpt_boundary_falloff_factor_init(SculptSession *ss, BKE_curvemapping_init(brush->curve); for (int i = 0; i < totvert; i++) { - if (boundary->edit_info[i].num_propagation_steps != -1) { + if (boundary->edit_info[i].propagation_steps_num != -1) { boundary->edit_info[i].strength_factor = BKE_brush_curve_strength( - brush, boundary->edit_info[i].num_propagation_steps, boundary->max_propagation_steps); + brush, boundary->edit_info[i].propagation_steps_num, boundary->max_propagation_steps); } if (boundary->edit_info[i].original_vertex_i == @@ -542,7 +542,7 @@ SculptBoundary *SCULPT_boundary_data_init(Object *object, void SCULPT_boundary_data_free(SculptBoundary *boundary) { - MEM_SAFE_FREE(boundary->vertices); + MEM_SAFE_FREE(boundary->verts); MEM_SAFE_FREE(boundary->edges); MEM_SAFE_FREE(boundary->distance); MEM_SAFE_FREE(boundary->edit_info); @@ -564,7 +564,7 @@ static void sculpt_boundary_bend_data_init(SculptSession *ss, SculptBoundary *bo boundary->bend.pivot_positions = MEM_calloc_arrayN(totvert, sizeof(float[3]), "pivot positions"); for (int i = 0; i < totvert; i++) { - if (boundary->edit_info[i].num_propagation_steps != boundary->max_propagation_steps) { + if (boundary->edit_info[i].propagation_steps_num != boundary->max_propagation_steps) { continue; } @@ -586,7 +586,7 @@ static void sculpt_boundary_bend_data_init(SculptSession *ss, SculptBoundary *bo } for (int i = 0; i < totvert; i++) { - if (boundary->edit_info[i].num_propagation_steps == BOUNDARY_STEPS_NONE) { + if (boundary->edit_info[i].propagation_steps_num == BOUNDARY_STEPS_NONE) { continue; } copy_v3_v3(boundary->bend.pivot_positions[i], @@ -602,7 +602,7 @@ static void sculpt_boundary_slide_data_init(SculptSession *ss, SculptBoundary *b boundary->slide.directions = MEM_calloc_arrayN(totvert, sizeof(float[3]), "slide directions"); for (int i = 0; i < totvert; i++) { - if (boundary->edit_info[i].num_propagation_steps != boundary->max_propagation_steps) { + if (boundary->edit_info[i].propagation_steps_num != boundary->max_propagation_steps) { continue; } sub_v3_v3v3( @@ -614,7 +614,7 @@ static void sculpt_boundary_slide_data_init(SculptSession *ss, SculptBoundary *b } for (int i = 0; i < totvert; i++) { - if (boundary->edit_info[i].num_propagation_steps == BOUNDARY_STEPS_NONE) { + if (boundary->edit_info[i].propagation_steps_num == BOUNDARY_STEPS_NONE) { continue; } copy_v3_v3(boundary->slide.directions[i], @@ -625,15 +625,14 @@ static void sculpt_boundary_slide_data_init(SculptSession *ss, SculptBoundary *b static void sculpt_boundary_twist_data_init(SculptSession *ss, SculptBoundary *boundary) { zero_v3(boundary->twist.pivot_position); - float(*poly_verts)[3] = MEM_malloc_arrayN( - boundary->num_vertices, sizeof(float[3]), "poly verts"); - for (int i = 0; i < boundary->num_vertices; i++) { - add_v3_v3(boundary->twist.pivot_position, SCULPT_vertex_co_get(ss, boundary->vertices[i])); - copy_v3_v3(poly_verts[i], SCULPT_vertex_co_get(ss, boundary->vertices[i])); + float(*poly_verts)[3] = MEM_malloc_arrayN(boundary->verts_num, sizeof(float[3]), "poly verts"); + for (int i = 0; i < boundary->verts_num; i++) { + add_v3_v3(boundary->twist.pivot_position, SCULPT_vertex_co_get(ss, boundary->verts[i])); + copy_v3_v3(poly_verts[i], SCULPT_vertex_co_get(ss, boundary->verts[i])); } - mul_v3_fl(boundary->twist.pivot_position, 1.0f / boundary->num_vertices); + mul_v3_fl(boundary->twist.pivot_position, 1.0f / boundary->verts_num); if (boundary->forms_loop) { - normal_poly_v3(boundary->twist.rotation_axis, poly_verts, boundary->num_vertices); + normal_poly_v3(boundary->twist.rotation_axis, poly_verts, boundary->verts_num); } else { sub_v3_v3v3(boundary->twist.rotation_axis, @@ -684,7 +683,7 @@ static void do_boundary_brush_bend_task_cb_ex(void *__restrict userdata, const float angle = angle_factor * M_PI; BKE_pbvh_vertex_iter_begin (ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) { - if (boundary->edit_info[vd.index].num_propagation_steps == -1) { + if (boundary->edit_info[vd.index].propagation_steps_num == -1) { continue; } @@ -732,7 +731,7 @@ static void do_boundary_brush_slide_task_cb_ex(void *__restrict userdata, const float disp = sculpt_boundary_displacement_from_grab_delta_get(ss, boundary); BKE_pbvh_vertex_iter_begin (ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) { - if (boundary->edit_info[vd.index].num_propagation_steps == -1) { + if (boundary->edit_info[vd.index].propagation_steps_num == -1) { continue; } @@ -778,7 +777,7 @@ static void do_boundary_brush_inflate_task_cb_ex(void *__restrict userdata, const float disp = sculpt_boundary_displacement_from_grab_delta_get(ss, boundary); BKE_pbvh_vertex_iter_begin (ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) { - if (boundary->edit_info[vd.index].num_propagation_steps == -1) { + if (boundary->edit_info[vd.index].propagation_steps_num == -1) { continue; } @@ -822,7 +821,7 @@ static void do_boundary_brush_grab_task_cb_ex(void *__restrict userdata, SCULPT_orig_vert_data_init(&orig_data, data->ob, data->nodes[n], SCULPT_UNDO_COORDS); BKE_pbvh_vertex_iter_begin (ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) { - if (boundary->edit_info[vd.index].num_propagation_steps == -1) { + if (boundary->edit_info[vd.index].propagation_steps_num == -1) { continue; } @@ -873,7 +872,7 @@ static void do_boundary_brush_twist_task_cb_ex(void *__restrict userdata, const float angle = angle_factor * M_PI; BKE_pbvh_vertex_iter_begin (ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) { - if (boundary->edit_info[vd.index].num_propagation_steps == -1) { + if (boundary->edit_info[vd.index].propagation_steps_num == -1) { continue; } @@ -919,7 +918,7 @@ static void do_boundary_brush_smooth_task_cb_ex(void *__restrict userdata, SCULPT_orig_vert_data_init(&orig_data, data->ob, data->nodes[n], SCULPT_UNDO_COORDS); BKE_pbvh_vertex_iter_begin (ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) { - if (boundary->edit_info[vd.index].num_propagation_steps == -1) { + if (boundary->edit_info[vd.index].propagation_steps_num == -1) { continue; } @@ -931,10 +930,10 @@ static void do_boundary_brush_smooth_task_cb_ex(void *__restrict userdata, float coord_accum[3] = {0.0f, 0.0f, 0.0f}; int total_neighbors = 0; - const int current_propagation_steps = boundary->edit_info[vd.index].num_propagation_steps; + const int current_propagation_steps = boundary->edit_info[vd.index].propagation_steps_num; SculptVertexNeighborIter ni; SCULPT_VERTEX_NEIGHBORS_ITER_BEGIN (ss, vd.vertex, ni) { - if (current_propagation_steps == boundary->edit_info[ni.index].num_propagation_steps) { + if (current_propagation_steps == boundary->edit_info[ni.index].propagation_steps_num) { add_v3_v3(coord_accum, SCULPT_vertex_co_get(ss, ni.vertex)); total_neighbors++; } @@ -1053,8 +1052,8 @@ void SCULPT_boundary_edges_preview_draw(const uint gpuattr, } immUniformColor3fvAlpha(outline_col, outline_alpha); GPU_line_width(2.0f); - immBegin(GPU_PRIM_LINES, ss->boundary_preview->num_edges * 2); - for (int i = 0; i < ss->boundary_preview->num_edges; i++) { + immBegin(GPU_PRIM_LINES, ss->boundary_preview->edges_num * 2); + for (int i = 0; i < ss->boundary_preview->edges_num; i++) { immVertex3fv(gpuattr, SCULPT_vertex_co_get(ss, ss->boundary_preview->edges[i].v1)); immVertex3fv(gpuattr, SCULPT_vertex_co_get(ss, ss->boundary_preview->edges[i].v2)); } diff --git a/source/blender/editors/sculpt_paint/sculpt_brush_types.c b/source/blender/editors/sculpt_paint/sculpt_brush_types.c index 245cbe0f54e..00ad77e48cf 100644 --- a/source/blender/editors/sculpt_paint/sculpt_brush_types.c +++ b/source/blender/editors/sculpt_paint/sculpt_brush_types.c @@ -1472,7 +1472,8 @@ static void do_layer_brush_task_cb_ex(void *__restrict userdata, Sculpt *sd = data->sd; const Brush *brush = data->brush; - const bool use_persistent_base = ss->persistent_base && brush->flag & BRUSH_PERSISTENT; + const bool use_persistent_base = !ss->bm && ss->attrs.persistent_co && + brush->flag & BRUSH_PERSISTENT; PBVHVertexIter vd; SculptOrigVertData orig_data; @@ -1503,7 +1504,7 @@ static void do_layer_brush_task_cb_ex(void *__restrict userdata, const int vi = vd.index; float *disp_factor; if (use_persistent_base) { - disp_factor = &ss->persistent_base[vi].disp; + disp_factor = (float *)SCULPT_vertex_attr_get(vd.vertex, ss->attrs.persistent_disp); } else { disp_factor = &ss->cache->layer_displacement_factor[vi]; diff --git a/source/blender/editors/sculpt_paint/sculpt_cloth.c b/source/blender/editors/sculpt_paint/sculpt_cloth.c index b4b2c4e48c8..b354e2cb182 100644 --- a/source/blender/editors/sculpt_paint/sculpt_cloth.c +++ b/source/blender/editors/sculpt_paint/sculpt_cloth.c @@ -617,10 +617,11 @@ static void do_cloth_brush_apply_forces_task_cb_ex(void *__restrict userdata, static ListBase *cloth_brush_collider_cache_create(Object *object, Depsgraph *depsgraph) { ListBase *cache = NULL; - DEG_OBJECT_ITER_BEGIN (depsgraph, - ob, - DEG_ITER_OBJECT_FLAG_LINKED_DIRECTLY | DEG_ITER_OBJECT_FLAG_VISIBLE | - DEG_ITER_OBJECT_FLAG_DUPLI) { + DEGObjectIterSettings deg_iter_settings = {0}; + deg_iter_settings.depsgraph = depsgraph; + deg_iter_settings.flags = DEG_ITER_OBJECT_FLAG_LINKED_DIRECTLY | DEG_ITER_OBJECT_FLAG_VISIBLE | + DEG_ITER_OBJECT_FLAG_DUPLI; + DEG_OBJECT_ITER_BEGIN (°_iter_settings, ob) { if (STREQ(object->id.name, ob->id.name)) { continue; } @@ -1579,7 +1580,7 @@ static int sculpt_cloth_filter_invoke(bContext *C, wmOperator *op, const wmEvent /* Needs mask data to be available as it is used when solving the constraints. */ BKE_sculpt_update_object_for_edit(depsgraph, ob, true, true, false); - SCULPT_undo_push_begin(ob, "Cloth filter"); + SCULPT_undo_push_begin(ob, op); SCULPT_filter_cache_init(C, ob, sd, SCULPT_UNDO_COORDS); ss->filter_cache->automasking = SCULPT_automasking_cache_init(sd, NULL, ob); diff --git a/source/blender/editors/sculpt_paint/sculpt_detail.c b/source/blender/editors/sculpt_paint/sculpt_detail.c index ebbb0fa429e..8f87cd1b6ed 100644 --- a/source/blender/editors/sculpt_paint/sculpt_detail.c +++ b/source/blender/editors/sculpt_paint/sculpt_detail.c @@ -76,7 +76,7 @@ static bool sculpt_and_dynamic_topology_poll(bContext *C) /** \name Detail Flood Fill * \{ */ -static int sculpt_detail_flood_fill_exec(bContext *C, wmOperator *UNUSED(op)) +static int sculpt_detail_flood_fill_exec(bContext *C, wmOperator *op) { Sculpt *sd = CTX_data_tool_settings(C)->sculpt; Object *ob = CTX_data_active_object(C); @@ -106,7 +106,7 @@ static int sculpt_detail_flood_fill_exec(bContext *C, wmOperator *UNUSED(op)) float object_space_constant_detail = 1.0f / (sd->constant_detail * mat4_to_scale(ob->obmat)); BKE_pbvh_bmesh_detail_size_set(ss->pbvh, object_space_constant_detail); - SCULPT_undo_push_begin(ob, "Dynamic topology flood fill"); + SCULPT_undo_push_begin(ob, op); SCULPT_undo_push_node(ob, NULL, SCULPT_UNDO_COORDS); while (BKE_pbvh_bmesh_update_topology( diff --git a/source/blender/editors/sculpt_paint/sculpt_dyntopo.c b/source/blender/editors/sculpt_paint/sculpt_dyntopo.c index 40b4b74a441..2e3834803c9 100644 --- a/source/blender/editors/sculpt_paint/sculpt_dyntopo.c +++ b/source/blender/editors/sculpt_paint/sculpt_dyntopo.c @@ -88,45 +88,6 @@ void SCULPT_pbvh_clear(Object *ob) DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY); } -void SCULPT_dyntopo_node_layers_add(SculptSession *ss) -{ - int cd_node_layer_index; - - char node_vertex_id[] = "_dyntopo_vnode_id"; - char node_face_id[] = "_dyntopo_fnode_id"; - - cd_node_layer_index = CustomData_get_named_layer_index( - &ss->bm->vdata, CD_PROP_INT32, node_vertex_id); - - if (cd_node_layer_index == -1) { - BM_data_layer_add_named(ss->bm, &ss->bm->vdata, CD_PROP_INT32, node_vertex_id); - cd_node_layer_index = CustomData_get_named_layer_index( - &ss->bm->vdata, CD_PROP_INT32, node_vertex_id); - } - - ss->cd_vert_node_offset = CustomData_get_n_offset( - &ss->bm->vdata, - CD_PROP_INT32, - cd_node_layer_index - CustomData_get_layer_index(&ss->bm->vdata, CD_PROP_INT32)); - - ss->bm->vdata.layers[cd_node_layer_index].flag |= CD_FLAG_TEMPORARY; - - cd_node_layer_index = CustomData_get_named_layer_index( - &ss->bm->pdata, CD_PROP_INT32, node_face_id); - if (cd_node_layer_index == -1) { - BM_data_layer_add_named(ss->bm, &ss->bm->pdata, CD_PROP_INT32, node_face_id); - cd_node_layer_index = CustomData_get_named_layer_index( - &ss->bm->pdata, CD_PROP_INT32, node_face_id); - } - - ss->cd_face_node_offset = CustomData_get_n_offset( - &ss->bm->pdata, - CD_PROP_INT32, - cd_node_layer_index - CustomData_get_layer_index(&ss->bm->pdata, CD_PROP_INT32)); - - ss->bm->pdata.layers[cd_node_layer_index].flag |= CD_FLAG_TEMPORARY; -} - void SCULPT_dynamic_topology_enable_ex(Main *bmain, Depsgraph *depsgraph, Scene *scene, Object *ob) { SculptSession *ss = ob->sculpt; @@ -156,8 +117,9 @@ void SCULPT_dynamic_topology_enable_ex(Main *bmain, Depsgraph *depsgraph, Scene .active_shapekey = ob->shapenr, })); SCULPT_dynamic_topology_triangulate(ss->bm); + BM_data_layer_add(ss->bm, &ss->bm->vdata, CD_PAINT_MASK); - SCULPT_dyntopo_node_layers_add(ss); + /* Make sure the data for existing faces are initialized. */ if (me->totpoly != ss->bm->totface) { BM_mesh_normals_update(ss->bm); @@ -185,6 +147,9 @@ static void SCULPT_dynamic_topology_disable_ex( SculptSession *ss = ob->sculpt; Mesh *me = ob->data; + BKE_sculpt_attribute_destroy(ob, ss->attrs.dyntopo_node_id_vertex); + BKE_sculpt_attribute_destroy(ob, ss->attrs.dyntopo_node_id_face); + SCULPT_pbvh_clear(ob); if (unode) { @@ -210,20 +175,12 @@ static void SCULPT_dynamic_topology_disable_ex( &geometry->ldata, &me->ldata, CD_MASK_MESH.lmask, CD_DUPLICATE, geometry->totloop); CustomData_copy( &geometry->pdata, &me->pdata, CD_MASK_MESH.pmask, CD_DUPLICATE, geometry->totpoly); - - BKE_mesh_update_customdata_pointers(me, false); } else { BKE_sculptsession_bm_to_me(ob, true); /* Reset Face Sets as they are no longer valid. */ - if (!CustomData_has_layer(&me->pdata, CD_SCULPT_FACE_SETS)) { - CustomData_add_layer(&me->pdata, CD_SCULPT_FACE_SETS, CD_CALLOC, NULL, me->totpoly); - } - ss->face_sets = CustomData_get_layer(&me->pdata, CD_SCULPT_FACE_SETS); - for (int i = 0; i < me->totpoly; i++) { - ss->face_sets[i] = 1; - } + CustomData_free_layer_named(&me->pdata, ".sculpt_face_set", me->totpoly); me->face_sets_color_default = 1; /* Sync the visibility to vertices manually as the pmap is still not initialized. */ @@ -274,7 +231,7 @@ void sculpt_dynamic_topology_disable_with_undo(Main *bmain, /* May be false in background mode. */ const bool use_undo = G.background ? (ED_undo_stack_get() != NULL) : true; if (use_undo) { - SCULPT_undo_push_begin(ob, "Dynamic topology disable"); + SCULPT_undo_push_begin_ex(ob, "Dynamic topology disable"); SCULPT_undo_push_node(ob, NULL, SCULPT_UNDO_DYNTOPO_END); } SCULPT_dynamic_topology_disable_ex(bmain, depsgraph, scene, ob, NULL); @@ -294,7 +251,7 @@ static void sculpt_dynamic_topology_enable_with_undo(Main *bmain, /* May be false in background mode. */ const bool use_undo = G.background ? (ED_undo_stack_get() != NULL) : true; if (use_undo) { - SCULPT_undo_push_begin(ob, "Dynamic topology enable"); + SCULPT_undo_push_begin_ex(ob, "Dynamic topology enable"); } SCULPT_dynamic_topology_enable_ex(bmain, depsgraph, scene, ob); if (use_undo) { diff --git a/source/blender/editors/sculpt_paint/sculpt_expand.c b/source/blender/editors/sculpt_paint/sculpt_expand.c index dd1c7a36c16..72b0b3a97fe 100644 --- a/source/blender/editors/sculpt_paint/sculpt_expand.c +++ b/source/blender/editors/sculpt_paint/sculpt_expand.c @@ -17,6 +17,7 @@ #include "DNA_brush_types.h" #include "DNA_mesh_types.h" #include "DNA_meshdata_types.h" +#include "DNA_modifier_types.h" #include "DNA_object_types.h" #include "BKE_brush.h" @@ -351,13 +352,13 @@ static float sculpt_expand_gradient_value_get(SculptSession *ss, static BLI_bitmap *sculpt_expand_bitmap_from_enabled(SculptSession *ss, ExpandCache *expand_cache) { const int totvert = SCULPT_vertex_count_get(ss); - BLI_bitmap *enabled_vertices = BLI_BITMAP_NEW(totvert, "enabled vertices"); + BLI_bitmap *enabled_verts = BLI_BITMAP_NEW(totvert, "enabled verts"); for (int i = 0; i < totvert; i++) { const bool enabled = sculpt_expand_state_get( ss, expand_cache, BKE_pbvh_index_to_vertex(ss->pbvh, i)); - BLI_BITMAP_SET(enabled_vertices, i, enabled); + BLI_BITMAP_SET(enabled_verts, i, enabled); } - return enabled_vertices; + return enabled_verts; } /** @@ -366,13 +367,13 @@ static BLI_bitmap *sculpt_expand_bitmap_from_enabled(SculptSession *ss, ExpandCa * vertex that is not enabled. */ static BLI_bitmap *sculpt_expand_boundary_from_enabled(SculptSession *ss, - const BLI_bitmap *enabled_vertices, + const BLI_bitmap *enabled_verts, const bool use_mesh_boundary) { const int totvert = SCULPT_vertex_count_get(ss); - BLI_bitmap *boundary_vertices = BLI_BITMAP_NEW(totvert, "boundary vertices"); + BLI_bitmap *boundary_verts = BLI_BITMAP_NEW(totvert, "boundary verts"); for (int i = 0; i < totvert; i++) { - if (!BLI_BITMAP_TEST(enabled_vertices, i)) { + if (!BLI_BITMAP_TEST(enabled_verts, i)) { continue; } @@ -381,7 +382,7 @@ static BLI_bitmap *sculpt_expand_boundary_from_enabled(SculptSession *ss, bool is_expand_boundary = false; SculptVertexNeighborIter ni; SCULPT_VERTEX_NEIGHBORS_ITER_BEGIN (ss, vertex, ni) { - if (!BLI_BITMAP_TEST(enabled_vertices, ni.index)) { + if (!BLI_BITMAP_TEST(enabled_verts, ni.index)) { is_expand_boundary = true; } } @@ -391,10 +392,10 @@ static BLI_bitmap *sculpt_expand_boundary_from_enabled(SculptSession *ss, is_expand_boundary = true; } - BLI_BITMAP_SET(boundary_vertices, i, is_expand_boundary); + BLI_BITMAP_SET(boundary_verts, i, is_expand_boundary); } - return boundary_vertices; + return boundary_verts; } /* Functions implementing different algorithms for initializing falloff values. */ @@ -596,7 +597,7 @@ static float *sculpt_expand_boundary_topology_falloff_create(Object *ob, const P SculptSession *ss = ob->sculpt; const int totvert = SCULPT_vertex_count_get(ss); float *dists = MEM_calloc_arrayN(totvert, sizeof(float), "spherical dist"); - BLI_bitmap *visited_vertices = BLI_BITMAP_NEW(totvert, "visited vertices"); + BLI_bitmap *visited_verts = BLI_BITMAP_NEW(totvert, "visited verts"); GSQueue *queue = BLI_gsqueue_new(sizeof(PBVHVertRef)); /* Search and initialize a boundary per symmetry pass, then mark those vertices as visited. */ @@ -614,9 +615,9 @@ static float *sculpt_expand_boundary_topology_falloff_create(Object *ob, const P continue; } - for (int i = 0; i < boundary->num_vertices; i++) { - BLI_gsqueue_push(queue, &boundary->vertices[i]); - BLI_BITMAP_ENABLE(visited_vertices, boundary->vertices_i[i]); + for (int i = 0; i < boundary->verts_num; i++) { + BLI_gsqueue_push(queue, &boundary->verts[i]); + BLI_BITMAP_ENABLE(visited_verts, BKE_pbvh_vertex_to_index(ss->pbvh, boundary->verts[i])); } SCULPT_boundary_data_free(boundary); } @@ -635,18 +636,18 @@ static float *sculpt_expand_boundary_topology_falloff_create(Object *ob, const P SculptVertexNeighborIter ni; SCULPT_VERTEX_NEIGHBORS_ITER_BEGIN (ss, v_next, ni) { - if (BLI_BITMAP_TEST(visited_vertices, ni.index)) { + if (BLI_BITMAP_TEST(visited_verts, ni.index)) { continue; } dists[ni.index] = dists[v_next_i] + 1.0f; - BLI_BITMAP_ENABLE(visited_vertices, ni.index); + BLI_BITMAP_ENABLE(visited_verts, ni.index); BLI_gsqueue_push(queue, &ni.vertex); } SCULPT_VERTEX_NEIGHBORS_ITER_END(ni); } BLI_gsqueue_free(queue); - MEM_freeN(visited_vertices); + MEM_freeN(visited_verts); return dists; } @@ -669,7 +670,7 @@ static float *sculpt_expand_diagonals_falloff_create(Object *ob, const PBVHVertR } /* Search and mask as visited the initial vertices using the enabled symmetry passes. */ - BLI_bitmap *visited_vertices = BLI_BITMAP_NEW(totvert, "visited vertices"); + BLI_bitmap *visited_verts = BLI_BITMAP_NEW(totvert, "visited verts"); GSQueue *queue = BLI_gsqueue_new(sizeof(PBVHVertRef)); const char symm = SCULPT_mesh_symmetry_xyz_get(ob); for (char symm_it = 0; symm_it <= symm; symm_it++) { @@ -682,7 +683,7 @@ static float *sculpt_expand_diagonals_falloff_create(Object *ob, const PBVHVertR int symm_vertex_i = BKE_pbvh_vertex_to_index(ss->pbvh, symm_vertex); BLI_gsqueue_push(queue, &symm_vertex); - BLI_BITMAP_ENABLE(visited_vertices, symm_vertex_i); + BLI_BITMAP_ENABLE(visited_verts, symm_vertex_i); } if (BLI_gsqueue_is_empty(queue)) { @@ -690,7 +691,6 @@ static float *sculpt_expand_diagonals_falloff_create(Object *ob, const PBVHVertR } /* Propagate the falloff increasing the value by 1 each time a new vertex is visited. */ - Mesh *mesh = ob->data; while (!BLI_gsqueue_is_empty(queue)) { PBVHVertRef v_next; BLI_gsqueue_pop(queue, &v_next); @@ -698,21 +698,21 @@ static float *sculpt_expand_diagonals_falloff_create(Object *ob, const PBVHVertR int v_next_i = BKE_pbvh_vertex_to_index(ss->pbvh, v_next); for (int j = 0; j < ss->pmap[v_next_i].count; j++) { - MPoly *p = &ss->mpoly[ss->pmap[v_next_i].indices[j]]; + const MPoly *p = &ss->mpoly[ss->pmap[v_next_i].indices[j]]; for (int l = 0; l < p->totloop; l++) { - const PBVHVertRef neighbor_v = BKE_pbvh_make_vref(mesh->mloop[p->loopstart + l].v); - if (BLI_BITMAP_TEST(visited_vertices, neighbor_v.i)) { + const PBVHVertRef neighbor_v = BKE_pbvh_make_vref(ss->mloop[p->loopstart + l].v); + if (BLI_BITMAP_TEST(visited_verts, neighbor_v.i)) { continue; } dists[neighbor_v.i] = dists[v_next_i] + 1.0f; - BLI_BITMAP_ENABLE(visited_vertices, neighbor_v.i); + BLI_BITMAP_ENABLE(visited_verts, neighbor_v.i); BLI_gsqueue_push(queue, &neighbor_v); } } } BLI_gsqueue_free(queue); - MEM_freeN(visited_vertices); + MEM_freeN(visited_verts); return dists; } @@ -777,11 +777,11 @@ static void sculpt_expand_grids_to_faces_falloff(SculptSession *ss, Mesh *mesh, ExpandCache *expand_cache) { - + const MPoly *polys = BKE_mesh_polys(mesh); const CCGKey *key = BKE_pbvh_get_grid_key(ss->pbvh); for (int p = 0; p < mesh->totpoly; p++) { - MPoly *poly = &mesh->mpoly[p]; + const MPoly *poly = &polys[p]; float accum = 0.0f; for (int l = 0; l < poly->totloop; l++) { const int grid_loop_index = (poly->loopstart + l) * key->grid_area; @@ -795,11 +795,14 @@ static void sculpt_expand_grids_to_faces_falloff(SculptSession *ss, static void sculpt_expand_vertex_to_faces_falloff(Mesh *mesh, ExpandCache *expand_cache) { + const MPoly *polys = BKE_mesh_polys(mesh); + const MLoop *loops = BKE_mesh_loops(mesh); + for (int p = 0; p < mesh->totpoly; p++) { - MPoly *poly = &mesh->mpoly[p]; + const MPoly *poly = &polys[p]; float accum = 0.0f; for (int l = 0; l < poly->totloop; l++) { - MLoop *loop = &mesh->mloop[l + poly->loopstart]; + const MLoop *loop = &loops[l + poly->loopstart]; accum += expand_cache->vert_falloff[loop->v]; } expand_cache->face_falloff[p] = accum / poly->totloop; @@ -840,27 +843,27 @@ static void sculpt_expand_mesh_face_falloff_from_vertex_falloff(SculptSession *s */ static void sculpt_expand_geodesics_from_state_boundary(Object *ob, ExpandCache *expand_cache, - BLI_bitmap *enabled_vertices) + BLI_bitmap *enabled_verts) { SculptSession *ss = ob->sculpt; BLI_assert(BKE_pbvh_type(ss->pbvh) == PBVH_FACES); - GSet *initial_vertices = BLI_gset_int_new("initial_vertices"); - BLI_bitmap *boundary_vertices = sculpt_expand_boundary_from_enabled(ss, enabled_vertices, false); + GSet *initial_verts = BLI_gset_int_new("initial_verts"); + BLI_bitmap *boundary_verts = sculpt_expand_boundary_from_enabled(ss, enabled_verts, false); const int totvert = SCULPT_vertex_count_get(ss); for (int i = 0; i < totvert; i++) { - if (!BLI_BITMAP_TEST(boundary_vertices, i)) { + if (!BLI_BITMAP_TEST(boundary_verts, i)) { continue; } - BLI_gset_add(initial_vertices, POINTER_FROM_INT(i)); + BLI_gset_add(initial_verts, POINTER_FROM_INT(i)); } - MEM_freeN(boundary_vertices); + MEM_freeN(boundary_verts); MEM_SAFE_FREE(expand_cache->vert_falloff); MEM_SAFE_FREE(expand_cache->face_falloff); - expand_cache->vert_falloff = SCULPT_geodesic_distances_create(ob, initial_vertices, FLT_MAX); - BLI_gset_free(initial_vertices, NULL); + expand_cache->vert_falloff = SCULPT_geodesic_distances_create(ob, initial_verts, FLT_MAX); + BLI_gset_free(initial_verts, NULL); } /** @@ -869,7 +872,7 @@ static void sculpt_expand_geodesics_from_state_boundary(Object *ob, */ static void sculpt_expand_topology_from_state_boundary(Object *ob, ExpandCache *expand_cache, - BLI_bitmap *enabled_vertices) + BLI_bitmap *enabled_verts) { MEM_SAFE_FREE(expand_cache->vert_falloff); MEM_SAFE_FREE(expand_cache->face_falloff); @@ -878,19 +881,19 @@ static void sculpt_expand_topology_from_state_boundary(Object *ob, const int totvert = SCULPT_vertex_count_get(ss); float *dists = MEM_calloc_arrayN(totvert, sizeof(float), "topology dist"); - BLI_bitmap *boundary_vertices = sculpt_expand_boundary_from_enabled(ss, enabled_vertices, false); + BLI_bitmap *boundary_verts = sculpt_expand_boundary_from_enabled(ss, enabled_verts, false); SculptFloodFill flood; SCULPT_floodfill_init(ss, &flood); for (int i = 0; i < totvert; i++) { - if (!BLI_BITMAP_TEST(boundary_vertices, i)) { + if (!BLI_BITMAP_TEST(boundary_verts, i)) { continue; } PBVHVertRef vertex = BKE_pbvh_index_to_vertex(ss->pbvh, i); SCULPT_floodfill_add_and_skip_initial(&flood, vertex); } - MEM_freeN(boundary_vertices); + MEM_freeN(boundary_verts); ExpandFloodFillData fdata; fdata.dists = dists; @@ -912,7 +915,7 @@ static void sculpt_expand_resursion_step_add(Object *ob, return; } - BLI_bitmap *enabled_vertices = sculpt_expand_bitmap_from_enabled(ss, expand_cache); + BLI_bitmap *enabled_verts = sculpt_expand_bitmap_from_enabled(ss, expand_cache); /* Each time a new recursion step is created, reset the distortion strength. This is the expected * result from the recursion, as otherwise the new falloff will render with undesired distortion @@ -921,10 +924,10 @@ static void sculpt_expand_resursion_step_add(Object *ob, switch (recursion_type) { case SCULPT_EXPAND_RECURSION_GEODESICS: - sculpt_expand_geodesics_from_state_boundary(ob, expand_cache, enabled_vertices); + sculpt_expand_geodesics_from_state_boundary(ob, expand_cache, enabled_verts); break; case SCULPT_EXPAND_RECURSION_TOPOLOGY: - sculpt_expand_topology_from_state_boundary(ob, expand_cache, enabled_vertices); + sculpt_expand_topology_from_state_boundary(ob, expand_cache, enabled_verts); break; } @@ -934,7 +937,7 @@ static void sculpt_expand_resursion_step_add(Object *ob, sculpt_expand_update_max_face_falloff_factor(ss, expand_cache); } - MEM_freeN(enabled_vertices); + MEM_freeN(enabled_verts); } /* Face Set Boundary falloff. */ @@ -951,7 +954,7 @@ static void sculpt_expand_initialize_from_face_set_boundary(Object *ob, SculptSession *ss = ob->sculpt; const int totvert = SCULPT_vertex_count_get(ss); - BLI_bitmap *enabled_vertices = BLI_BITMAP_NEW(totvert, "enabled vertices"); + BLI_bitmap *enabled_verts = BLI_BITMAP_NEW(totvert, "enabled verts"); for (int i = 0; i < totvert; i++) { PBVHVertRef vertex = BKE_pbvh_index_to_vertex(ss->pbvh, i); @@ -961,17 +964,17 @@ static void sculpt_expand_initialize_from_face_set_boundary(Object *ob, if (!SCULPT_vertex_has_face_set(ss, vertex, active_face_set)) { continue; } - BLI_BITMAP_ENABLE(enabled_vertices, i); + BLI_BITMAP_ENABLE(enabled_verts, i); } if (BKE_pbvh_type(ss->pbvh) == PBVH_FACES) { - sculpt_expand_geodesics_from_state_boundary(ob, expand_cache, enabled_vertices); + sculpt_expand_geodesics_from_state_boundary(ob, expand_cache, enabled_verts); } else { - sculpt_expand_topology_from_state_boundary(ob, expand_cache, enabled_vertices); + sculpt_expand_topology_from_state_boundary(ob, expand_cache, enabled_verts); } - MEM_freeN(enabled_vertices); + MEM_freeN(enabled_verts); if (internal_falloff) { for (int i = 0; i < totvert; i++) { @@ -1084,7 +1087,7 @@ static void sculpt_expand_snap_initialize_from_enabled(SculptSession *ss, expand_cache->snap = false; expand_cache->invert = false; - BLI_bitmap *enabled_vertices = sculpt_expand_bitmap_from_enabled(ss, expand_cache); + BLI_bitmap *enabled_verts = sculpt_expand_bitmap_from_enabled(ss, expand_cache); const int totface = ss->totfaces; for (int i = 0; i < totface; i++) { @@ -1093,11 +1096,11 @@ static void sculpt_expand_snap_initialize_from_enabled(SculptSession *ss, } for (int p = 0; p < totface; p++) { - MPoly *poly = &ss->mpoly[p]; + const MPoly *poly = &ss->mpoly[p]; bool any_disabled = false; for (int l = 0; l < poly->totloop; l++) { - MLoop *loop = &ss->mloop[l + poly->loopstart]; - if (!BLI_BITMAP_TEST(enabled_vertices, loop->v)) { + const MLoop *loop = &ss->mloop[l + poly->loopstart]; + if (!BLI_BITMAP_TEST(enabled_verts, loop->v)) { any_disabled = true; break; } @@ -1108,7 +1111,7 @@ static void sculpt_expand_snap_initialize_from_enabled(SculptSession *ss, } } - MEM_freeN(enabled_vertices); + MEM_freeN(enabled_verts); expand_cache->snap = prev_snap_state; expand_cache->invert = prev_invert_state; } @@ -1388,9 +1391,15 @@ static void sculpt_expand_original_state_store(Object *ob, ExpandCache *expand_c /* Face Sets are always stored as they are needed for snapping. */ expand_cache->initial_face_sets = MEM_malloc_arrayN(totface, sizeof(int), "initial face set"); expand_cache->original_face_sets = MEM_malloc_arrayN(totface, sizeof(int), "original face set"); - for (int i = 0; i < totface; i++) { - expand_cache->initial_face_sets[i] = ss->face_sets[i]; - expand_cache->original_face_sets[i] = ss->face_sets[i]; + if (ss->face_sets) { + for (int i = 0; i < totface; i++) { + expand_cache->initial_face_sets[i] = ss->face_sets[i]; + expand_cache->original_face_sets[i] = ss->face_sets[i]; + } + } + else { + memset(expand_cache->initial_face_sets, SCULPT_FACE_SET_NONE, sizeof(int) * totface); + memset(expand_cache->original_face_sets, SCULPT_FACE_SET_NONE, sizeof(int) * totface); } if (expand_cache->target == SCULPT_EXPAND_TARGET_MASK) { @@ -1512,7 +1521,7 @@ static void sculpt_expand_reposition_pivot(bContext *C, Object *ob, ExpandCache const bool initial_invert_state = expand_cache->invert; expand_cache->invert = false; - BLI_bitmap *enabled_vertices = sculpt_expand_bitmap_from_enabled(ss, expand_cache); + BLI_bitmap *enabled_verts = sculpt_expand_bitmap_from_enabled(ss, expand_cache); /* For boundary topology, position the pivot using only the boundary of the enabled vertices, * without taking mesh boundary into account. This allows to create deformations like bending the @@ -1520,8 +1529,8 @@ static void sculpt_expand_reposition_pivot(bContext *C, Object *ob, ExpandCache const float use_mesh_boundary = expand_cache->falloff_type != SCULPT_EXPAND_FALLOFF_BOUNDARY_TOPOLOGY; - BLI_bitmap *boundary_vertices = sculpt_expand_boundary_from_enabled( - ss, enabled_vertices, use_mesh_boundary); + BLI_bitmap *boundary_verts = sculpt_expand_boundary_from_enabled( + ss, enabled_verts, use_mesh_boundary); /* Ignore invert state, as this is the expected behavior in most cases and mask are created in * inverted state by default. */ @@ -1535,7 +1544,7 @@ static void sculpt_expand_reposition_pivot(bContext *C, Object *ob, ExpandCache for (int i = 0; i < totvert; i++) { PBVHVertRef vertex = BKE_pbvh_index_to_vertex(ss->pbvh, i); - if (!BLI_BITMAP_TEST(boundary_vertices, i)) { + if (!BLI_BITMAP_TEST(boundary_verts, i)) { continue; } @@ -1553,8 +1562,8 @@ static void sculpt_expand_reposition_pivot(bContext *C, Object *ob, ExpandCache total++; } - MEM_freeN(enabled_vertices); - MEM_freeN(boundary_vertices); + MEM_freeN(enabled_verts); + MEM_freeN(boundary_verts); if (total > 0) { mul_v3_v3fl(ss->pivot_pos, avg, 1.0f / total); @@ -1938,6 +1947,8 @@ static void sculpt_expand_delete_face_set_id(int *r_face_sets, { const int totface = ss->totfaces; MeshElemMap *pmap = ss->pmap; + const MPoly *polys = BKE_mesh_polys(mesh); + const MLoop *loops = BKE_mesh_loops(mesh); /* Check that all the face sets IDs in the mesh are not equal to `delete_id` * before attempting to delete it. */ @@ -1972,9 +1983,9 @@ static void sculpt_expand_delete_face_set_id(int *r_face_sets, while (BLI_LINKSTACK_SIZE(queue)) { const int f_index = POINTER_AS_INT(BLI_LINKSTACK_POP(queue)); int other_id = delete_id; - const MPoly *c_poly = &mesh->mpoly[f_index]; + const MPoly *c_poly = &polys[f_index]; for (int l = 0; l < c_poly->totloop; l++) { - const MLoop *c_loop = &mesh->mloop[c_poly->loopstart + l]; + const MLoop *c_loop = &loops[c_poly->loopstart + l]; const MeshElemMap *vert_map = &pmap[c_loop->v]; for (int i = 0; i < vert_map->count; i++) { @@ -2114,6 +2125,16 @@ static int sculpt_expand_invoke(bContext *C, wmOperator *op, const wmEvent *even return OPERATOR_CANCELLED; } + if (ss->expand_cache->target == SCULPT_EXPAND_TARGET_FACE_SETS) { + Mesh *mesh = ob->data; + ss->face_sets = BKE_sculpt_face_sets_ensure(mesh); + } + + if (ss->expand_cache->target == SCULPT_EXPAND_TARGET_MASK) { + MultiresModifierData *mmd = BKE_sculpt_multires_active(ss->scene, ob); + BKE_sculpt_mask_layers_ensure(ob, mmd); + } + /* Face Set operations are not supported in dyntopo. */ if (ss->expand_cache->target == SCULPT_EXPAND_TARGET_FACE_SETS && BKE_pbvh_type(ss->pbvh) == PBVH_BMESH) { @@ -2124,7 +2145,7 @@ static int sculpt_expand_invoke(bContext *C, wmOperator *op, const wmEvent *even sculpt_expand_ensure_sculptsession_data(ob); /* Initialize undo. */ - SCULPT_undo_push_begin(ob, "expand"); + SCULPT_undo_push_begin(ob, op); sculpt_expand_undo_push(ob, ss->expand_cache); /* Set the initial element for expand from the event position. */ @@ -2223,7 +2244,7 @@ void sculpt_expand_modal_keymap(wmKeyConfig *keyconf) static const char *name = "Sculpt Expand Modal"; wmKeyMap *keymap = WM_modalkeymap_find(keyconf, name); - /* This function is called for each spacetype, only needs to add map once. */ + /* This function is called for each space-type, only needs to add map once. */ if (keymap && keymap->modal_items) { return; } diff --git a/source/blender/editors/sculpt_paint/sculpt_face_set.c b/source/blender/editors/sculpt_paint/sculpt_face_set.cc index f045ba841f3..473caa18050 100644 --- a/source/blender/editors/sculpt_paint/sculpt_face_set.c +++ b/source/blender/editors/sculpt_paint/sculpt_face_set.cc @@ -5,11 +5,18 @@ * \ingroup edsculpt */ +#include <cmath> +#include <cstdlib> +#include <queue> + #include "MEM_guardedalloc.h" -#include "BLI_blenlib.h" +#include "BLI_bit_vector.hh" +#include "BLI_function_ref.hh" #include "BLI_hash.h" #include "BLI_math.h" +#include "BLI_math_vector.hh" +#include "BLI_span.hh" #include "BLI_task.h" #include "DNA_brush_types.h" @@ -19,6 +26,7 @@ #include "DNA_object_types.h" #include "DNA_scene_types.h" +#include "BKE_attribute.hh" #include "BKE_brush.h" #include "BKE_ccg.h" #include "BKE_colortools.h" @@ -53,21 +61,19 @@ #include "bmesh.h" -#include <math.h> -#include <stdlib.h> - /* Utils. */ int ED_sculpt_face_sets_find_next_available_id(struct Mesh *mesh) { - const int *face_sets = CustomData_get_layer(&mesh->pdata, CD_SCULPT_FACE_SETS); + const int *face_sets = static_cast<const int *>( + CustomData_get_layer_named(&mesh->pdata, CD_PROP_INT32, ".sculpt_face_set")); if (!face_sets) { return SCULPT_FACE_SET_NONE; } int next_face_set_id = 0; for (int i = 0; i < mesh->totpoly; i++) { - next_face_set_id = max_ii(next_face_set_id, abs(face_sets[i])); + next_face_set_id = max_ii(next_face_set_id, face_sets[i]); } next_face_set_id++; @@ -76,7 +82,8 @@ int ED_sculpt_face_sets_find_next_available_id(struct Mesh *mesh) void ED_sculpt_face_sets_initialize_none_to_id(struct Mesh *mesh, const int new_id) { - int *face_sets = CustomData_get_layer(&mesh->pdata, CD_SCULPT_FACE_SETS); + int *face_sets = static_cast<int *>( + CustomData_get_layer_named(&mesh->pdata, CD_PROP_INT32, ".sculpt_face_set")); if (!face_sets) { return; } @@ -109,7 +116,7 @@ static void do_draw_face_sets_brush_task_cb_ex(void *__restrict userdata, const int n, const TaskParallelTLS *__restrict tls) { - SculptThreadedTaskData *data = userdata; + SculptThreadedTaskData *data = static_cast<SculptThreadedTaskData *>(userdata); SculptSession *ss = data->ob->sculpt; const Brush *brush = data->brush; const float bstrength = ss->cache->bstrength; @@ -135,6 +142,10 @@ static void do_draw_face_sets_brush_task_cb_ex(void *__restrict userdata, if (!sculpt_brush_test_sq_fn(&test, poly_center)) { continue; } + const bool face_hidden = ss->hide_poly && ss->hide_poly[vert_map->indices[j]]; + if (face_hidden) { + continue; + } const float fade = bstrength * SCULPT_brush_strength_factor(ss, brush, vd.co, @@ -145,8 +156,8 @@ static void do_draw_face_sets_brush_task_cb_ex(void *__restrict userdata, vd.vertex, thread_id); - if (fade > 0.05f && ss->face_sets[vert_map->indices[j]] > 0) { - ss->face_sets[vert_map->indices[j]] = abs(ss->cache->paint_face_set); + if (fade > 0.05f) { + ss->face_sets[vert_map->indices[j]] = ss->cache->paint_face_set; } } } @@ -176,7 +187,7 @@ static void do_relax_face_sets_brush_task_cb_ex(void *__restrict userdata, const int n, const TaskParallelTLS *__restrict tls) { - SculptThreadedTaskData *data = userdata; + SculptThreadedTaskData *data = static_cast<SculptThreadedTaskData *>(userdata); SculptSession *ss = data->ob->sculpt; const Brush *brush = data->brush; float bstrength = ss->cache->bstrength; @@ -229,12 +240,11 @@ void SCULPT_do_draw_face_sets_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, in BKE_curvemapping_init(brush->curve); /* Threaded loop over nodes. */ - SculptThreadedTaskData data = { - .sd = sd, - .ob = ob, - .brush = brush, - .nodes = nodes, - }; + SculptThreadedTaskData data{}; + data.sd = sd; + data.ob = ob; + data.brush = brush; + data.nodes = nodes; TaskParallelSettings settings; BKE_pbvh_parallel_range_settings(&settings, true, totnode); @@ -287,7 +297,7 @@ static EnumPropertyItem prop_sculpt_face_set_create_types[] = { "Face Set from Edit Mode Selection", "Create an Face Set corresponding to the Edit Mode face selection", }, - {0, NULL, 0, NULL, NULL}, + {0, nullptr, 0, nullptr, nullptr}, }; static int sculpt_face_set_create_exec(bContext *C, wmOperator *op) @@ -303,6 +313,9 @@ static int sculpt_face_set_create_exec(bContext *C, wmOperator *op) return OPERATOR_CANCELLED; } + Mesh *mesh = static_cast<Mesh *>(ob->data); + ss->face_sets = BKE_sculpt_face_sets_ensure(mesh); + BKE_sculpt_update_object_for_edit(depsgraph, ob, true, mode == SCULPT_FACE_SET_MASKED, false); const int tot_vert = SCULPT_vertex_count_get(ss); @@ -311,13 +324,13 @@ static int sculpt_face_set_create_exec(bContext *C, wmOperator *op) PBVH *pbvh = ob->sculpt->pbvh; PBVHNode **nodes; int totnode; - BKE_pbvh_search_gather(pbvh, NULL, NULL, &nodes, &totnode); + BKE_pbvh_search_gather(pbvh, nullptr, nullptr, &nodes, &totnode); if (!nodes) { return OPERATOR_CANCELLED; } - SCULPT_undo_push_begin(ob, "face set change"); + SCULPT_undo_push_begin(ob, op); SCULPT_undo_push_node(ob, nodes[0], SCULPT_UNDO_FACE_SETS); const int next_face_set = SCULPT_face_set_next_available_get(ss); @@ -349,7 +362,6 @@ static int sculpt_face_set_create_exec(bContext *C, wmOperator *op) } if (all_visible) { - Mesh *mesh = ob->data; mesh->face_sets_color_default = next_face_set; BKE_pbvh_face_sets_color_set( ss->pbvh, mesh->face_sets_color_seed, mesh->face_sets_color_default); @@ -373,20 +385,16 @@ static int sculpt_face_set_create_exec(bContext *C, wmOperator *op) } if (mode == SCULPT_FACE_SET_SELECTION) { - Mesh *mesh = ob->data; BMesh *bm; const BMAllocTemplate allocsize = BMALLOC_TEMPLATE_FROM_ME(mesh); - bm = BM_mesh_create(&allocsize, - &((struct BMeshCreateParams){ - .use_toolflags = true, - })); - - BM_mesh_bm_from_me(bm, - mesh, - (&(struct BMeshFromMeshParams){ - .calc_face_normal = true, - .calc_vert_normal = true, - })); + BMeshCreateParams create_params{}; + create_params.use_toolflags = true; + bm = BM_mesh_create(&allocsize, &create_params); + + BMeshFromMeshParams convert_params{}; + convert_params.calc_vert_normal = true; + convert_params.calc_face_normal = true; + BM_mesh_bm_from_me(bm, mesh, &convert_params); BMIter iter; BMFace *f; @@ -505,186 +513,103 @@ static EnumPropertyItem prop_sculpt_face_sets_init_types[] = { "Create a Face Set per isolated Face Set", }, - {0, NULL, 0, NULL, NULL}, + {0, nullptr, 0, nullptr, nullptr}, }; -typedef bool (*face_sets_flood_fill_test)( - BMesh *bm, BMFace *from_f, BMEdge *from_e, BMFace *to_f, const float threshold); - -static bool sculpt_face_sets_init_loose_parts_test(BMesh *UNUSED(bm), - BMFace *UNUSED(from_f), - BMEdge *UNUSED(from_e), - BMFace *UNUSED(to_f), - const float UNUSED(threshold)) -{ - return true; -} - -static bool sculpt_face_sets_init_normals_test( - BMesh *UNUSED(bm), BMFace *from_f, BMEdge *UNUSED(from_e), BMFace *to_f, const float threshold) -{ - return fabsf(dot_v3v3(from_f->no, to_f->no)) > threshold; -} - -static bool sculpt_face_sets_init_uv_seams_test(BMesh *UNUSED(bm), - BMFace *UNUSED(from_f), - BMEdge *from_e, - BMFace *UNUSED(to_f), - const float UNUSED(threshold)) -{ - return !BM_elem_flag_test(from_e, BM_ELEM_SEAM); -} - -static bool sculpt_face_sets_init_crease_test( - BMesh *bm, BMFace *UNUSED(from_f), BMEdge *from_e, BMFace *UNUSED(to_f), const float threshold) -{ - return BM_elem_float_data_get(&bm->edata, from_e, CD_CREASE) < threshold; -} - -static bool sculpt_face_sets_init_bevel_weight_test( - BMesh *bm, BMFace *UNUSED(from_f), BMEdge *from_e, BMFace *UNUSED(to_f), const float threshold) -{ - return BM_elem_float_data_get(&bm->edata, from_e, CD_BWEIGHT) < threshold; -} - -static bool sculpt_face_sets_init_sharp_edges_test(BMesh *UNUSED(bm), - BMFace *UNUSED(from_f), - BMEdge *from_e, - BMFace *UNUSED(to_f), - const float UNUSED(threshold)) -{ - return BM_elem_flag_test(from_e, BM_ELEM_SMOOTH); -} - -static bool sculpt_face_sets_init_face_set_boundary_test( - BMesh *bm, BMFace *from_f, BMEdge *UNUSED(from_e), BMFace *to_f, const float UNUSED(threshold)) -{ - const int cd_face_sets_offset = CustomData_get_offset(&bm->pdata, CD_SCULPT_FACE_SETS); - return BM_ELEM_CD_GET_INT(from_f, cd_face_sets_offset) == - BM_ELEM_CD_GET_INT(to_f, cd_face_sets_offset); -} +using FaceSetsFloodFillFn = blender::FunctionRef<bool(int from_face, int edge, int to_face)>; -static void sculpt_face_sets_init_flood_fill(Object *ob, - face_sets_flood_fill_test test, - const float threshold) +static void sculpt_face_sets_init_flood_fill(Object *ob, const FaceSetsFloodFillFn &test_fn) { + using namespace blender; SculptSession *ss = ob->sculpt; - Mesh *mesh = ob->data; - BMesh *bm; - const BMAllocTemplate allocsize = BMALLOC_TEMPLATE_FROM_ME(mesh); - bm = BM_mesh_create(&allocsize, - &((struct BMeshCreateParams){ - .use_toolflags = true, - })); + Mesh *mesh = static_cast<Mesh *>(ob->data); - BM_mesh_bm_from_me(bm, - mesh, - (&(struct BMeshFromMeshParams){ - .calc_face_normal = true, - .calc_vert_normal = true, - })); - - BLI_bitmap *visited_faces = BLI_BITMAP_NEW(mesh->totpoly, "visited faces"); - const int totfaces = mesh->totpoly; + BitVector<> visited_faces(mesh->totpoly, false); int *face_sets = ss->face_sets; - BM_mesh_elem_table_init(bm, BM_FACE); - BM_mesh_elem_table_ensure(bm, BM_FACE); + const Span<MEdge> edges = mesh->edges(); + const Span<MPoly> polys = mesh->polys(); + const Span<MLoop> loops = mesh->loops(); + + if (!ss->epmap) { + BKE_mesh_edge_poly_map_create(&ss->epmap, + &ss->epmap_mem, + edges.data(), + edges.size(), + polys.data(), + polys.size(), + loops.data(), + loops.size()); + } int next_face_set = 1; - for (int i = 0; i < totfaces; i++) { - if (BLI_BITMAP_TEST(visited_faces, i)) { + for (const int i : polys.index_range()) { + if (visited_faces[i]) { continue; } - GSQueue *queue; - queue = BLI_gsqueue_new(sizeof(int)); + std::queue<int> queue; face_sets[i] = next_face_set; - BLI_BITMAP_ENABLE(visited_faces, i); - BLI_gsqueue_push(queue, &i); - - while (!BLI_gsqueue_is_empty(queue)) { - int from_f; - BLI_gsqueue_pop(queue, &from_f); - - BMFace *f, *f_neighbor; - BMEdge *ed; - BMIter iter_a, iter_b; - - f = BM_face_at_index(bm, from_f); - - BM_ITER_ELEM (ed, &iter_a, f, BM_EDGES_OF_FACE) { - BM_ITER_ELEM (f_neighbor, &iter_b, ed, BM_FACES_OF_EDGE) { - if (f_neighbor == f) { + visited_faces[i].set(true); + queue.push(i); + + while (!queue.empty()) { + const int poly_i = queue.front(); + const MPoly &poly = polys[poly_i]; + queue.pop(); + + for (const MLoop &loop : loops.slice(poly.loopstart, poly.totloop)) { + const int edge_i = loop.e; + const Span<int> neighbor_polys(ss->epmap[edge_i].indices, ss->epmap[edge_i].count); + for (const int neighbor_i : neighbor_polys) { + if (neighbor_i == poly_i) { continue; } - int neighbor_face_index = BM_elem_index_get(f_neighbor); - if (BLI_BITMAP_TEST(visited_faces, neighbor_face_index)) { + if (visited_faces[neighbor_i]) { continue; } - if (!test(bm, f, ed, f_neighbor, threshold)) { + if (!test_fn(poly_i, edge_i, neighbor_i)) { continue; } - face_sets[neighbor_face_index] = next_face_set; - BLI_BITMAP_ENABLE(visited_faces, neighbor_face_index); - BLI_gsqueue_push(queue, &neighbor_face_index); + face_sets[neighbor_i] = next_face_set; + visited_faces[neighbor_i].set(true); + queue.push(neighbor_i); } } } next_face_set += 1; - - BLI_gsqueue_free(queue); } - - MEM_SAFE_FREE(visited_faces); - - BM_mesh_free(bm); } static void sculpt_face_sets_init_loop(Object *ob, const int mode) { - Mesh *mesh = ob->data; + using namespace blender; + Mesh *mesh = static_cast<Mesh *>(ob->data); SculptSession *ss = ob->sculpt; - BMesh *bm; - const BMAllocTemplate allocsize = BMALLOC_TEMPLATE_FROM_ME(mesh); - bm = BM_mesh_create(&allocsize, - &((struct BMeshCreateParams){ - .use_toolflags = true, - })); - - BM_mesh_bm_from_me(bm, - mesh, - (&(struct BMeshFromMeshParams){ - .calc_face_normal = true, - .calc_vert_normal = true, - })); - BMIter iter; - BMFace *f; - const int cd_fmaps_offset = CustomData_get_offset(&bm->pdata, CD_FACEMAP); - - BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) { - if (mode == SCULPT_FACE_SETS_FROM_MATERIALS) { - ss->face_sets[BM_elem_index_get(f)] = (int)(f->mat_nr + 1); + if (mode == SCULPT_FACE_SETS_FROM_MATERIALS) { + const bke::AttributeAccessor attributes = mesh->attributes(); + const VArraySpan<int> material_indices = attributes.lookup_or_default<int>( + "material_index", ATTR_DOMAIN_FACE, 0); + for (const int i : IndexRange(mesh->totpoly)) { + ss->face_sets[i] = material_indices[i] + 1; } - else if (mode == SCULPT_FACE_SETS_FROM_FACE_MAPS) { - if (cd_fmaps_offset != -1) { - ss->face_sets[BM_elem_index_get(f)] = BM_ELEM_CD_GET_INT(f, cd_fmaps_offset) + 2; - } - else { - ss->face_sets[BM_elem_index_get(f)] = 1; - } + } + else if (mode == SCULPT_FACE_SETS_FROM_FACE_MAPS) { + const int *face_maps = static_cast<int *>(CustomData_get_layer(&mesh->pdata, CD_FACEMAP)); + for (const int i : IndexRange(mesh->totpoly)) { + ss->face_sets[i] = face_maps ? face_maps[i] : 1; } } - BM_mesh_free(bm); } static int sculpt_face_set_init_exec(bContext *C, wmOperator *op) { + using namespace blender; Object *ob = CTX_data_active_object(C); SculptSession *ss = ob->sculpt; Depsgraph *depsgraph = CTX_data_depsgraph_pointer(C); @@ -701,52 +626,96 @@ static int sculpt_face_set_init_exec(bContext *C, wmOperator *op) PBVH *pbvh = ob->sculpt->pbvh; PBVHNode **nodes; int totnode; - BKE_pbvh_search_gather(pbvh, NULL, NULL, &nodes, &totnode); + BKE_pbvh_search_gather(pbvh, nullptr, nullptr, &nodes, &totnode); if (!nodes) { return OPERATOR_CANCELLED; } - SCULPT_undo_push_begin(ob, "face set change"); + SCULPT_undo_push_begin(ob, op); SCULPT_undo_push_node(ob, nodes[0], SCULPT_UNDO_FACE_SETS); const float threshold = RNA_float_get(op->ptr, "threshold"); + Mesh *mesh = static_cast<Mesh *>(ob->data); + ss->face_sets = BKE_sculpt_face_sets_ensure(mesh); + const bke::AttributeAccessor attributes = mesh->attributes(); + switch (mode) { - case SCULPT_FACE_SETS_FROM_LOOSE_PARTS: - sculpt_face_sets_init_flood_fill(ob, sculpt_face_sets_init_loose_parts_test, threshold); + case SCULPT_FACE_SETS_FROM_LOOSE_PARTS: { + const VArray<bool> hide_poly = attributes.lookup_or_default<bool>( + ".hide_poly", ATTR_DOMAIN_FACE, false); + sculpt_face_sets_init_flood_fill( + ob, [&](const int from_face, const int /*edge*/, const int to_face) { + return hide_poly[from_face] == hide_poly[to_face]; + }); break; - case SCULPT_FACE_SETS_FROM_MATERIALS: + } + case SCULPT_FACE_SETS_FROM_MATERIALS: { sculpt_face_sets_init_loop(ob, SCULPT_FACE_SETS_FROM_MATERIALS); break; - case SCULPT_FACE_SETS_FROM_NORMALS: - sculpt_face_sets_init_flood_fill(ob, sculpt_face_sets_init_normals_test, threshold); + } + case SCULPT_FACE_SETS_FROM_NORMALS: { + const Span<float3> poly_normals( + reinterpret_cast<const float3 *>(BKE_mesh_poly_normals_ensure(mesh)), mesh->totpoly); + sculpt_face_sets_init_flood_fill( + ob, [&](const int from_face, const int /*edge*/, const int to_face) -> bool { + return std::abs(math::dot(poly_normals[from_face], poly_normals[to_face])) > threshold; + }); break; - case SCULPT_FACE_SETS_FROM_UV_SEAMS: - sculpt_face_sets_init_flood_fill(ob, sculpt_face_sets_init_uv_seams_test, threshold); + } + case SCULPT_FACE_SETS_FROM_UV_SEAMS: { + const Span<MEdge> edges = mesh->edges(); + sculpt_face_sets_init_flood_fill( + ob, [&](const int /*from_face*/, const int edge, const int /*to_face*/) -> bool { + return (edges[edge].flag & ME_SEAM) == 0; + }); break; - case SCULPT_FACE_SETS_FROM_CREASES: - sculpt_face_sets_init_flood_fill(ob, sculpt_face_sets_init_crease_test, threshold); + } + case SCULPT_FACE_SETS_FROM_CREASES: { + const float *creases = static_cast<const float *>( + CustomData_get_layer(&mesh->edata, CD_CREASE)); + sculpt_face_sets_init_flood_fill( + ob, [&](const int /*from_face*/, const int edge, const int /*to_face*/) -> bool { + return creases[edge] < threshold; + }); break; - case SCULPT_FACE_SETS_FROM_SHARP_EDGES: - sculpt_face_sets_init_flood_fill(ob, sculpt_face_sets_init_sharp_edges_test, threshold); + } + case SCULPT_FACE_SETS_FROM_SHARP_EDGES: { + const Span<MEdge> edges = mesh->edges(); + sculpt_face_sets_init_flood_fill( + ob, [&](const int /*from_face*/, const int edge, const int /*to_face*/) -> bool { + return (edges[edge].flag & ME_SHARP) == 0; + }); break; - case SCULPT_FACE_SETS_FROM_BEVEL_WEIGHT: - sculpt_face_sets_init_flood_fill(ob, sculpt_face_sets_init_bevel_weight_test, threshold); + } + case SCULPT_FACE_SETS_FROM_BEVEL_WEIGHT: { + const float *bevel_weights = static_cast<const float *>( + CustomData_get_layer(&mesh->edata, CD_BWEIGHT)); + sculpt_face_sets_init_flood_fill( + ob, [&](const int /*from_face*/, const int edge, const int /*to_face*/) -> bool { + return bevel_weights ? bevel_weights[edge] / 255.0f < threshold : true; + }); break; - case SCULPT_FACE_SETS_FROM_FACE_SET_BOUNDARIES: + } + case SCULPT_FACE_SETS_FROM_FACE_SET_BOUNDARIES: { + Array<int> face_sets_copy(Span<int>(ss->face_sets, mesh->totpoly)); sculpt_face_sets_init_flood_fill( - ob, sculpt_face_sets_init_face_set_boundary_test, threshold); + ob, [&](const int from_face, const int /*edge*/, const int to_face) -> bool { + return face_sets_copy[from_face] == face_sets_copy[to_face]; + }); break; - case SCULPT_FACE_SETS_FROM_FACE_MAPS: + } + case SCULPT_FACE_SETS_FROM_FACE_MAPS: { sculpt_face_sets_init_loop(ob, SCULPT_FACE_SETS_FROM_FACE_MAPS); break; + } } SCULPT_undo_push_end(ob); /* Sync face sets visibility and vertex visibility as now all Face Sets are visible. */ - SCULPT_visibility_sync_all_face_sets_to_vertices(ob); + SCULPT_visibility_sync_all_from_faces(ob); for (int i = 0; i < totnode; i++) { BKE_pbvh_node_mark_update_visibility(nodes[i]); @@ -757,7 +726,7 @@ static int sculpt_face_set_init_exec(bContext *C, wmOperator *op) MEM_SAFE_FREE(nodes); if (BKE_pbvh_type(pbvh) == PBVH_FACES) { - BKE_mesh_flush_hidden_from_verts(ob->data); + BKE_mesh_flush_hidden_from_verts(mesh); } SCULPT_tag_update_overlays(C); @@ -836,7 +805,7 @@ static EnumPropertyItem prop_sculpt_face_sets_change_visibility_types[] = { "Show All Face Sets", "Show All Face Sets", }, - {0, NULL, 0, NULL, NULL}, + {0, nullptr, 0, nullptr, nullptr}, }; static int sculpt_face_sets_change_visibility_exec(bContext *C, wmOperator *op) @@ -850,19 +819,25 @@ static int sculpt_face_sets_change_visibility_exec(bContext *C, wmOperator *op) return OPERATOR_CANCELLED; } + if (!ss->face_sets) { + return OPERATOR_CANCELLED; + } + + Mesh *mesh = BKE_object_get_original_mesh(ob); + BKE_sculpt_update_object_for_edit(depsgraph, ob, true, true, false); const int tot_vert = SCULPT_vertex_count_get(ss); const int mode = RNA_enum_get(op->ptr, "mode"); const int active_face_set = SCULPT_active_face_set_get(ss); - SCULPT_undo_push_begin(ob, "Hide area"); + SCULPT_undo_push_begin(ob, op); PBVH *pbvh = ob->sculpt->pbvh; PBVHNode **nodes; int totnode; - BKE_pbvh_search_gather(pbvh, NULL, NULL, &nodes, &totnode); + BKE_pbvh_search_gather(pbvh, nullptr, nullptr, &nodes, &totnode); if (totnode == 0) { MEM_SAFE_FREE(nodes); @@ -887,37 +862,49 @@ static int sculpt_face_sets_change_visibility_exec(bContext *C, wmOperator *op) } } - for (int i = 0; i < ss->totfaces; i++) { - if (ss->face_sets[i] <= 0) { - hidden_vertex = true; - break; + if (ss->hide_poly) { + for (int i = 0; i < ss->totfaces; i++) { + if (ss->hide_poly[i]) { + hidden_vertex = true; + break; + } } } + ss->hide_poly = BKE_sculpt_hide_poly_ensure(mesh); + if (hidden_vertex) { - SCULPT_face_sets_visibility_all_set(ss, true); + SCULPT_face_visibility_all_set(ss, true); } else { - SCULPT_face_sets_visibility_all_set(ss, false); + SCULPT_face_visibility_all_set(ss, false); SCULPT_face_set_visibility_set(ss, active_face_set, true); } } if (mode == SCULPT_FACE_SET_VISIBILITY_SHOW_ALL) { - SCULPT_face_sets_visibility_all_set(ss, true); + /* As an optimization, free the hide attribute when making all geometry visible. This allows + * reduced memory usage without manually clearing it later, and allows sculpt operations to + * avoid checking element's hide status. */ + CustomData_free_layer_named(&mesh->pdata, ".hide_poly", mesh->totpoly); + ss->hide_poly = nullptr; + BKE_pbvh_update_hide_attributes_from_mesh(pbvh); } if (mode == SCULPT_FACE_SET_VISIBILITY_SHOW_ACTIVE) { - SCULPT_face_sets_visibility_all_set(ss, false); + ss->hide_poly = BKE_sculpt_hide_poly_ensure(mesh); + SCULPT_face_visibility_all_set(ss, false); SCULPT_face_set_visibility_set(ss, active_face_set, true); } if (mode == SCULPT_FACE_SET_VISIBILITY_HIDE_ACTIVE) { + ss->hide_poly = BKE_sculpt_hide_poly_ensure(mesh); SCULPT_face_set_visibility_set(ss, active_face_set, false); } if (mode == SCULPT_FACE_SET_VISIBILITY_INVERT) { - SCULPT_face_sets_visibility_invert(ss); + ss->hide_poly = BKE_sculpt_hide_poly_ensure(mesh); + SCULPT_face_visibility_all_invert(ss); } /* For modes that use the cursor active vertex, update the rotation origin for viewport @@ -933,7 +920,7 @@ static int sculpt_face_sets_change_visibility_exec(bContext *C, wmOperator *op) } /* Sync face sets visibility and vertex visibility. */ - SCULPT_visibility_sync_all_face_sets_to_vertices(ob); + SCULPT_visibility_sync_all_from_faces(ob); SCULPT_undo_push_end(ob); @@ -960,7 +947,7 @@ static int sculpt_face_sets_change_visibility_invoke(bContext *C, /* Update the active vertex and Face Set using the cursor position to avoid relying on the paint * cursor updates. */ SculptCursorGeometryInfo sgi; - const float mval_fl[2] = {UNPACK2(event->mval)}; + const float mval_fl[2] = {(float)event->mval[0], (float)event->mval[1]}; SCULPT_vertex_random_access_ensure(ss); SCULPT_cursor_geometry_info_update(C, &sgi, mval_fl, false); @@ -1000,10 +987,14 @@ static int sculpt_face_sets_randomize_colors_exec(bContext *C, wmOperator *UNUSE return OPERATOR_CANCELLED; } + if (!ss->face_sets) { + return OPERATOR_CANCELLED; + } + PBVH *pbvh = ob->sculpt->pbvh; PBVHNode **nodes; int totnode; - Mesh *mesh = ob->data; + Mesh *mesh = static_cast<Mesh *>(ob->data); mesh->face_sets_color_seed += 1; if (ss->face_sets) { @@ -1014,7 +1005,7 @@ static int sculpt_face_sets_randomize_colors_exec(bContext *C, wmOperator *UNUSE } BKE_pbvh_face_sets_color_set(pbvh, mesh->face_sets_color_seed, mesh->face_sets_color_default); - BKE_pbvh_search_gather(pbvh, NULL, NULL, &nodes, &totnode); + BKE_pbvh_search_gather(pbvh, nullptr, nullptr, &nodes, &totnode); for (int i = 0; i < totnode; i++) { BKE_pbvh_node_mark_redraw(nodes[i]); } @@ -1086,7 +1077,7 @@ static EnumPropertyItem prop_sculpt_face_sets_edit_types[] = { "Creates a smooth as possible geometry patch from the Face Set minimizing changes in " "vertex tangents", }, - {0, NULL, 0, NULL, NULL}, + {0, nullptr, 0, nullptr, nullptr}, }; static void sculpt_face_set_grow(Object *ob, @@ -1096,13 +1087,16 @@ static void sculpt_face_set_grow(Object *ob, const bool modify_hidden) { Mesh *mesh = BKE_mesh_from_object(ob); + const MPoly *polys = BKE_mesh_polys(mesh); + const MLoop *loops = BKE_mesh_loops(mesh); + for (int p = 0; p < mesh->totpoly; p++) { if (!modify_hidden && prev_face_sets[p] <= 0) { continue; } - const MPoly *c_poly = &mesh->mpoly[p]; + const MPoly *c_poly = &polys[p]; for (int l = 0; l < c_poly->totloop; l++) { - const MLoop *c_loop = &mesh->mloop[c_poly->loopstart + l]; + const MLoop *c_loop = &loops[c_poly->loopstart + l]; const MeshElemMap *vert_map = &ss->pmap[c_loop->v]; for (int i = 0; i < vert_map->count; i++) { const int neighbor_face_index = vert_map->indices[i]; @@ -1124,14 +1118,16 @@ static void sculpt_face_set_shrink(Object *ob, const bool modify_hidden) { Mesh *mesh = BKE_mesh_from_object(ob); + const MPoly *polys = BKE_mesh_polys(mesh); + const MLoop *loops = BKE_mesh_loops(mesh); for (int p = 0; p < mesh->totpoly; p++) { if (!modify_hidden && prev_face_sets[p] <= 0) { continue; } if (abs(prev_face_sets[p]) == active_face_set_id) { - const MPoly *c_poly = &mesh->mpoly[p]; + const MPoly *c_poly = &polys[p]; for (int l = 0; l < c_poly->totloop; l++) { - const MLoop *c_loop = &mesh->mloop[c_poly->loopstart + l]; + const MLoop *c_loop = &loops[c_poly->loopstart + l]; const MeshElemMap *vert_map = &ss->pmap[c_loop->v]; for (int i = 0; i < vert_map->count; i++) { const int neighbor_face_index = vert_map->indices[i]; @@ -1149,18 +1145,21 @@ static void sculpt_face_set_shrink(Object *ob, static bool check_single_face_set(SculptSession *ss, int *face_sets, const bool check_visible_only) { - + if (face_sets == nullptr) { + return true; + } int first_face_set = SCULPT_FACE_SET_NONE; if (check_visible_only) { for (int f = 0; f < ss->totfaces; f++) { - if (face_sets[f] > 0) { - first_face_set = face_sets[f]; - break; + if (ss->hide_poly && ss->hide_poly[f]) { + continue; } + first_face_set = face_sets[f]; + break; } } else { - first_face_set = abs(face_sets[0]); + first_face_set = face_sets[0]; } if (first_face_set == SCULPT_FACE_SET_NONE) { @@ -1168,8 +1167,10 @@ static bool check_single_face_set(SculptSession *ss, int *face_sets, const bool } for (int f = 0; f < ss->totfaces; f++) { - const int face_set_id = check_visible_only ? face_sets[f] : abs(face_sets[f]); - if (face_set_id != first_face_set) { + if (check_visible_only && ss->hide_poly && ss->hide_poly[f]) { + continue; + } + if (face_sets[f] != first_face_set) { return false; } } @@ -1182,19 +1183,16 @@ static void sculpt_face_set_delete_geometry(Object *ob, const bool modify_hidden) { - Mesh *mesh = ob->data; + Mesh *mesh = static_cast<Mesh *>(ob->data); const BMAllocTemplate allocsize = BMALLOC_TEMPLATE_FROM_ME(mesh); - BMesh *bm = BM_mesh_create(&allocsize, - &((struct BMeshCreateParams){ - .use_toolflags = true, - })); - - BM_mesh_bm_from_me(bm, - mesh, - (&(struct BMeshFromMeshParams){ - .calc_face_normal = true, - .calc_vert_normal = true, - })); + BMeshCreateParams create_params{}; + create_params.use_toolflags = true; + BMesh *bm = BM_mesh_create(&allocsize, &create_params); + + BMeshFromMeshParams convert_params{}; + convert_params.calc_vert_normal = true; + convert_params.calc_face_normal = true; + BM_mesh_bm_from_me(bm, mesh, &convert_params); BM_mesh_elem_table_init(bm, BM_FACE); BM_mesh_elem_table_ensure(bm, BM_FACE); @@ -1203,46 +1201,45 @@ static void sculpt_face_set_delete_geometry(Object *ob, BMFace *f; BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) { const int face_index = BM_elem_index_get(f); - const int face_set_id = modify_hidden ? abs(ss->face_sets[face_index]) : - ss->face_sets[face_index]; - BM_elem_flag_set(f, BM_ELEM_TAG, face_set_id == active_face_set_id); + if (!modify_hidden && ss->hide_poly && ss->hide_poly[face_index]) { + continue; + } + BM_elem_flag_set(f, BM_ELEM_TAG, ss->face_sets[face_index] == active_face_set_id); } BM_mesh_delete_hflag_context(bm, BM_ELEM_TAG, DEL_FACES); BM_mesh_elem_hflag_disable_all(bm, BM_VERT | BM_EDGE | BM_FACE, BM_ELEM_TAG, false); - BM_mesh_bm_to_me(NULL, - bm, - ob->data, - (&(struct BMeshToMeshParams){ - .calc_object_remap = false, - })); + BMeshToMeshParams bmesh_to_mesh_params{}; + bmesh_to_mesh_params.calc_object_remap = false; + BM_mesh_bm_to_me(nullptr, bm, mesh, &bmesh_to_mesh_params); BM_mesh_free(bm); } static void sculpt_face_set_edit_fair_face_set(Object *ob, const int active_face_set_id, - const int fair_order) + const eMeshFairingDepth fair_order) { SculptSession *ss = ob->sculpt; const int totvert = SCULPT_vertex_count_get(ss); - Mesh *mesh = ob->data; - bool *fair_vertices = MEM_malloc_arrayN(totvert, sizeof(bool), "fair vertices"); + Mesh *mesh = static_cast<Mesh *>(ob->data); + bool *fair_verts = static_cast<bool *>( + MEM_malloc_arrayN(totvert, sizeof(bool), "fair vertices")); SCULPT_boundary_info_ensure(ob); for (int i = 0; i < totvert; i++) { PBVHVertRef vertex = BKE_pbvh_index_to_vertex(ss->pbvh, i); - fair_vertices[i] = !SCULPT_vertex_is_boundary(ss, vertex) && - SCULPT_vertex_has_face_set(ss, vertex, active_face_set_id) && - SCULPT_vertex_has_unique_face_set(ss, vertex); + fair_verts[i] = !SCULPT_vertex_is_boundary(ss, vertex) && + SCULPT_vertex_has_face_set(ss, vertex, active_face_set_id) && + SCULPT_vertex_has_unique_face_set(ss, vertex); } MVert *mvert = SCULPT_mesh_deformed_mverts_get(ss); - BKE_mesh_prefair_and_fair_vertices(mesh, mvert, fair_vertices, fair_order); - MEM_freeN(fair_vertices); + BKE_mesh_prefair_and_fair_verts(mesh, mvert, fair_verts, fair_order); + MEM_freeN(fair_verts); } static void sculpt_face_set_apply_edit(Object *ob, @@ -1254,13 +1251,13 @@ static void sculpt_face_set_apply_edit(Object *ob, switch (mode) { case SCULPT_FACE_SET_EDIT_GROW: { - int *prev_face_sets = MEM_dupallocN(ss->face_sets); + int *prev_face_sets = static_cast<int *>(MEM_dupallocN(ss->face_sets)); sculpt_face_set_grow(ob, ss, prev_face_sets, active_face_set_id, modify_hidden); MEM_SAFE_FREE(prev_face_sets); break; } case SCULPT_FACE_SET_EDIT_SHRINK: { - int *prev_face_sets = MEM_dupallocN(ss->face_sets); + int *prev_face_sets = static_cast<int *>(MEM_dupallocN(ss->face_sets)); sculpt_face_set_shrink(ob, ss, prev_face_sets, active_face_set_id, modify_hidden); MEM_SAFE_FREE(prev_face_sets); break; @@ -1317,23 +1314,26 @@ static void sculpt_face_set_edit_modify_geometry(bContext *C, Object *ob, const int active_face_set, const eSculptFaceSetEditMode mode, - const bool modify_hidden) + const bool modify_hidden, + wmOperator *op) { - ED_sculpt_undo_geometry_begin(ob, "edit face set delete geometry"); + Mesh *mesh = static_cast<Mesh *>(ob->data); + ED_sculpt_undo_geometry_begin(ob, op); sculpt_face_set_apply_edit(ob, abs(active_face_set), mode, modify_hidden); ED_sculpt_undo_geometry_end(ob); - BKE_mesh_batch_cache_dirty_tag(ob->data, BKE_MESH_BATCH_DIRTY_ALL); + BKE_mesh_batch_cache_dirty_tag(mesh, BKE_MESH_BATCH_DIRTY_ALL); DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY); - WM_event_add_notifier(C, NC_GEOM | ND_DATA, ob->data); + WM_event_add_notifier(C, NC_GEOM | ND_DATA, mesh); } static void face_set_edit_do_post_visibility_updates(Object *ob, PBVHNode **nodes, int totnode) { SculptSession *ss = ob->sculpt; PBVH *pbvh = ss->pbvh; + Mesh *mesh = static_cast<Mesh *>(ob->data); /* Sync face sets visibility and vertex visibility as now all Face Sets are visible. */ - SCULPT_visibility_sync_all_face_sets_to_vertices(ob); + SCULPT_visibility_sync_all_from_faces(ob); for (int i = 0; i < totnode; i++) { BKE_pbvh_node_mark_update_visibility(nodes[i]); @@ -1342,24 +1342,25 @@ static void face_set_edit_do_post_visibility_updates(Object *ob, PBVHNode **node BKE_pbvh_update_vertex_data(ss->pbvh, PBVH_UpdateVisibility); if (BKE_pbvh_type(pbvh) == PBVH_FACES) { - BKE_mesh_flush_hidden_from_verts(ob->data); + BKE_mesh_flush_hidden_from_verts(mesh); } } static void sculpt_face_set_edit_modify_face_sets(Object *ob, const int active_face_set, const eSculptFaceSetEditMode mode, - const bool modify_hidden) + const bool modify_hidden, + wmOperator *op) { PBVH *pbvh = ob->sculpt->pbvh; PBVHNode **nodes; int totnode; - BKE_pbvh_search_gather(pbvh, NULL, NULL, &nodes, &totnode); + BKE_pbvh_search_gather(pbvh, nullptr, nullptr, &nodes, &totnode); if (!nodes) { return; } - SCULPT_undo_push_begin(ob, "face set edit"); + SCULPT_undo_push_begin(ob, op); SCULPT_undo_push_node(ob, nodes[0], SCULPT_UNDO_FACE_SETS); sculpt_face_set_apply_edit(ob, abs(active_face_set), mode, modify_hidden); SCULPT_undo_push_end(ob); @@ -1370,15 +1371,16 @@ static void sculpt_face_set_edit_modify_face_sets(Object *ob, static void sculpt_face_set_edit_modify_coordinates(bContext *C, Object *ob, const int active_face_set, - const eSculptFaceSetEditMode mode) + const eSculptFaceSetEditMode mode, + wmOperator *op) { Sculpt *sd = CTX_data_tool_settings(C)->sculpt; SculptSession *ss = ob->sculpt; PBVH *pbvh = ss->pbvh; PBVHNode **nodes; int totnode; - BKE_pbvh_search_gather(pbvh, NULL, NULL, &nodes, &totnode); - SCULPT_undo_push_begin(ob, "face set edit"); + BKE_pbvh_search_gather(pbvh, nullptr, nullptr, &nodes, &totnode); + SCULPT_undo_push_begin(ob, op); for (int i = 0; i < totnode; i++) { BKE_pbvh_node_mark_update(nodes[i]); SCULPT_undo_push_node(ob, nodes[i], SCULPT_UNDO_COORDS); @@ -1400,19 +1402,21 @@ static int sculpt_face_set_edit_invoke(bContext *C, wmOperator *op, const wmEven SculptSession *ss = ob->sculpt; Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C); - const int mode = RNA_enum_get(op->ptr, "mode"); + const eSculptFaceSetEditMode mode = static_cast<eSculptFaceSetEditMode>( + RNA_enum_get(op->ptr, "mode")); const bool modify_hidden = RNA_boolean_get(op->ptr, "modify_hidden"); if (!sculpt_face_set_edit_is_operation_valid(ss, mode, modify_hidden)) { return OPERATOR_CANCELLED; } + ss->face_sets = BKE_sculpt_face_sets_ensure(BKE_mesh_from_object(ob)); BKE_sculpt_update_object_for_edit(depsgraph, ob, true, false, false); /* Update the current active Face Set and Vertex as the operator can be used directly from the * tool without brush cursor. */ SculptCursorGeometryInfo sgi; - const float mval_fl[2] = {UNPACK2(event->mval)}; + const float mval_fl[2] = {(float)event->mval[0], (float)event->mval[1]}; if (!SCULPT_cursor_geometry_info_update(C, &sgi, mval_fl, false)) { /* The cursor is not over the mesh. Cancel to avoid editing the last updated Face Set ID. */ return OPERATOR_CANCELLED; @@ -1421,15 +1425,15 @@ static int sculpt_face_set_edit_invoke(bContext *C, wmOperator *op, const wmEven switch (mode) { case SCULPT_FACE_SET_EDIT_DELETE_GEOMETRY: - sculpt_face_set_edit_modify_geometry(C, ob, active_face_set, mode, modify_hidden); + sculpt_face_set_edit_modify_geometry(C, ob, active_face_set, mode, modify_hidden, op); break; case SCULPT_FACE_SET_EDIT_GROW: case SCULPT_FACE_SET_EDIT_SHRINK: - sculpt_face_set_edit_modify_face_sets(ob, active_face_set, mode, modify_hidden); + sculpt_face_set_edit_modify_face_sets(ob, active_face_set, mode, modify_hidden, op); break; case SCULPT_FACE_SET_EDIT_FAIR_POSITIONS: case SCULPT_FACE_SET_EDIT_FAIR_TANGENCY: - sculpt_face_set_edit_modify_coordinates(C, ob, active_face_set, mode); + sculpt_face_set_edit_modify_coordinates(C, ob, active_face_set, mode, op); break; } diff --git a/source/blender/editors/sculpt_paint/sculpt_filter_color.c b/source/blender/editors/sculpt_paint/sculpt_filter_color.c index 7a1e08ea713..161fc563950 100644 --- a/source/blender/editors/sculpt_paint/sculpt_filter_color.c +++ b/source/blender/editors/sculpt_paint/sculpt_filter_color.c @@ -346,7 +346,7 @@ static int sculpt_color_filter_invoke(bContext *C, wmOperator *op, const wmEvent return OPERATOR_CANCELLED; } - SCULPT_undo_push_begin(ob, "color filter"); + SCULPT_undo_push_begin(ob, op); BKE_sculpt_color_layer_create_if_needed(ob); /* CTX_data_ensure_evaluated_depsgraph should be used at the end to include the updates of diff --git a/source/blender/editors/sculpt_paint/sculpt_filter_mask.c b/source/blender/editors/sculpt_paint/sculpt_filter_mask.c index fa4fe191273..bb27e4f1e9e 100644 --- a/source/blender/editors/sculpt_paint/sculpt_filter_mask.c +++ b/source/blender/editors/sculpt_paint/sculpt_filter_mask.c @@ -14,6 +14,7 @@ #include "DNA_mesh_types.h" #include "DNA_meshdata_types.h" +#include "DNA_modifier_types.h" #include "BKE_brush.h" #include "BKE_context.h" @@ -174,11 +175,15 @@ static int sculpt_mask_filter_exec(bContext *C, wmOperator *op) { Object *ob = CTX_data_active_object(C); Depsgraph *depsgraph = CTX_data_depsgraph_pointer(C); + const Scene *scene = CTX_data_scene(C); PBVHNode **nodes; Sculpt *sd = CTX_data_tool_settings(C)->sculpt; int totnode; int filter_type = RNA_enum_get(op->ptr, "filter_type"); + MultiresModifierData *mmd = BKE_sculpt_multires_active(scene, ob); + BKE_sculpt_mask_layers_ensure(ob, mmd); + BKE_sculpt_update_object_for_edit(depsgraph, ob, true, true, false); SculptSession *ss = ob->sculpt; @@ -193,7 +198,7 @@ static int sculpt_mask_filter_exec(bContext *C, wmOperator *op) int num_verts = SCULPT_vertex_count_get(ss); BKE_pbvh_search_gather(pbvh, NULL, NULL, &nodes, &totnode); - SCULPT_undo_push_begin(ob, "Mask Filter"); + SCULPT_undo_push_begin(ob, op); for (int i = 0; i < totnode; i++) { SCULPT_undo_push_node(ob, nodes[i], SCULPT_UNDO_MASK); @@ -409,7 +414,7 @@ static int sculpt_dirty_mask_exec(bContext *C, wmOperator *op) } BKE_pbvh_search_gather(pbvh, NULL, NULL, &nodes, &totnode); - SCULPT_undo_push_begin(ob, "Dirty Mask"); + SCULPT_undo_push_begin(ob, op); for (int i = 0; i < totnode; i++) { SCULPT_undo_push_node(ob, nodes[i], SCULPT_UNDO_MASK); diff --git a/source/blender/editors/sculpt_paint/sculpt_filter_mesh.c b/source/blender/editors/sculpt_paint/sculpt_filter_mesh.c index 4f45b7917ec..e576cfda3af 100644 --- a/source/blender/editors/sculpt_paint/sculpt_filter_mesh.c +++ b/source/blender/editors/sculpt_paint/sculpt_filter_mesh.c @@ -694,7 +694,7 @@ static int sculpt_mesh_filter_invoke(bContext *C, wmOperator *op, const wmEvent SCULPT_boundary_info_ensure(ob); } - SCULPT_undo_push_begin(ob, "Mesh Filter"); + SCULPT_undo_push_begin(ob, op); SCULPT_filter_cache_init(C, ob, sd, SCULPT_UNDO_COORDS); diff --git a/source/blender/editors/sculpt_paint/sculpt_geodesic.c b/source/blender/editors/sculpt_paint/sculpt_geodesic.c index ecf8c4586ae..5dd602bc36d 100644 --- a/source/blender/editors/sculpt_paint/sculpt_geodesic.c +++ b/source/blender/editors/sculpt_paint/sculpt_geodesic.c @@ -37,7 +37,6 @@ #include "DEG_depsgraph.h" #include "WM_api.h" -#include "WM_message.h" #include "WM_toolsystem.h" #include "WM_types.h" @@ -62,9 +61,9 @@ /* Propagate distance from v1 and v2 to v0. */ static bool sculpt_geodesic_mesh_test_dist_add( - MVert *mvert, const int v0, const int v1, const int v2, float *dists, GSet *initial_vertices) + MVert *mvert, const int v0, const int v1, const int v2, float *dists, GSet *initial_verts) { - if (BLI_gset_haskey(initial_vertices, POINTER_FROM_INT(v0))) { + if (BLI_gset_haskey(initial_verts, POINTER_FROM_INT(v0))) { return false; } @@ -97,7 +96,7 @@ static bool sculpt_geodesic_mesh_test_dist_add( } static float *SCULPT_geodesic_mesh_create(Object *ob, - GSet *initial_vertices, + GSet *initial_verts, const float limit_radius) { SculptSession *ss = ob->sculpt; @@ -108,8 +107,10 @@ static float *SCULPT_geodesic_mesh_create(Object *ob, const float limit_radius_sq = limit_radius * limit_radius; - MEdge *edges = mesh->medge; MVert *verts = SCULPT_mesh_deformed_mverts_get(ss); + const MEdge *edges = BKE_mesh_edges(mesh); + const MPoly *polys = BKE_mesh_polys(mesh); + const MLoop *loops = BKE_mesh_loops(mesh); float *dists = MEM_malloc_arrayN(totvert, sizeof(float), "distances"); BLI_bitmap *edge_tag = BLI_BITMAP_NEW(totedge, "edge tag"); @@ -117,16 +118,15 @@ static float *SCULPT_geodesic_mesh_create(Object *ob, if (!ss->epmap) { BKE_mesh_edge_poly_map_create(&ss->epmap, &ss->epmap_mem, - mesh->medge, + edges, mesh->totedge, - mesh->mpoly, + polys, mesh->totpoly, - mesh->mloop, + loops, mesh->totloop); } if (!ss->vemap) { - BKE_mesh_vert_edge_map_create( - &ss->vemap, &ss->vemap_mem, mesh->medge, mesh->totvert, mesh->totedge); + BKE_mesh_vert_edge_map_create(&ss->vemap, &ss->vemap_mem, edges, mesh->totvert, mesh->totedge); } /* Both contain edge indices encoded as *void. */ @@ -137,7 +137,7 @@ static float *SCULPT_geodesic_mesh_create(Object *ob, BLI_LINKSTACK_INIT(queue_next); for (int i = 0; i < totvert; i++) { - if (BLI_gset_haskey(initial_vertices, POINTER_FROM_INT(i))) { + if (BLI_gset_haskey(initial_verts, POINTER_FROM_INT(i))) { dists[i] = 0.0f; } else { @@ -159,7 +159,7 @@ static float *SCULPT_geodesic_mesh_create(Object *ob, /* This is an O(n^2) loop used to limit the geodesic distance calculation to a radius. When * this optimization is needed, it is expected for the tool to request the distance to a low * number of vertices (usually just 1 or 2). */ - GSET_ITER (gs_iter, initial_vertices) { + GSET_ITER (gs_iter, initial_verts) { const int v = POINTER_AS_INT(BLI_gsetIterator_getKey(&gs_iter)); float *v_co = verts[v].co; for (int i = 0; i < totvert; i++) { @@ -193,25 +193,24 @@ static float *SCULPT_geodesic_mesh_create(Object *ob, SWAP(int, v1, v2); } sculpt_geodesic_mesh_test_dist_add( - verts, v2, v1, SCULPT_GEODESIC_VERTEX_NONE, dists, initial_vertices); + verts, v2, v1, SCULPT_GEODESIC_VERTEX_NONE, dists, initial_verts); } if (ss->epmap[e].count != 0) { for (int poly_map_index = 0; poly_map_index < ss->epmap[e].count; poly_map_index++) { const int poly = ss->epmap[e].indices[poly_map_index]; - if (ss->face_sets[poly] <= 0) { + if (ss->hide_poly && ss->hide_poly[poly]) { continue; } - const MPoly *mpoly = &mesh->mpoly[poly]; + const MPoly *mpoly = &polys[poly]; for (int loop_index = 0; loop_index < mpoly->totloop; loop_index++) { - const MLoop *mloop = &mesh->mloop[loop_index + mpoly->loopstart]; + const MLoop *mloop = &loops[loop_index + mpoly->loopstart]; const int v_other = mloop->v; if (ELEM(v_other, v1, v2)) { continue; } - if (sculpt_geodesic_mesh_test_dist_add( - verts, v_other, v1, v2, dists, initial_vertices)) { + if (sculpt_geodesic_mesh_test_dist_add(verts, v_other, v1, v2, dists, initial_verts)) { for (int edge_map_index = 0; edge_map_index < ss->vemap[v_other].count; edge_map_index++) { const int e_other = ss->vemap[v_other].indices[edge_map_index]; @@ -258,7 +257,7 @@ static float *SCULPT_geodesic_mesh_create(Object *ob, /* For sculpt mesh data that does not support a geodesic distances algorithm, fallback to the * distance to each vertex. In this case, only one of the initial vertices will be used to * calculate the distance. */ -static float *SCULPT_geodesic_fallback_create(Object *ob, GSet *initial_vertices) +static float *SCULPT_geodesic_fallback_create(Object *ob, GSet *initial_verts) { SculptSession *ss = ob->sculpt; @@ -267,7 +266,7 @@ static float *SCULPT_geodesic_fallback_create(Object *ob, GSet *initial_vertices float *dists = MEM_malloc_arrayN(totvert, sizeof(float), "distances"); int first_affected = SCULPT_GEODESIC_VERTEX_NONE; GSetIterator gs_iter; - GSET_ITER (gs_iter, initial_vertices) { + GSET_ITER (gs_iter, initial_verts) { first_affected = POINTER_AS_INT(BLI_gsetIterator_getKey(&gs_iter)); break; } @@ -290,17 +289,15 @@ static float *SCULPT_geodesic_fallback_create(Object *ob, GSet *initial_vertices return dists; } -float *SCULPT_geodesic_distances_create(Object *ob, - GSet *initial_vertices, - const float limit_radius) +float *SCULPT_geodesic_distances_create(Object *ob, GSet *initial_verts, const float limit_radius) { SculptSession *ss = ob->sculpt; switch (BKE_pbvh_type(ss->pbvh)) { case PBVH_FACES: - return SCULPT_geodesic_mesh_create(ob, initial_vertices, limit_radius); + return SCULPT_geodesic_mesh_create(ob, initial_verts, limit_radius); case PBVH_BMESH: case PBVH_GRIDS: - return SCULPT_geodesic_fallback_create(ob, initial_vertices); + return SCULPT_geodesic_fallback_create(ob, initial_verts); } BLI_assert(false); return NULL; @@ -312,7 +309,7 @@ float *SCULPT_geodesic_from_vertex_and_symm(Sculpt *sd, const float limit_radius) { SculptSession *ss = ob->sculpt; - GSet *initial_vertices = BLI_gset_int_new("initial_vertices"); + GSet *initial_verts = BLI_gset_int_new("initial_verts"); const char symm = SCULPT_mesh_symmetry_xyz_get(ob); for (char i = 0; i <= symm; ++i) { @@ -328,22 +325,22 @@ float *SCULPT_geodesic_from_vertex_and_symm(Sculpt *sd, v = SCULPT_nearest_vertex_get(sd, ob, location, FLT_MAX, false); } if (v.i != PBVH_REF_NONE) { - BLI_gset_add(initial_vertices, POINTER_FROM_INT(BKE_pbvh_vertex_to_index(ss->pbvh, v))); + BLI_gset_add(initial_verts, POINTER_FROM_INT(BKE_pbvh_vertex_to_index(ss->pbvh, v))); } } } - float *dists = SCULPT_geodesic_distances_create(ob, initial_vertices, limit_radius); - BLI_gset_free(initial_vertices, NULL); + float *dists = SCULPT_geodesic_distances_create(ob, initial_verts, limit_radius); + BLI_gset_free(initial_verts, NULL); return dists; } float *SCULPT_geodesic_from_vertex(Object *ob, const PBVHVertRef vertex, const float limit_radius) { - GSet *initial_vertices = BLI_gset_int_new("initial_vertices"); - BLI_gset_add(initial_vertices, + GSet *initial_verts = BLI_gset_int_new("initial_verts"); + BLI_gset_add(initial_verts, POINTER_FROM_INT(BKE_pbvh_vertex_to_index(ob->sculpt->pbvh, vertex))); - float *dists = SCULPT_geodesic_distances_create(ob, initial_vertices, limit_radius); - BLI_gset_free(initial_vertices, NULL); + float *dists = SCULPT_geodesic_distances_create(ob, initial_verts, limit_radius); + BLI_gset_free(initial_verts, NULL); return dists; } diff --git a/source/blender/editors/sculpt_paint/sculpt_intern.h b/source/blender/editors/sculpt_paint/sculpt_intern.h index 6a10f7cad18..cdfa9c2586f 100644 --- a/source/blender/editors/sculpt_paint/sculpt_intern.h +++ b/source/blender/editors/sculpt_paint/sculpt_intern.h @@ -97,7 +97,7 @@ typedef struct { /* Flood Fill. */ typedef struct { GSQueue *queue; - BLI_bitmap *visited_vertices; + BLI_bitmap *visited_verts; } SculptFloodFill; typedef enum eBoundaryAutomaskMode { @@ -402,9 +402,6 @@ typedef struct AutomaskingSettings { typedef struct AutomaskingCache { AutomaskingSettings settings; - /* Precomputed auto-mask factor indexed by vertex, owned by the auto-masking system and - * initialized in #SCULPT_automasking_cache_init when needed. */ - float *factor; } AutomaskingCache; typedef struct FilterCache { @@ -1004,9 +1001,13 @@ void SCULPT_connected_components_ensure(Object *ob); void SCULPT_vertex_visible_set(SculptSession *ss, PBVHVertRef vertex, bool visible); bool SCULPT_vertex_visible_get(SculptSession *ss, PBVHVertRef vertex); +bool SCULPT_vertex_all_faces_visible_get(const SculptSession *ss, PBVHVertRef vertex); +bool SCULPT_vertex_any_face_visible_get(SculptSession *ss, PBVHVertRef vertex); -void SCULPT_visibility_sync_all_face_sets_to_vertices(struct Object *ob); -void SCULPT_visibility_sync_all_vertex_to_face_sets(struct SculptSession *ss); +void SCULPT_face_visibility_all_invert(SculptSession *ss); +void SCULPT_face_visibility_all_set(SculptSession *ss, bool visible); + +void SCULPT_visibility_sync_all_from_faces(struct Object *ob); /** \} */ @@ -1024,11 +1025,6 @@ bool SCULPT_vertex_has_unique_face_set(SculptSession *ss, PBVHVertRef vertex); int SCULPT_face_set_next_available_get(SculptSession *ss); void SCULPT_face_set_visibility_set(SculptSession *ss, int face_set, bool visible); -bool SCULPT_vertex_all_face_sets_visible_get(const SculptSession *ss, PBVHVertRef vertex); -bool SCULPT_vertex_any_face_set_visible_get(SculptSession *ss, PBVHVertRef vertex); - -void SCULPT_face_sets_visibility_invert(SculptSession *ss); -void SCULPT_face_sets_visibility_all_set(SculptSession *ss, bool visible); /** \} */ @@ -1274,7 +1270,6 @@ void sculpt_dynamic_topology_disable_with_undo(struct Main *bmain, bool SCULPT_stroke_is_dynamic_topology(const SculptSession *ss, const Brush *brush); void SCULPT_dynamic_topology_triangulate(struct BMesh *bm); -void SCULPT_dyntopo_node_layers_add(struct SculptSession *ss); enum eDynTopoWarnFlag SCULPT_dynamic_topology_check(Scene *scene, Object *ob); @@ -1494,10 +1489,17 @@ SculptUndoNode *SCULPT_undo_get_node(PBVHNode *node, SculptUndoType type); SculptUndoNode *SCULPT_undo_get_first_node(void); /** - * NOTE: `name` must match operator name for - * redo panels to work. + * Pushes an undo step using the operator name. This is necessary for + * redo panels to work; operators that do not support that may use + * #SCULPT_undo_push_begin_ex instead if so desired. */ -void SCULPT_undo_push_begin(struct Object *ob, const char *name); +void SCULPT_undo_push_begin(struct Object *ob, const struct wmOperator *op); + +/** + * NOTE: #SCULPT_undo_push_begin is preferred since `name` + * must match operator name for redo panels to work. + */ +void SCULPT_undo_push_begin_ex(struct Object *ob, const char *name); void SCULPT_undo_push_end(struct Object *ob); void SCULPT_undo_push_end_ex(struct Object *ob, const bool use_nested_undo); @@ -1830,6 +1832,21 @@ BLI_INLINE bool SCULPT_tool_is_paint(int tool) return ELEM(tool, SCULPT_TOOL_PAINT, SCULPT_TOOL_SMEAR); } +BLI_INLINE bool SCULPT_tool_is_mask(int tool) +{ + return ELEM(tool, SCULPT_TOOL_MASK); +} + +BLI_INLINE bool SCULPT_tool_is_face_sets(int tool) +{ + return ELEM(tool, SCULPT_TOOL_DRAW_FACE_SETS); +} + #ifdef __cplusplus } #endif + +/* Make SCULPT_ alias to a few blenkernel sculpt methods. */ + +#define SCULPT_vertex_attr_get BKE_sculpt_vertex_attr_get +#define SCULPT_face_attr_get BKE_sculpt_face_attr_get diff --git a/source/blender/editors/sculpt_paint/sculpt_mask_expand.c b/source/blender/editors/sculpt_paint/sculpt_mask_expand.c index 2e661711172..ec246cd3788 100644 --- a/source/blender/editors/sculpt_paint/sculpt_mask_expand.c +++ b/source/blender/editors/sculpt_paint/sculpt_mask_expand.c @@ -361,7 +361,7 @@ static int sculpt_mask_expand_invoke(bContext *C, wmOperator *op, const wmEvent BKE_pbvh_search_gather(pbvh, NULL, NULL, &ss->filter_cache->nodes, &ss->filter_cache->totnode); - SCULPT_undo_push_begin(ob, "Mask Expand"); + SCULPT_undo_push_begin(ob, op); if (create_face_set) { SCULPT_undo_push_node(ob, ss->filter_cache->nodes[0], SCULPT_UNDO_FACE_SETS); @@ -391,7 +391,7 @@ static int sculpt_mask_expand_invoke(bContext *C, wmOperator *op, const wmEvent if (create_face_set) { ss->filter_cache->prev_face_set = MEM_callocN(sizeof(float) * ss->totfaces, "prev face mask"); for (int i = 0; i < ss->totfaces; i++) { - ss->filter_cache->prev_face_set[i] = ss->face_sets[i]; + ss->filter_cache->prev_face_set[i] = ss->face_sets ? ss->face_sets[i] : 0; } ss->filter_cache->new_face_set = SCULPT_face_set_next_available_get(ss); } diff --git a/source/blender/editors/sculpt_paint/sculpt_mask_init.c b/source/blender/editors/sculpt_paint/sculpt_mask_init.c index cc27623adb0..b9b889ab2ce 100644 --- a/source/blender/editors/sculpt_paint/sculpt_mask_init.c +++ b/source/blender/editors/sculpt_paint/sculpt_mask_init.c @@ -131,7 +131,7 @@ static int sculpt_mask_init_exec(bContext *C, wmOperator *op) return OPERATOR_CANCELLED; } - SCULPT_undo_push_begin(ob, "init mask"); + SCULPT_undo_push_begin(ob, op); if (mode == SCULPT_MASK_INIT_RANDOM_PER_LOOSE_PART) { SCULPT_connected_components_ensure(ob); diff --git a/source/blender/editors/sculpt_paint/sculpt_ops.c b/source/blender/editors/sculpt_paint/sculpt_ops.c index 151eb7744ea..52bfa61cd95 100644 --- a/source/blender/editors/sculpt_paint/sculpt_ops.c +++ b/source/blender/editors/sculpt_paint/sculpt_ops.c @@ -47,6 +47,7 @@ #include "BKE_image.h" #include "BKE_kelvinlet.h" #include "BKE_key.h" +#include "BKE_layer.h" #include "BKE_lib_id.h" #include "BKE_main.h" #include "BKE_mesh.h" @@ -116,24 +117,33 @@ static int sculpt_set_persistent_base_exec(bContext *C, wmOperator *UNUSED(op)) Object *ob = CTX_data_active_object(C); SculptSession *ss = ob->sculpt; - if (!ss) { + /* Do not allow in DynTopo just yet. */ + if (!ss || (ss && ss->bm)) { return OPERATOR_FINISHED; } SCULPT_vertex_random_access_ensure(ss); BKE_sculpt_update_object_for_edit(depsgraph, ob, false, false, false); - MEM_SAFE_FREE(ss->persistent_base); + SculptAttributeParams params = {0}; + params.permanent = true; + + ss->attrs.persistent_co = BKE_sculpt_attribute_ensure( + ob, ATTR_DOMAIN_POINT, CD_PROP_FLOAT3, SCULPT_ATTRIBUTE_NAME(persistent_co), ¶ms); + ss->attrs.persistent_no = BKE_sculpt_attribute_ensure( + ob, ATTR_DOMAIN_POINT, CD_PROP_FLOAT3, SCULPT_ATTRIBUTE_NAME(persistent_no), ¶ms); + ss->attrs.persistent_disp = BKE_sculpt_attribute_ensure( + ob, ATTR_DOMAIN_POINT, CD_PROP_FLOAT, SCULPT_ATTRIBUTE_NAME(persistent_disp), ¶ms); const int totvert = SCULPT_vertex_count_get(ss); - ss->persistent_base = MEM_mallocN(sizeof(SculptPersistentBase) * totvert, - "layer persistent base"); for (int i = 0; i < totvert; i++) { PBVHVertRef vertex = BKE_pbvh_index_to_vertex(ss->pbvh, i); - copy_v3_v3(ss->persistent_base[i].co, SCULPT_vertex_co_get(ss, vertex)); - SCULPT_vertex_normal_get(ss, vertex, ss->persistent_base[i].no); - ss->persistent_base[i].disp = 0.0f; + copy_v3_v3((float *)SCULPT_vertex_attr_get(vertex, ss->attrs.persistent_co), + SCULPT_vertex_co_get(ss, vertex)); + SCULPT_vertex_normal_get( + ss, vertex, (float *)SCULPT_vertex_attr_get(vertex, ss->attrs.persistent_no)); + (*(float *)SCULPT_vertex_attr_get(vertex, ss->attrs.persistent_disp)) = 0.0f; } return OPERATOR_FINISHED; @@ -215,7 +225,7 @@ static int sculpt_symmetrize_exec(bContext *C, wmOperator *op) * as deleted, then after symmetrize operation all BMesh elements * are logged as added (as opposed to attempting to store just the * parts that symmetrize modifies). */ - SCULPT_undo_push_begin(ob, "Dynamic topology symmetrize"); + SCULPT_undo_push_begin(ob, op); SCULPT_undo_push_node(ob, NULL, SCULPT_UNDO_DYNTOPO_SYMMETRIZE); BM_log_before_all_removed(ss->bm, ss->bm_log); @@ -242,7 +252,7 @@ static int sculpt_symmetrize_exec(bContext *C, wmOperator *op) break; case PBVH_FACES: /* Mesh Symmetrize. */ - ED_sculpt_undo_geometry_begin(ob, "mesh symmetrize"); + ED_sculpt_undo_geometry_begin(ob, op); Mesh *mesh = ob->data; BKE_mesh_mirror_apply_mirror_on_axis(bmain, mesh, sd->symmetrize_direction, dist); @@ -299,28 +309,34 @@ static void sculpt_init_session(Main *bmain, Depsgraph *depsgraph, Scene *scene, ob->sculpt = MEM_callocN(sizeof(SculptSession), "sculpt session"); ob->sculpt->mode_type = OB_MODE_SCULPT; - BKE_sculpt_ensure_orig_mesh_data(scene, ob); + /* Trigger evaluation of modifier stack to ensure + * multires modifier sets .runtime.ccg in + * the evaluated mesh. + */ + DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY); BKE_scene_graph_evaluated_ensure(depsgraph, bmain); /* This function expects a fully evaluated depsgraph. */ BKE_sculpt_update_object_for_edit(depsgraph, ob, false, false, false); - /* Here we can detect geometry that was just added to Sculpt Mode as it has the - * SCULPT_FACE_SET_NONE assigned, so we can create a new Face Set for it. */ - /* In sculpt mode all geometry that is assigned to SCULPT_FACE_SET_NONE is considered as not - * initialized, which is used is some operators that modify the mesh topology to perform certain - * actions in the new polys. After these operations are finished, all polys should have a valid - * face set ID assigned (different from SCULPT_FACE_SET_NONE) to manage their visibility - * correctly. */ - /* TODO(pablodp606): Based on this we can improve the UX in future tools for creating new - * objects, like moving the transform pivot position to the new area or masking existing - * geometry. */ SculptSession *ss = ob->sculpt; - const int new_face_set = SCULPT_face_set_next_available_get(ss); - for (int i = 0; i < ss->totfaces; i++) { - if (ss->face_sets[i] == SCULPT_FACE_SET_NONE) { - ss->face_sets[i] = new_face_set; + if (ss->face_sets) { + /* Here we can detect geometry that was just added to Sculpt Mode as it has the + * SCULPT_FACE_SET_NONE assigned, so we can create a new Face Set for it. */ + /* In sculpt mode all geometry that is assigned to SCULPT_FACE_SET_NONE is considered as not + * initialized, which is used is some operators that modify the mesh topology to perform + * certain actions in the new polys. After these operations are finished, all polys should have + * a valid face set ID assigned (different from SCULPT_FACE_SET_NONE) to manage their + * visibility correctly. */ + /* TODO(pablodp606): Based on this we can improve the UX in future tools for creating new + * objects, like moving the transform pivot position to the new area or masking existing + * geometry. */ + const int new_face_set = SCULPT_face_set_next_available_get(ss); + for (int i = 0; i < ss->totfaces; i++) { + if (ss->face_sets[i] == SCULPT_FACE_SET_NONE) { + ss->face_sets[i] = new_face_set; + } } } } @@ -394,7 +410,7 @@ void ED_object_sculptmode_enter_ex(Main *bmain, bool has_undo = wm->undo_stack != NULL; /* Undo push is needed to prevent memory leak. */ if (has_undo) { - SCULPT_undo_push_begin(ob, "Dynamic topology enable"); + SCULPT_undo_push_begin_ex(ob, "Dynamic topology enable"); } SCULPT_dynamic_topology_enable_ex(bmain, depsgraph, scene, ob); if (has_undo) { @@ -418,7 +434,8 @@ void ED_object_sculptmode_enter(struct bContext *C, Depsgraph *depsgraph, Report Main *bmain = CTX_data_main(C); Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); - Object *ob = OBACT(view_layer); + BKE_view_layer_synced_ensure(scene, view_layer); + Object *ob = BKE_view_layer_active_object_get(view_layer); ED_object_sculptmode_enter_ex(bmain, depsgraph, scene, ob, false, reports); } @@ -470,7 +487,8 @@ void ED_object_sculptmode_exit(bContext *C, Depsgraph *depsgraph) Main *bmain = CTX_data_main(C); Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); - Object *ob = OBACT(view_layer); + BKE_view_layer_synced_ensure(scene, view_layer); + Object *ob = BKE_view_layer_active_object_get(view_layer); ED_object_sculptmode_exit_ex(bmain, depsgraph, scene, ob); } @@ -482,7 +500,8 @@ static int sculpt_mode_toggle_exec(bContext *C, wmOperator *op) Scene *scene = CTX_data_scene(C); ToolSettings *ts = scene->toolsettings; ViewLayer *view_layer = CTX_data_view_layer(C); - Object *ob = OBACT(view_layer); + BKE_view_layer_synced_ensure(scene, view_layer); + Object *ob = BKE_view_layer_active_object_get(view_layer); const int mode_flag = OB_MODE_SCULPT; const bool is_mode_set = (ob->mode & mode_flag) != 0; @@ -510,7 +529,7 @@ static int sculpt_mode_toggle_exec(bContext *C, wmOperator *op) * while it works it causes lag when undoing the first undo step, see T71564. */ wmWindowManager *wm = CTX_wm_manager(C); if (wm->op_undo_depth <= 1) { - SCULPT_undo_push_begin(ob, op->type->name); + SCULPT_undo_push_begin(ob, op); SCULPT_undo_push_end(ob); } } @@ -570,49 +589,48 @@ void SCULPT_geometry_preview_lines_update(bContext *C, SculptSession *ss, float float brush_co[3]; copy_v3_v3(brush_co, SCULPT_active_vertex_co_get(ss)); - BLI_bitmap *visited_vertices = BLI_BITMAP_NEW(SCULPT_vertex_count_get(ss), "visited_vertices"); + BLI_bitmap *visited_verts = BLI_BITMAP_NEW(SCULPT_vertex_count_get(ss), "visited_verts"); /* Assuming an average of 6 edges per vertex in a triangulated mesh. */ - const int max_preview_vertices = SCULPT_vertex_count_get(ss) * 3 * 2; + const int max_preview_verts = SCULPT_vertex_count_get(ss) * 3 * 2; if (ss->preview_vert_list == NULL) { - ss->preview_vert_list = MEM_callocN(max_preview_vertices * sizeof(PBVHVertRef), - "preview lines"); + ss->preview_vert_list = MEM_callocN(max_preview_verts * sizeof(PBVHVertRef), "preview lines"); } - GSQueue *not_visited_vertices = BLI_gsqueue_new(sizeof(PBVHVertRef)); + GSQueue *non_visited_verts = BLI_gsqueue_new(sizeof(PBVHVertRef)); PBVHVertRef active_v = SCULPT_active_vertex_get(ss); - BLI_gsqueue_push(not_visited_vertices, &active_v); + BLI_gsqueue_push(non_visited_verts, &active_v); - while (!BLI_gsqueue_is_empty(not_visited_vertices)) { + while (!BLI_gsqueue_is_empty(non_visited_verts)) { PBVHVertRef from_v; - BLI_gsqueue_pop(not_visited_vertices, &from_v); + BLI_gsqueue_pop(non_visited_verts, &from_v); SculptVertexNeighborIter ni; SCULPT_VERTEX_NEIGHBORS_ITER_BEGIN (ss, from_v, ni) { - if (totpoints + (ni.size * 2) < max_preview_vertices) { + if (totpoints + (ni.size * 2) < max_preview_verts) { PBVHVertRef to_v = ni.vertex; int to_v_i = ni.index; ss->preview_vert_list[totpoints] = from_v; totpoints++; ss->preview_vert_list[totpoints] = to_v; totpoints++; - if (BLI_BITMAP_TEST(visited_vertices, to_v_i)) { + if (BLI_BITMAP_TEST(visited_verts, to_v_i)) { continue; } - BLI_BITMAP_ENABLE(visited_vertices, to_v_i); + BLI_BITMAP_ENABLE(visited_verts, to_v_i); const float *co = SCULPT_vertex_co_for_grab_active_get(ss, to_v); if (len_squared_v3v3(brush_co, co) < radius * radius) { - BLI_gsqueue_push(not_visited_vertices, &to_v); + BLI_gsqueue_push(non_visited_verts, &to_v); } } } SCULPT_VERTEX_NEIGHBORS_ITER_END(ni); } - BLI_gsqueue_free(not_visited_vertices); + BLI_gsqueue_free(non_visited_verts); - MEM_freeN(visited_vertices); + MEM_freeN(visited_verts); ss->preview_vert_count = totpoints; } @@ -921,7 +939,7 @@ static int sculpt_mask_by_color_invoke(bContext *C, wmOperator *op, const wmEven const float mval_fl[2] = {UNPACK2(event->mval)}; SCULPT_cursor_geometry_info_update(C, &sgi, mval_fl, false); - SCULPT_undo_push_begin(ob, "Mask by color"); + SCULPT_undo_push_begin(ob, op); BKE_sculpt_color_layer_create_if_needed(ob); const PBVHVertRef active_vertex = SCULPT_active_vertex_get(ss); diff --git a/source/blender/editors/sculpt_paint/sculpt_transform.c b/source/blender/editors/sculpt_paint/sculpt_transform.c index 7207e6c35d4..dfaa0bd4daa 100644 --- a/source/blender/editors/sculpt_paint/sculpt_transform.c +++ b/source/blender/editors/sculpt_paint/sculpt_transform.c @@ -46,7 +46,7 @@ #include <math.h> #include <stdlib.h> -void ED_sculpt_init_transform(struct bContext *C, Object *ob) +void ED_sculpt_init_transform(struct bContext *C, Object *ob, const char *undo_name) { Sculpt *sd = CTX_data_tool_settings(C)->sculpt; SculptSession *ss = ob->sculpt; @@ -60,7 +60,7 @@ void ED_sculpt_init_transform(struct bContext *C, Object *ob) copy_v4_v4(ss->prev_pivot_rot, ss->pivot_rot); copy_v3_v3(ss->prev_pivot_scale, ss->pivot_scale); - SCULPT_undo_push_begin(ob, "Transform"); + SCULPT_undo_push_begin_ex(ob, undo_name); BKE_sculpt_update_object_for_edit(depsgraph, ob, false, false, false); ss->pivot_rot[3] = 1.0f; @@ -351,11 +351,6 @@ void ED_sculpt_end_transform(struct bContext *C, Object *ob) if (ss->filter_cache) { SCULPT_filter_cache_free(ss); } - /* Force undo push to happen even inside transform operator, since the sculpt - * undo system works separate from regular undo and this is require to properly - * finish an undo step also when canceling. */ - const bool use_nested_undo = true; - SCULPT_undo_push_end_ex(ob, use_nested_undo); SCULPT_flush_update_done(C, ob, SCULPT_UPDATE_COORDS); } diff --git a/source/blender/editors/sculpt_paint/sculpt_undo.c b/source/blender/editors/sculpt_paint/sculpt_undo.c index 04b2b2f04bf..4d36ff4b623 100644 --- a/source/blender/editors/sculpt_paint/sculpt_undo.c +++ b/source/blender/editors/sculpt_paint/sculpt_undo.c @@ -4,6 +4,29 @@ /** \file * \ingroup edsculpt * Implements the Sculpt Mode tools. + * + * Usage Guide + * =========== + * + * The sculpt undo system is a delta-based system. Each undo step stores + * the difference with the prior one. + * + * To use the sculpt undo system, you must call SCULPT_undo_push_begin + * inside an operator exec or invoke callback (ED_sculpt_undo_geometry_begin + * may be called if you wish to save a non-delta copy of the entire mesh). + * This will initialize the sculpt undo stack and set up an undo step. + * + * At the end of the operator you should call SCULPT_undo_push_end. + * + * SCULPT_undo_push_end and ED_sculpt_undo_geometry_begin both take a + * #wmOperatorType as an argument. There are _ex versions that allow a custom + * name; try to avoid using them. These can break the redo panel since it requires + * the undo push have the same name as the calling operator. + * + * NOTE: Sculpt undo steps are not appended to the global undo stack until + * the operator finishes. We use BKE_undosys_step_push_init_with_type to build + * a tentative undo step with is appended later when the operator ends. + * Operators must have the OPTYPE_UNDO flag set for this to work properly. */ #include <stddef.h> @@ -30,6 +53,7 @@ #include "BKE_customdata.h" #include "BKE_global.h" #include "BKE_key.h" +#include "BKE_layer.h" #include "BKE_main.h" #include "BKE_mesh.h" #include "BKE_mesh_mapping.h" @@ -144,9 +168,9 @@ struct PartialUpdateData { PBVH *pbvh; bool rebuild; char *modified_grids; - bool *modified_hidden_vertices; - bool *modified_mask_vertices; - bool *modified_color_vertices; + bool *modified_hidden_verts; + bool *modified_mask_verts; + bool *modified_color_verts; }; /** @@ -177,25 +201,25 @@ static void update_cb_partial(PBVHNode *node, void *userdata) const int *vert_indices; BKE_pbvh_node_num_verts(data->pbvh, node, NULL, &verts_num); BKE_pbvh_node_get_verts(data->pbvh, node, &vert_indices, NULL); - if (data->modified_mask_vertices != NULL) { + if (data->modified_mask_verts != NULL) { for (int i = 0; i < verts_num; i++) { - if (data->modified_mask_vertices[vert_indices[i]]) { + if (data->modified_mask_verts[vert_indices[i]]) { BKE_pbvh_node_mark_update_mask(node); break; } } } - if (data->modified_color_vertices != NULL) { + if (data->modified_color_verts != NULL) { for (int i = 0; i < verts_num; i++) { - if (data->modified_color_vertices[vert_indices[i]]) { + if (data->modified_color_verts[vert_indices[i]]) { BKE_pbvh_node_mark_update_color(node); break; } } } - if (data->modified_hidden_vertices != NULL) { + if (data->modified_hidden_verts != NULL) { for (int i = 0; i < verts_num; i++) { - if (data->modified_hidden_vertices[vert_indices[i]]) { + if (data->modified_hidden_verts[vert_indices[i]]) { if (data->rebuild) { BKE_pbvh_node_mark_update_visibility(node); } @@ -229,8 +253,10 @@ static bool sculpt_undo_restore_deformed( static bool sculpt_undo_restore_coords(bContext *C, Depsgraph *depsgraph, SculptUndoNode *unode) { + const Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); - Object *ob = OBACT(view_layer); + BKE_view_layer_synced_ensure(scene, view_layer); + Object *ob = BKE_view_layer_active_object_get(view_layer); SculptSession *ss = ob->sculpt; SubdivCCG *subdiv_ccg = ss->subdiv_ccg; MVert *mvert; @@ -341,8 +367,10 @@ static bool sculpt_undo_restore_coords(bContext *C, Depsgraph *depsgraph, Sculpt static bool sculpt_undo_restore_hidden(bContext *C, SculptUndoNode *unode, bool *modified_vertices) { + const Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); - Object *ob = OBACT(view_layer); + BKE_view_layer_synced_ensure(scene, view_layer); + Object *ob = BKE_view_layer_active_object_get(view_layer); SculptSession *ss = ob->sculpt; SubdivCCG *subdiv_ccg = ss->subdiv_ccg; @@ -350,10 +378,11 @@ static bool sculpt_undo_restore_hidden(bContext *C, SculptUndoNode *unode, bool if (unode->maxvert) { for (int i = 0; i < unode->totvert; i++) { - if ((BLI_BITMAP_TEST(unode->vert_hidden, i) != 0) != hide_vert[i]) { + const int vert_index = unode->index[i]; + if ((BLI_BITMAP_TEST(unode->vert_hidden, i) != 0) != hide_vert[vert_index]) { BLI_BITMAP_FLIP(unode->vert_hidden, i); - hide_vert[unode->index[i]] = !hide_vert[i]; - modified_vertices[unode->index[i]] = true; + hide_vert[vert_index] = !hide_vert[vert_index]; + modified_vertices[vert_index] = true; } } } @@ -370,8 +399,10 @@ static bool sculpt_undo_restore_hidden(bContext *C, SculptUndoNode *unode, bool static bool sculpt_undo_restore_color(bContext *C, SculptUndoNode *unode, bool *modified_vertices) { + const Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); - Object *ob = OBACT(view_layer); + BKE_view_layer_synced_ensure(scene, view_layer); + Object *ob = BKE_view_layer_active_object_get(view_layer); SculptSession *ss = ob->sculpt; bool modified = false; @@ -402,8 +433,10 @@ static bool sculpt_undo_restore_color(bContext *C, SculptUndoNode *unode, bool * static bool sculpt_undo_restore_mask(bContext *C, SculptUndoNode *unode, bool *modified_vertices) { + const Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); - Object *ob = OBACT(view_layer); + BKE_view_layer_synced_ensure(scene, view_layer); + Object *ob = BKE_view_layer_active_object_get(view_layer); SculptSession *ss = ob->sculpt; SubdivCCG *subdiv_ccg = ss->subdiv_ccg; float *vmask; @@ -448,12 +481,15 @@ static bool sculpt_undo_restore_mask(bContext *C, SculptUndoNode *unode, bool *m static bool sculpt_undo_restore_face_sets(bContext *C, SculptUndoNode *unode) { + const Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); - Object *ob = OBACT(view_layer); + BKE_view_layer_synced_ensure(scene, view_layer); + Object *ob = BKE_view_layer_active_object_get(view_layer); Mesh *me = BKE_object_get_original_mesh(ob); - int *face_sets = CustomData_get_layer(&me->pdata, CD_SCULPT_FACE_SETS); + int *face_sets = CustomData_add_layer_named( + &me->pdata, CD_PROP_INT32, CD_CONSTRUCT, NULL, me->totpoly, ".sculpt_face_set"); for (int i = 0; i < me->totpoly; i++) { - face_sets[i] = unode->face_sets[i]; + SWAP(int, face_sets[i], unode->face_sets[i]); } return false; } @@ -511,7 +547,7 @@ static void sculpt_undo_bmesh_enable(Object *ob, SculptUndoNode *unode) .use_toolflags = false, })); BM_data_layer_add(ss->bm, &ss->bm->vdata, CD_PAINT_MASK); - SCULPT_dyntopo_node_layers_add(ss); + me->flag |= ME_SCULPT_DYNAMIC_TOPOLOGY; /* Restore the BMLog using saved entries. */ @@ -602,8 +638,6 @@ static void sculpt_undo_geometry_restore_data(SculptUndoNodeGeometry *geometry, CustomData_copy( &geometry->pdata, &mesh->pdata, CD_MASK_MESH.pmask, CD_DUPLICATE, geometry->totpoly); - BKE_mesh_update_customdata_pointers(mesh, false); - BKE_mesh_runtime_clear_cache(mesh); } @@ -698,7 +732,8 @@ static void sculpt_undo_restore_list(bContext *C, Depsgraph *depsgraph, ListBase Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); View3D *v3d = CTX_wm_view3d(C); - Object *ob = OBACT(view_layer); + BKE_view_layer_synced_ensure(scene, view_layer); + Object *ob = BKE_view_layer_active_object_get(view_layer); SculptSession *ss = ob->sculpt; SubdivCCG *subdiv_ccg = ss->subdiv_ccg; SculptUndoNode *unode; @@ -732,7 +767,7 @@ static void sculpt_undo_restore_list(bContext *C, Depsgraph *depsgraph, ListBase BKE_sculpt_update_object_for_edit(depsgraph, ob, true, need_mask, false); - SCULPT_visibility_sync_all_face_sets_to_vertices(ob); + SCULPT_visibility_sync_all_from_faces(ob); BKE_pbvh_update_vertex_data(ss->pbvh, PBVH_UpdateVisibility); @@ -767,9 +802,9 @@ static void sculpt_undo_restore_list(bContext *C, Depsgraph *depsgraph, ListBase /* The PBVH already keeps track of which vertices need updated normals, but it doesn't keep track * of other updated. In order to tell the corresponding PBVH nodes to update, keep track of which * elements were updated for specific layers. */ - bool *modified_hidden_vertices = NULL; - bool *modified_mask_vertices = NULL; - bool *modified_color_vertices = NULL; + bool *modified_hidden_verts = NULL; + bool *modified_mask_verts = NULL; + bool *modified_color_verts = NULL; char *undo_modified_grids = NULL; bool use_multires_undo = false; @@ -802,19 +837,19 @@ static void sculpt_undo_restore_list(bContext *C, Depsgraph *depsgraph, ListBase } break; case SCULPT_UNDO_HIDDEN: - if (modified_hidden_vertices == NULL) { - modified_hidden_vertices = MEM_calloc_arrayN(ss->totvert, sizeof(bool), __func__); + if (modified_hidden_verts == NULL) { + modified_hidden_verts = MEM_calloc_arrayN(ss->totvert, sizeof(bool), __func__); } - if (sculpt_undo_restore_hidden(C, unode, modified_hidden_vertices)) { + if (sculpt_undo_restore_hidden(C, unode, modified_hidden_verts)) { rebuild = true; update_visibility = true; } break; case SCULPT_UNDO_MASK: - if (modified_mask_vertices == NULL) { - modified_mask_vertices = MEM_calloc_arrayN(ss->totvert, sizeof(bool), __func__); + if (modified_mask_verts == NULL) { + modified_mask_verts = MEM_calloc_arrayN(ss->totvert, sizeof(bool), __func__); } - if (sculpt_undo_restore_mask(C, unode, modified_mask_vertices)) { + if (sculpt_undo_restore_mask(C, unode, modified_mask_verts)) { update = true; update_mask = true; } @@ -822,10 +857,10 @@ static void sculpt_undo_restore_list(bContext *C, Depsgraph *depsgraph, ListBase case SCULPT_UNDO_FACE_SETS: break; case SCULPT_UNDO_COLOR: - if (modified_color_vertices == NULL) { - modified_color_vertices = MEM_calloc_arrayN(ss->totvert, sizeof(bool), __func__); + if (modified_color_verts == NULL) { + modified_color_verts = MEM_calloc_arrayN(ss->totvert, sizeof(bool), __func__); } - if (sculpt_undo_restore_color(C, unode, modified_color_vertices)) { + if (sculpt_undo_restore_color(C, unode, modified_color_verts)) { update = true; } @@ -876,10 +911,9 @@ static void sculpt_undo_restore_list(bContext *C, Depsgraph *depsgraph, ListBase .rebuild = rebuild, .pbvh = ss->pbvh, .modified_grids = undo_modified_grids, - .modified_hidden_vertices = modified_hidden_vertices, - .modified_mask_vertices = modified_mask_vertices, - .modified_color_vertices = modified_color_vertices, - + .modified_hidden_verts = modified_hidden_verts, + .modified_mask_verts = modified_mask_verts, + .modified_color_verts = modified_color_verts, }; BKE_pbvh_search_callback(ss->pbvh, NULL, NULL, update_cb_partial, &data); BKE_pbvh_update_bounds(ss->pbvh, PBVH_UpdateBB | PBVH_UpdateOriginalBB | PBVH_UpdateRedraw); @@ -889,7 +923,6 @@ static void sculpt_undo_restore_list(bContext *C, Depsgraph *depsgraph, ListBase } if (update_visibility) { - SCULPT_visibility_sync_all_vertex_to_face_sets(ss); BKE_pbvh_update_visibility(ss->pbvh); } @@ -925,9 +958,9 @@ static void sculpt_undo_restore_list(bContext *C, Depsgraph *depsgraph, ListBase } } - MEM_SAFE_FREE(modified_hidden_vertices); - MEM_SAFE_FREE(modified_mask_vertices); - MEM_SAFE_FREE(modified_color_vertices); + MEM_SAFE_FREE(modified_hidden_verts); + MEM_SAFE_FREE(modified_mask_verts); + MEM_SAFE_FREE(modified_color_verts); MEM_SAFE_FREE(undo_modified_grids); } @@ -999,7 +1032,7 @@ static bool sculpt_undo_cleanup(bContext *C, ListBase *lb) { Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); - Object *ob = OBACT(view_layer); + Object *ob = BKE_view_layer_active_object_get(view_layer); SculptUndoNode *unode; unode = lb->first; @@ -1142,8 +1175,7 @@ static SculptUndoNode *sculpt_undo_alloc_node(Object *ob, PBVHNode *node, Sculpt unode->co = MEM_callocN(alloc_size, "SculptUndoNode.co"); usculpt->undo_size += alloc_size; - /* FIXME: Should explain why this is allocated here, to be freed in - * `SCULPT_undo_push_end_ex()`? */ + /* Needed for original data lookup. */ alloc_size = sizeof(*unode->no) * (size_t)allvert; unode->no = MEM_callocN(alloc_size, "SculptUndoNode.no"); usculpt->undo_size += alloc_size; @@ -1332,9 +1364,14 @@ static SculptUndoNode *sculpt_undo_face_sets_push(Object *ob, SculptUndoType typ unode->face_sets = MEM_callocN(me->totpoly * sizeof(int), "sculpt face sets"); - const int *face_sets = CustomData_get_layer(&me->pdata, CD_SCULPT_FACE_SETS); - for (int i = 0; i < me->totpoly; i++) { - unode->face_sets[i] = face_sets[i]; + const int *face_sets = CustomData_get_layer_named(&me->pdata, CD_PROP_INT32, ".sculpt_face_set"); + if (face_sets) { + for (int i = 0; i < me->totpoly; i++) { + unode->face_sets[i] = face_sets[i]; + } + } + else { + memset(unode->face_sets, SCULPT_FACE_SET_NONE, sizeof(int) * me->totpoly); } BLI_addtail(&usculpt->nodes, unode); @@ -1492,7 +1529,9 @@ SculptUndoNode *SCULPT_undo_push_node(Object *ob, PBVHNode *node, SculptUndoType sculpt_undo_store_hidden(ob, unode); break; case SCULPT_UNDO_MASK: - sculpt_undo_store_mask(ob, unode); + if (pbvh_has_mask(ss->pbvh)) { + sculpt_undo_store_mask(ob, unode); + } break; case SCULPT_UNDO_COLOR: sculpt_undo_store_color(ob, unode); @@ -1546,7 +1585,12 @@ static void sculpt_save_active_attribute(Object *ob, SculptAttrRef *attr) attr->was_set = true; } -void SCULPT_undo_push_begin(Object *ob, const char *name) +void SCULPT_undo_push_begin(Object *ob, const wmOperator *op) +{ + SCULPT_undo_push_begin_ex(ob, op->type->name); +} + +void SCULPT_undo_push_begin_ex(Object *ob, const char *name) { UndoStack *ustack = ED_undo_stack_get(); @@ -1642,11 +1686,12 @@ static void sculpt_undo_set_active_layer(struct bContext *C, SculptAttrRef *attr */ if (!layer) { layer = BKE_id_attribute_search(&me->id, attr->name, CD_MASK_PROP_ALL, ATTR_DOMAIN_MASK_ALL); - eAttrDomain domain = layer ? BKE_id_attribute_domain(&me->id, layer) : ATTR_DOMAIN_NUM; - - if (layer && ED_geometry_attribute_convert( - me, attr->name, layer->type, domain, attr->type, attr->domain)) { - layer = BKE_id_attribute_find(&me->id, attr->name, attr->type, attr->domain); + if (layer) { + const eAttrDomain domain = BKE_id_attribute_domain(&me->id, layer); + if (ED_geometry_attribute_convert( + me, attr->name, layer->type, domain, attr->type, attr->domain)) { + layer = BKE_id_attribute_find(&me->id, attr->name, attr->type, attr->domain); + } } } @@ -1655,7 +1700,7 @@ static void sculpt_undo_set_active_layer(struct bContext *C, SculptAttrRef *attr CustomData *cdata = attr->domain == ATTR_DOMAIN_POINT ? &me->vdata : &me->ldata; int totelem = attr->domain == ATTR_DOMAIN_POINT ? me->totvert : me->totloop; - CustomData_add_layer_named(cdata, attr->type, CD_DEFAULT, NULL, totelem, attr->name); + CustomData_add_layer_named(cdata, attr->type, CD_SET_DEFAULT, NULL, totelem, attr->name); layer = BKE_id_attribute_find(&me->id, attr->name, attr->type, attr->domain); } @@ -1788,7 +1833,8 @@ static void sculpt_undosys_step_decode( { Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); - Object *ob = OBACT(view_layer); + BKE_view_layer_synced_ensure(scene, view_layer); + Object *ob = BKE_view_layer_active_object_get(view_layer); if (ob && (ob->type == OB_MESH)) { if (ob->mode & (OB_MODE_SCULPT | OB_MODE_VERTEX_PAINT)) { /* Pass. */ @@ -1834,9 +1880,15 @@ static void sculpt_undosys_step_free(UndoStep *us_p) sculpt_undo_free_list(&us->data.nodes); } -void ED_sculpt_undo_geometry_begin(struct Object *ob, const char *name) +void ED_sculpt_undo_geometry_begin(struct Object *ob, const wmOperator *op) +{ + SCULPT_undo_push_begin(ob, op); + SCULPT_undo_push_node(ob, NULL, SCULPT_UNDO_GEOMETRY); +} + +void ED_sculpt_undo_geometry_begin_ex(struct Object *ob, const char *name) { - SCULPT_undo_push_begin(ob, name); + SCULPT_undo_push_begin_ex(ob, name); SCULPT_undo_push_node(ob, NULL, SCULPT_UNDO_GEOMETRY); } @@ -1949,7 +2001,7 @@ void ED_sculpt_undo_push_multires_mesh_begin(bContext *C, const char *str) Object *object = CTX_data_active_object(C); - SCULPT_undo_push_begin(object, str); + SCULPT_undo_push_begin_ex(object, str); SculptUndoNode *geometry_unode = SCULPT_undo_push_node(object, NULL, SCULPT_UNDO_GEOMETRY); geometry_unode->geometry_clear_pbvh = false; diff --git a/source/blender/editors/sculpt_paint/sculpt_uv.c b/source/blender/editors/sculpt_paint/sculpt_uv.c index 14b06f888fe..4739fa52674 100644 --- a/source/blender/editors/sculpt_paint/sculpt_uv.c +++ b/source/blender/editors/sculpt_paint/sculpt_uv.c @@ -9,7 +9,7 @@ #include "MEM_guardedalloc.h" #include "BLI_ghash.h" -#include "BLI_math.h" +#include "BLI_math_base_safe.h" #include "BLI_utildefines.h" #include "DNA_brush_types.h" @@ -22,6 +22,7 @@ #include "BKE_context.h" #include "BKE_customdata.h" #include "BKE_editmesh.h" +#include "BKE_image.h" #include "BKE_mesh_mapping.h" #include "BKE_paint.h" @@ -30,6 +31,7 @@ #include "ED_image.h" #include "ED_mesh.h" #include "ED_screen.h" +#include "ED_uvedit.h" #include "WM_api.h" #include "WM_types.h" @@ -42,6 +44,9 @@ #include "UI_view2d.h" +/* When set, the UV element is on the boundary of the graph. + * i.e. Instead of a 2-dimensional laplace operator, use a 1-dimensional version. + * Visually, UV elements on the graph boundary appear as borders of the UV Island. */ #define MARK_BOUNDARY 1 typedef struct UvAdjacencyElement { @@ -49,16 +54,17 @@ typedef struct UvAdjacencyElement { UvElement *element; /* uv pointer for convenience. Caution, this points to the original UVs! */ float *uv; - /* general use flag (Used to check if Element is boundary here) */ - char flag; + /* Are we on locked in place? */ + bool is_locked; + /* Are we on the boundary? */ + bool is_boundary; } UvAdjacencyElement; typedef struct UvEdge { uint uv1; uint uv2; - /* general use flag - * (Used to check if edge is boundary here, and propagates to adjacency elements) */ - char flag; + /* Are we in the interior? */ + bool is_interior; } UvEdge; typedef struct UVInitialStrokeElement { @@ -90,13 +96,13 @@ typedef struct UvSculptData { * to their coincident UV's */ UvAdjacencyElement *uv; - /* ...Is what it says */ + /* Total number of unique UVs. */ int totalUniqueUvs; /* Edges used for adjacency info, used with laplacian smoothing */ UvEdge *uvedges; - /* need I say more? */ + /* Total number of #UvEdge. */ int totalUvEdges; /* data for initial stroke, used by tools like grab */ @@ -116,8 +122,25 @@ typedef struct UvSculptData { /* store invert flag here */ char invert; + + /* Is constrain to image bounds active? */ + bool constrain_to_bounds; + + /* Base for constrain_to_bounds. */ + float uv_base_offset[2]; } UvSculptData; +static void apply_sculpt_data_constraints(UvSculptData *sculptdata, float uv[2]) +{ + if (!sculptdata->constrain_to_bounds) { + return; + } + float u = sculptdata->uv_base_offset[0]; + float v = sculptdata->uv_base_offset[1]; + uv[0] = clamp_f(uv[0], u, u + 1.0f); + uv[1] = clamp_f(uv[1], v, v + 1.0f); +} + /*********** Improved Laplacian Relaxation Operator ************************/ /* original code by Raul Fernandez Hernandez "farsthary" * * adapted to uv smoothing by Antony Riakiatakis * @@ -170,17 +193,14 @@ static void HC_relaxation_iteration_uv(BMEditMesh *em, } for (i = 0; i < sculptdata->totalUniqueUvs; i++) { - float dist; - /* This is supposed to happen only if "Pin Edges" is on, - * since we have initialization on stroke start. - * If ever uv brushes get their own mode we should check for toolsettings option too. */ - if (sculptdata->uv[i].flag & MARK_BOUNDARY) { + if (sculptdata->uv[i].is_locked) { continue; } sub_v2_v2v2(diff, sculptdata->uv[i].uv, mouse_coord); diff[1] /= aspectRatio; - if ((dist = dot_v2v2(diff, diff)) <= radius) { + float dist = dot_v2v2(diff, diff); + if (dist <= radius) { UvElement *element; float strength; strength = alpha * BKE_brush_curve_strength_clamped(brush, sqrtf(dist), radius_root); @@ -196,6 +216,8 @@ static void HC_relaxation_iteration_uv(BMEditMesh *em, 0.5f * (tmp_uvdata[i].b[1] + tmp_uvdata[i].sum_b[1] / tmp_uvdata[i].ncounter)); + apply_sculpt_data_constraints(sculptdata, sculptdata->uv[i].uv); + for (element = sculptdata->uv[i].element; element; element = element->next) { MLoopUV *luv; BMLoop *l; @@ -214,6 +236,13 @@ static void HC_relaxation_iteration_uv(BMEditMesh *em, MEM_SAFE_FREE(tmp_uvdata); } +/* Legacy version which only does laplacian relaxation. + * Probably a little faster as it caches UvEdges. + * Mostly preserved for comparison with `HC_relaxation_iteration_uv`. + * Once the HC method has been merged into `relaxation_iteration_uv`, + * all the `HC_*` and `laplacian_*` specific functions can probably be removed. + */ + static void laplacian_relaxation_iteration_uv(BMEditMesh *em, UvSculptData *sculptdata, const float mouse_coord[2], @@ -233,11 +262,16 @@ static void laplacian_relaxation_iteration_uv(BMEditMesh *em, /* counting neighbors */ for (i = 0; i < sculptdata->totalUvEdges; i++) { UvEdge *tmpedge = sculptdata->uvedges + i; - tmp_uvdata[tmpedge->uv1].ncounter++; - tmp_uvdata[tmpedge->uv2].ncounter++; - - add_v2_v2(tmp_uvdata[tmpedge->uv2].sum_co, sculptdata->uv[tmpedge->uv1].uv); - add_v2_v2(tmp_uvdata[tmpedge->uv1].sum_co, sculptdata->uv[tmpedge->uv2].uv); + bool code1 = sculptdata->uv[sculptdata->uvedges[i].uv1].is_boundary; + bool code2 = sculptdata->uv[sculptdata->uvedges[i].uv2].is_boundary; + if (code1 || (code1 == code2)) { + tmp_uvdata[tmpedge->uv2].ncounter++; + add_v2_v2(tmp_uvdata[tmpedge->uv2].sum_co, sculptdata->uv[tmpedge->uv1].uv); + } + if (code2 || (code1 == code2)) { + tmp_uvdata[tmpedge->uv1].ncounter++; + add_v2_v2(tmp_uvdata[tmpedge->uv1].sum_co, sculptdata->uv[tmpedge->uv2].uv); + } } /* Original Laplacian algorithm included removal of normal component of translation. @@ -248,17 +282,14 @@ static void laplacian_relaxation_iteration_uv(BMEditMesh *em, } for (i = 0; i < sculptdata->totalUniqueUvs; i++) { - float dist; - /* This is supposed to happen only if "Pin Edges" is on, - * since we have initialization on stroke start. - * If ever uv brushes get their own mode we should check for toolsettings option too. */ - if (sculptdata->uv[i].flag & MARK_BOUNDARY) { + if (sculptdata->uv[i].is_locked) { continue; } sub_v2_v2v2(diff, sculptdata->uv[i].uv, mouse_coord); diff[1] /= aspectRatio; - if ((dist = dot_v2v2(diff, diff)) <= radius) { + float dist = dot_v2v2(diff, diff); + if (dist <= radius) { UvElement *element; float strength; strength = alpha * BKE_brush_curve_strength_clamped(brush, sqrtf(dist), radius_root); @@ -268,6 +299,8 @@ static void laplacian_relaxation_iteration_uv(BMEditMesh *em, sculptdata->uv[i].uv[1] = (1.0f - strength) * sculptdata->uv[i].uv[1] + strength * tmp_uvdata[i].p[1]; + apply_sculpt_data_constraints(sculptdata, sculptdata->uv[i].uv); + for (element = sculptdata->uv[i].element; element; element = element->next) { MLoopUV *luv; BMLoop *l; @@ -286,6 +319,153 @@ static void laplacian_relaxation_iteration_uv(BMEditMesh *em, MEM_SAFE_FREE(tmp_uvdata); } +static void add_weighted_edge(float (*delta_buf)[3], + const UvElement *storage, + const UvElement *ele_next, + const UvElement *ele_prev, + const MLoopUV *luv_next, + const MLoopUV *luv_prev, + const float weight) +{ + float delta[2]; + sub_v2_v2v2(delta, luv_next->uv, luv_prev->uv); + + bool code1 = (ele_prev->flag & MARK_BOUNDARY); + bool code2 = (ele_next->flag & MARK_BOUNDARY); + if (code1 || (code1 == code2)) { + int index_next = ele_next - storage; + delta_buf[index_next][0] -= delta[0] * weight; + delta_buf[index_next][1] -= delta[1] * weight; + delta_buf[index_next][2] += fabsf(weight); + } + if (code2 || (code1 == code2)) { + int index_prev = ele_prev - storage; + delta_buf[index_prev][0] += delta[0] * weight; + delta_buf[index_prev][1] += delta[1] * weight; + delta_buf[index_prev][2] += fabsf(weight); + } +} + +static float tri_weight_v3(int method, const float *v1, const float *v2, const float *v3) +{ + switch (method) { + case UV_SCULPT_TOOL_RELAX_LAPLACIAN: + case UV_SCULPT_TOOL_RELAX_HC: + return 1.0f; + case UV_SCULPT_TOOL_RELAX_COTAN: + return cotangent_tri_weight_v3(v1, v2, v3); + default: + BLI_assert_unreachable(); + } + return 0.0f; +} + +static void relaxation_iteration_uv(BMEditMesh *em, + UvSculptData *sculptdata, + const float mouse_coord[2], + const float alpha, + const float radius_squared, + const float aspect_ratio, + const int method) +{ + if (method == UV_SCULPT_TOOL_RELAX_HC) { + HC_relaxation_iteration_uv(em, sculptdata, mouse_coord, alpha, radius_squared, aspect_ratio); + return; + } + if (method == UV_SCULPT_TOOL_RELAX_LAPLACIAN) { + laplacian_relaxation_iteration_uv( + em, sculptdata, mouse_coord, alpha, radius_squared, aspect_ratio); + return; + } + + struct UvElement **head_table = BM_uv_element_map_ensure_head_table(sculptdata->elementMap); + + const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV); + BLI_assert(cd_loop_uv_offset >= 0); + + const int total_uvs = sculptdata->elementMap->total_uvs; + float(*delta_buf)[3] = (float(*)[3])MEM_callocN(total_uvs * sizeof(float[3]), __func__); + + const UvElement *storage = sculptdata->elementMap->storage; + for (int j = 0; j < total_uvs; j++) { + const UvElement *ele_curr = storage + j; + const BMFace *efa = ele_curr->l->f; + const UvElement *ele_next = BM_uv_element_get(sculptdata->elementMap, efa, ele_curr->l->next); + const UvElement *ele_prev = BM_uv_element_get(sculptdata->elementMap, efa, ele_curr->l->prev); + + const float *v_curr_co = ele_curr->l->v->co; + const float *v_prev_co = ele_prev->l->v->co; + const float *v_next_co = ele_next->l->v->co; + + const MLoopUV *luv_curr = BM_ELEM_CD_GET_VOID_P(ele_curr->l, cd_loop_uv_offset); + const MLoopUV *luv_next = BM_ELEM_CD_GET_VOID_P(ele_next->l, cd_loop_uv_offset); + const MLoopUV *luv_prev = BM_ELEM_CD_GET_VOID_P(ele_prev->l, cd_loop_uv_offset); + + const UvElement *head_curr = head_table[ele_curr - sculptdata->elementMap->storage]; + const UvElement *head_next = head_table[ele_next - sculptdata->elementMap->storage]; + const UvElement *head_prev = head_table[ele_prev - sculptdata->elementMap->storage]; + + /* If the mesh is triangulated with no boundaries, only one edge is required. */ + const float weight_curr = tri_weight_v3(method, v_curr_co, v_prev_co, v_next_co); + add_weighted_edge(delta_buf, storage, head_next, head_prev, luv_next, luv_prev, weight_curr); + + /* Triangulated with a boundary? We need the incoming edges to solve the boundary. */ + const float weight_prev = tri_weight_v3(method, v_prev_co, v_curr_co, v_next_co); + add_weighted_edge(delta_buf, storage, head_next, head_curr, luv_next, luv_curr, weight_prev); + + if (method == UV_SCULPT_TOOL_RELAX_LAPLACIAN) { + /* Laplacian method has zero weights on virtual edges. */ + continue; + } + + /* Meshes with quads (or other n-gons) need "virtual" edges too. */ + const float weight_next = tri_weight_v3(method, v_next_co, v_curr_co, v_prev_co); + add_weighted_edge(delta_buf, storage, head_prev, head_curr, luv_prev, luv_curr, weight_next); + } + + Brush *brush = BKE_paint_brush(sculptdata->uvsculpt); + for (int i = 0; i < sculptdata->totalUniqueUvs; i++) { + UvAdjacencyElement *adj_el = &sculptdata->uv[i]; + if (adj_el->is_locked) { + continue; /* Locked UVs can't move. */ + } + + /* Is UV within brush's influence? */ + float diff[2]; + sub_v2_v2v2(diff, adj_el->uv, mouse_coord); + diff[1] /= aspect_ratio; + const float dist_squared = len_squared_v2(diff); + if (dist_squared > radius_squared) { + continue; + } + const float strength = alpha * BKE_brush_curve_strength_clamped( + brush, sqrtf(dist_squared), sqrtf(radius_squared)); + + const float *delta_sum = delta_buf[adj_el->element - storage]; + + { + MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(adj_el->element->l, cd_loop_uv_offset); + BLI_assert(adj_el->uv == luv->uv); /* Only true for head. */ + adj_el->uv[0] = luv->uv[0] + strength * safe_divide(delta_sum[0], delta_sum[2]); + adj_el->uv[1] = luv->uv[1] + strength * safe_divide(delta_sum[1], delta_sum[2]); + apply_sculpt_data_constraints(sculptdata, adj_el->uv); + } + + /* Copy UV co-ordinates to all UvElements. */ + UvElement *tail = adj_el->element; + while (tail) { + MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(tail->l, cd_loop_uv_offset); + copy_v2_v2(luv->uv, adj_el->uv); + tail = tail->next; + if (tail && tail->separate) { + break; + } + } + } + + MEM_SAFE_FREE(delta_buf); +} + static void uv_sculpt_stroke_apply(bContext *C, wmOperator *op, const wmEvent *event, @@ -327,17 +507,15 @@ static void uv_sculpt_stroke_apply(bContext *C, int i; alpha *= invert; for (i = 0; i < sculptdata->totalUniqueUvs; i++) { - float dist, diff[2]; - /* This is supposed to happen only if "Lock Borders" is on, - * since we have initialization on stroke start. - * If ever uv brushes get their own mode we should check for toolsettings option too. */ - if (sculptdata->uv[i].flag & MARK_BOUNDARY) { + if (sculptdata->uv[i].is_locked) { continue; } + float diff[2]; sub_v2_v2v2(diff, sculptdata->uv[i].uv, co); diff[1] /= aspectRatio; - if ((dist = dot_v2v2(diff, diff)) <= radius) { + float dist = dot_v2v2(diff, diff); + if (dist <= radius) { UvElement *element; float strength; strength = alpha * BKE_brush_curve_strength_clamped(brush, sqrtf(dist), radius_root); @@ -346,6 +524,8 @@ static void uv_sculpt_stroke_apply(bContext *C, sculptdata->uv[i].uv[0] -= strength * diff[0] * 0.001f; sculptdata->uv[i].uv[1] -= strength * diff[1] * 0.001f; + apply_sculpt_data_constraints(sculptdata, sculptdata->uv[i].uv); + for (element = sculptdata->uv[i].element; element; element = element->next) { MLoopUV *luv; BMLoop *l; @@ -363,16 +543,11 @@ static void uv_sculpt_stroke_apply(bContext *C, } /* - * Smooth Tool + * Relax Tool */ else if (tool == UV_SCULPT_TOOL_RELAX) { - uint method = toolsettings->uv_relax_method; - if (method == UV_SCULPT_TOOL_RELAX_HC) { - HC_relaxation_iteration_uv(em, sculptdata, co, alpha, radius, aspectRatio); - } - else { - laplacian_relaxation_iteration_uv(em, sculptdata, co, alpha, radius, aspectRatio); - } + relaxation_iteration_uv( + em, sculptdata, co, alpha, radius, aspectRatio, toolsettings->uv_relax_method); } /* @@ -392,6 +567,8 @@ static void uv_sculpt_stroke_apply(bContext *C, sculptdata->uv[uvindex].uv[1] = sculptdata->initial_stroke->initialSelection[i].initial_uv[1] + strength * diff[1]; + apply_sculpt_data_constraints(sculptdata, sculptdata->uv[uvindex].uv); + for (element = sculptdata->uv[uvindex].element; element; element = element->next) { MLoopUV *luv; BMLoop *l; @@ -405,11 +582,18 @@ static void uv_sculpt_stroke_apply(bContext *C, copy_v2_v2(luv->uv, sculptdata->uv[uvindex].uv); } } + if (sima->flag & SI_LIVE_UNWRAP) { + ED_uvedit_live_unwrap_re_solve(); + } } } static void uv_sculpt_stroke_exit(bContext *C, wmOperator *op) { + SpaceImage *sima = CTX_wm_space_image(C); + if (sima->flag & SI_LIVE_UNWRAP) { + ED_uvedit_live_unwrap_end(false); + } UvSculptData *data = op->customdata; if (data->timer) { WM_event_remove_timer(CTX_wm_manager(C), CTX_wm_window(C), data->timer); @@ -454,6 +638,17 @@ static bool uv_edge_compare(const void *a, const void *b) return true; } +static void set_element_flag(UvElement *element, const int flag) +{ + while (element) { + element->flag |= flag; + element = element->next; + if (!element || element->separate) { + break; + } + } +} + static UvSculptData *uv_sculpt_stroke_init(bContext *C, wmOperator *op, const wmEvent *event) { Scene *scene = CTX_data_scene(C); @@ -481,8 +676,6 @@ static UvSculptData *uv_sculpt_stroke_init(bContext *C, wmOperator *op, const wm bool do_island_optimization = !(ts->uv_sculpt_settings & UV_SCULPT_ALL_ISLANDS); int island_index = 0; - /* Holds, for each UvElement in elementMap, an index of its unique UV. */ - int *uniqueUv; data->tool = (RNA_enum_get(op->ptr, "mode") == BRUSH_STROKE_SMOOTH) ? UV_SCULPT_TOOL_RELAX : ts->uvsculpt->paint.brush->uv_sculpt_tool; @@ -493,9 +686,10 @@ static UvSculptData *uv_sculpt_stroke_init(bContext *C, wmOperator *op, const wm /* Winding was added to island detection in 5197aa04c6bd * However the sculpt tools can flip faces, potentially creating orphaned islands. * See T100132 */ - bool use_winding = false; + const bool use_winding = false; + const bool use_seams = true; data->elementMap = BM_uv_element_map_create( - bm, scene, false, use_winding, do_island_optimization); + bm, scene, false, use_winding, use_seams, do_island_optimization); if (!data->elementMap) { uv_sculpt_stroke_exit(C, op); @@ -522,12 +716,13 @@ static UvSculptData *uv_sculpt_stroke_init(bContext *C, wmOperator *op, const wm } /* Allocate the unique uv buffers */ - data->uv = MEM_mallocN(sizeof(*data->uv) * unique_uvs, "uv_brush_unique_uvs"); - uniqueUv = MEM_mallocN(sizeof(*uniqueUv) * data->elementMap->total_uvs, - "uv_brush_unique_uv_map"); + data->uv = MEM_callocN(sizeof(*data->uv) * unique_uvs, "uv_brush_unique_uvs"); + /* Holds, for each UvElement in elementMap, an index of its unique UV. */ + int *uniqueUv = MEM_mallocN(sizeof(*uniqueUv) * data->elementMap->total_uvs, + "uv_brush_unique_uv_map"); edgeHash = BLI_ghash_new(uv_edge_hash, uv_edge_compare, "uv_brush_edge_hash"); /* we have at most totalUVs edges */ - edges = MEM_mallocN(sizeof(*edges) * data->elementMap->total_uvs, "uv_brush_all_edges"); + edges = MEM_callocN(sizeof(*edges) * data->elementMap->total_uvs, "uv_brush_all_edges"); if (!data->uv || !uniqueUv || !edgeHash || !edges) { MEM_SAFE_FREE(edges); MEM_SAFE_FREE(uniqueUv); @@ -559,8 +754,12 @@ static UvSculptData *uv_sculpt_stroke_init(bContext *C, wmOperator *op, const wm counter++; data->uv[counter].element = element; - data->uv[counter].flag = 0; data->uv[counter].uv = luv->uv; + if (data->tool != UV_SCULPT_TOOL_GRAB) { + if (luv->flag & MLOOPUV_PINNED) { + data->uv[counter].is_locked = true; + } + } } /* Pointer arithmetic to the rescue, as always :). */ uniqueUv[element - data->elementMap->storage] = counter; @@ -576,7 +775,6 @@ static UvSculptData *uv_sculpt_stroke_init(bContext *C, wmOperator *op, const wm data->elementMap, efa, l, island_index, do_island_optimization); int offset2, itmp2 = uv_element_offset_from_face_get( data->elementMap, efa, l->next, island_index, do_island_optimization); - char *flag; /* Skip edge if not found(unlikely) or not on valid island */ if (itmp1 == -1 || itmp2 == -1) { @@ -586,7 +784,6 @@ static UvSculptData *uv_sculpt_stroke_init(bContext *C, wmOperator *op, const wm offset1 = uniqueUv[itmp1]; offset2 = uniqueUv[itmp2]; - edges[counter].flag = 0; /* Using an order policy, sort UV's according to address space. * This avoids having two different UvEdges with the same UV's on different positions. */ if (offset1 < offset2) { @@ -597,15 +794,13 @@ static UvSculptData *uv_sculpt_stroke_init(bContext *C, wmOperator *op, const wm edges[counter].uv1 = offset2; edges[counter].uv2 = offset1; } - /* Hack! Set the value of the key to its flag. - * Now we can set the flag when an edge exists twice :) */ - flag = BLI_ghash_lookup(edgeHash, &edges[counter]); - if (flag) { - *flag = 1; + UvEdge *prev_edge = BLI_ghash_lookup(edgeHash, &edges[counter]); + if (prev_edge) { + prev_edge->is_interior = true; + edges[counter].is_interior = true; } else { - /* Hack mentioned */ - BLI_ghash_insert(edgeHash, &edges[counter], &edges[counter].flag); + BLI_ghash_insert(edgeHash, &edges[counter], &edges[counter]); } counter++; } @@ -614,7 +809,7 @@ static UvSculptData *uv_sculpt_stroke_init(bContext *C, wmOperator *op, const wm MEM_SAFE_FREE(uniqueUv); /* Allocate connectivity data, we allocate edges once */ - data->uvedges = MEM_mallocN(sizeof(*data->uvedges) * BLI_ghash_len(edgeHash), + data->uvedges = MEM_callocN(sizeof(*data->uvedges) * BLI_ghash_len(edgeHash), "uv_brush_edge_connectivity_data"); if (!data->uvedges) { BLI_ghash_free(edgeHash, NULL, NULL); @@ -637,20 +832,27 @@ static UvSculptData *uv_sculpt_stroke_init(bContext *C, wmOperator *op, const wm MEM_SAFE_FREE(edges); /* transfer boundary edge property to UV's */ - if (ts->uv_sculpt_settings & UV_SCULPT_LOCK_BORDERS) { - for (int i = 0; i < data->totalUvEdges; i++) { - if (!data->uvedges[i].flag) { - data->uv[data->uvedges[i].uv1].flag |= MARK_BOUNDARY; - data->uv[data->uvedges[i].uv2].flag |= MARK_BOUNDARY; + for (int i = 0; i < data->totalUvEdges; i++) { + if (!data->uvedges[i].is_interior) { + data->uv[data->uvedges[i].uv1].is_boundary = true; + data->uv[data->uvedges[i].uv2].is_boundary = true; + if (ts->uv_sculpt_settings & UV_SCULPT_LOCK_BORDERS) { + data->uv[data->uvedges[i].uv1].is_locked = true; + data->uv[data->uvedges[i].uv2].is_locked = true; } + set_element_flag(data->uv[data->uvedges[i].uv1].element, MARK_BOUNDARY); + set_element_flag(data->uv[data->uvedges[i].uv2].element, MARK_BOUNDARY); } } + SpaceImage *sima = CTX_wm_space_image(C); + data->constrain_to_bounds = (sima->flag & SI_CLIP_UV); + BKE_image_find_nearest_tile_with_offset(sima->image, co, data->uv_base_offset); + /* Allocate initial selection for grab tool */ if (data->tool == UV_SCULPT_TOOL_GRAB) { float radius, radius_root; UvSculptData *sculptdata = (UvSculptData *)op->customdata; - SpaceImage *sima; int width, height; float aspectRatio; float alpha, zoomx, zoomy; @@ -659,7 +861,6 @@ static UvSculptData *uv_sculpt_stroke_init(bContext *C, wmOperator *op, const wm alpha = BKE_brush_alpha_get(scene, brush); radius = BKE_brush_size_get(scene, brush); - sima = CTX_wm_space_image(C); ED_space_image_get_size(sima, &width, &height); ED_space_image_get_zoom(sima, region, &zoomx, &zoomy); @@ -684,16 +885,16 @@ static UvSculptData *uv_sculpt_stroke_init(bContext *C, wmOperator *op, const wm copy_v2_v2(data->initial_stroke->init_coord, co); counter = 0; - for (int i = 0; i < data->totalUniqueUvs; i++) { - float dist, diff[2]; - if (data->uv[i].flag & MARK_BOUNDARY) { + if (data->uv[i].is_locked) { continue; } + float diff[2]; sub_v2_v2v2(diff, data->uv[i].uv, co); diff[1] /= aspectRatio; - if ((dist = dot_v2v2(diff, diff)) <= radius) { + float dist = dot_v2v2(diff, diff); + if (dist <= radius) { float strength; strength = alpha * BKE_brush_curve_strength_clamped(brush, sqrtf(dist), radius_root); @@ -705,6 +906,9 @@ static UvSculptData *uv_sculpt_stroke_init(bContext *C, wmOperator *op, const wm } data->initial_stroke->totalInitialSelected = counter; + if (sima->flag & SI_LIVE_UNWRAP) { + ED_uvedit_live_unwrap_begin(scene, obedit); + } } } diff --git a/source/blender/editors/space_action/CMakeLists.txt b/source/blender/editors/space_action/CMakeLists.txt index 841bd5cf91b..b9e27c4de49 100644 --- a/source/blender/editors/space_action/CMakeLists.txt +++ b/source/blender/editors/space_action/CMakeLists.txt @@ -10,7 +10,6 @@ set(INC ../../makesdna ../../makesrna ../../windowmanager - ../../../../intern/glew-mx ../../../../intern/guardedalloc # RNA_prototypes.h ${CMAKE_BINARY_DIR}/source/blender/makesrna diff --git a/source/blender/editors/space_action/action_data.c b/source/blender/editors/space_action/action_data.c index 8f97a58451e..79047b171ef 100644 --- a/source/blender/editors/space_action/action_data.c +++ b/source/blender/editors/space_action/action_data.c @@ -169,7 +169,7 @@ static bool action_new_poll(bContext *C) SpaceAction *saction = (SpaceAction *)CTX_wm_space_data(C); Object *ob = CTX_data_active_object(C); - /* For now, actions are only for the active object, and on object and shapekey levels... */ + /* For now, actions are only for the active object, and on object and shape-key levels... */ if (saction->mode == SACTCONT_ACTION) { /* XXX: This assumes that actions are assigned to the active object in this mode */ if (ob) { @@ -460,7 +460,8 @@ static bool action_stash_create_poll(bContext *C) Scene *scene = CTX_data_scene(C); if (!(scene->flag & SCE_NLA_EDIT_ON)) { - /* For now, actions are only for the active object, and on object and shapekey levels... */ + /* For now, actions are only for the active object, and on object and shape-key levels... + */ return ELEM(saction->mode, SACTCONT_ACTION, SACTCONT_SHAPEKEY); } } diff --git a/source/blender/editors/space_action/action_draw.c b/source/blender/editors/space_action/action_draw.c index 7bdf2478862..eb56c6c4b54 100644 --- a/source/blender/editors/space_action/action_draw.c +++ b/source/blender/editors/space_action/action_draw.c @@ -206,7 +206,7 @@ void draw_channel_strips(bAnimContext *ac, SpaceAction *saction, ARegion *region GPUVertFormat *format = immVertexFormat(); uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); - immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); GPU_blend(GPU_BLEND_ALPHA); @@ -617,7 +617,7 @@ void timeline_draw_cache(SpaceAction *saction, Object *ob, Scene *scene) uint pos_id = GPU_vertformat_attr_add( immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); - immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); GPU_blend(GPU_BLEND_ALPHA); diff --git a/source/blender/editors/space_action/action_edit.c b/source/blender/editors/space_action/action_edit.c index 23c92cbdaa0..0803c5dc575 100644 --- a/source/blender/editors/space_action/action_edit.c +++ b/source/blender/editors/space_action/action_edit.c @@ -1326,7 +1326,7 @@ static int actkeys_expo_exec(bContext *C, wmOperator *op) void ACTION_OT_extrapolation_type(wmOperatorType *ot) { /* identifiers */ - ot->name = "Set Keyframe Extrapolation"; + ot->name = "Set F-Curve Extrapolation"; ot->idname = "ACTION_OT_extrapolation_type"; ot->description = "Set extrapolation mode for selected F-Curves"; @@ -1364,7 +1364,7 @@ static int actkeys_ipo_exec(bContext *C, wmOperator *op) /* set handle type */ ANIM_animdata_keyframe_callback(&ac, - (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_CURVE_VISIBLE | + (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_FOREDIT | ANIMFILTER_NODUPLIS | ANIMFILTER_FCURVESONLY), ANIM_editkeyframes_ipo(mode)); @@ -1414,7 +1414,7 @@ static int actkeys_easing_exec(bContext *C, wmOperator *op) /* set handle type */ ANIM_animdata_keyframe_callback(&ac, - (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_CURVE_VISIBLE | + (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_FOREDIT | ANIMFILTER_NODUPLIS | ANIMFILTER_FCURVESONLY), ANIM_editkeyframes_easing(mode)); diff --git a/source/blender/editors/space_action/action_select.c b/source/blender/editors/space_action/action_select.c index ed9d86e1a4e..9d45a2a3b89 100644 --- a/source/blender/editors/space_action/action_select.c +++ b/source/blender/editors/space_action/action_select.c @@ -449,7 +449,7 @@ static void box_select_action(bAnimContext *ac, const rcti rect, short mode, sho filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_LIST_CHANNELS); ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype); - /* Get beztriple editing/validation funcs. */ + /* Get beztriple editing/validation functions. */ sel_data.select_cb = ANIM_editkeyframes_select(selectmode); if (ELEM(mode, ACTKEYS_BORDERSEL_FRAMERANGE, ACTKEYS_BORDERSEL_ALLKEYS)) { @@ -585,7 +585,7 @@ void ACTION_OT_select_box(wmOperatorType *ot) ot->poll = ED_operator_action_active; /* flags */ - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + ot->flag = OPTYPE_UNDO; /* rna */ ot->prop = RNA_def_boolean(ot->srna, "axis_range", 0, "Axis Range", ""); @@ -693,7 +693,7 @@ static void region_select_action_keys( filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_LIST_CHANNELS); ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype); - /* Get beztriple editing/validation funcs. */ + /* Get beztriple editing/validation functions. */ sel_data.select_cb = ANIM_editkeyframes_select(selectmode); sel_data.ok_cb = ANIM_editkeyframes_ok(mode); @@ -936,7 +936,7 @@ static void markers_selectkeys_between(bAnimContext *ac) min -= 0.5f; max += 0.5f; - /* get editing funcs + data */ + /* Get editing functions + data. */ ok_cb = ANIM_editkeyframes_ok(BEZT_OK_FRAMERANGE); select_cb = ANIM_editkeyframes_select(SELECT_ADD); @@ -1129,6 +1129,7 @@ void ACTION_OT_select_column(wmOperatorType *ot) /* props */ ot->prop = RNA_def_enum(ot->srna, "mode", prop_column_select_types, 0, "Mode", ""); + RNA_def_property_flag(ot->prop, PROP_HIDDEN); } /* ******************** Select Linked Operator *********************** */ diff --git a/source/blender/editors/space_action/space_action.c b/source/blender/editors/space_action/space_action.c index 166a4351377..b54750accb0 100644 --- a/source/blender/editors/space_action/space_action.c +++ b/source/blender/editors/space_action/space_action.c @@ -307,7 +307,7 @@ static void action_header_region_draw(const bContext *C, ARegion *region) static void action_channel_region_listener(const wmRegionListenerParams *params) { ARegion *region = params->region; - wmNotifier *wmn = params->notifier; + const wmNotifier *wmn = params->notifier; /* context changes */ switch (wmn->category) { @@ -401,7 +401,7 @@ static void saction_channel_region_message_subscribe(const wmRegionMessageSubscr static void action_main_region_listener(const wmRegionListenerParams *params) { ARegion *region = params->region; - wmNotifier *wmn = params->notifier; + const wmNotifier *wmn = params->notifier; /* context changes */ switch (wmn->category) { @@ -499,7 +499,7 @@ static void saction_main_region_message_subscribe(const wmRegionMessageSubscribe static void action_listener(const wmSpaceTypeListenerParams *params) { ScrArea *area = params->area; - wmNotifier *wmn = params->notifier; + const wmNotifier *wmn = params->notifier; SpaceAction *saction = (SpaceAction *)area->spacedata.first; /* context changes */ @@ -653,7 +653,7 @@ static void action_header_region_listener(const wmRegionListenerParams *params) { ScrArea *area = params->area; ARegion *region = params->region; - wmNotifier *wmn = params->notifier; + const wmNotifier *wmn = params->notifier; SpaceAction *saction = (SpaceAction *)area->spacedata.first; /* context changes */ @@ -728,7 +728,7 @@ static void action_buttons_area_draw(const bContext *C, ARegion *region) static void action_region_listener(const wmRegionListenerParams *params) { ARegion *region = params->region; - wmNotifier *wmn = params->notifier; + const wmNotifier *wmn = params->notifier; /* context changes */ switch (wmn->category) { @@ -840,7 +840,7 @@ void ED_spacetype_action(void) ARegionType *art; st->spaceid = SPACE_ACTION; - strncpy(st->name, "Action", BKE_ST_MAXNAME); + STRNCPY(st->name, "Action"); st->create = action_create; st->free = action_free; @@ -905,5 +905,8 @@ void ED_spacetype_action(void) action_buttons_register(art); + art = ED_area_type_hud(st->spaceid); + BLI_addhead(&st->regiontypes, art); + BKE_spacetype_register(st); } diff --git a/source/blender/editors/space_buttons/CMakeLists.txt b/source/blender/editors/space_buttons/CMakeLists.txt index b509eae8ea6..d0ad510f5cf 100644 --- a/source/blender/editors/space_buttons/CMakeLists.txt +++ b/source/blender/editors/space_buttons/CMakeLists.txt @@ -9,7 +9,6 @@ set(INC ../../makesdna ../../makesrna ../../windowmanager - ../../../../intern/glew-mx ../../../../intern/guardedalloc ../../bmesh # RNA_prototypes.h diff --git a/source/blender/editors/space_buttons/buttons_context.c b/source/blender/editors/space_buttons/buttons_context.c index c3479409f0d..3dc522ffcb9 100644 --- a/source/blender/editors/space_buttons/buttons_context.c +++ b/source/blender/editors/space_buttons/buttons_context.c @@ -155,7 +155,8 @@ static bool buttons_context_path_collection(const bContext *C, /* if we have a view layer, use the view layer's active collection */ if (buttons_context_path_view_layer(path, window)) { ViewLayer *view_layer = path->ptr[path->len - 1].data; - Collection *c = view_layer->active_collection->collection; + BKE_view_layer_synced_ensure(scene, view_layer); + Collection *c = BKE_view_layer_active_collection_get(view_layer)->collection; /* Do not show collection tab for master collection. */ if (c == scene->master_collection) { @@ -209,7 +210,7 @@ static bool buttons_context_path_object(ButsContextPath *path) } ViewLayer *view_layer = ptr->data; - Object *ob = (view_layer->basact) ? view_layer->basact->object : NULL; + Object *ob = BKE_view_layer_active_object_get(view_layer); if (ob) { RNA_id_pointer_create(&ob->id, &path->ptr[path->len]); @@ -642,8 +643,10 @@ static bool buttons_context_path( static bool buttons_shading_context(const bContext *C, int mainb) { wmWindow *window = CTX_wm_window(C); + const Scene *scene = WM_window_get_active_scene(window); ViewLayer *view_layer = WM_window_get_active_view_layer(window); - Object *ob = OBACT(view_layer); + BKE_view_layer_synced_ensure(scene, view_layer); + Object *ob = BKE_view_layer_active_object_get(view_layer); if (ELEM(mainb, BCONTEXT_MATERIAL, BCONTEXT_WORLD, BCONTEXT_TEXTURE)) { return true; @@ -658,8 +661,10 @@ static bool buttons_shading_context(const bContext *C, int mainb) static int buttons_shading_new_context(const bContext *C, int flag) { wmWindow *window = CTX_wm_window(C); + const Scene *scene = WM_window_get_active_scene(window); ViewLayer *view_layer = WM_window_get_active_view_layer(window); - Object *ob = OBACT(view_layer); + BKE_view_layer_synced_ensure(scene, view_layer); + Object *ob = BKE_view_layer_active_object_get(view_layer); if (flag & (1 << BCONTEXT_MATERIAL)) { return BCONTEXT_MATERIAL; diff --git a/source/blender/editors/space_buttons/buttons_intern.h b/source/blender/editors/space_buttons/buttons_intern.h index 520d3a7c38d..1430cd4a8e8 100644 --- a/source/blender/editors/space_buttons/buttons_intern.h +++ b/source/blender/editors/space_buttons/buttons_intern.h @@ -26,7 +26,7 @@ struct SpaceProperties_Runtime { /** For filtering properties displayed in the space. */ char search_string[UI_MAX_NAME_STR]; /** - * Bitfield (in the same order as the tabs) for whether each tab has properties + * Bit-field (in the same order as the tabs) for whether each tab has properties * that match the search filter. Only valid when #search_string is set. */ BLI_bitmap *tab_search_results; diff --git a/source/blender/editors/space_buttons/buttons_ops.c b/source/blender/editors/space_buttons/buttons_ops.c index 10fb008049d..a9ce9a3d723 100644 --- a/source/blender/editors/space_buttons/buttons_ops.c +++ b/source/blender/editors/space_buttons/buttons_ops.c @@ -337,6 +337,12 @@ static int file_browse_invoke(bContext *C, wmOperator *op, const wmEvent *event) RNA_string_set(op->ptr, path_prop, str); MEM_freeN(str); + PropertyRNA *prop_check_existing = RNA_struct_find_property(op->ptr, "check_existing"); + if (!RNA_property_is_set(op->ptr, prop_check_existing)) { + const bool is_output_path = (RNA_property_flag(prop) & PROP_PATH_OUTPUT) != 0; + RNA_property_boolean_set(op->ptr, prop_check_existing, is_output_path); + } + WM_event_add_fileselect(C, op); return OPERATOR_RUNNING_MODAL; diff --git a/source/blender/editors/space_buttons/buttons_texture.c b/source/blender/editors/space_buttons/buttons_texture.c index a5cb9170f98..d4e456272f9 100644 --- a/source/blender/editors/space_buttons/buttons_texture.c +++ b/source/blender/editors/space_buttons/buttons_texture.c @@ -281,7 +281,8 @@ static void buttons_texture_users_from_context(ListBase *users, brush = BKE_paint_brush(BKE_paint_get_active_from_context(C)); linestyle = BKE_linestyle_active_from_view_layer(view_layer); - ob = OBACT(view_layer); + BKE_view_layer_synced_ensure(scene, view_layer); + ob = BKE_view_layer_active_object_get(view_layer); } /* fill users */ diff --git a/source/blender/editors/space_buttons/space_buttons.c b/source/blender/editors/space_buttons/space_buttons.c index e60946b8f66..209d60d4f58 100644 --- a/source/blender/editors/space_buttons/space_buttons.c +++ b/source/blender/editors/space_buttons/space_buttons.c @@ -507,7 +507,7 @@ static void buttons_main_region_layout(const bContext *C, ARegion *region) static void buttons_main_region_listener(const wmRegionListenerParams *params) { ARegion *region = params->region; - wmNotifier *wmn = params->notifier; + const wmNotifier *wmn = params->notifier; /* context changes */ switch (wmn->category) { @@ -603,7 +603,7 @@ static void buttons_navigation_bar_region_draw(const bContext *C, ARegion *regio } ED_region_panels_layout(C, region); - /* ED_region_panels_layout adds vertical scrollbars, we don't want them. */ + /* #ED_region_panels_layout adds vertical scroll-bars, we don't want them. */ region->v2d.scroll &= ~V2D_SCROLL_VERTICAL; ED_region_panels_draw(C, region); } @@ -645,7 +645,7 @@ static void buttons_area_redraw(ScrArea *area, short buttons) static void buttons_area_listener(const wmSpaceTypeListenerParams *params) { ScrArea *area = params->area; - wmNotifier *wmn = params->notifier; + const wmNotifier *wmn = params->notifier; SpaceProperties *sbuts = area->spacedata.first; /* context changes */ @@ -917,7 +917,7 @@ void ED_spacetype_buttons(void) ARegionType *art; st->spaceid = SPACE_PROPERTIES; - strncpy(st->name, "Buttons", BKE_ST_MAXNAME); + STRNCPY(st->name, "Buttons"); st->create = buttons_create; st->free = buttons_free; @@ -978,8 +978,7 @@ void ED_spacetype_buttons(void) /* regions: navigation bar */ art = MEM_callocN(sizeof(ARegionType), "spacetype nav buttons region"); art->regionid = RGN_TYPE_NAV_BAR; - art->prefsizex = AREAMINX - 3; /* XXX Works and looks best, - * should we update AREAMINX accordingly? */ + art->prefsizex = AREAMINX; art->keymapflag = ED_KEYMAP_UI | ED_KEYMAP_FRAMES | ED_KEYMAP_NAVBAR; art->init = buttons_navigation_bar_region_init; art->draw = buttons_navigation_bar_region_draw; diff --git a/source/blender/editors/space_clip/CMakeLists.txt b/source/blender/editors/space_clip/CMakeLists.txt index eddf1780d8b..8cb5299df6d 100644 --- a/source/blender/editors/space_clip/CMakeLists.txt +++ b/source/blender/editors/space_clip/CMakeLists.txt @@ -13,7 +13,6 @@ set(INC ../../makesdna ../../makesrna ../../windowmanager - ../../../../intern/glew-mx ../../../../intern/guardedalloc # dna_type_offsets.h diff --git a/source/blender/editors/space_clip/clip_buttons.c b/source/blender/editors/space_clip/clip_buttons.c index 72df2b74b11..3a4a2faa5f7 100644 --- a/source/blender/editors/space_clip/clip_buttons.c +++ b/source/blender/editors/space_clip/clip_buttons.c @@ -57,7 +57,7 @@ static void metadata_panel_context_draw(const bContext *C, Panel *panel) SpaceClip *space_clip = CTX_wm_space_clip(C); /* NOTE: This might not be exactly the same image buffer as shown in the * clip editor itself, since that might be coming from proxy, or being - * postprocessed (stabilized or undistored). + * postprocessed (stabilized or undistorted). * Ideally we need to query metadata from an original image or movie without * reading actual pixels to speed up the process. */ ImBuf *ibuf = ED_space_clip_get_buffer(space_clip); diff --git a/source/blender/editors/space_clip/clip_dopesheet_draw.c b/source/blender/editors/space_clip/clip_dopesheet_draw.c index 858fa229992..8f876f6a8a3 100644 --- a/source/blender/editors/space_clip/clip_dopesheet_draw.c +++ b/source/blender/editors/space_clip/clip_dopesheet_draw.c @@ -111,7 +111,7 @@ void clip_draw_dopesheet_main(SpaceClip *sc, ARegion *region, Scene *scene) GPUVertFormat *format = immVertexFormat(); uint pos_id = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); - immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); /* don't use totrect set, as the width stays the same * (NOTE: this is ok here, the configuration is pretty straightforward) @@ -313,7 +313,7 @@ void clip_draw_dopesheet_channels(const bContext *C, ARegion *region) GPUVertFormat *format = immVertexFormat(); uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); - immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); MovieTrackingDopesheetChannel *channel; for (channel = dopesheet->channels.first; channel; channel = channel->next) { diff --git a/source/blender/editors/space_clip/clip_draw.c b/source/blender/editors/space_clip/clip_draw.c index 78174160eb8..b9bd97260ef 100644 --- a/source/blender/editors/space_clip/clip_draw.c +++ b/source/blender/editors/space_clip/clip_draw.c @@ -149,7 +149,7 @@ static void draw_movieclip_cache(SpaceClip *sc, ARegion *region, MovieClip *clip uint pos = GPU_vertformat_attr_add( immVertexFormat(), "pos", GPU_COMP_I32, 2, GPU_FETCH_INT_TO_FLOAT); - immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); /* track */ if (act_track || act_plane_track) { @@ -241,7 +241,7 @@ static void draw_movieclip_cache(SpaceClip *sc, ARegion *region, MovieClip *clip ED_region_cache_draw_curfra_label(sc->user.framenr, x, 8.0f * UI_DPI_FAC); pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_I32, 2, GPU_FETCH_INT_TO_FLOAT); - immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); /* solver keyframes */ immUniformColor4ub(175, 255, 0, 255); @@ -286,7 +286,7 @@ static void draw_movieclip_muted(ARegion *region, int width, int height, float z int x, y; uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); - immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); /* find window pixel coordinates of origin */ UI_view2d_view_to_region(®ion->v2d, 0.0f, 0.0f, &x, &y); @@ -364,7 +364,7 @@ static void draw_stabilization_border( GPU_matrix_scale_2f(zoomx, zoomy); GPU_matrix_mul(sc->stabmat); - immBindBuiltinProgram(GPU_SHADER_2D_LINE_DASHED_UNIFORM_COLOR); + immBindBuiltinProgram(GPU_SHADER_3D_LINE_DASHED_UNIFORM_COLOR); float viewport_size[4]; GPU_viewport_size_get_f(viewport_size); @@ -521,7 +521,7 @@ static void draw_track_path(SpaceClip *sc, MovieClip *UNUSED(clip), MovieTrackin const uint position_attribute = GPU_vertformat_attr_add( immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); - immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); /* Draw path outline. */ if (!tiny) { @@ -738,7 +738,7 @@ static void draw_marker_areas(SpaceClip *sc, * just always go with dashed shader. */ immUnbindProgram(); - immBindBuiltinProgram(GPU_SHADER_2D_LINE_DASHED_UNIFORM_COLOR); + immBindBuiltinProgram(GPU_SHADER_3D_LINE_DASHED_UNIFORM_COLOR); float viewport_size[4]; GPU_viewport_size_get_f(viewport_size); @@ -865,7 +865,7 @@ static void draw_marker_areas(SpaceClip *sc, BLI_assert(pos == shdr_pos); UNUSED_VARS_NDEBUG(pos); - immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); } static float get_shortest_pattern_side(MovieTrackingMarker *marker) @@ -1210,10 +1210,10 @@ static void draw_plane_marker_image(Scene *scene, imm_format, "texCoord", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); /* Use 3D image for correct display of planar tracked images. */ - immBindBuiltinProgram(GPU_SHADER_3D_IMAGE_MODULATE_ALPHA); + immBindBuiltinProgram(GPU_SHADER_3D_IMAGE_COLOR); immBindTexture("image", texture); - immUniform1f("alpha", plane_track->image_opacity); + immUniformColor4f(1.0f, 1.0f, 1.0f, plane_track->image_opacity); immBegin(GPU_PRIM_TRI_FAN, 4); @@ -1278,7 +1278,7 @@ static void draw_plane_marker_ex(SpaceClip *sc, const uint shdr_pos = GPU_vertformat_attr_add( immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); - immBindBuiltinProgram(GPU_SHADER_2D_LINE_DASHED_UNIFORM_COLOR); + immBindBuiltinProgram(GPU_SHADER_3D_LINE_DASHED_UNIFORM_COLOR); float viewport_size[4]; GPU_viewport_size_get_f(viewport_size); @@ -1358,7 +1358,7 @@ static void draw_plane_marker_ex(SpaceClip *sc, /* Draw sliders. */ if (is_selected_track) { - immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); if (draw_outline) { immUniformThemeColor(TH_MARKER_OUTLINE); @@ -1525,7 +1525,7 @@ static void draw_tracking_tracks(SpaceClip *sc, uint position = GPU_vertformat_attr_add( immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); - immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); /* markers outline and non-selected areas */ track = tracksbase->first; @@ -1720,7 +1720,7 @@ static void draw_distortion(SpaceClip *sc, uint position = GPU_vertformat_attr_add( immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); - immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); /* grid */ if (sc->flag & SC_SHOW_GRID) { diff --git a/source/blender/editors/space_clip/clip_graph_draw.c b/source/blender/editors/space_clip/clip_graph_draw.c index 7236e7bcee0..5e3171d03c9 100644 --- a/source/blender/editors/space_clip/clip_graph_draw.c +++ b/source/blender/editors/space_clip/clip_graph_draw.c @@ -259,7 +259,7 @@ void clip_draw_graph(SpaceClip *sc, ARegion *region, Scene *scene) if (clip) { uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); - immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); GPU_point_size(3.0f); diff --git a/source/blender/editors/space_clip/clip_utils.c b/source/blender/editors/space_clip/clip_utils.c index 221b87a8b5a..04b87cb4c83 100644 --- a/source/blender/editors/space_clip/clip_utils.c +++ b/source/blender/editors/space_clip/clip_utils.c @@ -614,7 +614,7 @@ void clip_draw_sfra_efra(View2D *v2d, Scene *scene) GPU_blend(GPU_BLEND_ALPHA); uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); - immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); immUniformColor4f(0.0f, 0.0f, 0.0f, 0.4f); immRectf(pos, v2d->cur.xmin, v2d->cur.ymin, (float)scene->r.sfra, v2d->cur.ymax); diff --git a/source/blender/editors/space_clip/space_clip.c b/source/blender/editors/space_clip/space_clip.c index ce6409a7784..ab952470757 100644 --- a/source/blender/editors/space_clip/space_clip.c +++ b/source/blender/editors/space_clip/space_clip.c @@ -314,7 +314,7 @@ static SpaceLink *clip_duplicate(SpaceLink *sl) static void clip_listener(const wmSpaceTypeListenerParams *params) { ScrArea *area = params->area; - wmNotifier *wmn = params->notifier; + const wmNotifier *wmn = params->notifier; const Scene *scene = params->scene; /* context changes */ @@ -811,8 +811,8 @@ static void clip_main_region_draw(const bContext *C, ARegion *region) int width, height; bool show_cursor = false; - /* if tracking is in progress, we should synchronize framenr from clipuser - * so latest tracked frame would be shown */ + /* If tracking is in progress, we should synchronize the frame from the clip-user + * (#MovieClipUser.framenr) so latest tracked frame would be shown. */ if (clip && clip->tracking_context) { BKE_autotrack_context_sync_user(clip->tracking_context, &sc->user); } @@ -919,7 +919,7 @@ static void clip_main_region_draw(const bContext *C, ARegion *region) static void clip_main_region_listener(const wmRegionListenerParams *params) { ARegion *region = params->region; - wmNotifier *wmn = params->notifier; + const wmNotifier *wmn = params->notifier; /* context changes */ switch (wmn->category) { @@ -1118,7 +1118,7 @@ static void clip_header_region_draw(const bContext *C, ARegion *region) static void clip_header_region_listener(const wmRegionListenerParams *params) { ARegion *region = params->region; - wmNotifier *wmn = params->notifier; + const wmNotifier *wmn = params->notifier; /* context changes */ switch (wmn->category) { @@ -1160,7 +1160,7 @@ static void clip_tools_region_draw(const bContext *C, ARegion *region) static void clip_props_region_listener(const wmRegionListenerParams *params) { ARegion *region = params->region; - wmNotifier *wmn = params->notifier; + const wmNotifier *wmn = params->notifier; /* context changes */ switch (wmn->category) { @@ -1212,7 +1212,7 @@ static void clip_properties_region_draw(const bContext *C, ARegion *region) static void clip_properties_region_listener(const wmRegionListenerParams *params) { ARegion *region = params->region; - wmNotifier *wmn = params->notifier; + const wmNotifier *wmn = params->notifier; /* context changes */ switch (wmn->category) { @@ -1251,7 +1251,7 @@ void ED_spacetype_clip(void) ARegionType *art; st->spaceid = SPACE_CLIP; - strncpy(st->name, "Clip", BKE_ST_MAXNAME); + STRNCPY(st->name, "Clip"); st->create = clip_create; st->free = clip_free; diff --git a/source/blender/editors/space_clip/tracking_ops.c b/source/blender/editors/space_clip/tracking_ops.c index cba4157d044..0f5207b39c2 100644 --- a/source/blender/editors/space_clip/tracking_ops.c +++ b/source/blender/editors/space_clip/tracking_ops.c @@ -1535,6 +1535,7 @@ void CLIP_OT_average_tracks(wmOperatorType *ot) PropertyRNA *prop; prop = RNA_def_boolean(ot->srna, "keep_original", 1, "Keep Original", "Keep original tracks"); + RNA_def_property_translation_context(prop, BLT_I18NCONTEXT_ID_MOVIECLIP); RNA_def_property_flag(prop, PROP_SKIP_SAVE); } diff --git a/source/blender/editors/space_clip/tracking_ops_orient.c b/source/blender/editors/space_clip/tracking_ops_orient.c index d3b818fba43..c6d4a6ad104 100644 --- a/source/blender/editors/space_clip/tracking_ops_orient.c +++ b/source/blender/editors/space_clip/tracking_ops_orient.c @@ -72,7 +72,8 @@ static Object *get_orientation_object(bContext *C) object = get_camera_with_movieclip(scene, clip); } else { - object = OBACT(view_layer); + BKE_view_layer_synced_ensure(scene, view_layer); + object = BKE_view_layer_active_object_get(view_layer); } if (object != NULL && object->parent != NULL) { @@ -86,6 +87,7 @@ static bool set_orientation_poll(bContext *C) { SpaceClip *sc = CTX_wm_space_clip(C); if (sc != NULL) { + const Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); MovieClip *clip = ED_space_clip_get_clip(sc); if (clip != NULL) { @@ -94,7 +96,8 @@ static bool set_orientation_poll(bContext *C) if (tracking_object->flag & TRACKING_OBJECT_CAMERA) { return true; } - return OBACT(view_layer) != NULL; + BKE_view_layer_synced_ensure(scene, view_layer); + return BKE_view_layer_active_object_get(view_layer) != NULL; } } return false; diff --git a/source/blender/editors/space_console/CMakeLists.txt b/source/blender/editors/space_console/CMakeLists.txt index 841c21f12e7..345ab8b0970 100644 --- a/source/blender/editors/space_console/CMakeLists.txt +++ b/source/blender/editors/space_console/CMakeLists.txt @@ -9,7 +9,6 @@ set(INC ../../makesdna ../../makesrna ../../windowmanager - ../../../../intern/glew-mx ../../../../intern/guardedalloc ) diff --git a/source/blender/editors/space_console/console_draw.c b/source/blender/editors/space_console/console_draw.c index 140dc4c1d40..6710d4ce0e7 100644 --- a/source/blender/editors/space_console/console_draw.c +++ b/source/blender/editors/space_console/console_draw.c @@ -150,7 +150,7 @@ static void console_textview_draw_cursor(TextViewContext *tvc, int cwidth, int c /* cursor */ GPUVertFormat *format = immVertexFormat(); uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); - immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); immUniformThemeColor(TH_CONSOLE_CURSOR); immRectf(pos, pen[0] - U.pixelsize, pen[1], pen[0] + U.pixelsize, pen[1] + tvc->lheight); diff --git a/source/blender/editors/space_console/console_intern.h b/source/blender/editors/space_console/console_intern.h index deaaff05a33..8e2ebc9b8e9 100644 --- a/source/blender/editors/space_console/console_intern.h +++ b/source/blender/editors/space_console/console_intern.h @@ -15,7 +15,7 @@ struct wmOperatorType; /* console_draw.c */ void console_textview_main(struct SpaceConsole *sc, const struct ARegion *region); -/* needed to calculate the scrollbar */ +/* Needed to calculate the scroll-bar. */ int console_textview_height(struct SpaceConsole *sc, const struct ARegion *region); int console_char_pick(struct SpaceConsole *sc, const struct ARegion *region, const int mval[2]); diff --git a/source/blender/editors/space_console/console_ops.c b/source/blender/editors/space_console/console_ops.c index ef22b1b9f0b..11234d446da 100644 --- a/source/blender/editors/space_console/console_ops.c +++ b/source/blender/editors/space_console/console_ops.c @@ -280,7 +280,7 @@ static bool console_line_column_from_index( return false; } -/* static funcs for text editing */ +/* Static functions for text editing. */ /* similar to the text editor, with some not used. keep compatible */ static const EnumPropertyItem console_move_type_items[] = { diff --git a/source/blender/editors/space_console/space_console.c b/source/blender/editors/space_console/space_console.c index 90b3cec437c..8838b5d341f 100644 --- a/source/blender/editors/space_console/space_console.c +++ b/source/blender/editors/space_console/space_console.c @@ -125,6 +125,10 @@ static void console_main_region_init(wmWindowManager *wm, ARegion *region) keymap = WM_keymap_ensure(wm->defaultconf, "Console", SPACE_CONSOLE, 0); WM_event_add_keymap_handler_v2d_mask(®ion->handlers, keymap); + /* Include after "Console" so cursor motion keys such as "Home" isn't overridden. */ + keymap = WM_keymap_ensure(wm->defaultconf, "View2D Buttons List", 0, 0); + WM_event_add_keymap_handler(®ion->handlers, keymap); + /* add drop boxes */ lb = WM_dropboxmap_find("Console", SPACE_CONSOLE, RGN_TYPE_WINDOW); @@ -155,7 +159,7 @@ static void id_drop_copy(bContext *UNUSED(C), wmDrag *drag, wmDropBox *drop) ID *id = WM_drag_get_local_ID(drag, 0); /* copy drag path to properties */ - char *text = RNA_path_full_ID_py(G_MAIN, id); + char *text = RNA_path_full_ID_py(id); RNA_string_set(drop->ptr, "text", text); MEM_freeN(text); } @@ -257,7 +261,7 @@ static void console_main_region_listener(const wmRegionListenerParams *params) { ScrArea *area = params->area; ARegion *region = params->region; - wmNotifier *wmn = params->notifier; + const wmNotifier *wmn = params->notifier; /* context changes */ switch (wmn->category) { @@ -286,7 +290,7 @@ void ED_spacetype_console(void) ARegionType *art; st->spaceid = SPACE_CONSOLE; - strncpy(st->name, "Console", BKE_ST_MAXNAME); + STRNCPY(st->name, "Console"); st->create = console_create; st->free = console_free; diff --git a/source/blender/editors/space_file/CMakeLists.txt b/source/blender/editors/space_file/CMakeLists.txt index b8c28e354da..fb9d5ab9b13 100644 --- a/source/blender/editors/space_file/CMakeLists.txt +++ b/source/blender/editors/space_file/CMakeLists.txt @@ -15,7 +15,6 @@ set(INC ../../render ../../windowmanager ../../../../intern/atomic - ../../../../intern/glew-mx ../../../../intern/guardedalloc # RNA_prototypes.h ${CMAKE_BINARY_DIR}/source/blender/makesrna @@ -28,8 +27,9 @@ set(SRC file_ops.c file_panels.c file_utils.c - filelist.c + filelist.cc filesel.c + folder_history.cc fsmenu.c space_file.c diff --git a/source/blender/editors/space_file/file_draw.c b/source/blender/editors/space_file/file_draw.c index f3359336b14..93eb5938301 100644 --- a/source/blender/editors/space_file/file_draw.c +++ b/source/blender/editors/space_file/file_draw.c @@ -378,7 +378,7 @@ static void file_draw_preview(const SpaceFile *sfile, GPU_blend(GPU_BLEND_ALPHA_PREMULT); } - IMMDrawPixelsTexState state = immDrawPixelsTexSetup(GPU_SHADER_2D_IMAGE_COLOR); + IMMDrawPixelsTexState state = immDrawPixelsTexSetup(GPU_SHADER_3D_IMAGE_COLOR); immDrawPixelsTexTiled_scaling(&state, (float)xco, (float)yco, @@ -463,7 +463,7 @@ static void file_draw_preview(const SpaceFile *sfile, if (show_outline) { GPUVertFormat *format = immVertexFormat(); uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); - immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); float border_color[4] = {1.0f, 1.0f, 1.0f, 0.4f}; float bgcolor[4]; UI_GetThemeColor4fv(TH_BACK, bgcolor); @@ -581,7 +581,7 @@ static void draw_background(FileLayout *layout, View2D *v2d) int sy; uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); - immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); float col_alternating[4]; UI_GetThemeColor4fv(TH_ROW_ALTERNATE, col_alternating); immUniformThemeColorBlend(TH_BACK, TH_ROW_ALTERNATE, col_alternating[3]); @@ -631,7 +631,7 @@ static void draw_dividers(FileLayout *layout, View2D *v2d) uint color = GPU_vertformat_attr_add( format, "color", GPU_COMP_U8, 3, GPU_FETCH_INT_TO_FLOAT_UNIT); - immBindBuiltinProgram(GPU_SHADER_2D_FLAT_COLOR); + immBindBuiltinProgram(GPU_SHADER_3D_FLAT_COLOR); immBegin(GPU_PRIM_LINES, vertex_len); sx = (int)v2d->tot.xmin; @@ -660,7 +660,7 @@ static void draw_columnheader_background(const FileLayout *layout, const View2D { uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); - immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); immUniformThemeColorShade(TH_BACK, 11); immRectf(pos, @@ -712,7 +712,7 @@ static void draw_columnheader_columns(const FileSelectParams *params, uint pos = GPU_vertformat_attr_add( immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); - immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); immUniformThemeColorShade(TH_BACK, -10); immBegin(GPU_PRIM_LINES, 2); immVertex2f(pos, sx - 1, sy - divider_pad); @@ -727,7 +727,7 @@ static void draw_columnheader_columns(const FileSelectParams *params, /* Vertical separator lines line */ { uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); - immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); immUniformThemeColorShade(TH_BACK, -10); immBegin(GPU_PRIM_LINES, 4); immVertex2f(pos, v2d->cur.xmin, sy); diff --git a/source/blender/editors/space_file/file_intern.h b/source/blender/editors/space_file/file_intern.h index 655a7983e2b..eac72af00ab 100644 --- a/source/blender/editors/space_file/file_intern.h +++ b/source/blender/editors/space_file/file_intern.h @@ -95,11 +95,15 @@ int file_highlight_set(struct SpaceFile *sfile, struct ARegion *region, int mx, * Use to set the file selector path from some arbitrary source. */ void file_sfile_filepath_set(struct SpaceFile *sfile, const char *filepath); -void file_sfile_to_operator_ex(struct Main *bmain, +void file_sfile_to_operator_ex(struct bContext *C, + struct Main *bmain, struct wmOperator *op, struct SpaceFile *sfile, char *filepath); -void file_sfile_to_operator(struct Main *bmain, struct wmOperator *op, struct SpaceFile *sfile); +void file_sfile_to_operator(struct bContext *C, + struct Main *bmain, + struct wmOperator *op, + struct SpaceFile *sfile); void file_operator_to_sfile(struct Main *bmain, struct SpaceFile *sfile, struct wmOperator *op); @@ -113,7 +117,7 @@ void fileselect_refresh_params(struct SpaceFile *sfile); /** * Sets #FileSelectParams.file (name of selected file) */ -void fileselect_file_set(SpaceFile *sfile, int index); +void fileselect_file_set(struct bContext *C, SpaceFile *sfile, int index); bool file_attribute_column_type_enabled(const FileSelectParams *params, FileAttributeColumnType column); /** @@ -181,6 +185,19 @@ void file_on_reload_callback_register(struct SpaceFile *sfile, onReloadFn callback, onReloadFnData custom_data); +/* folder_history.cc */ + +/* not listbase itself */ +void folderlist_free(struct ListBase *folderlist); +void folderlist_popdir(struct ListBase *folderlist, char *dir); +void folderlist_pushdir(struct ListBase *folderlist, const char *dir); +const char *folderlist_peeklastdir(struct ListBase *folderlist); +bool folderlist_clear_next(struct SpaceFile *sfile); + +void folder_history_list_ensure_for_active_browse_mode(struct SpaceFile *sfile); +void folder_history_list_free(struct SpaceFile *sfile); +struct ListBase folder_history_list_duplicate(struct ListBase *listbase); + /* file_panels.c */ void file_tool_props_region_panels_register(struct ARegionType *art); diff --git a/source/blender/editors/space_file/file_ops.c b/source/blender/editors/space_file/file_ops.c index 59d9a15fbab..3f671fd44a1 100644 --- a/source/blender/editors/space_file/file_ops.c +++ b/source/blender/editors/space_file/file_ops.c @@ -213,7 +213,7 @@ static FileSelect file_select_do(bContext *C, int selected_idx, bool do_diropen) else { retval = FILE_SELECT_FILE; } - fileselect_file_set(sfile, selected_idx); + fileselect_file_set(C, sfile, selected_idx); } return retval; } @@ -367,6 +367,39 @@ static FileSelect file_select( /** \} */ /* -------------------------------------------------------------------- */ +/** \name Bookmark Utilities + * \{ */ + +/** + * Local utility to write #BLENDER_BOOKMARK_FILE, reporting an error on failure. + */ +static bool fsmenu_write_file_and_refresh_or_report_error(struct FSMenu *fsmenu, + ScrArea *area, + ReportList *reports) +{ + /* NOTE: use warning instead of error here, because the bookmark operation may be part of + * other actions which should not cause the operator to fail entirely. */ + const char *cfgdir = BKE_appdir_folder_id_create(BLENDER_USER_CONFIG, NULL); + if (UNLIKELY(!cfgdir)) { + BKE_report(reports, RPT_ERROR, "Unable to create configuration directory to write bookmarks"); + return false; + } + + char filepath[FILE_MAX]; + BLI_join_dirfile(filepath, sizeof(filepath), cfgdir, BLENDER_BOOKMARK_FILE); + if (UNLIKELY(!fsmenu_write_file(fsmenu, filepath))) { + BKE_reportf(reports, RPT_ERROR, "Unable to open or write bookmark file \"%s\"", filepath); + return false; + } + + ED_area_tag_refresh(area); + ED_area_tag_redraw(area); + return true; +} + +/** \} */ + +/* -------------------------------------------------------------------- */ /** \name Box Select Operator * \{ */ @@ -451,7 +484,7 @@ static int file_box_select_modal(bContext *C, wmOperator *op, const wmEvent *eve else { params->highlight_file = -1; params->sel_first = params->sel_last = -1; - fileselect_file_set(sfile, params->active_file); + fileselect_file_set(C, sfile, params->active_file); file_select_deselect_all(sfile, FILE_SEL_HIGHLIGHTED); WM_event_add_notifier(C, NC_SPACE | ND_SPACE_FILE_PARAMS, NULL); } @@ -669,7 +702,8 @@ void FILE_OT_select(wmOperatorType *ot) /** * \returns true if selection has changed */ -static bool file_walk_select_selection_set(wmWindow *win, +static bool file_walk_select_selection_set(struct bContext *C, + wmWindow *win, ARegion *region, SpaceFile *sfile, const int direction, @@ -775,7 +809,7 @@ static bool file_walk_select_selection_set(wmWindow *win, } BLI_assert(IN_RANGE(active, -1, numfiles)); - fileselect_file_set(sfile, params->active_file); + fileselect_file_set(C, sfile, params->active_file); /* ensure newly selected file is inside viewbounds */ file_ensure_inside_viewbounds(region, sfile, params->active_file); @@ -856,7 +890,8 @@ static bool file_walk_select_do(bContext *C, } } - return file_walk_select_selection_set(win, + return file_walk_select_selection_set(C, + win, region, sfile, direction, @@ -1053,19 +1088,17 @@ static int bookmark_select_exec(bContext *C, wmOperator *op) { Main *bmain = CTX_data_main(C); SpaceFile *sfile = CTX_wm_space_file(C); - PropertyRNA *prop; - if ((prop = RNA_struct_find_property(op->ptr, "dir"))) { - FileSelectParams *params = ED_fileselect_get_active_params(sfile); - char entry[256]; + PropertyRNA *prop = RNA_struct_find_property(op->ptr, "dir"); + FileSelectParams *params = ED_fileselect_get_active_params(sfile); + char entry[256]; - RNA_property_string_get(op->ptr, prop, entry); - BLI_strncpy(params->dir, entry, sizeof(params->dir)); - BLI_path_normalize_dir(BKE_main_blendfile_path(bmain), params->dir); - ED_file_change_dir(C); + RNA_property_string_get(op->ptr, prop, entry); + BLI_strncpy(params->dir, entry, sizeof(params->dir)); + BLI_path_normalize_dir(BKE_main_blendfile_path(bmain), params->dir); + ED_file_change_dir(C); - WM_event_add_notifier(C, NC_SPACE | ND_SPACE_FILE_LIST, NULL); - } + WM_event_add_notifier(C, NC_SPACE | ND_SPACE_FILE_LIST, NULL); return OPERATOR_FINISHED; } @@ -1095,7 +1128,7 @@ void FILE_OT_select_bookmark(wmOperatorType *ot) /** \name Add Bookmark Operator * \{ */ -static int bookmark_add_exec(bContext *C, wmOperator *UNUSED(op)) +static int bookmark_add_exec(bContext *C, wmOperator *op) { ScrArea *area = CTX_wm_area(C); SpaceFile *sfile = CTX_wm_space_file(C); @@ -1103,19 +1136,11 @@ static int bookmark_add_exec(bContext *C, wmOperator *UNUSED(op)) struct FileSelectParams *params = ED_fileselect_get_active_params(sfile); if (params->dir[0] != '\0') { - char name[FILE_MAX]; fsmenu_insert_entry( fsmenu, FS_CATEGORY_BOOKMARKS, params->dir, NULL, ICON_FILE_FOLDER, FS_INSERT_SAVE); - BLI_join_dirfile(name, - sizeof(name), - BKE_appdir_folder_id_create(BLENDER_USER_CONFIG, NULL), - BLENDER_BOOKMARK_FILE); - fsmenu_write_file(fsmenu, name); + fsmenu_write_file_and_refresh_or_report_error(fsmenu, area, op->reports); } - - ED_area_tag_refresh(area); - ED_area_tag_redraw(area); return OPERATOR_FINISHED; } @@ -1146,27 +1171,11 @@ static int bookmark_delete_exec(bContext *C, wmOperator *op) int nentries = ED_fsmenu_get_nentries(fsmenu, FS_CATEGORY_BOOKMARKS); PropertyRNA *prop = RNA_struct_find_property(op->ptr, "index"); - - if (prop) { - int index; - if (RNA_property_is_set(op->ptr, prop)) { - index = RNA_property_int_get(op->ptr, prop); - } - else { /* if index unset, use active bookmark... */ - index = sfile->bookmarknr; - } - if ((index > -1) && (index < nentries)) { - char name[FILE_MAX]; - - fsmenu_remove_entry(fsmenu, FS_CATEGORY_BOOKMARKS, index); - BLI_join_dirfile(name, - sizeof(name), - BKE_appdir_folder_id_create(BLENDER_USER_CONFIG, NULL), - BLENDER_BOOKMARK_FILE); - fsmenu_write_file(fsmenu, name); - ED_area_tag_refresh(area); - ED_area_tag_redraw(area); - } + const int index = RNA_property_is_set(op->ptr, prop) ? RNA_property_int_get(op->ptr, prop) : + sfile->bookmarknr; + if ((index > -1) && (index < nentries)) { + fsmenu_remove_entry(fsmenu, FS_CATEGORY_BOOKMARKS, index); + fsmenu_write_file_and_refresh_or_report_error(fsmenu, area, op->reports); } return OPERATOR_FINISHED; @@ -1197,7 +1206,7 @@ void FILE_OT_bookmark_delete(wmOperatorType *ot) /** \name Cleanup Bookmark Operator * \{ */ -static int bookmark_cleanup_exec(bContext *C, wmOperator *UNUSED(op)) +static int bookmark_cleanup_exec(bContext *C, wmOperator *op) { ScrArea *area = CTX_wm_area(C); struct FSMenu *fsmenu = ED_fsmenu_get(); @@ -1218,16 +1227,8 @@ static int bookmark_cleanup_exec(bContext *C, wmOperator *UNUSED(op)) } if (changed) { - char name[FILE_MAX]; - - BLI_join_dirfile(name, - sizeof(name), - BKE_appdir_folder_id_create(BLENDER_USER_CONFIG, NULL), - BLENDER_BOOKMARK_FILE); - fsmenu_write_file(fsmenu, name); + fsmenu_write_file_and_refresh_or_report_error(fsmenu, area, op->reports); fsmenu_refresh_bookmarks_status(CTX_wm_manager(C), fsmenu); - ED_area_tag_refresh(area); - ED_area_tag_redraw(area); } return OPERATOR_FINISHED; @@ -1269,8 +1270,6 @@ static int bookmark_move_exec(bContext *C, wmOperator *op) struct FSMenuEntry *fsmentry = ED_fsmenu_get_category(fsmenu, FS_CATEGORY_BOOKMARKS); const struct FSMenuEntry *fsmentry_org = fsmentry; - char fname[FILE_MAX]; - const int direction = RNA_enum_get(op->ptr, "direction"); const int totitems = ED_fsmenu_get_nentries(fsmenu, FS_CATEGORY_BOOKMARKS); const int act_index = sfile->bookmarknr; @@ -1306,13 +1305,8 @@ static int bookmark_move_exec(bContext *C, wmOperator *op) /* Need to update active bookmark number. */ sfile->bookmarknr = new_index; - BLI_join_dirfile(fname, - sizeof(fname), - BKE_appdir_folder_id_create(BLENDER_USER_CONFIG, NULL), - BLENDER_BOOKMARK_FILE); - fsmenu_write_file(fsmenu, fname); + fsmenu_write_file_and_refresh_or_report_error(fsmenu, area, op->reports); - ED_area_tag_redraw(area); return OPERATOR_FINISHED; } @@ -1352,21 +1346,16 @@ void FILE_OT_bookmark_move(wmOperatorType *ot) /** \name Reset Recent Blend Files Operator * \{ */ -static int reset_recent_exec(bContext *C, wmOperator *UNUSED(op)) +static int reset_recent_exec(bContext *C, wmOperator *op) { ScrArea *area = CTX_wm_area(C); - char name[FILE_MAX]; struct FSMenu *fsmenu = ED_fsmenu_get(); while (ED_fsmenu_get_entry(fsmenu, FS_CATEGORY_RECENT, 0) != NULL) { fsmenu_remove_entry(fsmenu, FS_CATEGORY_RECENT, 0); } - BLI_join_dirfile(name, - sizeof(name), - BKE_appdir_folder_id_create(BLENDER_USER_CONFIG, NULL), - BLENDER_BOOKMARK_FILE); - fsmenu_write_file(fsmenu, name); - ED_area_tag_redraw(area); + + fsmenu_write_file_and_refresh_or_report_error(fsmenu, area, op->reports); return OPERATOR_FINISHED; } @@ -1568,7 +1557,8 @@ void FILE_OT_cancel(struct wmOperatorType *ot) /** \name Operator Utilities * \{ */ -void file_sfile_to_operator_ex(Main *bmain, wmOperator *op, SpaceFile *sfile, char *filepath) +void file_sfile_to_operator_ex( + bContext *C, Main *bmain, wmOperator *op, SpaceFile *sfile, char *filepath) { FileSelectParams *params = ED_fileselect_get_active_params(sfile); PropertyRNA *prop; @@ -1582,14 +1572,27 @@ void file_sfile_to_operator_ex(Main *bmain, wmOperator *op, SpaceFile *sfile, ch } } + char value[FILE_MAX]; if ((prop = RNA_struct_find_property(op->ptr, "filename"))) { + RNA_property_string_get(op->ptr, prop, value); RNA_property_string_set(op->ptr, prop, params->file); + if (RNA_property_update_check(prop) && !STREQ(params->file, value)) { + RNA_property_update(C, op->ptr, prop); + } } if ((prop = RNA_struct_find_property(op->ptr, "directory"))) { + RNA_property_string_get(op->ptr, prop, value); RNA_property_string_set(op->ptr, prop, params->dir); + if (RNA_property_update_check(prop) && !STREQ(params->dir, value)) { + RNA_property_update(C, op->ptr, prop); + } } if ((prop = RNA_struct_find_property(op->ptr, "filepath"))) { + RNA_property_string_get(op->ptr, prop, value); RNA_property_string_set(op->ptr, prop, filepath); + if (RNA_property_update_check(prop) && !STREQ(filepath, value)) { + RNA_property_update(C, op->ptr, prop); + } } /* some ops have multiple files to select */ @@ -1643,11 +1646,11 @@ void file_sfile_to_operator_ex(Main *bmain, wmOperator *op, SpaceFile *sfile, ch } } } -void file_sfile_to_operator(Main *bmain, wmOperator *op, SpaceFile *sfile) +void file_sfile_to_operator(bContext *C, Main *bmain, wmOperator *op, SpaceFile *sfile) { char filepath_dummy[FILE_MAX]; - file_sfile_to_operator_ex(bmain, op, sfile, filepath_dummy); + file_sfile_to_operator_ex(C, bmain, op, sfile, filepath_dummy); } void file_operator_to_sfile(Main *bmain, SpaceFile *sfile, wmOperator *op) @@ -1708,7 +1711,7 @@ void file_draw_check_ex(bContext *C, ScrArea *area) if (op) { /* fail on reload */ if (op->type->check) { Main *bmain = CTX_data_main(C); - file_sfile_to_operator(bmain, op, sfile); + file_sfile_to_operator(C, bmain, op, sfile); /* redraw */ if (op->type->check(C, op)) { @@ -1795,15 +1798,17 @@ static bool file_execute(bContext *C, SpaceFile *sfile) } /* Opening file, sends events now, so things get handled on window-queue level. */ else if (sfile->op) { + ScrArea *area = CTX_wm_area(C); + struct FSMenu *fsmenu = ED_fsmenu_get(); wmOperator *op = sfile->op; char filepath[FILE_MAX]; sfile->op = NULL; - file_sfile_to_operator_ex(bmain, op, sfile, filepath); + file_sfile_to_operator_ex(C, bmain, op, sfile, filepath); if (BLI_exists(params->dir)) { - fsmenu_insert_entry(ED_fsmenu_get(), + fsmenu_insert_entry(fsmenu, FS_CATEGORY_RECENT, params->dir, NULL, @@ -1811,11 +1816,8 @@ static bool file_execute(bContext *C, SpaceFile *sfile) FS_INSERT_SAVE | FS_INSERT_FIRST); } - BLI_join_dirfile(filepath, - sizeof(filepath), - BKE_appdir_folder_id_create(BLENDER_USER_CONFIG, NULL), - BLENDER_BOOKMARK_FILE); - fsmenu_write_file(ED_fsmenu_get(), filepath); + fsmenu_write_file_and_refresh_or_report_error(fsmenu, area, op->reports); + WM_event_fileselect_event(CTX_wm_manager(C), op, EVT_FILESELECT_EXEC); } @@ -2268,7 +2270,7 @@ static int filepath_drop_exec(bContext *C, wmOperator *op) file_sfile_filepath_set(sfile, filepath); if (sfile->op) { - file_sfile_to_operator(bmain, sfile->op, sfile); + file_sfile_to_operator(C, bmain, sfile->op, sfile); file_draw_check(C); } @@ -2327,7 +2329,6 @@ static int file_directory_new_exec(bContext *C, wmOperator *op) char name[FILE_MAXFILE]; char path[FILE_MAX]; bool generate_name = true; - PropertyRNA *prop; wmWindowManager *wm = CTX_wm_manager(C); SpaceFile *sfile = CTX_wm_space_file(C); @@ -2341,7 +2342,8 @@ static int file_directory_new_exec(bContext *C, wmOperator *op) path[0] = '\0'; - if ((prop = RNA_struct_find_property(op->ptr, "directory"))) { + { + PropertyRNA *prop = RNA_struct_find_property(op->ptr, "directory"); RNA_property_string_get(op->ptr, prop, path); if (path[0] != '\0') { generate_name = false; diff --git a/source/blender/editors/space_file/filelist.c b/source/blender/editors/space_file/filelist.cc index 24e1faaf4c9..daf04aa5f41 100644 --- a/source/blender/editors/space_file/filelist.c +++ b/source/blender/editors/space_file/filelist.cc @@ -7,11 +7,11 @@ /* global includes */ -#include <math.h> -#include <stdlib.h> -#include <string.h> +#include <cmath> +#include <cstdlib> +#include <cstring> +#include <ctime> #include <sys/stat.h> -#include <time.h> #ifndef WIN32 # include <unistd.h> @@ -79,183 +79,14 @@ #define FILEDIR_NBR_ENTRIES_UNSET -1 -/* ----------------- FOLDERLIST (previous/next) -------------- */ - -typedef struct FolderList { - struct FolderList *next, *prev; - char *foldername; -} FolderList; - -void folderlist_popdir(struct ListBase *folderlist, char *dir) -{ - const char *prev_dir; - struct FolderList *folder; - folder = folderlist->last; - - if (folder) { - /* remove the current directory */ - MEM_freeN(folder->foldername); - BLI_freelinkN(folderlist, folder); - - folder = folderlist->last; - if (folder) { - prev_dir = folder->foldername; - BLI_strncpy(dir, prev_dir, FILE_MAXDIR); - } - } - /* delete the folder next or use setdir directly before PREVIOUS OP */ -} - -void folderlist_pushdir(ListBase *folderlist, const char *dir) -{ - if (!dir[0]) { - return; - } - - struct FolderList *folder, *previous_folder; - previous_folder = folderlist->last; - - /* check if already exists */ - if (previous_folder && previous_folder->foldername) { - if (BLI_path_cmp(previous_folder->foldername, dir) == 0) { - return; - } - } - - /* create next folder element */ - folder = MEM_mallocN(sizeof(*folder), __func__); - folder->foldername = BLI_strdup(dir); - - /* add it to the end of the list */ - BLI_addtail(folderlist, folder); -} - -const char *folderlist_peeklastdir(ListBase *folderlist) -{ - struct FolderList *folder; - - if (!folderlist->last) { - return NULL; - } - - folder = folderlist->last; - return folder->foldername; -} - -int folderlist_clear_next(struct SpaceFile *sfile) -{ - const FileSelectParams *params = ED_fileselect_get_active_params(sfile); - struct FolderList *folder; - - /* if there is no folder_next there is nothing we can clear */ - if (BLI_listbase_is_empty(sfile->folders_next)) { - return 0; - } - - /* if previous_folder, next_folder or refresh_folder operators are executed - * it doesn't clear folder_next */ - folder = sfile->folders_prev->last; - if ((!folder) || (BLI_path_cmp(folder->foldername, params->dir) == 0)) { - return 0; - } - - /* eventually clear flist->folders_next */ - return 1; -} - -void folderlist_free(ListBase *folderlist) -{ - if (folderlist) { - FolderList *folder; - for (folder = folderlist->first; folder; folder = folder->next) { - MEM_freeN(folder->foldername); - } - BLI_freelistN(folderlist); - } -} - -static ListBase folderlist_duplicate(ListBase *folderlist) -{ - ListBase folderlistn = {NULL}; - - BLI_duplicatelist(&folderlistn, folderlist); - - for (FolderList *folder = folderlistn.first; folder; folder = folder->next) { - folder->foldername = MEM_dupallocN(folder->foldername); - } - return folderlistn; -} - -/* ----------------- Folder-History (wraps/owns file list above) -------------- */ - -static FileFolderHistory *folder_history_find(const SpaceFile *sfile, eFileBrowse_Mode browse_mode) -{ - LISTBASE_FOREACH (FileFolderHistory *, history, &sfile->folder_histories) { - if (history->browse_mode == browse_mode) { - return history; - } - } - - return NULL; -} - -void folder_history_list_ensure_for_active_browse_mode(SpaceFile *sfile) -{ - FileFolderHistory *history = folder_history_find(sfile, sfile->browse_mode); - - if (!history) { - history = MEM_callocN(sizeof(*history), __func__); - history->browse_mode = sfile->browse_mode; - BLI_addtail(&sfile->folder_histories, history); - } - - sfile->folders_next = &history->folders_next; - sfile->folders_prev = &history->folders_prev; -} - -static void folder_history_entry_free(SpaceFile *sfile, FileFolderHistory *history) -{ - if (sfile->folders_prev == &history->folders_prev) { - sfile->folders_prev = NULL; - } - if (sfile->folders_next == &history->folders_next) { - sfile->folders_next = NULL; - } - folderlist_free(&history->folders_prev); - folderlist_free(&history->folders_next); - BLI_freelinkN(&sfile->folder_histories, history); -} - -void folder_history_list_free(SpaceFile *sfile) -{ - LISTBASE_FOREACH_MUTABLE (FileFolderHistory *, history, &sfile->folder_histories) { - folder_history_entry_free(sfile, history); - } -} - -ListBase folder_history_list_duplicate(ListBase *listbase) -{ - ListBase histories = {NULL}; - - LISTBASE_FOREACH (FileFolderHistory *, history, listbase) { - FileFolderHistory *history_new = MEM_dupallocN(history); - history_new->folders_prev = folderlist_duplicate(&history->folders_prev); - history_new->folders_next = folderlist_duplicate(&history->folders_next); - BLI_addtail(&histories, history_new); - } - - return histories; -} - /* ------------------FILELIST------------------------ */ -typedef struct FileListInternEntry { - struct FileListInternEntry *next, *prev; +struct FileListInternEntry { + FileListInternEntry *next, *prev; FileUID uid; - /** eFileSel_File_Types */ - int typeflag; + eFileSel_File_Types typeflag; /** ID type, in case typeflag has FILE_TYPE_BLENDERLIB set. */ int blentype; @@ -287,18 +118,18 @@ typedef struct FileListInternEntry { /** Defined in BLI_fileops.h */ eFileAttributes attributes; BLI_stat_t st; -} FileListInternEntry; +}; -typedef struct FileListIntern { +struct FileListIntern { /** FileListInternEntry items. */ ListBase entries; FileListInternEntry **filtered; FileUID curr_uid; /* Used to generate UID during internal listing. */ -} FileListIntern; +}; #define FILELIST_ENTRYCACHESIZE_DEFAULT 1024 /* Keep it a power of two! */ -typedef struct FileListEntryCache { +struct FileListEntryCache { size_t size; /* The size of the cache... */ int flags; @@ -327,7 +158,7 @@ typedef struct FileListEntryCache { * previews either in `previews_pool` or `previews_done`. #filelist_cache_previews_update() makes * previews in `preview_done` ready for display, so the counter is decremented there. */ int previews_todo_count; -} FileListEntryCache; +}; /** #FileListCache.flags */ enum { @@ -335,21 +166,21 @@ enum { FLC_PREVIEWS_ACTIVE = 1 << 1, }; -typedef struct FileListEntryPreview { +struct FileListEntryPreview { char filepath[FILE_MAX]; uint flags; int index; int attributes; /* from FileDirEntry. */ int icon_id; -} FileListEntryPreview; +}; /* Dummy wrapper around FileListEntryPreview to ensure we do not access freed memory when freeing * tasks' data (see T74609). */ -typedef struct FileListEntryPreviewTaskData { +struct FileListEntryPreviewTaskData { FileListEntryPreview *preview; -} FileListEntryPreviewTaskData; +}; -typedef struct FileListFilter { +struct FileListFilter { uint64_t filter; uint64_t filter_id; char filter_glob[FILE_MAXFILE]; @@ -357,7 +188,7 @@ typedef struct FileListFilter { short flags; FileAssetCatalogFilterSettingsHandle *asset_catalog_filter; -} FileListFilter; +}; /** #FileListFilter.flags */ enum { @@ -369,13 +200,13 @@ enum { }; struct FileListReadJob; -typedef struct FileList { +struct FileList { FileDirEntryArr filelist; eFileSelectType type; /* The library this list was created for. Stored here so we know when to re-read. */ AssetLibraryReference *asset_library_ref; - struct AssetLibrary *asset_library; /* Non-owning pointer. */ + AssetLibrary *asset_library; /* Non-owning pointer. */ short flags; @@ -386,24 +217,24 @@ typedef struct FileList { /** * File indexer to use. Attribute is always set. */ - const struct FileIndexerType *indexer; + const FileIndexerType *indexer; - struct FileListIntern filelist_intern; + FileListIntern filelist_intern; - struct FileListEntryCache filelist_cache; + FileListEntryCache filelist_cache; /* We need to keep those info outside of actual filelist items, * because those are no more persistent * (only generated on demand, and freed as soon as possible). * Persistent part (mere list of paths + stat info) - * is kept as small as possible, and filebrowser-agnostic. + * is kept as small as possible, and file-browser agnostic. */ GHash *selection_state; short max_recursion; short recursion_level; - struct BlendHandle *libfiledata; + BlendHandle *libfiledata; /* Set given path as root directory, * if last bool is true may change given string in place to a valid value. @@ -419,7 +250,7 @@ typedef struct FileList { void (*prepare_filter_fn)(const struct FileList *, FileListFilter *); short tags; /* FileListTags */ -} FileList; +}; /** #FileList.flags */ enum { @@ -459,23 +290,23 @@ enum { static ImBuf *gSpecialFileImages[SPECIAL_IMG_MAX]; -static void filelist_readjob_main(struct FileListReadJob *job_params, +static void filelist_readjob_main(FileListReadJob *job_params, short *stop, short *do_update, float *progress); -static void filelist_readjob_lib(struct FileListReadJob *job_params, +static void filelist_readjob_lib(FileListReadJob *job_params, short *stop, short *do_update, float *progress); -static void filelist_readjob_dir(struct FileListReadJob *job_params, +static void filelist_readjob_dir(FileListReadJob *job_params, short *stop, short *do_update, float *progress); -static void filelist_readjob_asset_library(struct FileListReadJob *job_params, +static void filelist_readjob_asset_library(FileListReadJob *job_params, short *stop, short *do_update, float *progress); -static void filelist_readjob_main_assets(struct FileListReadJob *job_params, +static void filelist_readjob_main_assets(FileListReadJob *job_params, short *stop, short *do_update, float *progress); @@ -493,7 +324,7 @@ struct FileSortData { bool inverted; }; -static int compare_apply_inverted(int val, const struct FileSortData *sort_data) +static int compare_apply_inverted(int val, const FileSortData *sort_data) { return sort_data->inverted ? -val : val; } @@ -602,9 +433,9 @@ static int compare_direntry_generic(const FileListInternEntry *entry1, static int compare_name(void *user_data, const void *a1, const void *a2) { - const FileListInternEntry *entry1 = a1; - const FileListInternEntry *entry2 = a2; - const struct FileSortData *sort_data = user_data; + const FileListInternEntry *entry1 = static_cast<const FileListInternEntry *>(a1); + const FileListInternEntry *entry2 = static_cast<const FileListInternEntry *>(a2); + const FileSortData *sort_data = static_cast<const FileSortData *>(user_data); int ret; if ((ret = compare_direntry_generic(entry1, entry2))) { @@ -616,9 +447,9 @@ static int compare_name(void *user_data, const void *a1, const void *a2) static int compare_date(void *user_data, const void *a1, const void *a2) { - const FileListInternEntry *entry1 = a1; - const FileListInternEntry *entry2 = a2; - const struct FileSortData *sort_data = user_data; + const FileListInternEntry *entry1 = static_cast<const FileListInternEntry *>(a1); + const FileListInternEntry *entry2 = static_cast<const FileListInternEntry *>(a2); + const FileSortData *sort_data = static_cast<const FileSortData *>(user_data); int64_t time1, time2; int ret; @@ -640,9 +471,9 @@ static int compare_date(void *user_data, const void *a1, const void *a2) static int compare_size(void *user_data, const void *a1, const void *a2) { - const FileListInternEntry *entry1 = a1; - const FileListInternEntry *entry2 = a2; - const struct FileSortData *sort_data = user_data; + const FileListInternEntry *entry1 = static_cast<const FileListInternEntry *>(a1); + const FileListInternEntry *entry2 = static_cast<const FileListInternEntry *>(a2); + const FileSortData *sort_data = static_cast<const FileSortData *>(user_data); uint64_t size1, size2; int ret; @@ -664,9 +495,9 @@ static int compare_size(void *user_data, const void *a1, const void *a2) static int compare_extension(void *user_data, const void *a1, const void *a2) { - const FileListInternEntry *entry1 = a1; - const FileListInternEntry *entry2 = a2; - const struct FileSortData *sort_data = user_data; + const FileListInternEntry *entry1 = static_cast<const FileListInternEntry *>(a1); + const FileListInternEntry *entry2 = static_cast<const FileListInternEntry *>(a2); + const FileSortData *sort_data = static_cast<const FileSortData *>(user_data); int ret; if ((ret = compare_direntry_generic(entry1, entry2))) { @@ -720,7 +551,7 @@ static int compare_extension(void *user_data, const void *a1, const void *a2) void filelist_sort(struct FileList *filelist) { if (filelist->flags & FL_NEED_SORTING) { - void *sort_cb = NULL; + int (*sort_cb)(void *, const void *, const void *) = nullptr; switch (filelist->sort) { case FILE_SORT_ALPHA: @@ -740,10 +571,10 @@ void filelist_sort(struct FileList *filelist) BLI_assert(0); break; } - BLI_listbase_sort_r( - &filelist->filelist_intern.entries, - sort_cb, - &(struct FileSortData){.inverted = (filelist->flags & FL_SORT_INVERT) != 0}); + + FileSortData sort_data{0}; + sort_data.inverted = (filelist->flags & FL_SORT_INVERT) != 0; + BLI_listbase_sort_r(&filelist->filelist_intern.entries, sort_cb, &sort_data); filelist_tag_needs_filtering(filelist); filelist->flags &= ~FL_NEED_SORTING; @@ -1062,7 +893,7 @@ void filelist_filter(FileList *filelist) { int num_filtered = 0; const int num_files = filelist->filelist.entries_num; - FileListInternEntry **filtered_tmp, *file; + FileListInternEntry **filtered_tmp; if (ELEM(filelist->filelist.entries_num, FILEDIR_NBR_ENTRIES_UNSET, 0)) { return; @@ -1087,10 +918,11 @@ void filelist_filter(FileList *filelist) filelist->prepare_filter_fn(filelist, &filelist->filter_data); } - filtered_tmp = MEM_mallocN(sizeof(*filtered_tmp) * (size_t)num_files, __func__); + filtered_tmp = static_cast<FileListInternEntry **>( + MEM_mallocN(sizeof(*filtered_tmp) * (size_t)num_files, __func__)); /* Filter remap & count how many files are left after filter in a single loop. */ - for (file = filelist->filelist_intern.entries.first; file; file = file->next) { + LISTBASE_FOREACH (FileListInternEntry *, file, &filelist->filelist_intern.entries) { if (filelist->filter_fn(file, filelist->filelist.root, &filelist->filter_data)) { filtered_tmp[num_filtered++] = file; } @@ -1099,8 +931,8 @@ void filelist_filter(FileList *filelist) if (filelist->filelist_intern.filtered) { MEM_freeN(filelist->filelist_intern.filtered); } - filelist->filelist_intern.filtered = MEM_mallocN( - sizeof(*filelist->filelist_intern.filtered) * (size_t)num_filtered, __func__); + filelist->filelist_intern.filtered = static_cast<FileListInternEntry **>( + MEM_mallocN(sizeof(*filelist->filelist_intern.filtered) * (size_t)num_filtered, __func__)); memcpy(filelist->filelist_intern.filtered, filtered_tmp, sizeof(*filelist->filelist_intern.filtered) * (size_t)num_filtered); @@ -1228,8 +1060,7 @@ void filelist_setlibrary(FileList *filelist, const AssetLibraryReference *asset_ } if (!filelist->asset_library_ref) { - filelist->asset_library_ref = MEM_mallocN(sizeof(*filelist->asset_library_ref), - "filelist asset library"); + filelist->asset_library_ref = MEM_new<AssetLibraryReference>("filelist asset library"); *filelist->asset_library_ref = *asset_library_ref; filelist->flags |= FL_FORCE_RESET; @@ -1335,7 +1166,7 @@ static int filelist_geticon_ex(const FileDirEntry *file, const bool is_main, const bool ignore_libdir) { - const eFileSel_File_Types typeflag = file->typeflag; + const eFileSel_File_Types typeflag = (eFileSel_File_Types)file->typeflag; if ((typeflag & FILE_TYPE_DIR) && !(ignore_libdir && (typeflag & (FILE_TYPE_BLENDERLIB | FILE_TYPE_BLENDER)))) { @@ -1581,10 +1412,7 @@ static void filelist_intern_entry_free(FileListInternEntry *entry) static void filelist_intern_free(FileListIntern *filelist_intern) { - FileListInternEntry *entry, *entry_next; - - for (entry = filelist_intern->entries.first; entry; entry = entry_next) { - entry_next = entry->next; + LISTBASE_FOREACH_MUTABLE (FileListInternEntry *, entry, &filelist_intern->entries) { filelist_intern_entry_free(entry); } BLI_listbase_clear(&filelist_intern->entries); @@ -1614,11 +1442,14 @@ static int filelist_intern_free_main_files(FileListIntern *filelist_intern) static void filelist_cache_preview_runf(TaskPool *__restrict pool, void *taskdata) { - FileListEntryCache *cache = BLI_task_pool_user_data(pool); - FileListEntryPreviewTaskData *preview_taskdata = taskdata; + FileListEntryCache *cache = static_cast<FileListEntryCache *>(BLI_task_pool_user_data(pool)); + FileListEntryPreviewTaskData *preview_taskdata = static_cast<FileListEntryPreviewTaskData *>( + taskdata); FileListEntryPreview *preview = preview_taskdata->preview; - ThumbSource source = 0; + /* XXX #THB_SOURCE_IMAGE for "historic" reasons. The case of an undefined source should be + * handled better. */ + ThumbSource source = THB_SOURCE_IMAGE; // printf("%s: Start (%d)...\n", __func__, threadid); @@ -1662,7 +1493,8 @@ static void filelist_cache_preview_runf(TaskPool *__restrict pool, void *taskdat static void filelist_cache_preview_freef(TaskPool *__restrict UNUSED(pool), void *taskdata) { - FileListEntryPreviewTaskData *preview_taskdata = taskdata; + FileListEntryPreviewTaskData *preview_taskdata = static_cast<FileListEntryPreviewTaskData *>( + taskdata); /* In case the preview wasn't moved to the "done" queue yet. */ if (preview_taskdata->preview) { @@ -1689,7 +1521,8 @@ static void filelist_cache_previews_clear(FileListEntryCache *cache) BLI_task_pool_cancel(cache->previews_pool); FileListEntryPreview *preview; - while ((preview = BLI_thread_queue_pop_timeout(cache->previews_done, 0))) { + while ((preview = static_cast<FileListEntryPreview *>( + BLI_thread_queue_pop_timeout(cache->previews_done, 0)))) { // printf("%s: DONE %d - %s - %p\n", __func__, preview->index, preview->path, // preview->img); if (preview->icon_id) { @@ -1749,7 +1582,7 @@ static void filelist_cache_previews_push(FileList *filelist, FileDirEntry *entry filelist_cache_preview_ensure_running(cache); entry->flags |= FILE_ENTRY_PREVIEW_LOADING; - FileListEntryPreview *preview = MEM_mallocN(sizeof(*preview), __func__); + FileListEntryPreview *preview = MEM_new<FileListEntryPreview>(__func__); preview->index = index; preview->flags = entry->typeflag; preview->attributes = entry->attributes; @@ -1775,8 +1608,8 @@ static void filelist_cache_previews_push(FileList *filelist, FileDirEntry *entry } // printf("%s: %d - %s\n", __func__, preview->index, preview->filepath); - FileListEntryPreviewTaskData *preview_taskdata = MEM_mallocN(sizeof(*preview_taskdata), - __func__); + FileListEntryPreviewTaskData *preview_taskdata = MEM_new<FileListEntryPreviewTaskData>( + __func__); preview_taskdata->preview = preview; BLI_task_pool_push(cache->previews_pool, filelist_cache_preview_runf, @@ -1793,11 +1626,12 @@ static void filelist_cache_init(FileListEntryCache *cache, size_t cache_size) cache->block_cursor = cache->block_start_index = cache->block_center_index = cache->block_end_index = 0; - cache->block_entries = MEM_mallocN(sizeof(*cache->block_entries) * cache_size, __func__); + cache->block_entries = static_cast<FileDirEntry **>( + MEM_mallocN(sizeof(*cache->block_entries) * cache_size, __func__)); cache->misc_entries = BLI_ghash_ptr_new_ex(__func__, cache_size); - cache->misc_entries_indices = MEM_mallocN(sizeof(*cache->misc_entries_indices) * cache_size, - __func__); + cache->misc_entries_indices = static_cast<int *>( + MEM_mallocN(sizeof(*cache->misc_entries_indices) * cache_size, __func__)); copy_vn_i(cache->misc_entries_indices, cache_size, -1); cache->misc_cursor = 0; @@ -1815,8 +1649,6 @@ static void filelist_cache_init(FileListEntryCache *cache, size_t cache_size) static void filelist_cache_free(FileListEntryCache *cache) { - FileDirEntry *entry, *entry_next; - if (!(cache->flags & FLC_IS_INIT)) { return; } @@ -1830,8 +1662,7 @@ static void filelist_cache_free(FileListEntryCache *cache) BLI_ghash_free(cache->uids, NULL, NULL); - for (entry = cache->cached_entries.first; entry; entry = entry_next) { - entry_next = entry->next; + LISTBASE_FOREACH_MUTABLE (FileDirEntry *, entry, &cache->cached_entries) { filelist_entry_free(entry); } BLI_listbase_clear(&cache->cached_entries); @@ -1839,8 +1670,6 @@ static void filelist_cache_free(FileListEntryCache *cache) static void filelist_cache_clear(FileListEntryCache *cache, size_t new_size) { - FileDirEntry *entry, *entry_next; - if (!(cache->flags & FLC_IS_INIT)) { return; } @@ -1850,14 +1679,14 @@ static void filelist_cache_clear(FileListEntryCache *cache, size_t new_size) cache->block_cursor = cache->block_start_index = cache->block_center_index = cache->block_end_index = 0; if (new_size != cache->size) { - cache->block_entries = MEM_reallocN(cache->block_entries, - sizeof(*cache->block_entries) * new_size); + cache->block_entries = static_cast<FileDirEntry **>( + MEM_reallocN(cache->block_entries, sizeof(*cache->block_entries) * new_size)); } BLI_ghash_clear_ex(cache->misc_entries, NULL, NULL, new_size); if (new_size != cache->size) { - cache->misc_entries_indices = MEM_reallocN(cache->misc_entries_indices, - sizeof(*cache->misc_entries_indices) * new_size); + cache->misc_entries_indices = static_cast<int *>(MEM_reallocN( + cache->misc_entries_indices, sizeof(*cache->misc_entries_indices) * new_size)); } copy_vn_i(cache->misc_entries_indices, new_size, -1); @@ -1865,8 +1694,7 @@ static void filelist_cache_clear(FileListEntryCache *cache, size_t new_size) cache->size = new_size; - for (entry = cache->cached_entries.first; entry; entry = entry_next) { - entry_next = entry->next; + LISTBASE_FOREACH_MUTABLE (FileDirEntry *, entry, &cache->cached_entries) { filelist_entry_free(entry); } BLI_listbase_clear(&cache->cached_entries); @@ -1874,7 +1702,7 @@ static void filelist_cache_clear(FileListEntryCache *cache, size_t new_size) FileList *filelist_new(short type) { - FileList *p = MEM_callocN(sizeof(*p), __func__); + FileList *p = MEM_cnew<FileList>(__func__); filelist_cache_init(&p->filelist_cache, FILELIST_ENTRYCACHESIZE_DEFAULT); @@ -1891,7 +1719,7 @@ void filelist_settype(FileList *filelist, short type) return; } - filelist->type = type; + filelist->type = (eFileSelectType)type; filelist->tags = 0; filelist->indexer = &file_indexer_noop; switch (filelist->type) { @@ -2181,7 +2009,7 @@ static FileDirEntry *filelist_file_create_entry(FileList *filelist, const int in FileListEntryCache *cache = &filelist->filelist_cache; FileDirEntry *ret; - ret = MEM_callocN(sizeof(*ret), __func__); + ret = MEM_cnew<FileDirEntry>(__func__); ret->size = (uint64_t)entry->st.st_size; ret->time = (int64_t)entry->st.st_mtime; @@ -2240,7 +2068,8 @@ FileDirEntry *filelist_file_ex(struct FileList *filelist, const int index, const return cache->block_entries[idx]; } - if ((ret = BLI_ghash_lookup(cache->misc_entries, POINTER_FROM_INT(index)))) { + if ((ret = static_cast<FileDirEntry *>( + BLI_ghash_lookup(cache->misc_entries, POINTER_FROM_INT(index))))) { return ret; } @@ -2253,7 +2082,8 @@ FileDirEntry *filelist_file_ex(struct FileList *filelist, const int index, const /* Else, we have to add new entry to 'misc' cache - and possibly make room for it first! */ ret = filelist_file_create_entry(filelist, index); old_index = cache->misc_entries_indices[cache->misc_cursor]; - if ((old = BLI_ghash_popkey(cache->misc_entries, POINTER_FROM_INT(old_index), NULL))) { + if ((old = static_cast<FileDirEntry *>( + BLI_ghash_popkey(cache->misc_entries, POINTER_FROM_INT(old_index), NULL)))) { BLI_ghash_remove(cache->uids, POINTER_FROM_UINT(old->uid), NULL, NULL); filelist_file_release_entry(filelist, old); } @@ -2371,7 +2201,8 @@ static bool filelist_file_cache_block_create(FileList *filelist, FileDirEntry *entry; /* That entry might have already been requested and stored in misc cache... */ - if ((entry = BLI_ghash_popkey(cache->misc_entries, POINTER_FROM_INT(idx), NULL)) == NULL) { + if ((entry = static_cast<FileDirEntry *>( + BLI_ghash_popkey(cache->misc_entries, POINTER_FROM_INT(idx), NULL))) == NULL) { entry = filelist_file_create_entry(filelist, idx); BLI_ghash_insert(cache->uids, POINTER_FROM_UINT(entry->uid), entry); } @@ -2660,7 +2491,8 @@ bool filelist_cache_previews_update(FileList *filelist) // printf("%s: Update Previews...\n", __func__); while (!BLI_thread_queue_is_empty(cache->previews_done)) { - FileListEntryPreview *preview = BLI_thread_queue_pop(cache->previews_done); + FileListEntryPreview *preview = static_cast<FileListEntryPreview *>( + BLI_thread_queue_pop(cache->previews_done)); FileDirEntry *entry; /* Paranoid (should never happen currently @@ -3050,8 +2882,8 @@ static int filelist_readjob_list_dir(const char *root, continue; } - entry = MEM_callocN(sizeof(*entry), __func__); - entry->relpath = MEM_dupallocN(files[i].relname); + entry = MEM_cnew<FileListInternEntry>(__func__); + entry->relpath = static_cast<char *>(MEM_dupallocN(files[i].relname)); entry->st = files[i].s; BLI_join_dirfile(full_path, FILE_MAX, root, entry->relpath); @@ -3069,14 +2901,14 @@ static int filelist_readjob_list_dir(const char *root, /* Is this a file that points to another file? */ if (entry->attributes & FILE_ATTR_ALIAS) { - entry->redirection_path = MEM_callocN(FILE_MAXDIR, __func__); + entry->redirection_path = MEM_cnew_array<char>(FILE_MAXDIR, __func__); if (BLI_file_alias_target(full_path, entry->redirection_path)) { if (BLI_is_dir(entry->redirection_path)) { entry->typeflag = FILE_TYPE_DIR; BLI_path_slash_ensure(entry->redirection_path); } else { - entry->typeflag = ED_path_extension_type(entry->redirection_path); + entry->typeflag = (eFileSel_File_Types)ED_path_extension_type(entry->redirection_path); } target = entry->redirection_path; #ifdef WIN32 @@ -3101,7 +2933,7 @@ static int filelist_readjob_list_dir(const char *root, } } else { - entry->typeflag = ED_path_extension_type(target); + entry->typeflag = (eFileSel_File_Types)ED_path_extension_type(target); if (filter_glob[0] && BLI_path_extension_check_glob(target, filter_glob)) { entry->typeflag |= FILE_TYPE_OPERATOR; } @@ -3124,6 +2956,8 @@ static int filelist_readjob_list_dir(const char *root, } typedef enum ListLibOptions { + LIST_LIB_OPTION_NONE = 0, + /* Will read both the groups + actual ids from the library. Reduces the amount of times that * a library needs to be opened. */ LIST_LIB_RECURSIVE = (1 << 0), @@ -3134,11 +2968,12 @@ typedef enum ListLibOptions { /* Add given root as result. */ LIST_LIB_ADD_PARENT = (1 << 2), } ListLibOptions; +ENUM_OPERATORS(ListLibOptions, LIST_LIB_ADD_PARENT); static FileListInternEntry *filelist_readjob_list_lib_group_create(const int idcode, const char *group_name) { - FileListInternEntry *entry = MEM_callocN(sizeof(*entry), __func__); + FileListInternEntry *entry = MEM_cnew<FileListInternEntry>(__func__); entry->relpath = BLI_strdup(group_name); entry->typeflag |= FILE_TYPE_BLENDERLIB | FILE_TYPE_DIR; entry->blentype = idcode; @@ -3151,7 +2986,7 @@ static void filelist_readjob_list_lib_add_datablock(ListBase *entries, const int idcode, const char *group_name) { - FileListInternEntry *entry = MEM_callocN(sizeof(*entry), __func__); + FileListInternEntry *entry = MEM_cnew<FileListInternEntry>(__func__); if (prefix_relpath_with_group_name) { entry->relpath = BLI_sprintfN("%s/%s", group_name, datablock_info->name); } @@ -3175,7 +3010,7 @@ static void filelist_readjob_list_lib_add_datablocks(ListBase *entries, const char *group_name) { for (LinkNode *ln = datablock_infos; ln; ln = ln->next) { - struct BLODataBlockInfo *datablock_info = ln->link; + struct BLODataBlockInfo *datablock_info = static_cast<BLODataBlockInfo *>(ln->link); filelist_readjob_list_lib_add_datablock( entries, datablock_info, prefix_relpath_with_group_name, idcode, group_name); } @@ -3199,7 +3034,7 @@ static void filelist_readjob_list_lib_add_from_indexer_entries( static FileListInternEntry *filelist_readjob_list_lib_navigate_to_parent_entry_create(void) { - FileListInternEntry *entry = MEM_callocN(sizeof(*entry), __func__); + FileListInternEntry *entry = MEM_cnew<FileListInternEntry>(__func__); entry->relpath = BLI_strdup(FILENAME_PARENT); entry->typeflag |= (FILE_TYPE_BLENDERLIB | FILE_TYPE_DIR); return entry; @@ -3279,7 +3114,7 @@ static int filelist_readjob_list_lib(const char *root, } /* Open the library file. */ - BlendFileReadReport bf_reports = {.reports = NULL}; + BlendFileReadReport bf_reports{}; libfiledata = BLO_blendhandle_from_file(dir, &bf_reports); if (libfiledata == NULL) { return 0; @@ -3310,7 +3145,7 @@ static int filelist_readjob_list_lib(const char *root, group_len = BLI_linklist_count(groups); for (LinkNode *ln = groups; ln; ln = ln->next) { - const char *group_name = ln->link; + const char *group_name = static_cast<char *>(ln->link); const int idcode = groupname_to_code(group_name); FileListInternEntry *group_entry = filelist_readjob_list_lib_group_create(idcode, group_name); @@ -3615,7 +3450,7 @@ static void filelist_readjob_recursive_dir_add_items(const bool do_lib, int dirs_done_count = 0, dirs_todo_count = 1; todo_dirs = BLI_stack_new(sizeof(*td_dir), __func__); - td_dir = BLI_stack_push_r(todo_dirs); + td_dir = static_cast<TodoDir *>(BLI_stack_push_r(todo_dirs)); td_dir->level = 1; BLI_strncpy(dir, filelist->filelist.root, sizeof(dir)); @@ -3625,13 +3460,13 @@ static void filelist_readjob_recursive_dir_add_items(const bool do_lib, td_dir->dir = BLI_strdup(dir); /* Init the file indexer. */ - FileIndexer indexer_runtime = {.callbacks = filelist->indexer}; + FileIndexer indexer_runtime{}; + indexer_runtime.callbacks = filelist->indexer; if (indexer_runtime.callbacks->init_user_data) { indexer_runtime.user_data = indexer_runtime.callbacks->init_user_data(dir, sizeof(dir)); } while (!BLI_stack_is_empty(todo_dirs) && !(*stop)) { - FileListInternEntry *entry; int entries_num = 0; char *subdir; @@ -3639,7 +3474,7 @@ static void filelist_readjob_recursive_dir_add_items(const bool do_lib, int recursion_level; bool skip_currpar; - td_dir = BLI_stack_peek(todo_dirs); + td_dir = static_cast<TodoDir *>(BLI_stack_peek(todo_dirs)); subdir = td_dir->dir; recursion_level = td_dir->level; skip_currpar = (recursion_level > 1); @@ -3657,7 +3492,7 @@ static void filelist_readjob_recursive_dir_add_items(const bool do_lib, bool is_lib = false; if (do_lib) { - ListLibOptions list_lib_options = 0; + ListLibOptions list_lib_options = LIST_LIB_OPTION_NONE; if (!skip_currpar) { list_lib_options |= LIST_LIB_ADD_PARENT; } @@ -3684,7 +3519,7 @@ static void filelist_readjob_recursive_dir_add_items(const bool do_lib, subdir, &entries, filter_glob, do_lib, job_params->main_name, skip_currpar); } - for (entry = entries.first; entry; entry = entry->next) { + LISTBASE_FOREACH (FileListInternEntry *, entry, &entries) { entry->uid = filelist_uid_generate(filelist); /* When loading entries recursive, the rel_path should be relative from the root dir. @@ -3701,7 +3536,7 @@ static void filelist_readjob_recursive_dir_add_items(const bool do_lib, /* We have a directory we want to list, add it to todo list! */ BLI_join_dirfile(dir, sizeof(dir), root, entry->relpath); BLI_path_normalize_dir(job_params->main_name, dir); - td_dir = BLI_stack_push_r(todo_dirs); + td_dir = static_cast<TodoDir *>(BLI_stack_push_r(todo_dirs)); td_dir->level = recursion_level + 1; td_dir->dir = BLI_strdup(dir); dirs_todo_count++; @@ -3727,7 +3562,7 @@ static void filelist_readjob_recursive_dir_add_items(const bool do_lib, /* If we were interrupted by stop, stack may not be empty and we need to free * pending dir paths. */ while (!BLI_stack_is_empty(todo_dirs)) { - td_dir = BLI_stack_peek(todo_dirs); + td_dir = static_cast<TodoDir *>(BLI_stack_peek(todo_dirs)); MEM_freeN(td_dir->dir); BLI_stack_discard(todo_dirs); } @@ -3831,7 +3666,7 @@ static void filelist_readjob_main_assets_add_items(FileListReadJob *job_params, const char *id_code_name = BKE_idtype_idcode_to_name(GS(id_iter->name)); - entry = MEM_callocN(sizeof(*entry), __func__); + entry = MEM_cnew<FileListInternEntry>(__func__); entry->relpath = BLI_strdup(id_code_name); entry->name = id_iter->name + 2; entry->free_name = false; @@ -3935,7 +3770,7 @@ static bool filelist_readjob_is_partial_read(const FileListReadJob *read_job) */ static void filelist_readjob_startjob(void *flrjv, short *stop, short *do_update, float *progress) { - FileListReadJob *flrj = flrjv; + FileListReadJob *flrj = static_cast<FileListReadJob *>(flrjv); // printf("START filelist reading (%d files, main thread: %d)\n", // flrj->filelist->filelist.entries_num, BLI_thread_is_main()); @@ -3944,7 +3779,7 @@ static void filelist_readjob_startjob(void *flrjv, short *stop, short *do_update BLI_assert((flrj->tmp_filelist == NULL) && flrj->filelist); - flrj->tmp_filelist = MEM_dupallocN(flrj->filelist); + flrj->tmp_filelist = static_cast<FileList *>(MEM_dupallocN(flrj->filelist)); BLI_listbase_clear(&flrj->tmp_filelist->filelist.entries); flrj->tmp_filelist->filelist.entries_num = FILEDIR_NBR_ENTRIES_UNSET; @@ -3976,7 +3811,7 @@ static void filelist_readjob_startjob(void *flrjv, short *stop, short *do_update */ static void filelist_readjob_update(void *flrjv) { - FileListReadJob *flrj = flrjv; + FileListReadJob *flrj = static_cast<FileListReadJob *>(flrjv); FileListIntern *fl_intern = &flrj->filelist->filelist_intern; ListBase new_entries = {NULL}; int entries_num, new_entries_num = 0; @@ -4019,7 +3854,7 @@ static void filelist_readjob_update(void *flrjv) static void filelist_readjob_endjob(void *flrjv) { - FileListReadJob *flrj = flrjv; + FileListReadJob *flrj = static_cast<FileListReadJob *>(flrjv); /* In case there would be some dangling update... */ filelist_readjob_update(flrjv); @@ -4030,7 +3865,7 @@ static void filelist_readjob_endjob(void *flrjv) static void filelist_readjob_free(void *flrjv) { - FileListReadJob *flrj = flrjv; + FileListReadJob *flrj = static_cast<FileListReadJob *>(flrjv); // printf("END filelist reading (%d files)\n", flrj->filelist->filelist.entries_num); @@ -4060,7 +3895,7 @@ void filelist_readjob_start(FileList *filelist, const int space_notifier, const } /* prepare job data */ - flrj = MEM_callocN(sizeof(*flrj), __func__); + flrj = MEM_cnew<FileListReadJob>(__func__); flrj->filelist = filelist; flrj->current_main = bmain; BLI_strncpy(flrj->main_name, BKE_main_blendfile_path(bmain), sizeof(flrj->main_name)); diff --git a/source/blender/editors/space_file/filelist.h b/source/blender/editors/space_file/filelist.h index 4c1ae79eb22..89831483fdf 100644 --- a/source/blender/editors/space_file/filelist.h +++ b/source/blender/editors/space_file/filelist.h @@ -35,17 +35,6 @@ typedef enum FileCheckType { CHECK_ALL = 3, } FileCheckType; -/* not listbase itself */ -void folderlist_free(struct ListBase *folderlist); -void folderlist_popdir(struct ListBase *folderlist, char *dir); -void folderlist_pushdir(struct ListBase *folderlist, const char *dir); -const char *folderlist_peeklastdir(struct ListBase *folderlist); -int folderlist_clear_next(struct SpaceFile *sfile); - -void folder_history_list_ensure_for_active_browse_mode(struct SpaceFile *sfile); -void folder_history_list_free(struct SpaceFile *sfile); -struct ListBase folder_history_list_duplicate(struct ListBase *listbase); - void filelist_setsorting(struct FileList *filelist, short sort, bool invert_sort); void filelist_sort(struct FileList *filelist); diff --git a/source/blender/editors/space_file/filesel.c b/source/blender/editors/space_file/filesel.c index e42e1e98660..93aa5cf992d 100644 --- a/source/blender/editors/space_file/filesel.c +++ b/source/blender/editors/space_file/filesel.c @@ -665,12 +665,17 @@ void ED_fileselect_params_to_userdef(SpaceFile *sfile, } } -void fileselect_file_set(SpaceFile *sfile, const int index) +void fileselect_file_set(struct bContext *C, SpaceFile *sfile, const int index) { const struct FileDirEntry *file = filelist_file(sfile->files, index); if (file && file->relpath && file->relpath[0] && !(file->typeflag & FILE_TYPE_DIR)) { FileSelectParams *params = ED_fileselect_get_active_params(sfile); BLI_strncpy(params->file, file->relpath, FILE_MAXFILE); + if (sfile->op) { + /* Update the filepath properties of the operator. */ + Main *bmain = CTX_data_main(C); + file_sfile_to_operator(C, bmain, sfile->op, sfile); + } } } @@ -1041,7 +1046,7 @@ void ED_fileselect_init_layout(struct SpaceFile *sfile, ARegion *region) layout->attribute_column_header_h = 0; layout->offset_top = layout->attribute_column_header_h; layout->height = (int)(BLI_rctf_size_y(&v2d->cur) - 2 * layout->tile_border_y); - /* Padding by full scrollbar H is too much, can overlap tile border Y. */ + /* Padding by full scroll-bar H is too much, can overlap tile border Y. */ layout->rows = (layout->height - V2D_SCROLL_HEIGHT + layout->tile_border_y) / (layout->tile_h + 2 * layout->tile_border_y); layout->tile_w = VERTLIST_MAJORCOLUMN_WIDTH; @@ -1385,3 +1390,24 @@ ScrArea *ED_fileselect_handler_area_find_any_with_op(const wmWindow *win) return NULL; } + +void ED_fileselect_ensure_default_filepath(struct bContext *C, + struct wmOperator *op, + const char *extension) +{ + if (!RNA_struct_property_is_set_ex(op->ptr, "filepath", false)) { + struct Main *bmain = CTX_data_main(C); + char filepath[FILE_MAX]; + const char *blendfile_path = BKE_main_blendfile_path(bmain); + + if (blendfile_path[0] == '\0') { + BLI_strncpy(filepath, DATA_("untitled"), sizeof(filepath)); + } + else { + BLI_strncpy(filepath, blendfile_path, sizeof(filepath)); + } + + BLI_path_extension_replace(filepath, sizeof(filepath), extension); + RNA_string_set(op->ptr, "filepath", filepath); + } +} diff --git a/source/blender/editors/space_file/folder_history.cc b/source/blender/editors/space_file/folder_history.cc new file mode 100644 index 00000000000..1cb8fa279c5 --- /dev/null +++ b/source/blender/editors/space_file/folder_history.cc @@ -0,0 +1,199 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later + * Copyright 2007 Blender Foundation. All rights reserved. */ + +/** \file + * \ingroup spfile + * + * Storage for a list of folders for history backward and forward navigation. + */ + +#include <cstring> + +#include "BLI_listbase.h" +#include "BLI_path_util.h" +#include "BLI_string.h" + +#include "BKE_context.h" + +#include "DNA_space_types.h" + +#include "ED_fileselect.h" + +#include "MEM_guardedalloc.h" + +#include "file_intern.h" + +/* -------------------------------------------------------------------- */ +/** \name FOLDERLIST (previous/next) + * \{ */ + +typedef struct FolderList { + struct FolderList *next, *prev; + char *foldername; +} FolderList; + +void folderlist_popdir(struct ListBase *folderlist, char *dir) +{ + const char *prev_dir; + struct FolderList *folder; + folder = static_cast<FolderList *>(folderlist->last); + + if (folder) { + /* remove the current directory */ + MEM_freeN(folder->foldername); + BLI_freelinkN(folderlist, folder); + + folder = static_cast<FolderList *>(folderlist->last); + if (folder) { + prev_dir = folder->foldername; + BLI_strncpy(dir, prev_dir, FILE_MAXDIR); + } + } + /* Delete the folder next or use set-directory directly before PREVIOUS OP. */ +} + +void folderlist_pushdir(ListBase *folderlist, const char *dir) +{ + if (!dir[0]) { + return; + } + + struct FolderList *folder, *previous_folder; + previous_folder = static_cast<FolderList *>(folderlist->last); + + /* check if already exists */ + if (previous_folder && previous_folder->foldername) { + if (BLI_path_cmp(previous_folder->foldername, dir) == 0) { + return; + } + } + + /* create next folder element */ + folder = MEM_new<FolderList>(__func__); + folder->foldername = BLI_strdup(dir); + + /* add it to the end of the list */ + BLI_addtail(folderlist, folder); +} + +const char *folderlist_peeklastdir(ListBase *folderlist) +{ + struct FolderList *folder; + + if (!folderlist->last) { + return NULL; + } + + folder = static_cast<FolderList *>(folderlist->last); + return folder->foldername; +} + +bool folderlist_clear_next(struct SpaceFile *sfile) +{ + const FileSelectParams *params = ED_fileselect_get_active_params(sfile); + struct FolderList *folder; + + /* if there is no folder_next there is nothing we can clear */ + if (BLI_listbase_is_empty(sfile->folders_next)) { + return false; + } + + /* if previous_folder, next_folder or refresh_folder operators are executed + * it doesn't clear folder_next */ + folder = static_cast<FolderList *>(sfile->folders_prev->last); + if ((!folder) || (BLI_path_cmp(folder->foldername, params->dir) == 0)) { + return false; + } + + /* eventually clear flist->folders_next */ + return true; +} + +void folderlist_free(ListBase *folderlist) +{ + if (folderlist) { + LISTBASE_FOREACH (FolderList *, folder, folderlist) { + MEM_freeN(folder->foldername); + } + BLI_freelistN(folderlist); + } +} + +static ListBase folderlist_duplicate(ListBase *folderlist) +{ + ListBase folderlistn = {NULL}; + + BLI_duplicatelist(&folderlistn, folderlist); + + LISTBASE_FOREACH (FolderList *, folder, &folderlistn) { + folder->foldername = (char *)MEM_dupallocN(folder->foldername); + } + return folderlistn; +} + +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Folder-History (wraps/owns file list above) + * \{ */ + +static FileFolderHistory *folder_history_find(const SpaceFile *sfile, eFileBrowse_Mode browse_mode) +{ + LISTBASE_FOREACH (FileFolderHistory *, history, &sfile->folder_histories) { + if (history->browse_mode == browse_mode) { + return history; + } + } + + return NULL; +} + +void folder_history_list_ensure_for_active_browse_mode(SpaceFile *sfile) +{ + FileFolderHistory *history = folder_history_find(sfile, (eFileBrowse_Mode)sfile->browse_mode); + + if (!history) { + history = MEM_cnew<FileFolderHistory>(__func__); + history->browse_mode = sfile->browse_mode; + BLI_addtail(&sfile->folder_histories, history); + } + + sfile->folders_next = &history->folders_next; + sfile->folders_prev = &history->folders_prev; +} + +static void folder_history_entry_free(SpaceFile *sfile, FileFolderHistory *history) +{ + if (sfile->folders_prev == &history->folders_prev) { + sfile->folders_prev = NULL; + } + if (sfile->folders_next == &history->folders_next) { + sfile->folders_next = NULL; + } + folderlist_free(&history->folders_prev); + folderlist_free(&history->folders_next); + BLI_freelinkN(&sfile->folder_histories, history); +} + +void folder_history_list_free(SpaceFile *sfile) +{ + LISTBASE_FOREACH_MUTABLE (FileFolderHistory *, history, &sfile->folder_histories) { + folder_history_entry_free(sfile, history); + } +} + +ListBase folder_history_list_duplicate(ListBase *listbase) +{ + ListBase histories = {NULL}; + + LISTBASE_FOREACH (FileFolderHistory *, history, listbase) { + FileFolderHistory *history_new = static_cast<FileFolderHistory *>(MEM_dupallocN(history)); + history_new->folders_prev = folderlist_duplicate(&history->folders_prev); + history_new->folders_next = folderlist_duplicate(&history->folders_next); + BLI_addtail(&histories, history_new); + } + + return histories; +} + +/** \} */ diff --git a/source/blender/editors/space_file/fsmenu.c b/source/blender/editors/space_file/fsmenu.c index 310c688383b..35ce7ef364c 100644 --- a/source/blender/editors/space_file/fsmenu.c +++ b/source/blender/editors/space_file/fsmenu.c @@ -443,7 +443,7 @@ void fsmenu_insert_entry(struct FSMenu *fsmenu, if (STREQ(tfsm->path, fsm_iter->path)) { icon = tfsm->icon; if (tfsm->name[0] && (!name || !name[0])) { - name = tfsm->name; + name = DATA_(tfsm->name); } break; } @@ -519,7 +519,7 @@ void fsmenu_remove_entry(struct FSMenu *fsmenu, FSMenuCategory category, int idx } } -void fsmenu_write_file(struct FSMenu *fsmenu, const char *filepath) +bool fsmenu_write_file(struct FSMenu *fsmenu, const char *filepath) { FSMenuEntry *fsm_iter = NULL; char fsm_name[FILE_MAX]; @@ -527,33 +527,36 @@ void fsmenu_write_file(struct FSMenu *fsmenu, const char *filepath) FILE *fp = BLI_fopen(filepath, "w"); if (!fp) { - return; + return false; } - fprintf(fp, "[Bookmarks]\n"); + bool has_error = false; + has_error |= (fprintf(fp, "[Bookmarks]\n") < 0); for (fsm_iter = ED_fsmenu_get_category(fsmenu, FS_CATEGORY_BOOKMARKS); fsm_iter; fsm_iter = fsm_iter->next) { if (fsm_iter->path && fsm_iter->save) { fsmenu_entry_generate_name(fsm_iter, fsm_name, sizeof(fsm_name)); if (fsm_iter->name[0] && !STREQ(fsm_iter->name, fsm_name)) { - fprintf(fp, "!%s\n", fsm_iter->name); + has_error |= (fprintf(fp, "!%s\n", fsm_iter->name) < 0); } - fprintf(fp, "%s\n", fsm_iter->path); + has_error |= (fprintf(fp, "%s\n", fsm_iter->path) < 0); } } - fprintf(fp, "[Recent]\n"); + has_error = (fprintf(fp, "[Recent]\n") < 0); for (fsm_iter = ED_fsmenu_get_category(fsmenu, FS_CATEGORY_RECENT); fsm_iter && (nwritten < FSMENU_RECENT_MAX); fsm_iter = fsm_iter->next, nwritten++) { if (fsm_iter->path && fsm_iter->save) { fsmenu_entry_generate_name(fsm_iter, fsm_name, sizeof(fsm_name)); if (fsm_iter->name[0] && !STREQ(fsm_iter->name, fsm_name)) { - fprintf(fp, "!%s\n", fsm_iter->name); + has_error |= (fprintf(fp, "!%s\n", fsm_iter->name) < 0); } - fprintf(fp, "%s\n", fsm_iter->path); + has_error |= (fprintf(fp, "%s\n", fsm_iter->path) < 0); } } fclose(fp); + + return !has_error; } void fsmenu_read_bookmarks(struct FSMenu *fsmenu, const char *filepath) diff --git a/source/blender/editors/space_file/fsmenu.h b/source/blender/editors/space_file/fsmenu.h index 6e980a326fc..f4f0dafbc73 100644 --- a/source/blender/editors/space_file/fsmenu.h +++ b/source/blender/editors/space_file/fsmenu.h @@ -37,8 +37,11 @@ short fsmenu_can_save(struct FSMenu *fsmenu, enum FSMenuCategory category, int i /** Removes the fsmenu entry at the given \a index. */ void fsmenu_remove_entry(struct FSMenu *fsmenu, enum FSMenuCategory category, int idx); -/** saves the 'bookmarks' to the specified file */ -void fsmenu_write_file(struct FSMenu *fsmenu, const char *filepath); +/** + * Saves the 'bookmarks' to the specified file. + * \return true on success. + */ +bool fsmenu_write_file(struct FSMenu *fsmenu, const char *filepath); /** reads the 'bookmarks' from the specified file */ void fsmenu_read_bookmarks(struct FSMenu *fsmenu, const char *filepath); diff --git a/source/blender/editors/space_file/space_file.c b/source/blender/editors/space_file/space_file.c index a462476aae0..bba0c27bb4d 100644 --- a/source/blender/editors/space_file/space_file.c +++ b/source/blender/editors/space_file/space_file.c @@ -426,7 +426,7 @@ static void file_reset_filelist_showing_main_data(ScrArea *area, SpaceFile *sfil static void file_listener(const wmSpaceTypeListenerParams *listener_params) { ScrArea *area = listener_params->area; - wmNotifier *wmn = listener_params->notifier; + const wmNotifier *wmn = listener_params->notifier; SpaceFile *sfile = (SpaceFile *)area->spacedata.first; /* context changes */ @@ -514,7 +514,7 @@ static void file_main_region_init(wmWindowManager *wm, ARegion *region) static void file_main_region_listener(const wmRegionListenerParams *listener_params) { ARegion *region = listener_params->region; - wmNotifier *wmn = listener_params->notifier; + const wmNotifier *wmn = listener_params->notifier; /* context changes */ switch (wmn->category) { @@ -820,7 +820,7 @@ static void file_execution_region_draw(const bContext *C, ARegion *region) static void file_ui_region_listener(const wmRegionListenerParams *listener_params) { ARegion *region = listener_params->region; - wmNotifier *wmn = listener_params->notifier; + const wmNotifier *wmn = listener_params->notifier; /* context changes */ switch (wmn->category) { @@ -992,7 +992,7 @@ void ED_spacetype_file(void) ARegionType *art; st->spaceid = SPACE_FILE; - strncpy(st->name, "File", BKE_ST_MAXNAME); + STRNCPY(st->name, "File"); st->create = file_create; st->free = file_free; diff --git a/source/blender/editors/space_graph/CMakeLists.txt b/source/blender/editors/space_graph/CMakeLists.txt index ebcbf59be5f..39878debc39 100644 --- a/source/blender/editors/space_graph/CMakeLists.txt +++ b/source/blender/editors/space_graph/CMakeLists.txt @@ -10,7 +10,6 @@ set(INC ../../makesdna ../../makesrna ../../windowmanager - ../../../../intern/glew-mx ../../../../intern/guardedalloc # RNA_prototypes.h ${CMAKE_BINARY_DIR}/source/blender/makesrna diff --git a/source/blender/editors/space_graph/graph_buttons.c b/source/blender/editors/space_graph/graph_buttons.c index d41904d9790..edba3c39042 100644 --- a/source/blender/editors/space_graph/graph_buttons.c +++ b/source/blender/editors/space_graph/graph_buttons.c @@ -226,15 +226,15 @@ static void graph_panel_properties(const bContext *C, Panel *panel) /* color settings */ col = uiLayoutColumn(layout, true); - uiItemR(col, &fcu_ptr, "color_mode", 0, "Display Color", ICON_NONE); + uiItemR(col, &fcu_ptr, "color_mode", 0, IFACE_("Display Color"), ICON_NONE); if (fcu->color_mode == FCURVE_COLOR_CUSTOM) { - uiItemR(col, &fcu_ptr, "color", 0, "Color", ICON_NONE); + uiItemR(col, &fcu_ptr, "color", 0, IFACE_("Color"), ICON_NONE); } /* smoothing setting */ col = uiLayoutColumn(layout, true); - uiItemR(col, &fcu_ptr, "auto_smoothing", 0, "Handle Smoothing", ICON_NONE); + uiItemR(col, &fcu_ptr, "auto_smoothing", 0, IFACE_("Handle Smoothing"), ICON_NONE); MEM_freeN(ale); } @@ -641,7 +641,7 @@ static void do_graph_region_driver_buttons(bContext *C, void *id_v, int event) ID *id = id_v; AnimData *adt = BKE_animdata_from_id(id); - /* rebuild depsgraph for the new deps, and ensure COW copies get flushed. */ + /* Rebuild depsgraph for the new dependencies, and ensure COW copies get flushed. */ DEG_relations_tag_update(bmain); DEG_id_tag_update_ex(bmain, id, ID_RECALC_COPY_ON_WRITE); if (adt != NULL) { diff --git a/source/blender/editors/space_graph/graph_draw.c b/source/blender/editors/space_graph/graph_draw.c index 608a1f4d73e..41a8368152d 100644 --- a/source/blender/editors/space_graph/graph_draw.c +++ b/source/blender/editors/space_graph/graph_draw.c @@ -80,7 +80,7 @@ static void draw_fcurve_modifier_controls_envelope(FModifier *fcm, GPU_line_width(1.0f); - immBindBuiltinProgram(GPU_SHADER_2D_LINE_DASHED_UNIFORM_COLOR); + immBindBuiltinProgram(GPU_SHADER_3D_LINE_DASHED_UNIFORM_COLOR); float viewport_size[4]; GPU_viewport_size_get_f(viewport_size); @@ -107,7 +107,7 @@ static void draw_fcurve_modifier_controls_envelope(FModifier *fcm, /* set size of vertices (non-adjustable for now) */ GPU_point_size(2.0f); - immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); /* for now, point color is fixed, and is white */ immUniformColor3f(1.0f, 1.0f, 1.0f); @@ -408,7 +408,7 @@ static void draw_fcurve_handles(SpaceGraph *sipo, FCurve *fcu) uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); uint color = GPU_vertformat_attr_add( format, "color", GPU_COMP_U8, 4, GPU_FETCH_INT_TO_FLOAT_UNIT); - immBindBuiltinProgram(GPU_SHADER_2D_FLAT_COLOR); + immBindBuiltinProgram(GPU_SHADER_3D_FLAT_COLOR); if ((sipo->flag & SIPO_BEAUTYDRAW_OFF) == 0) { GPU_line_smooth(true); } @@ -540,7 +540,7 @@ static void draw_fcurve_samples(SpaceGraph *sipo, ARegion *region, FCurve *fcu) GPU_blend(GPU_BLEND_ALPHA); uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); - immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); immUniformThemeColor((fcu->flag & FCURVE_SELECTED) ? TH_TEXT_HI : TH_TEXT); @@ -1045,7 +1045,7 @@ static void draw_fcurve(bAnimContext *ac, SpaceGraph *sipo, ARegion *region, bAn if (BKE_fcurve_is_protected(fcu)) { /* Protected curves (non editable) are drawn with dotted lines. */ - immBindBuiltinProgram(GPU_SHADER_2D_LINE_DASHED_UNIFORM_COLOR); + immBindBuiltinProgram(GPU_SHADER_3D_LINE_DASHED_UNIFORM_COLOR); immUniform2f("viewport_size", viewport_size[2] / UI_DPI_FAC, viewport_size[3] / UI_DPI_FAC); immUniform1i("colors_len", 0); /* Simple dashes. */ immUniform1f("dash_width", 4.0f); @@ -1190,7 +1190,7 @@ static void graph_draw_driver_debug(bAnimContext *ac, ID *id, FCurve *fcu) const uint shdr_pos = GPU_vertformat_attr_add( immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); - immBindBuiltinProgram(GPU_SHADER_2D_LINE_DASHED_UNIFORM_COLOR); + immBindBuiltinProgram(GPU_SHADER_3D_LINE_DASHED_UNIFORM_COLOR); float viewport_size[4]; GPU_viewport_size_get_f(viewport_size); @@ -1268,7 +1268,7 @@ static void graph_draw_driver_debug(bAnimContext *ac, ID *id, FCurve *fcu) immUnbindProgram(); /* GPU_PRIM_POINTS do not survive dashed line geometry shader... */ - immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); /* x marks the spot .................................................... */ /* -> outer frame */ @@ -1310,7 +1310,7 @@ void graph_draw_ghost_curves(bAnimContext *ac, SpaceGraph *sipo, ARegion *region const uint shdr_pos = GPU_vertformat_attr_add( immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); - immBindBuiltinProgram(GPU_SHADER_2D_LINE_DASHED_UNIFORM_COLOR); + immBindBuiltinProgram(GPU_SHADER_3D_LINE_DASHED_UNIFORM_COLOR); float viewport_size[4]; GPU_viewport_size_get_f(viewport_size); diff --git a/source/blender/editors/space_graph/graph_edit.c b/source/blender/editors/space_graph/graph_edit.c index 64a3c603e73..cab491fb8d2 100644 --- a/source/blender/editors/space_graph/graph_edit.c +++ b/source/blender/editors/space_graph/graph_edit.c @@ -1448,7 +1448,7 @@ static int graphkeys_expo_exec(bContext *C, wmOperator *op) void GRAPH_OT_extrapolation_type(wmOperatorType *ot) { /* Identifiers */ - ot->name = "Set Keyframe Extrapolation"; + ot->name = "Set F-Curve Extrapolation"; ot->idname = "GRAPH_OT_extrapolation_type"; ot->description = "Set extrapolation mode for selected F-Curves"; @@ -3020,7 +3020,7 @@ static int graph_driver_vars_paste_exec(bContext *C, wmOperator *op) /* Successful or not? */ if (ok) { - /* Rebuild depsgraph, now that there are extra deps here. */ + /* Rebuild depsgraph, now that there are extra dependencies here. */ DEG_relations_tag_update(CTX_data_main(C)); /* Set notifier that keyframes have changed. */ diff --git a/source/blender/editors/space_graph/graph_select.c b/source/blender/editors/space_graph/graph_select.c index 0ce3e1a797a..932ed417f21 100644 --- a/source/blender/editors/space_graph/graph_select.c +++ b/source/blender/editors/space_graph/graph_select.c @@ -585,7 +585,7 @@ static bool box_select_graphkeys(bAnimContext *ac, initialize_box_select_key_editing_data( sipo, incl_handles, mode, ac, data, &scaled_rectf, &ked, &mapping_flag); - /* Get beztriple editing/validation funcs. */ + /* Get beztriple editing/validation functions. */ const KeyframeEditFunc select_cb = ANIM_editkeyframes_select(selectmode); const KeyframeEditFunc ok_cb = ANIM_editkeyframes_ok(mode); @@ -893,7 +893,7 @@ void GRAPH_OT_select_box(wmOperatorType *ot) ot->poll = graphop_visible_keyframes_poll; /* Flags. */ - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + ot->flag = OPTYPE_UNDO; /* Properties. */ ot->prop = RNA_def_boolean(ot->srna, "axis_range", 0, "Axis Range", ""); @@ -1145,7 +1145,7 @@ static void markers_selectkeys_between(bAnimContext *ac) min -= 0.5f; max += 0.5f; - /* get editing funcs + data */ + /* Get editing functions + data. */ ok_cb = ANIM_editkeyframes_ok(BEZT_OK_FRAMERANGE); select_cb = ANIM_editkeyframes_select(SELECT_ADD); @@ -1295,6 +1295,7 @@ void GRAPH_OT_select_column(wmOperatorType *ot) /* props */ ot->prop = RNA_def_enum(ot->srna, "mode", prop_column_select_types, 0, "Mode", ""); + RNA_def_property_flag(ot->prop, PROP_HIDDEN); } /** \} */ diff --git a/source/blender/editors/space_graph/space_graph.c b/source/blender/editors/space_graph/space_graph.c index ea2e2e44b90..1434f204ee5 100644 --- a/source/blender/editors/space_graph/space_graph.c +++ b/source/blender/editors/space_graph/space_graph.c @@ -224,7 +224,7 @@ static void graph_main_region_draw(const bContext *C, ARegion *region) if (((sipo->flag & SIPO_NODRAWCURSOR) == 0)) { uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); - immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); /* horizontal component of value-cursor (value line before the current frame line) */ float y = sipo->cursorVal; @@ -393,7 +393,7 @@ static void graph_buttons_region_draw(const bContext *C, ARegion *region) static void graph_region_listener(const wmRegionListenerParams *params) { ARegion *region = params->region; - wmNotifier *wmn = params->notifier; + const wmNotifier *wmn = params->notifier; /* context changes */ switch (wmn->category) { @@ -529,7 +529,7 @@ static void graph_region_message_subscribe(const wmRegionMessageSubscribeParams static void graph_listener(const wmSpaceTypeListenerParams *params) { ScrArea *area = params->area; - wmNotifier *wmn = params->notifier; + const wmNotifier *wmn = params->notifier; SpaceGraph *sipo = (SpaceGraph *)area->spacedata.first; /* context changes */ @@ -810,7 +810,7 @@ void ED_spacetype_ipo(void) ARegionType *art; st->spaceid = SPACE_GRAPH; - strncpy(st->name, "Graph", BKE_ST_MAXNAME); + STRNCPY(st->name, "Graph"); st->create = graph_create; st->free = graph_free; diff --git a/source/blender/editors/space_image/CMakeLists.txt b/source/blender/editors/space_image/CMakeLists.txt index c6a1a6a77b4..4284d0f76af 100644 --- a/source/blender/editors/space_image/CMakeLists.txt +++ b/source/blender/editors/space_image/CMakeLists.txt @@ -16,7 +16,6 @@ set(INC ../../render ../../windowmanager ../../../../intern/clog - ../../../../intern/glew-mx ../../../../intern/guardedalloc # RNA_prototypes.h ${CMAKE_BINARY_DIR}/source/blender/makesrna diff --git a/source/blender/editors/space_image/image_buttons.c b/source/blender/editors/space_image/image_buttons.c index 2109d3f9701..bc367a99d6b 100644 --- a/source/blender/editors/space_image/image_buttons.c +++ b/source/blender/editors/space_image/image_buttons.c @@ -922,7 +922,7 @@ void uiTemplateImage(uiLayout *layout, } } - /* Colorspace and alpha */ + /* Color-space and alpha. */ { uiItemS(layout); @@ -1212,8 +1212,8 @@ void uiTemplateImageInfo(uiLayout *layout, bContext *C, Image *ima, ImageUser *i ofs += BLI_strncpy_rlen(str + ofs, TIP_(" + Z"), len - ofs); } - eGPUTextureFormat texture_format = IMB_gpu_get_texture_format(ibuf, - ima->flag & IMA_HIGH_BITDEPTH); + eGPUTextureFormat texture_format = IMB_gpu_get_texture_format( + ibuf, ima->flag & IMA_HIGH_BITDEPTH, ibuf->planes >= 8); const char *texture_format_description = GPU_texture_format_description(texture_format); ofs += BLI_snprintf_rlen(str + ofs, len - ofs, TIP_(", %s"), texture_format_description); diff --git a/source/blender/editors/space_image/image_draw.c b/source/blender/editors/space_image/image_draw.c index f6f9428213f..8a934396229 100644 --- a/source/blender/editors/space_image/image_draw.c +++ b/source/blender/editors/space_image/image_draw.c @@ -98,7 +98,7 @@ static void draw_render_info( uint pos = GPU_vertformat_attr_add( immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); - immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); immUniformThemeColor(TH_FACE_SELECT); GPU_line_width(1.0f); @@ -158,7 +158,7 @@ void ED_image_draw_info(Scene *scene, uint pos = GPU_vertformat_attr_add( immVertexFormat(), "pos", GPU_COMP_I32, 2, GPU_FETCH_INT_TO_FLOAT); - immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); /* noisy, high contrast make impossible to read if lower alpha is used. */ immUniformColor4ub(0, 0, 0, 190); @@ -338,7 +338,7 @@ void ED_image_draw_info(Scene *scene, /* BLF uses immediate mode too, so we must reset our vertex format */ pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_I32, 2, GPU_FETCH_INT_TO_FLOAT); - immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); if (channels == 4) { rcti color_rect_half; @@ -381,7 +381,7 @@ void ED_image_draw_info(Scene *scene, /* draw outline */ pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); - immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); immUniformColor3ub(128, 128, 128); imm_draw_box_wire_2d(pos, color_rect.xmin, color_rect.ymin, color_rect.xmax, color_rect.ymax); immUnbindProgram(); @@ -448,7 +448,7 @@ void draw_image_sample_line(SpaceImage *sima) uint shdr_dashed_pos = GPU_vertformat_attr_add( format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); - immBindBuiltinProgram(GPU_SHADER_2D_LINE_DASHED_UNIFORM_COLOR); + immBindBuiltinProgram(GPU_SHADER_3D_LINE_DASHED_UNIFORM_COLOR); float viewport_size[4]; GPU_viewport_size_get_f(viewport_size); @@ -557,7 +557,7 @@ void draw_image_cache(const bContext *C, ARegion *region) uint pos = GPU_vertformat_attr_add( immVertexFormat(), "pos", GPU_COMP_I32, 2, GPU_FETCH_INT_TO_FLOAT); - immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); immUniformThemeColor(TH_CFRAME); immRecti(pos, x, region_bottom, x + ceilf(framelen), region_bottom + 8 * UI_DPI_FAC); immUnbindProgram(); @@ -585,34 +585,35 @@ float ED_space_image_zoom_level(const View2D *v2d, const int grid_dimension) } void ED_space_image_grid_steps(SpaceImage *sima, - float grid_steps[SI_GRID_STEPS_LEN], + float grid_steps_x[SI_GRID_STEPS_LEN], + float grid_steps_y[SI_GRID_STEPS_LEN], const int grid_dimension) { - if (sima->flag & SI_CUSTOM_GRID) { - for (int step = 0; step < SI_GRID_STEPS_LEN; step++) { - grid_steps[step] = powf(1, step) * (1.0f / ((float)sima->custom_grid_subdiv)); + const int flag = sima->flag; + for (int step = 0; step < SI_GRID_STEPS_LEN; step++) { + if (flag & SI_CUSTOM_GRID) { + grid_steps_x[step] = 1.0f / sima->custom_grid_subdiv[0]; + grid_steps_y[step] = 1.0f / sima->custom_grid_subdiv[1]; } - } - else { - for (int step = 0; step < SI_GRID_STEPS_LEN; step++) { - grid_steps[step] = powf(grid_dimension, step) * - (1.0f / (powf(grid_dimension, SI_GRID_STEPS_LEN))); + else { + grid_steps_x[step] = powf(grid_dimension, step - SI_GRID_STEPS_LEN); + grid_steps_y[step] = powf(grid_dimension, step - SI_GRID_STEPS_LEN); } } } -float ED_space_image_increment_snap_value(const int grid_dimesnions, +float ED_space_image_increment_snap_value(const int grid_dimensions, const float grid_steps[SI_GRID_STEPS_LEN], const float zoom_factor) { /* Small offset on each grid_steps[] so that snapping value doesn't change until grid lines are * significantly visible. - * `Offset = 3/4 * (grid_steps[i] - (grid_steps[i] / grid_dimesnsions))` + * `Offset = 3/4 * (grid_steps[i] - (grid_steps[i] / grid_dimensions))` * * Refer `grid_frag.glsl` to find out when grid lines actually start appearing */ for (int step = 0; step < SI_GRID_STEPS_LEN; step++) { - float offset = (3.0f / 4.0f) * (grid_steps[step] - (grid_steps[step] / grid_dimesnions)); + float offset = (3.0f / 4.0f) * (grid_steps[step] - (grid_steps[step] / grid_dimensions)); if ((grid_steps[step] - offset) > zoom_factor) { return grid_steps[step]; diff --git a/source/blender/editors/space_image/image_edit.c b/source/blender/editors/space_image/image_edit.c index 0de50474ab8..fa0fdb01bdf 100644 --- a/source/blender/editors/space_image/image_edit.c +++ b/source/blender/editors/space_image/image_edit.c @@ -18,6 +18,7 @@ #include "BKE_editmesh.h" #include "BKE_global.h" #include "BKE_image.h" +#include "BKE_layer.h" #include "BKE_lib_id.h" #include "BKE_main.h" #include "BKE_scene.h" @@ -470,8 +471,10 @@ bool ED_space_image_maskedit_poll(bContext *C) SpaceImage *sima = CTX_wm_space_image(C); if (sima) { + Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); - Object *obedit = OBEDIT_FROM_VIEW_LAYER(view_layer); + BKE_view_layer_synced_ensure(scene, view_layer); + Object *obedit = BKE_view_layer_edit_object_get(view_layer); return ED_space_image_check_show_maskedit(sima, obedit); } diff --git a/source/blender/editors/space_image/image_ops.c b/source/blender/editors/space_image/image_ops.c index 78aaf957a87..dec4055c737 100644 --- a/source/blender/editors/space_image/image_ops.c +++ b/source/blender/editors/space_image/image_ops.c @@ -941,7 +941,7 @@ static int image_view_selected_exec(bContext *C, wmOperator *UNUSED(op)) if (ED_space_image_show_uvedit(sima, obedit)) { uint objects_len = 0; Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data_with_uvs( - view_layer, ((View3D *)NULL), &objects_len); + scene, view_layer, ((View3D *)NULL), &objects_len); bool success = ED_uvedit_minmax_multi(scene, objects, objects_len, min, max); MEM_freeN(objects); if (!success) { diff --git a/source/blender/editors/space_image/image_undo.cc b/source/blender/editors/space_image/image_undo.cc index 065641c4051..8f144264824 100644 --- a/source/blender/editors/space_image/image_undo.cc +++ b/source/blender/editors/space_image/image_undo.cc @@ -522,7 +522,7 @@ static void ubuf_ensure_compat_ibuf(const UndoImageBuf *ubuf, ImBuf *ibuf) IMB_rect_size_set(ibuf, ubuf->image_dims); if (ubuf->image_state.use_float) { - imb_addrectfloatImBuf(ibuf); + imb_addrectfloatImBuf(ibuf, 4); } else { imb_addrectImBuf(ibuf); diff --git a/source/blender/editors/space_image/space_image.c b/source/blender/editors/space_image/space_image.c index 785a5419e04..2b65267644a 100644 --- a/source/blender/editors/space_image/space_image.c +++ b/source/blender/editors/space_image/space_image.c @@ -20,6 +20,7 @@ #include "BKE_colortools.h" #include "BKE_context.h" #include "BKE_image.h" +#include "BKE_layer.h" #include "BKE_lib_id.h" #include "BKE_lib_remap.h" #include "BKE_screen.h" @@ -111,7 +112,8 @@ static SpaceLink *image_create(const ScrArea *UNUSED(area), const Scene *UNUSED( simage->tile_grid_shape[0] = 1; simage->tile_grid_shape[1] = 1; - simage->custom_grid_subdiv = 10; + simage->custom_grid_subdiv[0] = 10; + simage->custom_grid_subdiv[1] = 10; /* header */ region = MEM_callocN(sizeof(ARegion), "header for image"); @@ -298,7 +300,7 @@ static void image_listener(const wmSpaceTypeListenerParams *params) { wmWindow *win = params->window; ScrArea *area = params->area; - wmNotifier *wmn = params->notifier; + const wmNotifier *wmn = params->notifier; SpaceImage *sima = (SpaceImage *)area->spacedata.first; /* context changes */ @@ -350,8 +352,10 @@ static void image_listener(const wmSpaceTypeListenerParams *params) } break; case NC_MASK: { + Scene *scene = WM_window_get_active_scene(win); ViewLayer *view_layer = WM_window_get_active_view_layer(win); - Object *obedit = OBEDIT_FROM_VIEW_LAYER(view_layer); + BKE_view_layer_synced_ensure(scene, view_layer); + Object *obedit = BKE_view_layer_edit_object_get(view_layer); if (ED_space_image_check_show_maskedit(sima, obedit)) { switch (wmn->data) { case ND_SELECT: @@ -392,8 +396,10 @@ static void image_listener(const wmSpaceTypeListenerParams *params) switch (wmn->data) { case ND_TRANSFORM: case ND_MODIFIER: { + const Scene *scene = WM_window_get_active_scene(win); ViewLayer *view_layer = WM_window_get_active_view_layer(win); - Object *ob = OBACT(view_layer); + BKE_view_layer_synced_ensure(scene, view_layer); + Object *ob = BKE_view_layer_active_object_get(view_layer); if (ob && (ob == wmn->reference) && (ob->mode & OB_MODE_EDIT)) { if (sima->lock && (sima->flag & SI_DRAWSHADOW)) { ED_area_tag_refresh(area); @@ -713,7 +719,7 @@ static void image_main_region_listener(const wmRegionListenerParams *params) { ScrArea *area = params->area; ARegion *region = params->region; - wmNotifier *wmn = params->notifier; + const wmNotifier *wmn = params->notifier; /* context changes */ switch (wmn->category) { @@ -827,7 +833,7 @@ static void image_buttons_region_draw(const bContext *C, ARegion *region) static void image_buttons_region_listener(const wmRegionListenerParams *params) { ARegion *region = params->region; - wmNotifier *wmn = params->notifier; + const wmNotifier *wmn = params->notifier; /* context changes */ switch (wmn->category) { @@ -889,7 +895,7 @@ static void image_tools_region_draw(const bContext *C, ARegion *region) static void image_tools_region_listener(const wmRegionListenerParams *params) { ARegion *region = params->region; - wmNotifier *wmn = params->notifier; + const wmNotifier *wmn = params->notifier; /* context changes */ switch (wmn->category) { @@ -945,7 +951,7 @@ static void image_header_region_draw(const bContext *C, ARegion *region) static void image_header_region_listener(const wmRegionListenerParams *params) { ARegion *region = params->region; - wmNotifier *wmn = params->notifier; + const wmNotifier *wmn = params->notifier; /* context changes */ switch (wmn->category) { @@ -1028,7 +1034,7 @@ void ED_spacetype_image(void) ARegionType *art; st->spaceid = SPACE_IMAGE; - strncpy(st->name, "Image", BKE_ST_MAXNAME); + STRNCPY(st->name, "Image"); st->create = image_create; st->free = image_free; diff --git a/source/blender/editors/space_info/CMakeLists.txt b/source/blender/editors/space_info/CMakeLists.txt index febb025f5bd..4e9df2b93b0 100644 --- a/source/blender/editors/space_info/CMakeLists.txt +++ b/source/blender/editors/space_info/CMakeLists.txt @@ -14,7 +14,6 @@ set(INC ../../makesdna ../../makesrna ../../windowmanager - ../../../../intern/glew-mx ../../../../intern/guardedalloc # RNA_prototypes.h ${CMAKE_BINARY_DIR}/source/blender/makesrna diff --git a/source/blender/editors/space_info/info_stats.cc b/source/blender/editors/space_info/info_stats.cc index e41ff02254b..0aa35069c1e 100644 --- a/source/blender/editors/space_info/info_stats.cc +++ b/source/blender/editors/space_info/info_stats.cc @@ -130,7 +130,7 @@ static void stats_object(Object *ob, SceneStats *stats, GSet *objects_gset) { - if ((ob->base_flag & BASE_VISIBLE_VIEWLAYER) == 0) { + if ((ob->base_flag & BASE_ENABLED_AND_VISIBLE_IN_DEFAULT_VIEWPORT) == 0) { return; } @@ -161,42 +161,6 @@ static void stats_object(Object *ob, stats->totlampsel++; } break; - case OB_SURF: - case OB_CURVES_LEGACY: - case OB_FONT: { - const Mesh *me_eval = BKE_object_get_evaluated_mesh(ob); - if ((me_eval != nullptr) && !BLI_gset_add(objects_gset, (void *)me_eval)) { - break; - } - - if (stats_mesheval(me_eval, is_selected, stats)) { - break; - } - ATTR_FALLTHROUGH; /* Fall-through to displist. */ - } - case OB_MBALL: { - int totv = 0, totf = 0, tottri = 0; - - if (ob->runtime.curve_cache && ob->runtime.curve_cache->disp.first) { - /* NOTE: We only get the same curve_cache for instances of the same curve/font/... - * For simple linked duplicated objects, each has its own dispList. */ - if (!BLI_gset_add(objects_gset, ob->runtime.curve_cache)) { - break; - } - - BKE_displist_count(&ob->runtime.curve_cache->disp, &totv, &totf, &tottri); - } - - stats->totvert += totv; - stats->totface += totf; - stats->tottri += tottri; - - if (is_selected) { - stats->totvertsel += totv; - stats->totfacesel += totf; - } - break; - } case OB_GPENCIL: { if (is_selected) { bGPdata *gpd = (bGPdata *)ob->data; @@ -381,7 +345,7 @@ static void stats_object_sculpt(const Object *ob, SceneStats *stats) stats->tottri = ob->sculpt->bm->totface; break; case PBVH_GRIDS: - stats->totvertsculpt = BKE_pbvh_get_grid_num_vertices(ss->pbvh); + stats->totvertsculpt = BKE_pbvh_get_grid_num_verts(ss->pbvh); stats->totfacesculpt = BKE_pbvh_get_grid_num_faces(ss->pbvh); break; } @@ -389,19 +353,21 @@ static void stats_object_sculpt(const Object *ob, SceneStats *stats) /* Statistics displayed in info header. Called regularly on scene changes. */ static void stats_update(Depsgraph *depsgraph, + const Scene *scene, ViewLayer *view_layer, View3D *v3d_local, SceneStats *stats) { - const Object *ob = OBACT(view_layer); - const Object *obedit = OBEDIT_FROM_VIEW_LAYER(view_layer); + BKE_view_layer_synced_ensure(scene, view_layer); + const Object *ob = BKE_view_layer_active_object_get(view_layer); + const Object *obedit = BKE_view_layer_edit_object_get(view_layer); memset(stats, 0x0, sizeof(*stats)); if (obedit) { /* Edit Mode. */ - FOREACH_OBJECT_BEGIN (view_layer, ob_iter) { - if (ob_iter->base_flag & BASE_VISIBLE_VIEWLAYER) { + FOREACH_OBJECT_BEGIN (scene, view_layer, ob_iter) { + if (ob_iter->base_flag & BASE_ENABLED_AND_VISIBLE_IN_DEFAULT_VIEWPORT) { if (ob_iter->mode & OB_MODE_EDIT) { stats_object_edit(ob_iter, stats); stats->totobjsel++; @@ -420,8 +386,8 @@ static void stats_update(Depsgraph *depsgraph, } else if (ob && (ob->mode & OB_MODE_POSE)) { /* Pose Mode. */ - FOREACH_OBJECT_BEGIN (view_layer, ob_iter) { - if (ob_iter->base_flag & BASE_VISIBLE_VIEWLAYER) { + FOREACH_OBJECT_BEGIN (scene, view_layer, ob_iter) { + if (ob_iter->base_flag & BASE_ENABLED_AND_VISIBLE_IN_DEFAULT_VIEWPORT) { if (ob_iter->mode & OB_MODE_POSE) { stats_object_pose(ob_iter, stats); stats->totobjsel++; @@ -444,10 +410,13 @@ static void stats_update(Depsgraph *depsgraph, else { /* Objects. */ GSet *objects_gset = BLI_gset_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp, __func__); - DEG_OBJECT_ITER_FOR_RENDER_ENGINE_BEGIN (depsgraph, ob_iter) { + DEGObjectIterSettings deg_iter_settings = {0}; + deg_iter_settings.depsgraph = depsgraph; + deg_iter_settings.flags = DEG_OBJECT_ITER_FOR_RENDER_ENGINE_FLAGS; + DEG_OBJECT_ITER_BEGIN (°_iter_settings, ob_iter) { stats_object(ob_iter, v3d_local, stats, objects_gset); } - DEG_OBJECT_ITER_FOR_RENDER_ENGINE_END; + DEG_OBJECT_ITER_END; BLI_gset_free(objects_gset, nullptr); } } @@ -486,7 +455,7 @@ static bool format_stats( } Depsgraph *depsgraph = BKE_scene_ensure_depsgraph(bmain, scene, view_layer); *stats_p = (SceneStats *)MEM_mallocN(sizeof(SceneStats), __func__); - stats_update(depsgraph, view_layer, v3d_local, *stats_p); + stats_update(depsgraph, scene, view_layer, v3d_local, *stats_p); } SceneStats *stats = *stats_p; @@ -525,13 +494,18 @@ static bool format_stats( return true; } -static void get_stats_string( - char *info, int len, size_t *ofs, ViewLayer *view_layer, SceneStatsFmt *stats_fmt) +static void get_stats_string(char *info, + int len, + size_t *ofs, + const Scene *scene, + ViewLayer *view_layer, + SceneStatsFmt *stats_fmt) { - Object *ob = OBACT(view_layer); + BKE_view_layer_synced_ensure(scene, view_layer); + Object *ob = BKE_view_layer_active_object_get(view_layer); Object *obedit = OBEDIT_FROM_OBACT(ob); eObjectMode object_mode = ob ? (eObjectMode)ob->mode : OB_MODE_OBJECT; - LayerCollection *layer_collection = view_layer->active_collection; + LayerCollection *layer_collection = BKE_view_layer_active_collection_get(view_layer); if (object_mode == OB_MODE_OBJECT) { *ofs += BLI_snprintf_rlen(info + *ofs, @@ -635,7 +609,7 @@ static const char *info_statusbar_string(Main *bmain, if (statusbar_flag & STATUSBAR_SHOW_STATS) { SceneStatsFmt stats_fmt; if (format_stats(bmain, scene, view_layer, nullptr, &stats_fmt)) { - get_stats_string(info + ofs, len, &ofs, view_layer, &stats_fmt); + get_stats_string(info + ofs, len, &ofs, scene, view_layer, &stats_fmt); } } @@ -720,7 +694,8 @@ void ED_info_draw_stats( return; } - Object *ob = OBACT(view_layer); + BKE_view_layer_synced_ensure(scene, view_layer); + Object *ob = BKE_view_layer_active_object_get(view_layer); Object *obedit = OBEDIT_FROM_OBACT(ob); eObjectMode object_mode = ob ? (eObjectMode)ob->mode : OB_MODE_OBJECT; const int font_id = BLF_set_default(); diff --git a/source/blender/editors/space_info/space_info.c b/source/blender/editors/space_info/space_info.c index 73d81c93981..63c8d74c684 100644 --- a/source/blender/editors/space_info/space_info.c +++ b/source/blender/editors/space_info/space_info.c @@ -186,7 +186,7 @@ static void info_header_region_draw(const bContext *C, ARegion *region) static void info_main_region_listener(const wmRegionListenerParams *params) { ARegion *region = params->region; - wmNotifier *wmn = params->notifier; + const wmNotifier *wmn = params->notifier; /* context changes */ switch (wmn->category) { @@ -202,7 +202,7 @@ static void info_main_region_listener(const wmRegionListenerParams *params) static void info_header_listener(const wmRegionListenerParams *params) { ARegion *region = params->region; - wmNotifier *wmn = params->notifier; + const wmNotifier *wmn = params->notifier; /* context changes */ switch (wmn->category) { @@ -254,7 +254,7 @@ void ED_spacetype_info(void) ARegionType *art; st->spaceid = SPACE_INFO; - strncpy(st->name, "Info", BKE_ST_MAXNAME); + STRNCPY(st->name, "Info"); st->create = info_create; st->free = info_free; diff --git a/source/blender/editors/space_info/textview.c b/source/blender/editors/space_info/textview.c index bc2b539474c..9aa2b84169e 100644 --- a/source/blender/editors/space_info/textview.c +++ b/source/blender/editors/space_info/textview.c @@ -74,7 +74,7 @@ static void textview_draw_sel(const char *str, GPUVertFormat *format = immVertexFormat(); uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_I32, 2, GPU_FETCH_INT_TO_FLOAT); - immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); immUniformColor4ubv(bg_sel); immRecti(pos, xy[0] + (cwidth * sta), xy[1] + lheight, xy[0] + (cwidth * end), xy[1]); @@ -197,7 +197,7 @@ static bool textview_draw_string(TextViewDrawState *tds, if (bg) { GPUVertFormat *format = immVertexFormat(); uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_I32, 2, GPU_FETCH_INT_TO_FLOAT); - immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); immUniformColor4ubv(bg); immRecti(pos, tds->draw_rect_outer->xmin, line_bottom, tds->draw_rect_outer->xmax, line_top); immUnbindProgram(); diff --git a/source/blender/editors/space_nla/CMakeLists.txt b/source/blender/editors/space_nla/CMakeLists.txt index 85a2c3fd0a1..e6995085dbe 100644 --- a/source/blender/editors/space_nla/CMakeLists.txt +++ b/source/blender/editors/space_nla/CMakeLists.txt @@ -10,7 +10,6 @@ set(INC ../../makesdna ../../makesrna ../../windowmanager - ../../../../intern/glew-mx ../../../../intern/guardedalloc # RNA_prototypes.h ${CMAKE_BINARY_DIR}/source/blender/makesrna diff --git a/source/blender/editors/space_nla/nla_buttons.c b/source/blender/editors/space_nla/nla_buttons.c index 9652819404e..a46da391bdc 100644 --- a/source/blender/editors/space_nla/nla_buttons.c +++ b/source/blender/editors/space_nla/nla_buttons.c @@ -213,7 +213,9 @@ static bool nla_panel_poll(const bContext *C, PanelType *pt) static bool nla_animdata_panel_poll(const bContext *C, PanelType *UNUSED(pt)) { PointerRNA ptr; - return (nla_panel_context(C, &ptr, NULL, NULL) && (ptr.data != NULL)); + PointerRNA strip_ptr; + return (nla_panel_context(C, &ptr, NULL, &strip_ptr) && (ptr.data != NULL) && + (ptr.owner_id != strip_ptr.owner_id)); } static bool nla_strip_panel_poll(const bContext *C, PanelType *UNUSED(pt)) @@ -265,13 +267,18 @@ static bool nla_strip_eval_panel_poll(const bContext *C, PanelType *UNUSED(pt)) static void nla_panel_animdata(const bContext *C, Panel *panel) { PointerRNA adt_ptr; + PointerRNA strip_ptr; /* AnimData *adt; */ uiLayout *layout = panel->layout; uiLayout *row; uiBlock *block; /* check context and also validity of pointer */ - if (!nla_panel_context(C, &adt_ptr, NULL, NULL)) { + if (!nla_panel_context(C, &adt_ptr, NULL, &strip_ptr)) { + return; + } + + if (adt_ptr.owner_id == strip_ptr.owner_id) { return; } diff --git a/source/blender/editors/space_nla/nla_channels.c b/source/blender/editors/space_nla/nla_channels.c index a0c6a29c422..3c0238806bf 100644 --- a/source/blender/editors/space_nla/nla_channels.c +++ b/source/blender/editors/space_nla/nla_channels.c @@ -20,6 +20,7 @@ #include "BKE_anim_data.h" #include "BKE_context.h" #include "BKE_global.h" +#include "BKE_layer.h" #include "BKE_nla.h" #include "BKE_report.h" #include "BKE_scene.h" @@ -129,7 +130,8 @@ static int mouse_nla_channels(bContext *C, bAnimContext *ac, int channel_index, else { /* deselect all */ /* TODO: should this deselect all other types of channels too? */ - LISTBASE_FOREACH (Base *, b, &view_layer->object_bases) { + BKE_view_layer_synced_ensure(ac->scene, view_layer); + LISTBASE_FOREACH (Base *, b, BKE_view_layer_object_bases_get(view_layer)) { ED_object_base_select(b, BA_DESELECT); if (b->object->adt) { b->object->adt->flag &= ~(ADT_UI_SELECTED | ADT_UI_ACTIVE); @@ -478,7 +480,7 @@ void NLA_OT_action_pushdown(wmOperatorType *ot) "Index of NLA action channel to perform pushdown operation on", 0, INT_MAX); - RNA_def_property_flag(ot->prop, PROP_SKIP_SAVE); + RNA_def_property_flag(ot->prop, PROP_SKIP_SAVE | PROP_HIDDEN); } /* ******************** Action Unlink ******************************** */ diff --git a/source/blender/editors/space_nla/nla_draw.c b/source/blender/editors/space_nla/nla_draw.c index 3b108a3ba8a..f57c9fead56 100644 --- a/source/blender/editors/space_nla/nla_draw.c +++ b/source/blender/editors/space_nla/nla_draw.c @@ -22,6 +22,7 @@ #include "BLI_range.h" #include "BLI_utildefines.h" +#include "BKE_action.h" #include "BKE_context.h" #include "BKE_fcurve.h" #include "BKE_nla.h" @@ -101,7 +102,7 @@ static void nla_action_draw_keyframes( GPUVertFormat *format = immVertexFormat(); uint pos_id = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); - immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); immUniformColor4fv(color); @@ -178,7 +179,7 @@ static void nla_actionclip_draw_markers( const uint shdr_pos = GPU_vertformat_attr_add( immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); if (dashed) { - immBindBuiltinProgram(GPU_SHADER_2D_LINE_DASHED_UNIFORM_COLOR); + immBindBuiltinProgram(GPU_SHADER_3D_LINE_DASHED_UNIFORM_COLOR); float viewport_size[4]; GPU_viewport_size_get_f(viewport_size); @@ -189,7 +190,7 @@ static void nla_actionclip_draw_markers( immUniform1f("dash_factor", 0.5f); } else { - immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); } immUniformThemeColorShade(TH_STRIP_SELECT, shade); @@ -377,7 +378,7 @@ static uint nla_draw_use_dashed_outlines(const float color[4], bool muted) /* Note that we use dashed shader here, and make it draw solid lines if not muted... */ uint shdr_pos = GPU_vertformat_attr_add( immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); - immBindBuiltinProgram(GPU_SHADER_2D_LINE_DASHED_UNIFORM_COLOR); + immBindBuiltinProgram(GPU_SHADER_3D_LINE_DASHED_UNIFORM_COLOR); float viewport_size[4]; GPU_viewport_size_get_f(viewport_size); @@ -441,7 +442,7 @@ static void nla_draw_strip(SpaceNla *snla, nla_strip_get_color_inside(adt, strip, color); shdr_pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); - immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); /* draw extrapolation info first (as backdrop) * - but this should only be drawn if track has some contribution @@ -502,7 +503,7 @@ static void nla_draw_strip(SpaceNla *snla, /* restore current vertex format & program (roundbox trashes it) */ shdr_pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); - immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); } else { /* strip is in disabled track - make less visible */ @@ -854,10 +855,11 @@ void draw_nla_main_data(bAnimContext *ac, SpaceNla *snla, ARegion *region) uint pos = GPU_vertformat_attr_add( immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); - immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); - /* just draw a semi-shaded rect spanning the width of the viewable area if there's data, - * and a second darker rect within which we draw keyframe indicator dots if there's data + /* just draw a semi-shaded rect spanning the width of the viewable area, based on if + * there's data and the action's extrapolation mode. Draw a second darker rect within + * which we draw keyframe indicator dots if there's data. */ GPU_blend(GPU_BLEND_ALPHA); @@ -869,8 +871,26 @@ void draw_nla_main_data(bAnimContext *ac, SpaceNla *snla, ARegion *region) /* draw slightly shifted up for greater separation from standard channels, * but also slightly shorter for some more contrast when viewing the strips */ - immRectf( - pos, v2d->cur.xmin, ymin + NLACHANNEL_SKIP, v2d->cur.xmax, ymax - NLACHANNEL_SKIP); + switch (adt->act_extendmode) { + case NLASTRIP_EXTEND_HOLD: { + immRectf(pos, + v2d->cur.xmin, + ymin + NLACHANNEL_SKIP, + v2d->cur.xmax, + ymax - NLACHANNEL_SKIP); + break; + } + case NLASTRIP_EXTEND_HOLD_FORWARD: { + float r_start; + float r_end; + BKE_action_get_frame_range(ale->data, &r_start, &r_end); + + immRectf(pos, r_end, ymin + NLACHANNEL_SKIP, v2d->cur.xmax, ymax - NLACHANNEL_SKIP); + break; + } + case NLASTRIP_EXTEND_NOTHING: + break; + } immUnbindProgram(); diff --git a/source/blender/editors/space_nla/nla_edit.c b/source/blender/editors/space_nla/nla_edit.c index 801d032a861..9df25b1229e 100644 --- a/source/blender/editors/space_nla/nla_edit.c +++ b/source/blender/editors/space_nla/nla_edit.c @@ -606,6 +606,36 @@ void NLA_OT_view_frame(wmOperatorType *ot) * (or the active block if no space in the track). * \{ */ +/* Get a list of the editable tracks being shown in the NLA. */ +static int nlaedit_get_editable_tracks(bAnimContext *ac, ListBase *anim_data) +{ + const int filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_ACTIVE | ANIMFILTER_FOREDIT | + ANIMFILTER_FCURVESONLY); + return ANIM_animdata_filter(ac, anim_data, filter, ac->data, ac->datatype); +} + +static int nlaedit_add_actionclip_invoke(bContext *C, wmOperator *op, const wmEvent *event) +{ + /* Get editor data. */ + bAnimContext ac; + if (ANIM_animdata_get_context(C, &ac) == 0) { + return OPERATOR_CANCELLED; + } + + ListBase anim_data = {NULL, NULL}; + const size_t items = nlaedit_get_editable_tracks(&ac, &anim_data); + + if (items == 0) { + BKE_report(op->reports, + RPT_ERROR, + "No active track(s) to add strip to, select an existing track or add one before " + "trying again"); + return OPERATOR_CANCELLED; + } + + return WM_enum_search_invoke(C, op, event); +} + /* add the specified action as new strip */ static int nlaedit_add_actionclip_exec(bContext *C, wmOperator *op) { @@ -615,8 +645,6 @@ static int nlaedit_add_actionclip_exec(bContext *C, wmOperator *op) ListBase anim_data = {NULL, NULL}; bAnimListElem *ale; - size_t items; - int filter; bAction *act; @@ -654,20 +682,7 @@ static int nlaedit_add_actionclip_exec(bContext *C, wmOperator *op) */ nlaedit_add_tracks_empty(&ac); - /* get a list of the editable tracks being shown in the NLA - * - this is limited to active ones for now, but could be expanded to - */ - filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_ACTIVE | ANIMFILTER_FOREDIT | - ANIMFILTER_FCURVESONLY); - items = ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype); - - if (items == 0) { - BKE_report(op->reports, - RPT_ERROR, - "No active track(s) to add strip to, select an existing track or add one before " - "trying again"); - return OPERATOR_CANCELLED; - } + nlaedit_get_editable_tracks(&ac, &anim_data); /* for every active track, * try to add strip to free space in track or to the top of the stack if no space */ @@ -736,7 +751,7 @@ void NLA_OT_actionclip_add(wmOperatorType *ot) "Add an Action-Clip strip (i.e. an NLA Strip referencing an Action) to the active track"; /* api callbacks */ - ot->invoke = WM_enum_search_invoke; + ot->invoke = nlaedit_add_actionclip_invoke; ot->exec = nlaedit_add_actionclip_exec; ot->poll = nlaop_poll_tweakmode_off; diff --git a/source/blender/editors/space_nla/nla_select.c b/source/blender/editors/space_nla/nla_select.c index a816f8fa4f6..ce93e36474f 100644 --- a/source/blender/editors/space_nla/nla_select.c +++ b/source/blender/editors/space_nla/nla_select.c @@ -401,7 +401,7 @@ void NLA_OT_select_box(wmOperatorType *ot) ot->poll = nlaop_poll_tweakmode_off; /* flags */ - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + ot->flag = OPTYPE_UNDO; /* properties */ RNA_def_boolean(ot->srna, "axis_range", 0, "Axis Range", ""); diff --git a/source/blender/editors/space_nla/space_nla.c b/source/blender/editors/space_nla/space_nla.c index 1dd5bb41fef..e658ddef513 100644 --- a/source/blender/editors/space_nla/space_nla.c +++ b/source/blender/editors/space_nla/space_nla.c @@ -303,7 +303,7 @@ static void nla_buttons_region_draw(const bContext *C, ARegion *region) static void nla_region_listener(const wmRegionListenerParams *params) { ARegion *region = params->region; - wmNotifier *wmn = params->notifier; + const wmNotifier *wmn = params->notifier; /* context changes */ switch (wmn->category) { @@ -342,7 +342,7 @@ static void nla_region_listener(const wmRegionListenerParams *params) static void nla_main_region_listener(const wmRegionListenerParams *params) { ARegion *region = params->region; - wmNotifier *wmn = params->notifier; + const wmNotifier *wmn = params->notifier; /* context changes */ switch (wmn->category) { @@ -436,7 +436,7 @@ static void nla_main_region_message_subscribe(const wmRegionMessageSubscribePara static void nla_channel_region_listener(const wmRegionListenerParams *params) { ARegion *region = params->region; - wmNotifier *wmn = params->notifier; + const wmNotifier *wmn = params->notifier; /* context changes */ switch (wmn->category) { @@ -512,7 +512,7 @@ static void nla_channel_region_message_subscribe(const wmRegionMessageSubscribeP static void nla_listener(const wmSpaceTypeListenerParams *params) { ScrArea *area = params->area; - wmNotifier *wmn = params->notifier; + const wmNotifier *wmn = params->notifier; /* context changes */ switch (wmn->category) { @@ -568,7 +568,7 @@ void ED_spacetype_nla(void) ARegionType *art; st->spaceid = SPACE_NLA; - strncpy(st->name, "NLA", BKE_ST_MAXNAME); + STRNCPY(st->name, "NLA"); st->create = nla_create; st->free = nla_free; @@ -628,5 +628,8 @@ void ED_spacetype_nla(void) nla_buttons_register(art); + art = ED_area_type_hud(st->spaceid); + BLI_addhead(&st->regiontypes, art); + BKE_spacetype_register(st); } diff --git a/source/blender/editors/space_node/CMakeLists.txt b/source/blender/editors/space_node/CMakeLists.txt index 26fddda8c22..adb03439568 100644 --- a/source/blender/editors/space_node/CMakeLists.txt +++ b/source/blender/editors/space_node/CMakeLists.txt @@ -17,7 +17,6 @@ set(INC ../../nodes ../../render ../../windowmanager - ../../../../intern/glew-mx ../../../../intern/guardedalloc # RNA_prototypes.h ${CMAKE_BINARY_DIR}/source/blender/makesrna @@ -25,6 +24,7 @@ set(INC set(SRC + add_node_search.cc drawnode.cc link_drag_search.cc node_add.cc diff --git a/source/blender/editors/space_node/add_node_search.cc b/source/blender/editors/space_node/add_node_search.cc new file mode 100644 index 00000000000..cdf20f7b76e --- /dev/null +++ b/source/blender/editors/space_node/add_node_search.cc @@ -0,0 +1,352 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ + +#include <optional> + +#include "BLI_listbase.h" +#include "BLI_string_search.h" + +#include "DNA_space_types.h" + +#include "BKE_asset.h" +#include "BKE_asset_catalog.hh" +#include "BKE_asset_library.hh" +#include "BKE_context.h" +#include "BKE_idprop.h" +#include "BKE_lib_id.h" +#include "BKE_main.h" +#include "BKE_node_tree_update.h" +#include "BKE_screen.h" + +#include "DEG_depsgraph_build.h" + +#include "BLT_translation.h" + +#include "RNA_access.h" + +#include "WM_api.h" + +#include "ED_asset.h" +#include "ED_node.h" + +#include "node_intern.hh" + +struct bContext; + +namespace blender::ed::space_node { + +struct AddNodeItem { + std::string ui_name; + std::string identifier; + std::string description; + std::optional<AssetHandle> asset; + std::function<void(const bContext &, bNodeTree &, bNode &)> after_add_fn; + int weight = 0; +}; + +struct AddNodeSearchStorage { + float2 cursor; + bool use_transform; + Vector<AddNodeItem> search_add_items; + char search[256]; + bool update_items_tag = true; +}; + +static void add_node_search_listen_fn(const wmRegionListenerParams *params, void *arg) +{ + AddNodeSearchStorage &storage = *static_cast<AddNodeSearchStorage *>(arg); + const wmNotifier *wmn = params->notifier; + + switch (wmn->category) { + case NC_ASSET: + if (wmn->data == ND_ASSET_LIST_READING) { + storage.update_items_tag = true; + } + break; + } +} + +static void search_items_for_asset_metadata(const bNodeTree &node_tree, + const AssetLibraryReference &library_ref, + const AssetHandle asset, + Vector<AddNodeItem> &search_items) +{ + const AssetMetaData &asset_data = *ED_asset_handle_get_metadata(&asset); + const IDProperty *tree_type = BKE_asset_metadata_idprop_find(&asset_data, "type"); + if (tree_type == nullptr || IDP_Int(tree_type) != node_tree.type) { + return; + } + + AddNodeItem item{}; + item.ui_name = ED_asset_handle_get_name(&asset); + item.identifier = node_tree.typeinfo->group_idname; + item.description = asset_data.description == nullptr ? "" : asset_data.description; + item.asset = asset; + item.after_add_fn = [asset, library_ref](const bContext &C, bNodeTree &node_tree, bNode &node) { + Main &bmain = *CTX_data_main(&C); + node.flag &= ~NODE_OPTIONS; + node.id = asset::get_local_id_from_asset_or_append_and_reuse(bmain, library_ref, asset); + id_us_plus(node.id); + BKE_ntree_update_tag_node_property(&node_tree, &node); + DEG_relations_tag_update(&bmain); + }; + + search_items.append(std::move(item)); +} + +static void gather_search_items_for_asset_library(const bContext &C, + const bNodeTree &node_tree, + const AssetLibraryReference &library_ref, + Set<std::string> &r_added_assets, + Vector<AddNodeItem> &search_items) +{ + AssetFilterSettings filter_settings{}; + filter_settings.id_types = FILTER_ID_NT; + + ED_assetlist_storage_fetch(&library_ref, &C); + ED_assetlist_ensure_previews_job(&library_ref, &C); + ED_assetlist_iterate(library_ref, [&](AssetHandle asset) { + if (!ED_asset_filter_matches_asset(&filter_settings, &asset)) { + return true; + } + if (!r_added_assets.add(ED_asset_handle_get_name(&asset))) { + /* If an asset with the same name has already been added, skip this. */ + return true; + } + search_items_for_asset_metadata(node_tree, library_ref, asset, search_items); + return true; + }); +} + +static void gather_search_items_for_all_assets(const bContext &C, + const bNodeTree &node_tree, + Set<std::string> &r_added_assets, + Vector<AddNodeItem> &search_items) +{ + int i; + LISTBASE_FOREACH_INDEX (const bUserAssetLibrary *, asset_library, &U.asset_libraries, i) { + AssetLibraryReference library_ref{}; + library_ref.custom_library_index = i; + library_ref.type = ASSET_LIBRARY_CUSTOM; + /* Skip local assets to avoid duplicates when the asset is part of the local file library. */ + gather_search_items_for_asset_library(C, node_tree, library_ref, r_added_assets, search_items); + } + + AssetLibraryReference library_ref{}; + library_ref.custom_library_index = -1; + library_ref.type = ASSET_LIBRARY_LOCAL; + gather_search_items_for_asset_library(C, node_tree, library_ref, r_added_assets, search_items); +} + +static void gather_search_items_for_node_groups(const bContext &C, + const bNodeTree &node_tree, + const Set<std::string> &local_assets, + Vector<AddNodeItem> &search_items) +{ + const StringRef group_node_id = node_tree.typeinfo->group_idname; + + Main &bmain = *CTX_data_main(&C); + LISTBASE_FOREACH (bNodeTree *, node_group, &bmain.nodetrees) { + if (node_group->typeinfo->group_idname != group_node_id) { + continue; + } + if (local_assets.contains(node_group->id.name)) { + continue; + } + if (!nodeGroupPoll(&node_tree, node_group, nullptr)) { + continue; + } + AddNodeItem item{}; + item.ui_name = node_group->id.name + 2; + item.identifier = node_tree.typeinfo->group_idname; + item.after_add_fn = [node_group](const bContext &C, bNodeTree &node_tree, bNode &node) { + Main &bmain = *CTX_data_main(&C); + node.id = &node_group->id; + id_us_plus(node.id); + BKE_ntree_update_tag_node_property(&node_tree, &node); + DEG_relations_tag_update(&bmain); + }; + search_items.append(std::move(item)); + } +} + +static void gather_add_node_operations(const bContext &C, + bNodeTree &node_tree, + Vector<AddNodeItem> &r_search_items) +{ + NODE_TYPES_BEGIN (node_type) { + const char *disabled_hint; + if (!(node_type->poll && node_type->poll(node_type, &node_tree, &disabled_hint))) { + continue; + } + + AddNodeItem item{}; + item.ui_name = IFACE_(node_type->ui_name); + item.identifier = node_type->idname; + item.description = TIP_(node_type->ui_description); + r_search_items.append(std::move(item)); + } + NODE_TYPES_END; + + /* Use a set to avoid adding items for node groups that are also assets. Using data-block + * names is a crutch, since different assets may have the same name. However, an alternative + * using #ED_asset_handle_get_local_id didn't work in this case. */ + Set<std::string> added_assets; + gather_search_items_for_all_assets(C, node_tree, added_assets, r_search_items); + gather_search_items_for_node_groups(C, node_tree, added_assets, r_search_items); +} + +static void add_node_search_update_fn( + const bContext *C, void *arg, const char *str, uiSearchItems *items, const bool is_first) +{ + AddNodeSearchStorage &storage = *static_cast<AddNodeSearchStorage *>(arg); + if (storage.update_items_tag) { + bNodeTree *node_tree = CTX_wm_space_node(C)->edittree; + storage.search_add_items.clear(); + gather_add_node_operations(*C, *node_tree, storage.search_add_items); + storage.update_items_tag = false; + } + + StringSearch *search = BLI_string_search_new(); + + for (AddNodeItem &item : storage.search_add_items) { + BLI_string_search_add(search, item.ui_name.c_str(), &item, item.weight); + } + + /* Don't filter when the menu is first opened, but still run the search + * so the items are in the same order they will appear in while searching. */ + const char *string = is_first ? "" : str; + AddNodeItem **filtered_items; + const int filtered_amount = BLI_string_search_query(search, string, (void ***)&filtered_items); + + for (const int i : IndexRange(filtered_amount)) { + AddNodeItem &item = *filtered_items[i]; + if (!UI_search_item_add(items, item.ui_name.c_str(), &item, ICON_NONE, 0, 0)) { + break; + } + } + + MEM_freeN(filtered_items); + BLI_string_search_free(search); +} + +static void add_node_search_exec_fn(bContext *C, void *arg1, void *arg2) +{ + Main &bmain = *CTX_data_main(C); + SpaceNode &snode = *CTX_wm_space_node(C); + bNodeTree &node_tree = *snode.edittree; + AddNodeSearchStorage &storage = *static_cast<AddNodeSearchStorage *>(arg1); + AddNodeItem *item = static_cast<AddNodeItem *>(arg2); + if (item == nullptr) { + return; + } + + node_deselect_all(snode); + bNode *new_node = nodeAddNode(C, &node_tree, item->identifier.c_str()); + BLI_assert(new_node != nullptr); + + if (item->after_add_fn) { + item->after_add_fn(*C, node_tree, *new_node); + } + + new_node->locx = storage.cursor.x / UI_DPI_FAC; + new_node->locy = storage.cursor.y / UI_DPI_FAC + 20 * UI_DPI_FAC; + + nodeSetSelected(new_node, true); + nodeSetActive(&node_tree, new_node); + + /* Ideally it would be possible to tag the node tree in some way so it updates only after the + * translate operation is finished, but normally moving nodes around doesn't cause updates. */ + ED_node_tree_propagate_change(C, &bmain, &node_tree); + + if (storage.use_transform) { + wmOperatorType *ot = WM_operatortype_find("NODE_OT_translate_attach_remove_on_cancel", true); + BLI_assert(ot); + PointerRNA ptr; + WM_operator_properties_create_ptr(&ptr, ot); + WM_operator_name_call_ptr(C, ot, WM_OP_INVOKE_DEFAULT, &ptr, nullptr); + WM_operator_properties_free(&ptr); + } +} + +static ARegion *add_node_search_tooltip_fn( + bContext *C, ARegion *region, const rcti *item_rect, void * /*arg*/, void *active) +{ + const AddNodeItem *item = static_cast<AddNodeItem *>(active); + + uiSearchItemTooltipData tooltip_data{}; + + BLI_strncpy(tooltip_data.description, + item->asset ? item->description.c_str() : TIP_(item->description.c_str()), + sizeof(tooltip_data.description)); + + return UI_tooltip_create_from_search_item_generic(C, region, item_rect, &tooltip_data); +} + +static void add_node_search_free_fn(void *arg) +{ + AddNodeSearchStorage *storage = static_cast<AddNodeSearchStorage *>(arg); + delete storage; +} + +static uiBlock *create_search_popup_block(bContext *C, ARegion *region, void *arg_op) +{ + AddNodeSearchStorage &storage = *(AddNodeSearchStorage *)arg_op; + + uiBlock *block = UI_block_begin(C, region, "_popup", UI_EMBOSS); + UI_block_flag_enable(block, UI_BLOCK_LOOP | UI_BLOCK_MOVEMOUSE_QUIT | UI_BLOCK_SEARCH_MENU); + UI_block_theme_style_set(block, UI_BLOCK_THEME_STYLE_POPUP); + + uiBut *but = uiDefSearchBut(block, + storage.search, + 0, + ICON_VIEWZOOM, + sizeof(storage.search), + 10, + 10, + UI_searchbox_size_x(), + UI_UNIT_Y, + 0, + 0, + ""); + UI_but_func_search_set_sep_string(but, UI_MENU_ARROW_SEP); + UI_but_func_search_set(but, + nullptr, + add_node_search_update_fn, + &storage, + false, + add_node_search_free_fn, + add_node_search_exec_fn, + nullptr); + UI_but_flag_enable(but, UI_BUT_ACTIVATE_ON_INIT); + UI_but_func_search_set_tooltip(but, add_node_search_tooltip_fn); + UI_but_func_search_set_listen(but, add_node_search_listen_fn); + + /* Fake button to hold space for the search items. */ + uiDefBut(block, + UI_BTYPE_LABEL, + 0, + "", + 10, + 10 - UI_searchbox_size_y(), + UI_searchbox_size_x(), + UI_searchbox_size_y(), + nullptr, + 0, + 0, + 0, + 0, + nullptr); + + const int offset[2] = {0, -UI_UNIT_Y}; + UI_block_bounds_set_popup(block, 0.3f * U.widget_unit, offset); + return block; +} + +void invoke_add_node_search_menu(bContext &C, const float2 &cursor, const bool use_transform) +{ + AddNodeSearchStorage *storage = new AddNodeSearchStorage{cursor, use_transform}; + /* Use the "_ex" variant with `can_refresh` false to avoid a double free when closing Blender. */ + UI_popup_block_invoke_ex(&C, create_search_popup_block, storage, nullptr, false); +} + +} // namespace blender::ed::space_node diff --git a/source/blender/editors/space_node/drawnode.cc b/source/blender/editors/space_node/drawnode.cc index 25ab06850f5..b2510df9105 100644 --- a/source/blender/editors/space_node/drawnode.cc +++ b/source/blender/editors/space_node/drawnode.cc @@ -6,6 +6,7 @@ * \brief lower level node drawing for nodes (boarders, headers etc), also node layout. */ +#include "BLI_color.hh" #include "BLI_system.h" #include "BLI_threads.h" @@ -477,7 +478,7 @@ static void node_shader_set_butfunc(bNodeType *ntype) case SH_NODE_RGB: ntype->draw_buttons = node_buts_rgb; break; - case SH_NODE_MIX_RGB: + case SH_NODE_MIX_RGB_LEGACY: ntype->draw_buttons = node_buts_mix_rgb; break; case SH_NODE_VALTORGB: @@ -626,7 +627,7 @@ static void node_composit_backdrop_viewer( GPUVertFormat *format = immVertexFormat(); uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); - immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); immUniformColor3f(1.0f, 1.0f, 1.0f); @@ -672,7 +673,7 @@ static void node_composit_backdrop_boxmask( GPUVertFormat *format = immVertexFormat(); uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); - immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); immUniformColor3f(1.0f, 1.0f, 1.0f); @@ -717,7 +718,7 @@ static void node_composit_backdrop_ellipsemask( GPUVertFormat *format = immVertexFormat(); uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); - immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); immUniformColor3f(1.0f, 1.0f, 1.0f); @@ -1569,7 +1570,7 @@ void draw_nodespace_back_pix(const bContext &C, uint pos = GPU_vertformat_attr_add( immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); - immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); immUniformThemeColor(TH_ACTIVE); immDrawBorderCorners(pos, &pixel_border, 1.0f, 1.0f); @@ -1584,102 +1585,82 @@ void draw_nodespace_back_pix(const bContext &C, GPU_matrix_pop(); } -bool node_link_bezier_handles(const View2D *v2d, - const SpaceNode *snode, - const bNodeLink &link, - float vec[4][2]) +static float2 socket_link_connection_location(const bNodeSocket &socket, const bNodeLink &link) { - float cursor[2] = {0.0f, 0.0f}; - - /* this function can be called with snode null (via cut_links_intersect) */ - /* XXX map snode->runtime->cursor back to view space */ - if (snode) { - cursor[0] = snode->runtime->cursor[0] * UI_DPI_FAC; - cursor[1] = snode->runtime->cursor[1] * UI_DPI_FAC; + const float2 socket_location(socket.locx, socket.locy); + if (socket.flag & SOCK_MULTI_INPUT && socket.in_out == SOCK_IN) { + return node_link_calculate_multi_input_position( + socket_location, link.multi_input_socket_index, socket.total_inputs); } + return socket_location; +} - /* in v0 and v3 we put begin/end points */ - if (link.fromsock) { - vec[0][0] = link.fromsock->locx; - vec[0][1] = link.fromsock->locy; - if (link.fromsock->flag & SOCK_MULTI_INPUT) { - const float2 position = node_link_calculate_multi_input_position( - {link.fromsock->locx, link.fromsock->locy}, - link.fromsock->total_inputs - 1, - link.fromsock->total_inputs); - copy_v2_v2(vec[0], position); - } - } - else { - if (snode == nullptr) { - return false; - } - copy_v2_v2(vec[0], cursor); - } - if (link.tosock) { - vec[3][0] = link.tosock->locx; - vec[3][1] = link.tosock->locy; - if (!(link.tonode->flag & NODE_HIDDEN) && link.tosock->flag & SOCK_MULTI_INPUT) { - const float2 position = node_link_calculate_multi_input_position( - {link.tosock->locx, link.tosock->locy}, - link.multi_input_socket_index, - link.tosock->total_inputs); - copy_v2_v2(vec[3], position); - } +static void calculate_inner_link_bezier_points(std::array<float2, 4> &points) +{ + const int curving = UI_GetThemeValueType(TH_NODE_CURVING, SPACE_NODE); + if (curving == 0) { + /* Straight line: align all points. */ + points[1] = math::interpolate(points[0], points[3], 1.0f / 3.0f); + points[2] = math::interpolate(points[0], points[3], 2.0f / 3.0f); } else { - if (snode == nullptr) { - return false; - } - copy_v2_v2(vec[3], cursor); - } + const float dist_x = math::distance(points[0].x, points[3].x); + const float dist_y = math::distance(points[0].y, points[3].y); - /* may be called outside of drawing (so pass spacetype) */ - int curving = UI_GetThemeValueType(TH_NODE_CURVING, SPACE_NODE); + /* Reduce the handle offset when the link endpoints are close to horizontal. */ + const float slope = safe_divide(dist_y, dist_x); + const float clamp_factor = math::min(1.0f, slope * (4.5f - 0.25f * float(curving))); - if (curving == 0) { - /* Straight line: align all points. */ - mid_v2_v2v2(vec[1], vec[0], vec[3]); - mid_v2_v2v2(vec[2], vec[1], vec[3]); - return true; - } + const float handle_offset = curving * 0.1f * dist_x * clamp_factor; - const float dist = curving * 0.10f * fabsf(vec[0][0] - vec[3][0]); + points[1].x = points[0].x + handle_offset; + points[1].y = points[0].y; - vec[1][0] = vec[0][0] + dist; - vec[1][1] = vec[0][1]; + points[2].x = points[3].x - handle_offset; + points[2].y = points[3].y; + } +} - vec[2][0] = vec[3][0] - dist; - vec[2][1] = vec[3][1]; +static std::array<float2, 4> node_link_bezier_points(const bNodeLink &link) +{ + std::array<float2, 4> points; + points[0] = socket_link_connection_location(*link.fromsock, link); + points[3] = socket_link_connection_location(*link.tosock, link); + calculate_inner_link_bezier_points(points); + return points; +} - if (v2d && min_ffff(vec[0][0], vec[1][0], vec[2][0], vec[3][0]) > v2d->cur.xmax) { - return false; /* clipped */ +static bool node_link_draw_is_visible(const View2D &v2d, const std::array<float2, 4> &points) +{ + if (min_ffff(points[0].x, points[1].x, points[2].x, points[3].x) > v2d.cur.xmax) { + return false; } - if (v2d && max_ffff(vec[0][0], vec[1][0], vec[2][0], vec[3][0]) < v2d->cur.xmin) { - return false; /* clipped */ + if (max_ffff(points[0].x, points[1].x, points[2].x, points[3].x) < v2d.cur.xmin) { + return false; } - return true; } -bool node_link_bezier_points(const View2D *v2d, - const SpaceNode *snode, - const bNodeLink &link, - float coord_array[][2], - const int resol) +void node_link_bezier_points_evaluated(const bNodeLink &link, + std::array<float2, NODE_LINK_RESOL + 1> &coords) { - float vec[4][2]; - - if (node_link_bezier_handles(v2d, snode, link, vec)) { - /* always do all three, to prevent data hanging around */ - BKE_curve_forward_diff_bezier( - vec[0][0], vec[1][0], vec[2][0], vec[3][0], coord_array[0] + 0, resol, sizeof(float[2])); - BKE_curve_forward_diff_bezier( - vec[0][1], vec[1][1], vec[2][1], vec[3][1], coord_array[0] + 1, resol, sizeof(float[2])); + const std::array<float2, 4> points = node_link_bezier_points(link); - return true; - } - return false; + /* The extra +1 in size is required by these functions and would be removed ideally. */ + BKE_curve_forward_diff_bezier(points[0].x, + points[1].x, + points[2].x, + points[3].x, + &coords[0].x, + NODE_LINK_RESOL, + sizeof(float2)); + BKE_curve_forward_diff_bezier(points[0].y, + points[1].y, + points[2].y, + points[3].y, + &coords[0].y, + NODE_LINK_RESOL, + sizeof(float2)); } #define NODELINK_GROUP_SIZE 256 @@ -1938,189 +1919,252 @@ void nodelink_batch_end(SpaceNode &snode) g_batch_link.enabled = false; } +struct NodeLinkDrawConfig { + int th_col1; + int th_col2; + int th_col3; + + ColorTheme4f start_color; + ColorTheme4f end_color; + ColorTheme4f outline_color; + + bool drawarrow; + bool drawmuted; + bool highlighted; + + float dim_factor; + float thickness; + float dash_factor; + float dash_alpha; +}; + static void nodelink_batch_add_link(const SpaceNode &snode, - const float2 &p0, - const float2 &p1, - const float2 &p2, - const float2 &p3, - int th_col1, - int th_col2, - int th_col3, - const float start_color[4], - const float end_color[4], - bool drawarrow, - bool drawmuted, - float dim_factor, - float thickness, - float dash_factor, - float dash_alpha) + const std::array<float2, 4> &points, + const NodeLinkDrawConfig &draw_config) { /* Only allow these colors. If more is needed, you need to modify the shader accordingly. */ - BLI_assert(ELEM(th_col1, TH_WIRE_INNER, TH_WIRE, TH_ACTIVE, TH_EDGE_SELECT, TH_REDALERT)); - BLI_assert(ELEM(th_col2, TH_WIRE_INNER, TH_WIRE, TH_ACTIVE, TH_EDGE_SELECT, TH_REDALERT)); - BLI_assert(ELEM(th_col3, TH_WIRE, TH_REDALERT, -1)); + BLI_assert( + ELEM(draw_config.th_col1, TH_WIRE_INNER, TH_WIRE, TH_ACTIVE, TH_EDGE_SELECT, TH_REDALERT)); + BLI_assert( + ELEM(draw_config.th_col2, TH_WIRE_INNER, TH_WIRE, TH_ACTIVE, TH_EDGE_SELECT, TH_REDALERT)); + BLI_assert(ELEM(draw_config.th_col3, TH_WIRE, TH_REDALERT, -1)); g_batch_link.count++; - copy_v2_v2((float *)GPU_vertbuf_raw_step(&g_batch_link.p0_step), p0); - copy_v2_v2((float *)GPU_vertbuf_raw_step(&g_batch_link.p1_step), p1); - copy_v2_v2((float *)GPU_vertbuf_raw_step(&g_batch_link.p2_step), p2); - copy_v2_v2((float *)GPU_vertbuf_raw_step(&g_batch_link.p3_step), p3); + copy_v2_v2((float *)GPU_vertbuf_raw_step(&g_batch_link.p0_step), points[0]); + copy_v2_v2((float *)GPU_vertbuf_raw_step(&g_batch_link.p1_step), points[1]); + copy_v2_v2((float *)GPU_vertbuf_raw_step(&g_batch_link.p2_step), points[2]); + copy_v2_v2((float *)GPU_vertbuf_raw_step(&g_batch_link.p3_step), points[3]); char *colid = (char *)GPU_vertbuf_raw_step(&g_batch_link.colid_step); - colid[0] = nodelink_get_color_id(th_col1); - colid[1] = nodelink_get_color_id(th_col2); - colid[2] = nodelink_get_color_id(th_col3); - colid[3] = drawarrow; - copy_v4_v4((float *)GPU_vertbuf_raw_step(&g_batch_link.start_color_step), start_color); - copy_v4_v4((float *)GPU_vertbuf_raw_step(&g_batch_link.end_color_step), end_color); + colid[0] = nodelink_get_color_id(draw_config.th_col1); + colid[1] = nodelink_get_color_id(draw_config.th_col2); + colid[2] = nodelink_get_color_id(draw_config.th_col3); + colid[3] = draw_config.drawarrow; + copy_v4_v4((float *)GPU_vertbuf_raw_step(&g_batch_link.start_color_step), + draw_config.start_color); + copy_v4_v4((float *)GPU_vertbuf_raw_step(&g_batch_link.end_color_step), draw_config.end_color); char *muted = (char *)GPU_vertbuf_raw_step(&g_batch_link.muted_step); - muted[0] = drawmuted; - *(float *)GPU_vertbuf_raw_step(&g_batch_link.dim_factor_step) = dim_factor; - *(float *)GPU_vertbuf_raw_step(&g_batch_link.thickness_step) = thickness; - *(float *)GPU_vertbuf_raw_step(&g_batch_link.dash_factor_step) = dash_factor; - *(float *)GPU_vertbuf_raw_step(&g_batch_link.dash_alpha_step) = dash_alpha; + muted[0] = draw_config.drawmuted; + *(float *)GPU_vertbuf_raw_step(&g_batch_link.dim_factor_step) = draw_config.dim_factor; + *(float *)GPU_vertbuf_raw_step(&g_batch_link.thickness_step) = draw_config.thickness; + *(float *)GPU_vertbuf_raw_step(&g_batch_link.dash_factor_step) = draw_config.dash_factor; + *(float *)GPU_vertbuf_raw_step(&g_batch_link.dash_alpha_step) = draw_config.dash_alpha; if (g_batch_link.count == NODELINK_GROUP_SIZE) { nodelink_batch_draw(snode); } } -void node_draw_link_bezier(const bContext &C, - const View2D &v2d, - const SpaceNode &snode, - const bNodeLink &link, - const int th_col1, - const int th_col2, - const int th_col3, - const bool selected) +static void node_draw_link_end_marker(const float2 center, + const float radius, + const ColorTheme4f &color) +{ + rctf rect; + BLI_rctf_init(&rect, center.x - radius, center.x + radius, center.y - radius, center.y + radius); + + UI_draw_roundbox_corner_set(UI_CNR_ALL); + UI_draw_roundbox_4fv(&rect, true, radius, color); + /* Roundbox disables alpha. Reenable it for node links that are drawn after this one. */ + GPU_blend(GPU_BLEND_ALPHA); +} + +static void node_draw_link_end_markers(const bNodeLink &link, + const NodeLinkDrawConfig &draw_config, + const std::array<float2, 4> &points, + const bool outline) +{ + const float radius = (outline ? 0.65f : 0.45f) * NODE_SOCKSIZE; + if (link.fromsock) { + node_draw_link_end_marker( + points[0], radius, outline ? draw_config.outline_color : draw_config.start_color); + } + if (link.tosock) { + node_draw_link_end_marker( + points[3], radius, outline ? draw_config.outline_color : draw_config.end_color); + } +} + +static bool node_link_is_field_link(const SpaceNode &snode, const bNodeLink &link) +{ + if (snode.edittree->type != NTREE_GEOMETRY) { + return false; + } + if (link.fromsock && link.fromsock->display_shape == SOCK_DISPLAY_SHAPE_DIAMOND) { + return true; + } + return false; +} + +static NodeLinkDrawConfig nodelink_get_draw_config(const bContext &C, + const View2D &v2d, + const SpaceNode &snode, + const bNodeLink &link, + const int th_col1, + const int th_col2, + const int th_col3, + const bool selected) { - const float dim_factor = selected ? 1.0f : node_link_dim_factor(v2d, link); - float thickness = 1.5f; - float dash_factor = 1.0f; + NodeLinkDrawConfig draw_config; + + draw_config.th_col1 = th_col1; + draw_config.th_col2 = th_col2; + draw_config.th_col3 = th_col3; + + draw_config.dim_factor = selected ? 1.0f : node_link_dim_factor(v2d, link); bTheme *btheme = UI_GetTheme(); - const float dash_alpha = btheme->space_node.dash_alpha; - - if (snode.edittree->type == NTREE_GEOMETRY) { - if (link.fromsock && link.fromsock->display_shape == SOCK_DISPLAY_SHAPE_DIAMOND) { - /* Make field links a bit thinner. */ - thickness = 1.0f; - /* Draw field as dashes. */ - dash_factor = 0.75f; + draw_config.dash_alpha = btheme->space_node.dash_alpha; + + const bool field_link = node_link_is_field_link(snode, link); + + draw_config.dash_factor = field_link ? 0.75f : 1.0f; + + const float scale = UI_view2d_scale_get_x(&v2d); + /* Clamp the thickness to make the links more readable when zooming out. */ + draw_config.thickness = max_ff(scale, 1.0f) * (field_link ? 0.7f : 1.0f); + draw_config.highlighted = link.flag & NODE_LINK_TEMP_HIGHLIGHT; + draw_config.drawarrow = ((link.tonode && (link.tonode->type == NODE_REROUTE)) && + (link.fromnode && (link.fromnode->type == NODE_REROUTE))); + draw_config.drawmuted = (link.flag & NODE_LINK_MUTED); + + UI_GetThemeColor4fv(th_col3, draw_config.outline_color); + + if (snode.overlay.flag & SN_OVERLAY_SHOW_OVERLAYS && + snode.overlay.flag & SN_OVERLAY_SHOW_WIRE_COLORS) { + PointerRNA from_node_ptr, to_node_ptr; + RNA_pointer_create((ID *)snode.edittree, &RNA_Node, link.fromnode, &from_node_ptr); + RNA_pointer_create((ID *)snode.edittree, &RNA_Node, link.tonode, &to_node_ptr); + + if (link.fromsock) { + node_socket_color_get( + C, *snode.edittree, from_node_ptr, *link.fromsock, draw_config.start_color); + } + else { + node_socket_color_get( + C, *snode.edittree, to_node_ptr, *link.tosock, draw_config.start_color); } - } - float vec[4][2]; - const bool highlighted = link.flag & NODE_LINK_TEMP_HIGHLIGHT; - if (node_link_bezier_handles(&v2d, &snode, link, vec)) { - int drawarrow = ((link.tonode && (link.tonode->type == NODE_REROUTE)) && - (link.fromnode && (link.fromnode->type == NODE_REROUTE))); - int drawmuted = (link.flag & NODE_LINK_MUTED); - if (g_batch_link.batch == nullptr) { - nodelink_batch_init(); + if (link.tosock) { + node_socket_color_get(C, *snode.edittree, to_node_ptr, *link.tosock, draw_config.end_color); } - /* Draw single link. */ - float colors[3][4] = {{0.0f}}; - if (th_col3 != -1) { - UI_GetThemeColor4fv(th_col3, colors[0]); + else { + node_socket_color_get( + C, *snode.edittree, from_node_ptr, *link.fromsock, draw_config.end_color); } + } + else { + UI_GetThemeColor4fv(th_col1, draw_config.start_color); + UI_GetThemeColor4fv(th_col2, draw_config.end_color); + } + + /* Highlight links connected to selected nodes. */ + if (selected) { + ColorTheme4f color_selected; + UI_GetThemeColor4fv(TH_EDGE_SELECT, color_selected); + const float alpha = color_selected.a; - if (snode.overlay.flag & SN_OVERLAY_SHOW_OVERLAYS && - snode.overlay.flag & SN_OVERLAY_SHOW_WIRE_COLORS) { - PointerRNA from_node_ptr, to_node_ptr; - RNA_pointer_create((ID *)snode.edittree, &RNA_Node, link.fromnode, &from_node_ptr); - RNA_pointer_create((ID *)snode.edittree, &RNA_Node, link.tonode, &to_node_ptr); + /* Interpolate color if highlight color is not fully transparent. */ + if (alpha != 0.0) { if (link.fromsock) { - node_socket_color_get(C, *snode.edittree, from_node_ptr, *link.fromsock, colors[1]); + interp_v3_v3v3(draw_config.start_color, draw_config.start_color, color_selected, alpha); } - else { - node_socket_color_get(C, *snode.edittree, to_node_ptr, *link.tosock, colors[1]); - } - if (link.tosock) { - node_socket_color_get(C, *snode.edittree, to_node_ptr, *link.tosock, colors[2]); - } - else { - node_socket_color_get(C, *snode.edittree, from_node_ptr, *link.fromsock, colors[2]); + interp_v3_v3v3(draw_config.end_color, draw_config.end_color, color_selected, alpha); } } - else { - UI_GetThemeColor4fv(th_col1, colors[1]); - UI_GetThemeColor4fv(th_col2, colors[2]); - } + } - /* Highlight links connected to selected nodes. */ - if (selected) { - float color_selected[4]; - UI_GetThemeColor4fv(TH_EDGE_SELECT, color_selected); - const float alpha = color_selected[3]; + if (draw_config.highlighted) { + ColorTheme4f link_preselection_highlight_color; + UI_GetThemeColor4fv(TH_SELECT, link_preselection_highlight_color); + /* Multi sockets can only be inputs. So we only have to highlight the end of the link. */ + copy_v4_v4(draw_config.end_color, link_preselection_highlight_color); + } - /* Interpolate color if highlight color is not fully transparent. */ - if (alpha != 0.0) { - if (link.fromsock) { - interp_v3_v3v3(colors[1], colors[1], color_selected, alpha); - } - if (link.tosock) { - interp_v3_v3v3(colors[2], colors[2], color_selected, alpha); - } - } - } + return draw_config; +} - if (g_batch_link.enabled && !highlighted) { - /* Add link to batch. */ - nodelink_batch_add_link(snode, - vec[0], - vec[1], - vec[2], - vec[3], - th_col1, - th_col2, - th_col3, - colors[1], - colors[2], - drawarrow, - drawmuted, - dim_factor, - thickness, - dash_factor, - dash_alpha); - } - else { - if (highlighted) { - float link_preselection_highlight_color[4]; - UI_GetThemeColor4fv(TH_SELECT, link_preselection_highlight_color); - copy_v4_v4(colors[2], link_preselection_highlight_color); - } +static void node_draw_link_bezier_ex(const SpaceNode &snode, + const NodeLinkDrawConfig &draw_config, + const std::array<float2, 4> &points) +{ + if (g_batch_link.batch == nullptr) { + nodelink_batch_init(); + } - NodeLinkData node_link_data; - for (int i = 0; i < 4; i++) { - copy_v2_v2(node_link_data.bezierPts[i], vec[i]); - } - for (int i = 0; i < 3; i++) { - copy_v4_v4(node_link_data.colors[i], colors[i]); - } - node_link_data.doArrow = drawarrow; - node_link_data.doMuted = drawmuted; - node_link_data.dim_factor = dim_factor; - node_link_data.thickness = thickness; - node_link_data.dash_factor = dash_factor; - node_link_data.dash_alpha = dash_alpha; - node_link_data.expandSize = snode.runtime->aspect * LINK_WIDTH; - node_link_data.arrowSize = ARROW_SIZE; - - GPUBatch *batch = g_batch_link.batch_single; - GPUUniformBuf *ubo = GPU_uniformbuf_create_ex( - sizeof(NodeLinkData), &node_link_data, __func__); - - GPU_batch_program_set_builtin(batch, GPU_SHADER_2D_NODELINK); - GPU_batch_uniformbuf_bind(batch, "node_link_data", ubo); - GPU_batch_draw(batch); - - GPU_uniformbuf_unbind(ubo); - GPU_uniformbuf_free(ubo); + if (g_batch_link.enabled && !draw_config.highlighted) { + /* Add link to batch. */ + nodelink_batch_add_link(snode, points, draw_config); + } + else { + NodeLinkData node_link_data; + for (const int i : IndexRange(points.size())) { + copy_v2_v2(node_link_data.bezierPts[i], points[i]); } + + copy_v4_v4(node_link_data.colors[0], draw_config.outline_color); + copy_v4_v4(node_link_data.colors[1], draw_config.start_color); + copy_v4_v4(node_link_data.colors[2], draw_config.end_color); + + node_link_data.doArrow = draw_config.drawarrow; + node_link_data.doMuted = draw_config.drawmuted; + node_link_data.dim_factor = draw_config.dim_factor; + node_link_data.thickness = draw_config.thickness; + node_link_data.dash_factor = draw_config.dash_factor; + node_link_data.dash_alpha = draw_config.dash_alpha; + node_link_data.expandSize = snode.runtime->aspect * LINK_WIDTH; + node_link_data.arrowSize = ARROW_SIZE; + + GPUBatch *batch = g_batch_link.batch_single; + GPUUniformBuf *ubo = GPU_uniformbuf_create_ex(sizeof(NodeLinkData), &node_link_data, __func__); + + GPU_batch_program_set_builtin(batch, GPU_SHADER_2D_NODELINK); + GPU_batch_uniformbuf_bind(batch, "node_link_data", ubo); + GPU_batch_draw(batch); + + GPU_uniformbuf_unbind(ubo); + GPU_uniformbuf_free(ubo); } } +void node_draw_link_bezier(const bContext &C, + const View2D &v2d, + const SpaceNode &snode, + const bNodeLink &link, + const int th_col1, + const int th_col2, + const int th_col3, + const bool selected) +{ + const std::array<float2, 4> points = node_link_bezier_points(link); + if (!node_link_draw_is_visible(v2d, points)) { + return; + } + const NodeLinkDrawConfig draw_config = nodelink_get_draw_config( + C, v2d, snode, link, th_col1, th_col2, th_col3, selected); + + node_draw_link_bezier_ex(snode, draw_config, points); +} + void node_draw_link(const bContext &C, const View2D &v2d, const SpaceNode &snode, @@ -2133,34 +2177,29 @@ void node_draw_link(const bContext &C, return; } - /* new connection */ - if (!link.fromsock || !link.tosock) { - th_col1 = th_col2 = TH_ACTIVE; + /* going to give issues once... */ + if (link.tosock->flag & SOCK_UNAVAIL) { + return; + } + if (link.fromsock->flag & SOCK_UNAVAIL) { + return; } - else { - /* going to give issues once... */ - if (link.tosock->flag & SOCK_UNAVAIL) { - return; - } - if (link.fromsock->flag & SOCK_UNAVAIL) { - return; - } - if (link.flag & NODE_LINK_VALID) { - /* special indicated link, on drop-node */ - if (link.flag & NODE_LINKFLAG_HILITE) { - th_col1 = th_col2 = TH_ACTIVE; - } - else if (link.flag & NODE_LINK_MUTED) { - th_col1 = th_col2 = TH_REDALERT; - } + if (link.flag & NODE_LINK_VALID) { + /* special indicated link, on drop-node */ + if (link.flag & NODE_LINKFLAG_HILITE) { + th_col1 = th_col2 = TH_ACTIVE; } - else { - /* Invalid link. */ - th_col1 = th_col2 = th_col3 = TH_REDALERT; - // th_col3 = -1; /* no shadow */ + else if (link.flag & NODE_LINK_MUTED) { + th_col1 = th_col2 = TH_REDALERT; } } + else { + /* Invalid link. */ + th_col1 = th_col2 = th_col3 = TH_REDALERT; + // th_col3 = -1; /* no shadow */ + } + /* Links from field to non-field sockets are not allowed. */ if (snode.edittree->type == NTREE_GEOMETRY && !(link.flag & NODE_LINK_DRAGGED)) { if ((link.fromsock && link.fromsock->display_shape == SOCK_DISPLAY_SHAPE_DIAMOND) && @@ -2172,6 +2211,38 @@ void node_draw_link(const bContext &C, node_draw_link_bezier(C, v2d, snode, link, th_col1, th_col2, th_col3, selected); } +static std::array<float2, 4> node_link_bezier_points_dragged(const SpaceNode &snode, + const bNodeLink &link) +{ + const float2 cursor = snode.runtime->cursor * UI_DPI_FAC; + std::array<float2, 4> points; + points[0] = link.fromsock ? socket_link_connection_location(*link.fromsock, link) : cursor; + points[3] = link.tosock ? socket_link_connection_location(*link.tosock, link) : cursor; + calculate_inner_link_bezier_points(points); + return points; +} + +void node_draw_link_dragged(const bContext &C, + const View2D &v2d, + const SpaceNode &snode, + const bNodeLink &link) +{ + if (link.fromsock == nullptr && link.tosock == nullptr) { + return; + } + + const std::array<float2, 4> points = node_link_bezier_points_dragged(snode, link); + + const NodeLinkDrawConfig draw_config = nodelink_get_draw_config( + C, v2d, snode, link, TH_ACTIVE, TH_ACTIVE, TH_WIRE, true); + /* End marker outline. */ + node_draw_link_end_markers(link, draw_config, points, true); + /* Link. */ + node_draw_link_bezier_ex(snode, draw_config, points); + /* End marker fill. */ + node_draw_link_end_markers(link, draw_config, points, false); +} + } // namespace blender::ed::space_node void ED_node_draw_snap(View2D *v2d, const float cent[2], float size, NodeBorder border, uint pos) diff --git a/source/blender/editors/space_node/link_drag_search.cc b/source/blender/editors/space_node/link_drag_search.cc index 9014e36c4e2..17410937d4c 100644 --- a/source/blender/editors/space_node/link_drag_search.cc +++ b/source/blender/editors/space_node/link_drag_search.cc @@ -5,7 +5,12 @@ #include "DNA_space_types.h" +#include "BKE_asset.h" #include "BKE_context.h" +#include "BKE_idprop.h" +#include "BKE_lib_id.h" +#include "BKE_node_tree_update.h" +#include "BKE_screen.h" #include "NOD_socket_search_link.hh" @@ -15,6 +20,9 @@ #include "WM_api.h" +#include "DEG_depsgraph_build.h" + +#include "ED_asset.h" #include "ED_node.h" #include "node_intern.hh" @@ -29,6 +37,7 @@ struct LinkDragSearchStorage { float2 cursor; Vector<SocketLinkOperation> search_link_ops; char search[256]; + bool update_items_tag = true; eNodeSocketInOut in_out() const { @@ -36,6 +45,20 @@ struct LinkDragSearchStorage { } }; +static void link_drag_search_listen_fn(const wmRegionListenerParams *params, void *arg) +{ + LinkDragSearchStorage &storage = *static_cast<LinkDragSearchStorage *>(arg); + const wmNotifier *wmn = params->notifier; + + switch (wmn->category) { + case NC_ASSET: + if (wmn->data == ND_ASSET_LIST_READING) { + storage.update_items_tag = true; + } + break; + } +} + static void add_reroute_node_fn(nodes::LinkSearchOpParams ¶ms) { bNode &reroute = params.add_node("NodeReroute"); @@ -112,11 +135,137 @@ static void add_existing_group_input_fn(nodes::LinkSearchOpParams ¶ms, } /** + * \note This could use #search_link_ops_for_socket_templates, but we have to store the inputs and + * outputs as IDProperties for assets because of asset indexing, so that's all we have without + * loading the file. + */ +static void search_link_ops_for_asset_metadata(const bNodeTree &node_tree, + const bNodeSocket &socket, + const AssetLibraryReference &library_ref, + const AssetHandle asset, + Vector<SocketLinkOperation> &search_link_ops) +{ + const AssetMetaData &asset_data = *ED_asset_handle_get_metadata(&asset); + const IDProperty *tree_type = BKE_asset_metadata_idprop_find(&asset_data, "type"); + if (tree_type == nullptr || IDP_Int(tree_type) != node_tree.type) { + return; + } + + const bNodeTreeType &node_tree_type = *node_tree.typeinfo; + const eNodeSocketInOut in_out = socket.in_out == SOCK_OUT ? SOCK_IN : SOCK_OUT; + + const IDProperty *sockets = BKE_asset_metadata_idprop_find( + &asset_data, in_out == SOCK_IN ? "inputs" : "outputs"); + + int weight = -1; + Set<StringRef> socket_names; + LISTBASE_FOREACH (IDProperty *, socket_property, &sockets->data.group) { + if (socket_property->type != IDP_STRING) { + continue; + } + const char *socket_idname = IDP_String(socket_property); + const bNodeSocketType *socket_type = nodeSocketTypeFind(socket_idname); + if (socket_type == nullptr) { + continue; + } + eNodeSocketDatatype from = (eNodeSocketDatatype)socket.type; + eNodeSocketDatatype to = (eNodeSocketDatatype)socket_type->type; + if (socket.in_out == SOCK_OUT) { + std::swap(from, to); + } + if (node_tree_type.validate_link && !node_tree_type.validate_link(from, to)) { + continue; + } + if (!socket_names.add(socket_property->name)) { + /* See comment in #search_link_ops_for_declarations. */ + continue; + } + + const StringRef asset_name = ED_asset_handle_get_name(&asset); + const StringRef socket_name = socket_property->name; + + search_link_ops.append( + {asset_name + " " + UI_MENU_ARROW_SEP + socket_name, + [library_ref, asset, socket_property, in_out](nodes::LinkSearchOpParams ¶ms) { + Main &bmain = *CTX_data_main(¶ms.C); + + bNode &node = params.add_node(params.node_tree.typeinfo->group_idname); + node.flag &= ~NODE_OPTIONS; + + node.id = asset::get_local_id_from_asset_or_append_and_reuse(bmain, library_ref, asset); + id_us_plus(node.id); + BKE_ntree_update_tag_node_property(¶ms.node_tree, &node); + DEG_relations_tag_update(&bmain); + + /* Create the inputs and outputs on the new node. */ + node.typeinfo->group_update_func(¶ms.node_tree, &node); + + bNodeSocket *new_node_socket = bke::node_find_enabled_socket( + node, in_out, socket_property->name); + if (new_node_socket != nullptr) { + /* Rely on the way #nodeAddLink switches in/out if necessary. */ + nodeAddLink(¶ms.node_tree, ¶ms.node, ¶ms.socket, &node, new_node_socket); + } + }, + weight}); + + weight--; + } +} + +static void gather_search_link_ops_for_asset_library(const bContext &C, + const bNodeTree &node_tree, + const bNodeSocket &socket, + const AssetLibraryReference &library_ref, + const bool skip_local, + Vector<SocketLinkOperation> &search_link_ops) +{ + AssetFilterSettings filter_settings{}; + filter_settings.id_types = FILTER_ID_NT; + + ED_assetlist_storage_fetch(&library_ref, &C); + ED_assetlist_ensure_previews_job(&library_ref, &C); + ED_assetlist_iterate(library_ref, [&](AssetHandle asset) { + if (!ED_asset_filter_matches_asset(&filter_settings, &asset)) { + return true; + } + if (skip_local && ED_asset_handle_get_local_id(&asset) != nullptr) { + return true; + } + search_link_ops_for_asset_metadata(node_tree, socket, library_ref, asset, search_link_ops); + return true; + }); +} + +static void gather_search_link_ops_for_all_assets(const bContext &C, + const bNodeTree &node_tree, + const bNodeSocket &socket, + Vector<SocketLinkOperation> &search_link_ops) +{ + int i; + LISTBASE_FOREACH_INDEX (const bUserAssetLibrary *, asset_library, &U.asset_libraries, i) { + AssetLibraryReference library_ref{}; + library_ref.custom_library_index = i; + library_ref.type = ASSET_LIBRARY_CUSTOM; + /* Skip local assets to avoid duplicates when the asset is part of the local file library. */ + gather_search_link_ops_for_asset_library( + C, node_tree, socket, library_ref, true, search_link_ops); + } + + AssetLibraryReference library_ref{}; + library_ref.custom_library_index = -1; + library_ref.type = ASSET_LIBRARY_LOCAL; + gather_search_link_ops_for_asset_library( + C, node_tree, socket, library_ref, false, search_link_ops); +} + +/** * Call the callback to gather compatible socket connections for all node types, and the operations * that will actually make the connections. Also add some custom operations like connecting a group * output node. */ -static void gather_socket_link_operations(bNodeTree &node_tree, +static void gather_socket_link_operations(const bContext &C, + bNodeTree &node_tree, const bNodeSocket &socket, Vector<SocketLinkOperation> &search_link_ops) { @@ -156,15 +305,20 @@ static void gather_socket_link_operations(bNodeTree &node_tree, weight--; } } + + gather_search_link_ops_for_all_assets(C, node_tree, socket, search_link_ops); } -static void link_drag_search_update_fn(const bContext *UNUSED(C), - void *arg, - const char *str, - uiSearchItems *items, - const bool is_first) +static void link_drag_search_update_fn( + const bContext *C, void *arg, const char *str, uiSearchItems *items, const bool is_first) { LinkDragSearchStorage &storage = *static_cast<LinkDragSearchStorage *>(arg); + if (storage.update_items_tag) { + bNodeTree *node_tree = CTX_wm_space_node(C)->edittree; + storage.search_link_ops.clear(); + gather_socket_link_operations(*C, *node_tree, storage.from_socket, storage.search_link_ops); + storage.update_items_tag = false; + } StringSearch *search = BLI_string_search_new(); @@ -214,7 +368,7 @@ static void link_drag_search_exec_fn(bContext *C, void *arg1, void *arg2) bNode *new_node = new_nodes.first(); new_node->locx = storage.cursor.x / UI_DPI_FAC; - new_node->locy = storage.cursor.y / UI_DPI_FAC + 20 * UI_DPI_FAC; + new_node->locy = storage.cursor.y / UI_DPI_FAC + 20; if (storage.in_out() == SOCK_IN) { new_node->locx -= new_node->width; } @@ -227,12 +381,10 @@ static void link_drag_search_exec_fn(bContext *C, void *arg1, void *arg2) ED_node_tree_propagate_change(C, &bmain, snode.edittree); /* Start translation operator with the new node. */ - wmOperatorType *ot = WM_operatortype_find("TRANSFORM_OT_translate", true); + wmOperatorType *ot = WM_operatortype_find("NODE_OT_translate_attach_remove_on_cancel", true); BLI_assert(ot); PointerRNA ptr; WM_operator_properties_create_ptr(&ptr, ot); - RNA_boolean_set(&ptr, "view2d_edge_pan", true); - RNA_boolean_set(&ptr, "remove_on_cancel", true); WM_operator_name_call_ptr(C, ot, WM_OP_INVOKE_DEFAULT, &ptr, nullptr); WM_operator_properties_free(&ptr); } @@ -247,9 +399,6 @@ static uiBlock *create_search_popup_block(bContext *C, ARegion *region, void *ar { LinkDragSearchStorage &storage = *(LinkDragSearchStorage *)arg_op; - bNodeTree *node_tree = CTX_wm_space_node(C)->nodetree; - gather_socket_link_operations(*node_tree, storage.from_socket, storage.search_link_ops); - uiBlock *block = UI_block_begin(C, region, "_popup", UI_EMBOSS); UI_block_flag_enable(block, UI_BLOCK_LOOP | UI_BLOCK_MOVEMOUSE_QUIT | UI_BLOCK_SEARCH_MENU); UI_block_theme_style_set(block, UI_BLOCK_THEME_STYLE_POPUP); @@ -267,6 +416,7 @@ static uiBlock *create_search_popup_block(bContext *C, ARegion *region, void *ar 0, ""); UI_but_func_search_set_sep_string(but, UI_MENU_ARROW_SEP); + UI_but_func_search_set_listen(but, link_drag_search_listen_fn); UI_but_func_search_set(but, nullptr, link_drag_search_update_fn, @@ -293,7 +443,7 @@ static uiBlock *create_search_popup_block(bContext *C, ARegion *region, void *ar 0, nullptr); - const int offset[2] = {0, -UI_UNIT_Y}; + const int2 offset = {0, -UI_UNIT_Y}; UI_block_bounds_set_popup(block, 0.3f * U.widget_unit, offset); return block; } diff --git a/source/blender/editors/space_node/node_add.cc b/source/blender/editors/space_node/node_add.cc index 0d498d07aff..efe53fd6f14 100644 --- a/source/blender/editors/space_node/node_add.cc +++ b/source/blender/editors/space_node/node_add.cc @@ -5,6 +5,8 @@ * \ingroup spnode */ +#include <numeric> + #include "MEM_guardedalloc.h" #include "DNA_collection_types.h" @@ -20,6 +22,7 @@ #include "BKE_lib_id.h" #include "BKE_main.h" #include "BKE_node.h" +#include "BKE_node_runtime.hh" #include "BKE_node_tree_update.h" #include "BKE_report.h" #include "BKE_scene.h" @@ -101,191 +104,113 @@ bNode *add_static_node(const bContext &C, int type, const float2 &location) /** \name Add Reroute Operator * \{ */ -static bool add_reroute_intersect_check(const bNodeLink &link, - float mcoords[][2], - int tot, - float result[2]) +std::optional<float2> link_path_intersection(const bNodeLink &link, const Span<float2> path) { - float coord_array[NODE_LINK_RESOL + 1][2]; - - if (node_link_bezier_points(nullptr, nullptr, link, coord_array, NODE_LINK_RESOL)) { - for (int i = 0; i < tot - 1; i++) { - for (int b = 0; b < NODE_LINK_RESOL; b++) { - if (isect_seg_seg_v2_point( - mcoords[i], mcoords[i + 1], coord_array[b], coord_array[b + 1], result) > 0) { - return true; - } + std::array<float2, NODE_LINK_RESOL + 1> coords; + node_link_bezier_points_evaluated(link, coords); + + for (const int i : path.index_range().drop_back(1)) { + for (const int j : IndexRange(NODE_LINK_RESOL)) { + float2 result; + if (isect_seg_seg_v2_point(path[i], path[i + 1], coords[j], coords[j + 1], result) > 0) { + return result; } } } - return false; -} -struct bNodeSocketLink { - struct bNodeSocketLink *next, *prev; + return std::nullopt; +} - struct bNodeSocket *sock; - struct bNodeLink *link; - float point[2]; +struct RerouteCutsForSocket { + /* The output socket's owner node. */ + bNode *from_node; + /* Intersected links connected to the socket and their path intersection locations. */ + Map<bNodeLink *, float2> links; }; -static bNodeSocketLink *add_reroute_insert_socket_link(ListBase *lb, - bNodeSocket *sock, - bNodeLink *link, - const float point[2]) +static int add_reroute_exec(bContext *C, wmOperator *op) { - bNodeSocketLink *socklink, *prev; - - socklink = MEM_cnew<bNodeSocketLink>("socket link"); - socklink->sock = sock; - socklink->link = link; - copy_v2_v2(socklink->point, point); + const ARegion ®ion = *CTX_wm_region(C); + SpaceNode &snode = *CTX_wm_space_node(C); + bNodeTree &ntree = *snode.edittree; - for (prev = (bNodeSocketLink *)lb->last; prev; prev = prev->prev) { - if (prev->sock == sock) { + Vector<float2> path; + RNA_BEGIN (op->ptr, itemptr, "path") { + float2 loc_region; + RNA_float_get_array(&itemptr, "loc", loc_region); + float2 loc_view; + UI_view2d_region_to_view(®ion.v2d, loc_region.x, loc_region.y, &loc_view.x, &loc_view.y); + path.append(loc_view); + if (path.size() >= 256) { break; } } - BLI_insertlinkafter(lb, prev, socklink); - return socklink; -} - -static bNodeSocketLink *add_reroute_do_socket_section(bContext *C, - bNodeSocketLink *socklink, - int in_out) -{ - SpaceNode *snode = CTX_wm_space_node(C); - bNodeTree *ntree = snode->edittree; - bNode *reroute_node = nullptr; - bNodeSocket *cursock = socklink->sock; - float insert_point[2]; - int num_links; - - zero_v2(insert_point); - num_links = 0; - - while (socklink && socklink->sock == cursock) { - if (!(socklink->link->flag & NODE_LINK_TEST)) { - socklink->link->flag |= NODE_LINK_TEST; - - /* create the reroute node for this cursock */ - if (!reroute_node) { - reroute_node = nodeAddStaticNode(C, ntree, NODE_REROUTE); - - /* add a single link to/from the reroute node to replace multiple links */ - if (in_out == SOCK_OUT) { - nodeAddLink(ntree, - socklink->link->fromnode, - socklink->link->fromsock, - reroute_node, - (bNodeSocket *)reroute_node->inputs.first); - } - else { - nodeAddLink(ntree, - reroute_node, - (bNodeSocket *)reroute_node->outputs.first, - socklink->link->tonode, - socklink->link->tosock); - } - } - - /* insert the reroute node into the link */ - if (in_out == SOCK_OUT) { - socklink->link->fromnode = reroute_node; - socklink->link->fromsock = (bNodeSocket *)reroute_node->outputs.first; - } - else { - socklink->link->tonode = reroute_node; - socklink->link->tosock = (bNodeSocket *)reroute_node->inputs.first; - } - - add_v2_v2(insert_point, socklink->point); - num_links++; - } - socklink = socklink->next; - } - - if (num_links > 0) { - /* average cut point from shared links */ - mul_v2_fl(insert_point, 1.0f / num_links); + RNA_END; - reroute_node->locx = insert_point[0] / UI_DPI_FAC; - reroute_node->locy = insert_point[1] / UI_DPI_FAC; + if (path.is_empty()) { + return OPERATOR_CANCELLED | OPERATOR_PASS_THROUGH; } - return socklink; -} + ntree.ensure_topology_cache(); + const Vector<bNode *> frame_nodes = ntree.nodes_by_type("NodeFrame"); -static int add_reroute_exec(bContext *C, wmOperator *op) -{ - SpaceNode &snode = *CTX_wm_space_node(C); - ARegion ®ion = *CTX_wm_region(C); - bNodeTree &ntree = *snode.edittree; - float mcoords[256][2]; - int i = 0; + ED_preview_kill_jobs(CTX_wm_manager(C), CTX_data_main(C)); + node_deselect_all(snode); - /* Get the cut path */ - RNA_BEGIN (op->ptr, itemptr, "path") { - float loc[2]; + /* All link "cuts" that start at a particular output socket. Deduplicating new reroutes per + * output socket is useful because it allows reusing reroutes for connected intersections. + * Further deduplication using the second map means we only have one cut per link. */ + Map<bNodeSocket *, RerouteCutsForSocket> cuts_per_socket; - RNA_float_get_array(&itemptr, "loc", loc); - UI_view2d_region_to_view( - ®ion.v2d, (short)loc[0], (short)loc[1], &mcoords[i][0], &mcoords[i][1]); - i++; - if (i >= 256) { - break; + LISTBASE_FOREACH (bNodeLink *, link, &ntree.links) { + if (node_link_is_hidden_or_dimmed(region.v2d, *link)) { + continue; + } + const std::optional<float2> intersection = link_path_intersection(*link, path); + if (!intersection) { + continue; } + RerouteCutsForSocket &from_cuts = cuts_per_socket.lookup_or_add_default(link->fromsock); + from_cuts.from_node = link->fromnode; + from_cuts.links.add(link, *intersection); } - RNA_END; - - if (i > 1) { - ListBase output_links, input_links; - bNodeSocketLink *socklink; - float insert_point[2]; - /* always first */ - ED_preview_kill_jobs(CTX_wm_manager(C), CTX_data_main(C)); + for (const auto item : cuts_per_socket.items()) { + const Map<bNodeLink *, float2> &cuts = item.value.links; - node_deselect_all(snode); + bNode *reroute = nodeAddStaticNode(C, &ntree, NODE_REROUTE); - /* Find cut links and sort them by sockets */ - BLI_listbase_clear(&output_links); - BLI_listbase_clear(&input_links); - - LISTBASE_FOREACH (bNodeLink *, link, &ntree.links) { - if (node_link_is_hidden_or_dimmed(region.v2d, *link)) { - continue; - } - if (add_reroute_intersect_check(*link, mcoords, i, insert_point)) { - add_reroute_insert_socket_link(&output_links, link->fromsock, link, insert_point); - add_reroute_insert_socket_link(&input_links, link->tosock, link, insert_point); + nodeAddLink(&ntree, + item.value.from_node, + item.key, + reroute, + static_cast<bNodeSocket *>(reroute->inputs.first)); - /* Clear flag */ - link->flag &= ~NODE_LINK_TEST; - } + /* Reconnect links from the original output socket to the new reroute. */ + for (bNodeLink *link : cuts.keys()) { + link->fromnode = reroute; + link->fromsock = static_cast<bNodeSocket *>(reroute->outputs.first); + BKE_ntree_update_tag_link_changed(&ntree); } - /* Create reroute nodes for intersected links. - * Only one reroute if links share the same input/output socket. - */ - socklink = (bNodeSocketLink *)output_links.first; - while (socklink) { - socklink = add_reroute_do_socket_section(C, socklink, SOCK_OUT); - } - socklink = (bNodeSocketLink *)input_links.first; - while (socklink) { - socklink = add_reroute_do_socket_section(C, socklink, SOCK_IN); + /* Place the new reroute at the average location of all connected cuts. */ + const float2 loc = std::accumulate(cuts.values().begin(), cuts.values().end(), float2(0)) / + cuts.size() / UI_DPI_FAC; + reroute->locx = loc.x; + reroute->locy = loc.y; + + /* Attach the reroute node to frame nodes behind it. */ + for (const int i : frame_nodes.index_range()) { + bNode *frame_node = frame_nodes.last(i); + if (BLI_rctf_isect_pt_v(&frame_node->totr, loc)) { + nodeAttachNode(reroute, frame_node); + break; + } } - - BLI_freelistN(&output_links); - BLI_freelistN(&input_links); - - /* always last */ - ED_node_tree_propagate_change(C, CTX_data_main(C), &ntree); - return OPERATOR_FINISHED; } - return OPERATOR_CANCELLED | OPERATOR_PASS_THROUGH; + ED_node_tree_propagate_change(C, CTX_data_main(C), &ntree); + return OPERATOR_FINISHED; } void NODE_OT_add_reroute(wmOperatorType *ot) @@ -885,4 +810,37 @@ void NODE_OT_new_node_tree(wmOperatorType *ot) /** \} */ +/* -------------------------------------------------------------------- */ +/** \name Add Node Search + * \{ */ + +static int node_add_search_invoke(bContext *C, wmOperator *op, const wmEvent *event) +{ + const ARegion ®ion = *CTX_wm_region(C); + + float2 cursor; + UI_view2d_region_to_view(®ion.v2d, event->mval[0], event->mval[1], &cursor.x, &cursor.y); + + invoke_add_node_search_menu(*C, cursor, RNA_boolean_get(op->ptr, "use_transform")); + + return OPERATOR_FINISHED; +} + +void NODE_OT_add_search(wmOperatorType *ot) +{ + ot->name = "Search and Add Node"; + ot->idname = "NODE_OT_add_search"; + ot->description = "Search for nodes and add one to the active tree"; + + ot->invoke = node_add_search_invoke; + ot->poll = ED_operator_node_editable; + + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + + RNA_def_boolean( + ot->srna, "use_transform", true, "Use Transform", "Start moving the node after adding it"); +} + +/** \} */ + } // namespace blender::ed::space_node diff --git a/source/blender/editors/space_node/node_context_path.cc b/source/blender/editors/space_node/node_context_path.cc index b9bee3ed15e..4f7497b5f49 100644 --- a/source/blender/editors/space_node/node_context_path.cc +++ b/source/blender/editors/space_node/node_context_path.cc @@ -28,27 +28,26 @@ #include "node_intern.hh" -struct Curve; -struct Light; struct Material; -struct Mesh; -struct World; namespace blender::ed::space_node { static void context_path_add_object_data(Vector<ui::ContextPathItem> &path, Object &object) { - if (object.type == OB_MESH && object.data) { - Mesh *mesh = (Mesh *)object.data; - ui::context_path_add_generic(path, RNA_Mesh, mesh); + if (!object.data) { + return; } - if (object.type == OB_LAMP && object.data) { - Light *light = (Light *)object.data; - ui::context_path_add_generic(path, RNA_Light, light); + if (object.type == OB_MESH) { + ui::context_path_add_generic(path, RNA_Mesh, object.data); } - if (ELEM(object.type, OB_CURVES_LEGACY, OB_FONT, OB_SURF) && object.data) { - Curve *curve = (Curve *)object.data; - ui::context_path_add_generic(path, RNA_Curve, curve); + else if (object.type == OB_CURVES) { + ui::context_path_add_generic(path, RNA_Curves, object.data); + } + else if (object.type == OB_LAMP) { + ui::context_path_add_generic(path, RNA_Light, object.data); + } + else if (ELEM(object.type, OB_CURVES_LEGACY, OB_FONT, OB_SURF)) { + ui::context_path_add_generic(path, RNA_Curve, object.data); } } @@ -71,8 +70,7 @@ static void get_context_path_node_shader(const bContext &C, Scene *scene = CTX_data_scene(&C); ui::context_path_add_generic(path, RNA_Scene, scene); if (scene != nullptr) { - World *world = scene->world; - ui::context_path_add_generic(path, RNA_World, world); + ui::context_path_add_generic(path, RNA_World, scene->world); } /* Skip the base node tree here, because the world contains a node tree already. */ context_path_add_node_tree_and_node_groups(snode, path, true); @@ -95,8 +93,7 @@ static void get_context_path_node_shader(const bContext &C, Scene *scene = CTX_data_scene(&C); ui::context_path_add_generic(path, RNA_Scene, scene); if (scene != nullptr) { - World *world = scene->world; - ui::context_path_add_generic(path, RNA_World, world); + ui::context_path_add_generic(path, RNA_World, scene->world); } } #ifdef WITH_FREESTYLE diff --git a/source/blender/editors/space_node/node_draw.cc b/source/blender/editors/space_node/node_draw.cc index c74cd58d8fb..937db9951b4 100644 --- a/source/blender/editors/space_node/node_draw.cc +++ b/source/blender/editors/space_node/node_draw.cc @@ -13,6 +13,7 @@ #include "DNA_light_types.h" #include "DNA_linestyle_types.h" #include "DNA_material_types.h" +#include "DNA_modifier_types.h" #include "DNA_node_types.h" #include "DNA_screen_types.h" #include "DNA_space_types.h" @@ -29,11 +30,14 @@ #include "BLT_translation.h" +#include "BKE_compute_contexts.hh" #include "BKE_context.h" #include "BKE_idtype.h" #include "BKE_lib_id.h" #include "BKE_main.h" #include "BKE_node.h" +#include "BKE_node_runtime.hh" +#include "BKE_node_tree_update.h" #include "BKE_object.h" #include "DEG_depsgraph.h" @@ -64,7 +68,8 @@ #include "RNA_access.h" #include "RNA_prototypes.h" -#include "NOD_geometry_nodes_eval_log.hh" +#include "NOD_geometry_exec.hh" +#include "NOD_geometry_nodes_log.hh" #include "NOD_node_declaration.hh" #include "NOD_socket_declarations_geometry.hh" @@ -73,10 +78,11 @@ #include "node_intern.hh" /* own include */ +namespace geo_log = blender::nodes::geo_eval_log; + using blender::GPointer; +using blender::Vector; using blender::fn::GField; -namespace geo_log = blender::nodes::geometry_nodes_eval_log; -using geo_log::eNamedAttrUsage; extern "C" { /* XXX interface.h */ @@ -84,6 +90,17 @@ extern void ui_draw_dropshadow( const rctf *rct, float radius, float aspect, float alpha, int select); } +/** + * This is passed to many functions which draw the node editor. + */ +struct TreeDrawContext { + /** + * Geometry nodes logs various data during execution. The logged data that corresponds to the + * currently drawn node tree can be retrieved from the log below. + */ + geo_log::GeoTreeLog *geo_tree_log = nullptr; +}; + float ED_node_grid_size() { return U.widget_unit; @@ -156,6 +173,12 @@ void ED_node_tag_update_id(ID *id) namespace blender::ed::space_node { +static void node_socket_add_tooltip_in_node_editor(TreeDrawContext * /*tree_draw_ctx*/, + const bNodeTree *ntree, + const bNode *node, + const bNodeSocket *sock, + uiLayout *layout); + static bool compare_nodes(const bNode *a, const bNode *b) { /* These tell if either the node or any of the parent nodes is selected. @@ -248,6 +271,7 @@ void node_sort(bNodeTree &ntree) b++; BLI_remlink(&ntree.nodes, tmp); BLI_insertlinkbefore(&ntree.nodes, node_a, tmp); + BKE_ntree_update_tag_node_reordered(&ntree); } } @@ -311,7 +335,11 @@ float2 node_from_view(const bNode &node, const float2 &co) /** * Based on settings and sockets in node, set drawing rect info. */ -static void node_update_basis(const bContext &C, bNodeTree &ntree, bNode &node, uiBlock &block) +static void node_update_basis(const bContext &C, + TreeDrawContext &tree_draw_ctx, + bNodeTree &ntree, + bNode &node, + uiBlock &block) { PointerRNA nodeptr; RNA_pointer_create(&ntree.id, &RNA_Node, &node, &nodeptr); @@ -340,13 +368,13 @@ static void node_update_basis(const bContext &C, bNodeTree &ntree, bNode &node, bool add_output_space = false; int buty; - LISTBASE_FOREACH (bNodeSocket *, nsock, &node.outputs) { - if (nodeSocketIsHidden(nsock)) { + LISTBASE_FOREACH (bNodeSocket *, socket, &node.outputs) { + if (nodeSocketIsHidden(socket)) { continue; } PointerRNA sockptr; - RNA_pointer_create(&ntree.id, &RNA_NodeSocket, nsock, &sockptr); + RNA_pointer_create(&ntree.id, &RNA_NodeSocket, socket, &sockptr); uiLayout *layout = UI_block_layout(&block, UI_LAYOUT_VERTICAL, @@ -369,10 +397,10 @@ static void node_update_basis(const bContext &C, bNodeTree &ntree, bNode &node, /* Align output buttons to the right. */ uiLayout *row = uiLayoutRow(layout, true); uiLayoutSetAlignment(row, UI_LAYOUT_ALIGN_RIGHT); - const char *socket_label = nodeSocketLabel(nsock); - nsock->typeinfo->draw((bContext *)&C, row, &sockptr, &nodeptr, IFACE_(socket_label)); + const char *socket_label = nodeSocketLabel(socket); + socket->typeinfo->draw((bContext *)&C, row, &sockptr, &nodeptr, IFACE_(socket_label)); - node_socket_add_tooltip(&ntree, &node, nsock, row); + node_socket_add_tooltip_in_node_editor(&tree_draw_ctx, &ntree, &node, socket, row); UI_block_align_end(&block); UI_block_layout_resolve(&block, nullptr, &buty); @@ -381,11 +409,11 @@ static void node_update_basis(const bContext &C, bNodeTree &ntree, bNode &node, buty = min_ii(buty, dy - NODE_DY); /* Round the socket location to stop it from jiggling. */ - nsock->locx = round(loc.x + NODE_WIDTH(node)); - nsock->locy = round(dy - NODE_DYS); + socket->locx = round(loc.x + NODE_WIDTH(node)); + socket->locy = round(dy - NODE_DYS); dy = buty; - if (nsock->next) { + if (socket->next) { dy -= NODE_SOCKDY; } @@ -463,20 +491,20 @@ static void node_update_basis(const bContext &C, bNodeTree &ntree, bNode &node, } /* Input sockets. */ - LISTBASE_FOREACH (bNodeSocket *, nsock, &node.inputs) { - if (nodeSocketIsHidden(nsock)) { + LISTBASE_FOREACH (bNodeSocket *, socket, &node.inputs) { + if (nodeSocketIsHidden(socket)) { continue; } PointerRNA sockptr; - RNA_pointer_create(&ntree.id, &RNA_NodeSocket, nsock, &sockptr); + RNA_pointer_create(&ntree.id, &RNA_NodeSocket, socket, &sockptr); /* Add the half the height of a multi-input socket to cursor Y * to account for the increased height of the taller sockets. */ float multi_input_socket_offset = 0.0f; - if (nsock->flag & SOCK_MULTI_INPUT) { - if (nsock->total_inputs > 2) { - multi_input_socket_offset = (nsock->total_inputs - 2) * NODE_MULTI_INPUT_LINK_GAP; + if (socket->flag & SOCK_MULTI_INPUT) { + if (socket->total_inputs > 2) { + multi_input_socket_offset = (socket->total_inputs - 2) * NODE_MULTI_INPUT_LINK_GAP; } } dy -= multi_input_socket_offset * 0.5f; @@ -501,10 +529,10 @@ static void node_update_basis(const bContext &C, bNodeTree &ntree, bNode &node, uiLayout *row = uiLayoutRow(layout, true); - const char *socket_label = nodeSocketLabel(nsock); - nsock->typeinfo->draw((bContext *)&C, row, &sockptr, &nodeptr, IFACE_(socket_label)); + const char *socket_label = nodeSocketLabel(socket); + socket->typeinfo->draw((bContext *)&C, row, &sockptr, &nodeptr, IFACE_(socket_label)); - node_socket_add_tooltip(&ntree, &node, nsock, row); + node_socket_add_tooltip_in_node_editor(&tree_draw_ctx, &ntree, &node, socket, row); UI_block_align_end(&block); UI_block_layout_resolve(&block, nullptr, &buty); @@ -512,12 +540,12 @@ static void node_update_basis(const bContext &C, bNodeTree &ntree, bNode &node, /* Ensure minimum socket height in case layout is empty. */ buty = min_ii(buty, dy - NODE_DY); - nsock->locx = loc.x; + socket->locx = loc.x; /* Round the socket vertical position to stop it from jiggling. */ - nsock->locy = round(dy - NODE_DYS); + socket->locy = round(dy - NODE_DYS); dy = buty - multi_input_socket_offset * 0.5; - if (nsock->next) { + if (socket->next) { dy -= NODE_SOCKDY; } } @@ -555,13 +583,13 @@ static void node_update_hidden(bNode &node, uiBlock &block) loc.y = round(loc.y); /* Calculate minimal radius. */ - LISTBASE_FOREACH (bNodeSocket *, nsock, &node.inputs) { - if (!nodeSocketIsHidden(nsock)) { + LISTBASE_FOREACH (bNodeSocket *, socket, &node.inputs) { + if (!nodeSocketIsHidden(socket)) { totin++; } } - LISTBASE_FOREACH (bNodeSocket *, nsock, &node.outputs) { - if (!nodeSocketIsHidden(nsock)) { + LISTBASE_FOREACH (bNodeSocket *, socket, &node.outputs) { + if (!nodeSocketIsHidden(socket)) { totout++; } } @@ -581,11 +609,11 @@ static void node_update_hidden(bNode &node, uiBlock &block) float rad = (float)M_PI / (1.0f + (float)totout); float drad = rad; - LISTBASE_FOREACH (bNodeSocket *, nsock, &node.outputs) { - if (!nodeSocketIsHidden(nsock)) { + LISTBASE_FOREACH (bNodeSocket *, socket, &node.outputs) { + if (!nodeSocketIsHidden(socket)) { /* Round the socket location to stop it from jiggling. */ - nsock->locx = round(node.totr.xmax - hiddenrad + sinf(rad) * hiddenrad); - nsock->locy = round(node.totr.ymin + hiddenrad + cosf(rad) * hiddenrad); + socket->locx = round(node.totr.xmax - hiddenrad + sinf(rad) * hiddenrad); + socket->locy = round(node.totr.ymin + hiddenrad + cosf(rad) * hiddenrad); rad += drad; } } @@ -593,11 +621,11 @@ static void node_update_hidden(bNode &node, uiBlock &block) /* Input sockets. */ rad = drad = -(float)M_PI / (1.0f + (float)totin); - LISTBASE_FOREACH (bNodeSocket *, nsock, &node.inputs) { - if (!nodeSocketIsHidden(nsock)) { + LISTBASE_FOREACH (bNodeSocket *, socket, &node.inputs) { + if (!nodeSocketIsHidden(socket)) { /* Round the socket location to stop it from jiggling. */ - nsock->locx = round(node.totr.xmin + hiddenrad + sinf(rad) * hiddenrad); - nsock->locy = round(node.totr.ymin + hiddenrad + cosf(rad) * hiddenrad); + socket->locx = round(node.totr.xmin + hiddenrad + sinf(rad) * hiddenrad); + socket->locy = round(node.totr.ymin + hiddenrad + cosf(rad) * hiddenrad); rad += drad; } } @@ -663,7 +691,9 @@ static void node_draw_mute_line(const bContext &C, GPU_blend(GPU_BLEND_ALPHA); LISTBASE_FOREACH (const bNodeLink *, link, &node.internal_links) { - node_draw_link_bezier(C, v2d, snode, *link, TH_WIRE_INNER, TH_WIRE_INNER, TH_WIRE, false); + if (!nodeLinkIsHidden(link)) { + node_draw_link_bezier(C, v2d, snode, *link, TH_WIRE_INNER, TH_WIRE_INNER, TH_WIRE, false); + } } GPU_blend(GPU_BLEND_NONE); @@ -718,8 +748,7 @@ static void node_socket_draw_multi_input(const float color[4], const float color_outline[4], const float width, const float height, - const int locx, - const int locy) + const float2 location) { /* The other sockets are drawn with the keyframe shader. There, the outline has a base thickness * that can be varied but always scales with the size the socket is drawn at. Using `U.dpi_fac` @@ -729,10 +758,10 @@ static void node_socket_draw_multi_input(const float color[4], /* UI_draw_roundbox draws the outline on the outer side, so compensate for the outline width. */ const rctf rect = { - locx - width + outline_width * 0.5f, - locx + width - outline_width * 0.5f, - locy - height + outline_width * 0.5f, - locy + height - outline_width * 0.5f, + location.x - width + outline_width * 0.5f, + location.x + width - outline_width * 0.5f, + location.y - height + outline_width * 0.5f, + location.y + height - outline_width * 0.5f, }; UI_draw_roundbox_corner_set(UI_CNR_ALL); @@ -756,6 +785,7 @@ static void node_socket_outline_color_get(const bool selected, } else { UI_GetThemeColor4fv(TH_WIRE, r_outline_color); + r_outline_color[3] = 1.0f; } } @@ -773,9 +803,9 @@ void node_socket_color_get(const bContext &C, } struct SocketTooltipData { - bNodeTree *ntree; - bNode *node; - bNodeSocket *socket; + const bNodeTree *ntree; + const bNode *node; + const bNodeSocket *socket; }; static void create_inspection_string_for_generic_value(const GPointer value, std::stringstream &ss) @@ -819,25 +849,16 @@ static void create_inspection_string_for_generic_value(const GPointer value, std } } -static void create_inspection_string_for_gfield(const geo_log::GFieldValueLog &value_log, - std::stringstream &ss) +static void create_inspection_string_for_field_info(const geo_log::FieldInfoLog &value_log, + std::stringstream &ss) { - const CPPType &type = value_log.type(); - const GField &field = value_log.field(); - const Span<std::string> input_tooltips = value_log.input_tooltips(); + const CPPType &type = value_log.type; + const Span<std::string> input_tooltips = value_log.input_tooltips; if (input_tooltips.is_empty()) { - if (field) { - BUFFER_FOR_CPP_TYPE_VALUE(type, buffer); - blender::fn::evaluate_constant_field(field, buffer); - create_inspection_string_for_generic_value({type, buffer}, ss); - type.destruct(buffer); - } - else { - /* Constant values should always be logged. */ - BLI_assert_unreachable(); - ss << "Value has not been logged"; - } + /* Should have been logged as constant value. */ + BLI_assert_unreachable(); + ss << "Value has not been logged"; } else { if (type.is<int>()) { @@ -870,11 +891,11 @@ static void create_inspection_string_for_gfield(const geo_log::GFieldValueLog &v } } -static void create_inspection_string_for_geometry(const geo_log::GeometryValueLog &value_log, - std::stringstream &ss, - const nodes::decl::Geometry *geometry) +static void create_inspection_string_for_geometry_info(const geo_log::GeometryInfoLog &value_log, + std::stringstream &ss, + const nodes::decl::Geometry *socket_decl) { - Span<GeometryComponentType> component_types = value_log.component_types(); + Span<GeometryComponentType> component_types = value_log.component_types; if (component_types.is_empty()) { ss << TIP_("Empty Geometry"); return; @@ -891,7 +912,7 @@ static void create_inspection_string_for_geometry(const geo_log::GeometryValueLo const char *line_end = (type == component_types.last()) ? "" : ".\n"; switch (type) { case GEO_COMPONENT_TYPE_MESH: { - const geo_log::GeometryValueLog::MeshInfo &mesh_info = *value_log.mesh_info; + const geo_log::GeometryInfoLog::MeshInfo &mesh_info = *value_log.mesh_info; char line[256]; BLI_snprintf(line, sizeof(line), @@ -903,7 +924,7 @@ static void create_inspection_string_for_geometry(const geo_log::GeometryValueLo break; } case GEO_COMPONENT_TYPE_POINT_CLOUD: { - const geo_log::GeometryValueLog::PointCloudInfo &pointcloud_info = + const geo_log::GeometryInfoLog::PointCloudInfo &pointcloud_info = *value_log.pointcloud_info; char line[256]; BLI_snprintf(line, @@ -914,7 +935,7 @@ static void create_inspection_string_for_geometry(const geo_log::GeometryValueLo break; } case GEO_COMPONENT_TYPE_CURVE: { - const geo_log::GeometryValueLog::CurveInfo &curve_info = *value_log.curve_info; + const geo_log::GeometryInfoLog::CurveInfo &curve_info = *value_log.curve_info; char line[256]; BLI_snprintf(line, sizeof(line), @@ -924,7 +945,7 @@ static void create_inspection_string_for_geometry(const geo_log::GeometryValueLo break; } case GEO_COMPONENT_TYPE_INSTANCES: { - const geo_log::GeometryValueLog::InstancesInfo &instances_info = *value_log.instances_info; + const geo_log::GeometryInfoLog::InstancesInfo &instances_info = *value_log.instances_info; char line[256]; BLI_snprintf(line, sizeof(line), @@ -939,7 +960,7 @@ static void create_inspection_string_for_geometry(const geo_log::GeometryValueLo } case GEO_COMPONENT_TYPE_EDIT: { if (value_log.edit_data_info.has_value()) { - const geo_log::GeometryValueLog::EditDataInfo &edit_info = *value_log.edit_data_info; + const geo_log::GeometryInfoLog::EditDataInfo &edit_info = *value_log.edit_data_info; char line[256]; BLI_snprintf(line, sizeof(line), @@ -955,11 +976,11 @@ static void create_inspection_string_for_geometry(const geo_log::GeometryValueLo /* If the geometry declaration is null, as is the case for input to group output, * or it is an output socket don't show supported types. */ - if (geometry == nullptr || geometry->in_out() == SOCK_OUT) { + if (socket_decl == nullptr || socket_decl->in_out() == SOCK_OUT) { return; } - Span<GeometryComponentType> supported_types = geometry->supported_types(); + Span<GeometryComponentType> supported_types = socket_decl->supported_types(); if (supported_types.is_empty()) { ss << ".\n\n" << TIP_("Supported: All Types"); return; @@ -996,64 +1017,66 @@ static void create_inspection_string_for_geometry(const geo_log::GeometryValueLo } } -static std::optional<std::string> create_socket_inspection_string(bContext *C, - bNode &node, - bNodeSocket &socket) +static std::optional<std::string> create_socket_inspection_string(TreeDrawContext &tree_draw_ctx, + const bNodeSocket &socket) { - SpaceNode *snode = CTX_wm_space_node(C); - if (snode == nullptr) { - return {}; - }; - - const geo_log::SocketLog *socket_log = geo_log::ModifierLog::find_socket_by_node_editor_context( - *snode, node, socket); - if (socket_log == nullptr) { - return {}; - } - const geo_log::ValueLog *value_log = socket_log->value(); + using namespace blender::nodes::geo_eval_log; + tree_draw_ctx.geo_tree_log->ensure_socket_values(); + ValueLog *value_log = tree_draw_ctx.geo_tree_log->find_socket_value_log(socket); if (value_log == nullptr) { - return {}; + return std::nullopt; } - std::stringstream ss; if (const geo_log::GenericValueLog *generic_value_log = dynamic_cast<const geo_log::GenericValueLog *>(value_log)) { - create_inspection_string_for_generic_value(generic_value_log->value(), ss); + create_inspection_string_for_generic_value(generic_value_log->value, ss); } - if (const geo_log::GFieldValueLog *gfield_value_log = - dynamic_cast<const geo_log::GFieldValueLog *>(value_log)) { - create_inspection_string_for_gfield(*gfield_value_log, ss); + else if (const geo_log::FieldInfoLog *gfield_value_log = + dynamic_cast<const geo_log::FieldInfoLog *>(value_log)) { + create_inspection_string_for_field_info(*gfield_value_log, ss); } - else if (const geo_log::GeometryValueLog *geo_value_log = - dynamic_cast<const geo_log::GeometryValueLog *>(value_log)) { - create_inspection_string_for_geometry( + else if (const geo_log::GeometryInfoLog *geo_value_log = + dynamic_cast<const geo_log::GeometryInfoLog *>(value_log)) { + create_inspection_string_for_geometry_info( *geo_value_log, ss, dynamic_cast<const nodes::decl::Geometry *>(socket.runtime->declaration)); } - return ss.str(); + std::string str = ss.str(); + if (str.empty()) { + return std::nullopt; + } + return str; } -static bool node_socket_has_tooltip(bNodeTree *ntree, bNodeSocket *socket) +static bool node_socket_has_tooltip(const bNodeTree &ntree, const bNodeSocket &socket) { - if (ntree->type == NTREE_GEOMETRY) { + if (ntree.type == NTREE_GEOMETRY) { return true; } - if (socket->runtime->declaration != nullptr) { - const blender::nodes::SocketDeclaration &socket_decl = *socket->runtime->declaration; + if (socket.runtime->declaration != nullptr) { + const nodes::SocketDeclaration &socket_decl = *socket.runtime->declaration; return !socket_decl.description().is_empty(); } return false; } -static char *node_socket_get_tooltip(bContext *C, - bNodeTree *ntree, - bNode *node, - bNodeSocket *socket) +static char *node_socket_get_tooltip(const bContext *C, + const bNodeTree *ntree, + const bNode *UNUSED(node), + const bNodeSocket *socket) { + SpaceNode *snode = CTX_wm_space_node(C); + TreeDrawContext tree_draw_ctx; + if (snode != nullptr) { + if (ntree->type == NTREE_GEOMETRY) { + tree_draw_ctx.geo_tree_log = geo_log::GeoModifierLog::get_tree_log_for_node_editor(*snode); + } + } + std::stringstream output; if (socket->runtime->declaration != nullptr) { const blender::nodes::SocketDeclaration &socket_decl = *socket->runtime->declaration; @@ -1063,13 +1086,13 @@ static char *node_socket_get_tooltip(bContext *C, } } - if (ntree->type == NTREE_GEOMETRY) { + if (ntree->type == NTREE_GEOMETRY && tree_draw_ctx.geo_tree_log != nullptr) { if (!output.str().empty()) { output << ".\n\n"; } std::optional<std::string> socket_inspection_str = create_socket_inspection_string( - C, *node, *socket); + tree_draw_ctx, *socket); if (socket_inspection_str.has_value()) { output << *socket_inspection_str; } @@ -1085,9 +1108,13 @@ static char *node_socket_get_tooltip(bContext *C, return BLI_strdup(output.str().c_str()); } -void node_socket_add_tooltip(bNodeTree *ntree, bNode *node, bNodeSocket *sock, uiLayout *layout) +static void node_socket_add_tooltip_in_node_editor(TreeDrawContext *UNUSED(tree_draw_ctx), + const bNodeTree *ntree, + const bNode *node, + const bNodeSocket *sock, + uiLayout *layout) { - if (!node_socket_has_tooltip(ntree, sock)) { + if (!node_socket_has_tooltip(*ntree, *sock)) { return; } @@ -1107,6 +1134,14 @@ void node_socket_add_tooltip(bNodeTree *ntree, bNode *node, bNodeSocket *sock, u MEM_freeN); } +void node_socket_add_tooltip(const bNodeTree &ntree, + const bNode &node, + const bNodeSocket &sock, + uiLayout &layout) +{ + node_socket_add_tooltip_in_node_editor(nullptr, &ntree, &node, &sock, &layout); +} + static void node_socket_draw_nested(const bContext &C, bNodeTree &ntree, PointerRNA &node_ptr, @@ -1120,9 +1155,10 @@ static void node_socket_draw_nested(const bContext &C, const float size, const bool selected) { + const float2 location(sock.locx, sock.locy); + float color[4]; float outline_color[4]; - node_socket_color_get(C, ntree, node_ptr, sock, color); node_socket_outline_color_get(selected, sock.type, outline_color); @@ -1130,15 +1166,15 @@ static void node_socket_draw_nested(const bContext &C, color, outline_color, size, - sock.locx, - sock.locy, + location.x, + location.y, pos_id, col_id, shape_id, size_id, outline_col_id); - if (!node_socket_has_tooltip(&ntree, &sock)) { + if (!node_socket_has_tooltip(ntree, sock)) { return; } @@ -1150,8 +1186,8 @@ static void node_socket_draw_nested(const bContext &C, UI_BTYPE_BUT, 0, ICON_NONE, - sock.locx - size / 2, - sock.locy - size / 2, + location.x - size / 2.0f, + location.y - size / 2.0f, size, size, nullptr, @@ -1161,9 +1197,9 @@ static void node_socket_draw_nested(const bContext &C, 0, nullptr); - SocketTooltipData *data = (SocketTooltipData *)MEM_mallocN(sizeof(SocketTooltipData), __func__); + SocketTooltipData *data = MEM_new<SocketTooltipData>(__func__); data->ntree = &ntree; - data->node = (bNode *)node_ptr.data; + data->node = static_cast<const bNode *>(node_ptr.data); data->socket = &sock; UI_but_func_tooltip_set( @@ -1282,7 +1318,7 @@ static void node_draw_preview(bNodePreview *preview, rctf *prv) /* Premul graphics. */ GPU_blend(GPU_BLEND_ALPHA); - IMMDrawPixelsTexState state = immDrawPixelsTexSetup(GPU_SHADER_2D_IMAGE_COLOR); + IMMDrawPixelsTexState state = immDrawPixelsTexSetup(GPU_SHADER_3D_IMAGE_COLOR); immDrawPixelsTexTiled(&state, draw_rect.xmin, draw_rect.ymin, @@ -1298,14 +1334,14 @@ static void node_draw_preview(bNodePreview *preview, rctf *prv) GPU_blend(GPU_BLEND_NONE); uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); - immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); immUniformThemeColorShadeAlpha(TH_BACK, -15, +100); imm_draw_box_wire_2d(pos, draw_rect.xmin, draw_rect.ymin, draw_rect.xmax, draw_rect.ymax); immUnbindProgram(); } /* Common handle function for operator buttons that need to select the node first. */ -static void node_toggle_button_cb(struct bContext *C, void *node_argv, void *op_argv) +static void node_toggle_button_cb(bContext *C, void *node_argv, void *op_argv) { bNode *node = (bNode *)node_argv; const char *opname = (const char *)op_argv; @@ -1524,7 +1560,8 @@ static void node_draw_sockets(const View2D &v2d, node_socket_color_get(C, ntree, node_ptr, *socket, color); node_socket_outline_color_get(socket->flag & SELECT, socket->type, outline_color); - node_socket_draw_multi_input(color, outline_color, width, height, socket->locx, socket->locy); + const float2 location(socket->locx, socket->locy); + node_socket_draw_multi_input(color, outline_color, width, height, location); } } @@ -1598,27 +1635,26 @@ static char *node_errors_tooltip_fn(bContext *UNUSED(C), void *argN, const char #define NODE_HEADER_ICON_SIZE (0.8f * U.widget_unit) -static void node_add_error_message_button( - const bContext &C, bNode &node, uiBlock &block, const rctf &rect, float &icon_offset) +static void node_add_error_message_button(TreeDrawContext &tree_draw_ctx, + bNode &node, + uiBlock &block, + const rctf &rect, + float &icon_offset) { - SpaceNode *snode = CTX_wm_space_node(&C); - const geo_log::NodeLog *node_log = geo_log::ModifierLog::find_node_by_node_editor_context(*snode, - node); - if (node_log == nullptr) { - return; + Span<geo_log::NodeWarning> warnings; + if (tree_draw_ctx.geo_tree_log) { + geo_log::GeoNodeLog *node_log = tree_draw_ctx.geo_tree_log->nodes.lookup_ptr(node.name); + if (node_log != nullptr) { + warnings = node_log->warnings; + } } - - Span<geo_log::NodeWarning> warnings = node_log->warnings(); - if (warnings.is_empty()) { return; } - NodeErrorsTooltipData *tooltip_data = (NodeErrorsTooltipData *)MEM_mallocN( - sizeof(NodeErrorsTooltipData), __func__); - tooltip_data->warnings = warnings; - const geo_log::NodeWarningType display_type = node_error_highest_priority(warnings); + NodeErrorsTooltipData *tooltip_data = MEM_new<NodeErrorsTooltipData>(__func__); + tooltip_data->warnings = warnings; icon_offset -= NODE_HEADER_ICON_SIZE; UI_block_emboss_set(&block, UI_EMBOSS_NONE); @@ -1636,90 +1672,70 @@ static void node_add_error_message_button( 0, 0, nullptr); - UI_but_func_tooltip_set(but, node_errors_tooltip_fn, tooltip_data, MEM_freeN); + UI_but_func_tooltip_set(but, node_errors_tooltip_fn, tooltip_data, [](void *arg) { + MEM_delete(static_cast<NodeErrorsTooltipData *>(arg)); + }); UI_block_emboss_set(&block, UI_EMBOSS); } -static void get_exec_time_other_nodes(const bNode &node, - const SpaceNode &snode, - std::chrono::microseconds &exec_time, - int &node_count) +static std::optional<std::chrono::nanoseconds> node_get_execution_time( + TreeDrawContext &tree_draw_ctx, const bNodeTree &ntree, const bNode &node) { - if (node.type == NODE_GROUP) { - const geo_log::TreeLog *root_tree_log = geo_log::ModifierLog::find_tree_by_node_editor_context( - snode); - if (root_tree_log == nullptr) { - return; - } - const geo_log::TreeLog *tree_log = root_tree_log->lookup_child_log(node.name); - if (tree_log == nullptr) { - return; - } - tree_log->foreach_node_log([&](const geo_log::NodeLog &node_log) { - exec_time += node_log.execution_time(); - node_count++; - }); - } - else { - const geo_log::NodeLog *node_log = geo_log::ModifierLog::find_node_by_node_editor_context( - snode, node); - if (node_log) { - exec_time += node_log->execution_time(); - node_count++; - } + const geo_log::GeoTreeLog *tree_log = tree_draw_ctx.geo_tree_log; + if (tree_log == nullptr) { + return std::nullopt; } -} - -static std::chrono::microseconds node_get_execution_time(const bNodeTree &ntree, - const bNode &node, - const SpaceNode &snode, - int &node_count) -{ - std::chrono::microseconds exec_time = std::chrono::microseconds::zero(); if (node.type == NODE_GROUP_OUTPUT) { - const geo_log::TreeLog *tree_log = geo_log::ModifierLog::find_tree_by_node_editor_context( - snode); - - if (tree_log == nullptr) { - return exec_time; - } - tree_log->foreach_node_log([&](const geo_log::NodeLog &node_log) { - exec_time += node_log.execution_time(); - node_count++; - }); + return tree_log->run_time_sum; } - else if (node.type == NODE_FRAME) { + if (node.type == NODE_FRAME) { /* Could be cached in the future if this recursive code turns out to be slow. */ + std::chrono::nanoseconds run_time{0}; + bool found_node = false; LISTBASE_FOREACH (bNode *, tnode, &ntree.nodes) { if (tnode->parent != &node) { continue; } if (tnode->type == NODE_FRAME) { - exec_time += node_get_execution_time(ntree, *tnode, snode, node_count); + std::optional<std::chrono::nanoseconds> sub_frame_run_time = node_get_execution_time( + tree_draw_ctx, ntree, *tnode); + if (sub_frame_run_time.has_value()) { + run_time += *sub_frame_run_time; + found_node = true; + } } else { - get_exec_time_other_nodes(*tnode, snode, exec_time, node_count); + if (const geo_log::GeoNodeLog *node_log = tree_log->nodes.lookup_ptr_as(tnode->name)) { + found_node = true; + run_time += node_log->run_time; + } } } + if (found_node) { + return run_time; + } + return std::nullopt; } - else { - get_exec_time_other_nodes(node, snode, exec_time, node_count); + if (const geo_log::GeoNodeLog *node_log = tree_log->nodes.lookup_ptr(node.name)) { + return node_log->run_time; } - return exec_time; + return std::nullopt; } -static std::string node_get_execution_time_label(const SpaceNode &snode, const bNode &node) +static std::string node_get_execution_time_label(TreeDrawContext &tree_draw_ctx, + const SpaceNode &snode, + const bNode &node) { - int node_count = 0; - std::chrono::microseconds exec_time = node_get_execution_time( - *snode.edittree, node, snode, node_count); + const std::optional<std::chrono::nanoseconds> exec_time = node_get_execution_time( + tree_draw_ctx, *snode.edittree, node); - if (node_count == 0) { + if (!exec_time.has_value()) { return std::string(""); } - uint64_t exec_time_us = exec_time.count(); + const uint64_t exec_time_us = + std::chrono::duration_cast<std::chrono::microseconds>(*exec_time).count(); /* Don't show time if execution time is 0 microseconds. */ if (exec_time_us == 0) { @@ -1754,7 +1770,7 @@ struct NodeExtraInfoRow { }; struct NamedAttributeTooltipArg { - Map<std::string, eNamedAttrUsage> usage_by_attribute; + Map<StringRefNull, geo_log::NamedAttributeUsage> usage_by_attribute; }; static char *named_attribute_tooltip(bContext *UNUSED(C), void *argN, const char *UNUSED(tip)) @@ -1766,7 +1782,7 @@ static char *named_attribute_tooltip(bContext *UNUSED(C), void *argN, const char struct NameWithUsage { StringRefNull name; - eNamedAttrUsage usage; + geo_log::NamedAttributeUsage usage; }; Vector<NameWithUsage> sorted_used_attribute; @@ -1781,16 +1797,16 @@ static char *named_attribute_tooltip(bContext *UNUSED(C), void *argN, const char for (const NameWithUsage &attribute : sorted_used_attribute) { const StringRefNull name = attribute.name; - const eNamedAttrUsage usage = attribute.usage; + const geo_log::NamedAttributeUsage usage = attribute.usage; ss << " \u2022 \"" << name << "\": "; Vector<std::string> usages; - if ((usage & eNamedAttrUsage::Read) != eNamedAttrUsage::None) { + if ((usage & geo_log::NamedAttributeUsage::Read) != geo_log::NamedAttributeUsage::None) { usages.append(TIP_("read")); } - if ((usage & eNamedAttrUsage::Write) != eNamedAttrUsage::None) { + if ((usage & geo_log::NamedAttributeUsage::Write) != geo_log::NamedAttributeUsage::None) { usages.append(TIP_("write")); } - if ((usage & eNamedAttrUsage::Remove) != eNamedAttrUsage::None) { + if ((usage & geo_log::NamedAttributeUsage::Remove) != geo_log::NamedAttributeUsage::None) { usages.append(TIP_("remove")); } for (const int i : usages.index_range()) { @@ -1808,7 +1824,7 @@ static char *named_attribute_tooltip(bContext *UNUSED(C), void *argN, const char } static NodeExtraInfoRow row_from_used_named_attribute( - const Map<std::string, eNamedAttrUsage> &usage_by_attribute_name) + const Map<StringRefNull, geo_log::NamedAttributeUsage> &usage_by_attribute_name) { const int attributes_num = usage_by_attribute_name.size(); @@ -1822,32 +1838,11 @@ static NodeExtraInfoRow row_from_used_named_attribute( return row; } -static std::optional<NodeExtraInfoRow> node_get_accessed_attributes_row(const SpaceNode &snode, - const bNode &node) +static std::optional<NodeExtraInfoRow> node_get_accessed_attributes_row( + TreeDrawContext &tree_draw_ctx, const bNode &node) { - if (node.type == NODE_GROUP) { - const geo_log::TreeLog *root_tree_log = geo_log::ModifierLog::find_tree_by_node_editor_context( - snode); - if (root_tree_log == nullptr) { - return std::nullopt; - } - const geo_log::TreeLog *tree_log = root_tree_log->lookup_child_log(node.name); - if (tree_log == nullptr) { - return std::nullopt; - } - - Map<std::string, eNamedAttrUsage> usage_by_attribute; - tree_log->foreach_node_log([&](const geo_log::NodeLog &node_log) { - for (const geo_log::UsedNamedAttribute &used_attribute : node_log.used_named_attributes()) { - usage_by_attribute.lookup_or_add_as(used_attribute.name, - used_attribute.usage) |= used_attribute.usage; - } - }); - if (usage_by_attribute.is_empty()) { - return std::nullopt; - } - - return row_from_used_named_attribute(usage_by_attribute); + if (tree_draw_ctx.geo_tree_log == nullptr) { + return std::nullopt; } if (ELEM(node.type, GEO_NODE_STORE_NAMED_ATTRIBUTE, @@ -1856,31 +1851,26 @@ static std::optional<NodeExtraInfoRow> node_get_accessed_attributes_row(const Sp /* Only show the overlay when the name is passed in from somewhere else. */ LISTBASE_FOREACH (bNodeSocket *, socket, &node.inputs) { if (STREQ(socket->name, "Name")) { - if ((socket->flag & SOCK_IN_USE) == 0) { + if (!socket->is_directly_linked()) { return std::nullopt; } } } - const geo_log::NodeLog *node_log = geo_log::ModifierLog::find_node_by_node_editor_context( - snode, node.name); - if (node_log == nullptr) { - return std::nullopt; - } - Map<std::string, eNamedAttrUsage> usage_by_attribute; - for (const geo_log::UsedNamedAttribute &used_attribute : node_log->used_named_attributes()) { - usage_by_attribute.lookup_or_add_as(used_attribute.name, - used_attribute.usage) |= used_attribute.usage; - } - if (usage_by_attribute.is_empty()) { - return std::nullopt; - } - return row_from_used_named_attribute(usage_by_attribute); } - - return std::nullopt; + tree_draw_ctx.geo_tree_log->ensure_used_named_attributes(); + geo_log::GeoNodeLog *node_log = tree_draw_ctx.geo_tree_log->nodes.lookup_ptr(node.name); + if (node_log == nullptr) { + return std::nullopt; + } + if (node_log->used_named_attributes.is_empty()) { + return std::nullopt; + } + return row_from_used_named_attribute(node_log->used_named_attributes); } -static Vector<NodeExtraInfoRow> node_get_extra_info(const SpaceNode &snode, const bNode &node) +static Vector<NodeExtraInfoRow> node_get_extra_info(TreeDrawContext &tree_draw_ctx, + const SpaceNode &snode, + const bNode &node) { Vector<NodeExtraInfoRow> rows; if (!(snode.overlay.flag & SN_OVERLAY_SHOW_OVERLAYS)) { @@ -1889,7 +1879,8 @@ static Vector<NodeExtraInfoRow> node_get_extra_info(const SpaceNode &snode, cons if (snode.overlay.flag & SN_OVERLAY_SHOW_NAMED_ATTRIBUTES && snode.edittree->type == NTREE_GEOMETRY) { - if (std::optional<NodeExtraInfoRow> row = node_get_accessed_attributes_row(snode, node)) { + if (std::optional<NodeExtraInfoRow> row = node_get_accessed_attributes_row(tree_draw_ctx, + node)) { rows.append(std::move(*row)); } } @@ -1898,7 +1889,7 @@ static Vector<NodeExtraInfoRow> node_get_extra_info(const SpaceNode &snode, cons (ELEM(node.typeinfo->nclass, NODE_CLASS_GEOMETRY, NODE_CLASS_GROUP, NODE_CLASS_ATTRIBUTE) || ELEM(node.type, NODE_FRAME, NODE_GROUP_OUTPUT))) { NodeExtraInfoRow row; - row.text = node_get_execution_time_label(snode, node); + row.text = node_get_execution_time_label(tree_draw_ctx, snode, node); if (!row.text.empty()) { row.tooltip = TIP_( "The execution time from the node tree's latest evaluation. For frame and group nodes, " @@ -1907,14 +1898,17 @@ static Vector<NodeExtraInfoRow> node_get_extra_info(const SpaceNode &snode, cons rows.append(std::move(row)); } } - const geo_log::NodeLog *node_log = geo_log::ModifierLog::find_node_by_node_editor_context(snode, - node); - if (node_log != nullptr) { - for (const std::string &message : node_log->debug_messages()) { - NodeExtraInfoRow row; - row.text = message; - row.icon = ICON_INFO; - rows.append(std::move(row)); + + if (snode.edittree->type == NTREE_GEOMETRY && tree_draw_ctx.geo_tree_log != nullptr) { + tree_draw_ctx.geo_tree_log->ensure_debug_messages(); + const geo_log::GeoNodeLog *node_log = tree_draw_ctx.geo_tree_log->nodes.lookup_ptr(node.name); + if (node_log != nullptr) { + for (const StringRef message : node_log->debug_messages) { + NodeExtraInfoRow row; + row.text = message; + row.icon = ICON_INFO; + rows.append(std::move(row)); + } } } @@ -1979,9 +1973,12 @@ static void node_draw_extra_info_row(const bNode &node, } } -static void node_draw_extra_info_panel(const SpaceNode &snode, const bNode &node, uiBlock &block) +static void node_draw_extra_info_panel(TreeDrawContext &tree_draw_ctx, + const SpaceNode &snode, + const bNode &node, + uiBlock &block) { - Vector<NodeExtraInfoRow> extra_info_rows = node_get_extra_info(snode, node); + Vector<NodeExtraInfoRow> extra_info_rows = node_get_extra_info(tree_draw_ctx, snode, node); if (extra_info_rows.size() == 0) { return; @@ -2037,6 +2034,7 @@ static void node_draw_extra_info_panel(const SpaceNode &snode, const bNode &node } static void node_draw_basis(const bContext &C, + TreeDrawContext &tree_draw_ctx, const View2D &v2d, const SpaceNode &snode, bNodeTree &ntree, @@ -2061,7 +2059,7 @@ static void node_draw_basis(const bContext &C, GPU_line_width(1.0f); - node_draw_extra_info_panel(snode, node, block); + node_draw_extra_info_panel(tree_draw_ctx, snode, node, block); /* Header. */ { @@ -2156,7 +2154,7 @@ static void node_draw_basis(const bContext &C, UI_block_emboss_set(&block, UI_EMBOSS); } - node_add_error_message_button(C, node, block, rct, iconofs); + node_add_error_message_button(tree_draw_ctx, node, block, rct, iconofs); /* Title. */ if (node.flag & SELECT) { @@ -2261,6 +2259,7 @@ static void node_draw_basis(const bContext &C, if (node.flag & NODE_MUTED) { UI_GetThemeColor4fv(TH_WIRE, color_underline); + color_underline[3] = 1.0f; } else { UI_GetThemeColorBlend4f(TH_BACK, color_id, 0.2f, color_underline); @@ -2328,6 +2327,7 @@ static void node_draw_basis(const bContext &C, } static void node_draw_hidden(const bContext &C, + TreeDrawContext &tree_draw_ctx, const View2D &v2d, const SpaceNode &snode, bNodeTree &ntree, @@ -2343,7 +2343,7 @@ static void node_draw_hidden(const bContext &C, const int color_id = node_get_colorid(node); - node_draw_extra_info_panel(snode, node, block); + node_draw_extra_info_panel(tree_draw_ctx, snode, node, block); /* Shadow. */ node_draw_shadow(snode, node, hiddenrad, 1.0f); @@ -2468,7 +2468,7 @@ static void node_draw_hidden(const bContext &C, /* Scale widget thing. */ uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); GPU_blend(GPU_BLEND_ALPHA); - immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); immUniformThemeColorShadeAlpha(TH_TEXT, -40, -180); float dx = 0.5f * U.widget_unit; @@ -2641,13 +2641,13 @@ static void reroute_node_prepare_for_draw(bNode &node) const float2 loc = node_to_view(node, float2(0)); /* reroute node has exactly one input and one output, both in the same place */ - bNodeSocket *nsock = (bNodeSocket *)node.outputs.first; - nsock->locx = loc.x; - nsock->locy = loc.y; + bNodeSocket *socket = (bNodeSocket *)node.outputs.first; + socket->locx = loc.x; + socket->locy = loc.y; - nsock = (bNodeSocket *)node.inputs.first; - nsock->locx = loc.x; - nsock->locy = loc.y; + socket = (bNodeSocket *)node.inputs.first; + socket->locx = loc.x; + socket->locy = loc.y; const float size = 8.0f; node.width = size * 2; @@ -2658,6 +2658,7 @@ static void reroute_node_prepare_for_draw(bNode &node) } static void node_update_nodetree(const bContext &C, + TreeDrawContext &tree_draw_ctx, bNodeTree &ntree, Span<bNode *> nodes, Span<uiBlock *> blocks) @@ -2684,7 +2685,7 @@ static void node_update_nodetree(const bContext &C, node_update_hidden(node, block); } else { - node_update_basis(C, ntree, node, block); + node_update_basis(C, tree_draw_ctx, ntree, node, block); } } } @@ -2764,7 +2765,7 @@ static void frame_node_draw_label(const bNodeTree &ntree, BLF_wordwrap(fontid, line_width); LISTBASE_FOREACH (const TextLine *, line, &text->lines) { - struct ResultBLF info; + ResultBLF info; if (line->line[0]) { BLF_position(fontid, x, y, 0); BLF_draw_ex(fontid, line->line, line->len, &info); @@ -2785,6 +2786,7 @@ static void frame_node_draw_label(const bNodeTree &ntree, } static void frame_node_draw(const bContext &C, + TreeDrawContext &tree_draw_ctx, const ARegion ®ion, const SpaceNode &snode, bNodeTree &ntree, @@ -2831,7 +2833,7 @@ static void frame_node_draw(const bContext &C, /* label and text */ frame_node_draw_label(ntree, node, snode); - node_draw_extra_info_panel(snode, node, block); + node_draw_extra_info_panel(tree_draw_ctx, snode, node, block); UI_block_end(&C, &block); UI_block_draw(&C, &block); @@ -2885,6 +2887,7 @@ static void reroute_node_draw( } static void node_draw(const bContext &C, + TreeDrawContext &tree_draw_ctx, ARegion ®ion, const SpaceNode &snode, bNodeTree &ntree, @@ -2893,7 +2896,7 @@ static void node_draw(const bContext &C, bNodeInstanceKey key) { if (node.type == NODE_FRAME) { - frame_node_draw(C, region, snode, ntree, node, block); + frame_node_draw(C, tree_draw_ctx, region, snode, ntree, node, block); } else if (node.type == NODE_REROUTE) { reroute_node_draw(C, region, ntree, node, block); @@ -2901,10 +2904,10 @@ static void node_draw(const bContext &C, else { const View2D &v2d = region.v2d; if (node.flag & NODE_HIDDEN) { - node_draw_hidden(C, v2d, snode, ntree, node, block); + node_draw_hidden(C, tree_draw_ctx, v2d, snode, ntree, node, block); } else { - node_draw_basis(C, v2d, snode, ntree, node, block, key); + node_draw_basis(C, tree_draw_ctx, v2d, snode, ntree, node, block, key); } } } @@ -2912,6 +2915,7 @@ static void node_draw(const bContext &C, #define USE_DRAW_TOT_UPDATE static void node_draw_nodetree(const bContext &C, + TreeDrawContext &tree_draw_ctx, ARegion ®ion, SpaceNode &snode, bNodeTree &ntree, @@ -2936,7 +2940,7 @@ static void node_draw_nodetree(const bContext &C, } bNodeInstanceKey key = BKE_node_instance_key(parent_key, &ntree, nodes[i]); - node_draw(C, region, snode, ntree, *nodes[i], *blocks[i], key); + node_draw(C, tree_draw_ctx, region, snode, ntree, *nodes[i], *blocks[i], key); } /* Node lines. */ @@ -2966,7 +2970,7 @@ static void node_draw_nodetree(const bContext &C, } bNodeInstanceKey key = BKE_node_instance_key(parent_key, &ntree, nodes[i]); - node_draw(C, region, snode, ntree, *nodes[i], *blocks[i], key); + node_draw(C, tree_draw_ctx, region, snode, ntree, *nodes[i], *blocks[i], key); } } @@ -3019,13 +3023,23 @@ static void draw_nodetree(const bContext &C, bNodeInstanceKey parent_key) { SpaceNode *snode = CTX_wm_space_node(&C); + ntree.ensure_topology_cache(); - Vector<bNode *> nodes = ntree.nodes; + Span<bNode *> nodes = ntree.all_nodes(); Array<uiBlock *> blocks = node_uiblocks_init(C, nodes); - node_update_nodetree(C, ntree, nodes, blocks); - node_draw_nodetree(C, region, *snode, ntree, nodes, blocks, parent_key); + TreeDrawContext tree_draw_ctx; + if (ntree.type == NTREE_GEOMETRY) { + tree_draw_ctx.geo_tree_log = geo_log::GeoModifierLog::get_tree_log_for_node_editor(*snode); + if (tree_draw_ctx.geo_tree_log != nullptr) { + tree_draw_ctx.geo_tree_log->ensure_node_warnings(); + tree_draw_ctx.geo_tree_log->ensure_node_run_time(); + } + } + + node_update_nodetree(C, tree_draw_ctx, ntree, nodes, blocks); + node_draw_nodetree(C, tree_draw_ctx, region, *snode, ntree, nodes, blocks, parent_key); } /** @@ -3100,8 +3114,8 @@ void node_draw_space(const bContext &C, ARegion ®ion) } /* Current View2D center, will be set temporarily for parent node trees. */ - float center[2]; - UI_view2d_center_get(&v2d, ¢er[0], ¢er[1]); + float2 center; + UI_view2d_center_get(&v2d, ¢er.x, ¢er.y); /* Store new view center in path and current edit tree. */ copy_v2_v2(path->view_center, center); @@ -3140,7 +3154,7 @@ void node_draw_space(const bContext &C, ARegion ®ion) GPU_line_smooth(true); if (snode.runtime->linkdrag) { for (const bNodeLink *link : snode.runtime->linkdrag->links) { - node_draw_link(C, v2d, snode, *link, true); + node_draw_link_dragged(C, v2d, snode, *link); } } GPU_line_smooth(false); diff --git a/source/blender/editors/space_node/node_edit.cc b/source/blender/editors/space_node/node_edit.cc index 0b1f2037292..31d99eafbc1 100644 --- a/source/blender/editors/space_node/node_edit.cc +++ b/source/blender/editors/space_node/node_edit.cc @@ -29,6 +29,8 @@ #include "BKE_scene.h" #include "BKE_workspace.h" +#include "BLT_translation.h" + #include "DEG_depsgraph.h" #include "DEG_depsgraph_build.h" #include "DEG_depsgraph_query.h" @@ -107,8 +109,7 @@ float2 node_link_calculate_multi_input_position(const float2 &socket_position, { const float offset = (total_inputs * NODE_MULTI_INPUT_LINK_GAP - NODE_MULTI_INPUT_LINK_GAP) * 0.5f; - return {socket_position.x - NODE_SOCKSIZE * 0.5f, - socket_position.y - offset + index * NODE_MULTI_INPUT_LINK_GAP}; + return {socket_position.x, socket_position.y - offset + index * NODE_MULTI_INPUT_LINK_GAP}; } static void compo_tag_output_nodes(bNodeTree *nodetree, int recalc_flags) @@ -319,7 +320,7 @@ static void compo_completejob(void *cjv) /** \name Composite Job C API * \{ */ -void ED_node_composite_job(const bContext *C, struct bNodeTree *nodetree, Scene *scene_owner) +void ED_node_composite_job(const bContext *C, bNodeTree *nodetree, Scene *scene_owner) { using namespace blender::ed::space_node; @@ -463,22 +464,22 @@ void ED_node_set_tree_type(SpaceNode *snode, bNodeTreeType *typeinfo) } } -bool ED_node_is_compositor(struct SpaceNode *snode) +bool ED_node_is_compositor(SpaceNode *snode) { return STREQ(snode->tree_idname, ntreeType_Composite->idname); } -bool ED_node_is_shader(struct SpaceNode *snode) +bool ED_node_is_shader(SpaceNode *snode) { return STREQ(snode->tree_idname, ntreeType_Shader->idname); } -bool ED_node_is_texture(struct SpaceNode *snode) +bool ED_node_is_texture(SpaceNode *snode) { return STREQ(snode->tree_idname, ntreeType_Texture->idname); } -bool ED_node_is_geometry(struct SpaceNode *snode) +bool ED_node_is_geometry(SpaceNode *snode) { return STREQ(snode->tree_idname, ntreeType_Geometry->idname); } @@ -505,12 +506,12 @@ void ED_node_shader_default(const bContext *C, ID *id) } else if (ELEM(GS(id->name), ID_WO, ID_LA)) { /* Emission */ - bNodeTree *ntree = ntreeAddTree(nullptr, "Shader Nodetree", ntreeType_Shader->idname); + bNodeTree *ntree = ntreeAddTreeEmbedded( + nullptr, id, "Shader Nodetree", ntreeType_Shader->idname); bNode *shader, *output; if (GS(id->name) == ID_WO) { World *world = (World *)id; - world->nodetree = ntree; shader = nodeAddStaticNode(nullptr, ntree, SH_NODE_BACKGROUND); output = nodeAddStaticNode(nullptr, ntree, SH_NODE_OUTPUT_WORLD); @@ -524,9 +525,6 @@ void ED_node_shader_default(const bContext *C, ID *id) copy_v3_v3(((bNodeSocketValueRGBA *)color_sock->default_value)->value, &world->horr); } else { - Light *light = (Light *)id; - light->nodetree = ntree; - shader = nodeAddStaticNode(nullptr, ntree, SH_NODE_EMISSION); output = nodeAddStaticNode(nullptr, ntree, SH_NODE_OUTPUT_LIGHT); nodeAddLink(ntree, @@ -549,7 +547,7 @@ void ED_node_shader_default(const bContext *C, ID *id) } } -void ED_node_composit_default(const bContext *C, struct Scene *sce) +void ED_node_composit_default(const bContext *C, Scene *sce) { /* but lets check it anyway */ if (sce->nodetree) { @@ -559,7 +557,8 @@ void ED_node_composit_default(const bContext *C, struct Scene *sce) return; } - sce->nodetree = ntreeAddTree(nullptr, "Compositing Nodetree", ntreeType_Composite->idname); + sce->nodetree = ntreeAddTreeEmbedded( + nullptr, &sce->id, "Compositing Nodetree", ntreeType_Composite->idname); sce->nodetree->chunksize = 256; sce->nodetree->edit_quality = NTREE_QUALITY_HIGH; @@ -592,7 +591,8 @@ void ED_node_texture_default(const bContext *C, Tex *tex) return; } - tex->nodetree = ntreeAddTree(nullptr, "Texture Nodetree", ntreeType_Texture->idname); + tex->nodetree = ntreeAddTreeEmbedded( + nullptr, &tex->id, "Texture Nodetree", ntreeType_Texture->idname); bNode *out = nodeAddStaticNode(C, tex->nodetree, TEX_NODE_OUTPUT); out->locx = 300.0f; @@ -713,10 +713,12 @@ void ED_node_set_active( /* Sync to active texpaint slot, otherwise we can end up painting on a different slot * than we are looking at. */ if (ma->texpaintslot) { - Image *image = (Image *)node->id; - for (int i = 0; i < ma->tot_slots; i++) { - if (ma->texpaintslot[i].ima == image) { - ma->paint_active_slot = i; + if (node->id != nullptr && GS(node->id->name) == ID_IM) { + Image *image = (Image *)node->id; + for (int i = 0; i < ma->tot_slots; i++) { + if (ma->texpaintslot[i].ima == image) { + ma->paint_active_slot = i; + } } } } @@ -729,18 +731,28 @@ void ED_node_set_active( } } - /* Sync to Image Editor. */ - Image *image = (Image *)node->id; - wmWindowManager *wm = (wmWindowManager *)bmain->wm.first; - LISTBASE_FOREACH (wmWindow *, win, &wm->windows) { - const bScreen *screen = WM_window_get_active_screen(win); - LISTBASE_FOREACH (ScrArea *, area, &screen->areabase) { - LISTBASE_FOREACH (SpaceLink *, sl, &area->spacedata) { - if (sl->spacetype == SPACE_IMAGE) { + /* Sync to Image Editor under the following conditions: + * - current image is not pinned + * - current image is not a Render Result or ViewerNode (want to keep looking at these) */ + if (node->id != nullptr && GS(node->id->name) == ID_IM) { + Image *image = (Image *)node->id; + wmWindowManager *wm = (wmWindowManager *)bmain->wm.first; + LISTBASE_FOREACH (wmWindow *, win, &wm->windows) { + const bScreen *screen = WM_window_get_active_screen(win); + LISTBASE_FOREACH (ScrArea *, area, &screen->areabase) { + LISTBASE_FOREACH (SpaceLink *, sl, &area->spacedata) { + if (sl->spacetype != SPACE_IMAGE) { + continue; + } SpaceImage *sima = (SpaceImage *)sl; - if (!sima->pin) { - ED_space_image_set(bmain, sima, image, true); + if (sima->pin) { + continue; } + if (sima->image && + ELEM(sima->image->type, IMA_TYPE_R_RESULT, IMA_TYPE_COMPOSITE)) { + continue; + } + ED_space_image_set(bmain, sima, image, true); } } } @@ -913,15 +925,24 @@ static void edit_node_properties_get( /** \name Node Generic * \{ */ -/* is rct in visible part of node? */ -static bNode *visible_node(SpaceNode &snode, const rctf &rct) +static bool socket_is_occluded(const float2 &location, + const bNode &node_the_socket_belongs_to, + const SpaceNode &snode) { LISTBASE_FOREACH_BACKWARD (bNode *, node, &snode.edittree->nodes) { - if (BLI_rctf_isect(&node->totr, &rct, nullptr)) { - return node; + if (node == &node_the_socket_belongs_to) { + /* Nodes after this one are underneath and can't occlude the socket. */ + return false; + } + + rctf socket_hitbox; + const float socket_hitbox_radius = NODE_SOCKSIZE - 0.1f * U.widget_unit; + BLI_rctf_init_pt_radius(&socket_hitbox, location, socket_hitbox_radius); + if (BLI_rctf_inside_rctf(&node->totr, &socket_hitbox)) { + return true; } } - return nullptr; + return false; } /** \} */ @@ -939,14 +960,14 @@ struct NodeSizeWidget { }; static void node_resize_init( - bContext *C, wmOperator *op, const float cursor[2], const bNode *node, NodeResizeDirection dir) + bContext *C, wmOperator *op, const float2 &cursor, const bNode *node, NodeResizeDirection dir) { NodeSizeWidget *nsw = MEM_cnew<NodeSizeWidget>(__func__); op->customdata = nsw; - nsw->mxstart = cursor[0]; - nsw->mystart = cursor[1]; + nsw->mxstart = cursor.x; + nsw->mystart = cursor.y; /* store old */ nsw->oldlocx = node->locx; @@ -993,12 +1014,12 @@ static int node_resize_modal(bContext *C, wmOperator *op, const wmEvent *event) switch (event->type) { case MOUSEMOVE: { - int mval[2]; + int2 mval; WM_event_drag_start_mval(event, region, mval); float mx, my; - UI_view2d_region_to_view(®ion->v2d, mval[0], mval[1], &mx, &my); - float dx = (mx - nsw->mxstart) / UI_DPI_FAC; - float dy = (my - nsw->mystart) / UI_DPI_FAC; + UI_view2d_region_to_view(®ion->v2d, mval.x, mval.y, &mx, &my); + const float dx = (mx - nsw->mxstart) / UI_DPI_FAC; + const float dy = (my - nsw->mystart) / UI_DPI_FAC; if (node) { float *pwidth = &node->width; @@ -1100,11 +1121,11 @@ static int node_resize_invoke(bContext *C, wmOperator *op, const wmEvent *event) } /* convert mouse coordinates to v2d space */ - float cursor[2]; - int mval[2]; + float2 cursor; + int2 mval; WM_event_drag_start_mval(event, region, mval); - UI_view2d_region_to_view(®ion->v2d, mval[0], mval[1], &cursor[0], &cursor[1]); - const NodeResizeDirection dir = node_get_resize_direction(node, cursor[0], cursor[1]); + UI_view2d_region_to_view(®ion->v2d, mval.x, mval.y, &cursor.x, &cursor.y); + const NodeResizeDirection dir = node_get_resize_direction(node, cursor.x, cursor.y); if (dir == NODE_RESIZE_NONE) { return OPERATOR_CANCELLED | OPERATOR_PASS_THROUGH; } @@ -1182,21 +1203,22 @@ void node_set_hidden_sockets(SpaceNode *snode, bNode *node, int set) } /* checks snode->mouse position, and returns found node/socket */ -static bool cursor_isect_multi_input_socket(const float cursor[2], const bNodeSocket &socket) +static bool cursor_isect_multi_input_socket(const float2 &cursor, const bNodeSocket &socket) { const float node_socket_height = node_socket_calculate_height(socket); - rctf multi_socket_rect; + const float2 location(socket.locx, socket.locy); /* `.xmax = socket->locx + NODE_SOCKSIZE * 5.5f` * would be the same behavior as for regular sockets. * But keep it smaller because for multi-input socket you * sometimes want to drag the link to the other side, if you may * accidentally pick the wrong link otherwise. */ + rctf multi_socket_rect; BLI_rctf_init(&multi_socket_rect, - socket.locx - NODE_SOCKSIZE * 4.0f, - socket.locx + NODE_SOCKSIZE * 2.0f, - socket.locy - node_socket_height, - socket.locy + node_socket_height); - if (BLI_rctf_isect_pt(&multi_socket_rect, cursor[0], cursor[1])) { + location.x - NODE_SOCKSIZE * 4.0f, + location.x + NODE_SOCKSIZE * 2.0f, + location.y - node_socket_height, + location.y + node_socket_height); + if (BLI_rctf_isect_pt(&multi_socket_rect, cursor.x, cursor.y)) { return true; } return false; @@ -1216,10 +1238,8 @@ bool node_find_indicated_socket(SpaceNode &snode, *sockp = nullptr; /* check if we click in a socket */ - LISTBASE_FOREACH (bNode *, node, &snode.edittree->nodes) { + LISTBASE_FOREACH_BACKWARD (bNode *, node, &snode.edittree->nodes) { BLI_rctf_init_pt_radius(&rect, cursor, size_sock_padded); - rctf node_visible; - BLI_rctf_init_pt_radius(&node_visible, cursor, size_sock_padded); if (!(node->flag & NODE_HIDDEN)) { /* extra padding inside and out - allow dragging on the text areas too */ @@ -1236,17 +1256,18 @@ bool node_find_indicated_socket(SpaceNode &snode, if (in_out & SOCK_IN) { LISTBASE_FOREACH (bNodeSocket *, sock, &node->inputs) { if (!nodeSocketIsHidden(sock)) { + const float2 location(sock->locx, sock->locy); if (sock->flag & SOCK_MULTI_INPUT && !(node->flag & NODE_HIDDEN)) { if (cursor_isect_multi_input_socket(cursor, *sock)) { - if (node == visible_node(snode, node_visible)) { + if (!socket_is_occluded(location, *node, snode)) { *nodep = node; *sockp = sock; return true; } } } - else if (BLI_rctf_isect_pt(&rect, sock->locx, sock->locy)) { - if (node == visible_node(snode, node_visible)) { + else if (BLI_rctf_isect_pt(&rect, location.x, location.y)) { + if (!socket_is_occluded(location, *node, snode)) { *nodep = node; *sockp = sock; return true; @@ -1258,8 +1279,9 @@ bool node_find_indicated_socket(SpaceNode &snode, if (in_out & SOCK_OUT) { LISTBASE_FOREACH (bNodeSocket *, sock, &node->outputs) { if (!nodeSocketIsHidden(sock)) { - if (BLI_rctf_isect_pt(&rect, sock->locx, sock->locy)) { - if (node == visible_node(snode, node_visible)) { + const float2 location(sock->locx, sock->locy); + if (BLI_rctf_isect_pt(&rect, location.x, location.y)) { + if (!socket_is_occluded(location, *node, snode)) { *nodep = node; *sockp = sock; return true; @@ -1285,11 +1307,12 @@ float node_link_dim_factor(const View2D &v2d, const bNodeLink &link) return 1.0f; } + const float2 from(link.fromsock->locx, link.fromsock->locy); + const float2 to(link.tosock->locx, link.tosock->locy); + const float min_endpoint_distance = std::min( - std::max(BLI_rctf_length_x(&v2d.cur, link.fromsock->locx), - BLI_rctf_length_y(&v2d.cur, link.fromsock->locy)), - std::max(BLI_rctf_length_x(&v2d.cur, link.tosock->locx), - BLI_rctf_length_y(&v2d.cur, link.tosock->locy))); + std::max(BLI_rctf_length_x(&v2d.cur, from.x), BLI_rctf_length_y(&v2d.cur, from.y)), + std::max(BLI_rctf_length_x(&v2d.cur, to.x), BLI_rctf_length_y(&v2d.cur, to.y))); if (min_endpoint_distance == 0.0f) { return 1.0f; @@ -1348,7 +1371,7 @@ static int node_duplicate_exec(bContext *C, wmOperator *op) bNode *lastnode = (bNode *)ntree->nodes.last; LISTBASE_FOREACH (bNode *, node, &ntree->nodes) { if (node->flag & SELECT) { - bNode *new_node = blender::bke::node_copy_with_mapping( + bNode *new_node = bke::node_copy_with_mapping( ntree, *node, LIB_ID_COPY_DEFAULT, true, socket_map); node_map.add_new(node, new_node); changed = true; @@ -1455,43 +1478,6 @@ void NODE_OT_duplicate(wmOperatorType *ot) ot->srna, "keep_inputs", false, "Keep Inputs", "Keep the input links to duplicated nodes"); } -static bool node_select_check(const ListBase *lb) -{ - LISTBASE_FOREACH (const bNode *, node, lb) { - if (node->flag & NODE_SELECT) { - return true; - } - } - - return false; -} - -void node_select_all(ListBase *lb, int action) -{ - if (action == SEL_TOGGLE) { - if (node_select_check(lb)) { - action = SEL_DESELECT; - } - else { - action = SEL_SELECT; - } - } - - LISTBASE_FOREACH (bNode *, node, lb) { - switch (action) { - case SEL_SELECT: - nodeSetSelected(node, true); - break; - case SEL_DESELECT: - nodeSetSelected(node, false); - break; - case SEL_INVERT: - nodeSetSelected(node, !(node->flag & SELECT)); - break; - } - } -} - /* XXX: some code needing updating to operators. */ /* goes over all scenes, reads render layers */ @@ -2153,24 +2139,23 @@ static int node_copy_color_exec(bContext *C, wmOperator *UNUSED(op)) SpaceNode &snode = *CTX_wm_space_node(C); bNodeTree &ntree = *snode.edittree; - bNode *node = nodeGetActive(&ntree); - if (!node) { + bNode *active_node = nodeGetActive(&ntree); + if (!active_node) { return OPERATOR_CANCELLED; } - LISTBASE_FOREACH (bNode *, node_iter, &ntree.nodes) { - if (node_iter->flag & NODE_SELECT && node_iter != node) { - if (node->flag & NODE_CUSTOM_COLOR) { - node_iter->flag |= NODE_CUSTOM_COLOR; - copy_v3_v3(node_iter->color, node->color); + LISTBASE_FOREACH (bNode *, node, &ntree.nodes) { + if (node->flag & NODE_SELECT && node != active_node) { + if (active_node->flag & NODE_CUSTOM_COLOR) { + node->flag |= NODE_CUSTOM_COLOR; + copy_v3_v3(node->color, active_node->color); } else { - node_iter->flag &= ~NODE_CUSTOM_COLOR; + node->flag &= ~NODE_CUSTOM_COLOR; } } } - node_sort(ntree); WM_event_add_notifier(C, NC_NODE | ND_DISPLAY, nullptr); return OPERATOR_FINISHED; @@ -2215,12 +2200,12 @@ static int node_clipboard_copy_exec(bContext *C, wmOperator *UNUSED(op)) if (node->flag & SELECT) { /* No ID refcounting, this node is virtual, * detached from any actual Blender data currently. */ - bNode *new_node = blender::bke::node_copy_with_mapping(nullptr, - *node, - LIB_ID_CREATE_NO_USER_REFCOUNT | - LIB_ID_CREATE_NO_MAIN, - false, - socket_map); + bNode *new_node = bke::node_copy_with_mapping(nullptr, + *node, + LIB_ID_CREATE_NO_USER_REFCOUNT | + LIB_ID_CREATE_NO_MAIN, + false, + socket_map); node_map.add_new(node, new_node); } } @@ -2340,11 +2325,11 @@ static int node_clipboard_paste_exec(bContext *C, wmOperator *op) node_deselect_all(*snode); /* calculate "barycenter" for placing on mouse cursor */ - float center[2] = {0.0f, 0.0f}; + float2 center = {0.0f, 0.0f}; int num_nodes = 0; LISTBASE_FOREACH_INDEX (bNode *, node, clipboard_nodes_lb, num_nodes) { - center[0] += BLI_rctf_cent_x(&node->totr); - center[1] += BLI_rctf_cent_y(&node->totr); + center.x += BLI_rctf_cent_x(&node->totr); + center.y += BLI_rctf_cent_y(&node->totr); } mul_v2_fl(center, 1.0 / num_nodes); @@ -2353,7 +2338,7 @@ static int node_clipboard_paste_exec(bContext *C, wmOperator *op) /* copy nodes from clipboard */ LISTBASE_FOREACH (bNode *, node, clipboard_nodes_lb) { - bNode *new_node = blender::bke::node_copy_with_mapping( + bNode *new_node = bke::node_copy_with_mapping( ntree, *node, LIB_ID_COPY_DEFAULT, true, socket_map); node_map.add_new(node, new_node); } @@ -2428,7 +2413,7 @@ static int ntree_socket_add_exec(bContext *C, wmOperator *op) const eNodeSocketInOut in_out = (eNodeSocketInOut)RNA_enum_get(op->ptr, "in_out"); ListBase *sockets = (in_out == SOCK_IN) ? &ntree->inputs : &ntree->outputs; - const char *default_name = (in_out == SOCK_IN) ? "Input" : "Output"; + const char *default_name = (in_out == SOCK_IN) ? DATA_("Input") : DATA_("Output"); bNodeSocket *active_sock = ntree_get_active_interface_socket(sockets); bNodeSocket *sock; @@ -2552,7 +2537,7 @@ static int ntree_socket_change_type_exec(bContext *C, wmOperator *op) return OPERATOR_FINISHED; } - /* Don't handle subtypes for now. */ + /* Don't handle sub-types for now. */ nodeModifySocketType(ntree, nullptr, iosock, socket_type->idname); /* Need the extra update here because the loop above does not check for valid links in the node diff --git a/source/blender/editors/space_node/node_geometry_attribute_search.cc b/source/blender/editors/space_node/node_geometry_attribute_search.cc index e328a86b0fd..809c4b2fe59 100644 --- a/source/blender/editors/space_node/node_geometry_attribute_search.cc +++ b/source/blender/editors/space_node/node_geometry_attribute_search.cc @@ -14,6 +14,7 @@ #include "DNA_space_types.h" #include "BKE_context.h" +#include "BKE_node_runtime.hh" #include "BKE_node_tree_update.h" #include "BKE_object.h" @@ -30,12 +31,11 @@ #include "UI_interface.hh" #include "UI_resources.h" -#include "NOD_geometry_nodes_eval_log.hh" +#include "NOD_geometry_nodes_log.hh" #include "node_intern.hh" -namespace geo_log = blender::nodes::geometry_nodes_eval_log; -using geo_log::GeometryAttributeInfo; +using blender::nodes::geo_eval_log::GeometryAttributeInfo; namespace blender::ed::space_node { @@ -50,6 +50,8 @@ BLI_STATIC_ASSERT(std::is_trivially_destructible_v<AttributeSearchData>, ""); static Vector<const GeometryAttributeInfo *> get_attribute_info_from_context( const bContext &C, AttributeSearchData &data) { + using namespace nodes::geo_eval_log; + SpaceNode *snode = CTX_wm_space_node(&C); if (!snode) { BLI_assert_unreachable(); @@ -65,41 +67,48 @@ static Vector<const GeometryAttributeInfo *> get_attribute_info_from_context( BLI_assert_unreachable(); return {}; } + GeoTreeLog *tree_log = GeoModifierLog::get_tree_log_for_node_editor(*snode); + if (tree_log == nullptr) { + return {}; + } + tree_log->ensure_socket_values(); /* For the attribute input node, collect attribute information from all nodes in the group. */ if (node->type == GEO_NODE_INPUT_NAMED_ATTRIBUTE) { - const geo_log::TreeLog *tree_log = geo_log::ModifierLog::find_tree_by_node_editor_context( - *snode); - if (tree_log == nullptr) { - return {}; - } - + tree_log->ensure_existing_attributes(); Vector<const GeometryAttributeInfo *> attributes; - Set<StringRef> names; - tree_log->foreach_node_log([&](const geo_log::NodeLog &node_log) { - for (const geo_log::SocketLog &socket_log : node_log.input_logs()) { - const geo_log::ValueLog *value_log = socket_log.value(); - if (const geo_log::GeometryValueLog *geo_value_log = - dynamic_cast<const geo_log::GeometryValueLog *>(value_log)) { - for (const GeometryAttributeInfo &attribute : geo_value_log->attributes()) { - if (bke::allow_procedural_attribute_access(attribute.name)) { - if (names.add(attribute.name)) { - attributes.append(&attribute); - } - } - } - } + for (const GeometryAttributeInfo *attribute : tree_log->existing_attributes) { + if (bke::allow_procedural_attribute_access(attribute->name)) { + attributes.append(attribute); } - }); + } return attributes; } - - const geo_log::NodeLog *node_log = geo_log::ModifierLog::find_node_by_node_editor_context( - *snode, data.node_name); + GeoNodeLog *node_log = tree_log->nodes.lookup_ptr(node->name); if (node_log == nullptr) { return {}; } - return node_log->lookup_available_attributes(); + Set<StringRef> names; + Vector<const GeometryAttributeInfo *> attributes; + for (const bNodeSocket *input_socket : node->input_sockets()) { + if (input_socket->type != SOCK_GEOMETRY) { + continue; + } + const ValueLog *value_log = tree_log->find_socket_value_log(*input_socket); + if (value_log == nullptr) { + continue; + } + if (const GeometryInfoLog *geo_log = dynamic_cast<const GeometryInfoLog *>(value_log)) { + for (const GeometryAttributeInfo &attribute : geo_log->attributes) { + if (bke::allow_procedural_attribute_access(attribute.name)) { + if (names.add(attribute.name)) { + attributes.append(&attribute); + } + } + } + } + } + return attributes; } static void attribute_search_update_fn( diff --git a/source/blender/editors/space_node/node_gizmo.cc b/source/blender/editors/space_node/node_gizmo.cc index 4f27f9baabc..f9126556b71 100644 --- a/source/blender/editors/space_node/node_gizmo.cc +++ b/source/blender/editors/space_node/node_gizmo.cc @@ -49,14 +49,14 @@ static void node_gizmo_calc_matrix_space(const SpaceNode *snode, static void node_gizmo_calc_matrix_space_with_image_dims(const SpaceNode *snode, const ARegion *region, - const float image_dims[2], + const float2 &image_dims, float matrix_space[4][4]) { unit_m4(matrix_space); - mul_v3_fl(matrix_space[0], snode->zoom * image_dims[0]); - mul_v3_fl(matrix_space[1], snode->zoom * image_dims[1]); - matrix_space[3][0] = ((region->winx / 2) + snode->xof) - ((image_dims[0] / 2.0f) * snode->zoom); - matrix_space[3][1] = ((region->winy / 2) + snode->yof) - ((image_dims[1] / 2.0f) * snode->zoom); + mul_v3_fl(matrix_space[0], snode->zoom * image_dims.x); + mul_v3_fl(matrix_space[1], snode->zoom * image_dims.y); + matrix_space[3][0] = ((region->winx / 2) + snode->xof) - ((image_dims.x / 2.0f) * snode->zoom); + matrix_space[3][1] = ((region->winy / 2) + snode->yof) - ((image_dims.y / 2.0f) * snode->zoom); } /** \} */ @@ -135,7 +135,7 @@ static void WIDGETGROUP_node_transform_refresh(const bContext *C, wmGizmoGroup * ImBuf *ibuf = BKE_image_acquire_ibuf(ima, nullptr, &lock); if (ibuf) { - const float dims[2] = { + const float2 dims = { (ibuf->x > 0) ? ibuf->x : 64.0f, (ibuf->y > 0) ? ibuf->y : 64.0f, }; @@ -190,7 +190,7 @@ struct NodeCropWidgetGroup { wmGizmo *border; struct { - float dims[2]; + float2 dims; } state; struct { @@ -206,10 +206,7 @@ static void gizmo_node_crop_update(struct NodeCropWidgetGroup *crop_group) crop_group->update_data.context, &crop_group->update_data.ptr, crop_group->update_data.prop); } -static void two_xy_to_rect(const NodeTwoXYs *nxy, - rctf *rect, - const float dims[2], - bool is_relative) +static void two_xy_to_rect(const NodeTwoXYs *nxy, rctf *rect, const float2 &dims, bool is_relative) { if (is_relative) { rect->xmin = nxy->fac_x1; @@ -218,16 +215,16 @@ static void two_xy_to_rect(const NodeTwoXYs *nxy, rect->ymax = nxy->fac_y2; } else { - rect->xmin = nxy->x1 / dims[0]; - rect->xmax = nxy->x2 / dims[0]; - rect->ymin = nxy->y1 / dims[1]; - rect->ymax = nxy->y2 / dims[1]; + rect->xmin = nxy->x1 / dims.x; + rect->xmax = nxy->x2 / dims.x; + rect->ymin = nxy->y1 / dims.y; + rect->ymax = nxy->y2 / dims.y; } } static void two_xy_from_rect(NodeTwoXYs *nxy, const rctf *rect, - const float dims[2], + const float2 &dims, bool is_relative) { if (is_relative) { @@ -237,10 +234,10 @@ static void two_xy_from_rect(NodeTwoXYs *nxy, nxy->fac_y2 = rect->ymax; } else { - nxy->x1 = rect->xmin * dims[0]; - nxy->x2 = rect->xmax * dims[0]; - nxy->y1 = rect->ymin * dims[1]; - nxy->y2 = rect->ymax * dims[1]; + nxy->x1 = rect->xmin * dims.x; + nxy->x2 = rect->xmax * dims.x; + nxy->y1 = rect->ymin * dims.y; + nxy->y2 = rect->ymax * dims.y; } } @@ -321,9 +318,7 @@ static bool WIDGETGROUP_node_crop_poll(const bContext *C, wmGizmoGroupType *UNUS static void WIDGETGROUP_node_crop_setup(const bContext *UNUSED(C), wmGizmoGroup *gzgroup) { - struct NodeCropWidgetGroup *crop_group = (NodeCropWidgetGroup *)MEM_mallocN( - sizeof(struct NodeCropWidgetGroup), __func__); - + NodeCropWidgetGroup *crop_group = MEM_new<NodeCropWidgetGroup>(__func__); crop_group->border = WM_gizmo_new("GIZMO_GT_cage_2d", gzgroup, nullptr); RNA_enum_set(crop_group->border->ptr, @@ -407,7 +402,7 @@ struct NodeSunBeamsWidgetGroup { wmGizmo *gizmo; struct { - float dims[2]; + float2 dims; } state; }; @@ -512,7 +507,7 @@ struct NodeCornerPinWidgetGroup { wmGizmo *gizmos[4]; struct { - float dims[2]; + float2 dims; } state; }; diff --git a/source/blender/editors/space_node/node_group.cc b/source/blender/editors/space_node/node_group.cc index bb520c0537e..21def1bd9d7 100644 --- a/source/blender/editors/space_node/node_group.cc +++ b/source/blender/editors/space_node/node_group.cc @@ -25,6 +25,7 @@ #include "BKE_context.h" #include "BKE_lib_id.h" #include "BKE_main.h" +#include "BKE_node_runtime.hh" #include "BKE_node_tree_update.h" #include "BKE_report.h" @@ -462,8 +463,7 @@ static bool node_group_separate_selected( bNode *newnode; if (make_copy) { /* make a copy */ - newnode = blender::bke::node_copy_with_mapping( - &ngroup, *node, LIB_ID_COPY_DEFAULT, true, socket_map); + newnode = bke::node_copy_with_mapping(&ngroup, *node, LIB_ID_COPY_DEFAULT, true, socket_map); node_map.add_new(node, newnode); } else { @@ -653,7 +653,7 @@ static bool node_group_make_use_node(bNode &node, bNode *gnode) static bool node_group_make_test_selected(bNodeTree &ntree, bNode *gnode, const char *ntree_idname, - struct ReportList &reports) + ReportList &reports) { int ok = true; @@ -717,13 +717,13 @@ static int node_get_selected_minmax( INIT_MINMAX2(min, max); LISTBASE_FOREACH (bNode *, node, &ntree.nodes) { if (node_group_make_use_node(*node, gnode)) { - float loc[2]; - nodeToView(node, node->offsetx, node->offsety, &loc[0], &loc[1]); - minmax_v2v2_v2(min, max, loc); + float2 loc; + nodeToView(node, node->offsetx, node->offsety, &loc.x, &loc.y); + math::min_max(loc, min, max); if (use_size) { - loc[0] += node->width; - loc[1] -= node->height; - minmax_v2v2_v2(min, max, loc); + loc.x += node->width; + loc.y -= node->height; + math::min_max(loc, min, max); } totselect++; } @@ -837,8 +837,8 @@ static void node_group_make_insert_selected(const bContext &C, bNodeTree &ntree, /* relink external sockets */ LISTBASE_FOREACH_MUTABLE (bNodeLink *, link, &ntree.links) { - int fromselect = node_group_make_use_node(*link->fromnode, gnode); - int toselect = node_group_make_use_node(*link->tonode, gnode); + const bool fromselect = node_group_make_use_node(*link->fromnode, gnode); + const bool toselect = node_group_make_use_node(*link->tonode, gnode); if ((fromselect && link->tonode == gnode) || (toselect && link->fromnode == gnode)) { /* remove all links to/from the gnode. @@ -918,8 +918,8 @@ static void node_group_make_insert_selected(const bContext &C, bNodeTree &ntree, /* move internal links */ LISTBASE_FOREACH_MUTABLE (bNodeLink *, link, &ntree.links) { - int fromselect = node_group_make_use_node(*link->fromnode, gnode); - int toselect = node_group_make_use_node(*link->tonode, gnode); + const bool fromselect = node_group_make_use_node(*link->fromnode, gnode); + const bool toselect = node_group_make_use_node(*link->tonode, gnode); if (fromselect && toselect) { BLI_remlink(&ntree.links, link); @@ -1042,9 +1042,6 @@ static int node_group_make_exec(bContext *C, wmOperator *op) nodeSetActive(&ntree, gnode); if (ngroup) { ED_node_tree_push(&snode, ngroup, gnode); - LISTBASE_FOREACH (bNode *, node, &ngroup->nodes) { - sort_multi_input_socket_links(snode, *node, nullptr, nullptr); - } } } diff --git a/source/blender/editors/space_node/node_intern.hh b/source/blender/editors/space_node/node_intern.hh index 81c2bc0e962..70ac0e48d01 100644 --- a/source/blender/editors/space_node/node_intern.hh +++ b/source/blender/editors/space_node/node_intern.hh @@ -9,6 +9,7 @@ #include "BLI_math_vector.h" #include "BLI_math_vector.hh" +#include "BLI_set.hh" #include "BLI_vector.hh" #include "BKE_node.h" @@ -144,7 +145,10 @@ void node_socket_color_get(const bContext &C, void node_draw_space(const bContext &C, ARegion ®ion); -void node_socket_add_tooltip(bNodeTree *ntree, bNode *node, bNodeSocket *sock, uiLayout *layout); +void node_socket_add_tooltip(const bNodeTree &ntree, + const bNode &node, + const bNodeSocket &sock, + uiLayout &layout); /** * Sort nodes by selection: unselected nodes first, then selected, @@ -166,8 +170,9 @@ void node_keymap(wmKeyConfig *keyconf); /* node_select.cc */ rctf node_frame_rect_inside(const bNode &node); -bool node_or_socket_isect_event(bContext *C, const wmEvent *event); +bool node_or_socket_isect_event(const bContext &C, const wmEvent &event); +Set<bNode *> get_selected_nodes(bNodeTree &node_tree); void node_deselect_all(SpaceNode &snode); void node_socket_select(bNode *node, bNodeSocket &sock); void node_socket_deselect(bNode *node, bNodeSocket &sock, bool deselect_node); @@ -214,6 +219,10 @@ void node_draw_link(const bContext &C, const SpaceNode &snode, const bNodeLink &link, bool selected); +void node_draw_link_dragged(const bContext &C, + const View2D &v2d, + const SpaceNode &snode, + const bNodeLink &link); /** * Don't do shadows if th_col3 is -1. */ @@ -225,19 +234,12 @@ void node_draw_link_bezier(const bContext &C, int th_col2, int th_col3, bool selected); -/** If v2d not nullptr, it clips and returns 0 if not visible. */ -bool node_link_bezier_points(const View2D *v2d, - const SpaceNode *snode, - const bNodeLink &link, - float coord_array[][2], - int resol); -/** - * Return quadratic beziers points for a given nodelink and clip if v2d is not nullptr. - */ -bool node_link_bezier_handles(const View2D *v2d, - const SpaceNode *snode, - const bNodeLink &ink, - float vec[4][2]); + +void node_link_bezier_points_evaluated(const bNodeLink &link, + std::array<float2, NODE_LINK_RESOL + 1> &coords); + +std::optional<float2> link_path_intersection(const bNodeLink &link, Span<float2> path); + void draw_nodespace_back_pix(const bContext &C, ARegion ®ion, SpaceNode &snode, @@ -249,6 +251,7 @@ bNode *add_node(const bContext &C, StringRef idname, const float2 &location); bNode *add_static_node(const bContext &C, int type, const float2 &location); void NODE_OT_add_reroute(wmOperatorType *ot); +void NODE_OT_add_search(wmOperatorType *ot); void NODE_OT_add_group(wmOperatorType *ot); void NODE_OT_add_object(wmOperatorType *ot); void NODE_OT_add_collection(wmOperatorType *ot); @@ -267,11 +270,6 @@ void NODE_OT_group_edit(wmOperatorType *ot); /* node_relationships.cc */ -void sort_multi_input_socket_links(SpaceNode &snode, - bNode &node, - bNodeLink *drag_link, - const float2 *cursor); - void NODE_OT_link(wmOperatorType *ot); void NODE_OT_link_make(wmOperatorType *ot); void NODE_OT_links_cut(wmOperatorType *ot); @@ -293,8 +291,6 @@ float2 node_link_calculate_multi_input_position(const float2 &socket_position, int index, int total_inputs); -void node_select_all(ListBase *lb, int action); - float node_socket_calculate_height(const bNodeSocket &socket); void snode_set_context(const bContext &C); @@ -380,4 +376,8 @@ void invoke_node_link_drag_add_menu(bContext &C, bNodeSocket &socket, const float2 &cursor); +/* add_node_search.cc */ + +void invoke_add_node_search_menu(bContext &C, const float2 &cursor, bool use_transform); + } // namespace blender::ed::space_node diff --git a/source/blender/editors/space_node/node_ops.cc b/source/blender/editors/space_node/node_ops.cc index ce000aba1da..f02c019359d 100644 --- a/source/blender/editors/space_node/node_ops.cc +++ b/source/blender/editors/space_node/node_ops.cc @@ -75,6 +75,7 @@ void node_operatortypes() WM_operatortype_append(NODE_OT_backimage_fit); WM_operatortype_append(NODE_OT_backimage_sample); + WM_operatortype_append(NODE_OT_add_search); WM_operatortype_append(NODE_OT_add_group); WM_operatortype_append(NODE_OT_add_object); WM_operatortype_append(NODE_OT_add_collection); @@ -111,7 +112,7 @@ void node_operatortypes() WM_operatortype_append(NODE_OT_cryptomatte_layer_remove); } -void node_keymap(struct wmKeyConfig *keyconf) +void node_keymap(wmKeyConfig *keyconf) { /* Entire Editor only ----------------- */ WM_keymap_ensure(keyconf, "Node Generic", SPACE_NODE, 0); @@ -144,7 +145,7 @@ void ED_operatormacros_node() WM_operatortype_macro_define(ot, "NODE_OT_attach"); WM_operatortype_macro_define(ot, "NODE_OT_insert_offset"); - /* NODE_OT_translate_attach with remove_on_canel set to true */ + /* NODE_OT_translate_attach with remove_on_cancel set to true. */ ot = WM_operatortype_append_macro("NODE_OT_translate_attach_remove_on_cancel", "Move and Attach", "Move nodes and attach to frame", diff --git a/source/blender/editors/space_node/node_relationships.cc b/source/blender/editors/space_node/node_relationships.cc index d911e53be7f..e12ab3191cb 100644 --- a/source/blender/editors/space_node/node_relationships.cc +++ b/source/blender/editors/space_node/node_relationships.cc @@ -11,6 +11,7 @@ #include "DNA_node_types.h" #include "BLI_easing.h" +#include "BLI_stack.hh" #include "BKE_anim_data.h" #include "BKE_context.h" @@ -18,6 +19,7 @@ #include "BKE_lib_id.h" #include "BKE_main.h" #include "BKE_node.h" +#include "BKE_node_runtime.hh" #include "BKE_node_tree_update.h" #include "BKE_screen.h" @@ -46,19 +48,11 @@ #include "BLT_translation.h" #include "NOD_node_declaration.hh" -#include "NOD_node_tree_ref.hh" #include "NOD_socket_declarations.hh" #include "NOD_socket_declarations_geometry.hh" #include "node_intern.hh" /* own include */ -using namespace blender::nodes::node_tree_ref_types; - -struct bNodeListItem { - struct bNodeListItem *next, *prev; - struct bNode *node; -}; - struct NodeInsertOfsData { bNodeTree *ntree; bNode *insert; /* inserted node */ @@ -79,6 +73,8 @@ static void clear_picking_highlight(ListBase *links) namespace blender::ed::space_node { +void update_multi_input_indices_for_removed_links(bNode &node); + /* -------------------------------------------------------------------- */ /** \name Add Node * \{ */ @@ -109,11 +105,9 @@ static void pick_link( nldrag.links.append(link); nodeRemLink(snode.edittree, &link_to_pick); - + snode.edittree->ensure_topology_cache(); BLI_assert(nldrag.last_node_hovered_while_dragging_a_link != nullptr); - - sort_multi_input_socket_links( - snode, *nldrag.last_node_hovered_while_dragging_a_link, nullptr, nullptr); + update_multi_input_indices_for_removed_links(*nldrag.last_node_hovered_while_dragging_a_link); /* Send changed event to original link->tonode. */ if (node) { @@ -127,10 +121,8 @@ static void pick_input_link_by_link_intersect(const bContext &C, const float2 &cursor) { SpaceNode *snode = CTX_wm_space_node(&C); - const ARegion *region = CTX_wm_region(&C); - const View2D *v2d = ®ion->v2d; - float drag_start[2]; + float2 drag_start; RNA_float_get_array(op.ptr, "drag_start", drag_start); bNode *node; bNodeSocket *socket; @@ -139,26 +131,16 @@ static void pick_input_link_by_link_intersect(const bContext &C, /* Distance to test overlapping of cursor on link. */ const float cursor_link_touch_distance = 12.5f * UI_DPI_FAC; - const int resolution = NODE_LINK_RESOL; - bNodeLink *link_to_pick = nullptr; clear_picking_highlight(&snode->edittree->links); LISTBASE_FOREACH (bNodeLink *, link, &snode->edittree->links) { if (link->tosock == socket) { /* Test if the cursor is near a link. */ - float vec[4][2]; - node_link_bezier_handles(v2d, snode, *link, vec); - - float data[NODE_LINK_RESOL * 2 + 2]; - BKE_curve_forward_diff_bezier( - vec[0][0], vec[1][0], vec[2][0], vec[3][0], data, resolution, sizeof(float[2])); - BKE_curve_forward_diff_bezier( - vec[0][1], vec[1][1], vec[2][1], vec[3][1], data + 1, resolution, sizeof(float[2])); - - for (int i = 0; i < resolution * 2; i += 2) { - float *l1 = &data[i]; - float *l2 = &data[i + 2]; - float distance = dist_squared_to_line_segment_v2(cursor, l1, l2); + std::array<float2, NODE_LINK_RESOL + 1> coords; + node_link_bezier_points_evaluated(*link, coords); + + for (const int i : IndexRange(coords.size() - 1)) { + const float distance = dist_squared_to_line_segment_v2(cursor, coords[i], coords[i + 1]); if (distance < cursor_link_touch_distance) { link_to_pick = link; nldrag.last_picked_multi_input_socket_link = link_to_pick; @@ -310,35 +292,24 @@ struct LinkAndPosition { float2 multi_socket_position; }; -void sort_multi_input_socket_links(SpaceNode &snode, - bNode &node, - bNodeLink *drag_link, - const float2 *cursor) +static void sort_multi_input_socket_links_with_drag(bNode &node, + bNodeLink &drag_link, + const float2 &cursor) { - LISTBASE_FOREACH (bNodeSocket *, socket, &node.inputs) { - if (!(socket->flag & SOCK_MULTI_INPUT)) { + for (bNodeSocket *socket : node.input_sockets()) { + if (!socket->is_multi_input()) { continue; } - Vector<LinkAndPosition, 8> links; + const float2 &socket_location = {socket->locx, socket->locy}; - LISTBASE_FOREACH (bNodeLink *, link, &snode.edittree->links) { - if (link->tosock == socket) { - links.append( - {link, - node_link_calculate_multi_input_position({link->tosock->locx, link->tosock->locy}, - link->multi_input_socket_index, - link->tosock->total_inputs)}); - } - } + Vector<LinkAndPosition, 8> links; + for (bNodeLink *link : socket->directly_linked_links()) { + const float2 location = node_link_calculate_multi_input_position( + socket_location, link->multi_input_socket_index, link->tosock->total_inputs); + links.append({link, location}); + }; - if (drag_link) { - LinkAndPosition link_and_position{}; - link_and_position.link = drag_link; - if (cursor) { - link_and_position.multi_socket_position = *cursor; - } - links.append(link_and_position); - } + links.append({&drag_link, cursor}); std::sort(links.begin(), links.end(), [](const LinkAndPosition a, const LinkAndPosition b) { return a.multi_socket_position.y < b.multi_socket_position.y; @@ -350,6 +321,23 @@ void sort_multi_input_socket_links(SpaceNode &snode, } } +void update_multi_input_indices_for_removed_links(bNode &node) +{ + for (bNodeSocket *socket : node.input_sockets()) { + if (!socket->is_multi_input()) { + continue; + } + Vector<bNodeLink *, 8> links = socket->directly_linked_links(); + std::sort(links.begin(), links.end(), [](const bNodeLink *a, const bNodeLink *b) { + return a->multi_input_socket_index < b->multi_input_socket_index; + }); + + for (const int i : links.index_range()) { + links[i]->multi_input_socket_index = i; + } + } +} + static void snode_autoconnect(SpaceNode &snode, const bool allow_multiple, const bool replace) { bNodeTree *ntree = snode.edittree; @@ -434,18 +422,18 @@ namespace viewer_linking { * \{ */ /* Depending on the node tree type, different socket types are supported by viewer nodes. */ -static bool socket_can_be_viewed(const OutputSocketRef &socket) +static bool socket_can_be_viewed(const bNodeSocket &socket) { - if (nodeSocketIsHidden(socket.bsocket())) { + if (nodeSocketIsHidden(&socket)) { return false; } - if (socket.idname() == "NodeSocketVirtual") { + if (STREQ(socket.idname, "NodeSocketVirtual")) { return false; } - if (socket.tree().btree()->type != NTREE_GEOMETRY) { + if (socket.owner_tree().type != NTREE_GEOMETRY) { return true; } - return ELEM(socket.typeinfo()->type, + return ELEM(socket.typeinfo->type, SOCK_GEOMETRY, SOCK_FLOAT, SOCK_VECTOR, @@ -502,15 +490,15 @@ static bNodeSocket *node_link_viewer_get_socket(bNodeTree &ntree, return nullptr; } -static bool is_viewer_node(const NodeRef &node) +static bool is_viewer_node(const bNode &node) { - return ELEM(node.bnode()->type, CMP_NODE_VIEWER, CMP_NODE_SPLITVIEWER, GEO_NODE_VIEWER); + return ELEM(node.type, CMP_NODE_VIEWER, CMP_NODE_SPLITVIEWER, GEO_NODE_VIEWER); } -static Vector<const NodeRef *> find_viewer_nodes(const NodeTreeRef &tree) +static Vector<const bNode *> find_viewer_nodes(const bNodeTree &tree) { - Vector<const NodeRef *> viewer_nodes; - for (const NodeRef *node : tree.nodes()) { + Vector<const bNode *> viewer_nodes; + for (const bNode *node : tree.all_nodes()) { if (is_viewer_node(*node)) { viewer_nodes.append(node); } @@ -518,20 +506,20 @@ static Vector<const NodeRef *> find_viewer_nodes(const NodeTreeRef &tree) return viewer_nodes; } -static bool is_viewer_socket_in_viewer(const InputSocketRef &socket) +static bool is_viewer_socket_in_viewer(const bNodeSocket &socket) { - const NodeRef &node = socket.node(); + const bNode &node = socket.owner_node(); BLI_assert(is_viewer_node(node)); - if (node.typeinfo()->type == GEO_NODE_VIEWER) { + if (node.typeinfo->type == GEO_NODE_VIEWER) { return true; } return socket.index() == 0; } -static bool is_linked_to_viewer(const OutputSocketRef &socket, const NodeRef &viewer_node) +static bool is_linked_to_viewer(const bNodeSocket &socket, const bNode &viewer_node) { - for (const InputSocketRef *target_socket : socket.directly_linked_sockets()) { - if (&target_socket->node() != &viewer_node) { + for (const bNodeSocket *target_socket : socket.directly_linked_sockets()) { + if (&target_socket->owner_node() != &viewer_node) { continue; } if (!target_socket->is_available()) { @@ -561,39 +549,39 @@ static void remove_links_to_unavailable_viewer_sockets(bNodeTree &btree, bNode & } } -static const NodeRef *get_existing_viewer(const NodeTreeRef &tree) +static const bNode *get_existing_viewer(const bNodeTree &tree) { - Vector<const NodeRef *> viewer_nodes = find_viewer_nodes(tree); + Vector<const bNode *> viewer_nodes = find_viewer_nodes(tree); /* Check if there is already an active viewer node that should be used. */ - for (const NodeRef *viewer_node : viewer_nodes) { - if (viewer_node->bnode()->flag & NODE_DO_OUTPUT) { + for (const bNode *viewer_node : viewer_nodes) { + if (viewer_node->flag & NODE_DO_OUTPUT) { return viewer_node; } } /* If no active but non-active viewers exist, make one active. */ if (!viewer_nodes.is_empty()) { - viewer_nodes[0]->bnode()->flag |= NODE_DO_OUTPUT; + const_cast<bNode *>(viewer_nodes[0])->flag |= NODE_DO_OUTPUT; return viewer_nodes[0]; } return nullptr; } -static const OutputSocketRef *find_output_socket_to_be_viewed(const NodeRef *active_viewer_node, - const NodeRef &node_to_view) +static const bNodeSocket *find_output_socket_to_be_viewed(const bNode *active_viewer_node, + const bNode &node_to_view) { /* Check if any of the output sockets is selected, which is the case when the user just clicked * on the socket. */ - for (const OutputSocketRef *output_socket : node_to_view.outputs()) { - if (output_socket->bsocket()->flag & SELECT) { + for (const bNodeSocket *output_socket : node_to_view.output_sockets()) { + if (output_socket->flag & SELECT) { return output_socket; } } - const OutputSocketRef *last_socket_linked_to_viewer = nullptr; + const bNodeSocket *last_socket_linked_to_viewer = nullptr; if (active_viewer_node != nullptr) { - for (const OutputSocketRef *output_socket : node_to_view.outputs()) { + for (const bNodeSocket *output_socket : node_to_view.output_sockets()) { if (!socket_can_be_viewed(*output_socket)) { continue; } @@ -604,7 +592,7 @@ static const OutputSocketRef *find_output_socket_to_be_viewed(const NodeRef *act } if (last_socket_linked_to_viewer == nullptr) { /* If no output is connected to a viewer, use the first output that can be viewed. */ - for (const OutputSocketRef *output_socket : node_to_view.outputs()) { + for (const bNodeSocket *output_socket : node_to_view.output_sockets()) { if (socket_can_be_viewed(*output_socket)) { return output_socket; } @@ -612,10 +600,10 @@ static const OutputSocketRef *find_output_socket_to_be_viewed(const NodeRef *act } else { /* Pick the next socket to be linked to the viewer. */ - const int tot_outputs = node_to_view.outputs().size(); + const int tot_outputs = node_to_view.output_sockets().size(); for (const int offset : IndexRange(1, tot_outputs - 1)) { const int index = (last_socket_linked_to_viewer->index() + offset) % tot_outputs; - const OutputSocketRef &output_socket = node_to_view.output(index); + const bNodeSocket &output_socket = node_to_view.output_socket(index); if (!socket_can_be_viewed(output_socket)) { continue; } @@ -639,7 +627,8 @@ static int link_socket_to_viewer(const bContext &C, if (viewer_bnode == nullptr) { /* Create a new viewer node if none exists. */ const int viewer_type = get_default_viewer_type(&C); - const float2 location{bsocket_to_view.locx + 100, bsocket_to_view.locy}; + const float2 location{bsocket_to_view.locx / UI_DPI_FAC + 100, + bsocket_to_view.locy / UI_DPI_FAC}; viewer_bnode = add_static_node(C, viewer_type, location); if (viewer_bnode == nullptr) { return OPERATOR_CANCELLED; @@ -682,20 +671,15 @@ static int node_link_viewer(const bContext &C, bNode &bnode_to_view) { SpaceNode &snode = *CTX_wm_space_node(&C); bNodeTree *btree = snode.edittree; + btree->ensure_topology_cache(); - const NodeTreeRef tree{btree}; - const NodeRef &node_to_view = *tree.find_node(bnode_to_view); - const NodeRef *active_viewer_node = get_existing_viewer(tree); - - const OutputSocketRef *socket_to_view = find_output_socket_to_be_viewed(active_viewer_node, - node_to_view); - if (socket_to_view == nullptr) { + bNode *active_viewer_bnode = const_cast<bNode *>(get_existing_viewer(*btree)); + bNodeSocket *bsocket_to_view = const_cast<bNodeSocket *>( + find_output_socket_to_be_viewed(active_viewer_bnode, bnode_to_view)); + if (bsocket_to_view == nullptr) { return OPERATOR_FINISHED; } - - bNodeSocket &bsocket_to_view = *socket_to_view->bsocket(); - bNode *viewer_bnode = active_viewer_node ? active_viewer_node->bnode() : nullptr; - return link_socket_to_viewer(C, viewer_bnode, bnode_to_view, bsocket_to_view); + return link_socket_to_viewer(C, active_viewer_bnode, bnode_to_view, *bsocket_to_view); } /** \} */ @@ -949,6 +933,7 @@ static void node_link_find_socket(bContext &C, wmOperator &op, const float2 &cur if (nldrag->in_out == SOCK_OUT) { bNode *tnode; bNodeSocket *tsock = nullptr; + snode.edittree->ensure_topology_cache(); if (node_find_indicated_socket(snode, &tnode, &tsock, cursor, SOCK_IN)) { for (bNodeLink *link : nldrag->links) { /* skip if socket is on the same node as the fromsock */ @@ -975,19 +960,19 @@ static void node_link_find_socket(bContext &C, wmOperator &op, const float2 &cur continue; } if (link->tosock && link->tosock->flag & SOCK_MULTI_INPUT) { - sort_multi_input_socket_links(snode, *tnode, link, &cursor); + sort_multi_input_socket_links_with_drag(*tnode, *link, cursor); } } } else { for (bNodeLink *link : nldrag->links) { - if (nldrag->last_node_hovered_while_dragging_a_link) { - sort_multi_input_socket_links( - snode, *nldrag->last_node_hovered_while_dragging_a_link, nullptr, &cursor); - } link->tonode = nullptr; link->tosock = nullptr; } + if (nldrag->last_node_hovered_while_dragging_a_link) { + update_multi_input_indices_for_removed_links( + *nldrag->last_node_hovered_while_dragging_a_link); + } } } else { @@ -1184,7 +1169,7 @@ static int node_link_invoke(bContext *C, wmOperator *op, const wmEvent *event) bool detach = RNA_boolean_get(op->ptr, "detach"); - int mval[2]; + int2 mval; WM_event_drag_start_mval(event, ®ion, mval); float2 cursor; @@ -1324,28 +1309,6 @@ void NODE_OT_link_make(wmOperatorType *ot) /** \} */ /* -------------------------------------------------------------------- */ -/** \name Node Link Intersect - * \{ */ - -static bool node_links_intersect(bNodeLink &link, const float mcoords[][2], int tot) -{ - float coord_array[NODE_LINK_RESOL + 1][2]; - - if (node_link_bezier_points(nullptr, nullptr, link, coord_array, NODE_LINK_RESOL)) { - for (int i = 0; i < tot - 1; i++) { - for (int b = 0; b < NODE_LINK_RESOL; b++) { - if (isect_seg_seg_v2(mcoords[i], mcoords[i + 1], coord_array[b], coord_array[b + 1]) > 0) { - return true; - } - } - } - } - return false; -} - -/** \} */ - -/* -------------------------------------------------------------------- */ /** \name Cut Link Operator * \{ */ @@ -1353,56 +1316,63 @@ static int cut_links_exec(bContext *C, wmOperator *op) { Main &bmain = *CTX_data_main(C); SpaceNode &snode = *CTX_wm_space_node(C); - ARegion ®ion = *CTX_wm_region(C); + const ARegion ®ion = *CTX_wm_region(C); - int i = 0; - float mcoords[256][2]; + Vector<float2> path; RNA_BEGIN (op->ptr, itemptr, "path") { - float loc[2]; - - RNA_float_get_array(&itemptr, "loc", loc); - UI_view2d_region_to_view( - ®ion.v2d, (int)loc[0], (int)loc[1], &mcoords[i][0], &mcoords[i][1]); - i++; - if (i >= 256) { + float2 loc_region; + RNA_float_get_array(&itemptr, "loc", loc_region); + float2 loc_view; + UI_view2d_region_to_view(®ion.v2d, loc_region.x, loc_region.y, &loc_view.x, &loc_view.y); + path.append(loc_view); + if (path.size() >= 256) { break; } } RNA_END; - if (i > 1) { - bool found = false; + if (path.is_empty()) { + return OPERATOR_CANCELLED | OPERATOR_PASS_THROUGH; + } - ED_preview_kill_jobs(CTX_wm_manager(C), &bmain); + bool found = false; - LISTBASE_FOREACH_MUTABLE (bNodeLink *, link, &snode.edittree->links) { - if (node_link_is_hidden_or_dimmed(region.v2d, *link)) { - continue; - } + ED_preview_kill_jobs(CTX_wm_manager(C), &bmain); - if (node_links_intersect(*link, mcoords, i)) { + bNodeTree &node_tree = *snode.edittree; - if (found == false) { - /* TODO(sergey): Why did we kill jobs twice? */ - ED_preview_kill_jobs(CTX_wm_manager(C), &bmain); - found = true; - } + Set<bNode *> affected_nodes; - bNode *to_node = link->tonode; - nodeRemLink(snode.edittree, link); - sort_multi_input_socket_links(snode, *to_node, nullptr, nullptr); - } + LISTBASE_FOREACH_MUTABLE (bNodeLink *, link, &node_tree.links) { + if (node_link_is_hidden_or_dimmed(region.v2d, *link)) { + continue; } - ED_node_tree_propagate_change(C, CTX_data_main(C), snode.edittree); - if (found) { - return OPERATOR_FINISHED; + if (link_path_intersection(*link, path)) { + + if (!found) { + /* TODO(sergey): Why did we kill jobs twice? */ + ED_preview_kill_jobs(CTX_wm_manager(C), &bmain); + found = true; + } + + bNode *to_node = link->tonode; + nodeRemLink(snode.edittree, link); + affected_nodes.add(to_node); } + } - return OPERATOR_CANCELLED; + node_tree.ensure_topology_cache(); + for (bNode *node : affected_nodes) { + update_multi_input_indices_for_removed_links(*node); } - return OPERATOR_CANCELLED | OPERATOR_PASS_THROUGH; + ED_node_tree_propagate_change(C, CTX_data_main(C), snode.edittree); + if (found) { + return OPERATOR_FINISHED; + } + + return OPERATOR_CANCELLED; } void NODE_OT_links_cut(wmOperatorType *ot) @@ -1436,69 +1406,99 @@ void NODE_OT_links_cut(wmOperatorType *ot) /** \name Mute Links Operator * \{ */ +static bool all_links_muted(const bNodeSocket &socket) +{ + for (const bNodeLink *link : socket.directly_linked_links()) { + if (!(link->flag & NODE_LINK_MUTED)) { + return false; + } + } + return true; +} + static int mute_links_exec(bContext *C, wmOperator *op) { Main &bmain = *CTX_data_main(C); SpaceNode &snode = *CTX_wm_space_node(C); - ARegion ®ion = *CTX_wm_region(C); + const ARegion ®ion = *CTX_wm_region(C); + bNodeTree &ntree = *snode.edittree; - int i = 0; - float mcoords[256][2]; + Vector<float2> path; RNA_BEGIN (op->ptr, itemptr, "path") { - float loc[2]; - - RNA_float_get_array(&itemptr, "loc", loc); - UI_view2d_region_to_view( - ®ion.v2d, (int)loc[0], (int)loc[1], &mcoords[i][0], &mcoords[i][1]); - i++; - if (i >= 256) { + float2 loc_region; + RNA_float_get_array(&itemptr, "loc", loc_region); + float2 loc_view; + UI_view2d_region_to_view(®ion.v2d, loc_region.x, loc_region.y, &loc_view.x, &loc_view.y); + path.append(loc_view); + if (path.size() >= 256) { break; } } RNA_END; - if (i > 1) { - ED_preview_kill_jobs(CTX_wm_manager(C), &bmain); + if (path.is_empty()) { + return OPERATOR_CANCELLED | OPERATOR_PASS_THROUGH; + } - /* Count intersected links and clear test flag. */ - int tot = 0; - LISTBASE_FOREACH (bNodeLink *, link, &snode.edittree->links) { - if (node_link_is_hidden_or_dimmed(region.v2d, *link)) { - continue; - } - link->flag &= ~NODE_LINK_TEST; - if (node_links_intersect(*link, mcoords, i)) { - tot++; - } + ED_preview_kill_jobs(CTX_wm_manager(C), &bmain); + + ntree.ensure_topology_cache(); + + Set<bNodeLink *> affected_links; + LISTBASE_FOREACH (bNodeLink *, link, &ntree.links) { + if (node_link_is_hidden_or_dimmed(region.v2d, *link)) { + continue; } - if (tot == 0) { - return OPERATOR_CANCELLED; + if (!link_path_intersection(*link, path)) { + continue; } + affected_links.add(link); + } - /* Mute links. */ - LISTBASE_FOREACH (bNodeLink *, link, &snode.edittree->links) { - if (node_link_is_hidden_or_dimmed(region.v2d, *link) || (link->flag & NODE_LINK_TEST)) { - continue; - } + if (affected_links.is_empty()) { + return OPERATOR_CANCELLED; + } + + bke::node_tree_runtime::AllowUsingOutdatedInfo allow_outdated_info{ntree}; + + for (bNodeLink *link : affected_links) { + nodeLinkSetMute(&ntree, link, !(link->flag & NODE_LINK_MUTED)); + const bool muted = link->flag & NODE_LINK_MUTED; - if (node_links_intersect(*link, mcoords, i)) { - nodeMuteLinkToggle(snode.edittree, link); + /* Propagate mute status downstream past reroute nodes. */ + if (link->tonode->is_reroute()) { + Stack<bNodeLink *> links; + links.push_multiple(link->tonode->output_sockets().first()->directly_linked_links()); + while (!links.is_empty()) { + bNodeLink *link = links.pop(); + nodeLinkSetMute(&ntree, link, muted); + if (!link->tonode->is_reroute()) { + continue; + } + links.push_multiple(link->tonode->output_sockets().first()->directly_linked_links()); } } - - /* Clear remaining test flags. */ - LISTBASE_FOREACH (bNodeLink *, link, &snode.edittree->links) { - if (node_link_is_hidden_or_dimmed(region.v2d, *link)) { - continue; + /* Propagate mute status upstream past reroutes, but only if all outputs are muted. */ + if (link->fromnode->is_reroute()) { + if (!muted || all_links_muted(*link->fromsock)) { + Stack<bNodeLink *> links; + links.push_multiple(link->fromnode->input_sockets().first()->directly_linked_links()); + while (!links.is_empty()) { + bNodeLink *link = links.pop(); + nodeLinkSetMute(&ntree, link, muted); + if (!link->fromnode->is_reroute()) { + continue; + } + if (!muted || all_links_muted(*link->fromsock)) { + links.push_multiple(link->fromnode->input_sockets().first()->directly_linked_links()); + } + } } - link->flag &= ~NODE_LINK_TEST; } - - ED_node_tree_propagate_change(C, CTX_data_main(C), snode.edittree); - return OPERATOR_FINISHED; } - return OPERATOR_CANCELLED | OPERATOR_PASS_THROUGH; + ED_node_tree_propagate_change(C, CTX_data_main(C), &ntree); + return OPERATOR_FINISHED; } void NODE_OT_links_mute(wmOperatorType *ot) @@ -1619,7 +1619,9 @@ void NODE_OT_parent_set(wmOperatorType *ot) #define NODE_JOIN_DONE 1 #define NODE_JOIN_IS_DESCENDANT 2 -static void node_join_attach_recursive(bNode *node, bNode *frame) +static void node_join_attach_recursive(bNode *node, + bNode *frame, + const Set<bNode *> &selected_nodes) { node->done |= NODE_JOIN_DONE; @@ -1629,21 +1631,21 @@ static void node_join_attach_recursive(bNode *node, bNode *frame) else if (node->parent) { /* call recursively */ if (!(node->parent->done & NODE_JOIN_DONE)) { - node_join_attach_recursive(node->parent, frame); + node_join_attach_recursive(node->parent, frame, selected_nodes); } /* in any case: if the parent is a descendant, so is the child */ if (node->parent->done & NODE_JOIN_IS_DESCENDANT) { node->done |= NODE_JOIN_IS_DESCENDANT; } - else if (node->flag & NODE_TEST) { + else if (selected_nodes.contains(node)) { /* if parent is not an descendant of the frame, reattach the node */ nodeDetachNode(node); nodeAttachNode(node, frame); node->done |= NODE_JOIN_IS_DESCENDANT; } } - else if (node->flag & NODE_TEST) { + else if (selected_nodes.contains(node)) { nodeAttachNode(node, frame); node->done |= NODE_JOIN_IS_DESCENDANT; } @@ -1651,21 +1653,13 @@ static void node_join_attach_recursive(bNode *node, bNode *frame) static int node_join_exec(bContext *C, wmOperator *UNUSED(op)) { + Main &bmain = *CTX_data_main(C); SpaceNode &snode = *CTX_wm_space_node(C); bNodeTree &ntree = *snode.edittree; - /* XXX save selection: add_static_node call below sets the new frame as single - * active+selected node */ - LISTBASE_FOREACH (bNode *, node, &ntree.nodes) { - if (node->flag & NODE_SELECT) { - node->flag |= NODE_TEST; - } - else { - node->flag &= ~NODE_TEST; - } - } + const Set<bNode *> selected_nodes = get_selected_nodes(ntree); - bNode *frame = add_static_node(*C, NODE_FRAME, float2(0)); + bNode *frame_node = nodeAddStaticNode(C, &ntree, NODE_FRAME); /* reset tags */ LISTBASE_FOREACH (bNode *, node, &ntree.nodes) { @@ -1674,18 +1668,12 @@ static int node_join_exec(bContext *C, wmOperator *UNUSED(op)) LISTBASE_FOREACH (bNode *, node, &ntree.nodes) { if (!(node->done & NODE_JOIN_DONE)) { - node_join_attach_recursive(node, frame); - } - } - - /* restore selection */ - LISTBASE_FOREACH (bNode *, node, &ntree.nodes) { - if (node->flag & NODE_TEST) { - node->flag |= NODE_SELECT; + node_join_attach_recursive(node, frame_node, selected_nodes); } } node_sort(ntree); + ED_node_tree_propagate_change(C, &bmain, snode.edittree); WM_event_add_notifier(C, NC_NODE | ND_DISPLAY, nullptr); return OPERATOR_FINISHED; @@ -1714,11 +1702,11 @@ void NODE_OT_join(wmOperatorType *ot) static bNode *node_find_frame_to_attach(ARegion ®ion, const bNodeTree &ntree, - const int mouse_xy[2]) + const int2 mouse_xy) { /* convert mouse coordinates to v2d space */ - float cursor[2]; - UI_view2d_region_to_view(®ion.v2d, UNPACK2(mouse_xy), &cursor[0], &cursor[1]); + float2 cursor; + UI_view2d_region_to_view(®ion.v2d, mouse_xy.x, mouse_xy.y, &cursor.x, &cursor.y); LISTBASE_FOREACH_BACKWARD (bNode *, frame, &ntree.nodes) { /* skip selected, those are the nodes we want to attach */ @@ -1739,32 +1727,34 @@ static int node_attach_invoke(bContext *C, wmOperator *UNUSED(op), const wmEvent SpaceNode &snode = *CTX_wm_space_node(C); bNodeTree &ntree = *snode.edittree; bNode *frame = node_find_frame_to_attach(region, ntree, event->mval); + if (frame == nullptr) { + /* Return "finished" so that auto offset operator macros can work. */ + return OPERATOR_FINISHED; + } - if (frame) { - LISTBASE_FOREACH_BACKWARD (bNode *, node, &ntree.nodes) { - if (node->flag & NODE_SELECT) { - if (node->parent == nullptr) { - /* disallow moving a parent into its child */ - if (nodeAttachNodeCheck(frame, node) == false) { - /* attach all unparented nodes */ - nodeAttachNode(node, frame); - } + LISTBASE_FOREACH_BACKWARD (bNode *, node, &ntree.nodes) { + if (node->flag & NODE_SELECT) { + if (node->parent == nullptr) { + /* disallow moving a parent into its child */ + if (nodeAttachNodeCheck(frame, node) == false) { + /* attach all unparented nodes */ + nodeAttachNode(node, frame); } - else { - /* attach nodes which share parent with the frame */ - bNode *parent; - for (parent = frame->parent; parent; parent = parent->parent) { - if (parent == node->parent) { - break; - } + } + else { + /* attach nodes which share parent with the frame */ + bNode *parent; + for (parent = frame->parent; parent; parent = parent->parent) { + if (parent == node->parent) { + break; } + } - if (parent) { - /* disallow moving a parent into its child */ - if (nodeAttachNodeCheck(frame, node) == false) { - nodeDetachNode(node); - nodeAttachNode(node, frame); - } + if (parent) { + /* disallow moving a parent into its child */ + if (nodeAttachNodeCheck(frame, node) == false) { + nodeDetachNode(node); + nodeAttachNode(node, frame); } } } @@ -1942,6 +1932,7 @@ static bool ed_node_link_conditions(ScrArea *area, void ED_node_link_intersect_test(ScrArea *area, int test) { + using namespace blender; using namespace blender::ed::space_node; bNode *select; @@ -1965,36 +1956,34 @@ void ED_node_link_intersect_test(ScrArea *area, int test) bNodeLink *selink = nullptr; float dist_best = FLT_MAX; LISTBASE_FOREACH (bNodeLink *, link, &snode->edittree->links) { - float coord_array[NODE_LINK_RESOL + 1][2]; if (node_link_is_hidden_or_dimmed(region->v2d, *link)) { continue; } - if (node_link_bezier_points(nullptr, nullptr, *link, coord_array, NODE_LINK_RESOL)) { - float dist = FLT_MAX; + std::array<float2, NODE_LINK_RESOL + 1> coords; + node_link_bezier_points_evaluated(*link, coords); + float dist = FLT_MAX; - /* loop over link coords to find shortest dist to - * upper left node edge of a intersected line segment */ - for (int i = 0; i < NODE_LINK_RESOL; i++) { - /* Check if the node rectangle intersects the line from this point to next one. */ - if (BLI_rctf_isect_segment(&select->totr, coord_array[i], coord_array[i + 1])) { - /* store the shortest distance to the upper left edge - * of all intersections found so far */ - const float node_xy[] = {select->totr.xmin, select->totr.ymax}; + /* loop over link coords to find shortest dist to + * upper left node edge of a intersected line segment */ + for (int i = 0; i < NODE_LINK_RESOL; i++) { + /* Check if the node rectangle intersects the line from this point to next one. */ + if (BLI_rctf_isect_segment(&select->totr, coords[i], coords[i + 1])) { + /* store the shortest distance to the upper left edge + * of all intersections found so far */ + const float node_xy[] = {select->totr.xmin, select->totr.ymax}; - /* to be precise coord_array should be clipped by select->totr, - * but not done since there's no real noticeable difference */ - dist = min_ff( - dist_squared_to_line_segment_v2(node_xy, coord_array[i], coord_array[i + 1]), dist); - } + /* to be precise coords should be clipped by select->totr, + * but not done since there's no real noticeable difference */ + dist = min_ff(dist_squared_to_line_segment_v2(node_xy, coords[i], coords[i + 1]), dist); } + } - /* we want the link with the shortest distance to node center */ - if (dist < dist_best) { - dist_best = dist; - selink = link; - } + /* we want the link with the shortest distance to node center */ + if (dist < dist_best) { + dist_best = dist; + selink = link; } } @@ -2048,7 +2037,7 @@ static bNodeSocket *get_main_socket(bNodeTree &ntree, bNode &node, eNodeSocketIn /* Try to get the main socket based on the socket declaration. */ nodeDeclarationEnsure(&ntree, &node); - const nodes::NodeDeclaration *node_decl = node.runtime->declaration; + const nodes::NodeDeclaration *node_decl = node.declaration(); if (node_decl != nullptr) { Span<nodes::SocketDeclarationPtr> socket_decls = (in_out == SOCK_IN) ? node_decl->inputs() : node_decl->outputs(); @@ -2323,10 +2312,10 @@ static void node_link_insert_offset_ntree(NodeInsertOfsData *iofsd, /** * Modal handler for insert offset animation */ -static int node_insert_offset_modal(bContext *C, wmOperator *UNUSED(op), const wmEvent *event) +static int node_insert_offset_modal(bContext *C, wmOperator *op, const wmEvent *event) { SpaceNode *snode = CTX_wm_space_node(C); - NodeInsertOfsData *iofsd = snode->runtime->iofsd; + NodeInsertOfsData *iofsd = static_cast<NodeInsertOfsData *>(op->customdata); bool redraw = false; if (!snode || event->type != TIMER || iofsd == nullptr || @@ -2366,7 +2355,6 @@ static int node_insert_offset_modal(bContext *C, wmOperator *UNUSED(op), const w node->anim_init_locx = node->anim_ofsx = 0.0f; } - snode->runtime->iofsd = nullptr; MEM_freeN(iofsd); return (OPERATOR_FINISHED | OPERATOR_PASS_THROUGH); @@ -2381,6 +2369,8 @@ static int node_insert_offset_invoke(bContext *C, wmOperator *op, const wmEvent { const SpaceNode *snode = CTX_wm_space_node(C); NodeInsertOfsData *iofsd = snode->runtime->iofsd; + snode->runtime->iofsd = nullptr; + op->customdata = iofsd; if (!iofsd || !iofsd->insert) { return OPERATOR_CANCELLED; @@ -2487,6 +2477,7 @@ void ED_node_link_insert(Main *bmain, ScrArea *area) /* Set up insert offset data, it needs stuff from here. */ if ((snode->flag & SNODE_SKIP_INSOFFSET) == 0) { + BLI_assert(snode->runtime->iofsd == nullptr); NodeInsertOfsData *iofsd = MEM_cnew<NodeInsertOfsData>(__func__); iofsd->insert = node_to_insert; diff --git a/source/blender/editors/space_node/node_select.cc b/source/blender/editors/space_node/node_select.cc index 9d73156edab..d93b205b1b7 100644 --- a/source/blender/editors/space_node/node_select.cc +++ b/source/blender/editors/space_node/node_select.cc @@ -22,6 +22,7 @@ #include "BKE_context.h" #include "BKE_main.h" #include "BKE_node.h" +#include "BKE_node_runtime.hh" #include "BKE_workspace.h" #include "ED_node.h" /* own include */ @@ -48,7 +49,7 @@ namespace blender::ed::space_node { -static bool is_event_over_node_or_socket(bContext *C, const wmEvent *event); +static bool is_event_over_node_or_socket(const bContext &C, const wmEvent &event); /** * Function to detect if there is a visible view3d that uses workbench in texture mode. @@ -100,17 +101,17 @@ rctf node_frame_rect_inside(const bNode &node) return frame_inside; } -bool node_or_socket_isect_event(bContext *C, const wmEvent *event) +bool node_or_socket_isect_event(const bContext &C, const wmEvent &event) { return is_event_over_node_or_socket(C, event); } -static bool node_frame_select_isect_mouse(bNode *node, const float2 &mouse) +static bool node_frame_select_isect_mouse(const bNode &node, const float2 &mouse) { /* Frame nodes are selectable by their borders (including their whole rect - as for other nodes - * would prevent e.g. box selection of nodes inside that frame). */ - const rctf frame_inside = node_frame_rect_inside(*node); - if (BLI_rctf_isect_pt(&node->totr, mouse.x, mouse.y) && + const rctf frame_inside = node_frame_rect_inside(node); + if (BLI_rctf_isect_pt(&node.totr, mouse.x, mouse.y) && !BLI_rctf_isect_pt(&frame_inside, mouse.x, mouse.y)) { return true; } @@ -118,19 +119,18 @@ static bool node_frame_select_isect_mouse(bNode *node, const float2 &mouse) return false; } -static bNode *node_under_mouse_select(bNodeTree &ntree, int mx, int my) +static bNode *node_under_mouse_select(bNodeTree &ntree, const float2 mouse) { LISTBASE_FOREACH_BACKWARD (bNode *, node, &ntree.nodes) { switch (node->type) { case NODE_FRAME: { - const float2 mouse{(float)mx, (float)my}; - if (node_frame_select_isect_mouse(node, mouse)) { + if (node_frame_select_isect_mouse(*node, mouse)) { return node; } break; } default: { - if (BLI_rctf_isect_pt(&node->totr, mx, my)) { + if (BLI_rctf_isect_pt(&node->totr, int(mouse.x), int(mouse.y))) { return node; } break; @@ -140,35 +140,32 @@ static bNode *node_under_mouse_select(bNodeTree &ntree, int mx, int my) return nullptr; } -static bNode *node_under_mouse_tweak(bNodeTree &ntree, const float2 &mouse) +static bool node_under_mouse_tweak(const bNodeTree &ntree, const float2 &mouse) { - using namespace blender::math; - - LISTBASE_FOREACH_BACKWARD (bNode *, node, &ntree.nodes) { + LISTBASE_FOREACH_BACKWARD (const bNode *, node, &ntree.nodes) { switch (node->type) { case NODE_REROUTE: { - bNodeSocket *socket = (bNodeSocket *)node->inputs.first; - const float2 location{socket->locx, socket->locy}; - if (distance(mouse, location) < 24.0f) { - return node; + const float2 location = node_to_view(*node, {node->locx, node->locy}); + if (math::distance(mouse, location) < 24.0f) { + return true; } break; } case NODE_FRAME: { - if (node_frame_select_isect_mouse(node, mouse)) { - return node; + if (node_frame_select_isect_mouse(*node, mouse)) { + return true; } break; } default: { if (BLI_rctf_isect_pt(&node->totr, mouse.x, mouse.y)) { - return node; + return true; } break; } } } - return nullptr; + return false; } static bool is_position_over_node_or_socket(SpaceNode &snode, const float2 &mouse) @@ -187,17 +184,17 @@ static bool is_position_over_node_or_socket(SpaceNode &snode, const float2 &mous return false; } -static bool is_event_over_node_or_socket(bContext *C, const wmEvent *event) +static bool is_event_over_node_or_socket(const bContext &C, const wmEvent &event) { - SpaceNode *snode = CTX_wm_space_node(C); - ARegion *region = CTX_wm_region(C); - float2 mouse; + SpaceNode &snode = *CTX_wm_space_node(&C); + ARegion ®ion = *CTX_wm_region(&C); - int mval[2]; - WM_event_drag_start_mval(event, region, mval); + int2 mval; + WM_event_drag_start_mval(&event, ®ion, mval); - UI_view2d_region_to_view(®ion->v2d, mval[0], mval[1], &mouse.x, &mouse.y); - return is_position_over_node_or_socket(*snode, mouse); + float2 mouse; + UI_view2d_region_to_view(®ion.v2d, mval.x, mval.y, &mouse.x, &mouse.y); + return is_position_over_node_or_socket(snode, mouse); } void node_socket_select(bNode *node, bNodeSocket &sock) @@ -314,6 +311,17 @@ void node_deselect_all_output_sockets(SpaceNode &snode, const bool deselect_node } } +Set<bNode *> get_selected_nodes(bNodeTree &node_tree) +{ + Set<bNode *> selected_nodes; + for (bNode *node : node_tree.all_nodes()) { + if (node->flag & NODE_SELECT) { + selected_nodes.add(node); + } + } + return selected_nodes; +} + /** \} */ /* -------------------------------------------------------------------- */ @@ -412,9 +420,7 @@ static int node_select_grouped_exec(bContext *C, wmOperator *op) const int type = RNA_enum_get(op->ptr, "type"); if (!extend) { - LISTBASE_FOREACH (bNode *, node, &node_tree.nodes) { - nodeSetSelected(node, false); - } + node_deselect_all(snode); } nodeSetSelected(node_act, true); @@ -514,8 +520,8 @@ void node_select_single(bContext &C, bNode &node) static bool node_mouse_select(bContext *C, wmOperator *op, - const int mval[2], - struct SelectPick_Params *params) + const int2 mval, + SelectPick_Params *params) { Main &bmain = *CTX_data_main(C); SpaceNode &snode = *CTX_wm_space_node(C); @@ -526,7 +532,6 @@ static bool node_mouse_select(bContext *C, bNode *node, *tnode; bNodeSocket *sock = nullptr; bNodeSocket *tsock; - float cursor[2]; /* always do socket_select when extending selection. */ const bool socket_select = (params->sel_op == SEL_OP_XOR) || @@ -536,7 +541,8 @@ static bool node_mouse_select(bContext *C, bool node_was_selected = false; /* get mouse coordinates in view2d space */ - UI_view2d_region_to_view(®ion.v2d, mval[0], mval[1], &cursor[0], &cursor[1]); + float2 cursor; + UI_view2d_region_to_view(®ion.v2d, mval.x, mval.y, &cursor.x, &cursor.y); /* first do socket selection, these generally overlap with nodes. */ if (socket_select) { @@ -593,7 +599,7 @@ static bool node_mouse_select(bContext *C, if (!sock) { /* find the closest visible node */ - node = node_under_mouse_select(*snode.edittree, (int)cursor[0], (int)cursor[1]); + node = node_under_mouse_select(*snode.edittree, cursor); found = (node != nullptr); node_was_selected = node && (node->flag & SELECT); @@ -603,9 +609,7 @@ static bool node_mouse_select(bContext *C, } else if (found || params->deselect_all) { /* Deselect everything. */ - for (tnode = (bNode *)snode.edittree->nodes.first; tnode; tnode = tnode->next) { - nodeSetSelected(tnode, false); - } + node_deselect_all(snode); changed = true; } } @@ -640,37 +644,38 @@ static bool node_mouse_select(bContext *C, } } - /* update node order */ - if (changed || found) { - bool active_texture_changed = false; - bool viewer_node_changed = false; - if ((node != nullptr) && (node_was_selected == false || params->select_passthrough == false)) { - viewer_node_changed = (node->flag & NODE_DO_OUTPUT) == 0 && node->type == GEO_NODE_VIEWER; - ED_node_set_active(&bmain, &snode, snode.edittree, node, &active_texture_changed); - } - else if (node != nullptr && node->type == GEO_NODE_VIEWER) { - ED_spreadsheet_context_paths_set_geometry_node(&bmain, &snode, node); - } - ED_node_set_active_viewer_key(&snode); - node_sort(*snode.edittree); - if ((active_texture_changed && has_workbench_in_texture_color(wm, scene, ob)) || - viewer_node_changed) { - DEG_id_tag_update(&snode.edittree->id, ID_RECALC_COPY_ON_WRITE); - } + if (!(changed || found)) { + return false; + } - WM_event_add_notifier(C, NC_NODE | NA_SELECTED, nullptr); + bool active_texture_changed = false; + bool viewer_node_changed = false; + if ((node != nullptr) && (node_was_selected == false || params->select_passthrough == false)) { + viewer_node_changed = (node->flag & NODE_DO_OUTPUT) == 0 && node->type == GEO_NODE_VIEWER; + ED_node_set_active(&bmain, &snode, snode.edittree, node, &active_texture_changed); + } + else if (node != nullptr && node->type == GEO_NODE_VIEWER) { + ED_spreadsheet_context_paths_set_geometry_node(&bmain, &snode, node); } + ED_node_set_active_viewer_key(&snode); + node_sort(*snode.edittree); + if ((active_texture_changed && has_workbench_in_texture_color(wm, scene, ob)) || + viewer_node_changed) { + DEG_id_tag_update(&snode.edittree->id, ID_RECALC_COPY_ON_WRITE); + } + + WM_event_add_notifier(C, NC_NODE | NA_SELECTED, nullptr); - return changed || found; + return true; } static int node_select_exec(bContext *C, wmOperator *op) { /* get settings from RNA properties for operator */ - int mval[2]; + int2 mval; RNA_int_get_array(op->ptr, "location", mval); - struct SelectPick_Params params = {}; + SelectPick_Params params = {}; ED_select_pick_params_from_operator(op->ptr, ¶ms); /* perform the select */ @@ -747,7 +752,7 @@ static int node_box_select_exec(bContext *C, wmOperator *op) const eSelectOp sel_op = (eSelectOp)RNA_enum_get(op->ptr, "mode"); const bool select = (sel_op != SEL_OP_SUB); if (SEL_OP_USE_PRE_DESELECT(sel_op)) { - node_select_all(&node_tree.nodes, SEL_DESELECT); + node_deselect_all(snode); } LISTBASE_FOREACH (bNode *, node, &node_tree.nodes) { @@ -787,7 +792,7 @@ static int node_box_select_invoke(bContext *C, wmOperator *op, const wmEvent *ev { const bool tweak = RNA_boolean_get(op->ptr, "tweak"); - if (tweak && is_event_over_node_or_socket(C, event)) { + if (tweak && is_event_over_node_or_socket(*C, *event)) { return OPERATOR_CANCELLED | OPERATOR_PASS_THROUGH; } @@ -836,7 +841,7 @@ static int node_circleselect_exec(bContext *C, wmOperator *op) bNode *node; int x, y, radius; - float offset[2]; + float2 offset; float zoom = (float)(BLI_rcti_size_x(®ion->winrct)) / (float)(BLI_rctf_size_x(®ion->v2d.cur)); @@ -846,7 +851,7 @@ static int node_circleselect_exec(bContext *C, wmOperator *op) WM_gesture_is_modal_first((const wmGesture *)op->customdata)); const bool select = (sel_op != SEL_OP_SUB); if (SEL_OP_USE_PRE_DESELECT(sel_op)) { - node_select_all(&snode->edittree->nodes, SEL_DESELECT); + node_deselect_all(*snode); } /* get operator properties */ @@ -854,7 +859,7 @@ static int node_circleselect_exec(bContext *C, wmOperator *op) y = RNA_int_get(op->ptr, "y"); radius = RNA_int_get(op->ptr, "radius"); - UI_view2d_region_to_view(®ion->v2d, x, y, &offset[0], &offset[1]); + UI_view2d_region_to_view(®ion->v2d, x, y, &offset.x, &offset.y); for (node = (bNode *)snode->edittree->nodes.first; node; node = node->next) { switch (node->type) { @@ -916,7 +921,7 @@ static int node_lasso_select_invoke(bContext *C, wmOperator *op, const wmEvent * { const bool tweak = RNA_boolean_get(op->ptr, "tweak"); - if (tweak && is_event_over_node_or_socket(C, event)) { + if (tweak && is_event_over_node_or_socket(*C, *event)) { return OPERATOR_CANCELLED | OPERATOR_PASS_THROUGH; } @@ -938,7 +943,7 @@ static bool do_lasso_select_node(bContext *C, const bool select = (sel_op != SEL_OP_SUB); if (SEL_OP_USE_PRE_DESELECT(sel_op)) { - node_select_all(&snode->edittree->nodes, SEL_DESELECT); + node_deselect_all(*snode); changed = true; } @@ -968,14 +973,14 @@ static bool do_lasso_select_node(bContext *C, break; } default: { - int screen_co[2]; - const float cent[2] = {BLI_rctf_cent_x(&node->totr), BLI_rctf_cent_y(&node->totr)}; + int2 screen_co; + const float2 center = {BLI_rctf_cent_x(&node->totr), BLI_rctf_cent_y(&node->totr)}; /* marker in screen coords */ if (UI_view2d_view_to_region_clip( - ®ion->v2d, cent[0], cent[1], &screen_co[0], &screen_co[1]) && - BLI_rcti_isect_pt(&rect, screen_co[0], screen_co[1]) && - BLI_lasso_is_point_inside(mcoords, mcoords_len, screen_co[0], screen_co[1], INT_MAX)) { + ®ion->v2d, center.x, center.y, &screen_co.x, &screen_co.y) && + BLI_rcti_isect_pt(&rect, screen_co.x, screen_co.y) && + BLI_lasso_is_point_inside(mcoords, mcoords_len, screen_co.x, screen_co.y, INT_MAX)) { nodeSetSelected(node, select); changed = true; } @@ -1042,13 +1047,48 @@ void NODE_OT_select_lasso(wmOperatorType *ot) /** \name (De)select All Operator * \{ */ +static bool any_node_selected(const bNodeTree &node_tree) +{ + for (const bNode *node : node_tree.all_nodes()) { + if (node->flag & NODE_SELECT) { + return true; + } + } + return false; +} + static int node_select_all_exec(bContext *C, wmOperator *op) { SpaceNode &snode = *CTX_wm_space_node(C); - ListBase *node_lb = &snode.edittree->nodes; + bNodeTree &node_tree = *snode.edittree; + + node_tree.ensure_topology_cache(); + int action = RNA_enum_get(op->ptr, "action"); + if (action == SEL_TOGGLE) { + if (any_node_selected(node_tree)) { + action = SEL_DESELECT; + } + else { + action = SEL_SELECT; + } + } - node_select_all(node_lb, action); + switch (action) { + case SEL_SELECT: + for (bNode *node : node_tree.all_nodes()) { + nodeSetSelected(node, true); + } + break; + case SEL_DESELECT: + node_deselect_all(snode); + break; + case SEL_INVERT: + for (bNode *node : node_tree.all_nodes()) { + nodeSetSelected(node, !(node->flag & SELECT)); + } + break; + } node_sort(*snode.edittree); @@ -1084,22 +1124,21 @@ static int node_select_linked_to_exec(bContext *C, wmOperator *UNUSED(op)) SpaceNode &snode = *CTX_wm_space_node(C); bNodeTree &node_tree = *snode.edittree; - LISTBASE_FOREACH (bNode *, node, &node_tree.nodes) { - node->flag &= ~NODE_TEST; - } + node_tree.ensure_topology_cache(); - LISTBASE_FOREACH (bNodeLink *, link, &node_tree.links) { - if (nodeLinkIsHidden(link)) { - continue; - } - if (link->fromnode && link->tonode && (link->fromnode->flag & NODE_SELECT)) { - link->tonode->flag |= NODE_TEST; - } - } + Set<bNode *> initial_selection = get_selected_nodes(node_tree); - LISTBASE_FOREACH (bNode *, node, &node_tree.nodes) { - if (node->flag & NODE_TEST) { - nodeSetSelected(node, true); + for (bNode *node : initial_selection) { + for (bNodeSocket *output_socket : node->output_sockets()) { + if (!output_socket->is_available()) { + continue; + } + for (bNodeSocket *input_socket : output_socket->directly_linked_sockets()) { + if (!input_socket->is_available()) { + continue; + } + nodeSetSelected(&input_socket->owner_node(), true); + } } } @@ -1135,22 +1174,21 @@ static int node_select_linked_from_exec(bContext *C, wmOperator *UNUSED(op)) SpaceNode &snode = *CTX_wm_space_node(C); bNodeTree &node_tree = *snode.edittree; - LISTBASE_FOREACH (bNode *, node, &node_tree.nodes) { - node->flag &= ~NODE_TEST; - } + node_tree.ensure_topology_cache(); - LISTBASE_FOREACH (bNodeLink *, link, &node_tree.links) { - if (nodeLinkIsHidden(link)) { - continue; - } - if (link->fromnode && link->tonode && (link->tonode->flag & NODE_SELECT)) { - link->fromnode->flag |= NODE_TEST; - } - } + Set<bNode *> initial_selection = get_selected_nodes(node_tree); - LISTBASE_FOREACH (bNode *, node, &node_tree.nodes) { - if (node->flag & NODE_TEST) { - nodeSetSelected(node, true); + for (bNode *node : initial_selection) { + for (bNodeSocket *input_socket : node->input_sockets()) { + if (!input_socket->is_available()) { + continue; + } + for (bNodeSocket *output_socket : input_socket->directly_linked_sockets()) { + if (!output_socket->is_available()) { + continue; + } + nodeSetSelected(&output_socket->owner_node(), true); + } } } @@ -1298,7 +1336,7 @@ static void node_find_create_label(const bNode *node, char *str, int maxlen) } /* Generic search invoke. */ -static void node_find_update_fn(const struct bContext *C, +static void node_find_update_fn(const bContext *C, void *UNUSED(arg), const char *str, uiSearchItems *items, @@ -1330,7 +1368,7 @@ static void node_find_update_fn(const struct bContext *C, BLI_string_search_free(search); } -static void node_find_exec_fn(struct bContext *C, void *UNUSED(arg1), void *arg2) +static void node_find_exec_fn(bContext *C, void *UNUSED(arg1), void *arg2) { SpaceNode *snode = CTX_wm_space_node(C); bNode *active = (bNode *)arg2; diff --git a/source/blender/editors/space_node/node_templates.cc b/source/blender/editors/space_node/node_templates.cc index 58a313c328e..5fc194e02a4 100644 --- a/source/blender/editors/space_node/node_templates.cc +++ b/source/blender/editors/space_node/node_templates.cc @@ -758,43 +758,42 @@ namespace blender::ed::space_node { /**************************** Node Tree Layout *******************************/ static void ui_node_draw_input( - uiLayout *layout, bContext *C, bNodeTree *ntree, bNode *node, bNodeSocket *input, int depth); + uiLayout &layout, bContext &C, bNodeTree &ntree, bNode &node, bNodeSocket &input, int depth); static void ui_node_draw_node( - uiLayout *layout, bContext *C, bNodeTree *ntree, bNode *node, int depth) + uiLayout &layout, bContext &C, bNodeTree &ntree, bNode &node, int depth) { - bNodeSocket *input; PointerRNA nodeptr; - RNA_pointer_create(&ntree->id, &RNA_Node, node, &nodeptr); + RNA_pointer_create(&ntree.id, &RNA_Node, &node, &nodeptr); - if (node->typeinfo->draw_buttons) { - if (node->type != NODE_GROUP) { - uiLayoutSetPropSep(layout, true); - node->typeinfo->draw_buttons(layout, C, &nodeptr); + if (node.typeinfo->draw_buttons) { + if (node.type != NODE_GROUP) { + uiLayoutSetPropSep(&layout, true); + node.typeinfo->draw_buttons(&layout, &C, &nodeptr); } } - for (input = (bNodeSocket *)node->inputs.first; input; input = input->next) { - ui_node_draw_input(layout, C, ntree, node, input, depth + 1); + LISTBASE_FOREACH (bNodeSocket *, input, &node.inputs) { + ui_node_draw_input(layout, C, ntree, node, *input, depth + 1); } } static void ui_node_draw_input( - uiLayout *layout, bContext *C, bNodeTree *ntree, bNode *node, bNodeSocket *input, int depth) + uiLayout &layout, bContext &C, bNodeTree &ntree, bNode &node, bNodeSocket &input, int depth) { PointerRNA inputptr, nodeptr; - uiBlock *block = uiLayoutGetBlock(layout); + uiBlock *block = uiLayoutGetBlock(&layout); uiLayout *row = nullptr; bool dependency_loop; - if (input->flag & SOCK_UNAVAIL) { + if (input.flag & SOCK_UNAVAIL) { return; } /* to avoid eternal loops on cyclic dependencies */ - node->flag |= NODE_TEST; - bNode *lnode = (input->link) ? input->link->fromnode : nullptr; + node.flag |= NODE_TEST; + bNode *lnode = (input.link) ? input.link->fromnode : nullptr; dependency_loop = (lnode && (lnode->flag & NODE_TEST)); if (dependency_loop) { @@ -802,10 +801,10 @@ static void ui_node_draw_input( } /* socket RNA pointer */ - RNA_pointer_create(&ntree->id, &RNA_NodeSocket, input, &inputptr); - RNA_pointer_create(&ntree->id, &RNA_Node, node, &nodeptr); + RNA_pointer_create(&ntree.id, &RNA_NodeSocket, &input, &inputptr); + RNA_pointer_create(&ntree.id, &RNA_Node, &node, &nodeptr); - row = uiLayoutRow(layout, true); + row = uiLayoutRow(&layout, true); /* Decorations are added manually here. */ uiLayoutSetPropDecorate(row, false); @@ -821,8 +820,8 @@ static void ui_node_draw_input( if (lnode && (lnode->inputs.first || (lnode->typeinfo->draw_buttons && lnode->type != NODE_GROUP))) { - int icon = (input->flag & SOCK_COLLAPSED) ? ICON_DISCLOSURE_TRI_RIGHT : - ICON_DISCLOSURE_TRI_DOWN; + int icon = (input.flag & SOCK_COLLAPSED) ? ICON_DISCLOSURE_TRI_RIGHT : + ICON_DISCLOSURE_TRI_DOWN; uiItemR(sub, &inputptr, "show_expanded", UI_ITEM_R_ICON_ONLY, "", icon); } @@ -831,7 +830,7 @@ static void ui_node_draw_input( sub = uiLayoutRow(sub, true); uiLayoutSetAlignment(sub, UI_LAYOUT_ALIGN_RIGHT); - uiItemL(sub, IFACE_(input->name), ICON_NONE); + uiItemL(sub, IFACE_(input.name), ICON_NONE); } if (dependency_loop) { @@ -840,28 +839,28 @@ static void ui_node_draw_input( } else if (lnode) { /* input linked to a node */ - uiTemplateNodeLink(row, C, ntree, node, input); + uiTemplateNodeLink(row, &C, &ntree, &node, &input); add_dummy_decorator = true; - if (depth == 0 || !(input->flag & SOCK_COLLAPSED)) { + if (depth == 0 || !(input.flag & SOCK_COLLAPSED)) { if (depth == 0) { - uiItemS(layout); + uiItemS(&layout); } - ui_node_draw_node(layout, C, ntree, lnode, depth); + ui_node_draw_node(layout, C, ntree, *lnode, depth); } } else { uiLayout *sub = uiLayoutRow(row, true); - uiTemplateNodeLink(sub, C, ntree, node, input); + uiTemplateNodeLink(sub, &C, &ntree, &node, &input); - if (input->flag & SOCK_HIDE_VALUE) { + if (input.flag & SOCK_HIDE_VALUE) { add_dummy_decorator = true; } /* input not linked, show value */ else { - switch (input->type) { + switch (input.type) { case SOCK_VECTOR: uiItemS(sub); sub = uiLayoutColumn(sub, true); @@ -876,11 +875,11 @@ static void ui_node_draw_input( break; case SOCK_STRING: { const bNodeTree *node_tree = (const bNodeTree *)nodeptr.owner_id; - SpaceNode *snode = CTX_wm_space_node(C); + SpaceNode *snode = CTX_wm_space_node(&C); if (node_tree->type == NTREE_GEOMETRY && snode != nullptr) { /* Only add the attribute search in the node editor, in other places there is not * enough context. */ - node_geometry_add_attribute_search_button(*C, *node, inputptr, *sub); + node_geometry_add_attribute_search_button(C, node, inputptr, *sub); } else { uiItemR(sub, &inputptr, "default_value", 0, "", ICON_NONE); @@ -899,10 +898,10 @@ static void ui_node_draw_input( uiItemDecoratorR(split_wrapper.decorate_column, nullptr, nullptr, 0); } - node_socket_add_tooltip(ntree, node, input, row); + node_socket_add_tooltip(ntree, node, input, *row); /* clear */ - node->flag &= ~NODE_TEST; + node.flag &= ~NODE_TEST; } } // namespace blender::ed::space_node @@ -924,9 +923,9 @@ void uiTemplateNodeView( } if (input) { - ui_node_draw_input(layout, C, ntree, node, input, 0); + ui_node_draw_input(*layout, *C, *ntree, *node, *input, 0); } else { - ui_node_draw_node(layout, C, ntree, node, 0); + ui_node_draw_node(*layout, *C, *ntree, *node, 0); } } diff --git a/source/blender/editors/space_node/node_view.cc b/source/blender/editors/space_node/node_view.cc index 6f30632244b..33a75385022 100644 --- a/source/blender/editors/space_node/node_view.cc +++ b/source/blender/editors/space_node/node_view.cc @@ -177,7 +177,7 @@ void NODE_OT_view_selected(wmOperatorType *ot) * \{ */ struct NodeViewMove { - int mvalo[2]; + int2 mvalo; int xmin, ymin, xmax, ymax; /** Original Offset for cancel. */ float xof_orig, yof_orig; @@ -192,10 +192,10 @@ static int snode_bg_viewmove_modal(bContext *C, wmOperator *op, const wmEvent *e switch (event->type) { case MOUSEMOVE: - snode->xof -= (nvm->mvalo[0] - event->mval[0]); - snode->yof -= (nvm->mvalo[1] - event->mval[1]); - nvm->mvalo[0] = event->mval[0]; - nvm->mvalo[1] = event->mval[1]; + snode->xof -= (nvm->mvalo.x - event->mval[0]); + snode->yof -= (nvm->mvalo.y - event->mval[1]); + nvm->mvalo.x = event->mval[0]; + nvm->mvalo.y = event->mval[1]; /* prevent dragging image outside of the window and losing it! */ CLAMP(snode->xof, nvm->xmin, nvm->xmax); @@ -240,7 +240,7 @@ static int snode_bg_viewmove_invoke(bContext *C, wmOperator *op, const wmEvent * NodeViewMove *nvm; Image *ima; ImBuf *ibuf; - const float pad = 32.0f; /* better be bigger than scrollbars */ + const float pad = 32.0f; /* Better be bigger than scroll-bars. */ void *lock; @@ -252,10 +252,10 @@ static int snode_bg_viewmove_invoke(bContext *C, wmOperator *op, const wmEvent * return OPERATOR_CANCELLED; } - nvm = MEM_cnew<NodeViewMove>("NodeViewMove struct"); + nvm = MEM_cnew<NodeViewMove>(__func__); op->customdata = nvm; - nvm->mvalo[0] = event->mval[0]; - nvm->mvalo[1] = event->mval[1]; + nvm->mvalo.x = event->mval[0]; + nvm->mvalo.y = event->mval[1]; nvm->xmin = -(region->winx / 2) - (ibuf->x * (0.5f * snode->zoom)) + pad; nvm->xmax = (region->winx / 2) + (ibuf->x * (0.5f * snode->zoom)) - pad; @@ -447,7 +447,7 @@ static void sample_draw(const bContext *C, ARegion *region, void *arg_info) } // namespace blender::ed::space_node bool ED_space_node_get_position( - Main *bmain, SpaceNode *snode, struct ARegion *region, const int mval[2], float fpos[2]) + Main *bmain, SpaceNode *snode, ARegion *region, const int mval[2], float fpos[2]) { if (!ED_node_is_compositor(snode) || (snode->flag & SNODE_BACKDRAW) == 0) { return false; @@ -645,7 +645,7 @@ static int sample_invoke(bContext *C, wmOperator *op, const wmEvent *event) /* Don't handle events intended for nodes (which rely on click/drag distinction). * which this operator would use since sampling is normally activated on press, see: T98191. */ - if (node_or_socket_isect_event(C, event)) { + if (node_or_socket_isect_event(*C, *event)) { return OPERATOR_PASS_THROUGH; } diff --git a/source/blender/editors/space_node/space_node.cc b/source/blender/editors/space_node/space_node.cc index 15afd024766..fae3eb1a143 100644 --- a/source/blender/editors/space_node/space_node.cc +++ b/source/blender/editors/space_node/space_node.cc @@ -302,7 +302,7 @@ static void node_free(SpaceLink *sl) } /* spacetype; init callback */ -static void node_init(struct wmWindowManager *UNUSED(wm), ScrArea *area) +static void node_init(wmWindowManager *UNUSED(wm), ScrArea *area) { SpaceNode *snode = (SpaceNode *)area->spacedata.first; @@ -362,7 +362,7 @@ static void node_area_tag_tree_recalc(SpaceNode *snode, ScrArea *area) static void node_area_listener(const wmSpaceTypeListenerParams *params) { ScrArea *area = params->area; - wmNotifier *wmn = params->notifier; + const wmNotifier *wmn = params->notifier; /* NOTE: #ED_area_tag_refresh will re-execute compositor. */ SpaceNode *snode = (SpaceNode *)area->spacedata.first; @@ -511,7 +511,7 @@ static void node_area_listener(const wmSpaceTypeListenerParams *params) } } -static void node_area_refresh(const struct bContext *C, ScrArea *area) +static void node_area_refresh(const bContext *C, ScrArea *area) { /* default now: refresh node is starting preview */ SpaceNode *snode = (SpaceNode *)area->spacedata.first; @@ -526,7 +526,7 @@ static void node_area_refresh(const struct bContext *C, ScrArea *area) if (snode->runtime->recalc_auto_compositing) { snode->runtime->recalc_auto_compositing = false; snode->runtime->recalc_regular_compositing = false; - node_render_changed_exec((struct bContext *)C, nullptr); + node_render_changed_exec((bContext *)C, nullptr); } else if (snode->runtime->recalc_regular_compositing) { snode->runtime->recalc_regular_compositing = false; @@ -753,7 +753,7 @@ static void node_header_region_draw(const bContext *C, ARegion *region) static void node_region_listener(const wmRegionListenerParams *params) { ARegion *region = params->region; - wmNotifier *wmn = params->notifier; + const wmNotifier *wmn = params->notifier; wmGizmoMap *gzmap = region->gizmo_map; /* context changes */ @@ -973,9 +973,7 @@ static void node_id_remap_cb(ID *old_id, ID *new_id, void *user_data) } } -static void node_id_remap(ScrArea *UNUSED(area), - SpaceLink *slink, - const struct IDRemapper *mappings) +static void node_id_remap(ScrArea *UNUSED(area), SpaceLink *slink, const IDRemapper *mappings) { /* Although we should be able to perform all the mappings in a single go this lead to issues when * running the python test cases. Somehow the nodetree/edittree weren't updated to the new @@ -1023,7 +1021,7 @@ void ED_spacetype_node() ARegionType *art; st->spaceid = SPACE_NODE; - strncpy(st->name, "Node", BKE_ST_MAXNAME); + STRNCPY(st->name, "Node"); st->create = node_create; st->free = node_free; diff --git a/source/blender/editors/space_outliner/CMakeLists.txt b/source/blender/editors/space_outliner/CMakeLists.txt index b9f79303a06..d29028dad63 100644 --- a/source/blender/editors/space_outliner/CMakeLists.txt +++ b/source/blender/editors/space_outliner/CMakeLists.txt @@ -13,7 +13,6 @@ set(INC ../../sequencer ../../windowmanager ../../../../intern/clog - ../../../../intern/glew-mx ../../../../intern/guardedalloc # RNA_prototypes.h ${CMAKE_BINARY_DIR}/source/blender/makesrna diff --git a/source/blender/editors/space_outliner/outliner_collections.cc b/source/blender/editors/space_outliner/outliner_collections.cc index 02d54e4f702..48e7aa381ef 100644 --- a/source/blender/editors/space_outliner/outliner_collections.cc +++ b/source/blender/editors/space_outliner/outliner_collections.cc @@ -38,6 +38,8 @@ #include "outliner_intern.hh" /* own include */ +namespace blender::ed::outliner { + /* -------------------------------------------------------------------- */ /** \name Utility API * \{ */ @@ -86,7 +88,7 @@ Collection *outliner_collection_from_tree_element(const TreeElement *te) return nullptr; } -TreeTraversalAction outliner_find_selected_collections(TreeElement *te, void *customdata) +TreeTraversalAction outliner_collect_selected_collections(TreeElement *te, void *customdata) { struct IDsSelectedData *data = static_cast<IDsSelectedData *>(customdata); TreeStoreElem *tselem = TREESTORE(te); @@ -103,7 +105,7 @@ TreeTraversalAction outliner_find_selected_collections(TreeElement *te, void *cu return TRAVERSE_CONTINUE; } -TreeTraversalAction outliner_find_selected_objects(TreeElement *te, void *customdata) +TreeTraversalAction outliner_collect_selected_objects(TreeElement *te, void *customdata) { struct IDsSelectedData *data = static_cast<IDsSelectedData *>(customdata); TreeStoreElem *tselem = TREESTORE(te); @@ -122,15 +124,19 @@ TreeTraversalAction outliner_find_selected_objects(TreeElement *te, void *custom return TRAVERSE_CONTINUE; } +} // namespace blender::ed::outliner + void ED_outliner_selected_objects_get(const bContext *C, ListBase *objects) { + using namespace blender::ed::outliner; + SpaceOutliner *space_outliner = CTX_wm_space_outliner(C); struct IDsSelectedData data = {{nullptr}}; outliner_tree_traverse(space_outliner, &space_outliner->tree, 0, TSE_SELECTED, - outliner_find_selected_objects, + outliner_collect_selected_objects, &data); LISTBASE_FOREACH (LinkData *, link, &data.selected_array) { TreeElement *ten_selected = (TreeElement *)link->data; @@ -140,12 +146,16 @@ void ED_outliner_selected_objects_get(const bContext *C, ListBase *objects) BLI_freelistN(&data.selected_array); } +namespace blender::ed::outliner { + /** \} */ /* -------------------------------------------------------------------- */ /** \name Poll Functions * \{ */ +} // namespace blender::ed::outliner + bool ED_outliner_collections_editor_poll(bContext *C) { SpaceOutliner *space_outliner = CTX_wm_space_outliner(C); @@ -153,6 +163,8 @@ bool ED_outliner_collections_editor_poll(bContext *C) ELEM(space_outliner->outlinevis, SO_VIEW_LAYER, SO_SCENES, SO_LIBRARIES); } +namespace blender::ed::outliner { + static bool outliner_view_layer_collections_editor_poll(bContext *C) { SpaceOutliner *space_outliner = CTX_wm_space_outliner(C); @@ -284,7 +296,7 @@ struct CollectionEditData { bool is_liboverride_hierarchy_root_allowed; }; -static TreeTraversalAction collection_find_data_to_edit(TreeElement *te, void *customdata) +static TreeTraversalAction collection_collect_data_to_edit(TreeElement *te, void *customdata) { CollectionEditData *data = static_cast<CollectionEditData *>(customdata); Collection *collection = outliner_collection_from_tree_element(te); @@ -333,8 +345,12 @@ void outliner_collection_delete( /* We first walk over and find the Collections we actually want to delete * (ignoring duplicates). */ - outliner_tree_traverse( - space_outliner, &space_outliner->tree, 0, TSE_SELECTED, collection_find_data_to_edit, &data); + outliner_tree_traverse(space_outliner, + &space_outliner->tree, + 0, + TSE_SELECTED, + collection_collect_data_to_edit, + &data); /* Effectively delete the collections. */ GSetIterator collections_to_edit_iter; @@ -361,10 +377,8 @@ void outliner_collection_delete( if (parent->flag & COLLECTION_IS_MASTER) { BLI_assert(parent->id.flag & LIB_EMBEDDED_DATA); - const IDTypeInfo *id_type = BKE_idtype_get_info_from_id(&parent->id); - BLI_assert(id_type->owner_get != nullptr); - - ID *scene_owner = id_type->owner_get(bmain, &parent->id, NULL); + ID *scene_owner = BKE_id_owner_get(&parent->id); + BLI_assert(scene_owner != nullptr); BLI_assert(GS(scene_owner->name) == ID_SCE); if (ID_IS_LINKED(scene_owner) || ID_IS_OVERRIDE_LIBRARY(scene_owner)) { skip = true; @@ -397,7 +411,8 @@ static int collection_hierarchy_delete_exec(bContext *C, wmOperator *op) Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); struct wmMsgBus *mbus = CTX_wm_message_bus(C); - const Base *basact_prev = BASACT(view_layer); + BKE_view_layer_synced_ensure(scene, view_layer); + const Base *basact_prev = BKE_view_layer_active_base_get(view_layer); outliner_collection_delete(C, bmain, scene, op->reports, true); @@ -406,7 +421,8 @@ static int collection_hierarchy_delete_exec(bContext *C, wmOperator *op) WM_main_add_notifier(NC_SCENE | ND_LAYER, nullptr); - if (basact_prev != BASACT(view_layer)) { + BKE_view_layer_synced_ensure(scene, view_layer); + if (basact_prev != BKE_view_layer_active_base_get(view_layer)) { WM_msg_publish_rna_prop(mbus, &scene->id, view_layer, LayerObjects, active); } @@ -477,6 +493,7 @@ static LayerCollection *outliner_active_layer_collection(bContext *C) static int collection_objects_select_exec(bContext *C, wmOperator *op) { + Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); LayerCollection *layer_collection = outliner_active_layer_collection(C); bool deselect = STREQ(op->idname, "OUTLINER_OT_collection_objects_deselect"); @@ -485,9 +502,8 @@ static int collection_objects_select_exec(bContext *C, wmOperator *op) return OPERATOR_CANCELLED; } - BKE_layer_collection_objects_select(view_layer, layer_collection, deselect); + BKE_layer_collection_objects_select(scene, view_layer, layer_collection, deselect); - Scene *scene = CTX_data_scene(C); DEG_id_tag_update(&scene->id, ID_RECALC_SELECT); WM_main_add_notifier(NC_SCENE | ND_OB_SELECT, scene); ED_outliner_select_sync_from_object_tag(C); @@ -594,10 +610,7 @@ static int collection_duplicate_exec(bContext *C, wmOperator *op) else if (parent != nullptr && (parent->flag & COLLECTION_IS_MASTER) != 0) { BLI_assert(parent->id.flag & LIB_EMBEDDED_DATA); - const IDTypeInfo *id_type = BKE_idtype_get_info_from_id(&parent->id); - BLI_assert(id_type->owner_get != nullptr); - - Scene *scene_owner = (Scene *)id_type->owner_get(bmain, &parent->id, NULL); + Scene *scene_owner = reinterpret_cast<Scene *>(BKE_id_owner_get(&parent->id)); BLI_assert(scene_owner != nullptr); BLI_assert(GS(scene_owner->id.name) == ID_SCE); @@ -695,8 +708,12 @@ static int collection_link_exec(bContext *C, wmOperator *op) data.collections_to_edit = BLI_gset_ptr_new(__func__); /* We first walk over and find the Collections we actually want to link (ignoring duplicates). */ - outliner_tree_traverse( - space_outliner, &space_outliner->tree, 0, TSE_SELECTED, collection_find_data_to_edit, &data); + outliner_tree_traverse(space_outliner, + &space_outliner->tree, + 0, + TSE_SELECTED, + collection_collect_data_to_edit, + &data); /* Effectively link the collections. */ GSetIterator collections_to_edit_iter; @@ -754,8 +771,12 @@ static int collection_instance_exec(bContext *C, wmOperator *UNUSED(op)) /* We first walk over and find the Collections we actually want to instance * (ignoring duplicates). */ - outliner_tree_traverse( - space_outliner, &space_outliner->tree, 0, TSE_SELECTED, collection_find_data_to_edit, &data); + outliner_tree_traverse(space_outliner, + &space_outliner->tree, + 0, + TSE_SELECTED, + collection_collect_data_to_edit, + &data); /* Find an active collection to add to, that doesn't give dependency cycles. */ LayerCollection *active_lc = BKE_layer_collection_get_active(view_layer); @@ -812,7 +833,7 @@ void OUTLINER_OT_collection_instance(wmOperatorType *ot) /** \name Exclude Collection * \{ */ -static TreeTraversalAction layer_collection_find_data_to_edit(TreeElement *te, void *customdata) +static TreeTraversalAction layer_collection_collect_data_to_edit(TreeElement *te, void *customdata) { CollectionEditData *data = static_cast<CollectionEditData *>(customdata); TreeStoreElem *tselem = TREESTORE(te); @@ -857,7 +878,7 @@ static bool collections_view_layer_poll(bContext *C, bool clear, int flag) &space_outliner->tree, 0, TSE_SELECTED, - layer_collection_find_data_to_edit, + layer_collection_collect_data_to_edit, &data); GSetIterator collections_to_edit_iter; @@ -929,7 +950,7 @@ static int collection_view_layer_exec(bContext *C, wmOperator *op) &space_outliner->tree, 0, TSE_SELECTED, - layer_collection_find_data_to_edit, + layer_collection_collect_data_to_edit, &data); GSetIterator collections_to_edit_iter; @@ -941,7 +962,7 @@ static int collection_view_layer_exec(bContext *C, wmOperator *op) BLI_gset_free(data.collections_to_edit, nullptr); - BKE_layer_collection_sync(scene, view_layer); + BKE_view_layer_need_resync_tag(view_layer); DEG_relations_tag_update(bmain); WM_main_add_notifier(NC_SCENE | ND_LAYER, nullptr); @@ -1063,7 +1084,7 @@ static int collection_isolate_exec(bContext *C, wmOperator *op) &space_outliner->tree, 0, TSE_SELECTED, - layer_collection_find_data_to_edit, + layer_collection_collect_data_to_edit, &data); GSetIterator collections_to_edit_iter; @@ -1090,7 +1111,7 @@ static int collection_isolate_exec(bContext *C, wmOperator *op) } BLI_gset_free(data.collections_to_edit, nullptr); - BKE_layer_collection_sync(scene, view_layer); + BKE_view_layer_need_resync_tag(view_layer); DEG_id_tag_update(&scene->id, ID_RECALC_BASE_FLAGS); WM_main_add_notifier(NC_SCENE | ND_LAYER_CONTENT, nullptr); @@ -1163,18 +1184,18 @@ static int collection_visibility_exec(bContext *C, wmOperator *op) &space_outliner->tree, 0, TSE_SELECTED, - layer_collection_find_data_to_edit, + layer_collection_collect_data_to_edit, &data); GSetIterator collections_to_edit_iter; GSET_ITER (collections_to_edit_iter, data.collections_to_edit) { LayerCollection *layer_collection = static_cast<LayerCollection *>( BLI_gsetIterator_getKey(&collections_to_edit_iter)); - BKE_layer_collection_set_visible(view_layer, layer_collection, show, is_inside); + BKE_layer_collection_set_visible(scene, view_layer, layer_collection, show, is_inside); } BLI_gset_free(data.collections_to_edit, nullptr); - BKE_layer_collection_sync(scene, view_layer); + BKE_view_layer_need_resync_tag(view_layer); DEG_id_tag_update(&scene->id, ID_RECALC_BASE_FLAGS); WM_main_add_notifier(NC_SCENE | ND_LAYER_CONTENT, nullptr); @@ -1315,7 +1336,7 @@ static int collection_flag_exec(bContext *C, wmOperator *op) &space_outliner->tree, 0, TSE_SELECTED, - layer_collection_find_data_to_edit, + layer_collection_collect_data_to_edit, &data); GSetIterator collections_to_edit_iter; GSET_ITER (collections_to_edit_iter, data.collections_to_edit) { @@ -1344,7 +1365,7 @@ static int collection_flag_exec(bContext *C, wmOperator *op) &space_outliner->tree, 0, TSE_SELECTED, - collection_find_data_to_edit, + collection_collect_data_to_edit, &data); GSetIterator collections_to_edit_iter; GSET_ITER (collections_to_edit_iter, data.collections_to_edit) { @@ -1364,7 +1385,7 @@ static int collection_flag_exec(bContext *C, wmOperator *op) BLI_gset_free(data.collections_to_edit, nullptr); } - BKE_layer_collection_sync(scene, view_layer); + BKE_view_layer_need_resync_tag(view_layer); DEG_id_tag_update(&scene->id, ID_RECALC_BASE_FLAGS); if (!is_render) { @@ -1449,7 +1470,7 @@ struct OutlinerHideEditData { /** \name Visibility for Collection & Object Operators * \{ */ -static TreeTraversalAction outliner_hide_find_data_to_edit(TreeElement *te, void *customdata) +static TreeTraversalAction outliner_hide_collect_data_to_edit(TreeElement *te, void *customdata) { OutlinerHideEditData *data = static_cast<OutlinerHideEditData *>(customdata); TreeStoreElem *tselem = TREESTORE(te); @@ -1473,6 +1494,7 @@ static TreeTraversalAction outliner_hide_find_data_to_edit(TreeElement *te, void } else if ((tselem->type == TSE_SOME_ID) && (te->idcode == ID_OB)) { Object *ob = (Object *)tselem->id; + BKE_view_layer_synced_ensure(data->scene, data->view_layer); Base *base = BKE_view_layer_base_find(data->view_layer, ob); BLI_gset_add(data->bases_to_edit, base); } @@ -1496,14 +1518,14 @@ static int outliner_hide_exec(bContext *C, wmOperator *UNUSED(op)) &space_outliner->tree, 0, TSE_SELECTED, - outliner_hide_find_data_to_edit, + outliner_hide_collect_data_to_edit, &data); GSetIterator collections_to_edit_iter; GSET_ITER (collections_to_edit_iter, data.collections_to_edit) { LayerCollection *layer_collection = static_cast<LayerCollection *>( BLI_gsetIterator_getKey(&collections_to_edit_iter)); - BKE_layer_collection_set_visible(view_layer, layer_collection, false, false); + BKE_layer_collection_set_visible(scene, view_layer, layer_collection, false, false); } BLI_gset_free(data.collections_to_edit, nullptr); @@ -1514,7 +1536,7 @@ static int outliner_hide_exec(bContext *C, wmOperator *UNUSED(op)) } BLI_gset_free(data.bases_to_edit, nullptr); - BKE_layer_collection_sync(scene, view_layer); + BKE_view_layer_need_resync_tag(view_layer); DEG_id_tag_update(&scene->id, ID_RECALC_BASE_FLAGS); WM_main_add_notifier(NC_SCENE | ND_LAYER_CONTENT, nullptr); @@ -1548,11 +1570,12 @@ static int outliner_unhide_all_exec(bContext *C, wmOperator *UNUSED(op)) } /* Unhide all objects. */ - LISTBASE_FOREACH (Base *, base, &view_layer->object_bases) { + BKE_view_layer_synced_ensure(scene, view_layer); + LISTBASE_FOREACH (Base *, base, BKE_view_layer_object_bases_get(view_layer)) { base->flag &= ~BASE_HIDDEN; } - BKE_layer_collection_sync(scene, view_layer); + BKE_view_layer_need_resync_tag(view_layer); DEG_id_tag_update(&scene->id, ID_RECALC_BASE_FLAGS); WM_main_add_notifier(NC_SCENE | ND_LAYER_CONTENT, nullptr); @@ -1592,7 +1615,7 @@ static int outliner_color_tag_set_exec(bContext *C, wmOperator *op) &space_outliner->tree, 0, TSE_SELECTED, - outliner_find_selected_collections, + outliner_collect_selected_collections, &selected); LISTBASE_FOREACH (LinkData *, link, &selected.selected_array) { @@ -1636,3 +1659,5 @@ void OUTLINER_OT_collection_color_tag_set(wmOperatorType *ot) } /** \} */ + +} // namespace blender::ed::outliner diff --git a/source/blender/editors/space_outliner/outliner_context.cc b/source/blender/editors/space_outliner/outliner_context.cc index 1a804cb58b8..001bda57fa2 100644 --- a/source/blender/editors/space_outliner/outliner_context.cc +++ b/source/blender/editors/space_outliner/outliner_context.cc @@ -14,7 +14,7 @@ #include "outliner_intern.hh" #include "tree/tree_iterator.hh" -using namespace blender::ed::outliner; +namespace blender::ed::outliner { static void outliner_context_selected_ids_recursive(const SpaceOutliner &space_outliner, bContextDataResult *result) @@ -55,3 +55,5 @@ int /*eContextResult*/ outliner_context(const bContext *C, return CTX_RESULT_MEMBER_NOT_FOUND; } + +} // namespace blender::ed::outliner diff --git a/source/blender/editors/space_outliner/outliner_dragdrop.cc b/source/blender/editors/space_outliner/outliner_dragdrop.cc index 2fa512b4006..758928fed8e 100644 --- a/source/blender/editors/space_outliner/outliner_dragdrop.cc +++ b/source/blender/editors/space_outliner/outliner_dragdrop.cc @@ -45,6 +45,8 @@ #include "outliner_intern.hh" +namespace blender::ed::outliner { + static Collection *collection_parent_from_ID(ID *id); /* -------------------------------------------------------------------- */ @@ -291,6 +293,7 @@ static bool parent_drop_allowed(TreeElement *te, Object *potential_child) * active scene and parenting them is allowed (sergey) */ if (scene) { LISTBASE_FOREACH (ViewLayer *, view_layer, &scene->view_layers) { + BKE_view_layer_synced_ensure(scene, view_layer); if (BKE_view_layer_base_find(view_layer, potential_child)) { return true; } @@ -578,6 +581,7 @@ static int scene_drop_invoke(bContext *C, wmOperator *UNUSED(op), const wmEvent BKE_collection_object_add(bmain, collection, ob); LISTBASE_FOREACH (ViewLayer *, view_layer, &scene->view_layers) { + BKE_view_layer_synced_ensure(scene, view_layer); Base *base = BKE_view_layer_base_find(view_layer, ob); if (base) { ED_object_base_select(base, BA_SELECT); @@ -1474,7 +1478,7 @@ static int outliner_item_drag_drop_invoke(bContext *C, &space_outliner->tree, 0, TSE_SELECTED, - outliner_find_selected_objects, + outliner_collect_selected_objects, &selected); } else { @@ -1482,7 +1486,7 @@ static int outliner_item_drag_drop_invoke(bContext *C, &space_outliner->tree, 0, TSE_SELECTED, - outliner_find_selected_collections, + outliner_collect_selected_collections, &selected); } @@ -1592,3 +1596,5 @@ void outliner_dropboxes(void) } /** \} */ + +} // namespace blender::ed::outliner diff --git a/source/blender/editors/space_outliner/outliner_draw.cc b/source/blender/editors/space_outliner/outliner_draw.cc index e67eab4e432..3c52f79a80e 100644 --- a/source/blender/editors/space_outliner/outliner_draw.cc +++ b/source/blender/editors/space_outliner/outliner_draw.cc @@ -74,8 +74,7 @@ #include "tree/tree_element_rna.hh" #include "tree/tree_iterator.hh" -using namespace blender; -using namespace blender::ed::outliner; +namespace blender::ed::outliner { /* -------------------------------------------------------------------- */ /** \name Tree Size Functions @@ -285,8 +284,9 @@ static void outliner_object_set_flag_recursive_fn(bContext *C, DEG_id_tag_update(&ob_iter->id, ID_RECALC_COPY_ON_WRITE); } else { + BKE_view_layer_synced_ensure(scene, view_layer); Base *base_iter = BKE_view_layer_base_find(view_layer, ob_iter); - /* Child can be in a collection excluded from viewlayer. */ + /* Child can be in a collection excluded from view-layer. */ if (base_iter == nullptr) { continue; } @@ -302,7 +302,7 @@ static void outliner_object_set_flag_recursive_fn(bContext *C, DEG_relations_tag_update(bmain); } else { - BKE_layer_collection_sync(scene, view_layer); + BKE_view_layer_need_resync_tag(view_layer); DEG_id_tag_update(&scene->id, ID_RECALC_BASE_FLAGS); } } @@ -349,6 +349,7 @@ static void outliner_base_or_object_pointer_create( RNA_id_pointer_create(&ob->id, ptr); } else { + BKE_view_layer_synced_ensure(scene, view_layer); Base *base = BKE_view_layer_base_find(view_layer, ob); RNA_pointer_create(&scene->id, &RNA_ObjectBase, base, ptr); } @@ -701,7 +702,6 @@ static void namebutton_fn(bContext *C, void *tsep, char *oldname) if (ob->type == OB_MBALL) { DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY); } - DEG_id_tag_update(&ob->id, ID_RECALC_COPY_ON_WRITE); break; } default: @@ -732,6 +732,8 @@ static void namebutton_fn(bContext *C, void *tsep, char *oldname) lib->id.tag &= ~LIB_TAG_MISSING; } } + + DEG_id_tag_update(tselem->id, ID_RECALC_COPY_ON_WRITE); } else { switch (tselem->type) { @@ -740,6 +742,7 @@ static void namebutton_fn(bContext *C, void *tsep, char *oldname) bDeformGroup *vg = static_cast<bDeformGroup *>(te->directdata); BKE_object_defgroup_unique_name(vg, ob); WM_msg_publish_rna_prop(mbus, &ob->id, vg, VertexGroup, name); + DEG_id_tag_update(tselem->id, ID_RECALC_COPY_ON_WRITE); break; } case TSE_NLA_ACTION: { @@ -747,6 +750,7 @@ static void namebutton_fn(bContext *C, void *tsep, char *oldname) BKE_main_namemap_remove_name(bmain, &act->id, oldname); BLI_libblock_ensure_unique_name(bmain, act->id.name); WM_msg_publish_rna_prop(mbus, &act->id, &act->id, ID, name); + DEG_id_tag_update(tselem->id, ID_RECALC_COPY_ON_WRITE); break; } case TSE_EBONE: { @@ -761,6 +765,7 @@ static void namebutton_fn(bContext *C, void *tsep, char *oldname) ED_armature_bone_rename(bmain, arm, oldname, newname); WM_msg_publish_rna_prop(mbus, &arm->id, ebone, EditBone, name); WM_event_add_notifier(C, NC_OBJECT | ND_POSE, nullptr); + DEG_id_tag_update(tselem->id, ID_RECALC_COPY_ON_WRITE); } break; } @@ -782,6 +787,7 @@ static void namebutton_fn(bContext *C, void *tsep, char *oldname) ED_armature_bone_rename(bmain, arm, oldname, newname); WM_msg_publish_rna_prop(mbus, &arm->id, bone, Bone, name); WM_event_add_notifier(C, NC_OBJECT | ND_POSE, nullptr); + DEG_id_tag_update(tselem->id, ID_RECALC_COPY_ON_WRITE); break; } case TSE_POSE_CHANNEL: { @@ -804,6 +810,8 @@ static void namebutton_fn(bContext *C, void *tsep, char *oldname) ED_armature_bone_rename(bmain, static_cast<bArmature *>(ob->data), oldname, newname); WM_msg_publish_rna_prop(mbus, &arm->id, pchan->bone, Bone, name); WM_event_add_notifier(C, NC_OBJECT | ND_POSE, nullptr); + DEG_id_tag_update(tselem->id, ID_RECALC_COPY_ON_WRITE); + DEG_id_tag_update(&arm->id, ID_RECALC_COPY_ON_WRITE); break; } case TSE_POSEGRP: { @@ -818,6 +826,7 @@ static void namebutton_fn(bContext *C, void *tsep, char *oldname) sizeof(grp->name)); WM_msg_publish_rna_prop(mbus, &ob->id, grp, ActionGroup, name); WM_event_add_notifier(C, NC_OBJECT | ND_POSE, ob); + DEG_id_tag_update(tselem->id, ID_RECALC_COPY_ON_WRITE); break; } case TSE_GP_LAYER: { @@ -834,6 +843,7 @@ static void namebutton_fn(bContext *C, void *tsep, char *oldname) WM_msg_publish_rna_prop(mbus, &gpd->id, gpl, GPencilLayer, info); DEG_id_tag_update(&gpd->id, ID_RECALC_GEOMETRY); WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_SELECTED, gpd); + DEG_id_tag_update(tselem->id, ID_RECALC_COPY_ON_WRITE); break; } case TSE_R_LAYER: { @@ -849,6 +859,7 @@ static void namebutton_fn(bContext *C, void *tsep, char *oldname) BKE_view_layer_rename(bmain, scene, view_layer, newname); WM_msg_publish_rna_prop(mbus, &scene->id, view_layer, ViewLayer, name); WM_event_add_notifier(C, NC_ID | NA_RENAME, nullptr); + DEG_id_tag_update(tselem->id, ID_RECALC_COPY_ON_WRITE); break; } case TSE_LAYER_COLLECTION: { @@ -858,6 +869,7 @@ static void namebutton_fn(bContext *C, void *tsep, char *oldname) BLI_libblock_ensure_unique_name(bmain, collection->id.name); WM_msg_publish_rna_prop(mbus, &collection->id, &collection->id, ID, name); WM_event_add_notifier(C, NC_ID | NA_RENAME, nullptr); + DEG_id_tag_update(tselem->id, ID_RECALC_COPY_ON_WRITE); break; } } @@ -1136,6 +1148,7 @@ static void outliner_draw_restrictbuts(uiBlock *block, RNA_id_pointer_create(&ob->id, &ptr); if (space_outliner->show_restrict_flags & SO_RESTRICT_HIDE) { + BKE_view_layer_synced_ensure(scene, view_layer); Base *base = (te->directdata) ? (Base *)te->directdata : BKE_view_layer_base_find(view_layer, ob); if (base) { @@ -1948,7 +1961,7 @@ static void outliner_draw_separator(ARegion *region, const int x) GPU_line_width(1.0f); uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); - immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); immUniformThemeColorShadeAlpha(TH_BACK, -15, -200); immBegin(GPU_PRIM_LINES, 2); @@ -3203,10 +3216,12 @@ static bool element_should_draw_faded(const TreeViewContext *tvc, case ID_OB: { const Object *ob = (const Object *)tselem->id; /* Lookup in view layer is logically const as it only checks a cache. */ + BKE_view_layer_synced_ensure(tvc->scene, tvc->view_layer); const Base *base = (te->directdata) ? (const Base *)te->directdata : BKE_view_layer_base_find( (ViewLayer *)tvc->view_layer, (Object *)ob); - const bool is_visible = (base != nullptr) && (base->flag & BASE_VISIBLE_VIEWLAYER); + const bool is_visible = (base != nullptr) && + (base->flag & BASE_ENABLED_AND_VISIBLE_IN_DEFAULT_VIEWPORT); if (!is_visible) { return true; } @@ -3270,6 +3285,7 @@ static void outliner_draw_tree_element(bContext *C, if (tselem->type == TSE_SOME_ID) { if (te->idcode == ID_OB) { Object *ob = (Object *)tselem->id; + BKE_view_layer_synced_ensure(tvc->scene, tvc->view_layer); Base *base = (te->directdata) ? (Base *)te->directdata : BKE_view_layer_base_find(tvc->view_layer, ob); const bool is_selected = (base != nullptr) && ((base->flag & BASE_SELECTED) != 0); @@ -3325,7 +3341,7 @@ static void outliner_draw_tree_element(bContext *C, /* Scene collection in view layer can't expand/collapse. */ } else if (te->subtree.first || ((tselem->type == TSE_SOME_ID) && (te->idcode == ID_SCE)) || - (te->flag & TE_LAZY_CLOSED)) { + (te->flag & TE_PRETEND_HAS_CHILDREN)) { /* Open/close icon, only when sub-levels, except for scene. */ int icon_x = startx; @@ -3541,7 +3557,7 @@ static void outliner_draw_hierarchy_lines(SpaceOutliner *space_outliner, uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); uchar col[4]; - immBindBuiltinProgram(GPU_SHADER_2D_LINE_DASHED_UNIFORM_COLOR); + immBindBuiltinProgram(GPU_SHADER_3D_LINE_DASHED_UNIFORM_COLOR); float viewport_size[4]; GPU_viewport_size_get_f(viewport_size); @@ -3572,7 +3588,7 @@ static void outliner_draw_struct_marks(ARegion *region, if (tselem->type == TSE_RNA_STRUCT) { GPUVertFormat *format = immVertexFormat(); uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_I32, 2, GPU_FETCH_INT_TO_FLOAT); - immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); immThemeColorShadeAlpha(TH_BACK, -15, -200); immRecti(pos, 0, *starty + 1, (int)region->v2d.cur.xmax, *starty + UI_UNIT_Y - 1); immUnbindProgram(); @@ -3585,7 +3601,7 @@ static void outliner_draw_struct_marks(ARegion *region, if (tselem->type == TSE_RNA_STRUCT) { GPUVertFormat *format = immVertexFormat(); uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); - immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); immThemeColorShadeAlpha(TH_BACK, -15, -200); immBegin(GPU_PRIM_LINES, 2); @@ -3690,7 +3706,7 @@ static void outliner_draw_highlights(ARegion *region, GPU_blend(GPU_BLEND_ALPHA); GPUVertFormat *format = immVertexFormat(); uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_I32, 2, GPU_FETCH_INT_TO_FLOAT); - immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); outliner_draw_highlights(pos, region, space_outliner, @@ -3791,7 +3807,7 @@ static void outliner_back(ARegion *region) GPUVertFormat *format = immVertexFormat(); uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); - immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); float col_alternating[4]; UI_GetThemeColor4fv(TH_ROW_ALTERNATE, col_alternating); @@ -3843,7 +3859,7 @@ static void outliner_update_viewable_area(ARegion *region, int sizex = outliner_width(space_outliner, tree_width, right_column_width); int sizey = tree_height; - /* Extend size to allow for horizontal scrollbar and extra offset. */ + /* Extend size to allow for horizontal scroll-bar and extra offset. */ sizey += V2D_SCROLL_HEIGHT + OL_Y_OFFSET; UI_view2d_totRect_set(®ion->v2d, sizex, sizey); @@ -3983,3 +3999,5 @@ void draw_outliner(const bContext *C) } /** \} */ + +} // namespace blender::ed::outliner diff --git a/source/blender/editors/space_outliner/outliner_edit.cc b/source/blender/editors/space_outliner/outliner_edit.cc index f22db5d20fc..be3c1547579 100644 --- a/source/blender/editors/space_outliner/outliner_edit.cc +++ b/source/blender/editors/space_outliner/outliner_edit.cc @@ -29,6 +29,7 @@ #include "BKE_blender_copybuffer.h" #include "BKE_context.h" #include "BKE_idtype.h" +#include "BKE_layer.h" #include "BKE_lib_id.h" #include "BKE_lib_override.h" #include "BKE_lib_query.h" @@ -65,6 +66,8 @@ using namespace blender::ed::outliner; +namespace blender::ed::outliner { + static void outliner_show_active(SpaceOutliner *space_outliner, ARegion *region, TreeElement *te, @@ -144,14 +147,10 @@ void OUTLINER_OT_highlight_update(wmOperatorType *ot) /** \name Toggle Open/Closed Operator * \{ */ -void outliner_item_openclose(SpaceOutliner *space_outliner, - TreeElement *te, - bool open, - bool toggle_all) +void outliner_item_openclose(TreeElement *te, bool open, bool toggle_all) { - /* Prevent opening leaf elements in the tree unless in the Data API display mode because in that - * mode subtrees are empty unless expanded. */ - if (space_outliner->outlinevis != SO_DATA_API && BLI_listbase_is_empty(&te->subtree)) { + /* Only allow opening elements with children. */ + if (!(te->flag & TE_PRETEND_HAS_CHILDREN) && BLI_listbase_is_empty(&te->subtree)) { return; } @@ -198,7 +197,7 @@ static int outliner_item_openclose_modal(bContext *C, wmOperator *op, const wmEv /* Only toggle openclose on the same level as the first clicked element */ if (te->xs == data->x_location) { - outliner_item_openclose(space_outliner, te, data->open, false); + outliner_item_openclose(te, data->open, false); outliner_tag_redraw_avoid_rebuild_on_open_change(space_outliner, region); } @@ -242,7 +241,7 @@ static int outliner_item_openclose_invoke(bContext *C, wmOperator *op, const wmE const bool open = (tselem->flag & TSE_CLOSED) || (toggle_all && (outliner_flag_is_any_test(&te->subtree, TSE_CLOSED, 1))); - outliner_item_openclose(space_outliner, te, open, toggle_all); + outliner_item_openclose(te, open, toggle_all); outliner_tag_redraw_avoid_rebuild_on_open_change(space_outliner, region); /* Only toggle once for single click toggling */ @@ -1263,11 +1262,13 @@ static int outliner_open_back(TreeElement *te) /* Return element representing the active base or bone in the outliner, or NULL if none exists */ static TreeElement *outliner_show_active_get_element(bContext *C, SpaceOutliner *space_outliner, + const Scene *scene, ViewLayer *view_layer) { TreeElement *te; - Object *obact = OBACT(view_layer); + BKE_view_layer_synced_ensure(scene, view_layer); + Object *obact = BKE_view_layer_active_object_get(view_layer); if (!obact) { return nullptr; @@ -1318,11 +1319,13 @@ static void outliner_show_active(SpaceOutliner *space_outliner, static int outliner_show_active_exec(bContext *C, wmOperator *UNUSED(op)) { SpaceOutliner *space_outliner = CTX_wm_space_outliner(C); + const Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); ARegion *region = CTX_wm_region(C); View2D *v2d = ®ion->v2d; - TreeElement *active_element = outliner_show_active_get_element(C, space_outliner, view_layer); + TreeElement *active_element = outliner_show_active_get_element( + C, space_outliner, scene, view_layer); if (active_element) { ID *id = TREESTORE(active_element)->id; @@ -1410,129 +1413,6 @@ void OUTLINER_OT_scroll_page(wmOperatorType *ot) /** \} */ -#if 0 /* TODO: probably obsolete now with filtering? */ - -/* -------------------------------------------------------------------- */ -/** \name Search - * \{ */ - - -/* find next element that has this name */ -static TreeElement *outliner_find_name( - SpaceOutliner *space_outliner, ListBase *lb, char *name, int flags, TreeElement *prev, int *prevFound) -{ - TreeElement *te, *tes; - - for (te = lb->first; te; te = te->next) { - int found = outliner_filter_has_name(te, name, flags); - - if (found) { - /* name is right, but is element the previous one? */ - if (prev) { - if ((te != prev) && (*prevFound)) { - return te; - } - if (te == prev) { - *prevFound = 1; - } - } - else { - return te; - } - } - - tes = outliner_find_name(space_outliner, &te->subtree, name, flags, prev, prevFound); - if (tes) { - return tes; - } - } - - /* nothing valid found */ - return nullptr; -} - -static void outliner_find_panel( - Scene *UNUSED(scene), ARegion *region, SpaceOutliner *space_outliner, int again, int flags) -{ - ReportList *reports = nullptr; /* CTX_wm_reports(C); */ - TreeElement *te = nullptr; - TreeElement *last_find; - TreeStoreElem *tselem; - int ytop, xdelta, prevFound = 0; - char name[sizeof(space_outliner->search_string)]; - - /* get last found tree-element based on stored search_tse */ - last_find = outliner_find_tse(space_outliner, &space_outliner->search_tse); - - /* determine which type of search to do */ - if (again && last_find) { - /* no popup panel - previous + user wanted to search for next after previous */ - BLI_strncpy(name, space_outliner->search_string, sizeof(name)); - flags = space_outliner->search_flags; - - /* try to find matching element */ - te = outliner_find_name(space_outliner, &space_outliner->tree, name, flags, last_find, &prevFound); - if (te == nullptr) { - /* no more matches after previous, start from beginning again */ - prevFound = 1; - te = outliner_find_name(space_outliner, &space_outliner->tree, name, flags, last_find, &prevFound); - } - } - else { - /* pop up panel - no previous, or user didn't want search after previous */ - name[0] = '\0'; - // XXX if (sbutton(name, 0, sizeof(name) - 1, "Find: ") && name[0]) { - // te = outliner_find_name(space_outliner, &space_outliner->tree, name, flags, nullptr, &prevFound); - // } - // else return; XXX RETURN! XXX - } - - /* do selection and reveal */ - if (te) { - tselem = TREESTORE(te); - if (tselem) { - /* expand branches so that it will be visible, we need to get correct coordinates */ - if (outliner_open_back(space_outliner, te)) { - outliner_set_coordinates(region, space_outliner); - } - - /* deselect all visible, and select found element */ - outliner_flag_set(space_outliner, &space_outliner->tree, TSE_SELECTED, 0); - tselem->flag |= TSE_SELECTED; - - /* Make `te->ys` center of view. */ - ytop = (int)(te->ys + BLI_rctf_size_y(®ion->v2d.mask) / 2); - if (ytop > 0) { - ytop = 0; - } - region->v2d.cur.ymax = (float)ytop; - region->v2d.cur.ymin = (float)(ytop - BLI_rctf_size_y(®ion->v2d.mask)); - - /* Make `te->xs` ==> `te->xend` center of view. */ - xdelta = (int)(te->xs - region->v2d.cur.xmin); - region->v2d.cur.xmin += xdelta; - region->v2d.cur.xmax += xdelta; - - /* store selection */ - space_outliner->search_tse = *tselem; - - BLI_strncpy(space_outliner->search_string, name, sizeof(space_outliner->search_string)); - space_outliner->search_flags = flags; - - /* redraw */ - ED_region_tag_redraw_no_rebuild(region); - } - } - else { - /* no tree-element found */ - BKE_reportf(reports, RPT_WARNING, "Not found: %s", name); - } -} - -/** \} */ - -#endif /* if 0 */ - /* -------------------------------------------------------------------- */ /** \name Show One Level Operator * \{ */ @@ -2357,3 +2237,5 @@ void OUTLINER_OT_orphans_purge(wmOperatorType *ot) } /** \} */ + +} // namespace blender::ed::outliner diff --git a/source/blender/editors/space_outliner/outliner_intern.hh b/source/blender/editors/space_outliner/outliner_intern.hh index 5362782dd84..ad5d653949c 100644 --- a/source/blender/editors/space_outliner/outliner_intern.hh +++ b/source/blender/editors/space_outliner/outliner_intern.hh @@ -14,10 +14,6 @@ /* Needed for `tree_element_cast()`. */ #include "tree/tree_element.hh" -#ifdef __cplusplus -extern "C" { -#endif - /* internal exports only */ struct ARegion; @@ -27,7 +23,6 @@ struct ListBase; struct Main; struct Object; struct Scene; -struct TreeElement; struct TreeStoreElem; struct ViewLayer; struct bContext; @@ -37,47 +32,52 @@ struct View2D; struct wmKeyConfig; struct wmOperatorType; +namespace blender::bke::outliner::treehash { +class TreeHash; +} + namespace blender::ed::outliner { + class AbstractTreeDisplay; class AbstractTreeElement; -} // namespace blender::ed::outliner -namespace outliner = blender::ed::outliner; +namespace treehash = blender::bke::outliner::treehash; + +struct TreeElement; struct SpaceOutliner_Runtime { /** Object to create and manage the tree for a specific display type (View Layers, Scenes, * Blender File, etc.). */ - std::unique_ptr<outliner::AbstractTreeDisplay> tree_display; + std::unique_ptr<AbstractTreeDisplay> tree_display; - /** Pointers to tree-store elements, grouped by `(id, type, nr)` - * in hash-table for faster searching. */ - struct GHash *treehash; + /* Hash table for tree-store elements, using `(id, type, index)` as key. */ + std::unique_ptr<treehash::TreeHash> tree_hash; SpaceOutliner_Runtime() = default; /** Used for copying runtime data to a duplicated space. */ SpaceOutliner_Runtime(const SpaceOutliner_Runtime &); - ~SpaceOutliner_Runtime(); + ~SpaceOutliner_Runtime() = default; }; -typedef enum TreeElementInsertType { +enum TreeElementInsertType { TE_INSERT_BEFORE, TE_INSERT_AFTER, TE_INSERT_INTO, -} TreeElementInsertType; +}; -typedef enum TreeTraversalAction { +enum TreeTraversalAction { /** Continue traversal regularly, don't skip children. */ TRAVERSE_CONTINUE = 0, /** Stop traversal. */ TRAVERSE_BREAK, /** Continue traversal, but skip children of traversed element. */ TRAVERSE_SKIP_CHILDS, -} TreeTraversalAction; +}; -typedef TreeTraversalAction (*TreeTraversalFunc)(struct TreeElement *te, void *customdata); +typedef TreeTraversalAction (*TreeTraversalFunc)(TreeElement *te, void *customdata); -typedef struct TreeElement { - struct TreeElement *next, *prev, *parent; +struct TreeElement { + TreeElement *next, *prev, *parent; /** * The new inheritance based representation of the element (a derived type of base @@ -85,7 +85,7 @@ typedef struct TreeElement { * be moved to it and operations based on the type should become virtual methods of the class * hierarchy. */ - std::unique_ptr<outliner::AbstractTreeElement> abstract_element; + std::unique_ptr<AbstractTreeElement> abstract_element; ListBase subtree; int xs, ys; /* Do selection. */ @@ -96,12 +96,12 @@ typedef struct TreeElement { short xend; /* Width of item display, for select. */ const char *name; void *directdata; /* Armature Bones, Base, ... */ -} TreeElement; +}; -typedef struct TreeElementIcon { +struct TreeElementIcon { struct ID *drag_id, *drag_parent; int icon; -} TreeElementIcon; +}; #define TREESTORE_ID_TYPE(_id) \ (ELEM(GS((_id)->name), \ @@ -153,7 +153,10 @@ enum { /* Closed items display their children as icon within the row. TE_ICONROW is for * these child-items that are visible but only within the row of the closed parent. */ TE_ICONROW = (1 << 1), - TE_LAZY_CLOSED = (1 << 2), + /** Treat the element as if it had children, e.g. draw an icon to un-collapse it, even if it + * doesn't. Used where children are lazy-built only if the parent isn't collapsed (see + * #AbstractTreeDisplay::is_lazy_built()). */ + TE_PRETEND_HAS_CHILDREN = (1 << 2), TE_FREE_NAME = (1 << 3), TE_DRAGGING = (1 << 4), TE_CHILD_NOT_IN_COLLECTION = (1 << 6), @@ -165,17 +168,17 @@ enum { /* button events */ #define OL_NAMEBUTTON 1 -typedef enum { +enum eOLDrawState { OL_DRAWSEL_NONE = 0, /* inactive (regular black text) */ OL_DRAWSEL_NORMAL = 1, /* active object (draws white text) */ OL_DRAWSEL_ACTIVE = 2, /* active obdata (draws a circle around the icon) */ -} eOLDrawState; +}; -typedef enum { +enum eOLSetState { OL_SETSEL_NONE = 0, /* don't change the selection state */ OL_SETSEL_NORMAL = 1, /* select the item */ OL_SETSEL_EXTEND = 2, /* select the item and extend (also toggles selection) */ -} eOLSetState; +}; /* get TreeStoreElem associated with a TreeElement * < a: (TreeElement) tree element to find stored element for @@ -225,29 +228,29 @@ typedef enum { * Container to avoid passing around these variables to many functions. * Also so we can have one place to assign these variables. */ -typedef struct TreeViewContext { +struct TreeViewContext { /* Scene level. */ struct Scene *scene; struct ViewLayer *view_layer; /* Object level. */ - /** Avoid OBACT macro everywhere. */ + /** Avoid `BKE_view_layer_active_object_get` everywhere. */ Object *obact; Object *ob_edit; /** * The pose object may not be the active object (when in weight paint mode). * Checking this in draw loops isn't efficient, so set only once. */ Object *ob_pose; -} TreeViewContext; +}; -typedef enum TreeItemSelectAction { +enum TreeItemSelectAction { OL_ITEM_DESELECT = 0, /* Deselect the item */ OL_ITEM_SELECT = (1 << 0), /* Select the item */ OL_ITEM_SELECT_DATA = (1 << 1), /* Select object data */ OL_ITEM_ACTIVATE = (1 << 2), /* Activate the item */ OL_ITEM_EXTEND = (1 << 3), /* Extend the current selection */ OL_ITEM_RECURSIVE = (1 << 4), /* Select recursively */ -} TreeItemSelectAction; +}; /* outliner_tree.c ----------------------------------------------- */ @@ -270,24 +273,19 @@ void outliner_build_tree(struct Main *mainvar, struct SpaceOutliner *space_outliner, struct ARegion *region); -struct TreeElement *outliner_add_collection_recursive(SpaceOutliner *space_outliner, - struct Collection *collection, - TreeElement *ten); +TreeElement *outliner_add_collection_recursive(SpaceOutliner *space_outliner, + struct Collection *collection, + TreeElement *ten); bool outliner_requires_rebuild_on_select_or_active_change( const struct SpaceOutliner *space_outliner); -/** - * Check if a display mode needs a full rebuild if the open/collapsed state changes. - * Element types in these modes don't actually add children if collapsed, so the rebuild is needed. - */ -bool outliner_requires_rebuild_on_open_change(const struct SpaceOutliner *space_outliner); typedef struct IDsSelectedData { struct ListBase selected_array; } IDsSelectedData; -TreeTraversalAction outliner_find_selected_collections(struct TreeElement *te, void *customdata); -TreeTraversalAction outliner_find_selected_objects(struct TreeElement *te, void *customdata); +TreeTraversalAction outliner_collect_selected_collections(TreeElement *te, void *customdata); +TreeTraversalAction outliner_collect_selected_objects(TreeElement *te, void *customdata); /* outliner_draw.c ---------------------------------------------- */ @@ -349,7 +347,7 @@ struct bPoseChannel *outliner_find_parent_bone(TreeElement *te, TreeElement **r_ */ void outliner_item_select(struct bContext *C, struct SpaceOutliner *space_outliner, - struct TreeElement *te, + TreeElement *te, short select_flag); /** @@ -379,7 +377,7 @@ void outliner_item_mode_toggle(struct bContext *C, typedef void (*outliner_operation_fn)(struct bContext *C, struct ReportList *, struct Scene *scene, - struct TreeElement *, + TreeElement *, struct TreeStoreElem *, TreeStoreElem *, void *); @@ -408,12 +406,10 @@ int outliner_flag_is_any_test(ListBase *lb, short flag, int curlevel); * Set or unset \a flag for all outliner elements in \a lb and sub-trees. * \return if any flag was modified. */ -extern "C++" { bool outliner_flag_set(const SpaceOutliner &space_outliner, short flag, short set); bool outliner_flag_set(const ListBase &lb, short flag, short set); bool outliner_flag_flip(const SpaceOutliner &space_outliner, short flag); bool outliner_flag_flip(const ListBase &lb, short flag); -} void item_rename_fn(struct bContext *C, struct ReportList *reports, @@ -425,14 +421,14 @@ void item_rename_fn(struct bContext *C, void lib_relocate_fn(struct bContext *C, struct ReportList *reports, struct Scene *scene, - struct TreeElement *te, + TreeElement *te, struct TreeStoreElem *tsep, struct TreeStoreElem *tselem, void *user_data); void lib_reload_fn(struct bContext *C, struct ReportList *reports, struct Scene *scene, - struct TreeElement *te, + TreeElement *te, struct TreeStoreElem *tsep, struct TreeStoreElem *tselem, void *user_data); @@ -440,14 +436,14 @@ void lib_reload_fn(struct bContext *C, void id_delete_tag_fn(struct bContext *C, struct ReportList *reports, struct Scene *scene, - struct TreeElement *te, + TreeElement *te, struct TreeStoreElem *tsep, struct TreeStoreElem *tselem, void *user_data); void id_remap_fn(struct bContext *C, struct ReportList *reports, struct Scene *scene, - struct TreeElement *te, + TreeElement *te, struct TreeStoreElem *tsep, struct TreeStoreElem *tselem, void *user_data); @@ -461,10 +457,7 @@ void outliner_set_coordinates(const struct ARegion *region, /** * Open or close a tree element, optionally toggling all children recursively. */ -void outliner_item_openclose(struct SpaceOutliner *space_outliner, - TreeElement *te, - bool open, - bool toggle_all); +void outliner_item_openclose(TreeElement *te, bool open, bool toggle_all); /* outliner_dragdrop.c */ @@ -612,10 +605,6 @@ TreeElement *outliner_find_item_at_x_in_row(const SpaceOutliner *space_outliner, bool *r_is_merged_icon, bool *r_is_over_icon); /** - * `tse` is not in the tree-store, we use its contents to find a match. - */ -TreeElement *outliner_find_tse(struct SpaceOutliner *space_outliner, const TreeStoreElem *tse); -/** * Find specific item from the trees-tore. */ TreeElement *outliner_find_tree_element(ListBase *lb, const TreeStoreElem *store_elem); @@ -691,12 +680,6 @@ int outliner_context(const struct bContext *C, const char *member, struct bContextDataResult *result); -#ifdef __cplusplus -} -#endif - -namespace blender::ed::outliner { - /** * Helper to safely "cast" a #TreeElement to its new C++ #AbstractTreeElement, if possible. * \return nullptr if the tree-element doesn't match the requested type \a TreeElementT or the diff --git a/source/blender/editors/space_outliner/outliner_ops.cc b/source/blender/editors/space_outliner/outliner_ops.cc index b384c41aa69..cf9c4834667 100644 --- a/source/blender/editors/space_outliner/outliner_ops.cc +++ b/source/blender/editors/space_outliner/outliner_ops.cc @@ -11,6 +11,7 @@ #include "outliner_intern.hh" +namespace blender::ed::outliner { /* -------------------------------------------------------------------- */ /** \name Registration * \{ */ @@ -103,3 +104,5 @@ void outliner_keymap(wmKeyConfig *keyconf) } /** \} */ + +} // namespace blender::ed::outliner diff --git a/source/blender/editors/space_outliner/outliner_query.cc b/source/blender/editors/space_outliner/outliner_query.cc index d6483c44fce..11929cbe2f0 100644 --- a/source/blender/editors/space_outliner/outliner_query.cc +++ b/source/blender/editors/space_outliner/outliner_query.cc @@ -13,7 +13,7 @@ #include "outliner_intern.hh" #include "tree/tree_display.hh" -using namespace blender::ed::outliner; +namespace blender::ed::outliner { bool outliner_shows_mode_column(const SpaceOutliner &space_outliner) { @@ -46,3 +46,5 @@ bool outliner_has_element_warnings(const SpaceOutliner &space_outliner) return recursive_fn(space_outliner.tree); } + +} // namespace blender::ed::outliner diff --git a/source/blender/editors/space_outliner/outliner_select.cc b/source/blender/editors/space_outliner/outliner_select.cc index 31ae4aef7ff..15079448317 100644 --- a/source/blender/editors/space_outliner/outliner_select.cc +++ b/source/blender/editors/space_outliner/outliner_select.cc @@ -70,7 +70,7 @@ #include "tree/tree_element_seq.hh" #include "tree/tree_iterator.hh" -using namespace blender::ed::outliner; +namespace blender::ed::outliner { /* -------------------------------------------------------------------- */ /** \name Internal Utilities @@ -164,9 +164,10 @@ static void do_outliner_item_mode_toggle_generic(bContext *C, TreeViewContext *t ED_undo_group_begin(C); if (ED_object_mode_set(C, OB_MODE_OBJECT)) { + BKE_view_layer_synced_ensure(tvc->scene, tvc->view_layer); Base *base_active = BKE_view_layer_base_find(tvc->view_layer, tvc->obact); if (base_active != base) { - BKE_view_layer_base_deselect_all(tvc->view_layer); + BKE_view_layer_base_deselect_all(tvc->scene, tvc->view_layer); BKE_view_layer_base_select_and_set_active(tvc->view_layer, base); DEG_id_tag_update(&tvc->scene->id, ID_RECALC_SELECT); ED_undo_push(C, "Change Active"); @@ -188,10 +189,12 @@ void outliner_item_mode_toggle(bContext *C, if ((tselem->type == TSE_SOME_ID) && (te->idcode == ID_OB)) { Object *ob = (Object *)tselem->id; + BKE_view_layer_synced_ensure(tvc->scene, tvc->view_layer); Base *base = BKE_view_layer_base_find(tvc->view_layer, ob); /* Hidden objects can be removed from the mode. */ - if (!base || (!(base->flag & BASE_VISIBLE_DEPSGRAPH) && (ob->mode != tvc->obact->mode))) { + if (!base || (!(base->flag & BASE_ENABLED_AND_MAYBE_VISIBLE_IN_VIEWPORT) && + (ob->mode != tvc->obact->mode))) { return; } @@ -233,15 +236,15 @@ static void tree_element_viewlayer_activate(bContext *C, TreeElement *te) /** * Select object tree */ -static void do_outliner_object_select_recursive(ViewLayer *view_layer, +static void do_outliner_object_select_recursive(const Scene *scene, + ViewLayer *view_layer, Object *ob_parent, bool select) { - Base *base; - - for (base = static_cast<Base *>(FIRSTBASE(view_layer)); base; base = base->next) { + BKE_view_layer_synced_ensure(scene, view_layer); + LISTBASE_FOREACH (Base *, base, BKE_view_layer_object_bases_get(view_layer)) { Object *ob = base->object; - if ((((base->flag & BASE_VISIBLE_DEPSGRAPH) != 0) && + if ((((base->flag & BASE_ENABLED_AND_MAYBE_VISIBLE_IN_VIEWPORT) != 0) && BKE_object_is_child_recursive(ob_parent, ob))) { ED_object_base_select(base, select ? BA_SELECT : BA_DESELECT); } @@ -301,7 +304,8 @@ static void tree_element_object_activate(bContext *C, ob = (Object *)parent_tselem->id; /* Don't return when activating children of the previous active object. */ - if (ob == OBACT(view_layer) && set == OL_SETSEL_NONE) { + BKE_view_layer_synced_ensure(scene, view_layer); + if (ob == BKE_view_layer_active_object_get(view_layer) && set == OL_SETSEL_NONE) { return; } } @@ -317,11 +321,12 @@ static void tree_element_object_activate(bContext *C, } /* find associated base in current scene */ + BKE_view_layer_synced_ensure(sce, view_layer); base = BKE_view_layer_base_find(view_layer, ob); if (scene->toolsettings->object_flag & SCE_OBJECT_MODE_LOCK) { if (base != nullptr) { - Object *obact = OBACT(view_layer); + Object *obact = BKE_view_layer_active_object_get(view_layer); const eObjectMode object_mode = obact ? (eObjectMode)obact->mode : OB_MODE_OBJECT; if (base && !BKE_object_is_mode_compat(base->object, object_mode)) { if (object_mode == OB_MODE_OBJECT) { @@ -362,7 +367,7 @@ static void tree_element_object_activate(bContext *C, if ((scene->toolsettings->object_flag & SCE_OBJECT_MODE_LOCK) ? (ob->mode == OB_MODE_OBJECT) : true) { - BKE_view_layer_base_deselect_all(view_layer); + BKE_view_layer_base_deselect_all(scene, view_layer); } ED_object_base_select(base, BA_SELECT); if (parent_tselem) { @@ -372,7 +377,8 @@ static void tree_element_object_activate(bContext *C, if (recursive) { /* Recursive select/deselect for Object hierarchies */ - do_outliner_object_select_recursive(view_layer, ob, (base->flag & BASE_SELECTED) != 0); + do_outliner_object_select_recursive( + scene, view_layer, ob, (base->flag & BASE_SELECTED) != 0); } if (set != OL_SETSEL_NONE) { @@ -383,12 +389,17 @@ static void tree_element_object_activate(bContext *C, } } -static void tree_element_material_activate(bContext *C, ViewLayer *view_layer, TreeElement *te) +static void tree_element_material_activate(bContext *C, + const Scene *scene, + ViewLayer *view_layer, + TreeElement *te) { /* we search for the object parent */ Object *ob = (Object *)outliner_search_back(te, ID_OB); /* Note : ob->matbits can be nullptr when a local object points to a library mesh. */ - if (ob == nullptr || ob != OBACT(view_layer) || ob->matbits == nullptr) { + BKE_view_layer_synced_ensure(scene, view_layer); + if (ob == nullptr || ob != BKE_view_layer_active_object_get(view_layer) || + ob->matbits == nullptr) { return; /* just paranoia */ } @@ -479,6 +490,7 @@ static void tree_element_posegroup_activate(bContext *C, TreeElement *te, TreeSt } static void tree_element_posechannel_activate(bContext *C, + const Scene *scene, ViewLayer *view_layer, TreeElement *te, TreeStoreElem *tselem, @@ -493,7 +505,8 @@ static void tree_element_posechannel_activate(bContext *C, if (set != OL_SETSEL_EXTEND) { /* Single select forces all other bones to get unselected. */ uint objects_len = 0; - Object **objects = BKE_object_pose_array_get_unique(view_layer, nullptr, &objects_len); + Object **objects = BKE_object_pose_array_get_unique( + scene, view_layer, nullptr, &objects_len); for (uint object_index = 0; object_index < objects_len; object_index++) { Object *ob_iter = BKE_object_pose_armature_get(objects[object_index]); @@ -534,6 +547,7 @@ static void tree_element_posechannel_activate(bContext *C, } static void tree_element_bone_activate(bContext *C, + const Scene *scene, ViewLayer *view_layer, TreeElement *te, TreeStoreElem *tselem, @@ -544,7 +558,8 @@ static void tree_element_bone_activate(bContext *C, Bone *bone = static_cast<Bone *>(te->directdata); if (!(bone->flag & BONE_HIDDEN_P)) { - Object *ob = OBACT(view_layer); + BKE_view_layer_synced_ensure(scene, view_layer); + Object *ob = BKE_view_layer_active_object_get(view_layer); if (ob) { if (set != OL_SETSEL_EXTEND) { /* single select forces all other bones to get unselected */ @@ -583,6 +598,7 @@ static void tree_element_active_ebone__sel(bContext *C, bArmature *arm, EditBone WM_event_add_notifier(C, NC_OBJECT | ND_BONE_ACTIVE, CTX_data_edit_object(C)); } static void tree_element_ebone_activate(bContext *C, + const Scene *scene, ViewLayer *view_layer, TreeElement *te, TreeStoreElem *tselem, @@ -601,7 +617,7 @@ static void tree_element_ebone_activate(bContext *C, ob_params.no_dup_data = true; Base **bases = BKE_view_layer_array_from_bases_in_mode_params( - view_layer, nullptr, &bases_len, &ob_params); + scene, view_layer, nullptr, &bases_len, &ob_params); ED_armature_edit_deselect_all_multi_ex(bases, bases_len); MEM_freeN(bases); @@ -648,6 +664,7 @@ static void tree_element_psys_activate(bContext *C, TreeStoreElem *tselem) } static void tree_element_constraint_activate(bContext *C, + const Scene *scene, ViewLayer *view_layer, TreeElement *te, TreeStoreElem *tselem, @@ -660,7 +677,7 @@ static void tree_element_constraint_activate(bContext *C, while (te) { tselem = TREESTORE(te); if (tselem->type == TSE_POSE_CHANNEL) { - tree_element_posechannel_activate(C, view_layer, te, tselem, set, false); + tree_element_posechannel_activate(C, scene, view_layer, te, tselem, set, false); return; } te = te->parent; @@ -765,7 +782,7 @@ void tree_element_activate(bContext *C, } break; case ID_MA: - tree_element_material_activate(C, tvc->view_layer, te); + tree_element_material_activate(C, tvc->scene, tvc->view_layer, te); break; case ID_WO: tree_element_world_activate(C, tvc->scene, te); @@ -792,10 +809,10 @@ void tree_element_type_active_set(bContext *C, tree_element_defgroup_activate(C, te, tselem); break; case TSE_BONE: - tree_element_bone_activate(C, tvc->view_layer, te, tselem, set, recursive); + tree_element_bone_activate(C, tvc->scene, tvc->view_layer, te, tselem, set, recursive); break; case TSE_EBONE: - tree_element_ebone_activate(C, tvc->view_layer, te, tselem, set, recursive); + tree_element_ebone_activate(C, tvc->scene, tvc->view_layer, te, tselem, set, recursive); break; case TSE_MODIFIER: tree_element_modifier_activate(C, te, tselem, set); @@ -809,11 +826,12 @@ void tree_element_type_active_set(bContext *C, case TSE_POSE_BASE: return; case TSE_POSE_CHANNEL: - tree_element_posechannel_activate(C, tvc->view_layer, te, tselem, set, recursive); + tree_element_posechannel_activate( + C, tvc->scene, tvc->view_layer, te, tselem, set, recursive); break; case TSE_CONSTRAINT_BASE: case TSE_CONSTRAINT: - tree_element_constraint_activate(C, tvc->view_layer, te, tselem, set); + tree_element_constraint_activate(C, tvc->scene, tvc->view_layer, te, tselem, set); break; case TSE_R_LAYER: tree_element_viewlayer_activate(C, te); @@ -839,12 +857,14 @@ void tree_element_type_active_set(bContext *C, } } -static eOLDrawState tree_element_defgroup_state_get(const ViewLayer *view_layer, +static eOLDrawState tree_element_defgroup_state_get(const Scene *scene, + ViewLayer *view_layer, const TreeElement *te, const TreeStoreElem *tselem) { const Object *ob = (const Object *)tselem->id; - if (ob == OBACT(view_layer)) { + BKE_view_layer_synced_ensure(scene, view_layer); + if (ob == BKE_view_layer_active_object_get(view_layer)) { if (BKE_object_defgroup_active_index_get(ob) == te->index + 1) { return OL_DRAWSEL_NORMAL; } @@ -852,13 +872,15 @@ static eOLDrawState tree_element_defgroup_state_get(const ViewLayer *view_layer, return OL_DRAWSEL_NONE; } -static eOLDrawState tree_element_bone_state_get(const ViewLayer *view_layer, +static eOLDrawState tree_element_bone_state_get(const Scene *scene, + ViewLayer *view_layer, const TreeElement *te, const TreeStoreElem *tselem) { const bArmature *arm = (const bArmature *)tselem->id; const Bone *bone = static_cast<Bone *>(te->directdata); - const Object *ob = OBACT(view_layer); + BKE_view_layer_synced_ensure(scene, view_layer); + const Object *ob = BKE_view_layer_active_object_get(view_layer); if (ob && ob->data == arm) { if (bone->flag & BONE_SELECTED) { return OL_DRAWSEL_NORMAL; @@ -891,11 +913,13 @@ static eOLDrawState tree_element_object_state_get(const TreeViewContext *tvc, return (tselem->id == (const ID *)tvc->obact) ? OL_DRAWSEL_NORMAL : OL_DRAWSEL_NONE; } -static eOLDrawState tree_element_pose_state_get(const ViewLayer *view_layer, +static eOLDrawState tree_element_pose_state_get(const Scene *scene, + const ViewLayer *view_layer, const TreeStoreElem *tselem) { const Object *ob = (const Object *)tselem->id; /* This will just lookup in a cache, it will not change the arguments. */ + BKE_view_layer_synced_ensure(scene, (ViewLayer *)view_layer); const Base *base = BKE_view_layer_base_find((ViewLayer *)view_layer, (Object *)ob); if (base == nullptr) { /* Armature not instantiated in current scene (e.g. inside an appended group). */ @@ -937,13 +961,15 @@ static eOLDrawState tree_element_viewlayer_state_get(const bContext *C, const Tr return OL_DRAWSEL_NONE; } -static eOLDrawState tree_element_posegroup_state_get(const ViewLayer *view_layer, +static eOLDrawState tree_element_posegroup_state_get(const Scene *scene, + ViewLayer *view_layer, const TreeElement *te, const TreeStoreElem *tselem) { const Object *ob = (const Object *)tselem->id; - if (ob == OBACT(view_layer) && ob->pose) { + BKE_view_layer_synced_ensure(scene, view_layer); + if (ob == BKE_view_layer_active_object_get(view_layer) && ob->pose) { if (ob->pose->active_group == te->index + 1) { return OL_DRAWSEL_NORMAL; } @@ -1003,13 +1029,16 @@ static eOLDrawState tree_element_layer_collection_state_get(const bContext *C, return OL_DRAWSEL_NONE; } -static eOLDrawState tree_element_active_material_get(const ViewLayer *view_layer, +static eOLDrawState tree_element_active_material_get(const Scene *scene, + ViewLayer *view_layer, const TreeElement *te) { /* we search for the object parent */ const Object *ob = (const Object *)outliner_search_back((TreeElement *)te, ID_OB); /* Note : ob->matbits can be nullptr when a local object points to a library mesh. */ - if (ob == nullptr || ob != OBACT(view_layer) || ob->matbits == nullptr) { + BKE_view_layer_synced_ensure(scene, view_layer); + if (ob == nullptr || ob != BKE_view_layer_active_object_get(view_layer) || + ob->matbits == nullptr) { return OL_DRAWSEL_NONE; /* just paranoia */ } @@ -1078,7 +1107,7 @@ eOLDrawState tree_element_active_state_get(const TreeViewContext *tvc, return OL_DRAWSEL_NONE; break; case ID_MA: - return tree_element_active_material_get(tvc->view_layer, te); + return tree_element_active_material_get(tvc->scene, tvc->view_layer, te); case ID_WO: return tree_element_active_world_get(tvc->scene, te); case ID_CA: @@ -1094,9 +1123,9 @@ eOLDrawState tree_element_type_active_state_get(const bContext *C, { switch (tselem->type) { case TSE_DEFGROUP: - return tree_element_defgroup_state_get(tvc->view_layer, te, tselem); + return tree_element_defgroup_state_get(tvc->scene, tvc->view_layer, te, tselem); case TSE_BONE: - return tree_element_bone_state_get(tvc->view_layer, te, tselem); + return tree_element_bone_state_get(tvc->scene, tvc->view_layer, te, tselem); case TSE_EBONE: return tree_element_ebone_state_get(te); case TSE_MODIFIER: @@ -1106,7 +1135,7 @@ eOLDrawState tree_element_type_active_state_get(const bContext *C, case TSE_LINKED_PSYS: return OL_DRAWSEL_NONE; case TSE_POSE_BASE: - return tree_element_pose_state_get(tvc->view_layer, tselem); + return tree_element_pose_state_get(tvc->scene, tvc->view_layer, tselem); case TSE_POSE_CHANNEL: return tree_element_posechannel_state_get(tvc->ob_pose, te, tselem); case TSE_CONSTRAINT_BASE: @@ -1115,7 +1144,7 @@ eOLDrawState tree_element_type_active_state_get(const bContext *C, case TSE_R_LAYER: return tree_element_viewlayer_state_get(C, te); case TSE_POSEGRP: - return tree_element_posegroup_state_get(tvc->view_layer, te, tselem); + return tree_element_posegroup_state_get(tvc->scene, tvc->view_layer, te, tselem); case TSE_SEQUENCE: return tree_element_sequence_state_get(tvc->scene, te); case TSE_SEQUENCE_DUP: @@ -1396,6 +1425,7 @@ static void do_outliner_item_activate_tree_element(bContext *C, } else if ((te->idcode == ID_GR) && (space_outliner->outlinevis != SO_VIEW_LAYER)) { Collection *gr = (Collection *)tselem->id; + BKE_view_layer_synced_ensure(tvc->scene, tvc->view_layer); if (extend) { eObjectSelect_Mode sel = BA_SELECT; @@ -1417,7 +1447,7 @@ static void do_outliner_item_activate_tree_element(bContext *C, FOREACH_COLLECTION_OBJECT_RECURSIVE_END; } else { - BKE_view_layer_base_deselect_all(tvc->view_layer); + BKE_view_layer_base_deselect_all(tvc->scene, tvc->view_layer); FOREACH_COLLECTION_OBJECT_RECURSIVE_BEGIN (gr, object) { Base *base = BKE_view_layer_base_find(tvc->view_layer, object); @@ -1569,8 +1599,10 @@ static bool outliner_is_co_within_active_mode_column(bContext *C, SpaceOutliner *space_outliner, const float view_mval[2]) { + const Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); - Object *obact = OBACT(view_layer); + BKE_view_layer_synced_ensure(scene, view_layer); + Object *obact = BKE_view_layer_active_object_get(view_layer); return outliner_is_co_within_mode_column(space_outliner, view_mval) && obact && obact->mode != OB_MODE_OBJECT; @@ -1885,7 +1917,7 @@ static TreeElement *outliner_walk_left(SpaceOutliner *space_outliner, TreeStoreElem *tselem = TREESTORE(te); if (TSELEM_OPEN(tselem, space_outliner)) { - outliner_item_openclose(space_outliner, te, false, toggle_all); + outliner_item_openclose(te, false, toggle_all); } /* Only walk up a level if the element is closed and not toggling expand */ else if (!toggle_all && te->parent) { @@ -1906,7 +1938,7 @@ static TreeElement *outliner_walk_right(SpaceOutliner *space_outliner, te = static_cast<TreeElement *>(te->subtree.first); } else { - outliner_item_openclose(space_outliner, te, true, toggle_all); + outliner_item_openclose(te, true, toggle_all); } return te; @@ -2040,3 +2072,5 @@ void OUTLINER_OT_select_walk(wmOperatorType *ot) } /** \} */ + +} // namespace blender::ed::outliner diff --git a/source/blender/editors/space_outliner/outliner_sync.cc b/source/blender/editors/space_outliner/outliner_sync.cc index 772a5826f9f..995c83b589d 100644 --- a/source/blender/editors/space_outliner/outliner_sync.cc +++ b/source/blender/editors/space_outliner/outliner_sync.cc @@ -94,6 +94,8 @@ void ED_outliner_select_sync_flag_outliners(const bContext *C) wm->outliner_sync_select_dirty = 0; } +namespace blender::ed::outliner { + /** * Outliner sync select dirty flags are not enough to determine which types to sync, * outliner display mode also needs to be considered. This stores the types of data @@ -223,7 +225,8 @@ static void outliner_select_sync_to_object(ViewLayer *view_layer, } } -static void outliner_select_sync_to_edit_bone(ViewLayer *view_layer, +static void outliner_select_sync_to_edit_bone(const Scene *scene, + ViewLayer *view_layer, TreeElement *te, TreeStoreElem *tselem, GSet *selected_ebones) @@ -248,7 +251,8 @@ static void outliner_select_sync_to_edit_bone(ViewLayer *view_layer, /* Tag if selection changed */ if (bone_flag != ebone->flag) { - Object *obedit = OBEDIT_FROM_VIEW_LAYER(view_layer); + BKE_view_layer_synced_ensure(scene, view_layer); + Object *obedit = BKE_view_layer_edit_object_get(view_layer); DEG_id_tag_update(&arm->id, ID_RECALC_SELECT); WM_main_add_notifier(NC_OBJECT | ND_BONE_SELECT, obedit); } @@ -316,7 +320,8 @@ static void outliner_sync_selection_from_outliner(Scene *scene, } else if (tselem->type == TSE_EBONE) { if (sync_types->edit_bone) { - outliner_select_sync_to_edit_bone(view_layer, te, tselem, selected_items->edit_bones); + outliner_select_sync_to_edit_bone( + scene, view_layer, te, tselem, selected_items->edit_bones); } } else if (tselem->type == TSE_POSE_CHANNEL) { @@ -335,8 +340,12 @@ static void outliner_sync_selection_from_outliner(Scene *scene, } } +} // namespace blender::ed::outliner + void ED_outliner_select_sync_from_outliner(bContext *C, SpaceOutliner *space_outliner) { + using namespace blender::ed::outliner; + /* Don't sync if not checked or in certain outliner display modes */ if (!(space_outliner->flag & SO_SYNC_SELECT) || ELEM(space_outliner->outlinevis, SO_LIBRARIES, @@ -380,12 +389,16 @@ void ED_outliner_select_sync_from_outliner(bContext *C, SpaceOutliner *space_out } } -static void outliner_select_sync_from_object(ViewLayer *view_layer, +namespace blender::ed::outliner { + +static void outliner_select_sync_from_object(const Scene *scene, + ViewLayer *view_layer, Object *obact, TreeElement *te, TreeStoreElem *tselem) { Object *ob = (Object *)tselem->id; + BKE_view_layer_synced_ensure(scene, view_layer); Base *base = (te->directdata) ? (Base *)te->directdata : BKE_view_layer_base_find(view_layer, ob); const bool is_selected = (base != nullptr) && ((base->flag & BASE_SELECTED) != 0); @@ -479,7 +492,8 @@ struct SyncSelectActiveData { }; /** Sync select and active flags from active view layer, bones, and sequences to the outliner. */ -static void outliner_sync_selection_to_outliner(ViewLayer *view_layer, +static void outliner_sync_selection_to_outliner(const Scene *scene, + ViewLayer *view_layer, SpaceOutliner *space_outliner, ListBase *tree, SyncSelectActiveData *active_data, @@ -490,7 +504,7 @@ static void outliner_sync_selection_to_outliner(ViewLayer *view_layer, if ((tselem->type == TSE_SOME_ID) && te->idcode == ID_OB) { if (sync_types->object) { - outliner_select_sync_from_object(view_layer, active_data->object, te, tselem); + outliner_select_sync_from_object(scene, view_layer, active_data->object, te, tselem); } } else if (tselem->type == TSE_EBONE) { @@ -514,7 +528,7 @@ static void outliner_sync_selection_to_outliner(ViewLayer *view_layer, /* Sync subtree elements */ outliner_sync_selection_to_outliner( - view_layer, space_outliner, &te->subtree, active_data, sync_types); + scene, view_layer, space_outliner, &te->subtree, active_data, sync_types); } } @@ -523,7 +537,8 @@ static void get_sync_select_active_data(const bContext *C, SyncSelectActiveData { Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); - active_data->object = OBACT(view_layer); + BKE_view_layer_synced_ensure(scene, view_layer); + active_data->object = BKE_view_layer_active_object_get(view_layer); active_data->edit_bone = CTX_data_active_bone(C); active_data->pose_channel = CTX_data_active_pose_bone(C); active_data->sequence = SEQ_select_active_get(scene); @@ -537,6 +552,7 @@ void outliner_sync_selection(const bContext *C, SpaceOutliner *space_outliner) C, space_outliner, &sync_types); if (sync_required) { + const Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); /* Store active object, bones, and sequence */ @@ -544,7 +560,7 @@ void outliner_sync_selection(const bContext *C, SpaceOutliner *space_outliner) get_sync_select_active_data(C, &active_data); outliner_sync_selection_to_outliner( - view_layer, space_outliner, &space_outliner->tree, &active_data, &sync_types); + scene, view_layer, space_outliner, &space_outliner->tree, &active_data, &sync_types); /* Keep any un-synced data in the dirty flag. */ if (sync_types.object) { @@ -561,3 +577,5 @@ void outliner_sync_selection(const bContext *C, SpaceOutliner *space_outliner) } } } + +} // namespace blender::ed::outliner diff --git a/source/blender/editors/space_outliner/outliner_tools.cc b/source/blender/editors/space_outliner/outliner_tools.cc index f51a70af3bc..1628945c4cd 100644 --- a/source/blender/editors/space_outliner/outliner_tools.cc +++ b/source/blender/editors/space_outliner/outliner_tools.cc @@ -89,6 +89,8 @@ #include "tree/tree_element_seq.hh" #include "tree/tree_iterator.hh" +namespace blender::ed::outliner { + static CLG_LogRef LOG = {"ed.outliner.tools"}; using namespace blender::ed::outliner; @@ -102,97 +104,96 @@ using blender::Vector; * \{ */ static void get_element_operation_type( - TreeElement *te, int *scenelevel, int *objectlevel, int *idlevel, int *datalevel) + const TreeElement *te, int *scenelevel, int *objectlevel, int *idlevel, int *datalevel) { - TreeStoreElem *tselem = TREESTORE(te); - if (tselem->flag & TSE_SELECTED) { - /* Layer collection points to collection ID. */ - if (!ELEM(tselem->type, TSE_SOME_ID, TSE_LAYER_COLLECTION)) { - if (*datalevel == 0) { - *datalevel = tselem->type; - } - else if (*datalevel != tselem->type) { - *datalevel = -1; - } - } - else { - const int idcode = (int)GS(tselem->id->name); - bool is_standard_id = false; - switch ((ID_Type)idcode) { - case ID_SCE: - *scenelevel = 1; - break; - case ID_OB: - *objectlevel = 1; - break; + *scenelevel = *objectlevel = *idlevel = *datalevel = 0; - case ID_ME: - case ID_CU_LEGACY: - case ID_MB: - case ID_LT: - case ID_LA: - case ID_AR: - case ID_CA: - case ID_SPK: - case ID_MA: - case ID_TE: - case ID_IP: - case ID_IM: - case ID_SO: - case ID_KE: - case ID_WO: - case ID_AC: - case ID_TXT: - case ID_GR: - case ID_LS: - case ID_LI: - case ID_VF: - case ID_NT: - case ID_BR: - case ID_PA: - case ID_GD: - case ID_MC: - case ID_MSK: - case ID_PAL: - case ID_PC: - case ID_CF: - case ID_WS: - case ID_LP: - case ID_CV: - case ID_PT: - case ID_VO: - case ID_SIM: - is_standard_id = true; - break; - case ID_WM: - case ID_SCR: - /* Those are ignored here. */ - /* NOTE: while Screens should be manageable here, deleting a screen used by a workspace - * will cause crashes when trying to use that workspace, so for now let's play minimal, - * safe change. */ - break; - } - if (idcode == ID_NLA) { - /* Fake one, not an actual ID type... */ + const TreeStoreElem *tselem = TREESTORE(te); + if ((tselem->flag & TSE_SELECTED) == 0) { + return; + } + + /* Layer collection points to collection ID. */ + if (!ELEM(tselem->type, TSE_SOME_ID, TSE_LAYER_COLLECTION)) { + *datalevel = tselem->type; + } + else { + const int idcode = (int)GS(tselem->id->name); + bool is_standard_id = false; + switch ((ID_Type)idcode) { + case ID_SCE: + *scenelevel = 1; + break; + case ID_OB: + *objectlevel = 1; + break; + + case ID_ME: + case ID_CU_LEGACY: + case ID_MB: + case ID_LT: + case ID_LA: + case ID_AR: + case ID_CA: + case ID_SPK: + case ID_MA: + case ID_TE: + case ID_IP: + case ID_IM: + case ID_SO: + case ID_KE: + case ID_WO: + case ID_AC: + case ID_TXT: + case ID_GR: + case ID_LS: + case ID_LI: + case ID_VF: + case ID_NT: + case ID_BR: + case ID_PA: + case ID_GD: + case ID_MC: + case ID_MSK: + case ID_PAL: + case ID_PC: + case ID_CF: + case ID_WS: + case ID_LP: + case ID_CV: + case ID_PT: + case ID_VO: + case ID_SIM: is_standard_id = true; - } + break; + case ID_WM: + case ID_SCR: + /* Those are ignored here. */ + /* NOTE: while Screens should be manageable here, deleting a screen used by a workspace + * will cause crashes when trying to use that workspace, so for now let's play minimal, + * safe change. */ + break; + } + if (idcode == ID_NLA) { + /* Fake one, not an actual ID type... */ + is_standard_id = true; + } - if (is_standard_id) { - if (*idlevel == 0) { - *idlevel = idcode; - } - else if (*idlevel != idcode) { - *idlevel = -1; - } - if (ELEM(*datalevel, TSE_VIEW_COLLECTION_BASE, TSE_SCENE_COLLECTION_BASE)) { - *datalevel = 0; - } - } + if (is_standard_id) { + *idlevel = idcode; } } + + /* Return values are exclusive, only one may be non-null. */ + BLI_assert(((*scenelevel != 0) && (*objectlevel == 0) && (*idlevel == 0) && (*datalevel == 0)) || + ((*scenelevel == 0) && (*objectlevel != 0) && (*idlevel == 0) && (*datalevel == 0)) || + ((*scenelevel == 0) && (*objectlevel == 0) && (*idlevel != 0) && (*datalevel == 0)) || + ((*scenelevel == 0) && (*objectlevel == 0) && (*idlevel == 0) && (*datalevel != 0)) || + /* All null. */ + ((*scenelevel == 0) && (*objectlevel == 0) && (*idlevel == 0) && (*datalevel == 0))); } -static TreeElement *get_target_element(SpaceOutliner *space_outliner) +static TreeElement *get_target_element(const SpaceOutliner *space_outliner) { TreeElement *te = outliner_find_element_with_flag(&space_outliner->tree, TSE_ACTIVE); @@ -453,14 +454,14 @@ static void outliner_do_libdata_operation(bContext *C, }); } -typedef enum eOutlinerLibOpSelectionSet { +enum eOutlinerLibOpSelectionSet { /* Only selected items. */ OUTLINER_LIB_SELECTIONSET_SELECTED, /* Only content 'inside' selected items (their sub-tree). */ OUTLINER_LIB_LIB_SELECTIONSET_CONTENT, /* Combining both options above. */ OUTLINER_LIB_LIB_SELECTIONSET_SELECTED_AND_CONTENT, -} eOutlinerLibOpSelectionSet; +}; static const EnumPropertyItem prop_lib_op_selection_set[] = { {OUTLINER_LIB_SELECTIONSET_SELECTED, @@ -781,8 +782,10 @@ static void object_select_fn(bContext *C, TreeStoreElem *tselem, void *UNUSED(user_data)) { + const Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); Object *ob = (Object *)tselem->id; + BKE_view_layer_synced_ensure(scene, view_layer); Base *base = BKE_view_layer_base_find(view_layer, ob); if (base) { @@ -819,8 +822,10 @@ static void object_deselect_fn(bContext *C, TreeStoreElem *tselem, void *UNUSED(user_data)) { + const Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); Object *ob = (Object *)tselem->id; + BKE_view_layer_synced_ensure(scene, view_layer); Base *base = BKE_view_layer_base_find(view_layer, ob); if (base) { @@ -917,7 +922,7 @@ struct OutlinerLibOverrideData { * override), or an actual already existing override. */ Map<ID *, Vector<OutlinerLiboverrideDataIDRoot>> id_hierarchy_roots; - /** All 'session_uuid' of all hierarchy root IDs used or created by the operation. */ + /** All 'session_uuid' of all hierarchy root IDs used or created by the operation. */ Set<uint> id_hierarchy_roots_uid; void id_root_add(ID *id_hierarchy_root_reference, @@ -1274,22 +1279,69 @@ static void id_override_library_reset_fn(bContext *C, OutlinerLibOverrideData *data = static_cast<OutlinerLibOverrideData *>(user_data); const bool do_hierarchy = data->do_hierarchy; - if (ID_IS_OVERRIDE_LIBRARY_REAL(id_root)) { - Main *bmain = CTX_data_main(C); + if (!ID_IS_OVERRIDE_LIBRARY_REAL(id_root) || ID_IS_LINKED(id_root)) { + CLOG_WARN(&LOG, "Could not reset library override of data block '%s'", id_root->name); + return; + } - if (do_hierarchy) { - BKE_lib_override_library_id_hierarchy_reset(bmain, id_root, false); + Main *bmain = CTX_data_main(C); + + if (do_hierarchy) { + BKE_lib_override_library_id_hierarchy_reset(bmain, id_root, false); + } + else { + BKE_lib_override_library_id_reset(bmain, id_root, false); + } +} + +static void id_override_library_clear_single_fn(bContext *C, + ReportList *reports, + Scene *scene, + TreeElement *UNUSED(te), + TreeStoreElem *UNUSED(tsep), + TreeStoreElem *tselem, + void *UNUSED(user_data)) +{ + BLI_assert(TSE_IS_REAL_ID(tselem)); + Main *bmain = CTX_data_main(C); + ViewLayer *view_layer = CTX_data_view_layer(C); + ID *id = tselem->id; + + if (!ID_IS_OVERRIDE_LIBRARY_REAL(id) || ID_IS_LINKED(id)) { + BKE_reportf(reports, + RPT_WARNING, + "Cannot clear embedded library override id '%s', only overrides of real " + "data-blocks can be directly deleted", + id->name); + return; + } + + /* If given ID is not using any other override (it's a 'leaf' in the override hierarchy), + * delete it and remap its usages to its linked reference. Otherwise, keep it as a reset system + * override. */ + if (BKE_lib_override_library_is_hierarchy_leaf(bmain, id)) { + bool do_remap_active = false; + BKE_view_layer_synced_ensure(CTX_data_scene(C), view_layer); + if (BKE_view_layer_active_object_get(view_layer) == reinterpret_cast<Object *>(id)) { + BLI_assert(GS(id->name) == ID_OB); + do_remap_active = true; } - else { - BKE_lib_override_library_id_reset(bmain, id_root, false); + BKE_libblock_remap(bmain, id, id->override_library->reference, ID_REMAP_SKIP_INDIRECT_USAGE); + if (do_remap_active) { + Object *ref_object = reinterpret_cast<Object *>(id->override_library->reference); + Base *basact = BKE_view_layer_base_find(view_layer, ref_object); + if (basact != nullptr) { + view_layer->basact = basact; + } + DEG_id_tag_update(&scene->id, ID_RECALC_SELECT); } - - WM_event_add_notifier(C, NC_WM | ND_DATACHANGED, nullptr); - WM_event_add_notifier(C, NC_SPACE | ND_SPACE_VIEW3D, nullptr); + BKE_id_delete(bmain, id); } else { - CLOG_WARN(&LOG, "Could not reset library override of data block '%s'", id_root->name); + BKE_lib_override_library_id_reset(bmain, id, true); } + + DEG_id_tag_update(&scene->id, ID_RECALC_BASE_FLAGS | ID_RECALC_COPY_ON_WRITE); } static void id_override_library_resync_fn(bContext *UNUSED(C), @@ -1304,8 +1356,9 @@ static void id_override_library_resync_fn(bContext *UNUSED(C), ID *id_root = tselem->id; OutlinerLibOverrideData *data = static_cast<OutlinerLibOverrideData *>(user_data); - if (!ID_IS_OVERRIDE_LIBRARY_REAL(id_root)) { + if (!ID_IS_OVERRIDE_LIBRARY_REAL(id_root) || ID_IS_LINKED(id_root)) { CLOG_WARN(&LOG, "Could not resync library override of data block '%s'", id_root->name); + return; } if (id_root->override_library->hierarchy_root != nullptr) { @@ -1340,20 +1393,20 @@ static void id_override_library_resync_hierarchy_process(bContext *C, WM_event_add_notifier(C, NC_WINDOW, nullptr); } -static void id_override_library_clear_hierarchy_fn(bContext *UNUSED(C), - ReportList *UNUSED(reports), - Scene *UNUSED(scene), - TreeElement *UNUSED(te), - TreeStoreElem *UNUSED(tsep), - TreeStoreElem *tselem, - void *user_data) +static void id_override_library_delete_hierarchy_fn(bContext *UNUSED(C), + ReportList *UNUSED(reports), + Scene *UNUSED(scene), + TreeElement *UNUSED(te), + TreeStoreElem *UNUSED(tsep), + TreeStoreElem *tselem, + void *user_data) { OutlinerLibOverrideData *data = reinterpret_cast<OutlinerLibOverrideData *>(user_data); BLI_assert(TSE_IS_REAL_ID(tselem)); ID *id_root = tselem->id; - if (!ID_IS_OVERRIDE_LIBRARY_REAL(id_root)) { + if (!ID_IS_OVERRIDE_LIBRARY_REAL(id_root) || ID_IS_LINKED(id_root)) { CLOG_WARN(&LOG, "Could not delete library override of data block '%s'", id_root->name); return; } @@ -1366,52 +1419,15 @@ static void id_override_library_clear_hierarchy_fn(bContext *UNUSED(C), } /* Clear (delete) a hierarchy of library overrides. */ -static void id_override_library_clear_hierarchy_process(bContext *C, - ReportList *UNUSED(reports), - OutlinerLibOverrideData &data) +static void id_override_library_delete_hierarchy_process(bContext *C, + ReportList *UNUSED(reports), + OutlinerLibOverrideData &data) { Main *bmain = CTX_data_main(C); for (auto &&id_hierarchy_root : data.id_hierarchy_roots.keys()) { BKE_lib_override_library_delete(bmain, id_hierarchy_root); } - - WM_event_add_notifier(C, NC_WINDOW, nullptr); -} - -static void id_override_library_clear_single_fn(bContext *C, - ReportList *reports, - Scene *UNUSED(scene), - TreeElement *UNUSED(te), - TreeStoreElem *UNUSED(tsep), - TreeStoreElem *tselem, - void *UNUSED(user_data)) -{ - BLI_assert(TSE_IS_REAL_ID(tselem)); - Main *bmain = CTX_data_main(C); - ID *id = tselem->id; - - if (!ID_IS_OVERRIDE_LIBRARY_REAL(id)) { - BKE_reportf(reports, - RPT_WARNING, - "Cannot clear embedded library override id '%s', only overrides of real " - "data-blocks can be directly deleted", - id->name); - return; - } - - /* If given ID is not using any other override (it's a 'leaf' in the override hierarchy), - * delete it and remap its usages to its linked reference. Otherwise, keep it as a reset system - * override. */ - if (BKE_lib_override_library_is_hierarchy_leaf(bmain, id)) { - BKE_libblock_remap(bmain, id, id->override_library->reference, ID_REMAP_SKIP_INDIRECT_USAGE); - BKE_id_delete(bmain, id); - } - else { - BKE_lib_override_library_id_reset(bmain, id, true); - } - - WM_event_add_notifier(C, NC_WINDOW, nullptr); } static void id_fake_user_set_fn(bContext *UNUSED(C), @@ -1634,14 +1650,14 @@ static const EnumPropertyItem prop_liboverride_op_types[] = { {OUTLINER_LIBOVERRIDE_OP_CREATE_HIERARCHY, "OVERRIDE_LIBRARY_CREATE_HIERARCHY", 0, - "Create", - "Make a local override of the selected linked data-blocks, and their hierarchy of " + "Make", + "Create a local override of the selected linked data-blocks, and their hierarchy of " "dependencies"}, {OUTLINER_LIBOVERRIDE_OP_RESET, "OVERRIDE_LIBRARY_RESET", 0, "Reset", - "Reset the selected local override to their linked references values"}, + "Reset the selected local overrides to their linked references values"}, {OUTLINER_LIBOVERRIDE_OP_CLEAR_SINGLE, "OVERRIDE_LIBRARY_CLEAR_SINGLE", 0, @@ -1665,6 +1681,7 @@ static const EnumPropertyItem prop_liboverride_troubleshoot_op_types[] = { "Rebuild the selected local overrides from their linked references, as well as their " "hierarchies of dependencies, enforcing these hierarchies to match the linked data (i.e. " "ignoring existing overrides on data-blocks pointer properties)"}, + RNA_ENUM_ITEM_SEPR, {OUTLINER_LIBOVERRIDE_OP_DELETE_HIERARCHY, "OVERRIDE_LIBRARY_DELETE_HIERARCHY", 0, @@ -1686,16 +1703,12 @@ static int outliner_liboverride_operation_exec(bContext *C, wmOperator *op) { Scene *scene = CTX_data_scene(C); SpaceOutliner *space_outliner = CTX_wm_space_outliner(C); - int scenelevel = 0, objectlevel = 0, idlevel = 0, datalevel = 0; /* check for invalid states */ if (space_outliner == nullptr) { return OPERATOR_CANCELLED; } - TreeElement *te = get_target_element(space_outliner); - get_element_operation_type(te, &scenelevel, &objectlevel, &idlevel, &datalevel); - const eOutlinerLibOpSelectionSet selection_set = static_cast<eOutlinerLibOpSelectionSet>( RNA_enum_get(op->ptr, "selection_set")); const eOutlinerLibOverrideOpTypes event = static_cast<eOutlinerLibOverrideOpTypes>( @@ -1784,11 +1797,11 @@ static int outliner_liboverride_operation_exec(bContext *C, wmOperator *op) op->reports, scene, space_outliner, - id_override_library_clear_hierarchy_fn, + id_override_library_delete_hierarchy_fn, OUTLINER_LIB_SELECTIONSET_SELECTED, nullptr); - id_override_library_clear_hierarchy_process(C, op->reports, override_data); + id_override_library_delete_hierarchy_process(C, op->reports, override_data); ED_undo_push(C, "Delete Overridden Data Hierarchy"); break; @@ -1798,11 +1811,9 @@ static int outliner_liboverride_operation_exec(bContext *C, wmOperator *op) break; } - /* wrong notifier still... */ - WM_event_add_notifier(C, NC_ID | NA_EDITED, nullptr); - - /* XXX: this is just so that outliner is always up to date. */ - WM_event_add_notifier(C, NC_SPACE | ND_SPACE_OUTLINER, nullptr); + WM_event_add_notifier(C, NC_WINDOW, nullptr); + WM_event_add_notifier(C, NC_WM | ND_LIB_OVERRIDE_CHANGED, nullptr); + WM_event_add_notifier(C, NC_SPACE | ND_SPACE_VIEW3D, nullptr); return OPERATOR_FINISHED; } @@ -1812,6 +1823,7 @@ void OUTLINER_OT_liboverride_operation(wmOperatorType *ot) /* identifiers */ ot->name = "Outliner Library Override Operation"; ot->idname = "OUTLINER_OT_liboverride_operation"; + ot->description = "Create, reset or clear library override hierarchies"; /* callbacks */ ot->invoke = WM_menu_invoke; @@ -1834,6 +1846,7 @@ void OUTLINER_OT_liboverride_troubleshoot_operation(wmOperatorType *ot) /* identifiers */ ot->name = "Outliner Library Override Troubleshoot Operation"; ot->idname = "OUTLINER_OT_liboverride_troubleshoot_operation"; + ot->description = "Advanced operations over library override to help fix broken hierarchies"; /* callbacks */ ot->invoke = WM_menu_invoke; @@ -1842,18 +1855,18 @@ void OUTLINER_OT_liboverride_troubleshoot_operation(wmOperatorType *ot) ot->flag = 0; - RNA_def_enum(ot->srna, - "type", - prop_liboverride_troubleshoot_op_types, - 0, - "Library Override Troubleshoot Operation", - ""); ot->prop = RNA_def_enum(ot->srna, - "selection_set", - prop_lib_op_selection_set, + "type", + prop_liboverride_troubleshoot_op_types, 0, - "Selection Set", - "Over which part of the tree items to apply the operation"); + "Library Override Troubleshoot Operation", + ""); + RNA_def_enum(ot->srna, + "selection_set", + prop_lib_op_selection_set, + 0, + "Selection Set", + "Over which part of the tree items to apply the operation"); } /** \} */ @@ -2100,9 +2113,10 @@ static Base *outliner_batch_delete_hierarchy( if (!base) { return nullptr; } - + BKE_view_layer_synced_ensure(scene, view_layer); object = base->object; - for (child_base = static_cast<Base *>(view_layer->object_bases.first); child_base; + for (child_base = static_cast<Base *>(BKE_view_layer_object_bases_get(view_layer)->first); + child_base; child_base = base_next) { base_next = child_base->next; for (parent = child_base->object->parent; parent && (parent != object); @@ -2152,6 +2166,7 @@ static void object_batch_delete_hierarchy_fn(bContext *C, ViewLayer *view_layer = CTX_data_view_layer(C); Object *obedit = CTX_data_edit_object(C); + BKE_view_layer_synced_ensure(scene, view_layer); Base *base = BKE_view_layer_base_find(view_layer, ob); if (base) { @@ -2323,7 +2338,7 @@ static void outliner_do_object_delete(bContext *C, } } -static TreeTraversalAction outliner_find_objects_to_delete(TreeElement *te, void *customdata) +static TreeTraversalAction outliner_collect_objects_to_delete(TreeElement *te, void *customdata) { ObjectEditData *data = static_cast<ObjectEditData *>(customdata); GSet *objects_to_delete = data->objects_set; @@ -2338,6 +2353,17 @@ static TreeTraversalAction outliner_find_objects_to_delete(TreeElement *te, void return TRAVERSE_SKIP_CHILDS; } + /* Do not allow to delete children objects of an override collection. */ + TreeElement *te_parent = te->parent; + if (outliner_is_collection_tree_element(te_parent)) { + TreeStoreElem *tselem_parent = TREESTORE(te_parent); + ID *id_parent = tselem_parent->id; + BLI_assert(GS(id_parent->name) == ID_GR); + if (ID_IS_OVERRIDE_LIBRARY_REAL(id_parent)) { + return TRAVERSE_SKIP_CHILDS; + } + } + ID *id = tselem->id; if (ID_IS_OVERRIDE_LIBRARY_REAL(id)) { @@ -2365,7 +2391,8 @@ static int outliner_delete_exec(bContext *C, wmOperator *op) SpaceOutliner *space_outliner = CTX_wm_space_outliner(C); struct wmMsgBus *mbus = CTX_wm_message_bus(C); ViewLayer *view_layer = CTX_data_view_layer(C); - const Base *basact_prev = BASACT(view_layer); + BKE_view_layer_synced_ensure(scene, view_layer); + const Base *basact_prev = BKE_view_layer_active_base_get(view_layer); const bool delete_hierarchy = RNA_boolean_get(op->ptr, "hierarchy"); @@ -2379,7 +2406,7 @@ static int outliner_delete_exec(bContext *C, wmOperator *op) &space_outliner->tree, 0, TSE_SELECTED, - outliner_find_objects_to_delete, + outliner_collect_objects_to_delete, &object_delete_data); if (delete_hierarchy) { @@ -2409,7 +2436,8 @@ static int outliner_delete_exec(bContext *C, wmOperator *op) DEG_id_tag_update(&scene->id, ID_RECALC_COPY_ON_WRITE); DEG_relations_tag_update(bmain); - if (basact_prev != BASACT(view_layer)) { + BKE_view_layer_synced_ensure(scene, view_layer); + if (basact_prev != BKE_view_layer_active_base_get(view_layer)) { WM_event_add_notifier(C, NC_SCENE | ND_OB_ACTIVE, scene); WM_msg_publish_rna_prop(mbus, &scene->id, view_layer, LayerObjects, active); } @@ -2734,6 +2762,7 @@ void OUTLINER_OT_id_operation(wmOperatorType *ot) /* identifiers */ ot->name = "Outliner ID Data Operation"; ot->idname = "OUTLINER_OT_id_operation"; + ot->description = "General data-block management operations"; /* callbacks */ ot->invoke = WM_menu_invoke; @@ -2781,16 +2810,12 @@ static int outliner_lib_operation_exec(bContext *C, wmOperator *op) Main *bmain = CTX_data_main(C); Scene *scene = CTX_data_scene(C); SpaceOutliner *space_outliner = CTX_wm_space_outliner(C); - int scenelevel = 0, objectlevel = 0, idlevel = 0, datalevel = 0; /* check for invalid states */ if (space_outliner == nullptr) { return OPERATOR_CANCELLED; } - TreeElement *te = get_target_element(space_outliner); - get_element_operation_type(te, &scenelevel, &objectlevel, &idlevel, &datalevel); - eOutlinerLibOpTypes event = (eOutlinerLibOpTypes)RNA_enum_get(op->ptr, "type"); switch (event) { case OL_LIB_DELETE: { @@ -3169,6 +3194,24 @@ void OUTLINER_OT_modifier_operation(wmOperatorType *ot) /** \name Data Menu Operator * \{ */ +static bool outliner_data_operation_poll(bContext *C) +{ + if (!ED_operator_outliner_active(C)) { + return false; + } + const SpaceOutliner *space_outliner = CTX_wm_space_outliner(C); + const TreeElement *te = get_target_element(space_outliner); + int scenelevel = 0, objectlevel = 0, idlevel = 0, datalevel = 0; + get_element_operation_type(te, &scenelevel, &objectlevel, &idlevel, &datalevel); + return ELEM(datalevel, + TSE_POSE_CHANNEL, + TSE_BONE, + TSE_EBONE, + TSE_SEQUENCE, + TSE_GP_LAYER, + TSE_RNA_STRUCT); +} + static int outliner_data_operation_exec(bContext *C, wmOperator *op) { SpaceOutliner *space_outliner = CTX_wm_space_outliner(C); @@ -3279,7 +3322,7 @@ void OUTLINER_OT_data_operation(wmOperatorType *ot) /* callbacks */ ot->invoke = WM_menu_invoke; ot->exec = outliner_data_operation_exec; - ot->poll = outliner_operation_tree_element_poll; + ot->poll = outliner_data_operation_poll; ot->flag = 0; @@ -3301,9 +3344,12 @@ static int outliner_operator_menu(bContext *C, const char *opname) /* set this so the default execution context is the same as submenus */ uiLayoutSetOperatorContext(layout, WM_OP_INVOKE_REGION_WIN); - uiItemsEnumO(layout, ot->idname, RNA_property_identifier(ot->prop)); - uiItemS(layout); + if (WM_operator_poll(C, ot)) { + uiItemsEnumO(layout, ot->idname, RNA_property_identifier(ot->prop)); + + uiItemS(layout); + } uiItemMContents(layout, "OUTLINER_MT_context_menu"); @@ -3313,7 +3359,6 @@ static int outliner_operator_menu(bContext *C, const char *opname) } static int do_outliner_operation_event(bContext *C, - ReportList *reports, ARegion *region, SpaceOutliner *space_outliner, TreeElement *te) @@ -3336,10 +3381,6 @@ static int do_outliner_operation_event(bContext *C, get_element_operation_type(te, &scenelevel, &objectlevel, &idlevel, &datalevel); if (scenelevel) { - if (objectlevel || datalevel || idlevel) { - BKE_report(reports, RPT_WARNING, "Mixed selection"); - return OPERATOR_CANCELLED; - } return outliner_operator_menu(C, "OUTLINER_OT_scene_operation"); } if (objectlevel) { @@ -3347,11 +3388,6 @@ static int do_outliner_operation_event(bContext *C, return OPERATOR_FINISHED; } if (idlevel) { - if (idlevel == -1 || datalevel) { - BKE_report(reports, RPT_WARNING, "Mixed selection"); - return OPERATOR_CANCELLED; - } - switch (idlevel) { case ID_GR: WM_menu_name_call(C, "OUTLINER_MT_collection", WM_OP_INVOKE_REGION_WIN); @@ -3366,10 +3402,6 @@ static int do_outliner_operation_event(bContext *C, } } else if (datalevel) { - if (datalevel == -1) { - BKE_report(reports, RPT_WARNING, "Mixed selection"); - return OPERATOR_CANCELLED; - } if (datalevel == TSE_ANIM_DATA) { return outliner_operator_menu(C, "OUTLINER_OT_animdata_operation"); } @@ -3401,7 +3433,7 @@ static int do_outliner_operation_event(bContext *C, return OPERATOR_CANCELLED; } -static int outliner_operation(bContext *C, wmOperator *op, const wmEvent *event) +static int outliner_operation(bContext *C, wmOperator *UNUSED(op), const wmEvent *event) { ARegion *region = CTX_wm_region(C); SpaceOutliner *space_outliner = CTX_wm_space_outliner(C); @@ -3422,7 +3454,7 @@ static int outliner_operation(bContext *C, wmOperator *op, const wmEvent *event) return OPERATOR_PASS_THROUGH; } - return do_outliner_operation_event(C, op->reports, region, space_outliner, hovered_te); + return do_outliner_operation_event(C, region, space_outliner, hovered_te); } void OUTLINER_OT_operation(wmOperatorType *ot) @@ -3437,3 +3469,5 @@ void OUTLINER_OT_operation(wmOperatorType *ot) } /** \} */ + +} // namespace blender::ed::outliner diff --git a/source/blender/editors/space_outliner/outliner_tree.cc b/source/blender/editors/space_outliner/outliner_tree.cc index 0906bbb5797..8a2ff8c2ece 100644 --- a/source/blender/editors/space_outliner/outliner_tree.cc +++ b/source/blender/editors/space_outliner/outliner_tree.cc @@ -41,6 +41,7 @@ #include "BLI_fnmatch.h" #include "BLI_listbase.h" #include "BLI_mempool.h" +#include "BLI_timeit.hh" #include "BLI_utildefines.h" #include "BLT_translation.h" @@ -51,7 +52,7 @@ #include "BKE_lib_id.h" #include "BKE_main.h" #include "BKE_modifier.h" -#include "BKE_outliner_treehash.h" +#include "BKE_outliner_treehash.hh" #include "ED_screen.h" @@ -69,7 +70,7 @@ # include "BLI_math_base.h" /* M_PI */ #endif -using namespace blender::ed::outliner; +namespace blender::ed::outliner { /* prototypes */ static int outliner_exclude_filter_get(const SpaceOutliner *space_outliner); @@ -110,10 +111,7 @@ static void outliner_storage_cleanup(SpaceOutliner *space_outliner) if (BLI_mempool_len(ts) == unused) { BLI_mempool_destroy(ts); space_outliner->treestore = nullptr; - if (space_outliner->runtime->treehash) { - BKE_outliner_treehash_free(space_outliner->runtime->treehash); - space_outliner->runtime->treehash = nullptr; - } + space_outliner->runtime->tree_hash = nullptr; } else { TreeStoreElem *tsenew; @@ -128,16 +126,15 @@ static void outliner_storage_cleanup(SpaceOutliner *space_outliner) } BLI_mempool_destroy(ts); space_outliner->treestore = new_ts; - if (space_outliner->runtime->treehash) { + if (space_outliner->runtime->tree_hash) { /* update hash table to fix broken pointers */ - BKE_outliner_treehash_rebuild_from_treestore(space_outliner->runtime->treehash, - space_outliner->treestore); + space_outliner->runtime->tree_hash->rebuild_from_treestore(*space_outliner->treestore); } } } } - else if (space_outliner->runtime->treehash) { - BKE_outliner_treehash_clear_used(space_outliner->runtime->treehash); + else if (space_outliner->runtime->tree_hash) { + space_outliner->runtime->tree_hash->clear_used(); } } } @@ -150,15 +147,14 @@ static void check_persistent( space_outliner->treestore = BLI_mempool_create( sizeof(TreeStoreElem), 1, 512, BLI_MEMPOOL_ALLOW_ITER); } - if (space_outliner->runtime->treehash == nullptr) { - space_outliner->runtime->treehash = static_cast<GHash *>( - BKE_outliner_treehash_create_from_treestore(space_outliner->treestore)); + if (space_outliner->runtime->tree_hash == nullptr) { + space_outliner->runtime->tree_hash = treehash::TreeHash::create_from_treestore( + *space_outliner->treestore); } /* find any unused tree element in treestore and mark it as used * (note that there may be multiple unused elements in case of linked objects) */ - TreeStoreElem *tselem = BKE_outliner_treehash_lookup_unused( - space_outliner->runtime->treehash, type, nr, id); + TreeStoreElem *tselem = space_outliner->runtime->tree_hash->lookup_unused(type, nr, id); if (tselem) { te->store_elem = tselem; tselem->used = 1; @@ -173,7 +169,7 @@ static void check_persistent( tselem->used = 0; tselem->flag = TSE_CLOSED; te->store_elem = tselem; - BKE_outliner_treehash_add_element(space_outliner->runtime->treehash, tselem); + space_outliner->runtime->tree_hash->add_element(*tselem); } /** \} */ @@ -221,11 +217,6 @@ bool outliner_requires_rebuild_on_select_or_active_change(const SpaceOutliner *s return exclude_flags & (SO_FILTER_OB_STATE_SELECTED | SO_FILTER_OB_STATE_ACTIVE); } -bool outliner_requires_rebuild_on_open_change(const SpaceOutliner *space_outliner) -{ - return ELEM(space_outliner->outlinevis, SO_DATA_API); -} - /* special handling of hierarchical non-lib data */ static void outliner_add_bone(SpaceOutliner *space_outliner, ListBase *lb, @@ -795,8 +786,6 @@ static void outliner_add_id_contents(SpaceOutliner *space_outliner, } } -namespace blender::ed::outliner { - TreeElement *outliner_add_element(SpaceOutliner *space_outliner, ListBase *lb, void *idv, @@ -933,8 +922,6 @@ TreeElement *outliner_add_element(SpaceOutliner *space_outliner, return te; } -} // namespace blender::ed::outliner - /* ======================================================= */ BLI_INLINE void outliner_add_collection_init(TreeElement *te, Collection *collection) @@ -1408,7 +1395,8 @@ static int outliner_exclude_filter_get(const SpaceOutliner *space_outliner) return exclude_filter; } -static bool outliner_element_visible_get(ViewLayer *view_layer, +static bool outliner_element_visible_get(const Scene *scene, + ViewLayer *view_layer, TreeElement *te, const int exclude_filter) { @@ -1463,6 +1451,7 @@ static bool outliner_element_visible_get(ViewLayer *view_layer, if (exclude_filter & SO_FILTER_OB_STATE) { if (base == nullptr) { + BKE_view_layer_synced_ensure(scene, view_layer); base = BKE_view_layer_base_find(view_layer, ob); if (base == nullptr) { @@ -1472,7 +1461,7 @@ static bool outliner_element_visible_get(ViewLayer *view_layer, bool is_visible = true; if (exclude_filter & SO_FILTER_OB_STATE_VISIBLE) { - if ((base->flag & BASE_VISIBLE_VIEWLAYER) == 0) { + if ((base->flag & BASE_ENABLED_AND_VISIBLE_IN_DEFAULT_VIEWPORT) == 0) { is_visible = false; } } @@ -1488,7 +1477,8 @@ static bool outliner_element_visible_get(ViewLayer *view_layer, } else { BLI_assert(exclude_filter & SO_FILTER_OB_STATE_ACTIVE); - if (base != BASACT(view_layer)) { + BKE_view_layer_synced_ensure(scene, view_layer); + if (base != BKE_view_layer_active_base_get(view_layer)) { is_visible = false; } } @@ -1570,6 +1560,7 @@ static TreeElement *outliner_extract_children_from_subtree(TreeElement *element, } static int outliner_filter_subtree(SpaceOutliner *space_outliner, + const Scene *scene, ViewLayer *view_layer, ListBase *lb, const char *search_string, @@ -1580,18 +1571,18 @@ static int outliner_filter_subtree(SpaceOutliner *space_outliner, for (te = static_cast<TreeElement *>(lb->first); te; te = te_next) { te_next = te->next; - if ((outliner_element_visible_get(view_layer, te, exclude_filter) == false)) { + if ((outliner_element_visible_get(scene, view_layer, te, exclude_filter) == false)) { /* Don't free the tree, but extract the children from the parent and add to this tree. */ /* This also needs filtering the subtree prior (see T69246). */ outliner_filter_subtree( - space_outliner, view_layer, &te->subtree, search_string, exclude_filter); + space_outliner, scene, view_layer, &te->subtree, search_string, exclude_filter); te_next = outliner_extract_children_from_subtree(te, lb); continue; } if ((exclude_filter & SO_FILTER_SEARCH) == 0) { /* Filter subtree too. */ outliner_filter_subtree( - space_outliner, view_layer, &te->subtree, search_string, exclude_filter); + space_outliner, scene, view_layer, &te->subtree, search_string, exclude_filter); continue; } @@ -1609,7 +1600,8 @@ static int outliner_filter_subtree(SpaceOutliner *space_outliner, if ((!TSELEM_OPEN(tselem, space_outliner)) || outliner_filter_subtree( - space_outliner, view_layer, &te->subtree, search_string, exclude_filter) == 0) { + space_outliner, scene, view_layer, &te->subtree, search_string, exclude_filter) == + 0) { outliner_free_tree_element(te, lb); } } @@ -1621,7 +1613,7 @@ static int outliner_filter_subtree(SpaceOutliner *space_outliner, /* filter subtree too */ outliner_filter_subtree( - space_outliner, view_layer, &te->subtree, search_string, exclude_filter); + space_outliner, scene, view_layer, &te->subtree, search_string, exclude_filter); } } @@ -1629,7 +1621,9 @@ static int outliner_filter_subtree(SpaceOutliner *space_outliner, return (BLI_listbase_is_empty(lb) == false); } -static void outliner_filter_tree(SpaceOutliner *space_outliner, ViewLayer *view_layer) +static void outliner_filter_tree(SpaceOutliner *space_outliner, + const Scene *scene, + ViewLayer *view_layer) { char search_buff[sizeof(((struct SpaceOutliner *)nullptr)->search_string) + 2]; char *search_string; @@ -1650,7 +1644,7 @@ static void outliner_filter_tree(SpaceOutliner *space_outliner, ViewLayer *view_ } outliner_filter_subtree( - space_outliner, view_layer, &space_outliner->tree, search_string, exclude_filter); + space_outliner, scene, view_layer, &space_outliner->tree, search_string, exclude_filter); } static void outliner_clear_newid_from_main(Main *bmain) @@ -1684,10 +1678,9 @@ void outliner_build_tree(Main *mainvar, space_outliner->search_flags &= ~SO_SEARCH_RECURSIVE; } - if (space_outliner->runtime->treehash && (space_outliner->storeflag & SO_TREESTORE_REBUILD) && + if (space_outliner->runtime->tree_hash && (space_outliner->storeflag & SO_TREESTORE_REBUILD) && space_outliner->treestore) { - BKE_outliner_treehash_rebuild_from_treestore(space_outliner->runtime->treehash, - space_outliner->treestore); + space_outliner->runtime->tree_hash->rebuild_from_treestore(*space_outliner->treestore); } space_outliner->storeflag &= ~SO_TREESTORE_REBUILD; @@ -1698,6 +1691,10 @@ void outliner_build_tree(Main *mainvar, return; } + /* Enable for benchmarking. Starts a timer, results will be printed on function exit. */ + // SCOPED_TIMER("Outliner Rebuild"); + // SCOPED_TIMER_AVERAGED("Outliner Rebuild"); + OutlinerTreeElementFocus focus; outliner_store_scrolling_position(space_outliner, region, &focus); @@ -1724,7 +1721,7 @@ void outliner_build_tree(Main *mainvar, outliner_collections_children_sort(&space_outliner->tree); } - outliner_filter_tree(space_outliner, view_layer); + outliner_filter_tree(space_outliner, scene, view_layer); outliner_restore_scrolling_position(space_outliner, region, &focus); /* `ID.newid` pointer is abused when building tree, DO NOT call #BKE_main_id_newptr_and_tag_clear @@ -1733,3 +1730,5 @@ void outliner_build_tree(Main *mainvar, } /** \} */ + +} // namespace blender::ed::outliner diff --git a/source/blender/editors/space_outliner/outliner_utils.cc b/source/blender/editors/space_outliner/outliner_utils.cc index d8c50cd04f9..2deedccc29e 100644 --- a/source/blender/editors/space_outliner/outliner_utils.cc +++ b/source/blender/editors/space_outliner/outliner_utils.cc @@ -18,7 +18,7 @@ #include "BKE_context.h" #include "BKE_layer.h" #include "BKE_object.h" -#include "BKE_outliner_treehash.h" +#include "BKE_outliner_treehash.hh" #include "ED_outliner.h" #include "ED_screen.h" @@ -27,9 +27,10 @@ #include "UI_view2d.h" #include "outliner_intern.hh" +#include "tree/tree_display.hh" #include "tree/tree_iterator.hh" -using namespace blender::ed::outliner; +namespace blender::ed::outliner { /* -------------------------------------------------------------------- */ /** \name Tree View Context @@ -44,7 +45,8 @@ void outliner_viewcontext_init(const bContext *C, TreeViewContext *tvc) tvc->view_layer = CTX_data_view_layer(C); /* Objects. */ - tvc->obact = OBACT(tvc->view_layer); + BKE_view_layer_synced_ensure(tvc->scene, tvc->view_layer); + tvc->obact = BKE_view_layer_active_object_get(tvc->view_layer); if (tvc->obact != nullptr) { tvc->ob_edit = OBEDIT_FROM_OBACT(tvc->obact); @@ -175,24 +177,6 @@ TreeElement *outliner_find_parent_element(ListBase *lb, return nullptr; } -TreeElement *outliner_find_tse(SpaceOutliner *space_outliner, const TreeStoreElem *tse) -{ - TreeStoreElem *tselem; - - if (tse->id == nullptr) { - return nullptr; - } - - /* Check if 'tse' is in tree-store. */ - tselem = BKE_outliner_treehash_lookup_any( - space_outliner->runtime->treehash, tse->type, tse->nr, tse->id); - if (tselem) { - return outliner_find_tree_element(&space_outliner->tree, tselem); - } - - return nullptr; -} - TreeElement *outliner_find_id(SpaceOutliner *space_outliner, ListBase *lb, const ID *id) { LISTBASE_FOREACH (TreeElement *, te, lb) { @@ -454,7 +438,7 @@ void outliner_tag_redraw_avoid_rebuild_on_open_change(const SpaceOutliner *space ARegion *region) { /* Avoid rebuild if possible. */ - if (outliner_requires_rebuild_on_open_change(space_outliner)) { + if (space_outliner->runtime->tree_display->is_lazy_built()) { ED_region_tag_redraw(region); } else { @@ -462,9 +446,14 @@ void outliner_tag_redraw_avoid_rebuild_on_open_change(const SpaceOutliner *space } } +} // namespace blender::ed::outliner + +using namespace blender::ed::outliner; + Base *ED_outliner_give_base_under_cursor(bContext *C, const int mval[2]) { ARegion *region = CTX_wm_region(C); + const Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); SpaceOutliner *space_outliner = CTX_wm_space_outliner(C); TreeElement *te; @@ -478,6 +467,7 @@ Base *ED_outliner_give_base_under_cursor(bContext *C, const int mval[2]) TreeStoreElem *tselem = TREESTORE(te); if ((tselem->type == TSE_SOME_ID) && (te->idcode == ID_OB)) { Object *ob = (Object *)tselem->id; + BKE_view_layer_synced_ensure(scene, view_layer); base = (te->directdata) ? (Base *)te->directdata : BKE_view_layer_base_find(view_layer, ob); } } diff --git a/source/blender/editors/space_outliner/space_outliner.cc b/source/blender/editors/space_outliner/space_outliner.cc index 61bc3d35dfd..365bcae3f5d 100644 --- a/source/blender/editors/space_outliner/space_outliner.cc +++ b/source/blender/editors/space_outliner/space_outliner.cc @@ -16,7 +16,7 @@ #include "BKE_context.h" #include "BKE_lib_remap.h" -#include "BKE_outliner_treehash.h" +#include "BKE_outliner_treehash.hh" #include "BKE_screen.h" #include "ED_screen.h" @@ -37,16 +37,11 @@ #include "outliner_intern.hh" #include "tree/tree_display.hh" -SpaceOutliner_Runtime::SpaceOutliner_Runtime(const SpaceOutliner_Runtime & /*other*/) - : tree_display(nullptr), treehash(nullptr) -{ -} +namespace blender::ed::outliner { -SpaceOutliner_Runtime::~SpaceOutliner_Runtime() +SpaceOutliner_Runtime::SpaceOutliner_Runtime(const SpaceOutliner_Runtime & /*other*/) + : tree_display(nullptr), tree_hash(nullptr) { - if (treehash) { - BKE_outliner_treehash_free(treehash); - } } static void outliner_main_region_init(wmWindowManager *wm, ARegion *region) @@ -100,7 +95,7 @@ static void outliner_main_region_listener(const wmRegionListenerParams *params) { ScrArea *area = params->area; ARegion *region = params->region; - wmNotifier *wmn = params->notifier; + const wmNotifier *wmn = params->notifier; SpaceOutliner *space_outliner = static_cast<SpaceOutliner *>(area->spacedata.first); /* context changes */ @@ -191,7 +186,7 @@ static void outliner_main_region_listener(const wmRegionListenerParams *params) } break; case NC_ID: - if (ELEM(wmn->action, NA_RENAME, NA_ADDED)) { + if (ELEM(wmn->action, NA_RENAME, NA_ADDED, NA_REMOVED)) { ED_region_tag_redraw(region); } break; @@ -296,7 +291,7 @@ static void outliner_header_region_free(ARegion *UNUSED(region)) static void outliner_header_region_listener(const wmRegionListenerParams *params) { ARegion *region = params->region; - wmNotifier *wmn = params->notifier; + const wmNotifier *wmn = params->notifier; /* context changes */ switch (wmn->category) { @@ -391,8 +386,6 @@ static void outliner_id_remap(ScrArea *area, SpaceLink *slink, const struct IDRe { SpaceOutliner *space_outliner = (SpaceOutliner *)slink; - BKE_id_remapper_apply(mappings, (ID **)&space_outliner->search_tse.id, ID_REMAP_APPLY_DEFAULT); - if (!space_outliner->treestore) { return; } @@ -420,7 +413,7 @@ static void outliner_id_remap(ScrArea *area, SpaceLink *slink, const struct IDRe /* Note that the Outliner may not be the active editor of the area, and hence not initialized. * So runtime data might not have been created yet. */ - if (space_outliner->runtime && space_outliner->runtime->treehash && changed) { + if (space_outliner->runtime && space_outliner->runtime->tree_hash && changed) { /* rebuild hash table, because it depends on ids too */ /* postpone a full rebuild because this can be called many times on-free */ space_outliner->storeflag |= SO_TREESTORE_REBUILD; @@ -442,13 +435,17 @@ static void outliner_deactivate(struct ScrArea *area) ED_region_tag_redraw_no_rebuild(BKE_area_find_region_type(area, RGN_TYPE_WINDOW)); } +} // namespace blender::ed::outliner + void ED_spacetype_outliner(void) { + using namespace blender::ed::outliner; + SpaceType *st = MEM_cnew<SpaceType>("spacetype time"); ARegionType *art; st->spaceid = SPACE_OUTLINER; - strncpy(st->name, "Outliner", BKE_ST_MAXNAME); + STRNCPY(st->name, "Outliner"); st->create = outliner_create; st->free = outliner_free; diff --git a/source/blender/editors/space_outliner/tree/common.cc b/source/blender/editors/space_outliner/tree/common.cc index e590b0c97d1..199c80f021a 100644 --- a/source/blender/editors/space_outliner/tree/common.cc +++ b/source/blender/editors/space_outliner/tree/common.cc @@ -21,6 +21,8 @@ #include "common.hh" #include "tree_display.hh" +namespace blender::ed::outliner { + /* -------------------------------------------------------------------- */ /** \name ID Helpers. * \{ */ @@ -63,3 +65,5 @@ bool outliner_animdata_test(const AnimData *adt) } return false; } + +} // namespace blender::ed::outliner diff --git a/source/blender/editors/space_outliner/tree/common.hh b/source/blender/editors/space_outliner/tree/common.hh index 96c1eb34354..ba2d1c3fab6 100644 --- a/source/blender/editors/space_outliner/tree/common.hh +++ b/source/blender/editors/space_outliner/tree/common.hh @@ -8,7 +8,11 @@ struct ListBase; +namespace blender::ed::outliner { + const char *outliner_idcode_to_plural(short idcode); void outliner_make_object_parent_hierarchy(ListBase *lb); bool outliner_animdata_test(const struct AnimData *adt); + +} // namespace blender::ed::outliner diff --git a/source/blender/editors/space_outliner/tree/tree_display.cc b/source/blender/editors/space_outliner/tree/tree_display.cc index 6ab497b3fbb..fe4937829d6 100644 --- a/source/blender/editors/space_outliner/tree/tree_display.cc +++ b/source/blender/editors/space_outliner/tree/tree_display.cc @@ -50,4 +50,9 @@ bool AbstractTreeDisplay::supportsModeColumn() const return false; } +bool AbstractTreeDisplay::is_lazy_built() const +{ + return false; +} + } // namespace blender::ed::outliner diff --git a/source/blender/editors/space_outliner/tree/tree_display.hh b/source/blender/editors/space_outliner/tree/tree_display.hh index f8e35655c26..13b46651562 100644 --- a/source/blender/editors/space_outliner/tree/tree_display.hh +++ b/source/blender/editors/space_outliner/tree/tree_display.hh @@ -30,11 +30,11 @@ struct Main; struct Scene; struct Sequence; struct SpaceOutliner; -struct TreeElement; struct ViewLayer; namespace blender::ed::outliner { +struct TreeElement; class TreeElementID; /** @@ -84,6 +84,15 @@ class AbstractTreeDisplay { */ virtual bool supportsModeColumn() const; + /** + * Some trees may want to skip building children of collapsed parents. This should be done if the + * tree type may become very complex, which could cause noticeable slowdowns. + * Problem: This doesn't address performance issues while searching, since all elements are + * constructed for that. Trees of this type have to be rebuilt for any change to the collapsed + * state of any element. + */ + virtual bool is_lazy_built() const; + protected: /** All derived classes will need a handle to this, so storing it in the base for convenience. */ SpaceOutliner &space_outliner_; @@ -96,6 +105,7 @@ class AbstractTreeDisplay { * \brief Tree-Display for the View Layer display mode. */ class TreeDisplayViewLayer final : public AbstractTreeDisplay { + Scene *scene_ = nullptr; ViewLayer *view_layer_ = nullptr; bool show_objects_ = true; @@ -157,6 +167,8 @@ class TreeDisplayOverrideLibraryHierarchies final : public AbstractTreeDisplay { ListBase buildTree(const TreeSourceData &source_data) override; + bool is_lazy_built() const override; + private: ListBase build_hierarchy_for_lib_or_main(Main *bmain, TreeElement &parent_te, @@ -232,6 +244,8 @@ class TreeDisplayDataAPI final : public AbstractTreeDisplay { TreeDisplayDataAPI(SpaceOutliner &space_outliner); ListBase buildTree(const TreeSourceData &source_data) override; + + bool is_lazy_built() const override; }; } // namespace blender::ed::outliner diff --git a/source/blender/editors/space_outliner/tree/tree_display_data.cc b/source/blender/editors/space_outliner/tree/tree_display_data.cc index bfeb8ce2bdc..3d9b927fbf1 100644 --- a/source/blender/editors/space_outliner/tree/tree_display_data.cc +++ b/source/blender/editors/space_outliner/tree/tree_display_data.cc @@ -42,4 +42,9 @@ ListBase TreeDisplayDataAPI::buildTree(const TreeSourceData &source_data) return tree; } +bool TreeDisplayDataAPI::is_lazy_built() const +{ + return true; +} + } // namespace blender::ed::outliner diff --git a/source/blender/editors/space_outliner/tree/tree_display_override_library_hierarchies.cc b/source/blender/editors/space_outliner/tree/tree_display_override_library_hierarchies.cc index e0a1958795a..2150d2b211a 100644 --- a/source/blender/editors/space_outliner/tree/tree_display_override_library_hierarchies.cc +++ b/source/blender/editors/space_outliner/tree/tree_display_override_library_hierarchies.cc @@ -75,6 +75,11 @@ ListBase TreeDisplayOverrideLibraryHierarchies::buildTree(const TreeSourceData & return tree; } +bool TreeDisplayOverrideLibraryHierarchies::is_lazy_built() const +{ + return true; +} + /* -------------------------------------------------------------------- */ /** \name Library override hierarchy building * \{ */ @@ -165,10 +170,14 @@ void OverrideIDHierarchyBuilder::build_hierarchy_for_ID(ID &override_root_id, build_hierarchy_for_ID_recursive(override_root_id, build_data, te_to_expand); } +enum ForeachChildReturn { + FOREACH_CONTINUE, + FOREACH_BREAK, +}; /* Helpers (defined below). */ static void foreach_natural_hierarchy_child(const MainIDRelations &id_relations, const ID &parent_id, - FunctionRef<void(ID &)> fn); + FunctionRef<ForeachChildReturn(ID &)> fn); static bool id_is_in_override_hierarchy(const Main &bmain, const ID &id, const ID &relationship_parent_id, @@ -184,22 +193,30 @@ void OverrideIDHierarchyBuilder::build_hierarchy_for_ID_recursive(const ID &pare foreach_natural_hierarchy_child(id_relations_, parent_id, [&](ID &id) { /* Some IDs can use themselves, early abort. */ if (&id == &parent_id) { - return; + return FOREACH_CONTINUE; } if (!id_is_in_override_hierarchy(bmain_, id, parent_id, build_data.override_root_id_)) { - return; + return FOREACH_CONTINUE; } /* Avoid endless recursion: If there is an ancestor for this ID already, it recurses into * itself. */ if (build_data.parent_ids.lookup_key_default(&id, nullptr)) { - return; + return FOREACH_CONTINUE; } /* Avoid duplicates: If there is a sibling for this ID already, the same ID is just used * multiple times by the same parent. */ if (build_data.sibling_ids.lookup_key_default(&id, nullptr)) { - return; + return FOREACH_CONTINUE; + } + + /* We only want to add children whose parent isn't collapsed. Otherwise, in complex scenes with + * thousands of relationships, the building can slow down tremendously. Tag the parent to allow + * un-collapsing, but don't actually add the children. */ + if (!TSELEM_OPEN(TREESTORE(&te_to_expand), &space_outliner_)) { + te_to_expand.flag |= TE_PRETEND_HAS_CHILDREN; + return FOREACH_BREAK; } TreeElement *new_te = outliner_add_element( @@ -213,6 +230,8 @@ void OverrideIDHierarchyBuilder::build_hierarchy_for_ID_recursive(const ID &pare child_build_data.parent_ids.add(&id); child_build_data.sibling_ids.reserve(10); build_hierarchy_for_ID_recursive(id, child_build_data, *new_te); + + return FOREACH_CONTINUE; }); } @@ -238,7 +257,7 @@ void OverrideIDHierarchyBuilder::build_hierarchy_for_ID_recursive(const ID &pare */ static void foreach_natural_hierarchy_child(const MainIDRelations &id_relations, const ID &parent_id, - FunctionRef<void(ID &)> fn) + FunctionRef<ForeachChildReturn(ID &)> fn) { const MainIDRelationsEntry *relations_of_id = static_cast<MainIDRelationsEntry *>( BLI_ghash_lookup(id_relations.relations_from_pointers, &parent_id)); @@ -259,12 +278,16 @@ static void foreach_natural_hierarchy_child(const MainIDRelations &id_relations, if (GS(target_id.name) == ID_OB) { const Object &potential_child_ob = reinterpret_cast<const Object &>(target_id); if (potential_child_ob.parent) { - fn(potential_child_ob.parent->id); + if (fn(potential_child_ob.parent->id) == FOREACH_BREAK) { + return; + } continue; } } - fn(target_id); + if (fn(target_id) == FOREACH_BREAK) { + return; + } } /* If the ID is an object, find and iterate over any child objects. */ @@ -277,9 +300,13 @@ static void foreach_natural_hierarchy_child(const MainIDRelations &id_relations, continue; } - Object &potential_child_ob = reinterpret_cast<Object &>(potential_child_id); - if (potential_child_ob.parent && &potential_child_ob.parent->id == &parent_id) { - fn(potential_child_id); + const Object &potential_child_ob = reinterpret_cast<Object &>(potential_child_id); + if (!potential_child_ob.parent || &potential_child_ob.parent->id != &parent_id) { + continue; + } + + if (fn(potential_child_id) == FOREACH_BREAK) { + return; } } } @@ -297,7 +324,7 @@ static bool id_is_in_override_hierarchy(const Main &bmain, if (ID_IS_OVERRIDE_LIBRARY_VIRTUAL(&id)) { /* In many cases, `relationship_parent_id` is the owner, but not always (e.g. there can be - * drivers directly between an object and a shapekey). */ + * drivers directly between an object and a shape-key). */ BKE_lib_override_library_get(const_cast<Main *>(&bmain), const_cast<ID *>(&id), const_cast<ID *>(&relationship_parent_id), diff --git a/source/blender/editors/space_outliner/tree/tree_display_view_layer.cc b/source/blender/editors/space_outliner/tree/tree_display_view_layer.cc index c8869d90eca..66c1fa34914 100644 --- a/source/blender/editors/space_outliner/tree/tree_display_view_layer.cc +++ b/source/blender/editors/space_outliner/tree/tree_display_view_layer.cc @@ -64,6 +64,7 @@ ListBase TreeDisplayViewLayer::buildTree(const TreeSourceData &source_data) { ListBase tree = {nullptr}; Scene *scene = source_data.scene; + scene_ = scene; show_objects_ = !(space_outliner_.filter & SO_FILTER_NO_OBJECT); for (auto *view_layer : ListBaseWrapper<ViewLayer>(scene->view_layers)) { @@ -96,7 +97,8 @@ void TreeDisplayViewLayer::add_view_layer(Scene &scene, ListBase &tree, TreeElem if (space_outliner_.filter & SO_FILTER_NO_COLLECTION) { /* Show objects in the view layer. */ - for (Base *base : List<Base>(view_layer_->object_bases)) { + BKE_view_layer_synced_ensure(&scene, view_layer_); + for (Base *base : List<Base>(*BKE_view_layer_object_bases_get(view_layer_))) { TreeElement *te_object = outliner_add_element( &space_outliner_, &tree, base->object, parent, TSE_SOME_ID, 0); te_object->directdata = base; @@ -166,6 +168,7 @@ void TreeDisplayViewLayer::add_layer_collection_objects(ListBase &tree, LayerCollection &lc, TreeElement &ten) { + BKE_view_layer_synced_ensure(scene_, view_layer_); for (CollectionObject *cob : List<CollectionObject>(lc.collection->gobject)) { Base *base = BKE_view_layer_base_find(view_layer_, cob->ob); TreeElement *te_object = outliner_add_element( diff --git a/source/blender/editors/space_outliner/tree/tree_element.hh b/source/blender/editors/space_outliner/tree/tree_element.hh index fc6211f20ea..1b145a48daa 100644 --- a/source/blender/editors/space_outliner/tree/tree_element.hh +++ b/source/blender/editors/space_outliner/tree/tree_element.hh @@ -14,10 +14,11 @@ struct ListBase; struct SpaceOutliner; -struct TreeElement; namespace blender::ed::outliner { +struct TreeElement; + /* -------------------------------------------------------------------- */ /* Tree-Display Interface */ diff --git a/source/blender/editors/space_outliner/tree/tree_element_anim_data.hh b/source/blender/editors/space_outliner/tree/tree_element_anim_data.hh index 956cf3dec48..f3372329dd1 100644 --- a/source/blender/editors/space_outliner/tree/tree_element_anim_data.hh +++ b/source/blender/editors/space_outliner/tree/tree_element_anim_data.hh @@ -8,8 +8,6 @@ #include "tree_element.hh" -struct TreeElement; - namespace blender::ed::outliner { class TreeElementAnimData final : public AbstractTreeElement { diff --git a/source/blender/editors/space_outliner/tree/tree_element_driver.hh b/source/blender/editors/space_outliner/tree/tree_element_driver.hh index 053217e18ec..f0213dd39f2 100644 --- a/source/blender/editors/space_outliner/tree/tree_element_driver.hh +++ b/source/blender/editors/space_outliner/tree/tree_element_driver.hh @@ -8,8 +8,6 @@ #include "tree_element.hh" -struct TreeElement; - namespace blender::ed::outliner { class TreeElementDriverBase final : public AbstractTreeElement { diff --git a/source/blender/editors/space_outliner/tree/tree_element_overrides.cc b/source/blender/editors/space_outliner/tree/tree_element_overrides.cc index 49cabd5117f..11067d37966 100644 --- a/source/blender/editors/space_outliner/tree/tree_element_overrides.cc +++ b/source/blender/editors/space_outliner/tree/tree_element_overrides.cc @@ -292,7 +292,7 @@ void OverrideRNAPathTreeBuilder::build_path(TreeElement &parent, PointerRNA idpoin; RNA_id_pointer_create(&override_data.id, &idpoin); - ListBase path_elems = {NULL}; + ListBase path_elems = {nullptr}; if (!RNA_path_resolve_elements(&idpoin, override_data.override_property.rna_path, &path_elems)) { return; } diff --git a/source/blender/editors/space_outliner/tree/tree_element_rna.cc b/source/blender/editors/space_outliner/tree/tree_element_rna.cc index 6dd5ec84041..9e1f22b49d6 100644 --- a/source/blender/editors/space_outliner/tree/tree_element_rna.cc +++ b/source/blender/editors/space_outliner/tree/tree_element_rna.cc @@ -124,7 +124,7 @@ void TreeElementRNAStruct::expand(SpaceOutliner &space_outliner) const } } else if (tot) { - legacy_te_.flag |= TE_LAZY_CLOSED; + legacy_te_.flag |= TE_PRETEND_HAS_CHILDREN; } } @@ -172,7 +172,7 @@ void TreeElementRNAProperty::expand(SpaceOutliner &space_outliner) const &space_outliner, &legacy_te_.subtree, &pptr, &legacy_te_, TSE_RNA_STRUCT, -1); } else { - legacy_te_.flag |= TE_LAZY_CLOSED; + legacy_te_.flag |= TE_PRETEND_HAS_CHILDREN; } } } @@ -189,7 +189,7 @@ void TreeElementRNAProperty::expand(SpaceOutliner &space_outliner) const } } else if (tot) { - legacy_te_.flag |= TE_LAZY_CLOSED; + legacy_te_.flag |= TE_PRETEND_HAS_CHILDREN; } } else if (ELEM(proptype, PROP_BOOLEAN, PROP_INT, PROP_FLOAT)) { @@ -207,7 +207,7 @@ void TreeElementRNAProperty::expand(SpaceOutliner &space_outliner) const } } else if (tot) { - legacy_te_.flag |= TE_LAZY_CLOSED; + legacy_te_.flag |= TE_PRETEND_HAS_CHILDREN; } } } diff --git a/source/blender/editors/space_outliner/tree/tree_iterator.hh b/source/blender/editors/space_outliner/tree/tree_iterator.hh index de5bcd2c462..0c94c2f95cf 100644 --- a/source/blender/editors/space_outliner/tree/tree_iterator.hh +++ b/source/blender/editors/space_outliner/tree/tree_iterator.hh @@ -10,9 +10,11 @@ struct ListBase; struct SpaceOutliner; -struct TreeElement; namespace blender::ed::outliner { + +struct TreeElement; + namespace tree_iterator { using VisitorFn = FunctionRef<void(TreeElement *)>; diff --git a/source/blender/editors/space_script/CMakeLists.txt b/source/blender/editors/space_script/CMakeLists.txt index 8486fa0e872..f7fc4e38c17 100644 --- a/source/blender/editors/space_script/CMakeLists.txt +++ b/source/blender/editors/space_script/CMakeLists.txt @@ -8,7 +8,6 @@ set(INC ../../makesdna ../../makesrna ../../windowmanager - ../../../../intern/glew-mx ../../../../intern/guardedalloc ) diff --git a/source/blender/editors/space_script/space_script.c b/source/blender/editors/space_script/space_script.c index a623b98f1b1..c35b1e00184 100644 --- a/source/blender/editors/space_script/space_script.c +++ b/source/blender/editors/space_script/space_script.c @@ -152,7 +152,7 @@ void ED_spacetype_script(void) ARegionType *art; st->spaceid = SPACE_SCRIPT; - strncpy(st->name, "Script", BKE_ST_MAXNAME); + STRNCPY(st->name, "Script"); st->create = script_create; st->free = script_free; diff --git a/source/blender/editors/space_sequencer/CMakeLists.txt b/source/blender/editors/space_sequencer/CMakeLists.txt index 44f919ca361..deaec0136c4 100644 --- a/source/blender/editors/space_sequencer/CMakeLists.txt +++ b/source/blender/editors/space_sequencer/CMakeLists.txt @@ -15,7 +15,6 @@ set(INC ../../sequencer ../../windowmanager ../../../../intern/atomic - ../../../../intern/glew-mx ../../../../intern/guardedalloc # RNA_prototypes.h ${CMAKE_BINARY_DIR}/source/blender/makesrna diff --git a/source/blender/editors/space_sequencer/sequencer_drag_drop.c b/source/blender/editors/space_sequencer/sequencer_drag_drop.c index 4796d80b3a0..c892e7d7e55 100644 --- a/source/blender/editors/space_sequencer/sequencer_drag_drop.c +++ b/source/blender/editors/space_sequencer/sequencer_drag_drop.c @@ -293,7 +293,7 @@ static void sequencer_drop_copy(bContext *C, wmDrag *drag, wmDropBox *drop) SeqCollection *strips = SEQ_query_rendered_strips( scene, channels, seqbase, scene->r.cfra, sseq->chanshown); - /* Get the top most strip channel that is in view.*/ + /* Get the top most strip channel that is in view. */ Sequence *seq; int max_channel = -1; SEQ_ITERATOR_FOREACH (seq, strips) { @@ -365,7 +365,7 @@ static void draw_seq_in_view(bContext *C, wmWindow *UNUSED(win), wmDrag *drag, c GPU_blend(GPU_BLEND_ALPHA); GPU_line_smooth(true); uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); - immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); /* Draw strips. The code here is taken from sequencer_draw. */ float x1 = coords->start_frame; diff --git a/source/blender/editors/space_sequencer/sequencer_draw.c b/source/blender/editors/space_sequencer/sequencer_draw.c index 0bacbde8240..71804d29e6b 100644 --- a/source/blender/editors/space_sequencer/sequencer_draw.c +++ b/source/blender/editors/space_sequencer/sequencer_draw.c @@ -311,7 +311,7 @@ static size_t draw_waveform_segment(WaveVizData *waveform_data, bool use_rms) GPUPrimType prim_type = waveform_data->draw_line ? GPU_PRIM_LINE_STRIP : GPU_PRIM_TRI_STRIP; uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); uint col = GPU_vertformat_attr_add(format, "color", GPU_COMP_F32, 4, GPU_FETCH_FLOAT); - immBindBuiltinProgram(GPU_SHADER_2D_FLAT_COLOR); + immBindBuiltinProgram(GPU_SHADER_3D_FLAT_COLOR); immBegin(prim_type, vertex_count); while (vertices_done < vertex_count && !waveform_data->final_sample) { @@ -519,18 +519,6 @@ static void draw_seq_waveform_overlay( MEM_freeN(waveform_data); } -#if 0 -static size_t *waveform_append(WaveVizData *waveform_data, - vec2f pos, - const float value_min, - const float value_max, - const float y_mid, - const float y_scale, - const float rms, - const bool is_clipping, - const bool is_line_strip) -#endif - static void drawmeta_contents(Scene *scene, Sequence *seqm, float x1, @@ -580,7 +568,7 @@ static void drawmeta_contents(Scene *scene, col[3] = 196; /* Alpha, used for all meta children. */ uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); - immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); /* Draw only immediate children (1 level depth). */ for (seq = meta_seqbase->first; seq; seq = seq->next) { @@ -1170,7 +1158,7 @@ static void draw_seq_invalid(float x1, float x2, float y2, float text_margin_y) GPU_blend(GPU_BLEND_ALPHA); uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); - immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); immUniformColor4f(1.0f, 0.0f, 0.0f, 0.9f); immRectf(pos, x1, y2, x2, text_margin_y); @@ -1288,7 +1276,7 @@ static void draw_seq_fcurve_overlay( GPUBatch *batch = GPU_batch_create_ex(GPU_PRIM_TRI_STRIP, vbo, NULL, GPU_BATCH_OWNS_VBO); GPU_vertbuf_data_len_set(vbo, vert_count); - GPU_batch_program_set_builtin(batch, GPU_SHADER_2D_UNIFORM_COLOR); + GPU_batch_program_set_builtin(batch, GPU_SHADER_3D_UNIFORM_COLOR); GPU_batch_uniform_4f(batch, "color", 0.0f, 0.0f, 0.0f, 0.15f); GPU_blend(GPU_BLEND_ALPHA); @@ -1356,7 +1344,7 @@ static void draw_seq_strip(const bContext *C, } uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); - immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); draw_seq_background(scene, seq, pos, x1, x2, y1, y2, is_single_image, show_strip_color_tag); @@ -1412,7 +1400,7 @@ static void draw_seq_strip(const bContext *C, } pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); - immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); if (!SEQ_transform_is_locked(channels, seq)) { draw_seq_handle( @@ -1454,7 +1442,7 @@ static void draw_effect_inputs_highlight(const Scene *scene, Sequence *seq) GPU_blend(GPU_BLEND_ALPHA); uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); - immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); immUniformColor4ub(255, 255, 255, 48); immRectf(pos, @@ -1661,7 +1649,7 @@ static void sequencer_draw_borders_overlay(const SpaceSeq *sseq, const uint shdr_pos = GPU_vertformat_attr_add( immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); - immBindBuiltinProgram(GPU_SHADER_2D_LINE_DASHED_UNIFORM_COLOR); + immBindBuiltinProgram(GPU_SHADER_3D_LINE_DASHED_UNIFORM_COLOR); float viewport_size[4]; GPU_viewport_size_get_f(viewport_size); @@ -1932,7 +1920,7 @@ static void sequencer_draw_display_buffer(const bContext *C, GPU_texture_bind(texture, 0); if (!glsl_used) { - immBindBuiltinProgram(GPU_SHADER_2D_IMAGE_COLOR); + immBindBuiltinProgram(GPU_SHADER_3D_IMAGE_COLOR); immUniformColor3f(1.0f, 1.0f, 1.0f); } @@ -2121,7 +2109,7 @@ static void seq_draw_image_origin_and_outline(const bContext *C, Sequence *seq, GPU_line_smooth(true); GPU_blend(GPU_BLEND_ALPHA); GPU_line_width(2); - immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); float col[3]; if (is_active_seq) { @@ -2259,7 +2247,7 @@ void sequencer_draw_preview(const bContext *C, static void draw_seq_timeline_channels(View2D *v2d) { uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); - immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); GPU_blend(GPU_BLEND_ALPHA); immUniformThemeColor(TH_ROW_ALTERNATE); @@ -2337,7 +2325,7 @@ static void draw_seq_strips(const bContext *C, Editing *ed, ARegion *region) GPU_blend(GPU_BLEND_ALPHA); uint pos = GPU_vertformat_attr_add( immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); - immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); immUniformColor4ub(255, 255, 255, 48); immRectf(pos, v2d->cur.xmin, channel, v2d->cur.xmax, channel + 1); @@ -2354,7 +2342,7 @@ static void draw_seq_strips(const bContext *C, Editing *ed, ARegion *region) GPU_blend(GPU_BLEND_ALPHA); uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); - immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); immUniformColor4ub(255, 255, 255, 48); immRectf(pos, @@ -2378,7 +2366,7 @@ static void seq_draw_sfra_efra(const Scene *scene, View2D *v2d) GPU_blend(GPU_BLEND_ALPHA); uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); - immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); /* Draw overlay outside of frame range. */ immUniformThemeColorShadeAlpha(TH_BACK, -10, -100); @@ -2420,7 +2408,7 @@ static void seq_draw_sfra_efra(const Scene *scene, View2D *v2d) immUnbindProgram(); - immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); immUniformThemeColorShade(TH_BACK, -40); immBegin(GPU_PRIM_LINES, 4); @@ -2544,7 +2532,7 @@ static void draw_cache_view_batch( GPUBatch *batch = GPU_batch_create_ex(GPU_PRIM_TRIS, vbo, NULL, GPU_BATCH_OWNS_VBO); if (vert_count > 0) { GPU_vertbuf_data_len_set(vbo, vert_count); - GPU_batch_program_set_builtin(batch, GPU_SHADER_2D_UNIFORM_COLOR); + GPU_batch_program_set_builtin(batch, GPU_SHADER_3D_UNIFORM_COLOR); GPU_batch_uniform_4f(batch, "color", col_r, col_g, col_b, col_a); GPU_batch_draw(batch); } @@ -2563,7 +2551,7 @@ static void draw_cache_view(const bContext *C) GPU_blend(GPU_BLEND_ALPHA); uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); - immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); float stripe_bot, stripe_top; float stripe_ofs_y = UI_view2d_region_to_view_y(v2d, 1.0f) - v2d->cur.ymin; @@ -2672,7 +2660,7 @@ static void draw_overlap_frame_indicator(const struct Scene *scene, const View2D scene->r.cfra + scene->ed->overlay_frame_ofs; uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); - immBindBuiltinProgram(GPU_SHADER_2D_LINE_DASHED_UNIFORM_COLOR); + immBindBuiltinProgram(GPU_SHADER_3D_LINE_DASHED_UNIFORM_COLOR); float viewport_size[4]; GPU_viewport_size_get_f(viewport_size); immUniform2f("viewport_size", viewport_size[2], viewport_size[3]); diff --git a/source/blender/editors/space_sequencer/sequencer_edit.c b/source/blender/editors/space_sequencer/sequencer_edit.c index 9313e45a1d4..415bb5898a9 100644 --- a/source/blender/editors/space_sequencer/sequencer_edit.c +++ b/source/blender/editors/space_sequencer/sequencer_edit.c @@ -54,6 +54,7 @@ #include "RNA_prototypes.h" /* For menu, popup, icons, etc. */ +#include "ED_fileselect.h" #include "ED_keyframing.h" #include "ED_numinput.h" #include "ED_outliner.h" @@ -1931,7 +1932,7 @@ static int sequencer_meta_toggle_exec(bContext *C, wmOperator *UNUSED(op)) SEQ_select_active_set(scene, meta_parent); } - // DEG_id_tag_update(&scene->id, ID_RECALC_SEQUENCER_STRIPS); + DEG_id_tag_update(&scene->id, ID_RECALC_SEQUENCER_STRIPS); WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene); return OPERATOR_FINISHED; @@ -2637,12 +2638,12 @@ static int sequencer_swap_data_exec(bContext *C, wmOperator *op) Sequence *seq_other; const char *error_msg; - if (SEQ_select_active_get_pair(scene, &seq_act, &seq_other) == 0) { + if (SEQ_select_active_get_pair(scene, &seq_act, &seq_other) == false) { BKE_report(op->reports, RPT_ERROR, "Please select two strips"); return OPERATOR_CANCELLED; } - if (SEQ_edit_sequence_swap(scene, seq_act, seq_other, &error_msg) == 0) { + if (SEQ_edit_sequence_swap(scene, seq_act, seq_other, &error_msg) == false) { BKE_report(op->reports, RPT_ERROR, error_msg); return OPERATOR_CANCELLED; } @@ -3076,7 +3077,7 @@ static int seq_cmp_time_startdisp_channel(void *thunk, const void *a, const void int seq_a_start = SEQ_time_left_handle_frame_get(scene, seq_a); int seq_b_start = SEQ_time_left_handle_frame_get(scene, seq_b); - /* If strips have the same start frame favor the one with a higher channel.*/ + /* If strips have the same start frame favor the one with a higher channel. */ if (seq_a_start == seq_b_start) { return seq_a->machine > seq_b->machine; } @@ -3088,20 +3089,7 @@ static int sequencer_export_subtitles_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) { - Main *bmain = CTX_data_main(C); - if (!RNA_struct_property_is_set(op->ptr, "filepath")) { - char filepath[FILE_MAX]; - - if (BKE_main_blendfile_path(bmain)[0] == '\0') { - BLI_strncpy(filepath, "untitled", sizeof(filepath)); - } - else { - BLI_strncpy(filepath, BKE_main_blendfile_path(bmain), sizeof(filepath)); - } - - BLI_path_extension_replace(filepath, sizeof(filepath), ".srt"); - RNA_string_set(op->ptr, "filepath", filepath); - } + ED_fileselect_ensure_default_filepath(C, op, ".srt"); WM_event_add_fileselect(C, op); @@ -3136,7 +3124,7 @@ static int sequencer_export_subtitles_exec(bContext *C, wmOperator *op) FILE *file; char filepath[FILE_MAX]; - if (!RNA_struct_property_is_set(op->ptr, "filepath")) { + if (!RNA_struct_property_is_set_ex(op->ptr, "filepath", false)) { BKE_report(op->reports, RPT_ERROR, "No filename given"); return OPERATOR_CANCELLED; } diff --git a/source/blender/editors/space_sequencer/space_sequencer.c b/source/blender/editors/space_sequencer/space_sequencer.c index 0199fa81928..508f18ade5a 100644 --- a/source/blender/editors/space_sequencer/space_sequencer.c +++ b/source/blender/editors/space_sequencer/space_sequencer.c @@ -229,7 +229,7 @@ static void sequencer_free(SpaceLink *sl) } } -/* Spacetype init callback. */ +/* Space-type init callback. */ static void sequencer_init(struct wmWindowManager *UNUSED(wm), ScrArea *UNUSED(area)) { } @@ -374,7 +374,7 @@ static SpaceLink *sequencer_duplicate(SpaceLink *sl) static void sequencer_listener(const wmSpaceTypeListenerParams *params) { ScrArea *area = params->area; - wmNotifier *wmn = params->notifier; + const wmNotifier *wmn = params->notifier; /* Context changes. */ switch (wmn->category) { @@ -630,7 +630,7 @@ static void sequencer_main_region_view2d_changed(const bContext *C, ARegion *reg static void sequencer_main_region_listener(const wmRegionListenerParams *params) { ARegion *region = params->region; - wmNotifier *wmn = params->notifier; + const wmNotifier *wmn = params->notifier; /* Context changes. */ switch (wmn->category) { @@ -862,7 +862,7 @@ static void sequencer_preview_region_draw(const bContext *C, ARegion *region) static void sequencer_preview_region_listener(const wmRegionListenerParams *params) { ARegion *region = params->region; - wmNotifier *wmn = params->notifier; + const wmNotifier *wmn = params->notifier; WM_gizmomap_tag_refresh(region->gizmo_map); @@ -933,7 +933,7 @@ static void sequencer_buttons_region_draw(const bContext *C, ARegion *region) static void sequencer_buttons_region_listener(const wmRegionListenerParams *params) { ARegion *region = params->region; - wmNotifier *wmn = params->notifier; + const wmNotifier *wmn = params->notifier; /* Context changes. */ switch (wmn->category) { @@ -997,7 +997,7 @@ void ED_spacetype_sequencer(void) ARegionType *art; st->spaceid = SPACE_SEQ; - strncpy(st->name, "Sequencer", BKE_ST_MAXNAME); + STRNCPY(st->name, "Sequencer"); st->create = sequencer_create; st->free = sequencer_free; diff --git a/source/blender/editors/space_spreadsheet/CMakeLists.txt b/source/blender/editors/space_spreadsheet/CMakeLists.txt index f134cdb95c2..173d976c124 100644 --- a/source/blender/editors/space_spreadsheet/CMakeLists.txt +++ b/source/blender/editors/space_spreadsheet/CMakeLists.txt @@ -14,7 +14,6 @@ set(INC ../../makesrna ../../nodes ../../windowmanager - ../../../../intern/glew-mx ../../../../intern/guardedalloc # RNA_prototypes.h ${CMAKE_BINARY_DIR}/source/blender/makesrna diff --git a/source/blender/editors/space_spreadsheet/space_spreadsheet.cc b/source/blender/editors/space_spreadsheet/space_spreadsheet.cc index 8dbb4a2ee0c..435436611c5 100644 --- a/source/blender/editors/space_spreadsheet/space_spreadsheet.cc +++ b/source/blender/editors/space_spreadsheet/space_spreadsheet.cc @@ -436,7 +436,7 @@ static void spreadsheet_main_region_draw(const bContext *C, ARegion *region) static void spreadsheet_main_region_listener(const wmRegionListenerParams *params) { ARegion *region = params->region; - wmNotifier *wmn = params->notifier; + const wmNotifier *wmn = params->notifier; switch (wmn->category) { case NC_SCENE: { @@ -486,7 +486,7 @@ static void spreadsheet_header_region_free(ARegion *UNUSED(region)) static void spreadsheet_header_region_listener(const wmRegionListenerParams *params) { ARegion *region = params->region; - wmNotifier *wmn = params->notifier; + const wmNotifier *wmn = params->notifier; switch (wmn->category) { case NC_SCENE: { @@ -570,7 +570,7 @@ static void spreadsheet_footer_region_listener(const wmRegionListenerParams *UNU static void spreadsheet_dataset_region_listener(const wmRegionListenerParams *params) { ARegion *region = params->region; - wmNotifier *wmn = params->notifier; + const wmNotifier *wmn = params->notifier; switch (wmn->category) { case NC_SCENE: { @@ -619,7 +619,7 @@ void ED_spacetype_spreadsheet() ARegionType *art; st->spaceid = SPACE_SPREADSHEET; - strncpy(st->name, "Spreadsheet", BKE_ST_MAXNAME); + STRNCPY(st->name, "Spreadsheet"); st->create = spreadsheet_create; st->free = spreadsheet_free; diff --git a/source/blender/editors/space_spreadsheet/spreadsheet_data_source_geometry.cc b/source/blender/editors/space_spreadsheet/spreadsheet_data_source_geometry.cc index fdcf9798b7f..fd2ac4d39a1 100644 --- a/source/blender/editors/space_spreadsheet/spreadsheet_data_source_geometry.cc +++ b/source/blender/editors/space_spreadsheet/spreadsheet_data_source_geometry.cc @@ -4,6 +4,7 @@ #include "BLI_virtual_array.hh" #include "BKE_attribute.hh" +#include "BKE_compute_contexts.hh" #include "BKE_context.h" #include "BKE_curves.hh" #include "BKE_editmesh.h" @@ -26,7 +27,8 @@ #include "ED_curves_sculpt.h" #include "ED_spreadsheet.h" -#include "NOD_geometry_nodes_eval_log.hh" +#include "NOD_geometry_nodes_lazy_function.hh" +#include "NOD_geometry_nodes_log.hh" #include "BLT_translation.h" @@ -40,8 +42,8 @@ #include "spreadsheet_data_source_geometry.hh" #include "spreadsheet_intern.hh" -namespace geo_log = blender::nodes::geometry_nodes_eval_log; using blender::fn::GField; +using blender::nodes::geo_eval_log::ViewerNodeLog; namespace blender::ed::spreadsheet { @@ -168,45 +170,49 @@ std::unique_ptr<ColumnValues> GeometryDataSource::get_column_values( else if (G.debug_value == 4001 && component_->type() == GEO_COMPONENT_TYPE_MESH) { const MeshComponent &component = static_cast<const MeshComponent &>(*component_); if (const Mesh *mesh = component.get_for_read()) { + const Span<MEdge> edges = mesh->edges(); + const Span<MPoly> polys = mesh->polys(); + const Span<MLoop> loops = mesh->loops(); + if (domain_ == ATTR_DOMAIN_EDGE) { if (STREQ(column_id.name, "Vertex 1")) { return std::make_unique<ColumnValues>( - column_id.name, VArray<int>::ForFunc(mesh->totedge, [mesh](int64_t index) { - return mesh->medge[index].v1; + column_id.name, VArray<int>::ForFunc(edges.size(), [edges](int64_t index) { + return edges[index].v1; })); } if (STREQ(column_id.name, "Vertex 2")) { return std::make_unique<ColumnValues>( - column_id.name, VArray<int>::ForFunc(mesh->totedge, [mesh](int64_t index) { - return mesh->medge[index].v2; + column_id.name, VArray<int>::ForFunc(edges.size(), [edges](int64_t index) { + return edges[index].v2; })); } } else if (domain_ == ATTR_DOMAIN_FACE) { if (STREQ(column_id.name, "Corner Start")) { return std::make_unique<ColumnValues>( - column_id.name, VArray<int>::ForFunc(mesh->totpoly, [mesh](int64_t index) { - return mesh->mpoly[index].loopstart; + column_id.name, VArray<int>::ForFunc(polys.size(), [polys](int64_t index) { + return polys[index].loopstart; })); } if (STREQ(column_id.name, "Corner Size")) { return std::make_unique<ColumnValues>( - column_id.name, VArray<int>::ForFunc(mesh->totpoly, [mesh](int64_t index) { - return mesh->mpoly[index].totloop; + column_id.name, VArray<int>::ForFunc(polys.size(), [polys](int64_t index) { + return polys[index].totloop; })); } } else if (domain_ == ATTR_DOMAIN_CORNER) { if (STREQ(column_id.name, "Vertex")) { return std::make_unique<ColumnValues>( - column_id.name, VArray<int>::ForFunc(mesh->totloop, [mesh](int64_t index) { - return mesh->mloop[index].v; + column_id.name, VArray<int>::ForFunc(loops.size(), [loops](int64_t index) { + return loops[index].v; })); } if (STREQ(column_id.name, "Edge")) { return std::make_unique<ColumnValues>( - column_id.name, VArray<int>::ForFunc(mesh->totloop, [mesh](int64_t index) { - return mesh->mloop[index].e; + column_id.name, VArray<int>::ForFunc(loops.size(), [loops](int64_t index) { + return loops[index].e; })); } } @@ -265,6 +271,9 @@ IndexMask GeometryDataSource::apply_selection_filter(Vector<int64_t> &indices) c { std::lock_guard lock{mutex_}; const IndexMask full_range(this->tot_rows()); + if (full_range.is_empty()) { + return full_range; + } switch (component_->type()) { case GEO_COMPONENT_TYPE_MESH: { @@ -272,7 +281,7 @@ IndexMask GeometryDataSource::apply_selection_filter(Vector<int64_t> &indices) c BLI_assert(object_eval_->mode == OB_MODE_EDIT); Object *object_orig = DEG_get_original_object(object_eval_); const Mesh *mesh_eval = geometry_set_.get_mesh_for_read(); - const bke::AttributeAccessor attributes_eval = bke::mesh_attributes(*mesh_eval); + const bke::AttributeAccessor attributes_eval = mesh_eval->attributes(); Mesh *mesh_orig = (Mesh *)object_orig->data; BMesh *bm = mesh_orig->edit_mesh->bm; BM_mesh_elem_table_ensure(bm, BM_VERT); @@ -461,19 +470,10 @@ GeometrySet spreadsheet_get_display_geometry_set(const SpaceSpreadsheet *sspread } } else { - const geo_log::NodeLog *node_log = - geo_log::ModifierLog::find_node_by_spreadsheet_editor_context(*sspreadsheet); - if (node_log != nullptr) { - for (const geo_log::SocketLog &input_log : node_log->input_logs()) { - if (const geo_log::GeometryValueLog *geo_value_log = - dynamic_cast<const geo_log::GeometryValueLog *>(input_log.value())) { - const GeometrySet *full_geometry = geo_value_log->full_geometry(); - if (full_geometry != nullptr) { - geometry_set = *full_geometry; - break; - } - } - } + if (const ViewerNodeLog *viewer_log = + nodes::geo_eval_log::GeoModifierLog::find_viewer_node_log_for_spreadsheet( + *sspreadsheet)) { + geometry_set = viewer_log->geometry; } } } @@ -491,27 +491,11 @@ static void find_fields_to_evaluate(const SpaceSpreadsheet *sspreadsheet, /* No viewer is currently referenced by the context path. */ return; } - const geo_log::NodeLog *node_log = geo_log::ModifierLog::find_node_by_spreadsheet_editor_context( - *sspreadsheet); - if (node_log == nullptr) { - return; - } - for (const geo_log::SocketLog &socket_log : node_log->input_logs()) { - const geo_log::ValueLog *value_log = socket_log.value(); - if (value_log == nullptr) { - continue; - } - if (const geo_log::GFieldValueLog *field_value_log = - dynamic_cast<const geo_log::GFieldValueLog *>(value_log)) { - const GField &field = field_value_log->field(); - if (field) { - r_fields.add("Viewer", std::move(field)); - } - } - if (const geo_log::GenericValueLog *generic_value_log = - dynamic_cast<const geo_log::GenericValueLog *>(value_log)) { - GPointer value = generic_value_log->value(); - r_fields.add("Viewer", fn::make_constant_field(*value.type(), value.get())); + if (const ViewerNodeLog *viewer_log = + nodes::geo_eval_log::GeoModifierLog::find_viewer_node_log_for_spreadsheet( + *sspreadsheet)) { + if (viewer_log->field) { + r_fields.add("Viewer", viewer_log->field); } } } @@ -568,7 +552,7 @@ static void add_fields_as_extra_columns(SpaceSpreadsheet *sspreadsheet, GArray<> &evaluated_array = cache.arrays.lookup_or_add_cb({domain, field}, [&]() { GArray<> evaluated_array(field.cpp_type(), domain_num); - bke::GeometryComponentFieldContext field_context{component, domain}; + bke::GeometryFieldContext field_context{component, domain}; fn::FieldEvaluator field_evaluator{field_context, domain_num}; field_evaluator.add_with_destination(field, evaluated_array); field_evaluator.evaluate(); diff --git a/source/blender/editors/space_spreadsheet/spreadsheet_draw.cc b/source/blender/editors/space_spreadsheet/spreadsheet_draw.cc index c7170cd1da3..e1f13f05715 100644 --- a/source/blender/editors/space_spreadsheet/spreadsheet_draw.cc +++ b/source/blender/editors/space_spreadsheet/spreadsheet_draw.cc @@ -273,7 +273,7 @@ void draw_spreadsheet_in_region(const bContext *C, GPUVertFormat *format = immVertexFormat(); uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_I32, 2, GPU_FETCH_INT_TO_FLOAT); - immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); draw_index_column_background(pos, region, drawer); draw_alternating_row_overlay(pos, scroll_offset_y, region, drawer); diff --git a/source/blender/editors/space_spreadsheet/spreadsheet_row_filter.cc b/source/blender/editors/space_spreadsheet/spreadsheet_row_filter.cc index 6806e185cfe..03cf0116dce 100644 --- a/source/blender/editors/space_spreadsheet/spreadsheet_row_filter.cc +++ b/source/blender/editors/space_spreadsheet/spreadsheet_row_filter.cc @@ -71,6 +71,14 @@ static void apply_row_filter(const SpreadsheetRowFilter &row_filter, } } } + else if (column_data.type().is<bool>()) { + const bool value = (row_filter.flag & SPREADSHEET_ROW_FILTER_BOOL_VALUE) != 0; + apply_filter_operation( + column_data.typed<bool>(), + [&](const bool cell) { return cell == value; }, + prev_mask, + new_indices); + } else if (column_data.type().is<int8_t>()) { const int value = row_filter.value_int; switch (row_filter.operation) { @@ -274,7 +282,6 @@ static void apply_row_filter(const SpreadsheetRowFilter &row_filter, } else if (column_data.type().is<InstanceReference>()) { const StringRef value = row_filter.value_string; - apply_filter_operation( column_data.typed<InstanceReference>(), [&](const InstanceReference cell) { diff --git a/source/blender/editors/space_statusbar/CMakeLists.txt b/source/blender/editors/space_statusbar/CMakeLists.txt index fba40c1ec26..cf0ccd4e552 100644 --- a/source/blender/editors/space_statusbar/CMakeLists.txt +++ b/source/blender/editors/space_statusbar/CMakeLists.txt @@ -10,7 +10,6 @@ set(INC ../../makesdna ../../makesrna ../../windowmanager - ../../../../intern/glew-mx ../../../../intern/guardedalloc # RNA_prototypes.h ${CMAKE_BINARY_DIR}/source/blender/makesrna diff --git a/source/blender/editors/space_statusbar/space_statusbar.c b/source/blender/editors/space_statusbar/space_statusbar.c index 273c0375fb0..e99e8f21364 100644 --- a/source/blender/editors/space_statusbar/space_statusbar.c +++ b/source/blender/editors/space_statusbar/space_statusbar.c @@ -83,7 +83,7 @@ static void statusbar_keymap(struct wmKeyConfig *UNUSED(keyconf)) static void statusbar_header_region_listener(const wmRegionListenerParams *params) { ARegion *region = params->region; - wmNotifier *wmn = params->notifier; + const wmNotifier *wmn = params->notifier; /* context changes */ switch (wmn->category) { @@ -136,7 +136,7 @@ void ED_spacetype_statusbar(void) ARegionType *art; st->spaceid = SPACE_STATUSBAR; - strncpy(st->name, "Status Bar", BKE_ST_MAXNAME); + STRNCPY(st->name, "Status Bar"); st->create = statusbar_create; st->free = statusbar_free; diff --git a/source/blender/editors/space_text/CMakeLists.txt b/source/blender/editors/space_text/CMakeLists.txt index 6410e971a66..38787a84fce 100644 --- a/source/blender/editors/space_text/CMakeLists.txt +++ b/source/blender/editors/space_text/CMakeLists.txt @@ -10,7 +10,6 @@ set(INC ../../makesdna ../../makesrna ../../windowmanager - ../../../../intern/glew-mx ../../../../intern/guardedalloc ) diff --git a/source/blender/editors/space_text/space_text.c b/source/blender/editors/space_text/space_text.c index 1b4acda9bcf..be9bbdf109e 100644 --- a/source/blender/editors/space_text/space_text.c +++ b/source/blender/editors/space_text/space_text.c @@ -109,7 +109,7 @@ static SpaceLink *text_duplicate(SpaceLink *sl) static void text_listener(const wmSpaceTypeListenerParams *params) { ScrArea *area = params->area; - wmNotifier *wmn = params->notifier; + const wmNotifier *wmn = params->notifier; SpaceText *st = area->spacedata.first; /* context changes */ @@ -326,7 +326,7 @@ static void text_drop_paste(bContext *UNUSED(C), wmDrag *drag, wmDropBox *drop) ID *id = WM_drag_get_local_ID(drag, 0); /* copy drag path to properties */ - text = RNA_path_full_ID_py(G_MAIN, id); + text = RNA_path_full_ID_py(id); RNA_string_set(drop->ptr, "text", text); MEM_freeN(text); } @@ -403,7 +403,7 @@ void ED_spacetype_text(void) ARegionType *art; st->spaceid = SPACE_TEXT; - strncpy(st->name, "Text", BKE_ST_MAXNAME); + STRNCPY(st->name, "Text"); st->create = text_create; st->free = text_free; diff --git a/source/blender/editors/space_text/text_draw.c b/source/blender/editors/space_text/text_draw.c index c93ffccd477..a976bb6c34b 100644 --- a/source/blender/editors/space_text/text_draw.c +++ b/source/blender/editors/space_text/text_draw.c @@ -706,7 +706,7 @@ static void text_update_drawcache(SpaceText *st, ARegion *region) drawcache->showlinenrs = st->showlinenrs; drawcache->tabnumber = st->tabnumber; - strncpy(drawcache->text_id, txt->id.name, MAX_ID_NAME); + STRNCPY(drawcache->text_id, txt->id.name); /* clear update flag */ drawcache->update_flag = 0; @@ -925,12 +925,12 @@ static void calc_text_rcts(SpaceText *st, ARegion *region, rcti *scroll, rcti *b hlstart = (lhlstart * pix_available) / ltexth; hlend = (lhlend * pix_available) / ltexth; - /* The scrollbar is non-linear sized. */ + /* The scroll-bar is non-linear sized. */ if (pix_bardiff > 0) { /* the start of the highlight is in the current viewport */ if (st->runtime.viewlines && lhlstart >= st->top && lhlstart <= st->top + st->runtime.viewlines) { - /* Speed the progression of the start of the highlight through the scrollbar. */ + /* Speed the progression of the start of the highlight through the scroll-bar. */ hlstart = (((pix_available - pix_bardiff) * lhlstart) / ltexth) + (pix_bardiff * (lhlstart - st->top) / st->runtime.viewlines); } @@ -951,7 +951,7 @@ static void calc_text_rcts(SpaceText *st, ARegion *region, rcti *scroll, rcti *b /* the end of the highlight is in the current viewport */ if (st->runtime.viewlines && lhlend >= st->top && lhlend <= st->top + st->runtime.viewlines) { - /* Speed the progression of the end of the highlight through the scrollbar. */ + /* Speed the progression of the end of the highlight through the scroll-bar. */ hlend = (((pix_available - pix_bardiff) * lhlend) / ltexth) + (pix_bardiff * (lhlend - st->top) / st->runtime.viewlines); } @@ -994,10 +994,10 @@ static void draw_textscroll(const SpaceText *st, rcti *scroll, rcti *back) float col[4]; float rad; - /* background so highlights don't go behind the scrollbar */ + /* Background so highlights don't go behind the scroll-bar. */ uint pos = GPU_vertformat_attr_add( immVertexFormat(), "pos", GPU_COMP_I32, 2, GPU_FETCH_INT_TO_FLOAT); - immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); immUniformThemeColor(TH_BACK); immRecti(pos, back->xmin, back->ymin, back->xmax, back->ymax); immUnbindProgram(); @@ -1076,7 +1076,7 @@ static void draw_documentation(const SpaceText *st, ARegion *region) /* Draw panel */ uint pos = GPU_vertformat_attr_add( immVertexFormat(), "pos", GPU_COMP_I32, 2, GPU_FETCH_INT_TO_FLOAT); - immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); immUniformThemeColor(TH_BACK); immRecti(pos, x, y, x + boxw, y - boxh); @@ -1206,7 +1206,7 @@ static void draw_suggestion_list(const SpaceText *st, const TextDrawContext *tdc uint pos = GPU_vertformat_attr_add( immVertexFormat(), "pos", GPU_COMP_I32, 2, GPU_FETCH_INT_TO_FLOAT); - immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); immUniformThemeColor(TH_SHADE1); immRecti(pos, x - 1, y + 1, x + boxw + 1, y - boxh - 1); @@ -1232,7 +1232,7 @@ static void draw_suggestion_list(const SpaceText *st, const TextDrawContext *tdc if (item == sel) { uint posi = GPU_vertformat_attr_add( immVertexFormat(), "pos", GPU_COMP_I32, 2, GPU_FETCH_INT_TO_FLOAT); - immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); immUniformThemeColor(TH_SHADE2); immRecti(posi, x + margin_x, y - 3, x + margin_x + w, y + lheight - 3); @@ -1280,7 +1280,7 @@ static void draw_text_decoration(SpaceText *st, ARegion *region) uint pos = GPU_vertformat_attr_add( immVertexFormat(), "pos", GPU_COMP_I32, 2, GPU_FETCH_INT_TO_FLOAT); - immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); /* Draw the selection */ if (text->curl != text->sell || text->curc != text->selc) { @@ -1663,7 +1663,7 @@ void draw_text_main(SpaceText *st, ARegion *region) if (st->showlinenrs) { uint pos = GPU_vertformat_attr_add( immVertexFormat(), "pos", GPU_COMP_I32, 2, GPU_FETCH_INT_TO_FLOAT); - immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); immUniformThemeColor(TH_GRID); immRecti(pos, 0, 0, TXT_NUMCOL_WIDTH(st), region->winy); immUnbindProgram(); @@ -1726,7 +1726,7 @@ void draw_text_main(SpaceText *st, ARegion *region) if (margin_column_x >= x) { uint pos = GPU_vertformat_attr_add( immVertexFormat(), "pos", GPU_COMP_I32, 2, GPU_FETCH_INT_TO_FLOAT); - immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); float margin_color[4]; UI_GetThemeColor4fv(TH_TEXT, margin_color); margin_color[3] = 0.2f; diff --git a/source/blender/editors/space_topbar/CMakeLists.txt b/source/blender/editors/space_topbar/CMakeLists.txt index 26c6b796df5..f529c855e6d 100644 --- a/source/blender/editors/space_topbar/CMakeLists.txt +++ b/source/blender/editors/space_topbar/CMakeLists.txt @@ -10,7 +10,6 @@ set(INC ../../makesdna ../../makesrna ../../windowmanager - ../../../../intern/glew-mx ../../../../intern/guardedalloc # RNA_prototypes.h ${CMAKE_BINARY_DIR}/source/blender/makesrna diff --git a/source/blender/editors/space_topbar/space_topbar.c b/source/blender/editors/space_topbar/space_topbar.c index bc68de1dfce..e4826ed5964 100644 --- a/source/blender/editors/space_topbar/space_topbar.c +++ b/source/blender/editors/space_topbar/space_topbar.c @@ -116,7 +116,7 @@ static void topbar_header_region_init(wmWindowManager *UNUSED(wm), ARegion *regi static void topbar_main_region_listener(const wmRegionListenerParams *params) { ARegion *region = params->region; - wmNotifier *wmn = params->notifier; + const wmNotifier *wmn = params->notifier; /* context changes */ switch (wmn->category) { @@ -146,7 +146,7 @@ static void topbar_main_region_listener(const wmRegionListenerParams *params) static void topbar_header_listener(const wmRegionListenerParams *params) { ARegion *region = params->region; - wmNotifier *wmn = params->notifier; + const wmNotifier *wmn = params->notifier; /* context changes */ switch (wmn->category) { @@ -288,7 +288,7 @@ void ED_spacetype_topbar(void) ARegionType *art; st->spaceid = SPACE_TOPBAR; - strncpy(st->name, "Top Bar", BKE_ST_MAXNAME); + STRNCPY(st->name, "Top Bar"); st->create = topbar_create; st->free = topbar_free; diff --git a/source/blender/editors/space_userpref/space_userpref.c b/source/blender/editors/space_userpref/space_userpref.c index 1cda9cc0f0c..06a4c1d8702 100644 --- a/source/blender/editors/space_userpref/space_userpref.c +++ b/source/blender/editors/space_userpref/space_userpref.c @@ -189,7 +189,7 @@ void ED_spacetype_userpref(void) ARegionType *art; st->spaceid = SPACE_USERPREF; - strncpy(st->name, "Userpref", BKE_ST_MAXNAME); + STRNCPY(st->name, "Userpref"); st->create = userpref_create; st->free = userpref_free; diff --git a/source/blender/editors/space_view3d/CMakeLists.txt b/source/blender/editors/space_view3d/CMakeLists.txt index a76cd3377bc..d465460682d 100644 --- a/source/blender/editors/space_view3d/CMakeLists.txt +++ b/source/blender/editors/space_view3d/CMakeLists.txt @@ -15,7 +15,6 @@ set(INC ../../makesrna ../../render ../../windowmanager - ../../../../intern/glew-mx ../../../../intern/guardedalloc ../../../../intern/mantaflow/extern @@ -28,7 +27,7 @@ set(INC set(SRC drawobject.c - space_view3d.c + space_view3d.cc view3d_buttons.c view3d_camera_control.c view3d_cursor_snap.c @@ -61,7 +60,7 @@ set(SRC view3d_ops.c view3d_placement.c view3d_project.c - view3d_select.c + view3d_select.cc view3d_snap.c view3d_utils.c view3d_view.c @@ -76,7 +75,7 @@ set(LIB ) if(WITH_PYTHON) - blender_include_dirs(../../python) + list(APPEND INC ../../python) add_definitions(-DWITH_PYTHON) endif() diff --git a/source/blender/editors/space_view3d/drawobject.c b/source/blender/editors/space_view3d/drawobject.c index 8add6886584..36ced74a8b7 100644 --- a/source/blender/editors/space_view3d/drawobject.c +++ b/source/blender/editors/space_view3d/drawobject.c @@ -16,6 +16,7 @@ #include "BKE_customdata.h" #include "BKE_editmesh.h" #include "BKE_global.h" +#include "BKE_mesh.h" #include "BKE_object.h" #include "DEG_depsgraph.h" @@ -67,9 +68,9 @@ void ED_draw_object_facemap(Depsgraph *depsgraph, if (facemap_data) { GPU_blend(GPU_BLEND_ALPHA); - const MVert *mvert = me->mvert; - const MPoly *mpoly = me->mpoly; - const MLoop *mloop = me->mloop; + const MVert *verts = BKE_mesh_verts(me); + const MPoly *polys = BKE_mesh_polys(me); + const MLoop *loops = BKE_mesh_loops(me); int mpoly_len = me->totpoly; int mloop_len = me->totloop; @@ -95,12 +96,12 @@ void ED_draw_object_facemap(Depsgraph *depsgraph, int i; if (me->runtime.looptris.array) { const MLoopTri *mlt = me->runtime.looptris.array; - for (mp = mpoly, i = 0; i < mpoly_len; i++, mp++) { + for (mp = polys, i = 0; i < mpoly_len; i++, mp++) { if (facemap_data[i] == facemap) { for (int j = 2; j < mp->totloop; j++) { - copy_v3_v3(GPU_vertbuf_raw_step(&pos_step), mvert[mloop[mlt->tri[0]].v].co); - copy_v3_v3(GPU_vertbuf_raw_step(&pos_step), mvert[mloop[mlt->tri[1]].v].co); - copy_v3_v3(GPU_vertbuf_raw_step(&pos_step), mvert[mloop[mlt->tri[2]].v].co); + copy_v3_v3(GPU_vertbuf_raw_step(&pos_step), verts[loops[mlt->tri[0]].v].co); + copy_v3_v3(GPU_vertbuf_raw_step(&pos_step), verts[loops[mlt->tri[1]].v].co); + copy_v3_v3(GPU_vertbuf_raw_step(&pos_step), verts[loops[mlt->tri[2]].v].co); vbo_len_used += 3; mlt++; } @@ -112,15 +113,15 @@ void ED_draw_object_facemap(Depsgraph *depsgraph, } else { /* No tessellation data, fan-fill. */ - for (mp = mpoly, i = 0; i < mpoly_len; i++, mp++) { + for (mp = polys, i = 0; i < mpoly_len; i++, mp++) { if (facemap_data[i] == facemap) { - const MLoop *ml_start = &mloop[mp->loopstart]; + const MLoop *ml_start = &loops[mp->loopstart]; const MLoop *ml_a = ml_start + 1; const MLoop *ml_b = ml_start + 2; for (int j = 2; j < mp->totloop; j++) { - copy_v3_v3(GPU_vertbuf_raw_step(&pos_step), mvert[ml_start->v].co); - copy_v3_v3(GPU_vertbuf_raw_step(&pos_step), mvert[ml_a->v].co); - copy_v3_v3(GPU_vertbuf_raw_step(&pos_step), mvert[ml_b->v].co); + copy_v3_v3(GPU_vertbuf_raw_step(&pos_step), verts[ml_start->v].co); + copy_v3_v3(GPU_vertbuf_raw_step(&pos_step), verts[ml_a->v].co); + copy_v3_v3(GPU_vertbuf_raw_step(&pos_step), verts[ml_b->v].co); vbo_len_used += 3; ml_a++; diff --git a/source/blender/editors/space_view3d/space_view3d.c b/source/blender/editors/space_view3d/space_view3d.cc index 1a2eb20d1a9..1b168ca1dda 100644 --- a/source/blender/editors/space_view3d/space_view3d.c +++ b/source/blender/editors/space_view3d/space_view3d.cc @@ -83,12 +83,12 @@ RegionView3D *ED_view3d_context_rv3d(bContext *C) { RegionView3D *rv3d = CTX_wm_region_view3d(C); - if (rv3d == NULL) { + if (rv3d == nullptr) { ScrArea *area = CTX_wm_area(C); if (area && area->spacetype == SPACE_VIEW3D) { ARegion *region = BKE_area_find_region_active_win(area); if (region) { - rv3d = region->regiondata; + rv3d = static_cast<RegionView3D *>(region->regiondata); } } } @@ -99,8 +99,8 @@ bool ED_view3d_context_user_region(bContext *C, View3D **r_v3d, ARegion **r_regi { ScrArea *area = CTX_wm_area(C); - *r_v3d = NULL; - *r_region = NULL; + *r_v3d = nullptr; + *r_region = nullptr; if (area && area->spacetype == SPACE_VIEW3D) { ARegion *region = CTX_wm_region(C); @@ -108,7 +108,8 @@ bool ED_view3d_context_user_region(bContext *C, View3D **r_v3d, ARegion **r_regi if (region) { RegionView3D *rv3d; - if ((region->regiontype == RGN_TYPE_WINDOW) && (rv3d = region->regiondata) && + if ((region->regiontype == RGN_TYPE_WINDOW) && + (rv3d = static_cast<RegionView3D *>(region->regiondata)) && (rv3d->viewlock & RV3D_LOCK_ROTATION) == 0) { *r_v3d = v3d; *r_region = region; @@ -127,9 +128,9 @@ bool ED_view3d_context_user_region(bContext *C, View3D **r_v3d, ARegion **r_regi bool ED_view3d_area_user_region(const ScrArea *area, const View3D *v3d, ARegion **r_region) { - RegionView3D *rv3d = NULL; - ARegion *region_unlock_user = NULL; - ARegion *region_unlock = NULL; + RegionView3D *rv3d = nullptr; + ARegion *region_unlock_user = nullptr; + ARegion *region_unlock = nullptr; const ListBase *region_list = (v3d == area->spacedata.first) ? &area->regionbase : &v3d->regionbase; @@ -138,7 +139,7 @@ bool ED_view3d_area_user_region(const ScrArea *area, const View3D *v3d, ARegion LISTBASE_FOREACH (ARegion *, region, region_list) { /* find the first unlocked rv3d */ if (region->regiondata && region->regiontype == RGN_TYPE_WINDOW) { - rv3d = region->regiondata; + rv3d = static_cast<RegionView3D *>(region->regiondata); if ((rv3d->viewlock & RV3D_LOCK_ROTATION) == 0) { region_unlock = region; if (ELEM(rv3d->persp, RV3D_PERSP, RV3D_CAMOB)) { @@ -199,7 +200,7 @@ void ED_view3d_check_mats_rv3d(struct RegionView3D *rv3d) void ED_view3d_stop_render_preview(wmWindowManager *wm, ARegion *region) { - RegionView3D *rv3d = region->regiondata; + RegionView3D *rv3d = static_cast<RegionView3D *>(region->regiondata); if (rv3d->render_engine) { #ifdef WITH_PYTHON @@ -213,7 +214,7 @@ void ED_view3d_stop_render_preview(wmWindowManager *wm, ARegion *region) #endif RE_engine_free(rv3d->render_engine); - rv3d->render_engine = NULL; + rv3d->render_engine = nullptr; } /* A bit overkill but this make sure the viewport is reset completely. (fclem) */ @@ -222,12 +223,12 @@ void ED_view3d_stop_render_preview(wmWindowManager *wm, ARegion *region) void ED_view3d_shade_update(Main *bmain, View3D *v3d, ScrArea *area) { - wmWindowManager *wm = bmain->wm.first; + wmWindowManager *wm = static_cast<wmWindowManager *>(bmain->wm.first); if (v3d->shading.type != OB_RENDER) { ARegion *region; - for (region = area->regionbase.first; region; region = region->next) { + for (region = static_cast<ARegion *>(area->regionbase.first); region; region = region->next) { if ((region->regiontype == RGN_TYPE_WINDOW) && region->regiondata) { ED_view3d_stop_render_preview(wm, region); } @@ -250,14 +251,14 @@ static SpaceLink *view3d_create(const ScrArea *UNUSED(area), const Scene *scene) } /* header */ - region = MEM_callocN(sizeof(ARegion), "header for view3d"); + region = MEM_cnew<ARegion>("header for view3d"); BLI_addtail(&v3d->regionbase, region); region->regiontype = RGN_TYPE_HEADER; region->alignment = (U.uiflag & USER_HEADER_BOTTOM) ? RGN_ALIGN_BOTTOM : RGN_ALIGN_TOP; /* tool header */ - region = MEM_callocN(sizeof(ARegion), "tool header for view3d"); + region = MEM_cnew<ARegion>("tool header for view3d"); BLI_addtail(&v3d->regionbase, region); region->regiontype = RGN_TYPE_TOOL_HEADER; @@ -265,7 +266,7 @@ static SpaceLink *view3d_create(const ScrArea *UNUSED(area), const Scene *scene) region->flag = RGN_FLAG_HIDDEN | RGN_FLAG_HIDDEN_BY_USER; /* tool shelf */ - region = MEM_callocN(sizeof(ARegion), "toolshelf for view3d"); + region = MEM_cnew<ARegion>("toolshelf for view3d"); BLI_addtail(&v3d->regionbase, region); region->regiontype = RGN_TYPE_TOOLS; @@ -273,7 +274,7 @@ static SpaceLink *view3d_create(const ScrArea *UNUSED(area), const Scene *scene) region->flag = RGN_FLAG_HIDDEN; /* buttons/list view */ - region = MEM_callocN(sizeof(ARegion), "buttons for view3d"); + region = MEM_cnew<ARegion>("buttons for view3d"); BLI_addtail(&v3d->regionbase, region); region->regiontype = RGN_TYPE_UI; @@ -281,13 +282,13 @@ static SpaceLink *view3d_create(const ScrArea *UNUSED(area), const Scene *scene) region->flag = RGN_FLAG_HIDDEN; /* main region */ - region = MEM_callocN(sizeof(ARegion), "main region for view3d"); + region = MEM_cnew<ARegion>("main region for view3d"); BLI_addtail(&v3d->regionbase, region); region->regiontype = RGN_TYPE_WINDOW; - region->regiondata = MEM_callocN(sizeof(RegionView3D), "region view3d"); - rv3d = region->regiondata; + region->regiondata = MEM_cnew<RegionView3D>("region view3d"); + rv3d = static_cast<RegionView3D *>(region->regiondata); rv3d->viewquat[0] = 1.0f; rv3d->persp = RV3D_PERSP; rv3d->view = RV3D_VIEW_USER; @@ -313,7 +314,7 @@ static void view3d_free(SpaceLink *sl) if (vd->shading.prop) { IDP_FreeProperty(vd->shading.prop); - vd->shading.prop = NULL; + vd->shading.prop = nullptr; } } @@ -325,21 +326,21 @@ static void view3d_init(wmWindowManager *UNUSED(wm), ScrArea *UNUSED(area)) static void view3d_exit(wmWindowManager *UNUSED(wm), ScrArea *area) { BLI_assert(area->spacetype == SPACE_VIEW3D); - View3D *v3d = area->spacedata.first; + View3D *v3d = static_cast<View3D *>(area->spacedata.first); MEM_SAFE_FREE(v3d->runtime.local_stats); } static SpaceLink *view3d_duplicate(SpaceLink *sl) { View3D *v3do = (View3D *)sl; - View3D *v3dn = MEM_dupallocN(sl); + View3D *v3dn = static_cast<View3D *>(MEM_dupallocN(sl)); memset(&v3dn->runtime, 0x0, sizeof(v3dn->runtime)); /* clear or remove stuff from old */ if (v3dn->localvd) { - v3dn->localvd = NULL; + v3dn->localvd = nullptr; } v3dn->local_collections_uuid = 0; @@ -459,10 +460,10 @@ static ID_Type view3d_drop_id_in_main_region_poll_get_id_type(bContext *C, const ScrArea *area = CTX_wm_area(C); if (ED_region_overlap_isect_any_xy(area, event->xy)) { - return 0; + return ID_Type(0); } if (!view3d_drop_in_main_region_poll(C, event)) { - return 0; + return ID_Type(0); } ID *local_id = WM_drag_get_local_ID(drag, 0); @@ -472,10 +473,10 @@ static ID_Type view3d_drop_id_in_main_region_poll_get_id_type(bContext *C, wmDragAsset *asset_drag = WM_drag_get_asset_data(drag, 0); if (asset_drag) { - return asset_drag->id_type; + return ID_Type(asset_drag->id_type); } - return 0; + return ID_Type(0); } static bool view3d_drop_id_in_main_region_poll(bContext *C, @@ -492,7 +493,7 @@ static bool view3d_drop_id_in_main_region_poll(bContext *C, static void view3d_ob_drop_draw_activate(struct wmDropBox *drop, wmDrag *drag) { - V3DSnapCursorState *state = drop->draw_data; + V3DSnapCursorState *state = static_cast<V3DSnapCursorState *>(drop->draw_data); if (state) { return; } @@ -503,7 +504,8 @@ static void view3d_ob_drop_draw_activate(struct wmDropBox *drop, wmDrag *drag) return; } - state = drop->draw_data = ED_view3d_cursor_snap_active(); + state = static_cast<V3DSnapCursorState *>(ED_view3d_cursor_snap_active()); + drop->draw_data = state; state->draw_plane = true; float dimensions[3] = {0.0f}; @@ -515,7 +517,7 @@ static void view3d_ob_drop_draw_activate(struct wmDropBox *drop, wmDrag *drag) struct AssetMetaData *meta_data = WM_drag_get_asset_meta_data(drag, ID_OB); IDProperty *dimensions_prop = BKE_asset_metadata_idprop_find(meta_data, "dimensions"); if (dimensions_prop) { - copy_v3_v3(dimensions, IDP_Array(dimensions_prop)); + copy_v3_v3(dimensions, static_cast<float *>(IDP_Array(dimensions_prop))); } } @@ -528,10 +530,10 @@ static void view3d_ob_drop_draw_activate(struct wmDropBox *drop, wmDrag *drag) static void view3d_ob_drop_draw_deactivate(struct wmDropBox *drop, wmDrag *UNUSED(drag)) { - V3DSnapCursorState *state = drop->draw_data; + V3DSnapCursorState *state = static_cast<V3DSnapCursorState *>(drop->draw_data); if (state) { ED_view3d_cursor_snap_deactive(state); - drop->draw_data = NULL; + drop->draw_data = nullptr; } } @@ -669,7 +671,7 @@ static bool view3d_ima_empty_drop_poll(bContext *C, wmDrag *drag, const wmEvent Object *ob = ED_view3d_give_object_under_cursor(C, event->mval); - if (ob == NULL) { + if (ob == nullptr) { return true; } @@ -742,7 +744,7 @@ static void view3d_ob_drop_copy_external_asset(bContext *UNUSED(C), wmDrag *drag Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); - BKE_view_layer_base_deselect_all(view_layer); + BKE_view_layer_base_deselect_all(scene, view_layer); ID *id = WM_drag_asset_id_import(asset_drag, FILE_AUTOSELECT); @@ -752,15 +754,16 @@ static void view3d_ob_drop_copy_external_asset(bContext *UNUSED(C), wmDrag *drag RNA_int_set(drop->ptr, "session_uuid", id->session_uuid); + BKE_view_layer_synced_ensure(scene, view_layer); Base *base = BKE_view_layer_base_find(view_layer, (Object *)id); - if (base != NULL) { + if (base != nullptr) { BKE_view_layer_base_select_and_set_active(view_layer, base); WM_main_add_notifier(NC_SCENE | ND_OB_ACTIVE, scene); } DEG_id_tag_update(&scene->id, ID_RECALC_SELECT); ED_outliner_select_sync_from_object_tag(C); - V3DSnapCursorState *snap_state = drop->draw_data; + V3DSnapCursorState *snap_state = static_cast<V3DSnapCursorState *>(drop->draw_data); if (snap_state) { float obmat_final[4][4]; @@ -791,7 +794,7 @@ static void view3d_collection_drop_copy_external_asset(bContext *UNUSED(C), Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); - BKE_view_layer_base_deselect_all(view_layer); + BKE_view_layer_base_deselect_all(scene, view_layer); ID *id = WM_drag_asset_id_import(asset_drag, FILE_AUTOSELECT); Collection *collection = (Collection *)id; @@ -803,8 +806,9 @@ static void view3d_collection_drop_copy_external_asset(bContext *UNUSED(C), RNA_int_set(drop->ptr, "session_uuid", (int)id->session_uuid); /* Make an object active, just use the first one in the collection. */ - CollectionObject *cobject = collection->gobject.first; - Base *base = cobject ? BKE_view_layer_base_find(view_layer, cobject->ob) : NULL; + CollectionObject *cobject = static_cast<CollectionObject *>(collection->gobject.first); + BKE_view_layer_synced_ensure(scene, view_layer); + Base *base = cobject ? BKE_view_layer_base_find(view_layer, cobject->ob) : nullptr; if (base) { BLI_assert((base->flag & BASE_SELECTABLE) && (base->flag & BASE_ENABLED_VIEWPORT)); BKE_view_layer_base_select_and_set_active(view_layer, base); @@ -863,7 +867,7 @@ static void view3d_lightcache_update(bContext *C) RNA_int_set(&op_ptr, "delay", 200); RNA_enum_set_identifier(C, &op_ptr, "subset", "DIRTY"); - WM_operator_name_call_ptr(C, ot, WM_OP_INVOKE_DEFAULT, &op_ptr, NULL); + WM_operator_name_call_ptr(C, ot, WM_OP_INVOKE_DEFAULT, &op_ptr, nullptr); WM_operator_properties_free(&op_ptr); } @@ -879,7 +883,7 @@ static void view3d_dropboxes(void) view3d_ob_drop_poll_local_id, view3d_ob_drop_copy_local_id, WM_drag_free_imported_drag_ID, - NULL); + nullptr); drop->draw_droptip = WM_drag_draw_item_name_fn; drop->draw_activate = view3d_ob_drop_draw_activate; @@ -890,7 +894,7 @@ static void view3d_dropboxes(void) view3d_ob_drop_poll_external_asset, view3d_ob_drop_copy_external_asset, WM_drag_free_imported_drag_ID, - NULL); + nullptr); drop->draw_droptip = WM_drag_draw_item_name_fn; drop->draw_activate = view3d_ob_drop_draw_activate; @@ -901,13 +905,13 @@ static void view3d_dropboxes(void) view3d_collection_drop_poll_external_asset, view3d_collection_drop_copy_external_asset, WM_drag_free_imported_drag_ID, - NULL); + nullptr); WM_dropbox_add(lb, "OBJECT_OT_collection_instance_add", view3d_collection_drop_poll_local_id, view3d_collection_drop_copy_local_id, WM_drag_free_imported_drag_ID, - NULL); + nullptr); WM_dropbox_add(lb, "OBJECT_OT_drop_named_material", @@ -920,19 +924,19 @@ static void view3d_dropboxes(void) view3d_ima_bg_drop_poll, view3d_id_path_drop_copy, WM_drag_free_imported_drag_ID, - NULL); + nullptr); WM_dropbox_add(lb, "OBJECT_OT_drop_named_image", view3d_ima_empty_drop_poll, view3d_id_path_drop_copy, WM_drag_free_imported_drag_ID, - NULL); + nullptr); WM_dropbox_add(lb, "OBJECT_OT_volume_import", view3d_volume_drop_poll, view3d_id_path_drop_copy, WM_drag_free_imported_drag_ID, - NULL); + nullptr); WM_dropbox_add(lb, "OBJECT_OT_data_instance_add", view3d_object_data_drop_poll, @@ -944,13 +948,13 @@ static void view3d_dropboxes(void) view3d_world_drop_poll, view3d_id_drop_copy, WM_drag_free_imported_drag_ID, - NULL); + nullptr); } static void view3d_widgets(void) { - wmGizmoMapType *gzmap_type = WM_gizmomaptype_ensure( - &(const struct wmGizmoMapType_Params){SPACE_VIEW3D, RGN_TYPE_WINDOW}); + wmGizmoMapType_Params params{SPACE_VIEW3D, RGN_TYPE_WINDOW}; + wmGizmoMapType *gzmap_type = WM_gizmomaptype_ensure(¶ms); WM_gizmogrouptype_append_and_link(gzmap_type, VIEW3D_GGT_xform_gizmo_context); WM_gizmogrouptype_append_and_link(gzmap_type, VIEW3D_GGT_light_spot); @@ -986,7 +990,7 @@ static void view3d_widgets(void) /* type callback, not region itself */ static void view3d_main_region_free(ARegion *region) { - RegionView3D *rv3d = region->regiondata; + RegionView3D *rv3d = static_cast<RegionView3D *>(region->regiondata); if (rv3d) { if (rv3d->localvd) { @@ -1005,7 +1009,7 @@ static void view3d_main_region_free(ARegion *region) } MEM_freeN(rv3d); - region->regiondata = NULL; + region->regiondata = nullptr; } } @@ -1013,23 +1017,24 @@ static void view3d_main_region_free(ARegion *region) static void *view3d_main_region_duplicate(void *poin) { if (poin) { - RegionView3D *rv3d = poin, *new; + RegionView3D *rv3d = static_cast<RegionView3D *>(poin); + RegionView3D *new_rv3d; - new = MEM_dupallocN(rv3d); + new_rv3d = static_cast<RegionView3D *>(MEM_dupallocN(rv3d)); if (rv3d->localvd) { - new->localvd = MEM_dupallocN(rv3d->localvd); + new_rv3d->localvd = static_cast<RegionView3D *>(MEM_dupallocN(rv3d->localvd)); } if (rv3d->clipbb) { - new->clipbb = MEM_dupallocN(rv3d->clipbb); + new_rv3d->clipbb = static_cast<BoundBox *>(MEM_dupallocN(rv3d->clipbb)); } - new->render_engine = NULL; - new->sms = NULL; - new->smooth_timer = NULL; + new_rv3d->render_engine = nullptr; + new_rv3d->sms = nullptr; + new_rv3d->smooth_timer = nullptr; - return new; + return new_rv3d; } - return NULL; + return nullptr; } static void view3d_main_region_listener(const wmRegionListenerParams *params) @@ -1037,10 +1042,10 @@ static void view3d_main_region_listener(const wmRegionListenerParams *params) wmWindow *window = params->window; ScrArea *area = params->area; ARegion *region = params->region; - wmNotifier *wmn = params->notifier; + const wmNotifier *wmn = params->notifier; const Scene *scene = params->scene; - View3D *v3d = area->spacedata.first; - RegionView3D *rv3d = region->regiondata; + View3D *v3d = static_cast<View3D *>(area->spacedata.first); + RegionView3D *rv3d = static_cast<RegionView3D *>(region->regiondata); wmGizmoMap *gzmap = region->gizmo_map; /* context changes */ @@ -1085,7 +1090,7 @@ static void view3d_main_region_listener(const wmRegionListenerParams *params) break; case ND_LAYER: if (wmn->reference) { - BKE_screen_view3d_sync(v3d, wmn->reference); + BKE_screen_view3d_sync(v3d, static_cast<Scene *>(wmn->reference)); } ED_region_tag_redraw(region); WM_gizmomap_tag_refresh(gzmap); @@ -1262,7 +1267,8 @@ static void view3d_main_region_listener(const wmRegionListenerParams *params) } else if (wmn->subtype == NS_VIEW3D_SHADING) { #ifdef WITH_XR_OPENXR - ED_view3d_xr_shading_update(G_MAIN->wm.first, v3d, scene); + ED_view3d_xr_shading_update( + static_cast<wmWindowManager *>(G_MAIN->wm.first), v3d, scene); #endif ViewLayer *view_layer = WM_window_get_active_view_layer(window); @@ -1319,7 +1325,7 @@ static void view3d_do_msg_notify_workbench_view_update(struct bContext *C, View3D *v3d = (View3D *)area->spacedata.first; if (v3d->shading.type == OB_SOLID) { RenderEngineType *engine_type = ED_view3d_engine_type(scene, v3d->shading.type); - DRWUpdateContext drw_context = {NULL}; + DRWUpdateContext drw_context = {nullptr}; drw_context.bmain = CTX_data_main(C); drw_context.depsgraph = CTX_data_depsgraph_pointer(C); drw_context.scene = scene; @@ -1366,17 +1372,15 @@ static void view3d_main_region_message_subscribe(const wmRegionMessageSubscribeP &RNA_World, }; - wmMsgSubscribeValue msg_sub_value_region_tag_redraw = { - .owner = region, - .user_data = region, - .notify = ED_region_do_msg_notify_tag_redraw, - }; + wmMsgSubscribeValue msg_sub_value_region_tag_redraw{}; + msg_sub_value_region_tag_redraw.owner = region; + msg_sub_value_region_tag_redraw.user_data = region; + msg_sub_value_region_tag_redraw.notify = ED_region_do_msg_notify_tag_redraw; - wmMsgSubscribeValue msg_sub_value_workbench_view_update = { - .owner = region, - .user_data = area, - .notify = view3d_do_msg_notify_workbench_view_update, - }; + wmMsgSubscribeValue msg_sub_value_workbench_view_update{}; + msg_sub_value_workbench_view_update.owner = region; + msg_sub_value_workbench_view_update.user_data = area; + msg_sub_value_workbench_view_update.notify = view3d_do_msg_notify_workbench_view_update; for (int i = 0; i < ARRAY_SIZE(type_array); i++) { msg_key_params.ptr.type = type_array[i]; @@ -1384,7 +1388,7 @@ static void view3d_main_region_message_subscribe(const wmRegionMessageSubscribeP } /* Subscribe to a handful of other properties. */ - RegionView3D *rv3d = region->regiondata; + RegionView3D *rv3d = static_cast<RegionView3D *>(region->regiondata); WM_msg_subscribe_rna_anon_prop(mbus, RenderSettings, engine, &msg_sub_value_region_tag_redraw); WM_msg_subscribe_rna_anon_prop( @@ -1404,9 +1408,11 @@ static void view3d_main_region_message_subscribe(const wmRegionMessageSubscribeP WM_msg_subscribe_rna_anon_type(mbus, SceneDisplay, &msg_sub_value_region_tag_redraw); WM_msg_subscribe_rna_anon_type(mbus, ObjectDisplay, &msg_sub_value_region_tag_redraw); + const Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); - Object *obact = OBACT(view_layer); - if (obact != NULL) { + BKE_view_layer_synced_ensure(scene, view_layer); + Object *obact = BKE_view_layer_active_object_get(view_layer); + if (obact != nullptr) { switch (obact->mode) { case OB_MODE_PARTICLE_EDIT: WM_msg_subscribe_rna_anon_type(mbus, ParticleEdit, &msg_sub_value_region_tag_redraw); @@ -1422,11 +1428,10 @@ static void view3d_main_region_message_subscribe(const wmRegionMessageSubscribeP } { - wmMsgSubscribeValue msg_sub_value_region_tag_refresh = { - .owner = region, - .user_data = area, - .notify = WM_toolsystem_do_msg_notify_tag_refresh, - }; + wmMsgSubscribeValue msg_sub_value_region_tag_refresh{}; + msg_sub_value_region_tag_refresh.owner = region; + msg_sub_value_region_tag_refresh.user_data = area; + msg_sub_value_region_tag_refresh.notify = WM_toolsystem_do_msg_notify_tag_refresh; WM_msg_subscribe_rna_anon_prop(mbus, Object, mode, &msg_sub_value_region_tag_refresh); WM_msg_subscribe_rna_anon_prop(mbus, LayerObjects, active, &msg_sub_value_region_tag_refresh); } @@ -1439,8 +1444,10 @@ static void view3d_main_region_cursor(wmWindow *win, ScrArea *area, ARegion *reg return; } + Scene *scene = WM_window_get_active_scene(win); ViewLayer *view_layer = WM_window_get_active_view_layer(win); - Object *obedit = OBEDIT_FROM_VIEW_LAYER(view_layer); + BKE_view_layer_synced_ensure(scene, view_layer); + Object *obedit = BKE_view_layer_edit_object_get(view_layer); if (obedit) { WM_cursor_set(win, WM_CURSOR_EDIT); } @@ -1467,7 +1474,7 @@ static void view3d_header_region_draw(const bContext *C, ARegion *region) static void view3d_header_region_listener(const wmRegionListenerParams *params) { ARegion *region = params->region; - wmNotifier *wmn = params->notifier; + const wmNotifier *wmn = params->notifier; /* context changes */ switch (wmn->category) { @@ -1504,7 +1511,7 @@ static void view3d_header_region_listener(const wmRegionListenerParams *params) break; } - /* From topbar, which ones are needed? split per header? */ + /* From top-bar, which ones are needed? split per header? */ /* Disable for now, re-enable if needed, or remove - campbell. */ #if 0 /* context changes */ @@ -1545,11 +1552,10 @@ static void view3d_header_region_message_subscribe(const wmRegionMessageSubscrib &RNA_View3DShading, }; - wmMsgSubscribeValue msg_sub_value_region_tag_redraw = { - .owner = region, - .user_data = region, - .notify = ED_region_do_msg_notify_tag_redraw, - }; + wmMsgSubscribeValue msg_sub_value_region_tag_redraw{}; + msg_sub_value_region_tag_redraw.owner = region; + msg_sub_value_region_tag_redraw.user_data = region; + msg_sub_value_region_tag_redraw.notify = ED_region_do_msg_notify_tag_redraw; for (int i = 0; i < ARRAY_SIZE(type_array); i++) { msg_key_params.ptr.type = type_array[i]; @@ -1574,7 +1580,7 @@ void ED_view3d_buttons_region_layout_ex(const bContext *C, { const enum eContextObjectMode mode = CTX_data_mode_enum(C); - const char *contexts_base[4] = {NULL}; + const char *contexts_base[4] = {nullptr}; contexts_base[0] = CTX_data_mode_string(C); const char **contexts = &contexts_base[1]; @@ -1667,7 +1673,7 @@ void ED_view3d_buttons_region_layout_ex(const bContext *C, ListBase *paneltypes = ®ion->type->paneltypes; /* Allow drawing 3D view toolbar from non 3D view space type. */ - if (category_override != NULL) { + if (category_override != nullptr) { SpaceType *st = BKE_spacetype_from_id(SPACE_VIEW3D); ARegionType *art = BKE_regiontype_from_id(st, RGN_TYPE_UI); paneltypes = &art->paneltypes; @@ -1678,13 +1684,13 @@ void ED_view3d_buttons_region_layout_ex(const bContext *C, static void view3d_buttons_region_layout(const bContext *C, ARegion *region) { - ED_view3d_buttons_region_layout_ex(C, region, NULL); + ED_view3d_buttons_region_layout_ex(C, region, nullptr); } static void view3d_buttons_region_listener(const wmRegionListenerParams *params) { ARegion *region = params->region; - wmNotifier *wmn = params->notifier; + const wmNotifier *wmn = params->notifier; /* context changes */ switch (wmn->category) { @@ -1800,15 +1806,16 @@ static void view3d_tools_region_init(wmWindowManager *wm, ARegion *region) static void view3d_tools_region_draw(const bContext *C, ARegion *region) { - ED_region_panels_ex(C, region, (const char *[]){CTX_data_mode_string(C), NULL}); + const char *contexts[] = {CTX_data_mode_string(C), nullptr}; + ED_region_panels_ex(C, region, contexts); } /* area (not region) level listener */ static void space_view3d_listener(const wmSpaceTypeListenerParams *params) { ScrArea *area = params->area; - wmNotifier *wmn = params->notifier; - View3D *v3d = area->spacedata.first; + const wmNotifier *wmn = params->notifier; + View3D *v3d = static_cast<View3D *>(area->spacedata.first); /* context changes */ switch (wmn->category) { @@ -1862,7 +1869,7 @@ static void space_view3d_refresh(const bContext *C, ScrArea *area) const char *view3d_context_dir[] = { "active_object", "selected_ids", - NULL, + nullptr, }; static int view3d_context(const bContext *C, const char *member, bContextDataResult *result) @@ -1876,7 +1883,7 @@ static int view3d_context(const bContext *C, const char *member, bContextDataRes } if (CTX_data_equals(member, "active_object")) { /* In most cases the active object is the `view_layer->basact->object`. - * For the 3D view however it can be NULL when hidden. + * For the 3D view however it can be nullptr when hidden. * * This is ignored in the case the object is in any mode (besides object-mode), * since the object's mode impacts the current tool, cursor, gizmos etc. @@ -1888,11 +1895,14 @@ static int view3d_context(const bContext *C, const char *member, bContextDataRes * without showing the object. * * See T85532 for alternatives that were considered. */ + const Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); - if (view_layer->basact) { - Object *ob = view_layer->basact->object; + BKE_view_layer_synced_ensure(scene, view_layer); + Base *base = BKE_view_layer_active_base_get(view_layer); + if (base) { + Object *ob = base->object; /* if hidden but in edit mode, we still display, can happen with animation */ - if ((view_layer->basact->flag & BASE_VISIBLE_DEPSGRAPH) != 0 || + if ((base->flag & BASE_ENABLED_AND_MAYBE_VISIBLE_IN_VIEWPORT) != 0 || (ob->mode != OB_MODE_OBJECT)) { CTX_data_id_pointer_set(result, &ob->id); } @@ -1937,10 +1947,10 @@ static void view3d_id_remap_v3d(ScrArea *area, /* 3D view might be inactive, in that case needs to use slink->regionbase */ ListBase *regionbase = (slink == area->spacedata.first) ? &area->regionbase : &slink->regionbase; - for (region = regionbase->first; region; region = region->next) { + for (region = static_cast<ARegion *>(regionbase->first); region; region = region->next) { if (region->regiontype == RGN_TYPE_WINDOW) { RegionView3D *rv3d = is_local ? ((RegionView3D *)region->regiondata)->localvd : - region->regiondata; + static_cast<RegionView3D *>(region->regiondata); if (rv3d && (rv3d->persp == RV3D_CAMOB)) { rv3d->persp = RV3D_PERSP; } @@ -1960,7 +1970,7 @@ static void view3d_id_remap(ScrArea *area, SpaceLink *slink, const struct IDRema View3D *view3d = (View3D *)slink; view3d_id_remap_v3d(area, slink, view3d, mappings, false); view3d_id_remap_v3d_ob_centers(view3d, mappings); - if (view3d->localvd != NULL) { + if (view3d->localvd != nullptr) { /* Object centers in local-view aren't used, see: T52663 */ view3d_id_remap_v3d(area, slink, view3d->localvd, mappings, true); } @@ -1968,11 +1978,11 @@ static void view3d_id_remap(ScrArea *area, SpaceLink *slink, const struct IDRema void ED_spacetype_view3d(void) { - SpaceType *st = MEM_callocN(sizeof(SpaceType), "spacetype view3d"); + SpaceType *st = MEM_cnew<SpaceType>("spacetype view3d"); ARegionType *art; st->spaceid = SPACE_VIEW3D; - strncpy(st->name, "View3D", BKE_ST_MAXNAME); + STRNCPY(st->name, "View3D"); st->create = view3d_create; st->free = view3d_free; @@ -1989,7 +1999,7 @@ void ED_spacetype_view3d(void) st->id_remap = view3d_id_remap; /* regions: main window */ - art = MEM_callocN(sizeof(ARegionType), "spacetype view3d main region"); + art = MEM_cnew<ARegionType>("spacetype view3d main region"); art->regionid = RGN_TYPE_WINDOW; art->keymapflag = ED_KEYMAP_GIZMO | ED_KEYMAP_TOOL | ED_KEYMAP_GPENCIL; art->draw = view3d_main_region_draw; @@ -2004,7 +2014,7 @@ void ED_spacetype_view3d(void) BLI_addhead(&st->regiontypes, art); /* regions: listview/buttons */ - art = MEM_callocN(sizeof(ARegionType), "spacetype view3d buttons region"); + art = MEM_cnew<ARegionType>("spacetype view3d buttons region"); art->regionid = RGN_TYPE_UI; art->prefsizex = UI_SIDEBAR_PANEL_WIDTH; art->keymapflag = ED_KEYMAP_UI | ED_KEYMAP_FRAMES; @@ -2018,7 +2028,7 @@ void ED_spacetype_view3d(void) view3d_buttons_register(art); /* regions: tool(bar) */ - art = MEM_callocN(sizeof(ARegionType), "spacetype view3d tools region"); + art = MEM_cnew<ARegionType>("spacetype view3d tools region"); art->regionid = RGN_TYPE_TOOLS; art->prefsizex = 58; /* XXX */ art->prefsizey = 50; /* XXX */ @@ -2031,7 +2041,7 @@ void ED_spacetype_view3d(void) BLI_addhead(&st->regiontypes, art); /* regions: tool header */ - art = MEM_callocN(sizeof(ARegionType), "spacetype view3d tool header region"); + art = MEM_cnew<ARegionType>("spacetype view3d tool header region"); art->regionid = RGN_TYPE_TOOL_HEADER; art->prefsizey = HEADERY; art->keymapflag = ED_KEYMAP_UI | ED_KEYMAP_VIEW2D | ED_KEYMAP_FRAMES | ED_KEYMAP_HEADER; @@ -2042,7 +2052,7 @@ void ED_spacetype_view3d(void) BLI_addhead(&st->regiontypes, art); /* regions: header */ - art = MEM_callocN(sizeof(ARegionType), "spacetype view3d header region"); + art = MEM_cnew<ARegionType>("spacetype view3d header region"); art->regionid = RGN_TYPE_HEADER; art->prefsizey = HEADERY; art->keymapflag = ED_KEYMAP_UI | ED_KEYMAP_VIEW2D | ED_KEYMAP_FRAMES | ED_KEYMAP_HEADER; @@ -2057,7 +2067,7 @@ void ED_spacetype_view3d(void) BLI_addhead(&st->regiontypes, art); /* regions: xr */ - art = MEM_callocN(sizeof(ARegionType), "spacetype view3d xr region"); + art = MEM_cnew<ARegionType>("spacetype view3d xr region"); art->regionid = RGN_TYPE_XR; BLI_addhead(&st->regiontypes, art); diff --git a/source/blender/editors/space_view3d/view3d_buttons.c b/source/blender/editors/space_view3d/view3d_buttons.c index 6786bf8404e..b783b67357c 100644 --- a/source/blender/editors/space_view3d/view3d_buttons.c +++ b/source/blender/editors/space_view3d/view3d_buttons.c @@ -36,6 +36,7 @@ #include "BKE_customdata.h" #include "BKE_deform.h" #include "BKE_editmesh.h" +#include "BKE_layer.h" #include "BKE_object.h" #include "BKE_object_deform.h" #include "BKE_report.h" @@ -994,7 +995,9 @@ static void v3d_editvertex_buts(uiLayout *layout, View3D *v3d, Object *ob, float if (apply_vcos || median->bv_weight || median->v_crease || median->skin[0] || median->skin[1]) { if (median->bv_weight) { - BM_mesh_cd_flag_ensure(bm, me, ME_CDFLAG_VERT_BWEIGHT); + if (!CustomData_has_layer(&bm->vdata, CD_BWEIGHT)) { + BM_data_layer_add(bm, &bm->vdata, CD_BWEIGHT); + } cd_vert_bweight_offset = CustomData_get_offset(&bm->vdata, CD_BWEIGHT); BLI_assert(cd_vert_bweight_offset != -1); @@ -1002,7 +1005,9 @@ static void v3d_editvertex_buts(uiLayout *layout, View3D *v3d, Object *ob, float } if (median->v_crease) { - BM_mesh_cd_flag_ensure(bm, me, ME_CDFLAG_VERT_CREASE); + if (!CustomData_has_layer(&bm->vdata, CD_CREASE)) { + BM_data_layer_add(bm, &bm->vdata, CD_CREASE); + } cd_vert_crease_offset = CustomData_get_offset(&bm->vdata, CD_CREASE); BLI_assert(cd_vert_crease_offset != -1); @@ -1060,7 +1065,9 @@ static void v3d_editvertex_buts(uiLayout *layout, View3D *v3d, Object *ob, float if (median->be_weight || median->e_crease) { if (median->be_weight) { - BM_mesh_cd_flag_ensure(bm, me, ME_CDFLAG_EDGE_BWEIGHT); + if (!CustomData_has_layer(&bm->edata, CD_BWEIGHT)) { + BM_data_layer_add(bm, &bm->edata, CD_BWEIGHT); + } cd_edge_bweight_offset = CustomData_get_offset(&bm->edata, CD_BWEIGHT); BLI_assert(cd_edge_bweight_offset != -1); @@ -1068,7 +1075,9 @@ static void v3d_editvertex_buts(uiLayout *layout, View3D *v3d, Object *ob, float } if (median->e_crease) { - BM_mesh_cd_flag_ensure(bm, me, ME_CDFLAG_EDGE_CREASE); + if (!CustomData_has_layer(&bm->edata, CD_CREASE)) { + BM_data_layer_add(bm, &bm->edata, CD_CREASE); + } cd_edge_crease_offset = CustomData_get_offset(&bm->edata, CD_CREASE); BLI_assert(cd_edge_crease_offset != -1); @@ -1273,8 +1282,10 @@ static void do_view3d_vgroup_buttons(bContext *C, void *UNUSED(arg), int event) return; } + const Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); - Object *ob = view_layer->basact->object; + BKE_view_layer_synced_ensure(scene, view_layer); + Object *ob = BKE_view_layer_active_object_get(view_layer); ED_vgroup_vert_active_mirror(ob, event - B_VGRP_PNL_EDIT_SINGLE); DEG_id_tag_update(ob->data, ID_RECALC_GEOMETRY); WM_event_add_notifier(C, NC_GEOM | ND_DATA, ob->data); @@ -1282,8 +1293,10 @@ static void do_view3d_vgroup_buttons(bContext *C, void *UNUSED(arg), int event) static bool view3d_panel_vgroup_poll(const bContext *C, PanelType *UNUSED(pt)) { + const Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); - Object *ob = OBACT(view_layer); + BKE_view_layer_synced_ensure(scene, view_layer); + Object *ob = BKE_view_layer_active_object_get(view_layer); if (ob && (BKE_object_is_in_editmode_vgroup(ob) || BKE_object_is_in_wpaint_select_vert(ob))) { MDeformVert *dvert_act = ED_mesh_active_dvert_get_only(ob); if (dvert_act) { @@ -1299,7 +1312,8 @@ static void view3d_panel_vgroup(const bContext *C, Panel *panel) uiBlock *block = uiLayoutAbsoluteBlock(panel->layout); Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); - Object *ob = view_layer->basact->object; + BKE_view_layer_synced_ensure(scene, view_layer); + Object *ob = BKE_view_layer_active_object_get(view_layer); MDeformVert *dv; @@ -1681,9 +1695,11 @@ static void v3d_editmetaball_buts(uiLayout *layout, Object *ob) static void do_view3d_region_buttons(bContext *C, void *UNUSED(index), int event) { + Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); View3D *v3d = CTX_wm_view3d(C); - Object *ob = OBACT(view_layer); + BKE_view_layer_synced_ensure(scene, view_layer); + Object *ob = BKE_view_layer_active_object_get(view_layer); switch (event) { @@ -1710,15 +1726,19 @@ static void do_view3d_region_buttons(bContext *C, void *UNUSED(index), int event static bool view3d_panel_transform_poll(const bContext *C, PanelType *UNUSED(pt)) { + const Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); - return (view_layer->basact != NULL); + BKE_view_layer_synced_ensure(scene, view_layer); + return (BKE_view_layer_active_base_get(view_layer) != NULL); } static void view3d_panel_transform(const bContext *C, Panel *panel) { uiBlock *block; + const Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); - Object *ob = view_layer->basact->object; + BKE_view_layer_synced_ensure(scene, view_layer); + Object *ob = BKE_view_layer_active_object_get(view_layer); Object *obedit = OBEDIT_FROM_OBACT(ob); uiLayout *col; diff --git a/source/blender/editors/space_view3d/view3d_cursor_snap.c b/source/blender/editors/space_view3d/view3d_cursor_snap.c index fb44797eded..72e1f6f46c7 100644 --- a/source/blender/editors/space_view3d/view3d_cursor_snap.c +++ b/source/blender/editors/space_view3d/view3d_cursor_snap.c @@ -16,6 +16,7 @@ #include "BKE_context.h" #include "BKE_global.h" +#include "BKE_layer.h" #include "BKE_main.h" #include "BKE_object.h" #include "BKE_scene.h" @@ -691,7 +692,8 @@ static void v3d_cursor_snap_update(V3DSnapCursorState *state, } else { ViewLayer *view_layer = CTX_data_view_layer(C); - Object *ob = OBACT(view_layer); + BKE_view_layer_synced_ensure(CTX_data_scene(C), view_layer); + Object *ob = BKE_view_layer_active_object_get(view_layer); const int orient_index = BKE_scene_orientation_get_index(scene, SCE_ORIENT_DEFAULT); const int pivot_point = scene->toolsettings->transform_pivot_point; ED_transform_calc_orientation_from_type_ex( diff --git a/source/blender/editors/space_view3d/view3d_draw.c b/source/blender/editors/space_view3d/view3d_draw.c index df5ff163cf2..9a2885c44b1 100644 --- a/source/blender/editors/space_view3d/view3d_draw.c +++ b/source/blender/editors/space_view3d/view3d_draw.c @@ -567,7 +567,7 @@ static void drawviewborder(Scene *scene, Depsgraph *depsgraph, ARegion *region, /* First, solid lines. */ { - immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); /* passepartout, specified in camera edit buttons */ if (ca && (ca->flag & CAM_SHOWPASSEPARTOUT) && ca->passepartalpha > 0.000001f) { @@ -618,7 +618,7 @@ static void drawviewborder(Scene *scene, Depsgraph *depsgraph, ARegion *region, } /* And now, the dashed lines! */ - immBindBuiltinProgram(GPU_SHADER_2D_LINE_DASHED_UNIFORM_COLOR); + immBindBuiltinProgram(GPU_SHADER_3D_LINE_DASHED_UNIFORM_COLOR); { float viewport_size[4]; @@ -800,7 +800,7 @@ static void drawrenderborder(ARegion *region, View3D *v3d) GPU_line_width(1.0f); - immBindBuiltinProgram(GPU_SHADER_2D_LINE_DASHED_UNIFORM_COLOR); + immBindBuiltinProgram(GPU_SHADER_3D_LINE_DASHED_UNIFORM_COLOR); float viewport_size[4]; GPU_viewport_size_get_f(viewport_size); @@ -982,7 +982,7 @@ static void draw_view_axis(RegionView3D *rv3d, const rcti *rect) uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); uint col = GPU_vertformat_attr_add(format, "color", GPU_COMP_U8, 4, GPU_FETCH_INT_TO_FLOAT_UNIT); - immBindBuiltinProgram(GPU_SHADER_2D_FLAT_COLOR); + immBindBuiltinProgram(GPU_SHADER_3D_FLAT_COLOR); immBegin(GPU_PRIM_LINES, 6); for (int axis_i = 0; axis_i < 3; axis_i++) { @@ -1306,7 +1306,8 @@ static void draw_selected_name( s += sprintf(s, "(%d)", cfra); if ((ob == NULL) || (ob->mode == OB_MODE_OBJECT)) { - LayerCollection *layer_collection = view_layer->active_collection; + BKE_view_layer_synced_ensure(scene, view_layer); + LayerCollection *layer_collection = BKE_view_layer_active_collection_get(view_layer); s += sprintf(s, " %s%s", BKE_collection_ui_name_get(layer_collection->collection), @@ -1352,7 +1353,7 @@ static void draw_selected_name( } } else if (ELEM(ob->type, OB_MESH, OB_LATTICE, OB_CURVES_LEGACY)) { - /* try to display active bone and active shapekey too (if they exist) */ + /* Try to display active bone and active shape-key too (if they exist). */ if (ob->type == OB_MESH && ob->mode & OB_MODE_WEIGHT_PAINT) { Object *armobj = BKE_object_pose_armature_get(ob); @@ -1497,7 +1498,8 @@ void view3d_draw_region_info(const bContext *C, ARegion *region) } if (U.uiflag & USER_DRAWVIEWINFO) { - Object *ob = OBACT(view_layer); + BKE_view_layer_synced_ensure(scene, view_layer); + Object *ob = BKE_view_layer_active_object_get(view_layer); draw_selected_name(scene, view_layer, ob, xoffset, &yoffset); } @@ -2121,6 +2123,7 @@ bool ED_view3d_clipping_test(const RegionView3D *rv3d, const float co[3], const * \note Only use in object mode. */ static void validate_object_select_id(struct Depsgraph *depsgraph, + const Scene *scene, ViewLayer *view_layer, ARegion *region, View3D *v3d, @@ -2152,7 +2155,8 @@ static void validate_object_select_id(struct Depsgraph *depsgraph, return; } - if (obact_eval && ((obact_eval->base_flag & BASE_VISIBLE_DEPSGRAPH) != 0)) { + if (obact_eval && ((obact_eval->base_flag & BASE_ENABLED_AND_MAYBE_VISIBLE_IN_VIEWPORT) != 0)) { + BKE_view_layer_synced_ensure(scene, view_layer); Base *base = BKE_view_layer_base_find(view_layer, obact); DRW_select_buffer_context_create(&base, 1, -1); } @@ -2188,7 +2192,8 @@ static void view3d_opengl_read_Z_pixels(GPUViewport *viewport, rcti *rect, void void ED_view3d_select_id_validate(ViewContext *vc) { - validate_object_select_id(vc->depsgraph, vc->view_layer, vc->region, vc->v3d, vc->obact); + validate_object_select_id( + vc->depsgraph, vc->scene, vc->view_layer, vc->region, vc->v3d, vc->obact); } int ED_view3d_backbuf_sample_size_clamp(ARegion *region, const float dist) @@ -2400,7 +2405,6 @@ void ED_view3d_datamask(const bContext *C, } if ((CTX_data_mode_enum(C) == CTX_MODE_SCULPT)) { r_cddata_masks->vmask |= CD_MASK_PAINT_MASK; - r_cddata_masks->pmask |= CD_MASK_SCULPT_FACE_SETS; } } diff --git a/source/blender/editors/space_view3d/view3d_edit.c b/source/blender/editors/space_view3d/view3d_edit.c index d6ddd6d044e..6001f701c00 100644 --- a/source/blender/editors/space_view3d/view3d_edit.c +++ b/source/blender/editors/space_view3d/view3d_edit.c @@ -697,7 +697,7 @@ static int drop_world_exec(bContext *C, wmOperator *op) id_us_plus(&world->id); scene->world = world; - DEG_id_tag_update(&scene->id, 0); + DEG_id_tag_update(&scene->id, ID_RECALC_COPY_ON_WRITE); DEG_relations_tag_update(bmain); WM_event_add_notifier(C, NC_SCENE | ND_WORLD, scene); diff --git a/source/blender/editors/space_view3d/view3d_gizmo_armature.c b/source/blender/editors/space_view3d/view3d_gizmo_armature.c index 62799dd7a5c..4f73e2fada2 100644 --- a/source/blender/editors/space_view3d/view3d_gizmo_armature.c +++ b/source/blender/editors/space_view3d/view3d_gizmo_armature.c @@ -113,8 +113,10 @@ static bool WIDGETGROUP_armature_spline_poll(const bContext *C, wmGizmoGroupType return false; } + const Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); - Base *base = BASACT(view_layer); + BKE_view_layer_synced_ensure(scene, view_layer); + Base *base = BKE_view_layer_active_base_get(view_layer); if (base && BASE_SELECTABLE(v3d, base)) { Object *ob = BKE_object_pose_armature_get(base->object); if (ob) { @@ -132,8 +134,10 @@ static bool WIDGETGROUP_armature_spline_poll(const bContext *C, wmGizmoGroupType static void WIDGETGROUP_armature_spline_setup(const bContext *C, wmGizmoGroup *gzgroup) { + const Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); - Object *ob = BKE_object_pose_armature_get(OBACT(view_layer)); + BKE_view_layer_synced_ensure(scene, view_layer); + Object *ob = BKE_object_pose_armature_get(BKE_view_layer_active_object_get(view_layer)); bPoseChannel *pchan = BKE_pose_channel_active_if_layer_visible(ob); const wmGizmoType *gzt_move = WM_gizmotype_find("GIZMO_GT_move_3d", true); @@ -165,8 +169,10 @@ static void WIDGETGROUP_armature_spline_setup(const bContext *C, wmGizmoGroup *g static void WIDGETGROUP_armature_spline_refresh(const bContext *C, wmGizmoGroup *gzgroup) { + const Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); - Object *ob = BKE_object_pose_armature_get(OBACT(view_layer)); + BKE_view_layer_synced_ensure(scene, view_layer); + Object *ob = BKE_object_pose_armature_get(BKE_view_layer_active_object_get(view_layer)); if (!gzgroup->customdata) { return; diff --git a/source/blender/editors/space_view3d/view3d_gizmo_camera.c b/source/blender/editors/space_view3d/view3d_gizmo_camera.c index 83f589a64c9..952ef56710b 100644 --- a/source/blender/editors/space_view3d/view3d_gizmo_camera.c +++ b/source/blender/editors/space_view3d/view3d_gizmo_camera.c @@ -55,8 +55,10 @@ static bool WIDGETGROUP_camera_poll(const bContext *C, wmGizmoGroupType *UNUSED( return false; } + const Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); - Base *base = BASACT(view_layer); + BKE_view_layer_synced_ensure(scene, view_layer); + Base *base = BKE_view_layer_active_base_get(view_layer); if (base && BASE_SELECTABLE(v3d, base)) { Object *ob = base->object; if (ob->type == OB_CAMERA) { @@ -72,8 +74,10 @@ static bool WIDGETGROUP_camera_poll(const bContext *C, wmGizmoGroupType *UNUSED( static void WIDGETGROUP_camera_setup(const bContext *C, wmGizmoGroup *gzgroup) { + const Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); - Object *ob = OBACT(view_layer); + BKE_view_layer_synced_ensure(scene, view_layer); + Object *ob = BKE_view_layer_active_object_get(view_layer); float dir[3]; const wmGizmoType *gzt_arrow = WM_gizmotype_find("GIZMO_GT_arrow_3d", true); @@ -124,8 +128,10 @@ static void WIDGETGROUP_camera_refresh(const bContext *C, wmGizmoGroup *gzgroup) struct CameraWidgetGroup *cagzgroup = gzgroup->customdata; View3D *v3d = CTX_wm_view3d(C); + const Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); - Object *ob = OBACT(view_layer); + BKE_view_layer_synced_ensure(scene, view_layer); + Object *ob = BKE_view_layer_active_object_get(view_layer); Camera *ca = ob->data; PointerRNA camera_ptr; float dir[3]; @@ -151,7 +157,6 @@ static void WIDGETGROUP_camera_refresh(const bContext *C, wmGizmoGroup *gzgroup) } /* TODO: make focal length/ortho ob_scale_inv widget optional. */ - const Scene *scene = CTX_data_scene(C); const float aspx = (float)scene->r.xsch * scene->r.xasp; const float aspy = (float)scene->r.ysch * scene->r.yasp; const bool is_ortho = (ca->type == CAM_ORTHO); @@ -241,8 +246,10 @@ static void WIDGETGROUP_camera_message_subscribe(const bContext *C, struct wmMsgBus *mbus) { ARegion *region = CTX_wm_region(C); + const Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); - Object *ob = OBACT(view_layer); + BKE_view_layer_synced_ensure(scene, view_layer); + Object *ob = BKE_view_layer_active_object_get(view_layer); Camera *ca = ob->data; wmMsgSubscribeValue msg_sub_value_gz_tag_refresh = { @@ -370,7 +377,8 @@ static bool WIDGETGROUP_camera_view_poll(const bContext *C, wmGizmoGroupType *UN * We could change the rules for when to show. */ { ViewLayer *view_layer = CTX_data_view_layer(C); - if (scene->camera != OBACT(view_layer)) { + BKE_view_layer_synced_ensure(scene, view_layer); + if (scene->camera != BKE_view_layer_active_object_get(view_layer)) { return false; } } diff --git a/source/blender/editors/space_view3d/view3d_gizmo_empty.c b/source/blender/editors/space_view3d/view3d_gizmo_empty.c index f113cc60224..41a763192ce 100644 --- a/source/blender/editors/space_view3d/view3d_gizmo_empty.c +++ b/source/blender/editors/space_view3d/view3d_gizmo_empty.c @@ -99,8 +99,10 @@ static bool WIDGETGROUP_empty_image_poll(const bContext *C, wmGizmoGroupType *UN return false; } + const Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); - Base *base = BASACT(view_layer); + BKE_view_layer_synced_ensure(scene, view_layer); + Base *base = BKE_view_layer_active_base_get(view_layer); if (base && BASE_SELECTABLE(v3d, base)) { Object *ob = base->object; if (ob->type == OB_EMPTY) { @@ -132,8 +134,10 @@ static void WIDGETGROUP_empty_image_refresh(const bContext *C, wmGizmoGroup *gzg { struct EmptyImageWidgetGroup *igzgroup = gzgroup->customdata; wmGizmo *gz = igzgroup->gizmo; + const Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); - Object *ob = OBACT(view_layer); + BKE_view_layer_synced_ensure(scene, view_layer); + Object *ob = BKE_view_layer_active_object_get(view_layer); copy_m4_m4(gz->matrix_basis, ob->obmat); diff --git a/source/blender/editors/space_view3d/view3d_gizmo_forcefield.c b/source/blender/editors/space_view3d/view3d_gizmo_forcefield.c index 456e939eba7..58b43301397 100644 --- a/source/blender/editors/space_view3d/view3d_gizmo_forcefield.c +++ b/source/blender/editors/space_view3d/view3d_gizmo_forcefield.c @@ -42,8 +42,10 @@ static bool WIDGETGROUP_forcefield_poll(const bContext *C, wmGizmoGroupType *UNU return false; } + const Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); - Base *base = BASACT(view_layer); + BKE_view_layer_synced_ensure(scene, view_layer); + Base *base = BKE_view_layer_active_base_get(view_layer); if (base && BASE_SELECTABLE(v3d, base)) { Object *ob = base->object; if (ob->pd && ob->pd->forcefield) { @@ -73,8 +75,10 @@ static void WIDGETGROUP_forcefield_refresh(const bContext *C, wmGizmoGroup *gzgr { wmGizmoWrapper *wwrapper = gzgroup->customdata; wmGizmo *gz = wwrapper->gizmo; + const Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); - Object *ob = OBACT(view_layer); + BKE_view_layer_synced_ensure(scene, view_layer); + Object *ob = BKE_view_layer_active_object_get(view_layer); PartDeflect *pd = ob->pd; if (pd->forcefield == PFIELD_WIND) { diff --git a/source/blender/editors/space_view3d/view3d_gizmo_light.c b/source/blender/editors/space_view3d/view3d_gizmo_light.c index b3bc0bc70cb..df653f9a6e5 100644 --- a/source/blender/editors/space_view3d/view3d_gizmo_light.c +++ b/source/blender/editors/space_view3d/view3d_gizmo_light.c @@ -45,8 +45,10 @@ static bool WIDGETGROUP_light_spot_poll(const bContext *C, wmGizmoGroupType *UNU return false; } + const Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); - Base *base = BASACT(view_layer); + BKE_view_layer_synced_ensure(scene, view_layer); + Base *base = BKE_view_layer_active_base_get(view_layer); if (base && BASE_SELECTABLE(v3d, base)) { Object *ob = base->object; if (ob->type == OB_LAMP) { @@ -76,8 +78,10 @@ static void WIDGETGROUP_light_spot_refresh(const bContext *C, wmGizmoGroup *gzgr { wmGizmoWrapper *wwrapper = gzgroup->customdata; wmGizmo *gz = wwrapper->gizmo; + const Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); - Object *ob = OBACT(view_layer); + BKE_view_layer_synced_ensure(scene, view_layer); + Object *ob = BKE_view_layer_active_object_get(view_layer); Light *la = ob->data; float dir[3]; @@ -156,8 +160,10 @@ static bool WIDGETGROUP_light_area_poll(const bContext *C, wmGizmoGroupType *UNU return false; } + const Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); - Base *base = BASACT(view_layer); + BKE_view_layer_synced_ensure(scene, view_layer); + Base *base = BKE_view_layer_active_base_get(view_layer); if (base && BASE_SELECTABLE(v3d, base)) { Object *ob = base->object; if (ob->type == OB_LAMP) { @@ -186,8 +192,10 @@ static void WIDGETGROUP_light_area_setup(const bContext *UNUSED(C), wmGizmoGroup static void WIDGETGROUP_light_area_refresh(const bContext *C, wmGizmoGroup *gzgroup) { wmGizmoWrapper *wwrapper = gzgroup->customdata; + const Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); - Object *ob = OBACT(view_layer); + BKE_view_layer_synced_ensure(scene, view_layer); + Object *ob = BKE_view_layer_active_object_get(view_layer); Light *la = ob->data; wmGizmo *gz = wwrapper->gizmo; @@ -239,8 +247,10 @@ static bool WIDGETGROUP_light_target_poll(const bContext *C, wmGizmoGroupType *U return false; } + const Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); - Base *base = BASACT(view_layer); + BKE_view_layer_synced_ensure(scene, view_layer); + Base *base = BKE_view_layer_active_base_get(view_layer); if (base && BASE_SELECTABLE(v3d, base)) { Object *ob = base->object; if (ob->type == OB_LAMP) { @@ -280,8 +290,10 @@ static void WIDGETGROUP_light_target_setup(const bContext *UNUSED(C), wmGizmoGro static void WIDGETGROUP_light_target_draw_prepare(const bContext *C, wmGizmoGroup *gzgroup) { wmGizmoWrapper *wwrapper = gzgroup->customdata; + const Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); - Object *ob = OBACT(view_layer); + BKE_view_layer_synced_ensure(scene, view_layer); + Object *ob = BKE_view_layer_active_object_get(view_layer); wmGizmo *gz = wwrapper->gizmo; normalize_m4_m4(gz->matrix_basis, ob->obmat); diff --git a/source/blender/editors/space_view3d/view3d_gizmo_preselect_type.c b/source/blender/editors/space_view3d/view3d_gizmo_preselect_type.c index a0c010a6813..d0f6ca4c922 100644 --- a/source/blender/editors/space_view3d/view3d_gizmo_preselect_type.c +++ b/source/blender/editors/space_view3d/view3d_gizmo_preselect_type.c @@ -125,12 +125,15 @@ static int gizmo_preselect_elem_test_select(bContext *C, wmGizmo *gz, const int }; { + const Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); View3D *v3d = CTX_wm_view3d(C); - if (((gz_ele->bases)) == NULL || (gz_ele->bases[0] != view_layer->basact)) { + BKE_view_layer_synced_ensure(scene, view_layer); + if (((gz_ele->bases)) == NULL || + (gz_ele->bases[0] != BKE_view_layer_active_base_get(view_layer))) { MEM_SAFE_FREE(gz_ele->bases); gz_ele->bases = BKE_view_layer_array_from_bases_in_edit_mode( - view_layer, v3d, &gz_ele->bases_len); + scene, view_layer, v3d, &gz_ele->bases_len); } } @@ -351,12 +354,15 @@ static int gizmo_preselect_edgering_test_select(bContext *C, wmGizmo *gz, const }; { + const Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); View3D *v3d = CTX_wm_view3d(C); - if (((gz_ring->bases)) == NULL || (gz_ring->bases[0] != view_layer->basact)) { + BKE_view_layer_synced_ensure(scene, view_layer); + if (((gz_ring->bases)) == NULL || + (gz_ring->bases[0] != BKE_view_layer_active_base_get(view_layer))) { MEM_SAFE_FREE(gz_ring->bases); gz_ring->bases = BKE_view_layer_array_from_bases_in_edit_mode( - view_layer, v3d, &gz_ring->bases_len); + scene, view_layer, v3d, &gz_ring->bases_len); } } @@ -488,6 +494,7 @@ void ED_view3d_gizmo_mesh_preselect_get_active(bContext *C, Base **r_base, BMElem **r_ele) { + const Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); const int object_index = RNA_int_get(gz->ptr, "object_index"); @@ -498,7 +505,7 @@ void ED_view3d_gizmo_mesh_preselect_get_active(bContext *C, { uint bases_len; Base **bases = BKE_view_layer_array_from_bases_in_edit_mode( - view_layer, CTX_wm_view3d(C), &bases_len); + scene, view_layer, CTX_wm_view3d(C), &bases_len); if (object_index < bases_len) { base = bases[object_index]; obedit = base->object; diff --git a/source/blender/editors/space_view3d/view3d_gizmo_ruler.c b/source/blender/editors/space_view3d/view3d_gizmo_ruler.c index 62dc461e05c..d95d49dd982 100644 --- a/source/blender/editors/space_view3d/view3d_gizmo_ruler.c +++ b/source/blender/editors/space_view3d/view3d_gizmo_ruler.c @@ -17,6 +17,7 @@ #include "BKE_main.h" #include "BKE_report.h" +#include "BKE_layer.h" #include "BKE_material.h" #include "BKE_object.h" #include "BKE_scene.h" @@ -420,7 +421,8 @@ static bool view3d_ruler_item_mousemove(const bContext *C, Scene *scene = DEG_get_input_scene(depsgraph); ViewLayer *view_layer = DEG_get_input_view_layer(depsgraph); RegionView3D *rv3d = ruler_info->region->regiondata; - Object *ob = OBACT(view_layer); + BKE_view_layer_synced_ensure(scene, view_layer); + Object *ob = BKE_view_layer_active_object_get(view_layer); Object *obedit = OBEDIT_FROM_OBACT(ob); short orient_index = BKE_scene_orientation_get_index(scene, SCE_ORIENT_DEFAULT); @@ -783,7 +785,7 @@ static void gizmo_ruler_draw(const bContext *C, wmGizmo *gz) immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); if (ruler_item->flag & RULERITEM_USE_ANGLE) { - immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); /* capping */ { float rot_90_vec_a[2]; @@ -885,7 +887,7 @@ static void gizmo_ruler_draw(const bContext *C, wmGizmo *gz) } } else { - immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); sub_v2_v2v2(dir_ruler, co_ss[0], co_ss[2]); diff --git a/source/blender/editors/space_view3d/view3d_header.c b/source/blender/editors/space_view3d/view3d_header.c index 6e8d9e96abd..45f7a3a8fe9 100644 --- a/source/blender/editors/space_view3d/view3d_header.c +++ b/source/blender/editors/space_view3d/view3d_header.c @@ -20,6 +20,7 @@ #include "BKE_context.h" #include "BKE_editmesh.h" +#include "BKE_layer.h" #include "DEG_depsgraph.h" @@ -124,8 +125,10 @@ void uiTemplateEditModeSelection(uiLayout *layout, struct bContext *C) static void uiTemplatePaintModeSelection(uiLayout *layout, struct bContext *C) { + const Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); - Object *ob = OBACT(view_layer); + BKE_view_layer_synced_ensure(scene, view_layer); + Object *ob = BKE_view_layer_active_object_get(view_layer); /* Gizmos aren't used in paint modes */ if (!ELEM(ob->mode, OB_MODE_SCULPT, OB_MODE_PARTICLE_EDIT)) { @@ -146,8 +149,10 @@ static void uiTemplatePaintModeSelection(uiLayout *layout, struct bContext *C) void uiTemplateHeader3D_mode(uiLayout *layout, struct bContext *C) { + const Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); - Object *ob = OBACT(view_layer); + BKE_view_layer_synced_ensure(scene, view_layer); + Object *ob = BKE_view_layer_active_object_get(view_layer); Object *obedit = CTX_data_edit_object(C); bGPdata *gpd = CTX_data_gpencil_data(C); diff --git a/source/blender/editors/space_view3d/view3d_intern.h b/source/blender/editors/space_view3d/view3d_intern.h index 53fc450107a..08d42471998 100644 --- a/source/blender/editors/space_view3d/view3d_intern.h +++ b/source/blender/editors/space_view3d/view3d_intern.h @@ -9,6 +9,10 @@ #include "ED_view3d.h" +#ifdef __cplusplus +extern "C" { +#endif + /* internal exports only */ struct ARegion; @@ -83,7 +87,7 @@ void view3d_depths_rect_create(struct ARegion *region, struct rcti *rect, struct */ float view3d_depth_near(struct ViewDepths *d); -/* view3d_select.c */ +/* view3d_select.cc */ void VIEW3D_OT_select(struct wmOperatorType *ot); void VIEW3D_OT_select_circle(struct wmOperatorType *ot); @@ -202,7 +206,7 @@ void VIEW3D_OT_snap_cursor_to_active(struct wmOperatorType *ot); void VIEW3D_OT_interactive_add(struct wmOperatorType *ot); -/* space_view3d.c */ +/* space_view3d.cc */ extern const char *view3d_context_dir[]; /* doc access */ @@ -241,3 +245,7 @@ void VIEW3D_GGT_placement(struct wmGizmoGroupType *gzgt); extern uchar view3d_camera_border_hack_col[3]; extern bool view3d_camera_border_hack_test; #endif + +#ifdef __cplusplus +} +#endif diff --git a/source/blender/editors/space_view3d/view3d_iterators.c b/source/blender/editors/space_view3d/view3d_iterators.c index 6256eeb9621..34f68e87880 100644 --- a/source/blender/editors/space_view3d/view3d_iterators.c +++ b/source/blender/editors/space_view3d/view3d_iterators.c @@ -23,6 +23,7 @@ #include "BKE_curve.h" #include "BKE_displist.h" #include "BKE_editmesh.h" +#include "BKE_mesh.h" #include "BKE_mesh_iterators.h" #include "BKE_mesh_runtime.h" #include "BKE_mesh_wrapper.h" @@ -205,6 +206,7 @@ typedef struct foreachScreenObjectVert_userData { void (*func)(void *userData, MVert *mv, const float screen_co[2], int index); void *userData; ViewContext vc; + MVert *verts; const bool *hide_vert; eV3DProjTest clip_flag; } foreachScreenObjectVert_userData; @@ -245,7 +247,7 @@ typedef struct foreachScreenFace_userData { } foreachScreenFace_userData; /** - * \note foreach funcs should be called while drawing or directly after + * \note foreach functions should be called while drawing or directly after * if not, #ED_view3d_init_mats_rv3d() can be used for selection tools * but would not give correct results with dupli's for eg. which don't * use the object matrix in the usual way. @@ -266,7 +268,7 @@ static void meshobject_foreachScreenVert__mapFunc(void *userData, if (data->hide_vert && data->hide_vert[index]) { return; } - struct MVert *mv = &((Mesh *)(data->vc.obact->data))->mvert[index]; + MVert *mv = &data->verts[index]; float screen_co[2]; @@ -299,6 +301,7 @@ void meshobject_foreachScreenVert( data.func = func; data.userData = userData; data.clip_flag = clip_flag; + data.verts = BKE_mesh_verts_for_write((Mesh *)vc->obact->data); data.hide_vert = (const bool *)CustomData_get_layer_named( &me->vdata, CD_PROP_BOOL, ".hide_vert"); diff --git a/source/blender/editors/space_view3d/view3d_navigate.c b/source/blender/editors/space_view3d/view3d_navigate.c index f50e933fdac..b27c65c42ef 100644 --- a/source/blender/editors/space_view3d/view3d_navigate.c +++ b/source/blender/editors/space_view3d/view3d_navigate.c @@ -164,9 +164,11 @@ bool view3d_orbit_calc_center(bContext *C, float r_dyn_ofs[3]) const Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C); Scene *scene = CTX_data_scene(C); + Scene *scene_eval = DEG_get_evaluated_scene(depsgraph); ViewLayer *view_layer_eval = DEG_get_evaluated_view_layer(depsgraph); View3D *v3d = CTX_wm_view3d(C); - Object *ob_act_eval = OBACT(view_layer_eval); + BKE_view_layer_synced_ensure(scene_eval, view_layer_eval); + Object *ob_act_eval = BKE_view_layer_active_object_get(view_layer_eval); Object *ob_act = DEG_get_original_object(ob_act_eval); if (ob_act && (ob_act->mode & OB_MODE_ALL_PAINT) && @@ -203,12 +205,11 @@ bool view3d_orbit_calc_center(bContext *C, float r_dyn_ofs[3]) } else if (ob_act == NULL || ob_act->mode == OB_MODE_OBJECT) { /* object mode use boundbox centers */ - Base *base_eval; uint tot = 0; float select_center[3]; zero_v3(select_center); - for (base_eval = FIRSTBASE(view_layer_eval); base_eval; base_eval = base_eval->next) { + LISTBASE_FOREACH (Base *, base_eval, BKE_view_layer_object_bases_get(view_layer_eval)) { if (BASE_SELECTED(v3d, base_eval)) { /* use the boundbox if we can */ Object *ob_eval = base_eval->object; @@ -752,8 +753,9 @@ static int view3d_all_exec(bContext *C, wmOperator *op) RegionView3D *rv3d = CTX_wm_region_view3d(C); Scene *scene = CTX_data_scene(C); Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C); + Scene *scene_eval = DEG_get_evaluated_scene(depsgraph); ViewLayer *view_layer_eval = DEG_get_evaluated_view_layer(depsgraph); - Base *base_eval; + const bool use_all_regions = RNA_boolean_get(op->ptr, "use_all_regions"); const bool skip_camera = (ED_view3d_camera_lock_check(v3d, region->regiondata) || /* any one of the regions may be locked */ @@ -778,7 +780,8 @@ static int view3d_all_exec(bContext *C, wmOperator *op) INIT_MINMAX(min, max); } - for (base_eval = view_layer_eval->object_bases.first; base_eval; base_eval = base_eval->next) { + BKE_view_layer_synced_ensure(scene_eval, view_layer_eval); + LISTBASE_FOREACH (Base *, base_eval, BKE_view_layer_object_bases_get(view_layer_eval)) { if (BASE_VISIBLE(v3d, base_eval)) { bool only_center = false; Object *ob = DEG_get_original_object(base_eval->object); @@ -862,8 +865,10 @@ static int viewselected_exec(bContext *C, wmOperator *op) RegionView3D *rv3d = CTX_wm_region_view3d(C); Scene *scene = CTX_data_scene(C); Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C); + const Scene *scene_eval = DEG_get_evaluated_scene(depsgraph); ViewLayer *view_layer_eval = DEG_get_evaluated_view_layer(depsgraph); - Object *ob_eval = OBACT(view_layer_eval); + BKE_view_layer_synced_ensure(scene_eval, view_layer_eval); + Object *ob_eval = BKE_view_layer_active_object_get(view_layer_eval); Object *obedit = CTX_data_edit_object(C); const bGPdata *gpd_eval = ob_eval && (ob_eval->type == OB_GPENCIL) ? ob_eval->data : NULL; const bool is_gp_edit = gpd_eval ? GPENCIL_ANY_MODE(gpd_eval) : false; @@ -887,7 +892,8 @@ static int viewselected_exec(bContext *C, wmOperator *op) /* this is weak code this way, we should make a generic * active/selection callback interface once... */ Base *base_eval; - for (base_eval = view_layer_eval->object_bases.first; base_eval; base_eval = base_eval->next) { + for (base_eval = BKE_view_layer_object_bases_get(view_layer_eval)->first; base_eval; + base_eval = base_eval->next) { if (BASE_SELECTED_EDITABLE(v3d, base_eval)) { if (base_eval->object->type == OB_ARMATURE) { if (base_eval->object->mode & OB_MODE_POSE) { @@ -937,14 +943,15 @@ static int viewselected_exec(bContext *C, wmOperator *op) } else if (obedit) { /* only selected */ - FOREACH_OBJECT_IN_MODE_BEGIN (view_layer_eval, v3d, obedit->type, obedit->mode, ob_eval_iter) { + FOREACH_OBJECT_IN_MODE_BEGIN ( + scene_eval, view_layer_eval, v3d, obedit->type, obedit->mode, ob_eval_iter) { ok |= ED_view3d_minmax_verts(ob_eval_iter, min, max); } FOREACH_OBJECT_IN_MODE_END; } else if (ob_eval && (ob_eval->mode & OB_MODE_POSE)) { FOREACH_OBJECT_IN_MODE_BEGIN ( - view_layer_eval, v3d, ob_eval->type, ob_eval->mode, ob_eval_iter) { + scene_eval, view_layer_eval, v3d, ob_eval->type, ob_eval->mode, ob_eval_iter) { ok |= BKE_pose_minmax(ob_eval_iter, min, max, true, true); } FOREACH_OBJECT_IN_MODE_END; @@ -963,8 +970,7 @@ static int viewselected_exec(bContext *C, wmOperator *op) ok_dist = 0; /* don't zoom */ } else { - Base *base_eval; - for (base_eval = FIRSTBASE(view_layer_eval); base_eval; base_eval = base_eval->next) { + LISTBASE_FOREACH (Base *, base_eval, BKE_view_layer_object_bases_get(view_layer_eval)) { if (BASE_SELECTED(v3d, base_eval)) { bool only_center = false; Object *ob = DEG_get_original_object(base_eval->object); @@ -1169,10 +1175,12 @@ static int view_axis_exec(bContext *C, wmOperator *op) Object *obact = CTX_data_active_object(C); if (obact != NULL) { float twmat[3][3]; + const Scene *scene = CTX_data_scene(C); struct ViewLayer *view_layer = CTX_data_view_layer(C); Object *obedit = CTX_data_edit_object(C); /* same as transform gizmo when normal is set */ - ED_getTransformOrientationMatrix(view_layer, v3d, obact, obedit, V3D_AROUND_ACTIVE, twmat); + ED_getTransformOrientationMatrix( + scene, view_layer, v3d, obact, obedit, V3D_AROUND_ACTIVE, twmat); align_quat = align_quat_buf; mat3_to_quat(align_quat, twmat); invert_qt_normalized(align_quat); @@ -1306,7 +1314,8 @@ static int view_camera_exec(bContext *C, wmOperator *op) Scene *scene = CTX_data_scene(C); if (rv3d->persp != RV3D_CAMOB) { - Object *ob = OBACT(view_layer); + BKE_view_layer_synced_ensure(scene, view_layer); + Object *ob = BKE_view_layer_active_object_get(view_layer); if (!rv3d->smooth_timer) { /* store settings of current view before allowing overwriting with camera view @@ -1333,7 +1342,7 @@ static int view_camera_exec(bContext *C, wmOperator *op) } if (v3d->camera == NULL) { - v3d->camera = BKE_view_layer_camera_find(view_layer); + v3d->camera = BKE_view_layer_camera_find(scene, view_layer); } /* couldn't find any useful camera, bail out */ diff --git a/source/blender/editors/space_view3d/view3d_navigate.h b/source/blender/editors/space_view3d/view3d_navigate.h index 925acd90573..792357ae134 100644 --- a/source/blender/editors/space_view3d/view3d_navigate.h +++ b/source/blender/editors/space_view3d/view3d_navigate.h @@ -7,6 +7,10 @@ #pragma once +#ifdef __cplusplus +extern "C" { +#endif + /** * Size of the sphere being dragged for trackball rotation within the view bounds. * also affects speed (smaller is faster). @@ -298,3 +302,7 @@ void VIEW3D_OT_zoom(struct wmOperatorType *ot); /* view3d_navigate_zoom_border.c */ void VIEW3D_OT_zoom_border(struct wmOperatorType *ot); + +#ifdef __cplusplus +} +#endif diff --git a/source/blender/editors/space_view3d/view3d_navigate_dolly.c b/source/blender/editors/space_view3d/view3d_navigate_dolly.c index 376e8ba190b..df0f4e6e94b 100644 --- a/source/blender/editors/space_view3d/view3d_navigate_dolly.c +++ b/source/blender/editors/space_view3d/view3d_navigate_dolly.c @@ -41,7 +41,7 @@ void viewdolly_modal_keymap(wmKeyConfig *keyconf) wmKeyMap *keymap = WM_modalkeymap_find(keyconf, "View3D Dolly Modal"); - /* this function is called for each spacetype, only needs to add map once */ + /* This function is called for each space-type, only needs to add map once. */ if (keymap && keymap->modal_items) { return; } diff --git a/source/blender/editors/space_view3d/view3d_navigate_fly.c b/source/blender/editors/space_view3d/view3d_navigate_fly.c index 95114941d66..3e83f8085c7 100644 --- a/source/blender/editors/space_view3d/view3d_navigate_fly.c +++ b/source/blender/editors/space_view3d/view3d_navigate_fly.c @@ -122,7 +122,7 @@ void fly_modal_keymap(wmKeyConfig *keyconf) wmKeyMap *keymap = WM_modalkeymap_find(keyconf, "View3D Fly Modal"); - /* this function is called for each spacetype, only needs to add map once */ + /* This function is called for each space-type, only needs to add map once. */ if (keymap && keymap->modal_items) { return; } @@ -247,7 +247,7 @@ static void drawFlyPixel(const struct bContext *UNUSED(C), ARegion *UNUSED(regio GPUVertFormat *format = immVertexFormat(); uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); - immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); immUniformThemeColor3(TH_VIEW_OVERLAY); diff --git a/source/blender/editors/space_view3d/view3d_navigate_move.c b/source/blender/editors/space_view3d/view3d_navigate_move.c index e236b702fb8..9de0a2ae4c2 100644 --- a/source/blender/editors/space_view3d/view3d_navigate_move.c +++ b/source/blender/editors/space_view3d/view3d_navigate_move.c @@ -35,7 +35,7 @@ void viewmove_modal_keymap(wmKeyConfig *keyconf) wmKeyMap *keymap = WM_modalkeymap_find(keyconf, "View3D Move Modal"); - /* this function is called for each spacetype, only needs to add map once */ + /* This function is called for each space-type, only needs to add map once. */ if (keymap && keymap->modal_items) { return; } diff --git a/source/blender/editors/space_view3d/view3d_navigate_ndof.c b/source/blender/editors/space_view3d/view3d_navigate_ndof.c index 1ce9bdcb211..88abf602c26 100644 --- a/source/blender/editors/space_view3d/view3d_navigate_ndof.c +++ b/source/blender/editors/space_view3d/view3d_navigate_ndof.c @@ -373,6 +373,9 @@ static int view3d_ndof_cameraview_pan_zoom(bContext *C, const wmEvent *event) const bool has_translate = !is_zero_v2(ndof->tvec); const bool has_zoom = ndof->tvec[2] != 0.0f; + float pan_vec[3]; + WM_event_ndof_pan_get(ndof, pan_vec, true); + /* NOTE(@campbellbarton): In principle rotating could pass through to regular * non-camera NDOF behavior (exiting the camera-view and rotating). * Disabled this block since in practice it's difficult to control NDOF devices @@ -388,14 +391,14 @@ static int view3d_ndof_cameraview_pan_zoom(bContext *C, const wmEvent *event) if (has_translate) { const float speed = ndof->dt * NDOF_PIXELS_PER_SECOND; - float event_ofs[2] = {ndof->tvec[0] * speed, ndof->tvec[1] * speed}; + float event_ofs[2] = {pan_vec[0] * speed, pan_vec[1] * speed}; if (ED_view3d_camera_view_pan(region, event_ofs)) { changed = true; } } if (has_zoom) { - const float scale = 1.0f + (ndof->dt * ndof->tvec[2]); + const float scale = 1.0f + (ndof->dt * pan_vec[2]); if (ED_view3d_camera_view_zoom_scale(rv3d, scale)) { changed = true; } diff --git a/source/blender/editors/space_view3d/view3d_navigate_rotate.c b/source/blender/editors/space_view3d/view3d_navigate_rotate.c index 20385e15c48..10adf238001 100644 --- a/source/blender/editors/space_view3d/view3d_navigate_rotate.c +++ b/source/blender/editors/space_view3d/view3d_navigate_rotate.c @@ -37,7 +37,7 @@ void viewrotate_modal_keymap(wmKeyConfig *keyconf) wmKeyMap *keymap = WM_modalkeymap_find(keyconf, "View3D Rotate Modal"); - /* this function is called for each spacetype, only needs to add map once */ + /* This function is called for each space-type, only needs to add map once. */ if (keymap && keymap->modal_items) { return; } diff --git a/source/blender/editors/space_view3d/view3d_navigate_walk.c b/source/blender/editors/space_view3d/view3d_navigate_walk.c index 69deaab7ebe..3e0ce892b5a 100644 --- a/source/blender/editors/space_view3d/view3d_navigate_walk.c +++ b/source/blender/editors/space_view3d/view3d_navigate_walk.c @@ -170,7 +170,7 @@ void walk_modal_keymap(wmKeyConfig *keyconf) wmKeyMap *keymap = WM_modalkeymap_find(keyconf, "View3D Walk Modal"); - /* this function is called for each spacetype, only needs to add map once */ + /* This function is called for each space-type, only needs to add map once. */ if (keymap && keymap->modal_items) { return; } @@ -335,7 +335,7 @@ static void drawWalkPixel(const struct bContext *UNUSED(C), ARegion *region, voi GPUVertFormat *format = immVertexFormat(); uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_I32, 2, GPU_FETCH_INT_TO_FLOAT); - immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); immUniformThemeColorAlpha(TH_VIEW_OVERLAY, 1.0f); diff --git a/source/blender/editors/space_view3d/view3d_navigate_zoom.c b/source/blender/editors/space_view3d/view3d_navigate_zoom.c index 9230aa09b1a..40df2b1a9c9 100644 --- a/source/blender/editors/space_view3d/view3d_navigate_zoom.c +++ b/source/blender/editors/space_view3d/view3d_navigate_zoom.c @@ -41,7 +41,7 @@ void viewzoom_modal_keymap(wmKeyConfig *keyconf) wmKeyMap *keymap = WM_modalkeymap_find(keyconf, "View3D Zoom Modal"); - /* this function is called for each spacetype, only needs to add map once */ + /* This function is called for each space-type, only needs to add map once. */ if (keymap && keymap->modal_items) { return; } diff --git a/source/blender/editors/space_view3d/view3d_select.c b/source/blender/editors/space_view3d/view3d_select.cc index 763848574ed..a0b3802076a 100644 --- a/source/blender/editors/space_view3d/view3d_select.c +++ b/source/blender/editors/space_view3d/view3d_select.cc @@ -5,10 +5,10 @@ * \ingroup spview3d */ -#include <float.h> -#include <math.h> -#include <stdio.h> -#include <string.h> +#include <cfloat> +#include <cmath> +#include <cstdio> +#include <cstring> #include "DNA_action_types.h" #include "DNA_armature_types.h" @@ -23,7 +23,6 @@ #include "MEM_guardedalloc.h" -#include "BLI_array.h" #include "BLI_bitmap.h" #include "BLI_lasso_2d.h" #include "BLI_linklist.h" @@ -32,6 +31,7 @@ #include "BLI_rect.h" #include "BLI_string.h" #include "BLI_utildefines.h" +#include "BLI_vector.hh" #ifdef __BIG_ENDIAN__ # include "BLI_endian_switch.h" @@ -45,6 +45,7 @@ #include "BKE_action.h" #include "BKE_armature.h" +#include "BKE_attribute.hh" #include "BKE_context.h" #include "BKE_curve.h" #include "BKE_editmesh.h" @@ -140,10 +141,11 @@ void ED_view3d_viewcontext_init_object(ViewContext *vc, Object *obact) /** \name Internal Object Utilities * \{ */ -static bool object_deselect_all_visible(ViewLayer *view_layer, View3D *v3d) +static bool object_deselect_all_visible(const Scene *scene, ViewLayer *view_layer, View3D *v3d) { bool changed = false; - LISTBASE_FOREACH (Base *, base, &view_layer->object_bases) { + BKE_view_layer_synced_ensure(scene, view_layer); + LISTBASE_FOREACH (Base *, base, BKE_view_layer_object_bases_get(view_layer)) { if (base->flag & BASE_SELECTED) { if (BASE_SELECTABLE(v3d, base)) { ED_object_base_select(base, BA_DESELECT); @@ -155,10 +157,11 @@ static bool object_deselect_all_visible(ViewLayer *view_layer, View3D *v3d) } /* deselect all except b */ -static bool object_deselect_all_except(ViewLayer *view_layer, Base *b) +static bool object_deselect_all_except(const Scene *scene, ViewLayer *view_layer, Base *b) { bool changed = false; - LISTBASE_FOREACH (Base *, base, &view_layer->object_bases) { + BKE_view_layer_synced_ensure(scene, view_layer); + LISTBASE_FOREACH (Base *, base, BKE_view_layer_object_bases_get(view_layer)) { if (base->flag & BASE_SELECTED) { if (b != base) { ED_object_base_select(base, BA_DESELECT); @@ -191,7 +194,7 @@ static void editselect_buf_cache_init(ViewContext *vc, short select_mode) if (vc->obedit) { uint bases_len = 0; Base **bases = BKE_view_layer_array_from_bases_in_edit_mode( - vc->view_layer, vc->v3d, &bases_len); + vc->scene, vc->view_layer, vc->v3d, &bases_len); DRW_select_buffer_context_create(bases, bases_len, select_mode); MEM_freeN(bases); @@ -199,20 +202,21 @@ static void editselect_buf_cache_init(ViewContext *vc, short select_mode) else { /* Use for paint modes, currently only a single object at a time. */ if (vc->obact) { + BKE_view_layer_synced_ensure(vc->scene, vc->view_layer); Base *base = BKE_view_layer_base_find(vc->view_layer, vc->obact); DRW_select_buffer_context_create(&base, 1, select_mode); } } } -static void editselect_buf_cache_free(struct EditSelectBuf_Cache *esel) +static void editselect_buf_cache_free(EditSelectBuf_Cache *esel) { MEM_SAFE_FREE(esel->select_bitmap); } static void editselect_buf_cache_free_voidp(void *esel_voidp) { - editselect_buf_cache_free(esel_voidp); + editselect_buf_cache_free(static_cast<EditSelectBuf_Cache *>(esel_voidp)); MEM_freeN(esel_voidp); } @@ -220,7 +224,7 @@ static void editselect_buf_cache_init_with_generic_userdata(wmGenericUserData *w ViewContext *vc, short select_mode) { - struct EditSelectBuf_Cache *esel = MEM_callocN(sizeof(*esel), __func__); + EditSelectBuf_Cache *esel = MEM_cnew<EditSelectBuf_Cache>(__func__); wm_userdata->data = esel; wm_userdata->free_fn = editselect_buf_cache_free_voidp; wm_userdata->use_free = true; @@ -233,7 +237,7 @@ static void editselect_buf_cache_init_with_generic_userdata(wmGenericUserData *w /** \name Internal Edit-Mesh Utilities * \{ */ -static bool edbm_backbuf_check_and_select_verts(struct EditSelectBuf_Cache *esel, +static bool edbm_backbuf_check_and_select_verts(EditSelectBuf_Cache *esel, Depsgraph *depsgraph, Object *ob, BMEditMesh *em, @@ -265,7 +269,7 @@ static bool edbm_backbuf_check_and_select_verts(struct EditSelectBuf_Cache *esel return changed; } -static bool edbm_backbuf_check_and_select_edges(struct EditSelectBuf_Cache *esel, +static bool edbm_backbuf_check_and_select_edges(EditSelectBuf_Cache *esel, Depsgraph *depsgraph, Object *ob, BMEditMesh *em, @@ -297,7 +301,7 @@ static bool edbm_backbuf_check_and_select_edges(struct EditSelectBuf_Cache *esel return changed; } -static bool edbm_backbuf_check_and_select_faces(struct EditSelectBuf_Cache *esel, +static bool edbm_backbuf_check_and_select_faces(EditSelectBuf_Cache *esel, Depsgraph *depsgraph, Object *ob, BMEditMesh *em, @@ -331,59 +335,63 @@ static bool edbm_backbuf_check_and_select_faces(struct EditSelectBuf_Cache *esel /* object mode, edbm_ prefix is confusing here, rename? */ static bool edbm_backbuf_check_and_select_verts_obmode(Mesh *me, - struct EditSelectBuf_Cache *esel, + EditSelectBuf_Cache *esel, const eSelectOp sel_op) { - MVert *mv = me->mvert; + using namespace blender; bool changed = false; const BLI_bitmap *select_bitmap = esel->select_bitmap; - if (mv) { - const bool *hide_vert = (const bool *)CustomData_get_layer_named( - &me->vdata, CD_PROP_BOOL, ".hide_vert"); + bke::MutableAttributeAccessor attributes = me->attributes_for_write(); + bke::SpanAttributeWriter<bool> select_vert = attributes.lookup_or_add_for_write_span<bool>( + ".select_vert", ATTR_DOMAIN_POINT); + const VArray<bool> hide_vert = attributes.lookup_or_default<bool>( + ".hide_vert", ATTR_DOMAIN_POINT, false); - for (int index = 0; index < me->totvert; index++, mv++) { - if (!(hide_vert && hide_vert[index])) { - const bool is_select = mv->flag & SELECT; - const bool is_inside = BLI_BITMAP_TEST_BOOL(select_bitmap, index); - const int sel_op_result = ED_select_op_action_deselected(sel_op, is_select, is_inside); - if (sel_op_result != -1) { - SET_FLAG_FROM_TEST(mv->flag, sel_op_result, SELECT); - changed = true; - } + for (int index = 0; index < me->totvert; index++) { + if (!hide_vert[index]) { + const bool is_select = select_vert.span[index]; + const bool is_inside = BLI_BITMAP_TEST_BOOL(select_bitmap, index); + const int sel_op_result = ED_select_op_action_deselected(sel_op, is_select, is_inside); + if (sel_op_result != -1) { + select_vert.span[index] = sel_op_result == 1; + changed = true; } } } + select_vert.finish(); return changed; } /* object mode, edbm_ prefix is confusing here, rename? */ static bool edbm_backbuf_check_and_select_faces_obmode(Mesh *me, - struct EditSelectBuf_Cache *esel, + EditSelectBuf_Cache *esel, const eSelectOp sel_op) { - MPoly *mpoly = me->mpoly; + using namespace blender; bool changed = false; const BLI_bitmap *select_bitmap = esel->select_bitmap; - if (mpoly) { - const bool *hide_poly = (const bool *)CustomData_get_layer_named( - &me->pdata, CD_PROP_BOOL, ".hide_poly"); + bke::MutableAttributeAccessor attributes = me->attributes_for_write(); + bke::SpanAttributeWriter<bool> select_poly = attributes.lookup_or_add_for_write_span<bool>( + ".select_poly", ATTR_DOMAIN_FACE); + const VArray<bool> hide_poly = attributes.lookup_or_default<bool>( + ".hide_poly", ATTR_DOMAIN_FACE, false); - for (int index = 0; index < me->totpoly; index++, mpoly++) { - if (!(hide_poly && hide_poly[index])) { - const bool is_select = mpoly->flag & ME_FACE_SEL; - const bool is_inside = BLI_BITMAP_TEST_BOOL(select_bitmap, index); - const int sel_op_result = ED_select_op_action_deselected(sel_op, is_select, is_inside); - if (sel_op_result != -1) { - SET_FLAG_FROM_TEST(mpoly->flag, sel_op_result, ME_FACE_SEL); - changed = true; - } + for (int index = 0; index < me->totpoly; index++) { + if (!hide_poly[index]) { + const bool is_select = select_poly.span[index]; + const bool is_inside = BLI_BITMAP_TEST_BOOL(select_bitmap, index); + const int sel_op_result = ED_select_op_action_deselected(sel_op, is_select, is_inside); + if (sel_op_result != -1) { + select_poly.span[index] = sel_op_result == 1; + changed = true; } } } + select_poly.finish(); return changed; } @@ -393,7 +401,7 @@ static bool edbm_backbuf_check_and_select_faces_obmode(Mesh *me, /** \name Lasso Select * \{ */ -typedef struct LassoSelectUserData { +struct LassoSelectUserData { ViewContext *vc; const rcti *rect; const rctf *rect_fl; @@ -407,7 +415,7 @@ typedef struct LassoSelectUserData { int pass; bool is_done; bool is_changed; -} LassoSelectUserData; +}; static void view3d_userdata_lassoselect_init(LassoSelectUserData *r_data, ViewContext *vc, @@ -426,7 +434,7 @@ static void view3d_userdata_lassoselect_init(LassoSelectUserData *r_data, r_data->mcoords_len = mcoords_len; r_data->sel_op = sel_op; /* SELECT by default, but can be changed if needed (only few cases use and respect this). */ - r_data->select_flag = SELECT; + r_data->select_flag = (eBezTriple_Flag)SELECT; /* runtime */ r_data->pass = 0; @@ -439,24 +447,24 @@ static bool view3d_selectable_data(bContext *C) Object *ob = CTX_data_active_object(C); if (!ED_operator_region_view3d_active(C)) { - return 0; + return false; } if (ob) { if (ob->mode & OB_MODE_EDIT) { if (ob->type == OB_FONT) { - return 0; + return false; } } else { if ((ob->mode & (OB_MODE_VERTEX_PAINT | OB_MODE_WEIGHT_PAINT | OB_MODE_TEXTURE_PAINT)) && !BKE_paint_select_elem_test(ob)) { - return 0; + return false; } } } - return 1; + return true; } /* helper also for box_select */ @@ -471,21 +479,21 @@ static bool edge_inside_rect(const rctf *rect, const float v1[2], const float v2 /* check points in rect */ if (edge_fully_inside_rect(rect, v1, v2)) { - return 1; + return true; } /* check points completely out rect */ if (v1[0] < rect->xmin && v2[0] < rect->xmin) { - return 0; + return false; } if (v1[0] > rect->xmax && v2[0] > rect->xmax) { - return 0; + return false; } if (v1[1] < rect->ymin && v2[1] < rect->ymin) { - return 0; + return false; } if (v1[1] > rect->ymax && v2[1] > rect->ymax) { - return 0; + return false; } /* simple check lines intersecting. */ @@ -495,22 +503,22 @@ static bool edge_inside_rect(const rctf *rect, const float v1[2], const float v2 d4 = (v1[1] - v2[1]) * (v1[0] - rect->xmax) + (v2[0] - v1[0]) * (v1[1] - rect->ymin); if (d1 < 0 && d2 < 0 && d3 < 0 && d4 < 0) { - return 0; + return false; } if (d1 > 0 && d2 > 0 && d3 > 0 && d4 > 0) { - return 0; + return false; } - return 1; + return true; } static void do_lasso_select_pose__do_tag(void *userData, - struct bPoseChannel *pchan, + bPoseChannel *pchan, const float screen_co_a[2], const float screen_co_b[2]) { - LassoSelectUserData *data = userData; - const bArmature *arm = data->vc->obact->data; + LassoSelectUserData *data = static_cast<LassoSelectUserData *>(userData); + const bArmature *arm = static_cast<bArmature *>(data->vc->obact->data); if (!PBONE_SELECTABLE(arm, pchan->bone)) { return; } @@ -531,7 +539,7 @@ static void do_lasso_tag_pose(ViewContext *vc, LassoSelectUserData data; rcti rect; - if ((ob->type != OB_ARMATURE) || (ob->pose == NULL)) { + if ((ob->type != OB_ARMATURE) || (ob->pose == nullptr)) { return; } @@ -540,7 +548,8 @@ static void do_lasso_tag_pose(ViewContext *vc, BLI_lasso_boundbox(&rect, mcoords, mcoords_len); - view3d_userdata_lassoselect_init(&data, vc, &rect, mcoords, mcoords_len, 0); + view3d_userdata_lassoselect_init( + &data, vc, &rect, mcoords, mcoords_len, static_cast<eSelectOp>(0)); ED_view3d_init_mats_rv3d(vc_tmp.obact, vc->rv3d); @@ -557,14 +566,13 @@ static bool do_lasso_select_objects(ViewContext *vc, const eSelectOp sel_op) { View3D *v3d = vc->v3d; - Base *base; bool changed = false; if (SEL_OP_USE_PRE_DESELECT(sel_op)) { - changed |= object_deselect_all_visible(vc->view_layer, vc->v3d); + changed |= object_deselect_all_visible(vc->scene, vc->view_layer, vc->v3d); } - - for (base = vc->view_layer->object_bases.first; base; base = base->next) { + BKE_view_layer_synced_ensure(vc->scene, vc->view_layer); + LISTBASE_FOREACH (Base *, base, BKE_view_layer_object_bases_get(vc->view_layer)) { if (BASE_SELECTABLE(v3d, base)) { /* Use this to avoid unnecessary lasso look-ups. */ const bool is_select = base->flag & BASE_SELECTED; const bool is_inside = ((ED_view3d_project_base(vc->region, base) == V3D_PROJ_RET_OK) && @@ -588,32 +596,32 @@ static bool do_lasso_select_objects(ViewContext *vc, /** * Use for lasso & box select. */ -static Base **do_pose_tag_select_op_prepare(ViewContext *vc, uint *r_bases_len) +static blender::Vector<Base *> do_pose_tag_select_op_prepare(ViewContext *vc) { - Base **bases = NULL; - BLI_array_declare(bases); - FOREACH_BASE_IN_MODE_BEGIN (vc->view_layer, vc->v3d, OB_ARMATURE, OB_MODE_POSE, base_iter) { + blender::Vector<Base *> bases; + + FOREACH_BASE_IN_MODE_BEGIN ( + vc->scene, vc->view_layer, vc->v3d, OB_ARMATURE, OB_MODE_POSE, base_iter) { Object *ob_iter = base_iter->object; - bArmature *arm = ob_iter->data; + bArmature *arm = static_cast<bArmature *>(ob_iter->data); LISTBASE_FOREACH (bPoseChannel *, pchan, &ob_iter->pose->chanbase) { Bone *bone = pchan->bone; bone->flag &= ~BONE_DONE; } arm->id.tag |= LIB_TAG_DOIT; ob_iter->id.tag &= ~LIB_TAG_DOIT; - BLI_array_append(bases, base_iter); + bases.append(base_iter); } FOREACH_BASE_IN_MODE_END; - *r_bases_len = BLI_array_len(bases); return bases; } -static bool do_pose_tag_select_op_exec(Base **bases, const uint bases_len, const eSelectOp sel_op) +static bool do_pose_tag_select_op_exec(blender::MutableSpan<Base *> bases, const eSelectOp sel_op) { bool changed_multi = false; if (SEL_OP_USE_PRE_DESELECT(sel_op)) { - for (int i = 0; i < bases_len; i++) { + for (const int i : bases.index_range()) { Base *base_iter = bases[i]; Object *ob_iter = base_iter->object; if (ED_pose_deselect_all(ob_iter, SEL_DESELECT, false)) { @@ -623,10 +631,10 @@ static bool do_pose_tag_select_op_exec(Base **bases, const uint bases_len, const } } - for (int i = 0; i < bases_len; i++) { + for (const int i : bases.index_range()) { Base *base_iter = bases[i]; Object *ob_iter = base_iter->object; - bArmature *arm = ob_iter->data; + bArmature *arm = static_cast<bArmature *>(ob_iter->data); /* Don't handle twice. */ if (arm->id.tag & LIB_TAG_DOIT) { @@ -647,7 +655,7 @@ static bool do_pose_tag_select_op_exec(Base **bases, const uint bases_len, const SET_FLAG_FROM_TEST(bone->flag, sel_op_result, BONE_SELECTED); if (sel_op_result == 0) { if (arm->act_bone == bone) { - arm->act_bone = NULL; + arm->act_bone = nullptr; } } changed = true; @@ -667,22 +675,20 @@ static bool do_lasso_select_pose(ViewContext *vc, const int mcoords_len, const eSelectOp sel_op) { - uint bases_len; - Base **bases = do_pose_tag_select_op_prepare(vc, &bases_len); + blender::Vector<Base *> bases = do_pose_tag_select_op_prepare(vc); - for (int i = 0; i < bases_len; i++) { + for (const int i : bases.index_range()) { Base *base_iter = bases[i]; Object *ob_iter = base_iter->object; do_lasso_tag_pose(vc, ob_iter, mcoords, mcoords_len); } - const bool changed_multi = do_pose_tag_select_op_exec(bases, bases_len, sel_op); + const bool changed_multi = do_pose_tag_select_op_exec(bases, sel_op); if (changed_multi) { DEG_id_tag_update(&vc->scene->id, ID_RECALC_SELECT); WM_main_add_notifier(NC_SCENE | ND_OB_SELECT, vc->scene); } - MEM_freeN(bases); return changed_multi; } @@ -691,7 +697,7 @@ static void do_lasso_select_mesh__doSelectVert(void *userData, const float screen_co[2], int UNUSED(index)) { - LassoSelectUserData *data = userData; + LassoSelectUserData *data = static_cast<LassoSelectUserData *>(userData); const bool is_select = BM_elem_flag_test(eve, BM_ELEM_SELECT); const bool is_inside = (BLI_rctf_isect_pt_v(data->rect_fl, screen_co) && @@ -705,7 +711,7 @@ static void do_lasso_select_mesh__doSelectVert(void *userData, } struct LassoSelectUserData_ForMeshEdge { LassoSelectUserData *data; - struct EditSelectBuf_Cache *esel; + EditSelectBuf_Cache *esel; uint backbuf_offset; }; static void do_lasso_select_mesh__doSelectEdge_pass0(void *user_data, @@ -714,7 +720,8 @@ static void do_lasso_select_mesh__doSelectEdge_pass0(void *user_data, const float screen_co_b[2], int index) { - struct LassoSelectUserData_ForMeshEdge *data_for_edge = user_data; + LassoSelectUserData_ForMeshEdge *data_for_edge = static_cast<LassoSelectUserData_ForMeshEdge *>( + user_data); LassoSelectUserData *data = data_for_edge->data; bool is_visible = true; if (data_for_edge->backbuf_offset) { @@ -742,7 +749,8 @@ static void do_lasso_select_mesh__doSelectEdge_pass1(void *user_data, const float screen_co_b[2], int index) { - struct LassoSelectUserData_ForMeshEdge *data_for_edge = user_data; + LassoSelectUserData_ForMeshEdge *data_for_edge = static_cast<LassoSelectUserData_ForMeshEdge *>( + user_data); LassoSelectUserData *data = data_for_edge->data; bool is_visible = true; if (data_for_edge->backbuf_offset) { @@ -768,7 +776,7 @@ static void do_lasso_select_mesh__doSelectFace(void *userData, const float screen_co[2], int UNUSED(index)) { - LassoSelectUserData *data = userData; + LassoSelectUserData *data = static_cast<LassoSelectUserData *>(userData); const bool is_select = BM_elem_flag_test(efa, BM_ELEM_SELECT); const bool is_inside = (BLI_rctf_isect_pt_v(data->rect_fl, screen_co) && @@ -812,13 +820,13 @@ static bool do_lasso_select_mesh(ViewContext *vc, const bool use_zbuf = !XRAY_FLAG_ENABLED(vc->v3d); - struct EditSelectBuf_Cache *esel = wm_userdata->data; + EditSelectBuf_Cache *esel = static_cast<EditSelectBuf_Cache *>(wm_userdata->data); if (use_zbuf) { - if (wm_userdata->data == NULL) { + if (wm_userdata->data == nullptr) { editselect_buf_cache_init_with_generic_userdata(wm_userdata, vc, ts->selectmode); - esel = wm_userdata->data; + esel = static_cast<EditSelectBuf_Cache *>(wm_userdata->data); esel->select_bitmap = DRW_select_buffer_bitmap_from_poly( - vc->depsgraph, vc->region, vc->v3d, mcoords, mcoords_len, &rect, NULL); + vc->depsgraph, vc->region, vc->v3d, mcoords, mcoords_len, &rect, nullptr); } } @@ -834,16 +842,15 @@ static bool do_lasso_select_mesh(ViewContext *vc, } if (ts->selectmode & SCE_SELECT_EDGE) { /* Does both use_zbuf and non-use_zbuf versions (need screen cos for both) */ - struct LassoSelectUserData_ForMeshEdge data_for_edge = { - .data = &data, - .esel = use_zbuf ? esel : NULL, - .backbuf_offset = use_zbuf ? DRW_select_buffer_context_offset_for_object_elem( - vc->depsgraph, vc->obedit, SCE_SELECT_EDGE) : - 0, - }; + LassoSelectUserData_ForMeshEdge data_for_edge{}; + data_for_edge.data = &data; + data_for_edge.esel = use_zbuf ? esel : nullptr; + data_for_edge.backbuf_offset = use_zbuf ? DRW_select_buffer_context_offset_for_object_elem( + vc->depsgraph, vc->obedit, SCE_SELECT_EDGE) : + 0; const eV3DProjTest clip_flag = V3D_PROJ_TEST_CLIP_NEAR | - (use_zbuf ? 0 : V3D_PROJ_TEST_CLIP_BB); + (use_zbuf ? (eV3DProjTest)0 : V3D_PROJ_TEST_CLIP_BB); /* Fully inside. */ mesh_foreachScreenEdge_clip_bb_segment( vc, do_lasso_select_mesh__doSelectEdge_pass0, &data_for_edge, clip_flag); @@ -882,7 +889,7 @@ static void do_lasso_select_curve__doSelect(void *userData, bool handles_visible, const float screen_co[2]) { - LassoSelectUserData *data = userData; + LassoSelectUserData *data = static_cast<LassoSelectUserData *>(userData); const bool is_inside = BLI_lasso_is_point_inside( data->mcoords, data->mcoords_len, screen_co[0], screen_co[1], IS_CLIPPED); @@ -948,14 +955,14 @@ static bool do_lasso_select_curve(ViewContext *vc, } if (data.is_changed) { - BKE_curve_nurb_vert_active_validate(vc->obedit->data); + BKE_curve_nurb_vert_active_validate(static_cast<Curve *>(vc->obedit->data)); } return data.is_changed; } static void do_lasso_select_lattice__doSelect(void *userData, BPoint *bp, const float screen_co[2]) { - LassoSelectUserData *data = userData; + LassoSelectUserData *data = static_cast<LassoSelectUserData *>(userData); const bool is_select = bp->f1 & SELECT; const bool is_inside = (BLI_rctf_isect_pt_v(data->rect_fl, screen_co) && @@ -994,8 +1001,8 @@ static void do_lasso_select_armature__doSelectBone(void *userData, const float screen_co_a[2], const float screen_co_b[2]) { - LassoSelectUserData *data = userData; - const bArmature *arm = data->vc->obedit->data; + LassoSelectUserData *data = static_cast<LassoSelectUserData *>(userData); + const bArmature *arm = static_cast<const bArmature *>(data->vc->obedit->data); if (!EBONE_VISIBLE(arm, ebone)) { return; } @@ -1043,8 +1050,8 @@ static void do_lasso_select_armature__doSelectBone_clip_content(void *userData, const float screen_co_a[2], const float screen_co_b[2]) { - LassoSelectUserData *data = userData; - bArmature *arm = data->vc->obedit->data; + LassoSelectUserData *data = static_cast<LassoSelectUserData *>(userData); + bArmature *arm = static_cast<bArmature *>(data->vc->obedit->data); if (!EBONE_VISIBLE(arm, ebone)) { return; } @@ -1083,7 +1090,7 @@ static bool do_lasso_select_armature(ViewContext *vc, data.is_changed |= ED_armature_edit_deselect_all_visible(vc->obedit); } - bArmature *arm = vc->obedit->data; + bArmature *arm = static_cast<bArmature *>(vc->obedit->data); ED_armature_ebone_listbase_temp_clear(arm->edbo); @@ -1101,7 +1108,7 @@ static bool do_lasso_select_armature(ViewContext *vc, &data, V3D_PROJ_TEST_CLIP_DEFAULT | V3D_PROJ_TEST_CLIP_CONTENT_DEFAULT); - data.is_changed |= ED_armature_edit_select_op_from_tagged(vc->obedit->data, sel_op); + data.is_changed |= ED_armature_edit_select_op_from_tagged(arm, sel_op); if (data.is_changed) { WM_main_add_notifier(NC_OBJECT | ND_BONE_SELECT, vc->obedit); @@ -1110,10 +1117,10 @@ static bool do_lasso_select_armature(ViewContext *vc, } static void do_lasso_select_mball__doSelectElem(void *userData, - struct MetaElem *ml, + MetaElem *ml, const float screen_co[2]) { - LassoSelectUserData *data = userData; + LassoSelectUserData *data = static_cast<LassoSelectUserData *>(userData); const bool is_select = ml->flag & SELECT; const bool is_inside = (BLI_rctf_isect_pt_v(data->rect_fl, screen_co) && @@ -1151,20 +1158,27 @@ static bool do_lasso_select_meta(ViewContext *vc, return data.is_changed; } +struct LassoSelectUserData_ForMeshVert { + LassoSelectUserData lasso_data; + blender::MutableSpan<bool> select_vert; +}; static void do_lasso_select_meshobject__doSelectVert(void *userData, - MVert *mv, + MVert * /*mv*/, const float screen_co[2], - int UNUSED(index)) + int index) { - LassoSelectUserData *data = userData; - const bool is_select = mv->flag & SELECT; + using namespace blender; + LassoSelectUserData_ForMeshVert *mesh_data = static_cast<LassoSelectUserData_ForMeshVert *>( + userData); + LassoSelectUserData *data = &mesh_data->lasso_data; + const bool is_select = mesh_data->select_vert[index]; const bool is_inside = (BLI_rctf_isect_pt_v(data->rect_fl, screen_co) && BLI_lasso_is_point_inside( data->mcoords, data->mcoords_len, screen_co[0], screen_co[1], IS_CLIPPED)); const int sel_op_result = ED_select_op_action_deselected(data->sel_op, is_select, is_inside); if (sel_op_result != -1) { - SET_FLAG_FROM_TEST(mv->flag, sel_op_result, SELECT); + mesh_data->select_vert[index] = sel_op_result == 1; data->is_changed = true; } } @@ -1174,12 +1188,13 @@ static bool do_lasso_select_paintvert(ViewContext *vc, const int mcoords_len, const eSelectOp sel_op) { + using namespace blender; const bool use_zbuf = !XRAY_ENABLED(vc->v3d); Object *ob = vc->obact; - Mesh *me = ob->data; + Mesh *me = static_cast<Mesh *>(ob->data); rcti rect; - if (me == NULL || me->totvert == 0) { + if (me == nullptr || me->totvert == 0) { return false; } @@ -1191,32 +1206,38 @@ static bool do_lasso_select_paintvert(ViewContext *vc, BLI_lasso_boundbox(&rect, mcoords, mcoords_len); - struct EditSelectBuf_Cache *esel = wm_userdata->data; + EditSelectBuf_Cache *esel = static_cast<EditSelectBuf_Cache *>(wm_userdata->data); if (use_zbuf) { - if (wm_userdata->data == NULL) { + if (wm_userdata->data == nullptr) { editselect_buf_cache_init_with_generic_userdata(wm_userdata, vc, SCE_SELECT_VERTEX); - esel = wm_userdata->data; + esel = static_cast<EditSelectBuf_Cache *>(wm_userdata->data); esel->select_bitmap = DRW_select_buffer_bitmap_from_poly( - vc->depsgraph, vc->region, vc->v3d, mcoords, mcoords_len, &rect, NULL); + vc->depsgraph, vc->region, vc->v3d, mcoords, mcoords_len, &rect, nullptr); } } if (use_zbuf) { - if (esel->select_bitmap != NULL) { + if (esel->select_bitmap != nullptr) { changed |= edbm_backbuf_check_and_select_verts_obmode(me, esel, sel_op); } } else { - LassoSelectUserData data; + bke::MutableAttributeAccessor attributes = me->attributes_for_write(); + bke::SpanAttributeWriter<bool> select_vert = attributes.lookup_or_add_for_write_span<bool>( + ".select_vert", ATTR_DOMAIN_POINT); + + LassoSelectUserData_ForMeshVert data; + data.select_vert = select_vert.span; - view3d_userdata_lassoselect_init(&data, vc, &rect, mcoords, mcoords_len, sel_op); + view3d_userdata_lassoselect_init(&data.lasso_data, vc, &rect, mcoords, mcoords_len, sel_op); ED_view3d_init_mats_rv3d(vc->obact, vc->rv3d); meshobject_foreachScreenVert( vc, do_lasso_select_meshobject__doSelectVert, &data, V3D_PROJ_TEST_CLIP_DEFAULT); - changed |= data.is_changed; + changed |= data.lasso_data.is_changed; + select_vert.finish(); } if (changed) { @@ -1236,10 +1257,10 @@ static bool do_lasso_select_paintface(ViewContext *vc, const eSelectOp sel_op) { Object *ob = vc->obact; - Mesh *me = ob->data; + Mesh *me = static_cast<Mesh *>(ob->data); rcti rect; - if (me == NULL || me->totpoly == 0) { + if (me == nullptr || me->totpoly == 0) { return false; } @@ -1251,12 +1272,12 @@ static bool do_lasso_select_paintface(ViewContext *vc, BLI_lasso_boundbox(&rect, mcoords, mcoords_len); - struct EditSelectBuf_Cache *esel = wm_userdata->data; - if (esel == NULL) { + EditSelectBuf_Cache *esel = static_cast<EditSelectBuf_Cache *>(wm_userdata->data); + if (esel == nullptr) { editselect_buf_cache_init_with_generic_userdata(wm_userdata, vc, SCE_SELECT_FACE); - esel = wm_userdata->data; + esel = static_cast<EditSelectBuf_Cache *>(wm_userdata->data); esel->select_bitmap = DRW_select_buffer_bitmap_from_poly( - vc->depsgraph, vc->region, vc->v3d, mcoords, mcoords_len, &rect, NULL); + vc->depsgraph, vc->region, vc->v3d, mcoords, mcoords_len, &rect, nullptr); } if (esel->select_bitmap) { @@ -1278,10 +1299,10 @@ static bool view3d_lasso_select(bContext *C, Object *ob = CTX_data_active_object(C); bool changed_multi = false; - wmGenericUserData wm_userdata_buf = {0}; + wmGenericUserData wm_userdata_buf = {nullptr, nullptr, false}; wmGenericUserData *wm_userdata = &wm_userdata_buf; - if (vc->obedit == NULL) { /* Object Mode */ + if (vc->obedit == nullptr) { /* Object Mode */ if (BKE_paint_select_face_test(ob)) { changed_multi |= do_lasso_select_paintface(vc, wm_userdata, mcoords, mcoords_len, sel_op); } @@ -1293,7 +1314,7 @@ static bool view3d_lasso_select(bContext *C, /* pass */ } else if (ob && (ob->mode & OB_MODE_PARTICLE_EDIT)) { - changed_multi |= PE_lasso_select(C, mcoords, mcoords_len, sel_op); + changed_multi |= PE_lasso_select(C, mcoords, mcoords_len, sel_op) != OPERATOR_CANCELLED; } else if (ob && (ob->mode & OB_MODE_POSE)) { changed_multi |= do_lasso_select_pose(vc, mcoords, mcoords_len, sel_op); @@ -1309,7 +1330,8 @@ static bool view3d_lasso_select(bContext *C, } } else { /* Edit Mode */ - FOREACH_OBJECT_IN_MODE_BEGIN (vc->view_layer, vc->v3d, ob->type, ob->mode, ob_iter) { + FOREACH_OBJECT_IN_MODE_BEGIN ( + vc->scene, vc->view_layer, vc->v3d, ob->type, ob->mode, ob_iter) { ED_view3d_viewcontext_init_object(vc, ob_iter); bool changed = false; @@ -1339,7 +1361,7 @@ static bool view3d_lasso_select(bContext *C, } if (changed) { - DEG_id_tag_update(vc->obedit->data, ID_RECALC_SELECT); + DEG_id_tag_update(static_cast<ID *>(vc->obedit->data), ID_RECALC_SELECT); WM_event_add_notifier(C, NC_GEOM | ND_SELECT, vc->obedit->data); changed_multi = true; } @@ -1368,7 +1390,7 @@ static int view3d_lasso_select_exec(bContext *C, wmOperator *op) /* setup view context for argument to callbacks */ ED_view3d_viewcontext_init(C, &vc, depsgraph); - eSelectOp sel_op = RNA_enum_get(op->ptr, "mode"); + eSelectOp sel_op = static_cast<eSelectOp>(RNA_enum_get(op->ptr, "mode")); bool changed_multi = view3d_lasso_select(C, &vc, mcoords, mcoords_len, sel_op); MEM_freeN((void *)mcoords); @@ -1408,12 +1430,12 @@ void VIEW3D_OT_select_lasso(wmOperatorType *ot) * \{ */ /* The max number of menu items in an object select menu */ -typedef struct SelMenuItemF { +struct SelMenuItemF { char idname[MAX_ID_NAME - 2]; int icon; Base *base_ptr; void *item_ptr; -} SelMenuItemF; +}; #define SEL_MENU_SIZE 22 static SelMenuItemF object_mouse_select_menu_data[SEL_MENU_SIZE]; @@ -1424,12 +1446,12 @@ static const EnumPropertyItem *object_select_menu_enum_itemf(bContext *C, PropertyRNA *UNUSED(prop), bool *r_free) { - EnumPropertyItem *item = NULL, item_tmp = {0}; + EnumPropertyItem *item = nullptr, item_tmp = {0}; int totitem = 0; int i = 0; /* Don't need context but avoid API doc-generation using this. */ - if (C == NULL || object_mouse_select_menu_data[i].idname[0] == '\0') { + if (C == nullptr || object_mouse_select_menu_data[i].idname[0] == '\0') { return DummyRNA_NULL_items; } @@ -1457,10 +1479,12 @@ static int object_select_menu_exec(bContext *C, wmOperator *op) const char *name = object_mouse_select_menu_data[name_index].idname; View3D *v3d = CTX_wm_view3d(C); + Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); - const Base *oldbasact = BASACT(view_layer); + BKE_view_layer_synced_ensure(scene, view_layer); + const Base *oldbasact = BKE_view_layer_active_base_get(view_layer); - Base *basact = NULL; + Base *basact = nullptr; CTX_DATA_BEGIN (C, Base *, base, selectable_bases) { /* This is a bit dodgy, there should only be ONE object with this name, * but library objects can mess this up. */ @@ -1471,7 +1495,7 @@ static int object_select_menu_exec(bContext *C, wmOperator *op) } CTX_DATA_END; - if (basact == NULL) { + if (basact == nullptr) { return OPERATOR_CANCELLED; } UNUSED_VARS_NDEBUG(v3d); @@ -1498,7 +1522,7 @@ static int object_select_menu_exec(bContext *C, wmOperator *op) } } else { - object_deselect_all_except(view_layer, basact); + object_deselect_all_except(scene, view_layer, basact); ED_object_base_select(basact, BA_SELECT); changed = true; } @@ -1542,14 +1566,14 @@ void VIEW3D_OT_select_menu(wmOperatorType *ot) /* #Object.id.name to select (dynamic enum). */ prop = RNA_def_enum(ot->srna, "name", DummyRNA_NULL_items, 0, "Object Name", ""); RNA_def_enum_funcs(prop, object_select_menu_enum_itemf); - RNA_def_property_flag(prop, PROP_HIDDEN | PROP_ENUM_NO_TRANSLATE); + RNA_def_property_flag(prop, (PropertyFlag)(PROP_HIDDEN | PROP_ENUM_NO_TRANSLATE)); ot->prop = prop; - prop = RNA_def_boolean(ot->srna, "extend", 0, "Extend", ""); + prop = RNA_def_boolean(ot->srna, "extend", false, "Extend", ""); RNA_def_property_flag(prop, PROP_SKIP_SAVE); - prop = RNA_def_boolean(ot->srna, "deselect", 0, "Deselect", ""); + prop = RNA_def_boolean(ot->srna, "deselect", false, "Deselect", ""); RNA_def_property_flag(prop, PROP_SKIP_SAVE); - prop = RNA_def_boolean(ot->srna, "toggle", 0, "Toggle", ""); + prop = RNA_def_boolean(ot->srna, "toggle", false, "Toggle", ""); RNA_def_property_flag(prop, PROP_SKIP_SAVE); } @@ -1561,12 +1585,12 @@ static bool object_mouse_select_menu(bContext *C, const GPUSelectResult *buffer, const int hits, const int mval[2], - const struct SelectPick_Params *params, + const SelectPick_Params *params, Base **r_basact) { int base_count = 0; bool ok; - LinkNodePair linklist = {NULL, NULL}; + LinkNodePair linklist = {nullptr, nullptr}; /* handle base->object->select_id */ CTX_DATA_BEGIN (C, Base *, base, selectable_bases) { @@ -1603,14 +1627,14 @@ static bool object_mouse_select_menu(bContext *C, } CTX_DATA_END; - *r_basact = NULL; + *r_basact = nullptr; if (base_count == 0) { return false; } if (base_count == 1) { Base *base = (Base *)linklist.list->link; - BLI_linklist_free(linklist.list, NULL); + BLI_linklist_free(linklist.list, nullptr); *r_basact = base; return false; } @@ -1622,7 +1646,7 @@ static bool object_mouse_select_menu(bContext *C, memset(object_mouse_select_menu_data, 0, sizeof(object_mouse_select_menu_data)); for (node = linklist.list, i = 0; node; node = node->next, i++) { - Base *base = node->link; + Base *base = static_cast<Base *>(node->link); Object *ob = base->object; const char *name = ob->id.name + 2; @@ -1637,10 +1661,10 @@ static bool object_mouse_select_menu(bContext *C, RNA_boolean_set(&ptr, "extend", params->sel_op == SEL_OP_ADD); RNA_boolean_set(&ptr, "deselect", params->sel_op == SEL_OP_SUB); RNA_boolean_set(&ptr, "toggle", params->sel_op == SEL_OP_XOR); - WM_operator_name_call_ptr(C, ot, WM_OP_INVOKE_DEFAULT, &ptr, NULL); + WM_operator_name_call_ptr(C, ot, WM_OP_INVOKE_DEFAULT, &ptr, nullptr); WM_operator_properties_free(&ptr); - BLI_linklist_free(linklist.list, NULL); + BLI_linklist_free(linklist.list, nullptr); return true; } @@ -1648,17 +1672,18 @@ static int bone_select_menu_exec(bContext *C, wmOperator *op) { const int name_index = RNA_enum_get(op->ptr, "name"); - const struct SelectPick_Params params = { - .sel_op = ED_select_op_from_operator(op->ptr), - }; + SelectPick_Params params{}; + params.sel_op = ED_select_op_from_operator(op->ptr); View3D *v3d = CTX_wm_view3d(C); + Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); - const Base *oldbasact = BASACT(view_layer); + BKE_view_layer_synced_ensure(scene, view_layer); + const Base *oldbasact = BKE_view_layer_active_base_get(view_layer); Base *basact = object_mouse_select_menu_data[name_index].base_ptr; - if (basact == NULL) { + if (basact == nullptr) { return OPERATOR_CANCELLED; } @@ -1670,7 +1695,8 @@ static int bone_select_menu_exec(bContext *C, wmOperator *op) } else { bPoseChannel *pchan = (bPoseChannel *)object_mouse_select_menu_data[name_index].item_ptr; - ED_armature_pose_select_pick_bone(view_layer, v3d, basact->object, pchan->bone, ¶ms); + ED_armature_pose_select_pick_bone( + scene, view_layer, v3d, basact->object, pchan->bone, ¶ms); } /* Weak but ensures we activate the menu again before using the enum. */ @@ -1694,7 +1720,7 @@ static int bone_select_menu_exec(bContext *C, wmOperator *op) * Selection causes this to be considered the 'active' pose in weight-paint mode. * Eventually this limitation may be removed. * For now, de-select all other pose objects deforming this mesh. */ - ED_armature_pose_select_in_wpaint_mode(view_layer, basact); + ED_armature_pose_select_in_wpaint_mode(scene, view_layer, basact); } else { if (oldbasact != basact) { @@ -1704,7 +1730,6 @@ static int bone_select_menu_exec(bContext *C, wmOperator *op) } /* Undo? */ - Scene *scene = CTX_data_scene(C); DEG_id_tag_update(&scene->id, ID_RECALC_SELECT); DEG_id_tag_update(&scene->id, ID_RECALC_BASE_FLAGS); WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene); @@ -1733,14 +1758,14 @@ void VIEW3D_OT_bone_select_menu(wmOperatorType *ot) /* #Object.id.name to select (dynamic enum). */ prop = RNA_def_enum(ot->srna, "name", DummyRNA_NULL_items, 0, "Bone Name", ""); RNA_def_enum_funcs(prop, object_select_menu_enum_itemf); - RNA_def_property_flag(prop, PROP_HIDDEN | PROP_ENUM_NO_TRANSLATE); + RNA_def_property_flag(prop, (PropertyFlag)(PROP_HIDDEN | PROP_ENUM_NO_TRANSLATE)); ot->prop = prop; - prop = RNA_def_boolean(ot->srna, "extend", 0, "Extend", ""); + prop = RNA_def_boolean(ot->srna, "extend", false, "Extend", ""); RNA_def_property_flag(prop, PROP_SKIP_SAVE); - prop = RNA_def_boolean(ot->srna, "deselect", 0, "Deselect", ""); + prop = RNA_def_boolean(ot->srna, "deselect", false, "Deselect", ""); RNA_def_property_flag(prop, PROP_SKIP_SAVE); - prop = RNA_def_boolean(ot->srna, "toggle", 0, "Toggle", ""); + prop = RNA_def_boolean(ot->srna, "toggle", false, "Toggle", ""); RNA_def_property_flag(prop, PROP_SKIP_SAVE); } @@ -1751,19 +1776,19 @@ static bool bone_mouse_select_menu(bContext *C, const GPUSelectResult *buffer, const int hits, const bool is_editmode, - const struct SelectPick_Params *params) + const SelectPick_Params *params) { BLI_assert(buffer); int bone_count = 0; - LinkNodePair base_list = {NULL, NULL}; - LinkNodePair bone_list = {NULL, NULL}; + LinkNodePair base_list = {nullptr, nullptr}; + LinkNodePair bone_list = {nullptr, nullptr}; GSet *added_bones = BLI_gset_ptr_new("Bone mouse select menu"); /* Select logic taken from ed_armature_pick_bone_from_selectbuffer_impl in armature_select.c */ for (int a = 0; a < hits; a++) { - void *bone_ptr = NULL; - Base *bone_base = NULL; + void *bone_ptr = nullptr; + Base *bone_base = nullptr; uint hitresult = buffer[a].id; if (!(hitresult & BONESEL_ANY)) { @@ -1791,8 +1816,8 @@ static bool bone_mouse_select_menu(bContext *C, if (is_editmode) { EditBone *ebone; const uint hit_bone = (hitresult & ~BONESEL_ANY) >> 16; - bArmature *arm = bone_base->object->data; - ebone = BLI_findlink(arm->edbo, hit_bone); + bArmature *arm = static_cast<bArmature *>(bone_base->object->data); + ebone = static_cast<EditBone *>(BLI_findlink(arm->edbo, hit_bone)); if (ebone && !(ebone->flag & BONE_UNSELECTABLE)) { bone_ptr = ebone; } @@ -1800,7 +1825,8 @@ static bool bone_mouse_select_menu(bContext *C, else { bPoseChannel *pchan; const uint hit_bone = (hitresult & ~BONESEL_ANY) >> 16; - pchan = BLI_findlink(&bone_base->object->pose->chanbase, hit_bone); + pchan = static_cast<bPoseChannel *>( + BLI_findlink(&bone_base->object->pose->chanbase, hit_bone)); if (pchan && !(pchan->bone->flag & BONE_UNSELECTABLE)) { bone_ptr = pchan; } @@ -1825,14 +1851,14 @@ static bool bone_mouse_select_menu(bContext *C, } } - BLI_gset_free(added_bones, NULL); + BLI_gset_free(added_bones, nullptr); if (bone_count == 0) { return false; } if (bone_count == 1) { - BLI_linklist_free(base_list.list, NULL); - BLI_linklist_free(bone_list.list, NULL); + BLI_linklist_free(base_list.list, nullptr); + BLI_linklist_free(bone_list.list, nullptr); return false; } @@ -1846,15 +1872,15 @@ static bool bone_mouse_select_menu(bContext *C, base_node = base_node->next, bone_node = bone_node->next, i++) { char *name; - object_mouse_select_menu_data[i].base_ptr = base_node->link; + object_mouse_select_menu_data[i].base_ptr = static_cast<Base *>(base_node->link); if (is_editmode) { - EditBone *ebone = bone_node->link; + EditBone *ebone = static_cast<EditBone *>(bone_node->link); object_mouse_select_menu_data[i].item_ptr = ebone; name = ebone->name; } else { - bPoseChannel *pchan = bone_node->link; + bPoseChannel *pchan = static_cast<bPoseChannel *>(bone_node->link); object_mouse_select_menu_data[i].item_ptr = pchan; name = pchan->name; } @@ -1870,11 +1896,11 @@ static bool bone_mouse_select_menu(bContext *C, RNA_boolean_set(&ptr, "extend", params->sel_op == SEL_OP_ADD); RNA_boolean_set(&ptr, "deselect", params->sel_op == SEL_OP_SUB); RNA_boolean_set(&ptr, "toggle", params->sel_op == SEL_OP_XOR); - WM_operator_name_call_ptr(C, ot, WM_OP_INVOKE_DEFAULT, &ptr, NULL); + WM_operator_name_call_ptr(C, ot, WM_OP_INVOKE_DEFAULT, &ptr, nullptr); WM_operator_properties_free(&ptr); - BLI_linklist_free(base_list.list, NULL); - BLI_linklist_free(bone_list.list, NULL); + BLI_linklist_free(base_list.list, nullptr); + BLI_linklist_free(bone_list.list, nullptr); return true; } @@ -1932,7 +1958,7 @@ static int mixed_bones_object_selectbuffer(ViewContext *vc, int hits15, hits9 = 0, hits5 = 0; bool has_bones15 = false, has_bones9 = false, has_bones5 = false; - int select_mode = (do_nearest ? VIEW3D_SELECT_PICK_NEAREST : VIEW3D_SELECT_PICK_ALL); + eV3DSelectMode select_mode = (do_nearest ? VIEW3D_SELECT_PICK_NEAREST : VIEW3D_SELECT_PICK_ALL); int hits = 0; if (do_nearest_xray_if_supported) { @@ -2088,7 +2114,7 @@ static int gpu_select_buffer_depth_id_cmp(const void *sel_a_p, const void *sel_b * that are visible but not select-able, * since you may be in pose mode with an un-selectable object. * - * \return the active base or NULL. + * \return the active base or nullptr. */ static Base *mouse_select_eval_buffer(ViewContext *vc, const GPUSelectResult *buffer, @@ -2098,6 +2124,7 @@ static Base *mouse_select_eval_buffer(ViewContext *vc, bool do_bones_get_priotity, int *r_select_id_subelem) { + Scene *scene = vc->scene; ViewLayer *view_layer = vc->view_layer; View3D *v3d = vc->v3d; int a; @@ -2140,7 +2167,8 @@ static Base *mouse_select_eval_buffer(ViewContext *vc, else { { - GPUSelectResult *buffer_sorted = MEM_mallocN(sizeof(*buffer_sorted) * hits, __func__); + GPUSelectResult *buffer_sorted = static_cast<GPUSelectResult *>( + MEM_mallocN(sizeof(*buffer_sorted) * hits, __func__)); memcpy(buffer_sorted, buffer, sizeof(*buffer_sorted) * hits); /* Remove non-bone objects. */ if (has_bones && do_bones_get_priotity) { @@ -2160,8 +2188,10 @@ static Base *mouse_select_eval_buffer(ViewContext *vc, /* It's possible there are no hits (all objects contained bones). */ if (hits > 0) { /* Only exclude active object when it is selected. */ - if (BASACT(view_layer) && (BASACT(view_layer)->flag & BASE_SELECTED)) { - const int select_id_active = BASACT(view_layer)->object->runtime.select_id; + BKE_view_layer_synced_ensure(scene, view_layer); + Base *base = BKE_view_layer_active_base_get(view_layer); + if (base && (base->flag & BASE_SELECTED)) { + const int select_id_active = base->object->runtime.select_id; for (int i_next = 0, i_prev = hits - 1; i_next < hits; i_prev = i_next++) { if ((select_id_active == (buffer[i_prev].id & 0xFFFF)) && (select_id_active != (buffer[i_next].id & 0xFFFF))) { @@ -2186,9 +2216,10 @@ static Base *mouse_select_eval_buffer(ViewContext *vc, MEM_freeN((void *)buffer); } - Base *basact = NULL; + Base *basact = nullptr; if (found) { - for (Base *base = FIRSTBASE(view_layer); base; base = base->next) { + BKE_view_layer_synced_ensure(scene, view_layer); + LISTBASE_FOREACH (Base *, base, BKE_view_layer_object_bases_get(view_layer)) { if (has_bones ? BASE_VISIBLE(v3d, base) : BASE_SELECTABLE(v3d, base)) { if (base->object->runtime.select_id == select_id) { basact = base; @@ -2208,14 +2239,16 @@ static Base *mouse_select_eval_buffer(ViewContext *vc, static Base *mouse_select_object_center(ViewContext *vc, Base *startbase, const int mval[2]) { ARegion *region = vc->region; + Scene *scene = vc->scene; ViewLayer *view_layer = vc->view_layer; View3D *v3d = vc->v3d; - Base *oldbasact = BASACT(view_layer); + BKE_view_layer_synced_ensure(scene, view_layer); + Base *oldbasact = BKE_view_layer_active_base_get(view_layer); const float mval_fl[2] = {(float)mval[0], (float)mval[1]}; float dist = ED_view3d_select_dist_px() * 1.3333f; - Base *basact = NULL; + Base *basact = nullptr; /* Put the active object at a disadvantage to cycle through other objects. */ const float penalty_dist = 10.0f * UI_DPI_FAC; @@ -2238,8 +2271,8 @@ static Base *mouse_select_object_center(ViewContext *vc, Base *startbase, const } base = base->next; - if (base == NULL) { - base = FIRSTBASE(view_layer); + if (base == nullptr) { + base = static_cast<Base *>(BKE_view_layer_object_bases_get(view_layer)->first); } if (base == startbase) { break; @@ -2254,7 +2287,7 @@ static Base *ed_view3d_give_base_under_cursor_ex(bContext *C, { Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C); ViewContext vc; - Base *basact = NULL; + Base *basact = nullptr; GPUSelectResult buffer[MAXPICKELEMS]; /* setup view context for argument to callbacks */ @@ -2264,7 +2297,7 @@ static Base *ed_view3d_give_base_under_cursor_ex(bContext *C, ED_view3d_viewcontext_init(C, &vc, depsgraph); const bool do_nearest = !XRAY_ACTIVE(vc.v3d); - const bool do_material_slot_selection = r_material_slot != NULL; + const bool do_material_slot_selection = r_material_slot != nullptr; const int hits = mixed_bones_object_selectbuffer(&vc, buffer, ARRAY_SIZE(buffer), @@ -2275,7 +2308,7 @@ static Base *ed_view3d_give_base_under_cursor_ex(bContext *C, do_material_slot_selection); if (hits > 0) { - const bool has_bones = (r_material_slot == NULL) && selectbuffer_has_bones(buffer, hits); + const bool has_bones = (r_material_slot == nullptr) && selectbuffer_has_bones(buffer, hits); basact = mouse_select_eval_buffer( &vc, buffer, hits, do_nearest, has_bones, true, r_material_slot); } @@ -2285,7 +2318,7 @@ static Base *ed_view3d_give_base_under_cursor_ex(bContext *C, Base *ED_view3d_give_base_under_cursor(bContext *C, const int mval[2]) { - return ed_view3d_give_base_under_cursor_ex(C, mval, NULL); + return ed_view3d_give_base_under_cursor_ex(C, mval, nullptr); } Object *ED_view3d_give_object_under_cursor(bContext *C, const int mval[2]) @@ -2294,33 +2327,33 @@ Object *ED_view3d_give_object_under_cursor(bContext *C, const int mval[2]) if (base) { return base->object; } - return NULL; + return nullptr; } -struct Object *ED_view3d_give_material_slot_under_cursor(struct bContext *C, - const int mval[2], - int *r_material_slot) +Object *ED_view3d_give_material_slot_under_cursor(bContext *C, + const int mval[2], + int *r_material_slot) { Base *base = ed_view3d_give_base_under_cursor_ex(C, mval, r_material_slot); if (base) { return base->object; } - return NULL; + return nullptr; } bool ED_view3d_is_object_under_cursor(bContext *C, const int mval[2]) { - return ED_view3d_give_object_under_cursor(C, mval) != NULL; + return ED_view3d_give_object_under_cursor(C, mval) != nullptr; } static void deselect_all_tracks(MovieTracking *tracking) { MovieTrackingObject *object; - object = tracking->objects.first; + object = static_cast<MovieTrackingObject *>(tracking->objects.first); while (object) { ListBase *tracksbase = BKE_tracking_object_get_tracks(tracking, object); - MovieTrackingTrack *track = tracksbase->first; + MovieTrackingTrack *track = static_cast<MovieTrackingTrack *>(tracksbase->first); while (track) { BKE_tracking_track_deselect(track, TRACK_AREA_ALL); @@ -2336,16 +2369,16 @@ static bool ed_object_select_pick_camera_track(bContext *C, Scene *scene, Base *basact, MovieClip *clip, - const struct GPUSelectResult *buffer, + const GPUSelectResult *buffer, const short hits, - const struct SelectPick_Params *params) + const SelectPick_Params *params) { bool changed = false; bool found = false; MovieTracking *tracking = &clip->tracking; - ListBase *tracksbase = NULL; - MovieTrackingTrack *track = NULL; + ListBase *tracksbase = nullptr; + MovieTrackingTrack *track = nullptr; for (int i = 0; i < hits; i++) { const int hitresult = buffer[i].id; @@ -2433,7 +2466,7 @@ static bool ed_object_select_pick_camera_track(bContext *C, */ static bool ed_object_select_pick(bContext *C, const int mval[2], - const struct SelectPick_Params *params, + const SelectPick_Params *params, const bool center, const bool enumerate, const bool object_only) @@ -2447,21 +2480,21 @@ static bool ed_object_select_pick(bContext *C, View3D *v3d = vc.v3d; /* Menu activation may find a base to make active (if it only finds a single item to select). */ - Base *basact_override = NULL; + Base *basact_override = nullptr; - const bool is_obedit = (vc.obedit != NULL); + const bool is_obedit = (vc.obedit != nullptr); if (object_only) { /* Signal for #view3d_opengl_select to skip edit-mode objects. */ - vc.obedit = NULL; + vc.obedit = nullptr; } - /* Set for GPU depth buffer picking, leave NULL when selecting by center. */ - struct { + /* Set for GPU depth buffer picking, leave null when selecting by center. */ + struct GPUData { GPUSelectResult buffer[MAXPICKELEMS]; int hits; bool do_nearest; bool has_bones; - } *gpu = NULL; + } *gpu = nullptr; /* First handle menu selection, early exit if a menu opens * since this takes ownership of the selection action. @@ -2470,7 +2503,7 @@ static bool ed_object_select_pick(bContext *C, * the item under the cursor. */ if (center == false) { - gpu = MEM_mallocN(sizeof(*gpu), __func__); + gpu = MEM_new<GPUData>(__func__); gpu->do_nearest = false; gpu->has_bones = false; @@ -2497,7 +2530,7 @@ static bool ed_object_select_pick(bContext *C, if (enumerate) { bool has_menu = false; if (center) { - if (object_mouse_select_menu(C, &vc, NULL, 0, mval, params, &basact_override)) { + if (object_mouse_select_menu(C, &vc, nullptr, 0, mval, params, &basact_override)) { has_menu = true; } } @@ -2515,7 +2548,7 @@ static bool ed_object_select_pick(bContext *C, /* Let the menu handle any further actions. */ if (has_menu) { - if (gpu != NULL) { + if (gpu != nullptr) { MEM_freeN(gpu); } return false; @@ -2525,14 +2558,18 @@ static bool ed_object_select_pick(bContext *C, /* No menu, continue with selection. */ ViewLayer *view_layer = vc.view_layer; + BKE_view_layer_synced_ensure(scene, view_layer); /* Don't set when the context has no active object (hidden), see: T60807. */ - const Base *oldbasact = vc.obact ? BASACT(view_layer) : NULL; + const Base *oldbasact = vc.obact ? BKE_view_layer_active_base_get(view_layer) : nullptr; /* Always start list from `basact` when cycling the selection. */ - Base *startbase = (oldbasact && oldbasact->next) ? oldbasact->next : FIRSTBASE(view_layer); + Base *startbase = (oldbasact && oldbasact->next) ? + oldbasact->next : + static_cast<Base *>(BKE_view_layer_object_bases_get(view_layer)->first); /* The next object's base to make active. */ - Base *basact = NULL; - const eObjectMode object_mode = oldbasact ? oldbasact->object->mode : OB_MODE_OBJECT; + Base *basact = nullptr; + const eObjectMode object_mode = oldbasact ? static_cast<eObjectMode>(oldbasact->object->mode) : + OB_MODE_OBJECT; /* When enabled, don't attempt any further selection. */ bool handled = false; @@ -2579,8 +2616,8 @@ static bool ed_object_select_pick(bContext *C, gpu->do_nearest, gpu->has_bones, do_bones_get_priotity, - NULL) : - NULL; + nullptr) : + nullptr; } /* Select pose-bones or camera-tracks. */ @@ -2590,7 +2627,7 @@ static bool ed_object_select_pick(bContext *C, if (basact && (gpu->has_bones && (basact->object->type == OB_CAMERA))) { MovieClip *clip = BKE_object_movieclip_get(scene, basact->object, false); - if (clip != NULL) { + if (clip != nullptr) { if (ed_object_select_pick_camera_track( C, scene, basact, clip, gpu->buffer, gpu->hits, params)) { ED_object_base_select(basact, BA_SELECT); @@ -2603,11 +2640,12 @@ static bool ed_object_select_pick(bContext *C, /* Fallback to regular object selection if no new bundles were selected, * allows to select object parented to reconstruction object. */ basact = mouse_select_eval_buffer( - &vc, gpu->buffer, gpu->hits, gpu->do_nearest, false, false, NULL); + &vc, gpu->buffer, gpu->hits, gpu->do_nearest, false, false, nullptr); } } } - else if (ED_armature_pose_select_pick_with_buffer(view_layer, + else if (ED_armature_pose_select_pick_with_buffer(scene, + view_layer, v3d, basact ? basact : (Base *)oldbasact, gpu->buffer, @@ -2620,7 +2658,7 @@ static bool ed_object_select_pick(bContext *C, /* When there is no `baseact` this will have operated on `oldbasact`, * allowing #SelectPick_Params.deselect_all work in pose-mode. * In this case no object operations are needed. */ - if (basact != NULL) { + if (basact != nullptr) { /* By convention the armature-object is selected when in pose-mode. * While leaving it unselected will work, leaving pose-mode would leave the object * active + unselected which isn't ideal when performing other actions on the object. */ @@ -2638,7 +2676,7 @@ static bool ed_object_select_pick(bContext *C, * Selection causes this to be considered the 'active' pose in weight-paint mode. * Eventually this limitation may be removed. * For now, de-select all other pose objects deforming this mesh. */ - ED_armature_pose_select_in_wpaint_mode(view_layer, basact); + ED_armature_pose_select_in_wpaint_mode(scene, view_layer, basact); handled = true; } @@ -2675,11 +2713,11 @@ static bool ed_object_select_pick(bContext *C, if (is_obedit == false) { if (basact && !BKE_object_is_mode_compat(basact->object, object_mode)) { if (object_mode == OB_MODE_OBJECT) { - struct Main *bmain = vc.bmain; + Main *bmain = vc.bmain; ED_object_mode_generic_exit(bmain, vc.depsgraph, scene, basact->object); } if (!BKE_object_is_mode_compat(basact->object, object_mode)) { - basact = NULL; + basact = nullptr; } } @@ -2688,7 +2726,7 @@ static bool ed_object_select_pick(bContext *C, if (basact && oldbasact) { if ((oldbasact->object->mode != basact->object->mode) && (oldbasact->object->mode & basact->object->mode) == 0) { - basact = NULL; + basact = nullptr; } } } @@ -2697,10 +2735,10 @@ static bool ed_object_select_pick(bContext *C, /* Ensure code above doesn't change the active base. This code is already fairly involved, * it's best if changing the active object is localized to a single place. */ - BLI_assert(oldbasact == (vc.obact ? BASACT(view_layer) : NULL)); + BLI_assert(oldbasact == (vc.obact ? BKE_view_layer_active_base_get(view_layer) : nullptr)); - bool found = (basact != NULL); - if ((handled == false) && (vc.obedit == NULL)) { + bool found = (basact != nullptr); + if ((handled == false) && (vc.obedit == nullptr)) { /* Object-mode (pose mode will have been handled already). */ if (params->sel_op == SEL_OP_SET) { if ((found && params->select_passthrough) && (basact->flag & BASE_SELECTED)) { @@ -2708,8 +2746,8 @@ static bool ed_object_select_pick(bContext *C, } else if (found || params->deselect_all) { /* Deselect everything. */ - /* `basact` may be NULL. */ - if (object_deselect_all_except(view_layer, basact)) { + /* `basact` may be nullptr. */ + if (object_deselect_all_except(scene, view_layer, basact)) { changed_object = true; } } @@ -2721,7 +2759,7 @@ static bool ed_object_select_pick(bContext *C, if (vc.obedit) { /* Only do the select (use for setting vertex parents & hooks). * In edit-mode do not activate. */ - object_deselect_all_except(view_layer, basact); + object_deselect_all_except(scene, view_layer, basact); ED_object_base_select(basact, BA_SELECT); changed_object = true; @@ -2752,7 +2790,7 @@ static bool ed_object_select_pick(bContext *C, break; } case SEL_OP_SET: { - object_deselect_all_except(view_layer, basact); + object_deselect_all_except(scene, view_layer, basact); ED_object_base_select(basact, BA_SELECT); break; } @@ -2768,7 +2806,7 @@ static bool ed_object_select_pick(bContext *C, /* Perform the activation even when 'handled', since this is used to ensure * the object from the pose-bone selected is also activated. */ - if (use_activate_selected_base && (basact != NULL)) { + if (use_activate_selected_base && (basact != nullptr)) { changed_object = true; ED_object_base_activate(C, basact); /* adds notifier */ if ((scene->toolsettings->object_flag & SCE_OBJECT_MODE_LOCK) == 0) { @@ -2787,7 +2825,7 @@ static bool ed_object_select_pick(bContext *C, ED_outliner_select_sync_from_pose_bone_tag(C); } - if (gpu != NULL) { + if (gpu != nullptr) { MEM_freeN(gpu); } @@ -2802,21 +2840,25 @@ static bool ed_object_select_pick(bContext *C, */ static bool ed_wpaint_vertex_select_pick(bContext *C, const int mval[2], - const struct SelectPick_Params *params, + const SelectPick_Params *params, Object *obact) { + using namespace blender; View3D *v3d = CTX_wm_view3d(C); const bool use_zbuf = !XRAY_ENABLED(v3d); - Mesh *me = obact->data; /* already checked for NULL */ + Mesh *me = static_cast<Mesh *>(obact->data); /* already checked for nullptr */ uint index = 0; - MVert *mv; bool changed = false; bool found = ED_mesh_pick_vert(C, obact, mval, ED_MESH_PICK_DEFAULT_VERT_DIST, use_zbuf, &index); + bke::MutableAttributeAccessor attributes = me->attributes_for_write(); + bke::AttributeWriter<bool> select_vert = attributes.lookup_or_add_for_write<bool>( + ".select_vert", ATTR_DOMAIN_POINT); + if (params->sel_op == SEL_OP_SET) { - if ((found && params->select_passthrough) && (me->mvert[index].flag & SELECT)) { + if ((found && params->select_passthrough) && select_vert.varray[index]) { found = false; } else if (found || params->deselect_all) { @@ -2826,23 +2868,22 @@ static bool ed_wpaint_vertex_select_pick(bContext *C, } if (found) { - mv = &me->mvert[index]; switch (params->sel_op) { case SEL_OP_ADD: { - mv->flag |= SELECT; + select_vert.varray.set(index, true); break; } case SEL_OP_SUB: { - mv->flag &= ~SELECT; + select_vert.varray.set(index, false); break; } case SEL_OP_XOR: { - mv->flag ^= SELECT; + select_vert.varray.set(index, !select_vert.varray[index]); break; } case SEL_OP_SET: { paintvert_deselect_all_visible(obact, SEL_DESELECT, false); - mv->flag |= SELECT; + select_vert.varray.set(index, true); break; } case SEL_OP_AND: { @@ -2852,13 +2893,15 @@ static bool ed_wpaint_vertex_select_pick(bContext *C, } /* update mselect */ - if (mv->flag & SELECT) { + if (select_vert.varray[index]) { BKE_mesh_mselect_active_set(me, index, ME_VSEL); } else { BKE_mesh_mselect_validate(me); } + select_vert.finish(); + paintvert_flush_flags(obact); changed = true; @@ -2877,7 +2920,7 @@ static int view3d_select_exec(bContext *C, wmOperator *op) Object *obedit = CTX_data_edit_object(C); Object *obact = CTX_data_active_object(C); - struct SelectPick_Params params = {0}; + SelectPick_Params params{}; ED_select_pick_params_from_operator(op->ptr, ¶ms); const bool vert_without_handles = RNA_boolean_get(op->ptr, "vert_without_handles"); @@ -2898,8 +2941,8 @@ static int view3d_select_exec(bContext *C, wmOperator *op) int mval[2]; if (object_only) { - obedit = NULL; - obact = NULL; + obedit = nullptr; + obact = nullptr; /* ack, this is incorrect but to do this correctly we would need an * alternative edit-mode/object-mode keymap, this copies the functionality @@ -3011,21 +3054,25 @@ void VIEW3D_OT_select(wmOperatorType *ot) prop = RNA_def_boolean( ot->srna, "center", - 0, + false, "Center", "Use the object center when selecting, in edit mode used to extend object selection"); RNA_def_property_flag(prop, PROP_SKIP_SAVE); - prop = RNA_def_boolean( - ot->srna, "enumerate", 0, "Enumerate", "List objects under the mouse (object mode only)"); + prop = RNA_def_boolean(ot->srna, + "enumerate", + false, + "Enumerate", + "List objects under the mouse (object mode only)"); RNA_def_property_flag(prop, PROP_SKIP_SAVE); - prop = RNA_def_boolean(ot->srna, "object", 0, "Object", "Use object selection (edit mode only)"); + prop = RNA_def_boolean( + ot->srna, "object", false, "Object", "Use object selection (edit mode only)"); RNA_def_property_flag(prop, PROP_SKIP_SAVE); /* Needed for select-through to usefully drag handles, see: T98254. * NOTE: this option may be removed and become default behavior, see design task: T98552. */ prop = RNA_def_boolean(ot->srna, "vert_without_handles", - 0, + false, "Control Point Without Handles", "Only select the curve control point, not it's handles"); RNA_def_property_flag(prop, PROP_SKIP_SAVE); @@ -3033,7 +3080,7 @@ void VIEW3D_OT_select(wmOperatorType *ot) prop = RNA_def_int_vector(ot->srna, "location", 2, - NULL, + nullptr, INT_MIN, INT_MAX, "Location", @@ -3049,7 +3096,7 @@ void VIEW3D_OT_select(wmOperatorType *ot) /** \name Box Select * \{ */ -typedef struct BoxSelectUserData { +struct BoxSelectUserData { ViewContext *vc; const rcti *rect; const rctf *rect_fl; @@ -3060,7 +3107,7 @@ typedef struct BoxSelectUserData { /* runtime */ bool is_done; bool is_changed; -} BoxSelectUserData; +}; static void view3d_userdata_boxselect_init(BoxSelectUserData *r_data, ViewContext *vc, @@ -3075,7 +3122,7 @@ static void view3d_userdata_boxselect_init(BoxSelectUserData *r_data, r_data->sel_op = sel_op; /* SELECT by default, but can be changed if needed (only few cases use and respect this). */ - r_data->select_flag = SELECT; + r_data->select_flag = (eBezTriple_Flag)SELECT; /* runtime */ r_data->is_done = false; @@ -3091,17 +3138,23 @@ bool edge_inside_circle(const float cent[2], return (dist_squared_to_line_segment_v2(cent, screen_co_a, screen_co_b) < radius_squared); } +struct BoxSelectUserData_ForMeshVert { + BoxSelectUserData box_data; + blender::MutableSpan<bool> select_vert; +}; static void do_paintvert_box_select__doSelectVert(void *userData, - MVert *mv, + MVert * /*mv*/, const float screen_co[2], - int UNUSED(index)) + int index) { - BoxSelectUserData *data = userData; - const bool is_select = mv->flag & SELECT; + BoxSelectUserData_ForMeshVert *mesh_data = static_cast<BoxSelectUserData_ForMeshVert *>( + userData); + BoxSelectUserData *data = &mesh_data->box_data; + const bool is_select = mesh_data->select_vert[index]; const bool is_inside = BLI_rctf_isect_pt_v(data->rect_fl, screen_co); const int sel_op_result = ED_select_op_action_deselected(data->sel_op, is_select, is_inside); if (sel_op_result != -1) { - SET_FLAG_FROM_TEST(mv->flag, sel_op_result, SELECT); + mesh_data->select_vert[index] = sel_op_result == 1; data->is_changed = true; } } @@ -3110,13 +3163,12 @@ static bool do_paintvert_box_select(ViewContext *vc, const rcti *rect, const eSelectOp sel_op) { + using namespace blender; const bool use_zbuf = !XRAY_ENABLED(vc->v3d); - Mesh *me; - - me = vc->obact->data; - if ((me == NULL) || (me->totvert == 0)) { - return OPERATOR_CANCELLED; + Mesh *me = static_cast<Mesh *>(vc->obact->data); + if ((me == nullptr) || (me->totvert == 0)) { + return false; } bool changed = false; @@ -3128,27 +3180,33 @@ static bool do_paintvert_box_select(ViewContext *vc, /* pass */ } else if (use_zbuf) { - struct EditSelectBuf_Cache *esel = wm_userdata->data; - if (wm_userdata->data == NULL) { + EditSelectBuf_Cache *esel = static_cast<EditSelectBuf_Cache *>(wm_userdata->data); + if (wm_userdata->data == nullptr) { editselect_buf_cache_init_with_generic_userdata(wm_userdata, vc, SCE_SELECT_VERTEX); - esel = wm_userdata->data; + esel = static_cast<EditSelectBuf_Cache *>(wm_userdata->data); esel->select_bitmap = DRW_select_buffer_bitmap_from_rect( - vc->depsgraph, vc->region, vc->v3d, rect, NULL); + vc->depsgraph, vc->region, vc->v3d, rect, nullptr); } - if (esel->select_bitmap != NULL) { + if (esel->select_bitmap != nullptr) { changed |= edbm_backbuf_check_and_select_verts_obmode(me, esel, sel_op); } } else { - BoxSelectUserData data; + bke::MutableAttributeAccessor attributes = me->attributes_for_write(); + bke::SpanAttributeWriter<bool> select_vert = attributes.lookup_or_add_for_write_span<bool>( + ".select_vert", ATTR_DOMAIN_POINT); + + BoxSelectUserData_ForMeshVert data; + data.select_vert = select_vert.span; - view3d_userdata_boxselect_init(&data, vc, rect, sel_op); + view3d_userdata_boxselect_init(&data.box_data, vc, rect, sel_op); ED_view3d_init_mats_rv3d(vc->obact, vc->rv3d); meshobject_foreachScreenVert( vc, do_paintvert_box_select__doSelectVert, &data, V3D_PROJ_TEST_CLIP_DEFAULT); - changed |= data.is_changed; + changed |= data.box_data.is_changed; + select_vert.finish(); } if (changed) { @@ -3164,13 +3222,13 @@ static bool do_paintvert_box_select(ViewContext *vc, static bool do_paintface_box_select(ViewContext *vc, wmGenericUserData *wm_userdata, const rcti *rect, - int sel_op) + eSelectOp sel_op) { Object *ob = vc->obact; Mesh *me; me = BKE_mesh_from_object(ob); - if ((me == NULL) || (me->totpoly == 0)) { + if ((me == nullptr) || (me->totpoly == 0)) { return false; } @@ -3183,14 +3241,14 @@ static bool do_paintface_box_select(ViewContext *vc, /* pass */ } else { - struct EditSelectBuf_Cache *esel = wm_userdata->data; - if (wm_userdata->data == NULL) { + EditSelectBuf_Cache *esel = static_cast<EditSelectBuf_Cache *>(wm_userdata->data); + if (wm_userdata->data == nullptr) { editselect_buf_cache_init_with_generic_userdata(wm_userdata, vc, SCE_SELECT_FACE); - esel = wm_userdata->data; + esel = static_cast<EditSelectBuf_Cache *>(wm_userdata->data); esel->select_bitmap = DRW_select_buffer_bitmap_from_rect( - vc->depsgraph, vc->region, vc->v3d, rect, NULL); + vc->depsgraph, vc->region, vc->v3d, rect, nullptr); } - if (esel->select_bitmap != NULL) { + if (esel->select_bitmap != nullptr) { changed |= edbm_backbuf_check_and_select_faces_obmode(me, esel, sel_op); } } @@ -3209,7 +3267,7 @@ static void do_nurbs_box_select__doSelect(void *userData, bool handles_visible, const float screen_co[2]) { - BoxSelectUserData *data = userData; + BoxSelectUserData *data = static_cast<BoxSelectUserData *>(userData); const bool is_inside = BLI_rctf_isect_pt_v(data->rect_fl, screen_co); if (bp) { @@ -3266,14 +3324,14 @@ static bool do_nurbs_box_select(ViewContext *vc, rcti *rect, const eSelectOp sel data.is_changed |= BKE_nurbList_flag_set_from_flag(nurbs, BEZT_FLAG_TEMP_TAG, SELECT); } - BKE_curve_nurb_vert_active_validate(vc->obedit->data); + BKE_curve_nurb_vert_active_validate(curve); return data.is_changed; } static void do_lattice_box_select__doSelect(void *userData, BPoint *bp, const float screen_co[2]) { - BoxSelectUserData *data = userData; + BoxSelectUserData *data = static_cast<BoxSelectUserData *>(userData); const bool is_select = bp->f1 & SELECT; const bool is_inside = BLI_rctf_isect_pt_v(data->rect_fl, screen_co); const int sel_op_result = ED_select_op_action_deselected(data->sel_op, is_select, is_inside); @@ -3304,7 +3362,7 @@ static void do_mesh_box_select__doSelectVert(void *userData, const float screen_co[2], int UNUSED(index)) { - BoxSelectUserData *data = userData; + BoxSelectUserData *data = static_cast<BoxSelectUserData *>(userData); const bool is_select = BM_elem_flag_test(eve, BM_ELEM_SELECT); const bool is_inside = BLI_rctf_isect_pt_v(data->rect_fl, screen_co); const int sel_op_result = ED_select_op_action_deselected(data->sel_op, is_select, is_inside); @@ -3315,7 +3373,7 @@ static void do_mesh_box_select__doSelectVert(void *userData, } struct BoxSelectUserData_ForMeshEdge { BoxSelectUserData *data; - struct EditSelectBuf_Cache *esel; + EditSelectBuf_Cache *esel; uint backbuf_offset; }; /** @@ -3324,7 +3382,8 @@ struct BoxSelectUserData_ForMeshEdge { static void do_mesh_box_select__doSelectEdge_pass0( void *userData, BMEdge *eed, const float screen_co_a[2], const float screen_co_b[2], int index) { - struct BoxSelectUserData_ForMeshEdge *data_for_edge = userData; + BoxSelectUserData_ForMeshEdge *data_for_edge = static_cast<BoxSelectUserData_ForMeshEdge *>( + userData); BoxSelectUserData *data = data_for_edge->data; bool is_visible = true; if (data_for_edge->backbuf_offset) { @@ -3348,7 +3407,8 @@ static void do_mesh_box_select__doSelectEdge_pass0( static void do_mesh_box_select__doSelectEdge_pass1( void *userData, BMEdge *eed, const float screen_co_a[2], const float screen_co_b[2], int index) { - struct BoxSelectUserData_ForMeshEdge *data_for_edge = userData; + BoxSelectUserData_ForMeshEdge *data_for_edge = static_cast<BoxSelectUserData_ForMeshEdge *>( + userData); BoxSelectUserData *data = data_for_edge->data; bool is_visible = true; if (data_for_edge->backbuf_offset) { @@ -3369,7 +3429,7 @@ static void do_mesh_box_select__doSelectFace(void *userData, const float screen_co[2], int UNUSED(index)) { - BoxSelectUserData *data = userData; + BoxSelectUserData *data = static_cast<BoxSelectUserData *>(userData); const bool is_select = BM_elem_flag_test(efa, BM_ELEM_SELECT); const bool is_inside = BLI_rctf_isect_pt_v(data->rect_fl, screen_co); const int sel_op_result = ED_select_op_action_deselected(data->sel_op, is_select, is_inside); @@ -3402,13 +3462,13 @@ static bool do_mesh_box_select(ViewContext *vc, const bool use_zbuf = !XRAY_FLAG_ENABLED(vc->v3d); - struct EditSelectBuf_Cache *esel = wm_userdata->data; + EditSelectBuf_Cache *esel = static_cast<EditSelectBuf_Cache *>(wm_userdata->data); if (use_zbuf) { - if (wm_userdata->data == NULL) { + if (wm_userdata->data == nullptr) { editselect_buf_cache_init_with_generic_userdata(wm_userdata, vc, ts->selectmode); - esel = wm_userdata->data; + esel = static_cast<EditSelectBuf_Cache *>(wm_userdata->data); esel->select_bitmap = DRW_select_buffer_bitmap_from_rect( - vc->depsgraph, vc->region, vc->v3d, rect, NULL); + vc->depsgraph, vc->region, vc->v3d, rect, nullptr); } } @@ -3424,16 +3484,16 @@ static bool do_mesh_box_select(ViewContext *vc, } if (ts->selectmode & SCE_SELECT_EDGE) { /* Does both use_zbuf and non-use_zbuf versions (need screen cos for both) */ - struct BoxSelectUserData_ForMeshEdge cb_data = { - .data = &data, - .esel = use_zbuf ? esel : NULL, - .backbuf_offset = use_zbuf ? DRW_select_buffer_context_offset_for_object_elem( - vc->depsgraph, vc->obedit, SCE_SELECT_EDGE) : - 0, + struct BoxSelectUserData_ForMeshEdge cb_data { }; + cb_data.data = &data; + cb_data.esel = use_zbuf ? esel : nullptr; + cb_data.backbuf_offset = use_zbuf ? DRW_select_buffer_context_offset_for_object_elem( + vc->depsgraph, vc->obedit, SCE_SELECT_EDGE) : + 0; const eV3DProjTest clip_flag = V3D_PROJ_TEST_CLIP_NEAR | - (use_zbuf ? 0 : V3D_PROJ_TEST_CLIP_BB); + (use_zbuf ? (eV3DProjTest)0 : V3D_PROJ_TEST_CLIP_BB); /* Fully inside. */ mesh_foreachScreenEdge_clip_bb_segment( vc, do_mesh_box_select__doSelectEdge_pass0, &cb_data, clip_flag); @@ -3483,7 +3543,8 @@ static bool do_meta_box_select(ViewContext *vc, const rcti *rect, const eSelectO } int metaelem_id = 0; - for (ml = mb->editelems->first; ml; ml = ml->next, metaelem_id += 0x10000) { + for (ml = static_cast<MetaElem *>(mb->editelems->first); ml; + ml = ml->next, metaelem_id += 0x10000) { bool is_inside_radius = false; bool is_inside_stiff = false; @@ -3547,7 +3608,7 @@ static bool do_armature_box_select(ViewContext *vc, const rcti *rect, const eSel uint bases_len = 0; Base **bases = BKE_view_layer_array_from_bases_in_edit_mode_unique_data( - vc->view_layer, vc->v3d, &bases_len); + vc->scene, vc->view_layer, vc->v3d, &bases_len); if (SEL_OP_USE_PRE_DESELECT(sel_op)) { changed |= ED_armature_edit_deselect_all_visible_multi_ex(bases, bases_len); @@ -3557,7 +3618,7 @@ static bool do_armature_box_select(ViewContext *vc, const rcti *rect, const eSel Object *obedit = bases[base_index]->object; obedit->id.tag &= ~LIB_TAG_DOIT; - bArmature *arm = obedit->data; + bArmature *arm = static_cast<bArmature *>(obedit->data); ED_armature_ebone_listbase_temp_clear(arm->edbo); } @@ -3581,7 +3642,8 @@ static bool do_armature_box_select(ViewContext *vc, const rcti *rect, const eSel Object *obedit = bases[base_index]->object; if (obedit->id.tag & LIB_TAG_DOIT) { obedit->id.tag &= ~LIB_TAG_DOIT; - changed |= ED_armature_edit_select_op_from_tagged(obedit->data, sel_op); + changed |= ED_armature_edit_select_op_from_tagged(static_cast<bArmature *>(obedit->data), + sel_op); } } @@ -3619,33 +3681,33 @@ static bool do_object_box_select(bContext *C, ViewContext *vc, rcti *rect, const int totobj = MAXPICKELEMS; /* XXX solve later */ /* Selection buffer has bones potentially too, so we add #MAXPICKELEMS. */ - GPUSelectResult *buffer = MEM_mallocN((totobj + MAXPICKELEMS) * sizeof(GPUSelectResult), - "selection buffer"); + GPUSelectResult *buffer = static_cast<GPUSelectResult *>( + MEM_mallocN((totobj + MAXPICKELEMS) * sizeof(GPUSelectResult), __func__)); const eV3DSelectObjectFilter select_filter = ED_view3d_select_filter_from_mode(vc->scene, vc->obact); const int hits = view3d_opengl_select( vc, buffer, (totobj + MAXPICKELEMS), rect, VIEW3D_SELECT_ALL, select_filter); - - LISTBASE_FOREACH (Base *, base, &vc->view_layer->object_bases) { + BKE_view_layer_synced_ensure(vc->scene, vc->view_layer); + LISTBASE_FOREACH (Base *, base, BKE_view_layer_object_bases_get(vc->view_layer)) { base->object->id.tag &= ~LIB_TAG_DOIT; } - Base **bases = NULL; - BLI_array_declare(bases); + blender::Vector<Base *> bases; bool changed = false; if (SEL_OP_USE_PRE_DESELECT(sel_op)) { - changed |= object_deselect_all_visible(vc->view_layer, vc->v3d); + changed |= object_deselect_all_visible(vc->scene, vc->view_layer, vc->v3d); } + ListBase *object_bases = BKE_view_layer_object_bases_get(vc->view_layer); if ((hits == -1) && !SEL_OP_USE_OUTSIDE(sel_op)) { goto finally; } - LISTBASE_FOREACH (Base *, base, &vc->view_layer->object_bases) { + LISTBASE_FOREACH (Base *, base, object_bases) { if (BASE_SELECTABLE(v3d, base)) { if ((base->object->runtime.select_id & 0x0000FFFF) != 0) { - BLI_array_append(bases, base); + bases.append(base); } } } @@ -3657,13 +3719,13 @@ static bool do_object_box_select(bContext *C, ViewContext *vc, rcti *rect, const buf_iter++) { bPoseChannel *pchan_dummy; Base *base = ED_armature_base_and_pchan_from_select_buffer( - bases, BLI_array_len(bases), buf_iter->id, &pchan_dummy); - if (base != NULL) { + bases.data(), bases.size(), buf_iter->id, &pchan_dummy); + if (base != nullptr) { base->object->id.tag |= LIB_TAG_DOIT; } } - for (Base *base = vc->view_layer->object_bases.first; base && hits; base = base->next) { + for (Base *base = static_cast<Base *>(object_bases->first); base && hits; base = base->next) { if (BASE_SELECTABLE(v3d, base)) { const bool is_select = base->flag & BASE_SELECTED; const bool is_inside = base->object->id.tag & LIB_TAG_DOIT; @@ -3676,9 +3738,6 @@ static bool do_object_box_select(bContext *C, ViewContext *vc, rcti *rect, const } finally: - if (bases != NULL) { - MEM_freeN(bases); - } MEM_freeN(buffer); @@ -3691,14 +3750,13 @@ finally: static bool do_pose_box_select(bContext *C, ViewContext *vc, rcti *rect, const eSelectOp sel_op) { - uint bases_len; - Base **bases = do_pose_tag_select_op_prepare(vc, &bases_len); + blender::Vector<Base *> bases = do_pose_tag_select_op_prepare(vc); int totobj = MAXPICKELEMS; /* XXX solve later */ /* Selection buffer has bones potentially too, so add #MAXPICKELEMS. */ - GPUSelectResult *buffer = MEM_mallocN((totobj + MAXPICKELEMS) * sizeof(GPUSelectResult), - "selection buffer"); + GPUSelectResult *buffer = static_cast<GPUSelectResult *>( + MEM_mallocN((totobj + MAXPICKELEMS) * sizeof(GPUSelectResult), __func__)); const eV3DSelectObjectFilter select_filter = ED_view3d_select_filter_from_mode(vc->scene, vc->obact); const int hits = view3d_opengl_select( @@ -3722,16 +3780,16 @@ static bool do_pose_box_select(bContext *C, ViewContext *vc, rcti *rect, const e buf_iter++) { Bone *bone; Base *base = ED_armature_base_and_bone_from_select_buffer( - bases, bases_len, buf_iter->id, &bone); + bases.data(), bases.size(), buf_iter->id, &bone); - if (base == NULL) { + if (base == nullptr) { continue; } /* Loop over contiguous bone hits for 'base'. */ for (; buf_iter != buf_end; buf_iter++) { /* should never fail */ - if (bone != NULL) { + if (bone != nullptr) { base->object->id.tag |= LIB_TAG_DOIT; bone->flag |= BONE_DONE; } @@ -3742,28 +3800,26 @@ static bool do_pose_box_select(bContext *C, ViewContext *vc, rcti *rect, const e if ((base->object->runtime.select_id & 0x0000FFFF) != (col_next->id & 0x0000FFFF)) { break; } - if (base->object->pose != NULL) { + if (base->object->pose != nullptr) { const uint hit_bone = (col_next->id & ~BONESEL_ANY) >> 16; - bPoseChannel *pchan = BLI_findlink(&base->object->pose->chanbase, hit_bone); - bone = pchan ? pchan->bone : NULL; + bPoseChannel *pchan = static_cast<bPoseChannel *>( + BLI_findlink(&base->object->pose->chanbase, hit_bone)); + bone = pchan ? pchan->bone : nullptr; } else { - bone = NULL; + bone = nullptr; } } } } } - const bool changed_multi = do_pose_tag_select_op_exec(bases, bases_len, sel_op); + const bool changed_multi = do_pose_tag_select_op_exec(bases, sel_op); if (changed_multi) { DEG_id_tag_update(&vc->scene->id, ID_RECALC_SELECT); WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, vc->scene); } - if (bases != NULL) { - MEM_freeN(bases); - } MEM_freeN(buffer); return changed_multi; @@ -3776,7 +3832,7 @@ static int view3d_box_select_exec(bContext *C, wmOperator *op) rcti rect; bool changed_multi = false; - wmGenericUserData wm_userdata_buf = {0}; + wmGenericUserData wm_userdata_buf = {nullptr, nullptr, false}; wmGenericUserData *wm_userdata = &wm_userdata_buf; view3d_operator_needs_opengl(C); @@ -3785,12 +3841,12 @@ static int view3d_box_select_exec(bContext *C, wmOperator *op) /* setup view context for argument to callbacks */ ED_view3d_viewcontext_init(C, &vc, depsgraph); - eSelectOp sel_op = RNA_enum_get(op->ptr, "mode"); + eSelectOp sel_op = static_cast<eSelectOp>(RNA_enum_get(op->ptr, "mode")); WM_operator_properties_border_to_rcti(op, &rect); if (vc.obedit) { FOREACH_OBJECT_IN_MODE_BEGIN ( - vc.view_layer, vc.v3d, vc.obedit->type, vc.obedit->mode, ob_iter) { + vc.scene, vc.view_layer, vc.v3d, vc.obedit->type, vc.obedit->mode, ob_iter) { ED_view3d_viewcontext_init_object(&vc, ob_iter); bool changed = false; @@ -3799,7 +3855,7 @@ static int view3d_box_select_exec(bContext *C, wmOperator *op) vc.em = BKE_editmesh_from_object(vc.obedit); changed = do_mesh_box_select(&vc, wm_userdata, &rect, sel_op); if (changed) { - DEG_id_tag_update(vc.obedit->data, ID_RECALC_SELECT); + DEG_id_tag_update(static_cast<ID *>(vc.obedit->data), ID_RECALC_SELECT); WM_event_add_notifier(C, NC_GEOM | ND_SELECT, vc.obedit->data); } break; @@ -3807,14 +3863,14 @@ static int view3d_box_select_exec(bContext *C, wmOperator *op) case OB_SURF: changed = do_nurbs_box_select(&vc, &rect, sel_op); if (changed) { - DEG_id_tag_update(vc.obedit->data, ID_RECALC_SELECT); + DEG_id_tag_update(static_cast<ID *>(vc.obedit->data), ID_RECALC_SELECT); WM_event_add_notifier(C, NC_GEOM | ND_SELECT, vc.obedit->data); } break; case OB_MBALL: changed = do_meta_box_select(&vc, &rect, sel_op); if (changed) { - DEG_id_tag_update(vc.obedit->data, ID_RECALC_SELECT); + DEG_id_tag_update(static_cast<ID *>(vc.obedit->data), ID_RECALC_SELECT); WM_event_add_notifier(C, NC_GEOM | ND_SELECT, vc.obedit->data); } break; @@ -3829,7 +3885,7 @@ static int view3d_box_select_exec(bContext *C, wmOperator *op) case OB_LATTICE: changed = do_lattice_box_select(&vc, &rect, sel_op); if (changed) { - DEG_id_tag_update(vc.obedit->data, ID_RECALC_SELECT); + DEG_id_tag_update(static_cast<ID *>(vc.obedit->data), ID_RECALC_SELECT); WM_event_add_notifier(C, NC_GEOM | ND_SELECT, vc.obedit->data); } break; @@ -3901,7 +3957,7 @@ void VIEW3D_OT_select_box(wmOperatorType *ot) /** \name Circle Select * \{ */ -typedef struct CircleSelectUserData { +struct CircleSelectUserData { ViewContext *vc; bool select; int mval[2]; @@ -3912,7 +3968,7 @@ typedef struct CircleSelectUserData { /* runtime */ bool is_changed; -} CircleSelectUserData; +}; static void view3d_userdata_circleselect_init(CircleSelectUserData *r_data, ViewContext *vc, @@ -3930,7 +3986,7 @@ static void view3d_userdata_circleselect_init(CircleSelectUserData *r_data, r_data->radius_squared = rad * rad; /* SELECT by default, but can be changed if needed (only few cases use and respect this). */ - r_data->select_flag = SELECT; + r_data->select_flag = (eBezTriple_Flag)SELECT; /* runtime */ r_data->is_changed = false; @@ -3941,7 +3997,7 @@ static void mesh_circle_doSelectVert(void *userData, const float screen_co[2], int UNUSED(index)) { - CircleSelectUserData *data = userData; + CircleSelectUserData *data = static_cast<CircleSelectUserData *>(userData); if (len_squared_v2v2(data->mval_fl, screen_co) <= data->radius_squared) { BM_vert_select_set(data->vc->em->bm, eve, data->select); @@ -3954,7 +4010,7 @@ static void mesh_circle_doSelectEdge(void *userData, const float screen_co_b[2], int UNUSED(index)) { - CircleSelectUserData *data = userData; + CircleSelectUserData *data = static_cast<CircleSelectUserData *>(userData); if (edge_inside_circle(data->mval_fl, data->radius, screen_co_a, screen_co_b)) { BM_edge_select_set(data->vc->em->bm, eed, data->select); @@ -3966,7 +4022,7 @@ static void mesh_circle_doSelectFace(void *userData, const float screen_co[2], int UNUSED(index)) { - CircleSelectUserData *data = userData; + CircleSelectUserData *data = static_cast<CircleSelectUserData *>(userData); if (len_squared_v2v2(data->mval_fl, screen_co) <= data->radius_squared) { BM_face_select_set(data->vc->em->bm, efa, data->select); @@ -4003,22 +4059,22 @@ static bool mesh_circle_select(ViewContext *vc, const bool use_zbuf = !XRAY_FLAG_ENABLED(vc->v3d); if (use_zbuf) { - if (wm_userdata->data == NULL) { + if (wm_userdata->data == nullptr) { editselect_buf_cache_init_with_generic_userdata(wm_userdata, vc, ts->selectmode); } } - struct EditSelectBuf_Cache *esel = wm_userdata->data; + EditSelectBuf_Cache *esel = static_cast<EditSelectBuf_Cache *>(wm_userdata->data); if (use_zbuf) { - if (esel->select_bitmap == NULL) { + if (esel->select_bitmap == nullptr) { esel->select_bitmap = DRW_select_buffer_bitmap_from_circle( - vc->depsgraph, vc->region, vc->v3d, mval, (int)(rad + 1.0f), NULL); + vc->depsgraph, vc->region, vc->v3d, mval, (int)(rad + 1.0f), nullptr); } } if (ts->selectmode & SCE_SELECT_VERTEX) { if (use_zbuf) { - if (esel->select_bitmap != NULL) { + if (esel->select_bitmap != nullptr) { changed |= edbm_backbuf_check_and_select_verts( esel, vc->depsgraph, vc->obedit, vc->em, select ? SEL_OP_ADD : SEL_OP_SUB); } @@ -4030,7 +4086,7 @@ static bool mesh_circle_select(ViewContext *vc, if (ts->selectmode & SCE_SELECT_EDGE) { if (use_zbuf) { - if (esel->select_bitmap != NULL) { + if (esel->select_bitmap != nullptr) { changed |= edbm_backbuf_check_and_select_edges( esel, vc->depsgraph, vc->obedit, vc->em, select ? SEL_OP_ADD : SEL_OP_SUB); } @@ -4046,7 +4102,7 @@ static bool mesh_circle_select(ViewContext *vc, if (ts->selectmode & SCE_SELECT_FACE) { if (use_zbuf) { - if (esel->select_bitmap != NULL) { + if (esel->select_bitmap != nullptr) { changed |= edbm_backbuf_check_and_select_faces( esel, vc->depsgraph, vc->obedit, vc->em, select ? SEL_OP_ADD : SEL_OP_SUB); } @@ -4073,7 +4129,7 @@ static bool paint_facesel_circle_select(ViewContext *vc, { BLI_assert(ELEM(sel_op, SEL_OP_SET, SEL_OP_ADD, SEL_OP_SUB)); Object *ob = vc->obact; - Mesh *me = ob->data; + Mesh *me = static_cast<Mesh *>(ob->data); bool changed = false; if (SEL_OP_USE_PRE_DESELECT(sel_op)) { @@ -4081,18 +4137,18 @@ static bool paint_facesel_circle_select(ViewContext *vc, changed |= paintface_deselect_all_visible(vc->C, ob, SEL_DESELECT, false); } - if (wm_userdata->data == NULL) { + if (wm_userdata->data == nullptr) { editselect_buf_cache_init_with_generic_userdata(wm_userdata, vc, SCE_SELECT_FACE); } { - struct EditSelectBuf_Cache *esel = wm_userdata->data; + EditSelectBuf_Cache *esel = static_cast<EditSelectBuf_Cache *>(wm_userdata->data); esel->select_bitmap = DRW_select_buffer_bitmap_from_circle( - vc->depsgraph, vc->region, vc->v3d, mval, (int)(rad + 1.0f), NULL); - if (esel->select_bitmap != NULL) { + vc->depsgraph, vc->region, vc->v3d, mval, (int)(rad + 1.0f), nullptr); + if (esel->select_bitmap != nullptr) { changed |= edbm_backbuf_check_and_select_faces_obmode(me, esel, sel_op); MEM_freeN(esel->select_bitmap); - esel->select_bitmap = NULL; + esel->select_bitmap = nullptr; } } @@ -4102,15 +4158,21 @@ static bool paint_facesel_circle_select(ViewContext *vc, return changed; } +struct CircleSelectUserData_ForMeshVert { + CircleSelectUserData circle_data; + blender::MutableSpan<bool> select_vert; +}; static void paint_vertsel_circle_select_doSelectVert(void *userData, - MVert *mv, + MVert * /*mv*/, const float screen_co[2], - int UNUSED(index)) + int index) { - CircleSelectUserData *data = userData; + CircleSelectUserData_ForMeshVert *mesh_data = static_cast<CircleSelectUserData_ForMeshVert *>( + userData); + CircleSelectUserData *data = &mesh_data->circle_data; if (len_squared_v2v2(data->mval_fl, screen_co) <= data->radius_squared) { - SET_FLAG_FROM_TEST(mv->flag, data->select, SELECT); + mesh_data->select_vert[index] = data->select; data->is_changed = true; } } @@ -4120,11 +4182,12 @@ static bool paint_vertsel_circle_select(ViewContext *vc, const int mval[2], float rad) { + using namespace blender; BLI_assert(ELEM(sel_op, SEL_OP_SET, SEL_OP_ADD, SEL_OP_SUB)); const bool use_zbuf = !XRAY_ENABLED(vc->v3d); Object *ob = vc->obact; - Mesh *me = ob->data; - /* CircleSelectUserData data = {NULL}; */ /* UNUSED */ + Mesh *me = static_cast<Mesh *>(ob->data); + /* CircleSelectUserData data = {nullptr}; */ /* UNUSED */ bool changed = false; if (SEL_OP_USE_PRE_DESELECT(sel_op)) { @@ -4135,30 +4198,36 @@ static bool paint_vertsel_circle_select(ViewContext *vc, const bool select = (sel_op != SEL_OP_SUB); if (use_zbuf) { - if (wm_userdata->data == NULL) { + if (wm_userdata->data == nullptr) { editselect_buf_cache_init_with_generic_userdata(wm_userdata, vc, SCE_SELECT_VERTEX); } } if (use_zbuf) { - struct EditSelectBuf_Cache *esel = wm_userdata->data; + EditSelectBuf_Cache *esel = static_cast<EditSelectBuf_Cache *>(wm_userdata->data); esel->select_bitmap = DRW_select_buffer_bitmap_from_circle( - vc->depsgraph, vc->region, vc->v3d, mval, (int)(rad + 1.0f), NULL); - if (esel->select_bitmap != NULL) { + vc->depsgraph, vc->region, vc->v3d, mval, (int)(rad + 1.0f), nullptr); + if (esel->select_bitmap != nullptr) { changed |= edbm_backbuf_check_and_select_verts_obmode(me, esel, sel_op); MEM_freeN(esel->select_bitmap); - esel->select_bitmap = NULL; + esel->select_bitmap = nullptr; } } else { - CircleSelectUserData data; + bke::MutableAttributeAccessor attributes = me->attributes_for_write(); + bke::SpanAttributeWriter<bool> select_vert = attributes.lookup_or_add_for_write_span<bool>( + ".select_vert", ATTR_DOMAIN_POINT); + + CircleSelectUserData_ForMeshVert data; + data.select_vert = select_vert.span; ED_view3d_init_mats_rv3d(vc->obact, vc->rv3d); /* for foreach's screen/vert projection */ - view3d_userdata_circleselect_init(&data, vc, select, mval, rad); + view3d_userdata_circleselect_init(&data.circle_data, vc, select, mval, rad); meshobject_foreachScreenVert( vc, paint_vertsel_circle_select_doSelectVert, &data, V3D_PROJ_TEST_CLIP_DEFAULT); - changed |= data.is_changed; + changed |= data.circle_data.is_changed; + select_vert.finish(); } if (changed) { @@ -4179,7 +4248,7 @@ static void nurbscurve_circle_doSelect(void *userData, bool UNUSED(handles_visible), const float screen_co[2]) { - CircleSelectUserData *data = userData; + CircleSelectUserData *data = static_cast<CircleSelectUserData *>(userData); if (len_squared_v2v2(data->mval_fl, screen_co) <= data->radius_squared) { if (bp) { @@ -4227,14 +4296,14 @@ static bool nurbscurve_circle_select(ViewContext *vc, data.is_changed |= BKE_nurbList_flag_set_from_flag(nurbs, BEZT_FLAG_TEMP_TAG, SELECT); } - BKE_curve_nurb_vert_active_validate(vc->obedit->data); + BKE_curve_nurb_vert_active_validate(static_cast<Curve *>(vc->obedit->data)); return data.is_changed; } static void latticecurve_circle_doSelect(void *userData, BPoint *bp, const float screen_co[2]) { - CircleSelectUserData *data = userData; + CircleSelectUserData *data = static_cast<CircleSelectUserData *>(userData); if (len_squared_v2v2(data->mval_fl, screen_co) <= data->radius_squared) { bp->f1 = data->select ? (bp->f1 | SELECT) : (bp->f1 & ~SELECT); @@ -4268,7 +4337,7 @@ static bool pchan_circle_doSelectJoint(void *userData, bPoseChannel *pchan, const float screen_co[2]) { - CircleSelectUserData *data = userData; + CircleSelectUserData *data = static_cast<CircleSelectUserData *>(userData); if (len_squared_v2v2(data->mval_fl, screen_co) <= data->radius_squared) { if (data->select) { @@ -4277,17 +4346,17 @@ static bool pchan_circle_doSelectJoint(void *userData, else { pchan->bone->flag &= ~BONE_SELECTED; } - return 1; + return true; } - return 0; + return false; } static void do_circle_select_pose__doSelectBone(void *userData, - struct bPoseChannel *pchan, + bPoseChannel *pchan, const float screen_co_a[2], const float screen_co_b[2]) { - CircleSelectUserData *data = userData; - bArmature *arm = data->vc->obact->data; + CircleSelectUserData *data = static_cast<CircleSelectUserData *>(userData); + bArmature *arm = static_cast<bArmature *>(data->vc->obact->data); if (!PBONE_SELECTABLE(arm, pchan->bone)) { return; } @@ -4295,7 +4364,7 @@ static void do_circle_select_pose__doSelectBone(void *userData, bool is_point_done = false; int points_proj_tot = 0; - /* project head location to screenspace */ + /* Project head location to screen-space. */ if (screen_co_a[0] != IS_CLIPPED) { points_proj_tot++; if (pchan_circle_doSelectJoint(data, pchan, screen_co_a)) { @@ -4303,7 +4372,7 @@ static void do_circle_select_pose__doSelectBone(void *userData, } } - /* project tail location to screenspace */ + /* Project tail location to screen-space. */ if (screen_co_b[0] != IS_CLIPPED) { points_proj_tot++; if (pchan_circle_doSelectJoint(data, pchan, screen_co_b)) { @@ -4368,7 +4437,7 @@ static bool armature_circle_doSelectJoint(void *userData, const float screen_co[2], bool head) { - CircleSelectUserData *data = userData; + CircleSelectUserData *data = static_cast<CircleSelectUserData *>(userData); if (len_squared_v2v2(data->mval_fl, screen_co) <= data->radius_squared) { if (head) { @@ -4387,17 +4456,17 @@ static bool armature_circle_doSelectJoint(void *userData, ebone->flag &= ~BONE_TIPSEL; } } - return 1; + return true; } - return 0; + return false; } static void do_circle_select_armature__doSelectBone(void *userData, - struct EditBone *ebone, + EditBone *ebone, const float screen_co_a[2], const float screen_co_b[2]) { - CircleSelectUserData *data = userData; - const bArmature *arm = data->vc->obedit->data; + CircleSelectUserData *data = static_cast<CircleSelectUserData *>(userData); + const bArmature *arm = static_cast<const bArmature *>(data->vc->obedit->data); if (!(data->select ? EBONE_SELECTABLE(arm, ebone) : EBONE_VISIBLE(arm, ebone))) { return; } @@ -4409,7 +4478,7 @@ static void do_circle_select_armature__doSelectBone(void *userData, bool is_edge_done = false; int points_proj_tot = 0; - /* project head location to screenspace */ + /* Project head location to screen-space. */ if (screen_co_a[0] != IS_CLIPPED) { points_proj_tot++; if (armature_circle_doSelectJoint(data, ebone, screen_co_a, true)) { @@ -4417,7 +4486,7 @@ static void do_circle_select_armature__doSelectBone(void *userData, } } - /* project tail location to screenspace */ + /* Project tail location to screen-space. */ if (screen_co_b[0] != IS_CLIPPED) { points_proj_tot++; if (armature_circle_doSelectJoint(data, ebone, screen_co_b, false)) { @@ -4446,19 +4515,19 @@ static void do_circle_select_armature__doSelectBone(void *userData, data->is_changed |= is_point_done; } static void do_circle_select_armature__doSelectBone_clip_content(void *userData, - struct EditBone *ebone, + EditBone *ebone, const float screen_co_a[2], const float screen_co_b[2]) { - CircleSelectUserData *data = userData; - bArmature *arm = data->vc->obedit->data; + CircleSelectUserData *data = static_cast<CircleSelectUserData *>(userData); + bArmature *arm = static_cast<bArmature *>(data->vc->obedit->data); if (!(data->select ? EBONE_SELECTABLE(arm, ebone) : EBONE_VISIBLE(arm, ebone))) { return; } /* Set in the first pass, needed so circle select prioritizes joints. */ - if (ebone->temp.i == true) { + if (ebone->temp.i != 0) { return; } @@ -4473,7 +4542,7 @@ static bool armature_circle_select(ViewContext *vc, float rad) { CircleSelectUserData data; - bArmature *arm = vc->obedit->data; + bArmature *arm = static_cast<bArmature *>(vc->obedit->data); const bool select = (sel_op != SEL_OP_SUB); @@ -4506,10 +4575,10 @@ static bool armature_circle_select(ViewContext *vc, } static void do_circle_select_mball__doSelectElem(void *userData, - struct MetaElem *ml, + MetaElem *ml, const float screen_co[2]) { - CircleSelectUserData *data = userData; + CircleSelectUserData *data = static_cast<CircleSelectUserData *>(userData); if (len_squared_v2v2(data->mval_fl, screen_co) <= data->radius_squared) { if (data->select) { @@ -4533,7 +4602,7 @@ static bool mball_circle_select(ViewContext *vc, view3d_userdata_circleselect_init(&data, vc, select, mval, rad); if (SEL_OP_USE_PRE_DESELECT(sel_op)) { - data.is_changed |= BKE_mball_deselect_all(vc->obedit->data); + data.is_changed |= BKE_mball_deselect_all(static_cast<MetaBall *>(vc->obedit->data)); } ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d); @@ -4581,7 +4650,7 @@ static bool obedit_circle_select(bContext *C, } if (changed) { - DEG_id_tag_update(vc->obact->data, ID_RECALC_SELECT); + DEG_id_tag_update(static_cast<ID *>(vc->obact->data), ID_RECALC_SELECT); WM_main_add_notifier(NC_GEOM | ND_SELECT, vc->obact->data); } return changed; @@ -4593,21 +4662,21 @@ static bool object_circle_select(ViewContext *vc, float rad) { BLI_assert(ELEM(sel_op, SEL_OP_SET, SEL_OP_ADD, SEL_OP_SUB)); + Scene *scene = vc->scene; ViewLayer *view_layer = vc->view_layer; View3D *v3d = vc->v3d; const float radius_squared = rad * rad; - const float mval_fl[2] = {mval[0], mval[1]}; + const float mval_fl[2] = {static_cast<float>(mval[0]), static_cast<float>(mval[1])}; bool changed = false; if (SEL_OP_USE_PRE_DESELECT(sel_op)) { - changed |= object_deselect_all_visible(vc->view_layer, vc->v3d); + changed |= object_deselect_all_visible(vc->scene, vc->view_layer, vc->v3d); } const bool select = (sel_op != SEL_OP_SUB); const int select_flag = select ? BASE_SELECTED : 0; - - Base *base; - for (base = FIRSTBASE(view_layer); base; base = base->next) { + BKE_view_layer_synced_ensure(scene, view_layer); + LISTBASE_FOREACH (Base *, base, BKE_view_layer_object_bases_get(view_layer)) { if (BASE_SELECTABLE(v3d, base) && ((base->flag & BASE_SELECTED) != select_flag)) { float screen_co[2]; if (ED_view3d_project_float_global( @@ -4627,7 +4696,7 @@ static bool object_circle_select(ViewContext *vc, /* not a real operator, only for circle test */ static void view3d_circle_select_recalc(void *user_data) { - bContext *C = user_data; + bContext *C = static_cast<bContext *>(user_data); Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C); ViewContext vc; ED_view3d_viewcontext_init(C, &vc, depsgraph); @@ -4637,7 +4706,7 @@ static void view3d_circle_select_recalc(void *user_data) switch (vc.obedit->type) { case OB_MESH: { FOREACH_OBJECT_IN_MODE_BEGIN ( - vc.view_layer, vc.v3d, vc.obact->type, vc.obact->mode, ob_iter) { + vc.scene, vc.view_layer, vc.v3d, vc.obact->type, vc.obact->mode, ob_iter) { ED_view3d_viewcontext_init_object(&vc, ob_iter); BM_mesh_select_mode_flush_ex( vc.em->bm, vc.em->selectmode, BM_SELECT_LEN_FLUSH_RECALC_ALL); @@ -4675,12 +4744,12 @@ static int view3d_circle_select_exec(bContext *C, wmOperator *op) const int mval[2] = {RNA_int_get(op->ptr, "x"), RNA_int_get(op->ptr, "y")}; /* Allow each selection type to allocate their own data that's used between executions. */ - wmGesture *gesture = op->customdata; /* NULL when non-modal. */ - wmGenericUserData wm_userdata_buf = {0}; + wmGesture *gesture = static_cast<wmGesture *>(op->customdata); /* nullptr when non-modal. */ + wmGenericUserData wm_userdata_buf = {nullptr, nullptr, false}; wmGenericUserData *wm_userdata = gesture ? &gesture->user_data : &wm_userdata_buf; - const eSelectOp sel_op = ED_select_op_modal(RNA_enum_get(op->ptr, "mode"), - WM_gesture_is_modal_first(gesture)); + const eSelectOp sel_op = ED_select_op_modal( + static_cast<eSelectOp>(RNA_enum_get(op->ptr, "mode")), WM_gesture_is_modal_first(gesture)); ED_view3d_viewcontext_init(C, &vc, depsgraph); @@ -4689,11 +4758,12 @@ static int view3d_circle_select_exec(bContext *C, wmOperator *op) if (obedit || BKE_paint_select_elem_test(obact) || (obact && (obact->mode & OB_MODE_POSE))) { view3d_operator_needs_opengl(C); - if (obedit == NULL) { + if (obedit == nullptr) { BKE_object_update_select_id(CTX_data_main(C)); } - FOREACH_OBJECT_IN_MODE_BEGIN (vc.view_layer, vc.v3d, obact->type, obact->mode, ob_iter) { + FOREACH_OBJECT_IN_MODE_BEGIN ( + vc.scene, vc.view_layer, vc.v3d, obact->type, obact->mode, ob_iter) { ED_view3d_viewcontext_init_object(&vc, ob_iter); obact = vc.obact; @@ -4741,10 +4811,10 @@ static int view3d_circle_select_exec(bContext *C, wmOperator *op) WM_generic_user_data_free(wm_userdata); } else { - struct EditSelectBuf_Cache *esel = wm_userdata->data; + EditSelectBuf_Cache *esel = static_cast<EditSelectBuf_Cache *>(wm_userdata->data); if (esel && esel->select_bitmap) { MEM_freeN(esel->select_bitmap); - esel->select_bitmap = NULL; + esel->select_bitmap = nullptr; } } diff --git a/source/blender/editors/space_view3d/view3d_snap.c b/source/blender/editors/space_view3d/view3d_snap.c index 2f51b2dce3b..a5ecef69ff8 100644 --- a/source/blender/editors/space_view3d/view3d_snap.c +++ b/source/blender/editors/space_view3d/view3d_snap.c @@ -69,7 +69,7 @@ static int snap_sel_to_grid_exec(bContext *C, wmOperator *UNUSED(op)) ViewLayer *view_layer = CTX_data_view_layer(C); uint objects_len = 0; Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data( - view_layer, CTX_wm_view3d(C), &objects_len); + scene, view_layer, CTX_wm_view3d(C), &objects_len); for (uint ob_index = 0; ob_index < objects_len; ob_index++) { Object *obedit = objects[ob_index]; @@ -111,7 +111,7 @@ static int snap_sel_to_grid_exec(bContext *C, wmOperator *UNUSED(op)) else if (OBPOSE_FROM_OBACT(obact)) { struct KeyingSet *ks = ANIM_get_keyingset_for_autokeying(scene, ANIM_KS_LOCATION_ID); uint objects_len = 0; - Object **objects_eval = BKE_object_pose_array_get(view_layer_eval, v3d, &objects_len); + Object **objects_eval = BKE_object_pose_array_get(scene, view_layer_eval, v3d, &objects_len); for (uint ob_index = 0; ob_index < objects_len; ob_index++) { Object *ob_eval = objects_eval[ob_index]; Object *ob = DEG_get_original_object(ob_eval); @@ -203,7 +203,7 @@ static int snap_sel_to_grid_exec(bContext *C, wmOperator *UNUSED(op)) BKE_scene_graph_evaluated_ensure(depsgraph, bmain); xcs = ED_object_xform_skip_child_container_create(); ED_object_xform_skip_child_container_item_ensure_from_array( - xcs, view_layer, objects, objects_eval_len); + xcs, scene, view_layer, objects, objects_eval_len); MEM_freeN(objects); } if (use_transform_data_origin) { @@ -326,7 +326,7 @@ static bool snap_selected_to_location(bContext *C, ViewLayer *view_layer = CTX_data_view_layer(C); uint objects_len = 0; Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data( - view_layer, v3d, &objects_len); + scene, view_layer, v3d, &objects_len); for (uint ob_index = 0; ob_index < objects_len; ob_index++) { obedit = objects[ob_index]; @@ -376,7 +376,7 @@ static bool snap_selected_to_location(bContext *C, struct KeyingSet *ks = ANIM_get_keyingset_for_autokeying(scene, ANIM_KS_LOCATION_ID); ViewLayer *view_layer = CTX_data_view_layer(C); uint objects_len = 0; - Object **objects = BKE_object_pose_array_get(view_layer, v3d, &objects_len); + Object **objects = BKE_object_pose_array_get(scene, view_layer, v3d, &objects_len); for (uint ob_index = 0; ob_index < objects_len; ob_index++) { Object *ob = objects[ob_index]; @@ -487,7 +487,7 @@ static bool snap_selected_to_location(bContext *C, BKE_scene_graph_evaluated_ensure(depsgraph, bmain); xcs = ED_object_xform_skip_child_container_create(); ED_object_xform_skip_child_container_item_ensure_from_array( - xcs, view_layer, objects, objects_len); + xcs, scene, view_layer, objects, objects_len); } if (use_transform_data_origin) { BKE_scene_graph_evaluated_ensure(depsgraph, bmain); @@ -789,7 +789,7 @@ static bool snap_curs_to_sel_ex(bContext *C, const int pivot_point, float r_curs ViewLayer *view_layer = CTX_data_view_layer(C); uint objects_len = 0; Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data( - view_layer, CTX_wm_view3d(C), &objects_len); + scene, view_layer, CTX_wm_view3d(C), &objects_len); for (uint ob_index = 0; ob_index < objects_len; ob_index++) { obedit = objects[ob_index]; diff --git a/source/blender/editors/space_view3d/view3d_utils.c b/source/blender/editors/space_view3d/view3d_utils.c index 5f2a4e8c4cc..cb716391fb2 100644 --- a/source/blender/editors/space_view3d/view3d_utils.c +++ b/source/blender/editors/space_view3d/view3d_utils.c @@ -705,8 +705,9 @@ bool ED_view3d_camera_lock_undo_test(const View3D *v3d, * Create a MEMFILE undo-step for locked camera movement when transforming the view. * Edit and texture paint mode don't use MEMFILE undo so undo push is skipped for them. * NDOF and track-pad navigation would create an undo step on every gesture and we may end up with - * unnecessary undo steps so undo push for them is not supported for now. Also operators that uses - * smooth view for navigation are excluded too, but they can be supported, see: D15345. + * unnecessary undo steps so undo push for them is not supported for now. + * Operators that use smooth view for navigation are supported via an optional parameter field, + * see: #V3D_SmoothParams.undo_str. */ static bool view3d_camera_lock_undo_ex(const char *str, const View3D *v3d, diff --git a/source/blender/editors/space_view3d/view3d_view.c b/source/blender/editors/space_view3d/view3d_view.c index b8042a9f215..d0db4de0c47 100644 --- a/source/blender/editors/space_view3d/view3d_view.c +++ b/source/blender/editors/space_view3d/view3d_view.c @@ -553,7 +553,8 @@ int view3d_opengl_select_ex(ViewContext *vc, ARegion *region = vc->region; rcti rect; int hits = 0; - const bool use_obedit_skip = (OBEDIT_FROM_VIEW_LAYER(vc->view_layer) != NULL) && + BKE_view_layer_synced_ensure(scene, vc->view_layer); + const bool use_obedit_skip = (BKE_view_layer_edit_object_get(vc->view_layer) != NULL) && (vc->obedit == NULL); const bool is_pick_select = (U.gpu_flag & USER_GPU_FLAG_NO_DEPT_PICK) == 0; const bool do_passes = ((is_pick_select == false) && @@ -601,7 +602,7 @@ int view3d_opengl_select_ex(ViewContext *vc, goto finally; } - /* Important to use 'vc->obact', not 'OBACT(vc->view_layer)' below, + /* Important to use 'vc->obact', not 'BKE_view_layer_active_object_get(vc->view_layer)' below, * so it will be NULL when hidden. */ struct { DRW_ObjectFilterFn fn; @@ -824,6 +825,7 @@ static bool view3d_localview_init(const Depsgraph *depsgraph, wmWindowManager *wm, wmWindow *win, Main *bmain, + const Scene *scene, ViewLayer *view_layer, ScrArea *area, const bool frame_selected, @@ -831,7 +833,6 @@ static bool view3d_localview_init(const Depsgraph *depsgraph, ReportList *reports) { View3D *v3d = area->spacedata.first; - Base *base; float min[3], max[3], box[3]; float size = 0.0f; uint local_view_bit; @@ -852,12 +853,14 @@ static bool view3d_localview_init(const Depsgraph *depsgraph, ok = false; } else { - Object *obedit = OBEDIT_FROM_VIEW_LAYER(view_layer); + BKE_view_layer_synced_ensure(scene, view_layer); + Object *obedit = BKE_view_layer_edit_object_get(view_layer); if (obedit) { - for (base = FIRSTBASE(view_layer); base; base = base->next) { + BKE_view_layer_synced_ensure(scene, view_layer); + LISTBASE_FOREACH (Base *, base, BKE_view_layer_object_bases_get(view_layer)) { base->local_view_bits &= ~local_view_bit; } - FOREACH_BASE_IN_EDIT_MODE_BEGIN (view_layer, v3d, base_iter) { + FOREACH_BASE_IN_EDIT_MODE_BEGIN (scene, view_layer, v3d, base_iter) { BKE_object_minmax(base_iter->object, min, max, false); base_iter->local_view_bits |= local_view_bit; ok = true; @@ -865,7 +868,8 @@ static bool view3d_localview_init(const Depsgraph *depsgraph, FOREACH_BASE_IN_EDIT_MODE_END; } else { - for (base = FIRSTBASE(view_layer); base; base = base->next) { + BKE_view_layer_synced_ensure(scene, view_layer); + LISTBASE_FOREACH (Base *, base, BKE_view_layer_object_bases_get(view_layer)) { if (BASE_SELECTED(v3d, base)) { BKE_object_minmax(base->object, min, max, false); base->local_view_bits |= local_view_bit; @@ -956,6 +960,7 @@ static bool view3d_localview_init(const Depsgraph *depsgraph, static void view3d_localview_exit(const Depsgraph *depsgraph, wmWindowManager *wm, wmWindow *win, + const Scene *scene, ViewLayer *view_layer, ScrArea *area, const bool frame_selected, @@ -966,8 +971,8 @@ static void view3d_localview_exit(const Depsgraph *depsgraph, if (v3d->localvd == NULL) { return; } - - for (Base *base = FIRSTBASE(view_layer); base; base = base->next) { + BKE_view_layer_synced_ensure(scene, view_layer); + LISTBASE_FOREACH (Base *, base, BKE_view_layer_object_bases_get(view_layer)) { if (base->local_view_bits & v3d->local_view_uuid) { base->local_view_bits &= ~v3d->local_view_uuid; } @@ -1040,12 +1045,21 @@ static int localview_exec(bContext *C, wmOperator *op) bool changed; if (v3d->localvd) { - view3d_localview_exit(depsgraph, wm, win, view_layer, area, frame_selected, smooth_viewtx); + view3d_localview_exit( + depsgraph, wm, win, scene, view_layer, area, frame_selected, smooth_viewtx); changed = true; } else { - changed = view3d_localview_init( - depsgraph, wm, win, bmain, view_layer, area, frame_selected, smooth_viewtx, op->reports); + changed = view3d_localview_init(depsgraph, + wm, + win, + bmain, + scene, + view_layer, + area, + frame_selected, + smooth_viewtx, + op->reports); } if (changed) { @@ -1093,13 +1107,13 @@ static int localview_remove_from_exec(bContext *C, wmOperator *op) Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); bool changed = false; - - for (Base *base = FIRSTBASE(view_layer); base; base = base->next) { + BKE_view_layer_synced_ensure(scene, view_layer); + LISTBASE_FOREACH (Base *, base, BKE_view_layer_object_bases_get(view_layer)) { if (BASE_SELECTED(v3d, base)) { base->local_view_bits &= ~v3d->local_view_uuid; ED_object_base_select(base, BA_DESELECT); - if (base == BASACT(view_layer)) { + if (base == view_layer->basact) { view_layer->basact = NULL; } changed = true; @@ -1266,7 +1280,7 @@ void ED_view3d_local_collections_reset(struct bContext *C, const bool reset_all) else if (reset_all && (do_reset || (local_view_bit != ~(0)))) { view3d_local_collections_reset(bmain, ~(0)); View3D v3d = {.local_collections_uuid = ~(0)}; - BKE_layer_collection_local_sync(CTX_data_view_layer(C), &v3d); + BKE_layer_collection_local_sync(CTX_data_scene(C), CTX_data_view_layer(C), &v3d); DEG_id_tag_update(&CTX_data_scene(C)->id, ID_RECALC_BASE_FLAGS); } } diff --git a/source/blender/editors/transform/CMakeLists.txt b/source/blender/editors/transform/CMakeLists.txt index 6984dcb18d4..ec6f62e0f5b 100644 --- a/source/blender/editors/transform/CMakeLists.txt +++ b/source/blender/editors/transform/CMakeLists.txt @@ -15,7 +15,6 @@ set(INC ../../render ../../sequencer ../../windowmanager - ../../../../intern/glew-mx ../../../../intern/guardedalloc # RNA_prototypes.h ${CMAKE_BINARY_DIR}/source/blender/makesrna diff --git a/source/blender/editors/transform/transform.c b/source/blender/editors/transform/transform.c index 8dcbf07b776..95aa48efd84 100644 --- a/source/blender/editors/transform/transform.c +++ b/source/blender/editors/transform/transform.c @@ -19,6 +19,7 @@ #include "BKE_context.h" #include "BKE_editmesh.h" +#include "BKE_layer.h" #include "BKE_mask.h" #include "BKE_scene.h" @@ -484,7 +485,9 @@ static void viewRedrawForce(const bContext *C, TransInfo *t) /* XXX how to deal with lock? */ SpaceImage *sima = (SpaceImage *)t->area->spacedata.first; if (sima->lock) { - WM_event_add_notifier(C, NC_GEOM | ND_DATA, OBEDIT_FROM_VIEW_LAYER(t->view_layer)->data); + BKE_view_layer_synced_ensure(t->scene, t->view_layer); + WM_event_add_notifier( + C, NC_GEOM | ND_DATA, BKE_view_layer_edit_object_get(t->view_layer)->data); } else { ED_area_tag_redraw(t->area); @@ -1476,7 +1479,8 @@ static void drawTransformPixel(const struct bContext *C, ARegion *region, void * if (region == t->region) { Scene *scene = t->scene; ViewLayer *view_layer = t->view_layer; - Object *ob = OBACT(view_layer); + BKE_view_layer_synced_ensure(scene, view_layer); + Object *ob = BKE_view_layer_active_object_get(view_layer); /* draw auto-key-framing hint in the corner * - only draw if enabled (advanced users may be distracted/annoyed), @@ -1536,7 +1540,8 @@ void saveTransform(bContext *C, TransInfo *t, wmOperator *op) if (!(t->options & CTX_NO_PET)) { if ((prop = RNA_struct_find_property(op->ptr, "use_proportional_edit")) && !RNA_property_is_set(op->ptr, prop)) { - const Object *obact = OBACT(t->view_layer); + BKE_view_layer_synced_ensure(t->scene, t->view_layer); + const Object *obact = BKE_view_layer_active_object_get(t->view_layer); if (t->spacetype == SPACE_GRAPH) { ts->proportional_fcurve = use_prop_edit; @@ -1714,11 +1719,17 @@ static void initSnapSpatial(TransInfo *t, float r_snap[2]) int grid_size = SI_GRID_STEPS_LEN; float zoom_factor = ED_space_image_zoom_level(v2d, grid_size); float grid_steps[SI_GRID_STEPS_LEN]; + float grid_steps_y[SI_GRID_STEPS_LEN]; - ED_space_image_grid_steps(sima, grid_steps, grid_size); + ED_space_image_grid_steps(sima, grid_steps, grid_steps_y, grid_size); /* Snapping value based on what type of grid is used (adaptive-subdividing or custom-grid). */ r_snap[0] = ED_space_image_increment_snap_value(grid_size, grid_steps, zoom_factor); r_snap[1] = r_snap[0] / 2.0f; + + /* TODO: Implement snapping for custom grid sizes with `grid_steps[0] != grid_steps_y[0]`. + * r_snap_y[0] = ED_space_image_increment_snap_value(grid_size, grid_steps_y, zoom_factor); + * r_snap_y[1] = r_snap_y[0] / 2.0f; + */ } else if (t->spacetype == SPACE_CLIP) { r_snap[0] = 0.125f; diff --git a/source/blender/editors/transform/transform.h b/source/blender/editors/transform/transform.h index fc59787e1ec..09fc07f57f4 100644 --- a/source/blender/editors/transform/transform.h +++ b/source/blender/editors/transform/transform.h @@ -355,10 +355,12 @@ typedef struct MouseInput { /** Initial mouse position. */ int imval[2]; - bool precision; - float precision_factor; + float imval_unproj[3]; float center[2]; float factor; + float precision_factor; + bool precision; + /** Additional data, if needed by the particular function. */ void *data; @@ -618,6 +620,9 @@ typedef struct TransInfo { * value of the input parameter, except when a constrain is entered. */ float values_final[4]; + /** Cache safe value for constraints that require iteration or are slow to calculate. */ + float values_inside_constraints[4]; + /* Axis members for modes that use an axis separate from the orientation (rotate & shear). */ /** Primary axis, rotate only uses this. */ @@ -656,6 +661,9 @@ typedef struct TransInfo { /** Typically for mode settings. */ TransCustomDataContainer custom; + + /* Needed for sculpt transform. */ + const char *undo_name; } TransInfo; /** \} */ @@ -755,6 +763,7 @@ void applyMouseInput(struct TransInfo *t, struct MouseInput *mi, const int mval[2], float output[3]); +void transform_input_update(TransInfo *t, const float fac); void setCustomPoints(TransInfo *t, MouseInput *mi, const int start[2], const int end[2]); void setCustomPointsFromDirection(TransInfo *t, MouseInput *mi, const float dir[2]); @@ -803,6 +812,7 @@ void calculateCenter2D(TransInfo *t); void calculateCenterLocal(TransInfo *t, const float center_global[3]); void calculateCenter(TransInfo *t); +void tranformViewUpdate(TransInfo *t); /* API functions for getting center points */ void calculateCenterBound(TransInfo *t, float r_center[3]); diff --git a/source/blender/editors/transform/transform_constraints.c b/source/blender/editors/transform/transform_constraints.c index 658901a6991..d09bd99ef57 100644 --- a/source/blender/editors/transform/transform_constraints.c +++ b/source/blender/editors/transform/transform_constraints.c @@ -177,7 +177,7 @@ static void axisProjection(const TransInfo *t, const float in[3], float out[3]) { - float norm[3], vec[3], factor, angle; + float vec[3], factor, angle; float t_con_center[3]; if (is_zero_v3(in)) { @@ -214,7 +214,7 @@ static void axisProjection(const TransInfo *t, } else { float v[3]; - float norm_center[3]; + float norm[3], norm_center[3]; float plane[3]; view_vector_calc(t, t_con_center, norm_center); @@ -337,25 +337,20 @@ static bool isPlaneProjectionViewAligned(const TransInfo *t, const float plane[4 return fabsf(factor) < eps; } -static void planeProjection(const TransInfo *t, const float in[3], float out[3]) +static void planeProjection(const TransInfo *t, + const float plane[3], + const float in[3], + float out[3]) { - float vec[3], factor, norm[3]; - add_v3_v3v3(vec, in, t->center_global); - view_vector_calc(t, vec, norm); + float pos[3], view_vec[3], factor; - sub_v3_v3v3(vec, out, in); + add_v3_v3v3(pos, in, t->center_global); + view_vector_calc(t, pos, view_vec); - factor = dot_v3v3(vec, norm); - if (factor == 0.0f) { - return; /* prevent divide by zero */ + if (isect_ray_plane_v3(pos, view_vec, plane, &factor, false)) { + madd_v3_v3v3fl(out, in, view_vec, factor); } - factor = dot_v3v3(vec, vec) / factor; - - copy_v3_v3(vec, norm); - mul_v3_fl(vec, factor); - - add_v3_v3v3(out, in, vec); } static short transform_orientation_or_default(const TransInfo *t) @@ -397,7 +392,6 @@ static void applyAxisConstraintVec(const TransInfo *t, copy_v3_v3(out, in); if (!td && t->con.mode & CON_APPLY) { bool is_snap_to_point = false, is_snap_to_edge = false, is_snap_to_face = false; - mul_m3_v3(t->con.pmtx, out); if (activeSnap(t)) { if (validSnap(t)) { @@ -410,8 +404,11 @@ static void applyAxisConstraintVec(const TransInfo *t, } } - /* With snap points, a projection is alright, no adjustments needed. */ - if (!is_snap_to_point || is_snap_to_edge || is_snap_to_face) { + if (is_snap_to_point) { + /* With snap points, a projection is alright, no adjustments needed. */ + mul_m3_v3(t->con.pmtx, out); + } + else { const int dims = getConstraintSpaceDimension(t); if (dims == 2) { if (!is_zero_v3(out)) { @@ -428,7 +425,10 @@ static void applyAxisConstraintVec(const TransInfo *t, else { /* View alignment correction. */ if (!isPlaneProjectionViewAligned(t, plane)) { - planeProjection(t, in, out); + planeProjection(t, plane, in, out); + } + else { + mul_m3_v3(t->con.pmtx, out); } } } @@ -701,12 +701,12 @@ void setLocalConstraint(TransInfo *t, int mode, const char text[]) } } -void setUserConstraint(TransInfo *t, int mode, const char ftext[]) +void setUserConstraint(TransInfo *t, int mode, const char text_[]) { char text[256]; const short orientation = transform_orientation_or_default(t); const char *spacename = transform_orientations_spacename_get(t, orientation); - BLI_snprintf(text, sizeof(text), ftext, spacename); + BLI_snprintf(text, sizeof(text), text_, spacename); switch (orientation) { case V3D_ORIENT_LOCAL: diff --git a/source/blender/editors/transform/transform_constraints.h b/source/blender/editors/transform/transform_constraints.h index 9182330b729..90a693b089e 100644 --- a/source/blender/editors/transform/transform_constraints.h +++ b/source/blender/editors/transform/transform_constraints.h @@ -34,7 +34,7 @@ void setLocalConstraint(TransInfo *t, int mode, const char text[]); * `ftext` is a format string passed to #BLI_snprintf. It will add the name of * the orientation where %s is (logically). */ -void setUserConstraint(TransInfo *t, int mode, const char text[]); +void setUserConstraint(TransInfo *t, int mode, const char text_[]); void drawConstraint(TransInfo *t); /** * Called from drawview.c, as an extra per-window draw option. diff --git a/source/blender/editors/transform/transform_convert.c b/source/blender/editors/transform/transform_convert.c index d1c2af75274..1e29411fe84 100644 --- a/source/blender/editors/transform/transform_convert.c +++ b/source/blender/editors/transform/transform_convert.c @@ -940,15 +940,16 @@ static void init_TransDataContainers(TransInfo *t, bool free_objects = false; if (objects == NULL) { - objects = BKE_view_layer_array_from_objects_in_mode( + struct ObjectsInModeParams params = {0}; + params.object_mode = object_mode; + /* Pose transform operates on `ob->pose` so don't skip duplicate object-data. */ + params.no_dup_data = (object_mode & OB_MODE_POSE) == 0; + objects = BKE_view_layer_array_from_objects_in_mode_params( + t->scene, t->view_layer, (t->spacetype == SPACE_VIEW3D) ? t->view : NULL, &objects_len, - { - .object_mode = object_mode, - /* Pose transform operates on `ob->pose` so don't skip duplicate object-data. */ - .no_dup_data = (object_mode & OB_MODE_POSE) == 0, - }); + ¶ms); free_objects = true; } @@ -1000,7 +1001,8 @@ static void init_TransDataContainers(TransInfo *t, static TransConvertTypeInfo *convert_type_get(const TransInfo *t, Object **r_obj_armature) { ViewLayer *view_layer = t->view_layer; - Object *ob = OBACT(view_layer); + BKE_view_layer_synced_ensure(t->scene, t->view_layer); + Object *ob = BKE_view_layer_active_object_get(view_layer); /* if tests must match recalcData for correct updates */ if (t->options & CTX_CURSOR) { @@ -1143,8 +1145,8 @@ void createTransData(bContext *C, TransInfo *t) init_TransDataContainers(t, ob_armature, &ob_armature, 1); } else { - ViewLayer *view_layer = t->view_layer; - Object *ob = OBACT(view_layer); + BKE_view_layer_synced_ensure(t->scene, t->view_layer); + Object *ob = BKE_view_layer_active_object_get(t->view_layer); init_TransDataContainers(t, ob, NULL, 0); } diff --git a/source/blender/editors/transform/transform_convert_action.c b/source/blender/editors/transform/transform_convert_action.c index 41635522d26..8c6f2baf84a 100644 --- a/source/blender/editors/transform/transform_convert_action.c +++ b/source/blender/editors/transform/transform_convert_action.c @@ -18,6 +18,7 @@ #include "BKE_context.h" #include "BKE_gpencil.h" #include "BKE_key.h" +#include "BKE_layer.h" #include "BKE_mask.h" #include "BKE_nla.h" @@ -575,12 +576,14 @@ static void recalcData_actedit(TransInfo *t) bAnimListElem *ale; int filter; + BKE_view_layer_synced_ensure(t->scene, t->view_layer); + /* initialize relevant anim-context 'context' data from TransInfo data */ /* NOTE: sync this with the code in ANIM_animdata_get_context() */ ac.bmain = CTX_data_main(t->context); ac.scene = t->scene; ac.view_layer = t->view_layer; - ac.obact = OBACT(view_layer); + ac.obact = BKE_view_layer_active_object_get(view_layer); ac.area = t->area; ac.region = t->region; ac.sl = (t->area) ? t->area->spacedata.first : NULL; @@ -901,18 +904,18 @@ static void special_aftertrans_update__actedit(bContext *C, TransInfo *t) if (ELEM(t->frame_side, 'L', 'R')) { /* TFM_TIME_EXTEND */ /* same as below */ ED_markers_post_apply_transform( - ED_context_get_markers(C), t->scene, t->mode, t->values[0], t->frame_side); + ED_context_get_markers(C), t->scene, t->mode, t->values_final[0], t->frame_side); } else /* TFM_TIME_TRANSLATE */ #endif { ED_markers_post_apply_transform( - ED_context_get_markers(C), t->scene, t->mode, t->values[0], t->frame_side); + ED_context_get_markers(C), t->scene, t->mode, t->values_final[0], t->frame_side); } } else if (t->mode == TFM_TIME_SCALE) { ED_markers_post_apply_transform( - ED_context_get_markers(C), t->scene, t->mode, t->values[0], t->frame_side); + ED_context_get_markers(C), t->scene, t->mode, t->values_final[0], t->frame_side); } } diff --git a/source/blender/editors/transform/transform_convert_armature.c b/source/blender/editors/transform/transform_convert_armature.c index 97d9ab2964a..d83cca15219 100644 --- a/source/blender/editors/transform/transform_convert_armature.c +++ b/source/blender/editors/transform/transform_convert_armature.c @@ -1356,7 +1356,7 @@ static void pose_transform_mirror_update(TransInfo *t, TransDataContainer *tc, O } mul_v3_m4v3(data->grabtarget, flip_mtx, td->loc); if (pid) { - /* TODO(germano): Relative Mirror support. */ + /* TODO(@germano): Relative Mirror support. */ } data->flag |= CONSTRAINT_IK_AUTO; /* Add a temporary auto IK constraint here, as we will only temporarily active this diff --git a/source/blender/editors/transform/transform_convert_gpencil.c b/source/blender/editors/transform/transform_convert_gpencil.c index 0029eaefaba..b3d58f25ad3 100644 --- a/source/blender/editors/transform/transform_convert_gpencil.c +++ b/source/blender/editors/transform/transform_convert_gpencil.c @@ -19,6 +19,7 @@ #include "BKE_gpencil.h" #include "BKE_gpencil_curve.h" #include "BKE_gpencil_geom.h" +#include "BKE_layer.h" #include "ED_gpencil.h" #include "ED_keyframing.h" @@ -681,7 +682,8 @@ static void createTransGPencil(bContext *C, TransInfo *t) Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C); const Scene *scene = CTX_data_scene(C); ToolSettings *ts = scene->toolsettings; - Object *obact = OBACT(t->view_layer); + BKE_view_layer_synced_ensure(t->scene, t->view_layer); + Object *obact = BKE_view_layer_active_object_get(t->view_layer); bGPdata *gpd = obact->data; BLI_assert(gpd != NULL); diff --git a/source/blender/editors/transform/transform_convert_graph.c b/source/blender/editors/transform/transform_convert_graph.c index aca2439d5fb..27e6c8a25e1 100644 --- a/source/blender/editors/transform/transform_convert_graph.c +++ b/source/blender/editors/transform/transform_convert_graph.c @@ -14,6 +14,7 @@ #include "BKE_context.h" #include "BKE_fcurve.h" +#include "BKE_layer.h" #include "BKE_nla.h" #include "BKE_report.h" @@ -638,7 +639,7 @@ static bool fcu_test_selected(FCurve *fcu) return 0; } -/* this function is called on recalcData to apply the transforms applied +/* This function is called on recalcData to apply the transforms applied * to the transdata on to the actual keyframe data */ static void flushTransGraphData(TransInfo *t) @@ -907,12 +908,14 @@ static void recalcData_graphedit(TransInfo *t) bAnimListElem *ale; int dosort = 0; + BKE_view_layer_synced_ensure(t->scene, t->view_layer); + /* initialize relevant anim-context 'context' data from TransInfo data */ /* NOTE: sync this with the code in ANIM_animdata_get_context() */ ac.bmain = CTX_data_main(t->context); ac.scene = t->scene; ac.view_layer = t->view_layer; - ac.obact = OBACT(view_layer); + ac.obact = BKE_view_layer_active_object_get(view_layer); ac.area = t->area; ac.region = t->region; ac.sl = (t->area) ? t->area->spacedata.first : NULL; diff --git a/source/blender/editors/transform/transform_convert_mesh_edge.c b/source/blender/editors/transform/transform_convert_mesh_edge.c index becf3c7ce5a..7f26029850b 100644 --- a/source/blender/editors/transform/transform_convert_mesh_edge.c +++ b/source/blender/editors/transform/transform_convert_mesh_edge.c @@ -67,12 +67,16 @@ static void createTransEdge(bContext *UNUSED(C), TransInfo *t) /* create data we need */ if (t->mode == TFM_BWEIGHT) { - BM_mesh_cd_flag_ensure(em->bm, BKE_mesh_from_object(tc->obedit), ME_CDFLAG_EDGE_BWEIGHT); + if (!CustomData_has_layer(&em->bm->edata, CD_BWEIGHT)) { + BM_data_layer_add(em->bm, &em->bm->edata, CD_BWEIGHT); + } cd_edge_float_offset = CustomData_get_offset(&em->bm->edata, CD_BWEIGHT); } else { /* if (t->mode == TFM_EDGE_CREASE) { */ BLI_assert(t->mode == TFM_EDGE_CREASE); - BM_mesh_cd_flag_ensure(em->bm, BKE_mesh_from_object(tc->obedit), ME_CDFLAG_EDGE_CREASE); + if (!CustomData_has_layer(&em->bm->edata, CD_CREASE)) { + BM_data_layer_add(em->bm, &em->bm->edata, CD_CREASE); + } cd_edge_float_offset = CustomData_get_offset(&em->bm->edata, CD_CREASE); } diff --git a/source/blender/editors/transform/transform_convert_mesh_uv.c b/source/blender/editors/transform/transform_convert_mesh_uv.c index f3bef2c283b..4f15fc240d3 100644 --- a/source/blender/editors/transform/transform_convert_mesh_uv.c +++ b/source/blender/editors/transform/transform_convert_mesh_uv.c @@ -74,8 +74,12 @@ static void UVsToTransData(const float aspect[2], /** * \param dists: Store the closest connected distance to selected vertices. */ -static void uv_set_connectivity_distance(BMesh *bm, float *dists, const float aspect[2]) +static void uv_set_connectivity_distance(const ToolSettings *ts, + BMesh *bm, + float *dists, + const float aspect[2]) { +#define TMP_LOOP_SELECT_TAG BM_ELEM_TAG_ALT /* Mostly copied from #transform_convert_mesh_connectivity_distance. */ BLI_LINKSTACK_DECLARE(queue, BMLoop *); @@ -101,15 +105,15 @@ static void uv_set_connectivity_distance(BMesh *bm, float *dists, const float as BM_ITER_ELEM (l, &liter, f, BM_LOOPS_OF_FACE) { float dist; - MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); - - bool uv_vert_sel = luv->flag & MLOOPUV_VERTSEL; + bool uv_vert_sel = uvedit_uv_select_test_ex(ts, l, cd_loop_uv_offset); if (uv_vert_sel) { BLI_LINKSTACK_PUSH(queue, l); + BM_elem_flag_enable(l, TMP_LOOP_SELECT_TAG); dist = 0.0f; } else { + BM_elem_flag_disable(l, TMP_LOOP_SELECT_TAG); dist = FLT_MAX; } @@ -164,7 +168,7 @@ static void uv_set_connectivity_distance(BMesh *bm, float *dists, const float as bool other_vert_sel, connected_vert_sel; - other_vert_sel = luv_other->flag & MLOOPUV_VERTSEL; + other_vert_sel = BM_elem_flag_test_bool(l_other, TMP_LOOP_SELECT_TAG); BM_ITER_ELEM (l_connected, &l_connected_iter, l_other->v, BM_LOOPS_OF_VERT) { if (l_connected == l_other) { @@ -176,7 +180,7 @@ static void uv_set_connectivity_distance(BMesh *bm, float *dists, const float as } MLoopUV *luv_connected = BM_ELEM_CD_GET_VOID_P(l_connected, cd_loop_uv_offset); - connected_vert_sel = luv_connected->flag & MLOOPUV_VERTSEL; + connected_vert_sel = BM_elem_flag_test_bool(l_connected, TMP_LOOP_SELECT_TAG); /* Check if this loop is connected in UV space. * If the uv loops share the same selection state (if not, they are not connected as @@ -232,6 +236,7 @@ static void uv_set_connectivity_distance(BMesh *bm, float *dists, const float as BLI_LINKSTACK_FREE(queue_next); MEM_freeN(dists_prev); +#undef TMP_LOOP_SELECT_TAG } static void createTransUVs(bContext *C, TransInfo *t) @@ -265,7 +270,7 @@ static void createTransUVs(bContext *C, TransInfo *t) /* count */ if (is_island_center) { /* create element map with island information */ - elementmap = BM_uv_element_map_create(em->bm, scene, true, false, true); + elementmap = BM_uv_element_map_create(em->bm, scene, true, false, true, true); if (elementmap == NULL) { continue; } @@ -337,7 +342,7 @@ static void createTransUVs(bContext *C, TransInfo *t) if (is_prop_connected) { prop_dists = MEM_callocN(em->bm->totloop * sizeof(float), "TransObPropDists(UV Editing)"); - uv_set_connectivity_distance(em->bm, prop_dists, t->aspect); + uv_set_connectivity_distance(t->settings, em->bm, prop_dists, t->aspect); } BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { @@ -399,8 +404,8 @@ static void createTransUVs(bContext *C, TransInfo *t) static void flushTransUVs(TransInfo *t) { SpaceImage *sima = t->area->spacedata.first; - const bool use_pixel_snap = ((sima->pixel_snap_mode != SI_PIXEL_SNAP_DISABLED) && - (t->state != TRANS_CANCEL)); + const bool use_pixel_round = ((sima->pixel_round_mode != SI_PIXEL_ROUND_DISABLED) && + (t->state != TRANS_CANCEL)); FOREACH_TRANS_DATA_CONTAINER (t, tc) { TransData2D *td; @@ -410,7 +415,7 @@ static void flushTransUVs(TransInfo *t) aspect_inv[0] = 1.0f / t->aspect[0]; aspect_inv[1] = 1.0f / t->aspect[1]; - if (use_pixel_snap) { + if (use_pixel_round) { int size_i[2]; ED_space_image_get_size(sima, &size_i[0], &size_i[1]); size[0] = size_i[0]; @@ -422,16 +427,16 @@ static void flushTransUVs(TransInfo *t) td->loc2d[0] = td->loc[0] * aspect_inv[0]; td->loc2d[1] = td->loc[1] * aspect_inv[1]; - if (use_pixel_snap) { + if (use_pixel_round) { td->loc2d[0] *= size[0]; td->loc2d[1] *= size[1]; - switch (sima->pixel_snap_mode) { - case SI_PIXEL_SNAP_CENTER: + switch (sima->pixel_round_mode) { + case SI_PIXEL_ROUND_CENTER: td->loc2d[0] = roundf(td->loc2d[0] - 0.5f) + 0.5f; td->loc2d[1] = roundf(td->loc2d[1] - 0.5f) + 0.5f; break; - case SI_PIXEL_SNAP_CORNER: + case SI_PIXEL_ROUND_CORNER: td->loc2d[0] = roundf(td->loc2d[0]); td->loc2d[1] = roundf(td->loc2d[1]); break; diff --git a/source/blender/editors/transform/transform_convert_mesh_vert_cdata.c b/source/blender/editors/transform/transform_convert_mesh_vert_cdata.c index f05688f3325..e0b346945c3 100644 --- a/source/blender/editors/transform/transform_convert_mesh_vert_cdata.c +++ b/source/blender/editors/transform/transform_convert_mesh_vert_cdata.c @@ -84,11 +84,15 @@ static void createTransMeshVertCData(bContext *UNUSED(C), TransInfo *t) int cd_offset = -1; if (t->mode == TFM_BWEIGHT) { - BM_mesh_cd_flag_ensure(bm, me, ME_CDFLAG_VERT_BWEIGHT); + if (!CustomData_has_layer(&bm->vdata, CD_BWEIGHT)) { + BM_data_layer_add(bm, &bm->vdata, CD_BWEIGHT); + } cd_offset = CustomData_get_offset(&bm->vdata, CD_BWEIGHT); } else { - BM_mesh_cd_flag_ensure(bm, me, ME_CDFLAG_VERT_CREASE); + if (!CustomData_has_layer(&bm->edata, CD_CREASE)) { + BM_data_layer_add(bm, &bm->edata, CD_CREASE); + } cd_offset = CustomData_get_offset(&bm->vdata, CD_CREASE); } diff --git a/source/blender/editors/transform/transform_convert_node.c b/source/blender/editors/transform/transform_convert_node.c index e18f75b71ae..ed19789fdd8 100644 --- a/source/blender/editors/transform/transform_convert_node.c +++ b/source/blender/editors/transform/transform_convert_node.c @@ -27,6 +27,13 @@ #include "transform_convert.h" #include "transform_snap.h" +struct TransCustomDataNode { + View2DEdgePanData edgepan_data; + + /* Compare if the view has changed so we can update with `transformViewUpdate`. */ + rctf viewrect_prev; +}; + /* -------------------------------------------------------------------- */ /** \name Node Transform Creation * \{ */ @@ -95,15 +102,17 @@ static void createTransNodeData(bContext *UNUSED(C), TransInfo *t) SpaceNode *snode = t->area->spacedata.first; /* Custom data to enable edge panning during the node transform */ - View2DEdgePanData *customdata = MEM_callocN(sizeof(*customdata), __func__); + struct TransCustomDataNode *customdata = MEM_callocN(sizeof(*customdata), __func__); UI_view2d_edge_pan_init(t->context, - customdata, + &customdata->edgepan_data, NODE_EDGE_PAN_INSIDE_PAD, NODE_EDGE_PAN_OUTSIDE_PAD, NODE_EDGE_PAN_SPEED_RAMP, NODE_EDGE_PAN_MAX_SPEED, NODE_EDGE_PAN_DELAY, NODE_EDGE_PAN_ZOOM_INFLUENCE); + customdata->viewrect_prev = customdata->edgepan_data.initial_rect; + t->custom.type.data = customdata; t->custom.type.use_free = true; @@ -154,11 +163,11 @@ static void flushTransNodes(TransInfo *t) { const float dpi_fac = UI_DPI_FAC; - View2DEdgePanData *customdata = (View2DEdgePanData *)t->custom.type.data; + struct TransCustomDataNode *customdata = (struct TransCustomDataNode *)t->custom.type.data; if (t->options & CTX_VIEW2D_EDGE_PAN) { if (t->state == TRANS_CANCEL) { - UI_view2d_edge_pan_cancel(t->context, customdata); + UI_view2d_edge_pan_cancel(t->context, &customdata->edgepan_data); } else { /* Edge panning functions expect window coordinates, mval is relative to region */ @@ -166,13 +175,19 @@ static void flushTransNodes(TransInfo *t) t->region->winrct.xmin + t->mval[0], t->region->winrct.ymin + t->mval[1], }; - UI_view2d_edge_pan_apply(t->context, customdata, xy); + UI_view2d_edge_pan_apply(t->context, &customdata->edgepan_data, xy); } } - /* Initial and current view2D rects for additional transform due to view panning and zooming */ - const rctf *rect_src = &customdata->initial_rect; - const rctf *rect_dst = &t->region->v2d.cur; + float offset[2] = {0.0f, 0.0f}; + if (t->state != TRANS_CANCEL) { + if (!BLI_rctf_compare(&customdata->viewrect_prev, &t->region->v2d.cur, FLT_EPSILON)) { + /* Additional offset due to change in view2D rect. */ + BLI_rctf_transform_pt_v(&t->region->v2d.cur, &customdata->viewrect_prev, offset, offset); + tranformViewUpdate(t); + customdata->viewrect_prev = t->region->v2d.cur; + } + } FOREACH_TRANS_DATA_CONTAINER (t, tc) { applyGridAbsolute(t); @@ -184,10 +199,7 @@ static void flushTransNodes(TransInfo *t) bNode *node = td->extra; float loc[2]; - copy_v2_v2(loc, td2d->loc); - - /* additional offset due to change in view2D rect */ - BLI_rctf_transform_pt_v(rect_dst, rect_src, loc, loc); + add_v2_v2v2(loc, td2d->loc, offset); #ifdef USE_NODE_CENTER loc[0] -= 0.5f * BLI_rctf_size_x(&node->totr); diff --git a/source/blender/editors/transform/transform_convert_object.c b/source/blender/editors/transform/transform_convert_object.c index be5f59c61c0..caa11fa5db4 100644 --- a/source/blender/editors/transform/transform_convert_object.c +++ b/source/blender/editors/transform/transform_convert_object.c @@ -291,9 +291,10 @@ static void ObjectToTransData(TransInfo *t, TransData *td, Object *ob) } } -static void trans_object_base_deps_flag_prepare(ViewLayer *view_layer) +static void trans_object_base_deps_flag_prepare(const Scene *scene, ViewLayer *view_layer) { - LISTBASE_FOREACH (Base *, base, &view_layer->object_bases) { + BKE_view_layer_synced_ensure(scene, view_layer); + LISTBASE_FOREACH (Base *, base, BKE_view_layer_object_bases_get(view_layer)) { base->object->id.tag &= ~LIB_TAG_DOIT; } } @@ -323,11 +324,14 @@ static void flush_trans_object_base_deps_flag(Depsgraph *depsgraph, Object *obje NULL); } -static void trans_object_base_deps_flag_finish(const TransInfo *t, ViewLayer *view_layer) +static void trans_object_base_deps_flag_finish(const TransInfo *t, + const Scene *scene, + ViewLayer *view_layer) { if ((t->options & CTX_OBMODE_XFORM_OBDATA) == 0) { - LISTBASE_FOREACH (Base *, base, &view_layer->object_bases) { + BKE_view_layer_synced_ensure(scene, view_layer); + LISTBASE_FOREACH (Base *, base, BKE_view_layer_object_bases_get(view_layer)) { if (base->object->id.tag & LIB_TAG_DOIT) { base->flag_legacy |= BA_SNAP_FIX_DEPS_FIASCO; } @@ -352,13 +356,14 @@ static void set_trans_object_base_flags(TransInfo *t) return; } /* Makes sure base flags and object flags are identical. */ - BKE_scene_base_flag_to_objects(t->view_layer); + BKE_scene_base_flag_to_objects(t->scene, t->view_layer); /* Make sure depsgraph is here. */ DEG_graph_relations_update(depsgraph); /* Clear all flags we need. It will be used to detect dependencies. */ - trans_object_base_deps_flag_prepare(view_layer); + trans_object_base_deps_flag_prepare(scene, view_layer); /* Traverse all bases and set all possible flags. */ - LISTBASE_FOREACH (Base *, base, &view_layer->object_bases) { + BKE_view_layer_synced_ensure(scene, view_layer); + LISTBASE_FOREACH (Base *, base, BKE_view_layer_object_bases_get(view_layer)) { base->flag_legacy &= ~(BA_WAS_SEL | BA_TRANSFORM_LOCKED_IN_PLACE); if (BASE_SELECTED_EDITABLE(v3d, base)) { Object *ob = base->object; @@ -392,7 +397,7 @@ static void set_trans_object_base_flags(TransInfo *t) /* Store temporary bits in base indicating that base is being modified * (directly or indirectly) by transforming objects. */ - trans_object_base_deps_flag_finish(t, view_layer); + trans_object_base_deps_flag_finish(t, scene, view_layer); } static bool mark_children(Object *ob) @@ -420,11 +425,11 @@ static int count_proportional_objects(TransInfo *t) Scene *scene = t->scene; Depsgraph *depsgraph = BKE_scene_ensure_depsgraph(bmain, scene, view_layer); /* Clear all flags we need. It will be used to detect dependencies. */ - trans_object_base_deps_flag_prepare(view_layer); + trans_object_base_deps_flag_prepare(scene, view_layer); /* Rotations around local centers are allowed to propagate, so we take all objects. */ if (!((t->around == V3D_AROUND_LOCAL_ORIGINS) && (ELEM(t->mode, TFM_ROTATION, TFM_TRACKBALL)))) { /* Mark all parents. */ - LISTBASE_FOREACH (Base *, base, &view_layer->object_bases) { + LISTBASE_FOREACH (Base *, base, BKE_view_layer_object_bases_get(view_layer)) { if (BASE_SELECTED_EDITABLE(v3d, base) && BASE_SELECTABLE(v3d, base)) { Object *parent = base->object->parent; /* flag all parents */ @@ -435,7 +440,7 @@ static int count_proportional_objects(TransInfo *t) } } /* Mark all children. */ - LISTBASE_FOREACH (Base *, base, &view_layer->object_bases) { + LISTBASE_FOREACH (Base *, base, BKE_view_layer_object_bases_get(view_layer)) { /* all base not already selected or marked that is editable */ if ((base->object->flag & (BA_TRANSFORM_CHILD | BA_TRANSFORM_PARENT)) == 0 && (base->flag & BASE_SELECTED) == 0 && @@ -445,7 +450,7 @@ static int count_proportional_objects(TransInfo *t) } } /* Flush changed flags to all dependencies. */ - LISTBASE_FOREACH (Base *, base, &view_layer->object_bases) { + LISTBASE_FOREACH (Base *, base, BKE_view_layer_object_bases_get(view_layer)) { Object *ob = base->object; /* If base is not selected, not a parent of selection or not a child of * selection and it is editable and selectable. @@ -460,16 +465,17 @@ static int count_proportional_objects(TransInfo *t) /* Store temporary bits in base indicating that base is being modified * (directly or indirectly) by transforming objects. */ - trans_object_base_deps_flag_finish(t, view_layer); + trans_object_base_deps_flag_finish(t, scene, view_layer); return total; } static void clear_trans_object_base_flags(TransInfo *t) { + Scene *scene = t->scene; ViewLayer *view_layer = t->view_layer; - Base *base; - for (base = view_layer->object_bases.first; base; base = base->next) { + BKE_view_layer_synced_ensure(scene, view_layer); + LISTBASE_FOREACH (Base *, base, BKE_view_layer_object_bases_get(view_layer)) { if (base->flag_legacy & BA_WAS_SEL) { ED_object_base_select(base, BA_SELECT); } @@ -559,11 +565,12 @@ static void createTransObject(bContext *C, TransInfo *t) CTX_DATA_END; if (is_prop_edit) { + Scene *scene = t->scene; ViewLayer *view_layer = t->view_layer; View3D *v3d = t->view; - Base *base; - for (base = view_layer->object_bases.first; base; base = base->next) { + BKE_view_layer_synced_ensure(scene, view_layer); + LISTBASE_FOREACH (Base *, base, BKE_view_layer_object_bases_get(view_layer)) { Object *ob = base->object; /* if base is not selected, not a parent of selection @@ -592,10 +599,12 @@ static void createTransObject(bContext *C, TransInfo *t) } } + Scene *scene = t->scene; ViewLayer *view_layer = t->view_layer; View3D *v3d = t->view; - LISTBASE_FOREACH (Base *, base, &view_layer->object_bases) { + BKE_view_layer_synced_ensure(scene, view_layer); + LISTBASE_FOREACH (Base *, base, BKE_view_layer_object_bases_get(view_layer)) { Object *ob = base->object; /* if base is not selected, not a parent of selection @@ -640,9 +649,11 @@ static void createTransObject(bContext *C, TransInfo *t) } } + Scene *scene = t->scene; ViewLayer *view_layer = t->view_layer; - LISTBASE_FOREACH (Base *, base, &view_layer->object_bases) { + BKE_view_layer_synced_ensure(scene, view_layer); + LISTBASE_FOREACH (Base *, base, BKE_view_layer_object_bases_get(view_layer)) { Object *ob = base->object; if (ob->parent != NULL) { if (ob->parent && !BLI_gset_haskey(objects_in_transdata, ob->parent) && @@ -672,7 +683,7 @@ static void createTransObject(bContext *C, TransInfo *t) } } - LISTBASE_FOREACH (Base *, base, &view_layer->object_bases) { + LISTBASE_FOREACH (Base *, base, BKE_view_layer_object_bases_get(view_layer)) { Object *ob = base->object; if (BASE_XFORM_INDIRECT(base) || BLI_gset_haskey(objects_in_transdata, ob)) { @@ -782,7 +793,8 @@ static void autokeyframe_object( } else if (ELEM(tmode, TFM_ROTATION, TFM_TRACKBALL)) { if (scene->toolsettings->transform_pivot_point == V3D_AROUND_ACTIVE) { - if (ob != OBACT(view_layer)) { + BKE_view_layer_synced_ensure(scene, view_layer); + if (ob != BKE_view_layer_active_object_get(view_layer)) { do_loc = true; } } @@ -796,7 +808,8 @@ static void autokeyframe_object( } else if (tmode == TFM_RESIZE) { if (scene->toolsettings->transform_pivot_point == V3D_AROUND_ACTIVE) { - if (ob != OBACT(view_layer)) { + BKE_view_layer_synced_ensure(scene, view_layer); + if (ob != BKE_view_layer_active_object_get(view_layer)) { do_loc = true; } } diff --git a/source/blender/editors/transform/transform_convert_object_texspace.c b/source/blender/editors/transform/transform_convert_object_texspace.c index 39bf22a9af9..839bf6b77b3 100644 --- a/source/blender/editors/transform/transform_convert_object_texspace.c +++ b/source/blender/editors/transform/transform_convert_object_texspace.c @@ -11,6 +11,7 @@ #include "BKE_animsys.h" #include "BKE_context.h" +#include "BKE_layer.h" #include "BKE_object.h" #include "BKE_report.h" @@ -37,7 +38,8 @@ static void createTransTexspace(bContext *UNUSED(C), TransInfo *t) ID *id; char *texflag; - ob = OBACT(view_layer); + BKE_view_layer_synced_ensure(t->scene, t->view_layer); + ob = BKE_view_layer_active_object_get(view_layer); if (ob == NULL) { /* Shouldn't logically happen, but still. */ return; diff --git a/source/blender/editors/transform/transform_convert_particle.c b/source/blender/editors/transform/transform_convert_particle.c index 41f37b34af0..3e056b6a048 100644 --- a/source/blender/editors/transform/transform_convert_particle.c +++ b/source/blender/editors/transform/transform_convert_particle.c @@ -13,6 +13,7 @@ #include "BLI_math.h" #include "BKE_context.h" +#include "BKE_layer.h" #include "BKE_particle.h" #include "BKE_pointcache.h" @@ -34,7 +35,8 @@ static void createTransParticleVerts(bContext *UNUSED(C), TransInfo *t) TransData *td = NULL; TransDataExtension *tx; - Object *ob = OBACT(t->view_layer); + BKE_view_layer_synced_ensure(t->scene, t->view_layer); + Object *ob = BKE_view_layer_active_object_get(t->view_layer); ParticleEditSettings *pset = PE_settings(t->scene); PTCacheEdit *edit = PE_get_current(t->depsgraph, t->scene, ob); ParticleSystem *psys = NULL; @@ -183,7 +185,8 @@ static 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); + BKE_view_layer_synced_ensure(scene, view_layer); + Object *ob = BKE_view_layer_active_object_get(view_layer); PTCacheEdit *edit = PE_get_current(t->depsgraph, scene, ob); ParticleSystem *psys = edit->psys; PTCacheEditPoint *point; @@ -223,7 +226,7 @@ static void flushTransParticles(TransInfo *t) } } - PE_update_object(t->depsgraph, scene, OBACT(view_layer), 1); + PE_update_object(t->depsgraph, scene, ob, 1); BKE_particle_batch_cache_dirty_tag(psys, BKE_PARTICLE_BATCH_DIRTY_ALL); DEG_id_tag_update(&ob->id, ID_RECALC_PSYS_REDO); } diff --git a/source/blender/editors/transform/transform_convert_sculpt.c b/source/blender/editors/transform/transform_convert_sculpt.c index 95958b816ab..3792cfefe06 100644 --- a/source/blender/editors/transform/transform_convert_sculpt.c +++ b/source/blender/editors/transform/transform_convert_sculpt.c @@ -10,6 +10,7 @@ #include "BLI_math.h" #include "BKE_context.h" +#include "BKE_layer.h" #include "BKE_lib_id.h" #include "BKE_paint.h" #include "BKE_report.h" @@ -33,7 +34,8 @@ static void createTransSculpt(bContext *C, TransInfo *t) return; } - Object *ob = OBACT(t->view_layer); + BKE_view_layer_synced_ensure(t->scene, t->view_layer); + Object *ob = BKE_view_layer_active_object_get(t->view_layer); SculptSession *ss = ob->sculpt; { @@ -85,7 +87,7 @@ static void createTransSculpt(bContext *C, TransInfo *t) copy_m3_m4(td->axismtx, ob->obmat); BLI_assert(!(t->options & CTX_PAINT_CURVE)); - ED_sculpt_init_transform(C, ob); + ED_sculpt_init_transform(C, ob, t->undo_name); } /** \} */ @@ -96,7 +98,8 @@ static void createTransSculpt(bContext *C, TransInfo *t) static void recalcData_sculpt(TransInfo *t) { - Object *ob = OBACT(t->view_layer); + BKE_view_layer_synced_ensure(t->scene, t->view_layer); + Object *ob = BKE_view_layer_active_object_get(t->view_layer); ED_sculpt_update_modal_transform(t->context, ob); } @@ -108,7 +111,8 @@ static void special_aftertrans_update__sculpt(bContext *C, TransInfo *t) return; } - Object *ob = OBACT(t->view_layer); + BKE_view_layer_synced_ensure(t->scene, t->view_layer); + Object *ob = BKE_view_layer_active_object_get(t->view_layer); BLI_assert(!(t->options & CTX_PAINT_CURVE)); ED_sculpt_end_transform(C, ob); } diff --git a/source/blender/editors/transform/transform_convert_sequencer.c b/source/blender/editors/transform/transform_convert_sequencer.c index eefc9d0cc2a..ddc99caeef5 100644 --- a/source/blender/editors/transform/transform_convert_sequencer.c +++ b/source/blender/editors/transform/transform_convert_sequencer.c @@ -708,12 +708,12 @@ static void special_aftertrans_update__sequencer(bContext *UNUSED(C), TransInfo if (t->mode == TFM_SEQ_SLIDE) { if (t->frame_side == 'B') { ED_markers_post_apply_transform( - &t->scene->markers, t->scene, TFM_TIME_TRANSLATE, t->values[0], t->frame_side); + &t->scene->markers, t->scene, TFM_TIME_TRANSLATE, t->values_final[0], t->frame_side); } } else if (ELEM(t->frame_side, 'L', 'R')) { ED_markers_post_apply_transform( - &t->scene->markers, t->scene, TFM_TIME_EXTEND, t->values[0], t->frame_side); + &t->scene->markers, t->scene, TFM_TIME_EXTEND, t->values_final[0], t->frame_side); } } } diff --git a/source/blender/editors/transform/transform_draw_cursors.c b/source/blender/editors/transform/transform_draw_cursors.c index 42942493dc3..b5a8decc390 100644 --- a/source/blender/editors/transform/transform_draw_cursors.c +++ b/source/blender/editors/transform/transform_draw_cursors.c @@ -116,7 +116,7 @@ void transform_draw_cursor_draw(bContext *UNUSED(C), int x, int y, void *customd /* Dashed lines first. */ if (ELEM(t->helpline, HLP_SPRING, HLP_ANGLE)) { GPU_line_width(DASH_WIDTH); - immBindBuiltinProgram(GPU_SHADER_2D_LINE_DASHED_UNIFORM_COLOR); + immBindBuiltinProgram(GPU_SHADER_3D_LINE_DASHED_UNIFORM_COLOR); immUniform2f("viewport_size", viewport_size[2], viewport_size[3]); immUniform1i("colors_len", 0); /* "simple" mode */ immUniformThemeColor3(TH_VIEW_OVERLAY); diff --git a/source/blender/editors/transform/transform_generics.c b/source/blender/editors/transform/transform_generics.c index 56a7d045dfd..03c53e1b3d2 100644 --- a/source/blender/editors/transform/transform_generics.c +++ b/source/blender/editors/transform/transform_generics.c @@ -176,7 +176,8 @@ void initTransInfo(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *eve { Scene *sce = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); - Object *obact = OBACT(view_layer); + BKE_view_layer_synced_ensure(sce, view_layer); + Object *obact = BKE_view_layer_active_object_get(view_layer); const eObjectMode object_mode = obact ? obact->mode : OB_MODE_OBJECT; ToolSettings *ts = CTX_data_tool_settings(C); ARegion *region = CTX_wm_region(C); @@ -333,7 +334,8 @@ void initTransInfo(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *eve } else if (t->spacetype == SPACE_IMAGE) { SpaceImage *sima = area->spacedata.first; - if (ED_space_image_show_uvedit(sima, OBACT(t->view_layer))) { + BKE_view_layer_synced_ensure(t->scene, t->view_layer); + if (ED_space_image_show_uvedit(sima, BKE_view_layer_active_object_get(t->view_layer))) { /* UV transform */ } else if (sima->mode == SI_MODE_MASK) { @@ -1066,8 +1068,8 @@ bool calculateCenterActive(TransInfo *t, bool select_only, float r_center[3]) } } else if (t->options & CTX_POSE_BONE) { - ViewLayer *view_layer = t->view_layer; - Object *ob = OBACT(view_layer); + BKE_view_layer_synced_ensure(t->scene, t->view_layer); + Object *ob = BKE_view_layer_active_object_get(t->view_layer); if (ED_object_calc_active_center_for_posemode(ob, select_only, r_center)) { mul_m4_v3(ob->obmat, r_center); return true; @@ -1083,11 +1085,10 @@ bool calculateCenterActive(TransInfo *t, bool select_only, float r_center[3]) } else { /* object mode */ - ViewLayer *view_layer = t->view_layer; - Object *ob = OBACT(view_layer); - Base *base = BASACT(view_layer); - if (ob && ((!select_only) || ((base->flag & BASE_SELECTED) != 0))) { - copy_v3_v3(r_center, ob->obmat[3]); + BKE_view_layer_synced_ensure(t->scene, t->view_layer); + Base *base = BKE_view_layer_active_base_get(t->view_layer); + if (base && ((!select_only) || ((base->flag & BASE_SELECTED) != 0))) { + copy_v3_v3(r_center, base->object->obmat[3]); return true; } } @@ -1132,6 +1133,33 @@ static void calculateCenter_FromAround(TransInfo *t, int around, float r_center[ } } +static void calculateZfac(TransInfo *t) +{ + /* ED_view3d_calc_zfac() defines a factor for perspective depth correction, + * used in ED_view3d_win_to_delta() */ + + /* zfac is only used convertViewVec only in cases operator was invoked in RGN_TYPE_WINDOW + * and never used in other cases. + * + * We need special case here as well, since ED_view3d_calc_zfac will crash when called + * for a region different from RGN_TYPE_WINDOW. + */ + if ((t->spacetype == SPACE_VIEW3D) && (t->region->regiontype == RGN_TYPE_WINDOW)) { + t->zfac = ED_view3d_calc_zfac(t->region->regiondata, t->center_global); + } + else if (t->spacetype == SPACE_IMAGE) { + SpaceImage *sima = t->area->spacedata.first; + t->zfac = 1.0f / sima->zoom; + } + else if (t->region) { + View2D *v2d = &t->region->v2d; + /* Get zoom fac the same way as in + * `ui_view2d_curRect_validate_resize` - better keep in sync! */ + const float zoomx = (float)(BLI_rcti_size_x(&v2d->mask) + 1) / BLI_rctf_size_x(&v2d->cur); + t->zfac = 1.0f / zoomx; + } +} + void calculateCenter(TransInfo *t) { if ((t->flag & T_OVERRIDE_CENTER) == 0) { @@ -1166,22 +1194,46 @@ void calculateCenter(TransInfo *t) } } - if (t->spacetype == SPACE_VIEW3D) { - /* #ED_view3d_calc_zfac() defines a factor for perspective depth correction, - * used in #ED_view3d_win_to_delta(). */ + calculateZfac(t); +} - /* NOTE: `t->zfac` is only used #convertViewVec only in cases operator was invoked in - * #RGN_TYPE_WINDOW and never used in other cases. - * - * We need special case here as well, since #ED_view3d_calc_zfac will crash when called - * for a region different from #RGN_TYPE_WINDOW. */ - if (t->region->regiontype == RGN_TYPE_WINDOW) { - t->zfac = ED_view3d_calc_zfac(t->region->regiondata, t->center_global); +/* Called every time the view changes due to navigation. + * Adjusts the mouse position relative to the object. */ +void tranformViewUpdate(TransInfo *t) +{ + float zoom_prev = t->zfac; + float zoom_new; + if ((t->spacetype == SPACE_VIEW3D) && (t->region->regiontype == RGN_TYPE_WINDOW)) { + if (!t->persp) { + zoom_prev *= len_v3(t->persinv[0]); } - else { - t->zfac = 0.0f; + + setTransformViewMatrices(t); + calculateZfac(t); + + zoom_new = t->zfac; + if (!t->persp) { + zoom_new *= len_v3(t->persinv[0]); + } + + for (int i = 0; i < ARRAY_SIZE(t->orient); i++) { + if (t->orient[i].type == V3D_ORIENT_VIEW) { + copy_m3_m4(t->orient[i].matrix, t->viewinv); + normalize_m3(t->orient[i].matrix); + if (t->orient_curr == i) { + copy_m3_m3(t->spacemtx, t->orient[i].matrix); + invert_m3_m3_safe_ortho(t->spacemtx_inv, t->spacemtx); + } + } } } + else { + calculateZfac(t); + zoom_new = t->zfac; + } + + calculateCenter2D(t); + transform_input_update(t, zoom_prev / zoom_new); } void calculatePropRatio(TransInfo *t) @@ -1413,6 +1465,7 @@ Object *transform_object_deform_pose_armature_get(const TransInfo *t, Object *ob * Lines below just check is also visible. */ Object *ob_armature = BKE_modifiers_is_deformed_by_armature(ob); if (ob_armature && ob_armature->mode & OB_MODE_POSE) { + BKE_view_layer_synced_ensure(t->scene, t->view_layer); Base *base_arm = BKE_view_layer_base_find(t->view_layer, ob_armature); if (base_arm) { View3D *v3d = t->view; diff --git a/source/blender/editors/transform/transform_gizmo_2d.c b/source/blender/editors/transform/transform_gizmo_2d.c index 426b338f8a7..a6eb25975e9 100644 --- a/source/blender/editors/transform/transform_gizmo_2d.c +++ b/source/blender/editors/transform/transform_gizmo_2d.c @@ -236,7 +236,7 @@ static bool gizmo2d_calc_bounds(const bContext *C, float *r_center, float *r_min ViewLayer *view_layer = CTX_data_view_layer(C); uint objects_len = 0; Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data_with_uvs( - view_layer, NULL, &objects_len); + scene, view_layer, NULL, &objects_len); if (ED_uvedit_minmax_multi(scene, objects, objects_len, r_min, r_max)) { has_select = true; } diff --git a/source/blender/editors/transform/transform_gizmo_3d.c b/source/blender/editors/transform/transform_gizmo_3d.c index 5b749e05052..8e6a6c2c411 100644 --- a/source/blender/editors/transform/transform_gizmo_3d.c +++ b/source/blender/editors/transform/transform_gizmo_3d.c @@ -639,7 +639,8 @@ int ED_transform_calc_gizmo_stats(const bContext *C, (params->orientation_index - 1) : BKE_scene_orientation_get_index(scene, SCE_ORIENT_DEFAULT); - Object *ob = OBACT(view_layer); + BKE_view_layer_synced_ensure(scene, view_layer); + Object *ob = BKE_view_layer_active_object_get(view_layer); Object *obedit = OBEDIT_FROM_OBACT(ob); if (ob && ob->mode & OB_MODE_WEIGHT_PAINT) { Object *obpose = BKE_object_pose_armature_get(ob); @@ -753,7 +754,7 @@ int ED_transform_calc_gizmo_stats(const bContext *C, invert_m4_m4(obedit->imat, obedit->obmat); \ uint objects_len = 0; \ Object **objects = BKE_view_layer_array_from_objects_in_edit_mode( \ - view_layer, CTX_wm_view3d(C), &objects_len); \ + scene, view_layer, CTX_wm_view3d(C), &objects_len); \ for (uint ob_index = 0; ob_index < objects_len; ob_index++) { \ Object *ob_iter = objects[ob_index]; \ const bool use_mat_local = (ob_iter != obedit); @@ -941,7 +942,7 @@ int ED_transform_calc_gizmo_stats(const bContext *C, invert_m4_m4(ob->imat, ob->obmat); uint objects_len = 0; - Object **objects = BKE_object_pose_array_get(view_layer, v3d, &objects_len); + Object **objects = BKE_object_pose_array_get(scene, view_layer, v3d, &objects_len); for (uint ob_index = 0; ob_index < objects_len; ob_index++) { Object *ob_iter = objects[ob_index]; @@ -1014,13 +1015,14 @@ int ED_transform_calc_gizmo_stats(const bContext *C, else { /* we need the one selected object, if its not active */ - base = BASACT(view_layer); - ob = OBACT(view_layer); + BKE_view_layer_synced_ensure(scene, view_layer); + base = BKE_view_layer_active_base_get(view_layer); + ob = base ? base->object : NULL; if (base && ((base->flag & BASE_SELECTED) == 0)) { ob = NULL; } - for (base = view_layer->object_bases.first; base; base = base->next) { + for (base = BKE_view_layer_object_bases_get(view_layer)->first; base; base = base->next) { if (!BASE_SELECTED_EDITABLE(v3d, base)) { continue; } @@ -1103,7 +1105,8 @@ static void gizmo_prepare_mat(const bContext *C, /* pass */ } else { - Object *ob = OBACT(view_layer); + BKE_view_layer_synced_ensure(scene, view_layer); + Object *ob = BKE_view_layer_active_object_get(view_layer); if (ob != NULL) { if ((ob->mode & OB_MODE_ALL_SCULPT) && ob->sculpt) { SculptSession *ss = ob->sculpt; diff --git a/source/blender/editors/transform/transform_gizmo_extrude_3d.c b/source/blender/editors/transform/transform_gizmo_extrude_3d.c index a3b5fd2c575..0271f8e1988 100644 --- a/source/blender/editors/transform/transform_gizmo_extrude_3d.c +++ b/source/blender/editors/transform/transform_gizmo_extrude_3d.c @@ -101,7 +101,7 @@ static void gizmo_mesh_extrude_orientation_matrix_set_for_adjust(struct GizmoExt for (int j = 0; j < 3; j++) { copy_v3_v3(ggd->adjust[0]->matrix_basis[j], mat[j]); } - /* nop when (i == 2). */ + /* NOP when (i == 2). */ swap_v3_v3(ggd->adjust[0]->matrix_basis[ggd->adjust_axis], ggd->adjust[0]->matrix_basis[2]); } diff --git a/source/blender/editors/transform/transform_input.c b/source/blender/editors/transform/transform_input.c index 3b320ff51d5..38dbe742279 100644 --- a/source/blender/editors/transform/transform_input.c +++ b/source/blender/editors/transform/transform_input.c @@ -8,6 +8,7 @@ #include <stdlib.h> #include "DNA_screen_types.h" +#include "DNA_space_types.h" #include "BKE_context.h" @@ -18,6 +19,7 @@ #include "WM_types.h" #include "transform.h" +#include "transform_mode.h" #include "MEM_guardedalloc.h" @@ -251,11 +253,8 @@ void setCustomPointsFromDirection(TransInfo *t, MouseInput *mi, const float dir[ /** \name Setup & Handle Mouse Input * \{ */ -void initMouseInput(TransInfo *UNUSED(t), - MouseInput *mi, - const float center[2], - const int mval[2], - const bool precision) +void initMouseInput( + TransInfo *t, MouseInput *mi, const float center[2], const int mval[2], const bool precision) { mi->factor = 0; mi->precision = precision; @@ -266,14 +265,20 @@ void initMouseInput(TransInfo *UNUSED(t), mi->imval[0] = mval[0]; mi->imval[1] = mval[1]; + if ((t->spacetype == SPACE_VIEW3D) && (t->region->regiontype == RGN_TYPE_WINDOW)) { + float delta[3] = {mval[0] - center[0], mval[1] - center[1]}; + ED_view3d_win_to_delta(t->region, delta, t->zfac, delta); + add_v3_v3v3(mi->imval_unproj, t->center_global, delta); + } + mi->post = NULL; } static void calcSpringFactor(MouseInput *mi) { - mi->factor = sqrtf( - ((float)(mi->center[1] - mi->imval[1])) * ((float)(mi->center[1] - mi->imval[1])) + - ((float)(mi->center[0] - mi->imval[0])) * ((float)(mi->center[0] - mi->imval[0]))); + float mdir[2] = {(float)(mi->center[1] - mi->imval[1]), (float)(mi->center[0] - mi->imval[0])}; + + mi->factor = len_v2(mdir); if (mi->factor == 0.0f) { mi->factor = 1.0f; /* prevent Inf */ @@ -441,4 +446,52 @@ void applyMouseInput(TransInfo *t, MouseInput *mi, const int mval[2], float outp } } +void transform_input_update(TransInfo *t, const float fac) +{ + MouseInput *mi = &t->mouse; + t->mouse.factor *= fac; + if ((t->spacetype == SPACE_VIEW3D) && (t->region->regiontype == RGN_TYPE_WINDOW)) { + projectIntView(t, mi->imval_unproj, mi->imval); + } + else { + int offset[2], center_2d_int[2] = {mi->center[0], mi->center[1]}; + sub_v2_v2v2_int(offset, mi->imval, center_2d_int); + offset[0] *= fac; + offset[1] *= fac; + + center_2d_int[0] = t->center2d[0]; + center_2d_int[1] = t->center2d[1]; + add_v2_v2v2_int(mi->imval, center_2d_int, offset); + } + + float center_old[2]; + copy_v2_v2(center_old, mi->center); + copy_v2_v2(mi->center, t->center2d); + + if (mi->use_virtual_mval) { + /* Update accumulator. */ + double mval_delta[2]; + sub_v2_v2v2_db(mval_delta, mi->virtual_mval.accum, mi->virtual_mval.prev); + mval_delta[0] *= fac; + mval_delta[1] *= fac; + copy_v2_v2_db(mi->virtual_mval.accum, mi->virtual_mval.prev); + add_v2_v2_db(mi->virtual_mval.accum, mval_delta); + } + + if (ELEM(mi->apply, InputAngle, InputAngleSpring)) { + float offset_center[2]; + sub_v2_v2v2(offset_center, mi->center, center_old); + struct InputAngle_Data *data = mi->data; + data->mval_prev[0] += offset_center[0]; + data->mval_prev[1] += offset_center[1]; + } + + if (t->mode == TFM_EDGE_SLIDE) { + transform_mode_edge_slide_reproject_input(t); + } + else if (t->mode == TFM_VERT_SLIDE) { + transform_mode_vert_slide_reproject_input(t); + } +} + /** \} */ diff --git a/source/blender/editors/transform/transform_mode.c b/source/blender/editors/transform/transform_mode.c index d8da7a11d28..10ea022757d 100644 --- a/source/blender/editors/transform/transform_mode.c +++ b/source/blender/editors/transform/transform_mode.c @@ -1214,7 +1214,7 @@ void transform_mode_init(TransInfo *t, wmOperator *op, const int mode) transform_convert_mesh_customdatacorrect_init(t); } - /* TODO(germano): Some of these operations change the `t->mode`. + /* TODO(@germano): Some of these operations change the `t->mode`. * This can be bad for Redo. */ // BLI_assert(t->mode == mode); } diff --git a/source/blender/editors/transform/transform_mode.h b/source/blender/editors/transform/transform_mode.h index eac6734ed88..063de87ebb2 100644 --- a/source/blender/editors/transform/transform_mode.h +++ b/source/blender/editors/transform/transform_mode.h @@ -117,6 +117,7 @@ void drawEdgeSlide(TransInfo *t); void initEdgeSlide_ex( TransInfo *t, bool use_double_side, bool use_even, bool flipped, bool use_clamp); void initEdgeSlide(TransInfo *t); +void transform_mode_edge_slide_reproject_input(TransInfo *t); /* transform_mode_gpopacity.c */ @@ -191,3 +192,4 @@ void initTranslation(TransInfo *t); void drawVertSlide(TransInfo *t); void initVertSlide_ex(TransInfo *t, bool use_even, bool flipped, bool use_clamp); void initVertSlide(TransInfo *t); +void transform_mode_vert_slide_reproject_input(TransInfo *t); diff --git a/source/blender/editors/transform/transform_mode_edge_slide.c b/source/blender/editors/transform/transform_mode_edge_slide.c index b48ba0640ad..8a29321413e 100644 --- a/source/blender/editors/transform/transform_mode_edge_slide.c +++ b/source/blender/editors/transform/transform_mode_edge_slide.c @@ -292,8 +292,75 @@ static BMLoop *get_next_loop( return NULL; } +static void edge_slide_projmat_get(TransInfo *t, TransDataContainer *tc, float r_projectMat[4][4]) +{ + RegionView3D *rv3d = NULL; + + if (t->spacetype == SPACE_VIEW3D) { + /* Background mode support. */ + rv3d = t->region ? t->region->regiondata : NULL; + } + + if (!rv3d) { + /* Ok, let's try to survive this. */ + unit_m4(r_projectMat); + } + else { + ED_view3d_ob_project_mat_get(rv3d, tc->obedit, r_projectMat); + } +} + +static void edge_slide_pair_project(TransDataEdgeSlideVert *sv, + ARegion *region, + float projectMat[4][4], + float r_sco_a[3], + float r_sco_b[3]) +{ + BMVert *v = sv->v; + + if (sv->v_side[1]) { + ED_view3d_project_float_v3_m4(region, sv->v_side[1]->co, r_sco_b, projectMat); + } + else { + add_v3_v3v3(r_sco_b, v->co, sv->dir_side[1]); + ED_view3d_project_float_v3_m4(region, r_sco_b, r_sco_b, projectMat); + } + + if (sv->v_side[0]) { + ED_view3d_project_float_v3_m4(region, sv->v_side[0]->co, r_sco_a, projectMat); + } + else { + add_v3_v3v3(r_sco_a, v->co, sv->dir_side[0]); + ED_view3d_project_float_v3_m4(region, r_sco_a, r_sco_a, projectMat); + } +} + +static void edge_slide_data_init_mval(MouseInput *mi, EdgeSlideData *sld, float *mval_dir) +{ + /* Possible all of the edge loops are pointing directly at the view. */ + if (UNLIKELY(len_squared_v2(mval_dir) < 0.1f)) { + mval_dir[0] = 0.0f; + mval_dir[1] = 100.0f; + } + + float mval_start[2], mval_end[2]; + + /* Zero out Start. */ + zero_v2(mval_start); + + /* dir holds a vector along edge loop */ + copy_v2_v2(mval_end, mval_dir); + mul_v2_fl(mval_end, 0.5f); + + sld->mval_start[0] = mi->imval[0] + mval_start[0]; + sld->mval_start[1] = mi->imval[1] + mval_start[1]; + + sld->mval_end[0] = mi->imval[0] + mval_end[0]; + sld->mval_end[1] = mi->imval[1] + mval_end[1]; +} + /** - * Calculate screenspace `mval_start` / `mval_end`, optionally slide direction. + * Calculate screen-space `mval_start` / `mval_end`, optionally slide direction. */ static void calcEdgeSlide_mval_range(TransInfo *t, TransDataContainer *tc, @@ -308,29 +375,20 @@ static void calcEdgeSlide_mval_range(TransInfo *t, BMEditMesh *em = BKE_editmesh_from_object(tc->obedit); ARegion *region = t->region; View3D *v3d = NULL; - RegionView3D *rv3d = NULL; float projectMat[4][4]; BMBVHTree *bmbvh; /* only for use_calc_direction */ float(*loop_dir)[3] = NULL, *loop_maxdist = NULL; - float mval_start[2], mval_end[2]; float mval_dir[3], dist_best_sq; if (t->spacetype == SPACE_VIEW3D) { /* background mode support */ v3d = t->area ? t->area->spacedata.first : NULL; - rv3d = t->region ? t->region->regiondata : NULL; } - if (!rv3d) { - /* ok, let's try to survive this */ - unit_m4(projectMat); - } - else { - ED_view3d_ob_project_mat_get(rv3d, tc->obedit, projectMat); - } + edge_slide_projmat_get(t, tc, projectMat); if (use_occlude_geometry) { bmbvh = BKE_bmbvh_new_from_editmesh(em, BMBVH_RESPECT_HIDDEN, NULL, false); @@ -379,21 +437,7 @@ static void calcEdgeSlide_mval_range(TransInfo *t, continue; } - if (sv->v_side[1]) { - ED_view3d_project_float_v3_m4(region, sv->v_side[1]->co, sco_b, projectMat); - } - else { - add_v3_v3v3(sco_b, v->co, sv->dir_side[1]); - ED_view3d_project_float_v3_m4(region, sco_b, sco_b, projectMat); - } - - if (sv->v_side[0]) { - ED_view3d_project_float_v3_m4(region, sv->v_side[0]->co, sco_a, projectMat); - } - else { - add_v3_v3v3(sco_a, v->co, sv->dir_side[0]); - ED_view3d_project_float_v3_m4(region, sco_a, sco_a, projectMat); - } + edge_slide_pair_project(sv, region, projectMat, sco_a, sco_b); /* global direction */ dist_sq = dist_squared_to_line_segment_v2(mval, sco_b, sco_a); @@ -433,24 +477,7 @@ static void calcEdgeSlide_mval_range(TransInfo *t, MEM_freeN(loop_maxdist); } - /* possible all of the edge loops are pointing directly at the view */ - if (UNLIKELY(len_squared_v2(mval_dir) < 0.1f)) { - mval_dir[0] = 0.0f; - mval_dir[1] = 100.0f; - } - - /* zero out start */ - zero_v2(mval_start); - - /* dir holds a vector along edge loop */ - copy_v2_v2(mval_end, mval_dir); - mul_v2_fl(mval_end, 0.5f); - - sld->mval_start[0] = t->mval[0] + mval_start[0]; - sld->mval_start[1] = t->mval[1] + mval_start[1]; - - sld->mval_end[0] = t->mval[0] + mval_end[0]; - sld->mval_end[1] = t->mval[1] + mval_end[1]; + edge_slide_data_init_mval(&t->mouse, sld, mval_dir); if (bmbvh) { BKE_bmbvh_free(bmbvh); @@ -466,7 +493,6 @@ static void calcEdgeSlide_even(TransInfo *t, if (sld->totsv > 0) { ARegion *region = t->region; - RegionView3D *rv3d = NULL; float projectMat[4][4]; int i = 0; @@ -475,18 +501,7 @@ static void calcEdgeSlide_even(TransInfo *t, float dist_sq = 0; float dist_min_sq = FLT_MAX; - if (t->spacetype == SPACE_VIEW3D) { - /* background mode support */ - rv3d = t->region ? t->region->regiondata : NULL; - } - - if (!rv3d) { - /* ok, let's try to survive this */ - unit_m4(projectMat); - } - else { - ED_view3d_ob_project_mat_get(rv3d, tc->obedit, projectMat); - } + edge_slide_projmat_get(t, tc, projectMat); for (i = 0; i < sld->totsv; i++, sv++) { /* Set length */ @@ -1553,3 +1568,32 @@ void initEdgeSlide(TransInfo *t) } /** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Mouse Input Utilities + * \{ */ + +void transform_mode_edge_slide_reproject_input(TransInfo *t) +{ + ARegion *region = t->region; + + FOREACH_TRANS_DATA_CONTAINER (t, tc) { + EdgeSlideData *sld = tc->custom.mode.data; + if (sld) { + float projectMat[4][4]; + edge_slide_projmat_get(t, tc, projectMat); + + TransDataEdgeSlideVert *curr_sv = &sld->sv[sld->curr_sv_index]; + + float mval_dir[3], sco_a[3], sco_b[3]; + edge_slide_pair_project(curr_sv, region, projectMat, sco_a, sco_b); + sub_v3_v3v3(mval_dir, sco_b, sco_a); + edge_slide_data_init_mval(&t->mouse, sld, mval_dir); + } + } + + EdgeSlideData *sld = edgeSlideFirstGet(t); + setCustomPoints(t, &t->mouse, sld->mval_end, sld->mval_start); +} + +/** \} */ diff --git a/source/blender/editors/transform/transform_mode_rotate.c b/source/blender/editors/transform/transform_mode_rotate.c index a7207b36578..110000def35 100644 --- a/source/blender/editors/transform/transform_mode_rotate.c +++ b/source/blender/editors/transform/transform_mode_rotate.c @@ -286,9 +286,72 @@ static void applyRotationValue(TransInfo *t, } } +static bool uv_rotation_in_clip_bounds_test(const TransInfo *t, const float angle) +{ + const float cos_angle = cosf(angle); + const float sin_angle = sinf(angle); + const float *center = t->center_global; + FOREACH_TRANS_DATA_CONTAINER (t, tc) { + TransData *td = tc->data; + for (int i = 0; i < tc->data_len; i++, td++) { + if (td->flag & TD_SKIP) { + continue; + } + if (td->factor < 1.0f) { + continue; /* Proportional edit, will get picked up in next phase. */ + } + + float uv[2]; + sub_v2_v2v2(uv, td->iloc, center); + float pr[2]; + pr[0] = cos_angle * uv[0] + sin_angle * uv[1]; + pr[1] = -sin_angle * uv[0] + cos_angle * uv[1]; + add_v2_v2(pr, center); + /* TODO: UDIM support. */ + if (pr[0] < 0.0f || 1.0f < pr[0]) { + return false; + } + if (pr[1] < 0.0f || 1.0f < pr[1]) { + return false; + } + } + } + return true; +} + +static bool clip_uv_transform_rotate(const TransInfo *t, float *vec, float *vec_inside_bounds) +{ + float angle = vec[0]; + if (uv_rotation_in_clip_bounds_test(t, angle)) { + vec_inside_bounds[0] = angle; /* Store for next iteration. */ + return false; /* Nothing to do. */ + } + float angle_inside_bounds = vec_inside_bounds[0]; + if (!uv_rotation_in_clip_bounds_test(t, angle_inside_bounds)) { + return false; /* No known way to fix, may as well rotate anyway. */ + } + const int max_i = 32; /* Limit iteration, mainly for debugging. */ + for (int i = 0; i < max_i; i++) { + /* Binary search. */ + const float angle_mid = (angle_inside_bounds + angle) / 2.0f; + if (ELEM(angle_mid, angle_inside_bounds, angle)) { + break; /* float precision reached. */ + } + if (uv_rotation_in_clip_bounds_test(t, angle_mid)) { + angle_inside_bounds = angle_mid; + } + else { + angle = angle_mid; + } + } + + vec_inside_bounds[0] = angle_inside_bounds; /* Store for next iteration. */ + vec[0] = angle_inside_bounds; /* Update rotation angle. */ + return true; +} + static void applyRotation(TransInfo *t, const int UNUSED(mval[2])) { - char str[UI_MAX_DRAW_STR]; float axis_final[3]; float final = t->values[0] + t->values_modal_offset[0]; @@ -313,13 +376,27 @@ static void applyRotation(TransInfo *t, const int UNUSED(mval[2])) t->values_final[0] = final; - headerRotation(t, str, sizeof(str), final); - const bool is_large_rotation = hasNumInput(&t->num); applyRotationValue(t, final, axis_final, is_large_rotation); + if (t->flag & T_CLIP_UV) { + if (clip_uv_transform_rotate(t, t->values_final, t->values_inside_constraints)) { + applyRotationValue(t, t->values_final[0], axis_final, is_large_rotation); + } + + /* In proportional edit it can happen that */ + /* vertices in the radius of the brush end */ + /* outside the clipping area */ + /* XXX HACK - dg */ + if (t->flag & T_PROP_EDIT) { + clipUVData(t); + } + } + recalcData(t); + char str[UI_MAX_DRAW_STR]; + headerRotation(t, str, sizeof(str), t->values_final[0]); ED_area_status_text(t->area, str); } diff --git a/source/blender/editors/transform/transform_mode_vert_slide.c b/source/blender/editors/transform/transform_mode_vert_slide.c index 674ffcf17a8..d7c4d862b23 100644 --- a/source/blender/editors/transform/transform_mode_vert_slide.c +++ b/source/blender/editors/transform/transform_mode_vert_slide.c @@ -68,7 +68,7 @@ typedef struct VertSlideParams { bool flipped; } VertSlideParams; -static void calcVertSlideCustomPoints(struct TransInfo *t) +static void vert_slide_update_input(TransInfo *t) { VertSlideParams *slp = t->custom.mode.data; VertSlideData *sld = TRANS_DATA_CONTAINER_FIRST_OK(t)->custom.mode.data; @@ -94,6 +94,11 @@ static void calcVertSlideCustomPoints(struct TransInfo *t) else { setCustomPoints(t, &t->mouse, mval_end, mval_start); } +} + +static void calcVertSlideCustomPoints(struct TransInfo *t) +{ + vert_slide_update_input(t); /* setCustomPoints isn't normally changing as the mouse moves, * in this case apply mouse input immediately so we don't refresh @@ -673,3 +678,22 @@ void initVertSlide(TransInfo *t) } /** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Mouse Input Utilities + * \{ */ + +void transform_mode_vert_slide_reproject_input(TransInfo *t) +{ + if (t->spacetype == SPACE_VIEW3D) { + RegionView3D *rv3d = t->region->regiondata; + FOREACH_TRANS_DATA_CONTAINER (t, tc) { + VertSlideData *sld = tc->custom.mode.data; + ED_view3d_ob_project_mat_get(rv3d, tc->obedit, sld->proj_mat); + } + } + + vert_slide_update_input(t); +} + +/** \} */ diff --git a/source/blender/editors/transform/transform_ops.c b/source/blender/editors/transform/transform_ops.c index 7c94241f3e3..99919c0ed78 100644 --- a/source/blender/editors/transform/transform_ops.c +++ b/source/blender/editors/transform/transform_ops.c @@ -379,6 +379,8 @@ static int transformops_data(bContext *C, wmOperator *op, const wmEvent *event) if (op->customdata == NULL) { TransInfo *t = MEM_callocN(sizeof(TransInfo), "TransInfo data2"); + t->undo_name = op->type->name; + int mode = transformops_mode(op); retval = initTransform(C, t, op, event, mode); diff --git a/source/blender/editors/transform/transform_orientations.c b/source/blender/editors/transform/transform_orientations.c index c0d943e17ee..212df5978e4 100644 --- a/source/blender/editors/transform/transform_orientations.c +++ b/source/blender/editors/transform/transform_orientations.c @@ -476,7 +476,8 @@ void ED_transform_calc_orientation_from_type(const bContext *C, float r_mat[3][3 Object *obedit = CTX_data_edit_object(C); View3D *v3d = CTX_wm_view3d(C); RegionView3D *rv3d = region->regiondata; - Object *ob = OBACT(view_layer); + BKE_view_layer_synced_ensure(scene, view_layer); + Object *ob = BKE_view_layer_active_object_get(view_layer); const short orient_index = BKE_scene_orientation_get_index(scene, SCE_ORIENT_DEFAULT); const int pivot_point = scene->toolsettings->transform_pivot_point; @@ -515,7 +516,7 @@ short ED_transform_calc_orientation_from_type_ex(const Scene *scene, } case V3D_ORIENT_NORMAL: { if (obedit || (ob && ob->mode & OB_MODE_POSE)) { - ED_getTransformOrientationMatrix(view_layer, v3d, ob, obedit, pivot_point, r_mat); + ED_getTransformOrientationMatrix(scene, view_layer, v3d, ob, obedit, pivot_point, r_mat); break; } /* No break we define 'normal' as 'local' in Object mode. */ @@ -528,7 +529,7 @@ short ED_transform_calc_orientation_from_type_ex(const Scene *scene, * use the active pones axis for display T33575, this works as expected on a single * bone and users who select many bones will understand what's going on and what local * means when they start transforming. */ - ED_getTransformOrientationMatrix(view_layer, v3d, ob, obedit, pivot_point, r_mat); + ED_getTransformOrientationMatrix(scene, view_layer, v3d, ob, obedit, pivot_point, r_mat); } else { transform_orientations_create_from_axis(r_mat, UNPACK3(ob->obmat)); @@ -744,7 +745,8 @@ static uint bm_mesh_faces_select_get_n(BMesh *bm, BMVert **elems, const uint n) } #endif -int getTransformOrientation_ex(ViewLayer *view_layer, +int getTransformOrientation_ex(const Scene *scene, + ViewLayer *view_layer, const View3D *v3d, struct Object *ob, struct Object *obedit, @@ -1252,6 +1254,7 @@ int getTransformOrientation_ex(ViewLayer *view_layer, ok = true; } else { + BKE_view_layer_synced_ensure(scene, view_layer); Base *base = BKE_view_layer_base_find(view_layer, ob); if (UNLIKELY(base == NULL)) { /* This is very unlikely, if it happens allow the value to be set since the caller @@ -1282,13 +1285,15 @@ int getTransformOrientation(const bContext *C, float normal[3], float plane[3]) /* dummy value, not V3D_AROUND_ACTIVE and not V3D_AROUND_LOCAL_ORIGINS */ short around = V3D_AROUND_CENTER_BOUNDS; + const Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); View3D *v3d = CTX_wm_view3d(C); - return getTransformOrientation_ex(view_layer, v3d, obact, obedit, normal, plane, around); + return getTransformOrientation_ex(scene, view_layer, v3d, obact, obedit, normal, plane, around); } -void ED_getTransformOrientationMatrix(ViewLayer *view_layer, +void ED_getTransformOrientationMatrix(const Scene *scene, + ViewLayer *view_layer, const View3D *v3d, Object *ob, Object *obedit, @@ -1300,7 +1305,7 @@ void ED_getTransformOrientationMatrix(ViewLayer *view_layer, int type; - type = getTransformOrientation_ex(view_layer, v3d, ob, obedit, normal, plane, around); + type = getTransformOrientation_ex(scene, view_layer, v3d, ob, obedit, normal, plane, around); /* Fallback, when the plane can't be calculated. */ if (ORIENTATION_USE_PLANE(type) && is_zero_v3(plane)) { diff --git a/source/blender/editors/transform/transform_orientations.h b/source/blender/editors/transform/transform_orientations.h index 3ac235517a7..32093e830b0 100644 --- a/source/blender/editors/transform/transform_orientations.h +++ b/source/blender/editors/transform/transform_orientations.h @@ -55,7 +55,8 @@ enum { }; #define ORIENTATION_USE_PLANE(ty) ELEM(ty, ORIENTATION_NORMAL, ORIENTATION_EDGE, ORIENTATION_FACE) -int getTransformOrientation_ex(ViewLayer *view_layer, +int getTransformOrientation_ex(const Scene *scene, + ViewLayer *view_layer, const View3D *v3d, struct Object *ob, struct Object *obedit, diff --git a/source/blender/editors/transform/transform_snap.c b/source/blender/editors/transform/transform_snap.c index 9a563aaf473..31d36fc4d92 100644 --- a/source/blender/editors/transform/transform_snap.c +++ b/source/blender/editors/transform/transform_snap.c @@ -51,9 +51,6 @@ static bool doForceIncrementSnap(const TransInfo *t); -/* this should be passed as an arg for use in snap functions */ -#undef BASACT - /* use half of flt-max so we can scale up without an exception */ /* -------------------------------------------------------------------- */ @@ -128,15 +125,11 @@ bool activeSnap(const TransInfo *t) bool activeSnap_SnappingIndividual(const TransInfo *t) { - if (activeSnap(t) && t->tsnap.mode & SCE_SNAP_MODE_FACE_NEAREST) { - return true; - } - - if (!t->tsnap.project) { + if (!activeSnap(t) || (t->flag & T_NO_PROJECT)) { return false; } - if (!activeSnap(t) || (t->flag & T_NO_PROJECT)) { + if (!(t->tsnap.project || (t->tsnap.mode & SCE_SNAP_MODE_FACE_NEAREST))) { return false; } @@ -195,156 +188,152 @@ static bool doForceIncrementSnap(const TransInfo *t) void drawSnapping(const struct bContext *C, TransInfo *t) { uchar col[4], selectedCol[4], activeCol[4]; - if (!activeSnap(t)) { return; } - if (t->spacetype == SPACE_VIEW3D) { - bool draw_target = (t->tsnap.status & TARGET_INIT) && - (t->tsnap.mode & SCE_SNAP_MODE_EDGE_PERPENDICULAR); - - if (draw_target || validSnap(t)) { - UI_GetThemeColor3ubv(TH_TRANSFORM, col); - col[3] = 128; + bool draw_target = (t->spacetype == SPACE_VIEW3D) && (t->tsnap.status & TARGET_INIT) && + (t->tsnap.mode & SCE_SNAP_MODE_EDGE_PERPENDICULAR); - UI_GetThemeColor3ubv(TH_SELECT, selectedCol); - selectedCol[3] = 128; + if (!(draw_target || validSnap(t))) { + return; + } - UI_GetThemeColor3ubv(TH_ACTIVE, activeCol); - activeCol[3] = 192; + if (t->spacetype == SPACE_SEQ) { + UI_GetThemeColor3ubv(TH_SEQ_ACTIVE, col); + col[3] = 128; + } + else if (t->spacetype != SPACE_IMAGE) { + UI_GetThemeColor3ubv(TH_TRANSFORM, col); + col[3] = 128; - const float *loc_cur = NULL; - const float *loc_prev = NULL; - const float *normal = NULL; + UI_GetThemeColor3ubv(TH_SELECT, selectedCol); + selectedCol[3] = 128; - GPU_depth_test(GPU_DEPTH_NONE); + UI_GetThemeColor3ubv(TH_ACTIVE, activeCol); + activeCol[3] = 192; + } - RegionView3D *rv3d = CTX_wm_region_view3d(C); - if (!BLI_listbase_is_empty(&t->tsnap.points)) { - /* Draw snap points. */ + if (t->spacetype == SPACE_VIEW3D) { + const float *loc_cur = NULL; + const float *loc_prev = NULL; + const float *normal = NULL; - float size = 2.0f * UI_GetThemeValuef(TH_VERTEX_SIZE); - float view_inv[4][4]; - copy_m4_m4(view_inv, rv3d->viewinv); + GPU_depth_test(GPU_DEPTH_NONE); - uint pos = GPU_vertformat_attr_add( - immVertexFormat(), "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT); + RegionView3D *rv3d = CTX_wm_region_view3d(C); + if (!BLI_listbase_is_empty(&t->tsnap.points)) { + /* Draw snap points. */ - immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); + float size = 2.0f * UI_GetThemeValuef(TH_VERTEX_SIZE); + float view_inv[4][4]; + copy_m4_m4(view_inv, rv3d->viewinv); - LISTBASE_FOREACH (TransSnapPoint *, p, &t->tsnap.points) { - if (p == t->tsnap.selectedPoint) { - immUniformColor4ubv(selectedCol); - } - else { - immUniformColor4ubv(col); - } - imm_drawcircball(p->co, ED_view3d_pixel_size(rv3d, p->co) * size, view_inv, pos); - } + uint pos = GPU_vertformat_attr_add( + immVertexFormat(), "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT); - immUnbindProgram(); - } + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); - /* draw normal if needed */ - if (usingSnappingNormal(t) && validSnappingNormal(t)) { - normal = t->tsnap.snapNormal; + LISTBASE_FOREACH (TransSnapPoint *, p, &t->tsnap.points) { + if (p == t->tsnap.selectedPoint) { + immUniformColor4ubv(selectedCol); + } + else { + immUniformColor4ubv(col); + } + imm_drawcircball(p->co, ED_view3d_pixel_size(rv3d, p->co) * size, view_inv, pos); } - if (draw_target) { - loc_prev = t->tsnap.snapTarget; - } + immUnbindProgram(); + } - if (validSnap(t)) { - loc_cur = t->tsnap.snapPoint; - } + /* draw normal if needed */ + if (usingSnappingNormal(t) && validSnappingNormal(t)) { + normal = t->tsnap.snapNormal; + } - ED_view3d_cursor_snap_draw_util( - rv3d, loc_prev, loc_cur, normal, col, activeCol, t->tsnap.snapElem); + if (draw_target) { + loc_prev = t->tsnap.snapTarget; + } - GPU_depth_test(GPU_DEPTH_LESS_EQUAL); + if (validSnap(t)) { + loc_cur = t->tsnap.snapPoint; } + + ED_view3d_cursor_snap_draw_util( + rv3d, loc_prev, loc_cur, normal, col, activeCol, t->tsnap.snapElem); + + GPU_depth_test(GPU_DEPTH_LESS_EQUAL); } else if (t->spacetype == SPACE_IMAGE) { - if (validSnap(t)) { - uint pos = GPU_vertformat_attr_add( - immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); - - float x, y; - const float snap_point[2] = { - t->tsnap.snapPoint[0] / t->aspect[0], - t->tsnap.snapPoint[1] / t->aspect[1], - }; - UI_view2d_view_to_region_fl(&t->region->v2d, UNPACK2(snap_point), &x, &y); - float radius = 2.5f * UI_GetThemeValuef(TH_VERTEX_SIZE) * U.pixelsize; - - GPU_matrix_push_projection(); - wmOrtho2_region_pixelspace(t->region); - - immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); - immUniformColor3ub(255, 255, 255); - imm_draw_circle_wire_2d(pos, x, y, radius, 8); - immUnbindProgram(); + uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); - GPU_matrix_pop_projection(); - } - } - else if (t->spacetype == SPACE_NODE) { - if (validSnap(t)) { - ARegion *region = CTX_wm_region(C); - TransSnapPoint *p; - float size; + float x, y; + const float snap_point[2] = { + t->tsnap.snapPoint[0] / t->aspect[0], + t->tsnap.snapPoint[1] / t->aspect[1], + }; + UI_view2d_view_to_region_fl(&t->region->v2d, UNPACK2(snap_point), &x, &y); + float radius = 2.5f * UI_GetThemeValuef(TH_VERTEX_SIZE) * U.pixelsize; - size = 2.5f * UI_GetThemeValuef(TH_VERTEX_SIZE); + GPU_matrix_push_projection(); + wmOrtho2_region_pixelspace(t->region); - GPU_blend(GPU_BLEND_ALPHA); + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); + immUniformColor3ub(255, 255, 255); + imm_draw_circle_wire_2d(pos, x, y, radius, 8); + immUnbindProgram(); - uint pos = GPU_vertformat_attr_add( - immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); + GPU_matrix_pop_projection(); + } + else if (t->spacetype == SPACE_NODE) { + ARegion *region = CTX_wm_region(C); + TransSnapPoint *p; + float size; - immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + size = 2.5f * UI_GetThemeValuef(TH_VERTEX_SIZE); - for (p = t->tsnap.points.first; p; p = p->next) { - if (p == t->tsnap.selectedPoint) { - immUniformColor4ubv(selectedCol); - } - else { - immUniformColor4ubv(col); - } + GPU_blend(GPU_BLEND_ALPHA); - ED_node_draw_snap(®ion->v2d, p->co, size, 0, pos); - } + uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); - if (t->tsnap.status & POINT_INIT) { - immUniformColor4ubv(activeCol); + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); - ED_node_draw_snap(®ion->v2d, t->tsnap.snapPoint, size, t->tsnap.snapNodeBorder, pos); + for (p = t->tsnap.points.first; p; p = p->next) { + if (p == t->tsnap.selectedPoint) { + immUniformColor4ubv(selectedCol); + } + else { + immUniformColor4ubv(col); } - immUnbindProgram(); + ED_node_draw_snap(®ion->v2d, p->co, size, 0, pos); + } - GPU_blend(GPU_BLEND_NONE); + if (t->tsnap.status & POINT_INIT) { + immUniformColor4ubv(activeCol); + + ED_node_draw_snap(®ion->v2d, t->tsnap.snapPoint, size, t->tsnap.snapNodeBorder, pos); } + + immUnbindProgram(); + + GPU_blend(GPU_BLEND_NONE); } else if (t->spacetype == SPACE_SEQ) { - if (validSnap(t)) { - const ARegion *region = CTX_wm_region(C); - GPU_blend(GPU_BLEND_ALPHA); - uint pos = GPU_vertformat_attr_add( - immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); - immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); - UI_GetThemeColor3ubv(TH_SEQ_ACTIVE, col); - col[3] = 128; - immUniformColor4ubv(col); - float pixelx = BLI_rctf_size_x(®ion->v2d.cur) / BLI_rcti_size_x(®ion->v2d.mask); - immRectf(pos, - t->tsnap.snapPoint[0] - pixelx, - region->v2d.cur.ymax, - t->tsnap.snapPoint[0] + pixelx, - region->v2d.cur.ymin); - immUnbindProgram(); - GPU_blend(GPU_BLEND_NONE); - } + const ARegion *region = CTX_wm_region(C); + GPU_blend(GPU_BLEND_ALPHA); + uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); + immUniformColor4ubv(col); + float pixelx = BLI_rctf_size_x(®ion->v2d.cur) / BLI_rcti_size_x(®ion->v2d.mask); + immRectf(pos, + t->tsnap.snapPoint[0] - pixelx, + region->v2d.cur.ymax, + t->tsnap.snapPoint[0] + pixelx, + region->v2d.cur.ymin); + immUnbindProgram(); + GPU_blend(GPU_BLEND_NONE); } } @@ -729,8 +718,8 @@ static eSnapMode snap_mode_from_spacetype(TransInfo *t) static eSnapTargetSelect snap_target_select_from_spacetype(TransInfo *t) { - ViewLayer *view_layer = t->view_layer; - Base *base_act = view_layer->basact; + BKE_view_layer_synced_ensure(t->scene, t->view_layer); + Base *base_act = BKE_view_layer_active_base_get(t->view_layer); eSnapTargetSelect ret = SCE_SNAP_TARGET_ALL; @@ -967,7 +956,8 @@ static void setSnappingCallback(TransInfo *t) } else if (t->spacetype == SPACE_IMAGE) { SpaceImage *sima = t->area->spacedata.first; - Object *obact = t->view_layer->basact ? t->view_layer->basact->object : NULL; + BKE_view_layer_synced_ensure(t->scene, t->view_layer); + Object *obact = BKE_view_layer_active_object_get(t->view_layer); const bool is_uv_editor = sima->mode == SI_MODE_UV; const bool has_edit_object = obact && BKE_object_is_in_editmode(obact); @@ -1152,7 +1142,7 @@ static void snap_calc_uv_fn(TransInfo *t, float *UNUSED(vec)) if (t->tsnap.mode & SCE_SNAP_MODE_VERTEX) { uint objects_len = 0; Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data_with_uvs( - t->view_layer, NULL, &objects_len); + t->scene, t->view_layer, NULL, &objects_len); float dist_sq = square_f((float)SNAP_MIN_DISTANCE); if (ED_uvedit_nearest_uv_multi(&t->region->v2d, diff --git a/source/blender/editors/transform/transform_snap_object.cc b/source/blender/editors/transform/transform_snap_object.cc index 6808f06bdd3..6d643ae7180 100644 --- a/source/blender/editors/transform/transform_snap_object.cc +++ b/source/blender/editors/transform/transform_snap_object.cc @@ -47,6 +47,7 @@ using blender::float3; using blender::float4x4; using blender::Map; +using blender::Span; /* -------------------------------------------------------------------- */ /** \name Internal Data Types @@ -243,6 +244,11 @@ static SnapData_Mesh *snap_object_data_mesh_get(SnapObjectContext *sctx, SnapData_Mesh *sod; bool init = false; + const Span<MVert> verts = me_eval->verts(); + const Span<MEdge> edges = me_eval->edges(); + const Span<MPoly> polys = me_eval->polys(); + const Span<MLoop> loops = me_eval->loops(); + if (std::unique_ptr<SnapData_Mesh> *sod_p = sctx->mesh_caches.lookup_ptr(ob_eval)) { sod = sod_p->get(); bool is_dirty = false; @@ -264,16 +270,16 @@ static SnapData_Mesh *snap_object_data_mesh_get(SnapObjectContext *sctx, else if (sod->treedata_mesh.looptri != me_eval->runtime.looptris.array) { is_dirty = true; } - else if (sod->treedata_mesh.vert != me_eval->mvert) { + else if (sod->treedata_mesh.vert != verts.data()) { is_dirty = true; } - else if (sod->treedata_mesh.loop != me_eval->mloop) { + else if (sod->treedata_mesh.loop != loops.data()) { is_dirty = true; } - else if (sod->treedata_mesh.edge != me_eval->medge) { + else if (sod->treedata_mesh.edge != edges.data()) { is_dirty = true; } - else if (sod->poly != me_eval->mpoly) { + else if (sod->poly != polys.data()) { is_dirty = true; } @@ -303,16 +309,16 @@ static SnapData_Mesh *snap_object_data_mesh_get(SnapObjectContext *sctx, use_hide ? BVHTREE_FROM_LOOPTRI_NO_HIDDEN : BVHTREE_FROM_LOOPTRI, 4); - BLI_assert(sod->treedata_mesh.vert == me_eval->mvert); - BLI_assert(!me_eval->mvert || sod->treedata_mesh.vert_normals); - BLI_assert(sod->treedata_mesh.loop == me_eval->mloop); - BLI_assert(!me_eval->mpoly || sod->treedata_mesh.looptri); + BLI_assert(sod->treedata_mesh.vert == verts.data()); + BLI_assert(!verts.data() || sod->treedata_mesh.vert_normals); + BLI_assert(sod->treedata_mesh.loop == loops.data()); + BLI_assert(!polys.data() || sod->treedata_mesh.looptri); sod->has_looptris = sod->treedata_mesh.tree != nullptr; /* Required for snapping with occlusion. */ - sod->treedata_mesh.edge = me_eval->medge; - sod->poly = me_eval->mpoly; + sod->treedata_mesh.edge = edges.data(); + sod->poly = polys.data(); /* Start assuming that it has each of these element types. */ sod->has_loose_edge = true; @@ -537,11 +543,13 @@ static void iter_snap_objects(SnapObjectContext *sctx, IterSnapObjsCallback sob_callback, void *data) { + Scene *scene = DEG_get_input_scene(sctx->runtime.depsgraph); ViewLayer *view_layer = DEG_get_input_view_layer(sctx->runtime.depsgraph); const eSnapTargetSelect snap_target_select = params->snap_target_select; - Base *base_act = view_layer->basact; + BKE_view_layer_synced_ensure(scene, view_layer); + Base *base_act = BKE_view_layer_active_base_get(view_layer); - LISTBASE_FOREACH (Base *, base, &view_layer->object_bases) { + LISTBASE_FOREACH (Base *, base, BKE_view_layer_object_bases_get(view_layer)) { if (!snap_object_is_snappable(sctx, snap_target_select, base_act, base)) { continue; } @@ -564,7 +572,7 @@ static void iter_snap_objects(SnapObjectContext *sctx, /** \} */ /* -------------------------------------------------------------------- */ -/** \name Ray Cast Funcs +/** \name Ray Cast Functions * \{ */ /* Store all ray-hits @@ -1187,7 +1195,7 @@ static bool raycastObjects(SnapObjectContext *sctx, /** \} */ /* -------------------------------------------------------------------- */ -/** \name Surface Snap Funcs +/** \name Surface Snap Functions * \{ */ struct NearestWorldObjUserData { @@ -3402,8 +3410,8 @@ static eSnapMode transform_snap_context_project_view3d_mixed_impl(SnapObjectCont bool use_occlusion_test = params->use_occlusion_test && !XRAY_ENABLED(v3d); - /* Note: if both face raycast and face nearest are enabled, first find result of nearest, then - * override with raycast. */ + /* NOTE: if both face ray-cast and face nearest are enabled, first find result of nearest, then + * override with ray-cast. */ if ((snap_to_flag & SCE_SNAP_MODE_FACE_NEAREST) && !has_hit) { has_hit = nearestWorldObjects( sctx, params, init_co, prev_co, loc, no, &index, &ob_eval, obmat); diff --git a/source/blender/editors/undo/ed_undo.c b/source/blender/editors/undo/ed_undo.c index bb24bdac690..42563cb8f83 100644 --- a/source/blender/editors/undo/ed_undo.c +++ b/source/blender/editors/undo/ed_undo.c @@ -433,9 +433,11 @@ bool ED_undo_is_memfile_compatible(const bContext *C) { /* Some modes don't co-exist with memfile undo, disable their use: T60593 * (this matches 2.7x behavior). */ + const Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); if (view_layer != NULL) { - Object *obact = OBACT(view_layer); + BKE_view_layer_synced_ensure(scene, view_layer); + Object *obact = BKE_view_layer_active_object_get(view_layer); if (obact != NULL) { if (obact->mode & OB_MODE_EDIT) { return false; @@ -447,9 +449,11 @@ bool ED_undo_is_memfile_compatible(const bContext *C) bool ED_undo_is_legacy_compatible_for_property(struct bContext *C, ID *id) { + const Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); if (view_layer != NULL) { - Object *obact = OBACT(view_layer); + BKE_view_layer_synced_ensure(scene, view_layer); + Object *obact = BKE_view_layer_active_object_get(view_layer); if (obact != NULL) { if (obact->mode & OB_MODE_ALL_PAINT) { /* Don't store property changes when painting @@ -800,7 +804,8 @@ void ED_OT_undo_history(wmOperatorType *ot) void ED_undo_object_set_active_or_warn( Scene *scene, ViewLayer *view_layer, Object *ob, const char *info, CLG_LogRef *log) { - Object *ob_prev = OBACT(view_layer); + BKE_view_layer_synced_ensure(scene, view_layer); + Object *ob_prev = BKE_view_layer_active_object_get(view_layer); if (ob_prev != ob) { Base *base = BKE_view_layer_base_find(view_layer, ob); if (base != NULL) { @@ -820,15 +825,15 @@ void ED_undo_object_editmode_restore_helper(struct bContext *C, uint object_array_stride) { Main *bmain = CTX_data_main(C); + Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); uint bases_len = 0; /* Don't request unique data because we want to de-select objects when exiting edit-mode * for that to be done on all objects we can't skip ones that share data. */ - Base **bases = ED_undo_editmode_bases_from_view_layer(view_layer, &bases_len); + Base **bases = ED_undo_editmode_bases_from_view_layer(scene, view_layer, &bases_len); for (uint i = 0; i < bases_len; i++) { ((ID *)bases[i]->object->data)->tag |= LIB_TAG_DOIT; } - Scene *scene = CTX_data_scene(C); Object **ob_p = object_array; for (uint i = 0; i < object_array_len; i++, ob_p = POINTER_OFFSET(ob_p, object_array_stride)) { Object *obedit = *ob_p; @@ -859,11 +864,14 @@ void ED_undo_object_editmode_restore_helper(struct bContext *C, * and local collections may be used. * \{ */ -static int undo_editmode_objects_from_view_layer_prepare(ViewLayer *view_layer, Object *obact) +static int undo_editmode_objects_from_view_layer_prepare(const Scene *scene, + ViewLayer *view_layer, + Object *obact) { const short object_type = obact->type; - - LISTBASE_FOREACH (Base *, base, &view_layer->object_bases) { + BKE_view_layer_synced_ensure(scene, view_layer); + ListBase *object_bases = BKE_view_layer_object_bases_get(view_layer); + LISTBASE_FOREACH (Base *, base, object_bases) { Object *ob = base->object; if ((ob->type == object_type) && (ob->mode & OB_MODE_EDIT)) { ID *id = ob->data; @@ -872,7 +880,7 @@ static int undo_editmode_objects_from_view_layer_prepare(ViewLayer *view_layer, } int len = 0; - LISTBASE_FOREACH (Base *, base, &view_layer->object_bases) { + LISTBASE_FOREACH (Base *, base, object_bases) { Object *ob = base->object; if ((ob->type == object_type) && (ob->mode & OB_MODE_EDIT)) { ID *id = ob->data; @@ -885,19 +893,23 @@ static int undo_editmode_objects_from_view_layer_prepare(ViewLayer *view_layer, return len; } -Object **ED_undo_editmode_objects_from_view_layer(ViewLayer *view_layer, uint *r_len) +Object **ED_undo_editmode_objects_from_view_layer(const Scene *scene, + ViewLayer *view_layer, + uint *r_len) { - Base *baseact = BASACT(view_layer); + BKE_view_layer_synced_ensure(scene, view_layer); + Base *baseact = BKE_view_layer_active_base_get(view_layer); if ((baseact == NULL) || (baseact->object->mode & OB_MODE_EDIT) == 0) { return MEM_mallocN(0, __func__); } - const int len = undo_editmode_objects_from_view_layer_prepare(view_layer, baseact->object); + const int len = undo_editmode_objects_from_view_layer_prepare( + scene, view_layer, baseact->object); const short object_type = baseact->object->type; int i = 0; Object **objects = MEM_malloc_arrayN(len, sizeof(*objects), __func__); /* Base iteration, starting with the active-base to ensure it's the first item in the array. * Looping over the active-base twice is OK as the tag check prevents it being handled twice. */ - for (Base *base = baseact, *base_next = FIRSTBASE(view_layer); base; + for (Base *base = baseact, *base_next = BKE_view_layer_object_bases_get(view_layer)->first; base; base = base_next, base_next = base_next ? base_next->next : NULL) { Object *ob = base->object; if ((ob->type == object_type) && (ob->mode & OB_MODE_EDIT)) { @@ -914,19 +926,25 @@ Object **ED_undo_editmode_objects_from_view_layer(ViewLayer *view_layer, uint *r return objects; } -Base **ED_undo_editmode_bases_from_view_layer(ViewLayer *view_layer, uint *r_len) +Base **ED_undo_editmode_bases_from_view_layer(const Scene *scene, + ViewLayer *view_layer, + uint *r_len) { - Base *baseact = BASACT(view_layer); + BKE_view_layer_synced_ensure(scene, view_layer); + Base *baseact = BKE_view_layer_active_base_get(view_layer); if ((baseact == NULL) || (baseact->object->mode & OB_MODE_EDIT) == 0) { return MEM_mallocN(0, __func__); } - const int len = undo_editmode_objects_from_view_layer_prepare(view_layer, baseact->object); + const int len = undo_editmode_objects_from_view_layer_prepare( + scene, view_layer, baseact->object); const short object_type = baseact->object->type; int i = 0; Base **base_array = MEM_malloc_arrayN(len, sizeof(*base_array), __func__); /* Base iteration, starting with the active-base to ensure it's the first item in the array. * Looping over the active-base twice is OK as the tag check prevents it being handled twice. */ - for (Base *base = BASACT(view_layer), *base_next = FIRSTBASE(view_layer); base; + for (Base *base = BKE_view_layer_active_base_get(view_layer), + *base_next = BKE_view_layer_object_bases_get(view_layer)->first; + base; base = base_next, base_next = base_next ? base_next->next : NULL) { Object *ob = base->object; if ((ob->type == object_type) && (ob->mode & OB_MODE_EDIT)) { diff --git a/source/blender/editors/util/CMakeLists.txt b/source/blender/editors/util/CMakeLists.txt index cdfe40c7d35..a9e6adc6e60 100644 --- a/source/blender/editors/util/CMakeLists.txt +++ b/source/blender/editors/util/CMakeLists.txt @@ -16,7 +16,6 @@ set(INC ../../sequencer ../../windowmanager ../../../../intern/clog - ../../../../intern/glew-mx ../../../../intern/guardedalloc # RNA_prototypes.h ${CMAKE_BINARY_DIR}/source/blender/makesrna @@ -83,7 +82,6 @@ set(SRC ../include/ED_transform.h ../include/ED_transform_snap_object_context.h ../include/ED_transverts.h - ../include/ED_types.h ../include/ED_undo.h ../include/ED_userpref.h ../include/ED_util.h diff --git a/source/blender/editors/util/ed_draw.c b/source/blender/editors/util/ed_draw.c index 1b6a3efe19c..7ec3d3c1ef4 100644 --- a/source/blender/editors/util/ed_draw.c +++ b/source/blender/editors/util/ed_draw.c @@ -95,7 +95,7 @@ static void draw_overshoot_triangle(const uint8_t color[4], { const uint shdr_pos_2d = GPU_vertformat_attr_add( immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); - immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); GPU_blend(GPU_BLEND_ALPHA); GPU_polygon_smooth(true); immUniformColor3ubvAlpha(color, 225); @@ -370,11 +370,13 @@ tSlider *ED_slider_create(struct bContext *C) slider->factor = 0.5; /* Add draw callback. Always in header. */ - LISTBASE_FOREACH (ARegion *, region, &slider->area->regionbase) { - if (region->regiontype == RGN_TYPE_HEADER) { - slider->region_header = region; - slider->draw_handle = ED_region_draw_cb_activate( - region->type, slider_draw, slider, REGION_DRAW_POST_PIXEL); + if (slider->area) { + LISTBASE_FOREACH (ARegion *, region, &slider->area->regionbase) { + if (region->regiontype == RGN_TYPE_HEADER) { + slider->region_header = region; + slider->draw_handle = ED_region_draw_cb_activate( + region->type, slider_draw, slider, REGION_DRAW_POST_PIXEL); + } } } @@ -465,7 +467,9 @@ void ED_slider_status_string_get(const struct tSlider *slider, void ED_slider_destroy(struct bContext *C, tSlider *slider) { /* Remove draw callback. */ - ED_region_draw_cb_exit(slider->region_header->type, slider->draw_handle); + if (slider->draw_handle) { + ED_region_draw_cb_exit(slider->region_header->type, slider->draw_handle); + } ED_area_status_text(slider->area, NULL); ED_workspace_status_text(C, NULL); MEM_freeN(slider); @@ -512,7 +516,7 @@ void ED_region_draw_mouse_line_cb(const bContext *C, ARegion *region, void *arg_ GPU_line_width(1.0f); - immBindBuiltinProgram(GPU_SHADER_2D_LINE_DASHED_UNIFORM_COLOR); + immBindBuiltinProgram(GPU_SHADER_3D_LINE_DASHED_UNIFORM_COLOR); float viewport_size[4]; GPU_viewport_size_get_f(viewport_size); @@ -778,7 +782,7 @@ void ED_region_image_metadata_draw( /* draw top box */ GPUVertFormat *format = immVertexFormat(); uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); - immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); immUniformThemeColor(TH_METADATA_BG); immRectf(pos, rect.xmin, rect.ymin, rect.xmax, rect.ymax); immUnbindProgram(); @@ -803,7 +807,7 @@ void ED_region_image_metadata_draw( /* draw top box */ GPUVertFormat *format = immVertexFormat(); uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); - immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); immUniformThemeColor(TH_METADATA_BG); immRectf(pos, rect.xmin, rect.ymin, rect.xmax, rect.ymax); immUnbindProgram(); diff --git a/source/blender/editors/util/ed_util.c b/source/blender/editors/util/ed_util.c index 36a881ec158..12e77c6ef00 100644 --- a/source/blender/editors/util/ed_util.c +++ b/source/blender/editors/util/ed_util.c @@ -54,22 +54,19 @@ #include "WM_api.h" #include "WM_types.h" -/* ********* general editor util funcs, not BKE stuff please! ********* */ +/* ********* general editor util functions, not BKE stuff please! ********* */ void ED_editors_init_for_undo(Main *bmain) { wmWindowManager *wm = bmain->wm.first; LISTBASE_FOREACH (wmWindow *, win, &wm->windows) { + Scene *scene = WM_window_get_active_scene(win); ViewLayer *view_layer = WM_window_get_active_view_layer(win); - Base *base = BASACT(view_layer); - if (base != NULL) { - Object *ob = base->object; - if (ob->mode & OB_MODE_TEXTURE_PAINT) { - Scene *scene = WM_window_get_active_scene(win); - - BKE_texpaint_slots_refresh_object(scene, ob); - ED_paint_proj_mesh_data_check(scene, ob, NULL, NULL, NULL, NULL); - } + BKE_view_layer_synced_ensure(scene, view_layer); + Object *ob = BKE_view_layer_active_object_get(view_layer); + if (ob && (ob->mode & OB_MODE_TEXTURE_PAINT)) { + BKE_texpaint_slots_refresh_object(scene, ob); + ED_paint_proj_mesh_data_check(scene, ob, NULL, NULL, NULL, NULL); } } } @@ -377,7 +374,7 @@ void unpack_menu(bContext *C, char local_name[FILE_MAXDIR + FILE_MAX], fi[FILE_MAX]; BLI_split_file_part(abs_name, fi, sizeof(fi)); - BLI_snprintf(local_name, sizeof(local_name), "//%s/%s", folder, fi); + BLI_path_join(local_name, sizeof(local_name), "//", folder, fi, NULL); if (!STREQ(abs_name, local_name)) { switch (BKE_packedfile_compare_to_file(blendfile_path, local_name, pf)) { case PF_CMP_NOFILE: diff --git a/source/blender/editors/util/ed_util_imbuf.c b/source/blender/editors/util/ed_util_imbuf.c index 1ebbb0cecc3..f222f93d2b6 100644 --- a/source/blender/editors/util/ed_util_imbuf.c +++ b/source/blender/editors/util/ed_util_imbuf.c @@ -428,7 +428,7 @@ void ED_imbuf_sample_draw(const bContext *C, ARegion *region, void *arg_info) uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); const float color[3] = {1, 1, 1}; - immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); immUniformColor3fv(color); /* TODO(@campbellbarton): lock to pixels. */ diff --git a/source/blender/editors/util/select_utils.c b/source/blender/editors/util/select_utils.c index 660afa4c3d7..b29afdb5a9f 100644 --- a/source/blender/editors/util/select_utils.c +++ b/source/blender/editors/util/select_utils.c @@ -10,6 +10,8 @@ #include "BLI_math.h" #include "BLI_utildefines.h" +#include "BLT_translation.h" + #include "DNA_windowmanager_types.h" #include "RNA_access.h" @@ -161,18 +163,18 @@ const char *ED_select_pick_get_name(wmOperatorType *UNUSED(ot), PointerRNA *ptr) ED_select_pick_params_from_operator(ptr, ¶ms); switch (params.sel_op) { case SEL_OP_ADD: - return "Select (Extend)"; + return CTX_N_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Select (Extend)"); case SEL_OP_SUB: - return "Select (Deselect)"; + return CTX_N_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Select (Deselect)"); case SEL_OP_XOR: - return "Select (Toggle)"; + return CTX_N_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Select (Toggle)"); case SEL_OP_AND: BLI_assert_unreachable(); ATTR_FALLTHROUGH; case SEL_OP_SET: break; } - return "Select"; + return CTX_N_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Select"); } const char *ED_select_circle_get_name(wmOperatorType *UNUSED(ot), PointerRNA *ptr) @@ -181,9 +183,9 @@ const char *ED_select_circle_get_name(wmOperatorType *UNUSED(ot), PointerRNA *pt const eSelectOp sel_op = RNA_enum_get(ptr, "mode"); switch (sel_op) { case SEL_OP_ADD: - return "Circle Select (Extend)"; + return CTX_N_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Circle Select (Extend)"); case SEL_OP_SUB: - return "Circle Select (Deselect)"; + return CTX_N_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Circle Select (Deselect)"); case SEL_OP_XOR: ATTR_FALLTHROUGH; case SEL_OP_AND: @@ -192,7 +194,7 @@ const char *ED_select_circle_get_name(wmOperatorType *UNUSED(ot), PointerRNA *pt case SEL_OP_SET: break; } - return "Circle Select"; + return CTX_N_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Circle Select"); } /** \} */ diff --git a/source/blender/editors/uvedit/CMakeLists.txt b/source/blender/editors/uvedit/CMakeLists.txt index 761e7cd091e..4574c745d93 100644 --- a/source/blender/editors/uvedit/CMakeLists.txt +++ b/source/blender/editors/uvedit/CMakeLists.txt @@ -13,7 +13,6 @@ set(INC ../../makesrna ../../windowmanager ../../../../intern/eigen - ../../../../intern/glew-mx ../../../../intern/guardedalloc # RNA_prototypes.h ${CMAKE_BINARY_DIR}/source/blender/makesrna @@ -23,7 +22,7 @@ set(INC set(SRC uvedit_buttons.c uvedit_draw.c - uvedit_islands.c + uvedit_islands.cc uvedit_ops.c uvedit_path.c uvedit_rip.c diff --git a/source/blender/editors/uvedit/uvedit_buttons.c b/source/blender/editors/uvedit/uvedit_buttons.c index 6192ae56d65..10368f7d43f 100644 --- a/source/blender/editors/uvedit/uvedit_buttons.c +++ b/source/blender/editors/uvedit/uvedit_buttons.c @@ -123,7 +123,7 @@ static void uvedit_vertex_buttons(const bContext *C, uiBlock *block) int imx, imy, step, digits; uint objects_len = 0; Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data_with_uvs( - CTX_data_view_layer(C), CTX_wm_view3d(C), &objects_len); + scene, CTX_data_view_layer(C), CTX_wm_view3d(C), &objects_len); ED_space_image_get_size(sima, &imx, &imy); @@ -211,7 +211,7 @@ static void do_uvedit_vertex(bContext *C, void *UNUSED(arg), int event) uint objects_len = 0; Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data_with_uvs( - CTX_data_view_layer(C), CTX_wm_view3d(C), &objects_len); + scene, CTX_data_view_layer(C), CTX_wm_view3d(C), &objects_len); ED_space_image_get_size(sima, &imx, &imy); uvedit_center(scene, objects, objects_len, center); diff --git a/source/blender/editors/uvedit/uvedit_draw.c b/source/blender/editors/uvedit/uvedit_draw.c index 141b59e0355..9deeb27b259 100644 --- a/source/blender/editors/uvedit/uvedit_draw.c +++ b/source/blender/editors/uvedit/uvedit_draw.c @@ -39,7 +39,7 @@ void ED_image_draw_cursor(ARegion *region, const float cursor[2]) const uint shdr_pos = GPU_vertformat_attr_add( immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); - immBindBuiltinProgram(GPU_SHADER_2D_LINE_DASHED_UNIFORM_COLOR); + immBindBuiltinProgram(GPU_SHADER_3D_LINE_DASHED_UNIFORM_COLOR); float viewport_size[4]; GPU_viewport_size_get_f(viewport_size); diff --git a/source/blender/editors/uvedit/uvedit_islands.c b/source/blender/editors/uvedit/uvedit_islands.cc index 3877a9bb63b..42415be656a 100644 --- a/source/blender/editors/uvedit/uvedit_islands.c +++ b/source/blender/editors/uvedit/uvedit_islands.cc @@ -46,7 +46,7 @@ static void bm_face_uv_scale_y(BMFace *f, const float scale_y, const int cd_loop BMLoop *l_first; l_iter = l_first = BM_FACE_FIRST_LOOP(f); do { - MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(l_iter, cd_loop_uv_offset); + MLoopUV *luv = static_cast<MLoopUV *>(BM_ELEM_CD_GET_VOID_P(l_iter, cd_loop_uv_offset)); luv->uv[1] *= scale_y; } while ((l_iter = l_iter->next) != l_first); } @@ -61,7 +61,7 @@ static void bm_face_uv_translate_and_scale_around_pivot(BMFace *f, BMLoop *l_first; l_iter = l_first = BM_FACE_FIRST_LOOP(f); do { - MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(l_iter, cd_loop_uv_offset); + MLoopUV *luv = static_cast<MLoopUV *>(BM_ELEM_CD_GET_VOID_P(l_iter, cd_loop_uv_offset)); for (int i = 0; i < 2; i++) { luv->uv[i] = offset[i] + (((luv->uv[i] - pivot[i]) * scale[i]) + pivot[i]); } @@ -76,9 +76,10 @@ static void bm_face_uv_translate_and_scale_around_pivot(BMFace *f, static void bm_face_array_calc_bounds(BMFace **faces, int faces_len, - const uint cd_loop_uv_offset, + const int cd_loop_uv_offset, rctf *r_bounds_rect) { + BLI_assert(cd_loop_uv_offset >= 0); float bounds_min[2], bounds_max[2]; INIT_MINMAX2(bounds_min, bounds_max); for (int i = 0; i < faces_len; i++) { @@ -96,8 +97,9 @@ static void bm_face_array_calc_bounds(BMFace **faces, * without duplicating coordinates for loops that share a vertex. */ static float (*bm_face_array_calc_unique_uv_coords( - BMFace **faces, int faces_len, const uint cd_loop_uv_offset, int *r_coords_len))[2] + BMFace **faces, int faces_len, const int cd_loop_uv_offset, int *r_coords_len))[2] { + BLI_assert(cd_loop_uv_offset >= 0); int coords_len_alloc = 0; for (int i = 0; i < faces_len; i++) { BMFace *f = faces[i]; @@ -109,7 +111,8 @@ static float (*bm_face_array_calc_unique_uv_coords( coords_len_alloc += f->len; } - float(*coords)[2] = MEM_mallocN(sizeof(*coords) * coords_len_alloc, __func__); + float(*coords)[2] = static_cast<float(*)[2]>( + MEM_mallocN(sizeof(*coords) * coords_len_alloc, __func__)); int coords_len = 0; for (int i = 0; i < faces_len; i++) { @@ -123,7 +126,8 @@ static float (*bm_face_array_calc_unique_uv_coords( } BM_elem_flag_disable(l_iter, BM_ELEM_TAG); - const MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(l_iter, cd_loop_uv_offset); + const MLoopUV *luv = static_cast<const MLoopUV *>( + BM_ELEM_CD_GET_VOID_P(l_iter, cd_loop_uv_offset)); copy_v2_v2(coords[coords_len++], luv->uv); /* Un tag all connected so we don't add them twice. @@ -138,7 +142,8 @@ static float (*bm_face_array_calc_unique_uv_coords( do { if (l_radial->v == l_iter->v) { if (BM_elem_flag_test(l_radial, BM_ELEM_TAG)) { - const MLoopUV *luv_radial = BM_ELEM_CD_GET_VOID_P(l_radial, cd_loop_uv_offset); + const MLoopUV *luv_radial = static_cast<const MLoopUV *>( + BM_ELEM_CD_GET_VOID_P(l_radial, cd_loop_uv_offset)); if (equals_v2v2(luv->uv, luv_radial->uv)) { /* Don't add this UV when met in another face in `faces`. */ BM_elem_flag_disable(l_iter, BM_ELEM_TAG); @@ -150,7 +155,6 @@ static float (*bm_face_array_calc_unique_uv_coords( } while ((e = BM_DISK_EDGE_NEXT(e, v_pivot)) != e_first); } while ((l_iter = l_iter->next) != l_first); } - coords = MEM_reallocN(coords, sizeof(*coords) * coords_len); *r_coords_len = coords_len; return coords; } @@ -164,7 +168,7 @@ static float (*bm_face_array_calc_unique_uv_coords( static void bm_face_array_uv_rotate_fit_aabb(BMFace **faces, int faces_len, int align_to_axis, - const uint cd_loop_uv_offset) + const int cd_loop_uv_offset) { /* Calculate unique coordinates since calculating a convex hull can be an expensive operation. */ int coords_len; @@ -209,7 +213,7 @@ static void bm_face_array_uv_rotate_fit_aabb(BMFace **faces, static void bm_face_array_uv_scale_y(BMFace **faces, int faces_len, const float scale_y, - const uint cd_loop_uv_offset) + const int cd_loop_uv_offset) { for (int i = 0; i < faces_len; i++) { BMFace *f = faces[i]; @@ -311,13 +315,13 @@ static float uv_nearest_grid_tile_distance(const int udim_grid[2], * \{ */ struct SharedUVLoopData { - uint cd_loop_uv_offset; + int cd_loop_uv_offset; bool use_seams; }; static bool bm_loop_uv_shared_edge_check(const BMLoop *l_a, const BMLoop *l_b, void *user_data) { - const struct SharedUVLoopData *data = user_data; + const struct SharedUVLoopData *data = static_cast<const struct SharedUVLoopData *>(user_data); if (data->use_seams) { if (BM_elem_flag_test(l_a->e, BM_ELEM_SEAM)) { @@ -338,17 +342,14 @@ int bm_mesh_calc_uv_islands(const Scene *scene, const bool only_selected_uvs, const bool use_seams, const float aspect_y, - const uint cd_loop_uv_offset) + const int cd_loop_uv_offset) { + BLI_assert(cd_loop_uv_offset >= 0); int island_added = 0; BM_mesh_elem_table_ensure(bm, BM_FACE); - struct SharedUVLoopData user_data = { - .cd_loop_uv_offset = cd_loop_uv_offset, - .use_seams = use_seams, - }; - - int *groups_array = MEM_mallocN(sizeof(*groups_array) * (size_t)bm->totface, __func__); + int *groups_array = static_cast<int *>( + MEM_mallocN(sizeof(*groups_array) * (size_t)bm->totface, __func__)); int(*group_index)[2]; @@ -373,6 +374,10 @@ int bm_mesh_calc_uv_islands(const Scene *scene, } } + struct SharedUVLoopData user_data = {0}; + user_data.cd_loop_uv_offset = cd_loop_uv_offset; + user_data.use_seams = use_seams; + const int group_len = BM_mesh_calc_face_groups(bm, groups_array, &group_index, @@ -385,7 +390,7 @@ int bm_mesh_calc_uv_islands(const Scene *scene, for (int i = 0; i < group_len; i++) { const int faces_start = group_index[i][0]; const int faces_len = group_index[i][1]; - BMFace **faces = MEM_mallocN(sizeof(*faces) * faces_len, __func__); + BMFace **faces = static_cast<BMFace **>(MEM_mallocN(sizeof(*faces) * faces_len, __func__)); float bounds_min[2], bounds_max[2]; INIT_MINMAX2(bounds_min, bounds_max); @@ -394,7 +399,8 @@ int bm_mesh_calc_uv_islands(const Scene *scene, faces[j] = BM_face_at_index(bm, groups_array[faces_start + j]); } - struct FaceIsland *island = MEM_callocN(sizeof(*island), __func__); + struct FaceIsland *island = static_cast<struct FaceIsland *>( + MEM_callocN(sizeof(*island), __func__)); island->faces = faces; island->faces_len = faces_len; island->cd_loop_uv_offset = cd_loop_uv_offset; @@ -463,9 +469,10 @@ void ED_uvedit_pack_islands_multi(const Scene *scene, float margin = scene->toolsettings->uvcalc_margin; double area = 0.0f; - struct FaceIsland **island_array = MEM_mallocN(sizeof(*island_array) * island_list_len, - __func__); - BoxPack *boxarray = MEM_mallocN(sizeof(*boxarray) * island_list_len, __func__); + struct FaceIsland **island_array = static_cast<struct FaceIsland **>( + MEM_mallocN(sizeof(*island_array) * island_list_len, __func__)); + BoxPack *boxarray = static_cast<BoxPack *>( + MEM_mallocN(sizeof(*boxarray) * island_list_len, __func__)); int index; /* Coordinates of bounding box containing all selected UVs. */ @@ -617,7 +624,7 @@ void ED_uvedit_pack_islands_multi(const Scene *scene, for (uint ob_index = 0; ob_index < objects_len; ob_index++) { Object *obedit = objects[ob_index]; - DEG_id_tag_update(obedit->data, ID_RECALC_GEOMETRY); + DEG_id_tag_update(static_cast<ID *>(obedit->data), ID_RECALC_GEOMETRY); WM_main_add_notifier(NC_GEOM | ND_DATA, obedit->data); } diff --git a/source/blender/editors/uvedit/uvedit_ops.c b/source/blender/editors/uvedit/uvedit_ops.c index 6755630d3ef..5e2d9097abd 100644 --- a/source/blender/editors/uvedit/uvedit_ops.c +++ b/source/blender/editors/uvedit/uvedit_ops.c @@ -320,7 +320,7 @@ bool ED_uvedit_center_from_pivot_ex(SpaceImage *sima, if (r_has_select != NULL) { uint objects_len = 0; Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data_with_uvs( - view_layer, ((View3D *)NULL), &objects_len); + scene, view_layer, ((View3D *)NULL), &objects_len); *r_has_select = uvedit_select_is_any_selected_multi(scene, objects, objects_len); MEM_freeN(objects); } @@ -329,7 +329,7 @@ bool ED_uvedit_center_from_pivot_ex(SpaceImage *sima, default: { uint objects_len = 0; Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data_with_uvs( - view_layer, ((View3D *)NULL), &objects_len); + scene, view_layer, ((View3D *)NULL), &objects_len); changed = ED_uvedit_center_multi(scene, objects, objects_len, r_center, mode); MEM_freeN(objects); if (r_has_select != NULL) { @@ -535,7 +535,7 @@ static bool uvedit_uv_straighten(Scene *scene, BMesh *bm, eUVWeldAlign tool) return false; } - UvElementMap *element_map = BM_uv_element_map_create(bm, scene, true, false, true); + UvElementMap *element_map = BM_uv_element_map_create(bm, scene, true, false, true, true); if (element_map == NULL) { return false; } @@ -565,7 +565,7 @@ static void uv_weld_align(bContext *C, eUVWeldAlign tool) uint objects_len = 0; Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data_with_uvs( - view_layer, ((View3D *)NULL), &objects_len); + scene, view_layer, ((View3D *)NULL), &objects_len); if (tool == UV_ALIGN_AUTO) { for (uint ob_index = 0; ob_index < objects_len; ob_index++) { @@ -695,7 +695,7 @@ static int uv_remove_doubles_to_selected(bContext *C, wmOperator *op) uint objects_len = 0; Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data_with_uvs( - view_layer, ((View3D *)NULL), &objects_len); + scene, view_layer, ((View3D *)NULL), &objects_len); bool *changed = MEM_callocN(sizeof(bool) * objects_len, "uv_remove_doubles_selected.changed"); @@ -839,7 +839,7 @@ static int uv_remove_doubles_to_unselected(bContext *C, wmOperator *op) uint objects_len = 0; Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data_with_uvs( - view_layer, ((View3D *)NULL), &objects_len); + scene, view_layer, ((View3D *)NULL), &objects_len); /* Calculate max possible number of kdtree nodes. */ int uv_maxlen = 0; @@ -1047,7 +1047,7 @@ static int uv_snap_cursor_exec(bContext *C, wmOperator *op) uint objects_len = 0; Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data_with_uvs( - view_layer, ((View3D *)NULL), &objects_len); + scene, view_layer, ((View3D *)NULL), &objects_len); changed = uv_snap_cursor_to_selection(scene, objects, objects_len, sima); MEM_freeN(objects); break; @@ -1255,7 +1255,7 @@ static int uv_snap_selection_exec(bContext *C, wmOperator *op) uint objects_len = 0; Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data_with_uvs( - view_layer, ((View3D *)NULL), &objects_len); + scene, view_layer, ((View3D *)NULL), &objects_len); if (target == 2) { float center[2]; @@ -1348,7 +1348,7 @@ static int uv_pin_exec(bContext *C, wmOperator *op) uint objects_len = 0; Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data_with_uvs( - view_layer, ((View3D *)NULL), &objects_len); + scene, view_layer, ((View3D *)NULL), &objects_len); for (uint ob_index = 0; ob_index < objects_len; ob_index++) { Object *obedit = objects[ob_index]; @@ -1450,7 +1450,7 @@ static int uv_hide_exec(bContext *C, wmOperator *op) uint objects_len = 0; Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data_with_uvs( - view_layer, ((View3D *)NULL), &objects_len); + scene, view_layer, ((View3D *)NULL), &objects_len); for (uint ob_index = 0; ob_index < objects_len; ob_index++) { Object *ob = objects[ob_index]; @@ -1497,7 +1497,7 @@ static int uv_hide_exec(bContext *C, wmOperator *op) if (bm_face_is_all_uv_sel(efa, !swap, cd_loop_uv_offset)) { BM_face_select_set(em->bm, efa, false); } - uvedit_face_select_disable(scene, em, efa, cd_loop_uv_offset); + uvedit_face_select_disable(scene, em->bm, efa, cd_loop_uv_offset); } else { if (bm_face_is_all_uv_sel(efa, true, cd_loop_uv_offset) == !swap) { @@ -1514,7 +1514,7 @@ static int uv_hide_exec(bContext *C, wmOperator *op) } } if (!swap) { - uvedit_face_select_disable(scene, em, efa, cd_loop_uv_offset); + uvedit_face_select_disable(scene, em->bm, efa, cd_loop_uv_offset); } } } @@ -1536,7 +1536,7 @@ static int uv_hide_exec(bContext *C, wmOperator *op) break; } } - uvedit_face_select_disable(scene, em, efa, cd_loop_uv_offset); + uvedit_face_select_disable(scene, em->bm, efa, cd_loop_uv_offset); } else { BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { @@ -1560,7 +1560,7 @@ static int uv_hide_exec(bContext *C, wmOperator *op) } } if (!swap) { - uvedit_face_select_disable(scene, em, efa, cd_loop_uv_offset); + uvedit_face_select_disable(scene, em->bm, efa, cd_loop_uv_offset); } } } @@ -1622,7 +1622,7 @@ static int uv_reveal_exec(bContext *C, wmOperator *op) uint objects_len = 0; Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data_with_uvs( - view_layer, ((View3D *)NULL), &objects_len); + scene, view_layer, ((View3D *)NULL), &objects_len); for (uint ob_index = 0; ob_index < objects_len; ob_index++) { Object *ob = objects[ob_index]; @@ -1838,7 +1838,7 @@ static int uv_seams_from_islands_exec(bContext *C, wmOperator *op) uint objects_len = 0; Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data_with_uvs( - view_layer, ((View3D *)NULL), &objects_len); + scene, view_layer, ((View3D *)NULL), &objects_len); for (uint ob_index = 0; ob_index < objects_len; ob_index++) { Object *ob = objects[ob_index]; @@ -1943,7 +1943,7 @@ static int uv_mark_seam_exec(bContext *C, wmOperator *op) uint objects_len = 0; Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data_with_uvs( - view_layer, ((View3D *)NULL), &objects_len); + scene, view_layer, ((View3D *)NULL), &objects_len); bool changed = false; diff --git a/source/blender/editors/uvedit/uvedit_path.c b/source/blender/editors/uvedit/uvedit_path.c index 31a1b60167e..7af6cbe942b 100644 --- a/source/blender/editors/uvedit/uvedit_path.c +++ b/source/blender/editors/uvedit/uvedit_path.c @@ -71,7 +71,7 @@ struct PathSelectParams { struct UserData_UV { Scene *scene; BMEditMesh *em; - uint cd_loop_uv_offset; + int cd_loop_uv_offset; }; static void path_select_properties(wmOperatorType *ot) @@ -121,7 +121,7 @@ static bool verttag_test_cb(BMLoop *l, void *user_data_v) /* All connected loops are selected or we return false. */ struct UserData_UV *user_data = user_data_v; const Scene *scene = user_data->scene; - const uint cd_loop_uv_offset = user_data->cd_loop_uv_offset; + const int cd_loop_uv_offset = user_data->cd_loop_uv_offset; const MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); BMIter iter; BMLoop *l_iter; @@ -142,7 +142,7 @@ static void verttag_set_cb(BMLoop *l, bool val, void *user_data_v) struct UserData_UV *user_data = user_data_v; const Scene *scene = user_data->scene; BMEditMesh *em = user_data->em; - const uint cd_loop_uv_offset = user_data->cd_loop_uv_offset; + const int cd_loop_uv_offset = user_data->cd_loop_uv_offset; const MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); BMIter iter; BMLoop *l_iter; @@ -150,7 +150,7 @@ static void verttag_set_cb(BMLoop *l, bool val, void *user_data_v) if (verttag_filter_cb(l_iter, user_data)) { MLoopUV *luv_iter = BM_ELEM_CD_GET_VOID_P(l_iter, cd_loop_uv_offset); if (equals_v2v2(luv->uv, luv_iter->uv)) { - uvedit_uv_select_set(scene, em, l_iter, val, false, cd_loop_uv_offset); + uvedit_uv_select_set(scene, em->bm, l_iter, val, false, cd_loop_uv_offset); } } } @@ -253,7 +253,7 @@ static bool edgetag_test_cb(BMLoop *l, void *user_data_v) /* All connected loops (UV) are selected or we return false. */ struct UserData_UV *user_data = user_data_v; const Scene *scene = user_data->scene; - const uint cd_loop_uv_offset = user_data->cd_loop_uv_offset; + const int cd_loop_uv_offset = user_data->cd_loop_uv_offset; BMIter iter; BMLoop *l_iter; BM_ITER_ELEM (l_iter, &iter, l->e, BM_LOOPS_OF_EDGE) { @@ -272,7 +272,7 @@ static void edgetag_set_cb(BMLoop *l, bool val, void *user_data_v) struct UserData_UV *user_data = user_data_v; const Scene *scene = user_data->scene; BMEditMesh *em = user_data->em; - const uint cd_loop_uv_offset = user_data->cd_loop_uv_offset; + const int cd_loop_uv_offset = user_data->cd_loop_uv_offset; uvedit_edge_select_set_with_sticky(scene, em, l, val, false, cd_loop_uv_offset); } @@ -375,7 +375,7 @@ static bool facetag_test_cb(BMFace *f, void *user_data_v) /* All connected loops are selected or we return false. */ struct UserData_UV *user_data = user_data_v; const Scene *scene = user_data->scene; - const uint cd_loop_uv_offset = user_data->cd_loop_uv_offset; + const int cd_loop_uv_offset = user_data->cd_loop_uv_offset; BMIter iter; BMLoop *l_iter; BM_ITER_ELEM (l_iter, &iter, f, BM_LOOPS_OF_FACE) { @@ -390,7 +390,7 @@ static void facetag_set_cb(BMFace *f, bool val, void *user_data_v) struct UserData_UV *user_data = user_data_v; const Scene *scene = user_data->scene; BMEditMesh *em = user_data->em; - const uint cd_loop_uv_offset = user_data->cd_loop_uv_offset; + const int cd_loop_uv_offset = user_data->cd_loop_uv_offset; uvedit_face_select_set_with_sticky(scene, em, f, val, false, cd_loop_uv_offset); } @@ -799,7 +799,7 @@ static int uv_shortest_path_select_exec(bContext *C, wmOperator *op) ViewLayer *view_layer = CTX_data_view_layer(C); uint objects_len = 0; Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data( - view_layer, CTX_wm_view3d(C), &objects_len); + scene, view_layer, CTX_wm_view3d(C), &objects_len); for (uint ob_index = 0; ob_index < objects_len; ob_index++) { Object *obedit = objects[ob_index]; BMEditMesh *em = BKE_editmesh_from_object(obedit); diff --git a/source/blender/editors/uvedit/uvedit_rip.c b/source/blender/editors/uvedit/uvedit_rip.c index 545cc57e3c4..5497b9cd1e5 100644 --- a/source/blender/editors/uvedit/uvedit_rip.c +++ b/source/blender/editors/uvedit/uvedit_rip.c @@ -848,7 +848,7 @@ static bool uv_rip_object(Scene *scene, Object *obedit, const float co[2], const BMLoop *l_iter = BLI_gsetIterator_getKey(&gs_iter); ULData *ul = UL(l_iter); if (ul->side == side_from_cursor) { - uvedit_uv_select_disable(scene, em, l_iter, cd_loop_uv_offset); + uvedit_uv_select_disable(scene, em->bm, l_iter, cd_loop_uv_offset); changed = true; } /* Ensure we don't operate on these again. */ @@ -866,7 +866,7 @@ static bool uv_rip_object(Scene *scene, Object *obedit, const float co[2], const BMLoop *l_iter = BLI_gsetIterator_getKey(&gs_iter); ULData *ul = UL(l_iter); if (ul->side == side_from_cursor) { - uvedit_uv_select_disable(scene, em, l_iter, cd_loop_uv_offset); + uvedit_uv_select_disable(scene, em->bm, l_iter, cd_loop_uv_offset); changed = true; } /* Ensure we don't operate on these again. */ @@ -910,7 +910,7 @@ static int uv_rip_exec(bContext *C, wmOperator *op) uint objects_len = 0; Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data_with_uvs( - view_layer, ((View3D *)NULL), &objects_len); + scene, view_layer, ((View3D *)NULL), &objects_len); for (uint ob_index = 0; ob_index < objects_len; ob_index++) { Object *obedit = objects[ob_index]; diff --git a/source/blender/editors/uvedit/uvedit_select.c b/source/blender/editors/uvedit/uvedit_select.c index d88da21ef98..6c8fb9360bd 100644 --- a/source/blender/editors/uvedit/uvedit_select.c +++ b/source/blender/editors/uvedit/uvedit_select.c @@ -207,7 +207,7 @@ static void uvedit_vertex_select_tagged(BMEditMesh *em, BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { if (BM_elem_flag_test(l->v, BM_ELEM_TAG)) { - uvedit_uv_select_set(scene, em, l, select, false, cd_loop_uv_offset); + uvedit_uv_select_set(scene, em->bm, l, select, false, cd_loop_uv_offset); } } } @@ -265,7 +265,7 @@ void uvedit_face_select_set_with_sticky(const Scene *scene, const ToolSettings *ts = scene->toolsettings; const char sticky = ts->uv_sticky; if (ts->uv_flag & UV_SYNC_SELECTION) { - uvedit_face_select_set(scene, em, efa, select, do_history, cd_loop_uv_offset); + uvedit_face_select_set(scene, em->bm, efa, select, do_history, cd_loop_uv_offset); return; } if (!uvedit_face_visible_test(scene, efa)) { @@ -275,7 +275,7 @@ void uvedit_face_select_set_with_sticky(const Scene *scene, * (not part of any face selections). This now uses the sticky location mode logic instead. */ switch (sticky) { case SI_STICKY_DISABLE: { - uvedit_face_select_set(scene, em, efa, select, do_history, cd_loop_uv_offset); + uvedit_face_select_set(scene, em->bm, efa, select, do_history, cd_loop_uv_offset); break; } default: { @@ -313,32 +313,30 @@ void uvedit_face_select_shared_vert(const Scene *scene, } void uvedit_face_select_set(const Scene *scene, - BMEditMesh *em, + BMesh *bm, BMFace *efa, const bool select, const bool do_history, const int cd_loop_uv_offset) { if (select) { - uvedit_face_select_enable(scene, em, efa, do_history, cd_loop_uv_offset); + uvedit_face_select_enable(scene, bm, efa, do_history, cd_loop_uv_offset); } else { - uvedit_face_select_disable(scene, em, efa, cd_loop_uv_offset); + uvedit_face_select_disable(scene, bm, efa, cd_loop_uv_offset); } } -void uvedit_face_select_enable(const Scene *scene, - BMEditMesh *em, - BMFace *efa, - const bool do_history, - const int cd_loop_uv_offset) +void uvedit_face_select_enable( + const Scene *scene, BMesh *bm, BMFace *efa, const bool do_history, const int cd_loop_uv_offset) { + BLI_assert(cd_loop_uv_offset >= 0); const ToolSettings *ts = scene->toolsettings; if (ts->uv_flag & UV_SYNC_SELECTION) { - BM_face_select_set(em->bm, efa, true); + BM_face_select_set(bm, efa, true); if (do_history) { - BM_select_history_store(em->bm, (BMElem *)efa); + BM_select_history_store(bm, (BMElem *)efa); } } else { @@ -354,14 +352,15 @@ void uvedit_face_select_enable(const Scene *scene, } void uvedit_face_select_disable(const Scene *scene, - BMEditMesh *em, + BMesh *bm, BMFace *efa, const int cd_loop_uv_offset) { + BLI_assert(cd_loop_uv_offset >= 0); const ToolSettings *ts = scene->toolsettings; if (ts->uv_flag & UV_SYNC_SELECTION) { - BM_face_select_set(em->bm, efa, false); + BM_face_select_set(bm, efa, false); } else { BMLoop *l; @@ -407,11 +406,11 @@ void uvedit_edge_select_set_with_sticky(const Scene *scene, BMLoop *l, const bool select, const bool do_history, - const uint cd_loop_uv_offset) + const int cd_loop_uv_offset) { const ToolSettings *ts = scene->toolsettings; if (ts->uv_flag & UV_SYNC_SELECTION) { - uvedit_edge_select_set(scene, em, l, select, do_history, cd_loop_uv_offset); + uvedit_edge_select_set(scene, em->bm, l, select, do_history, cd_loop_uv_offset); return; } @@ -419,7 +418,7 @@ void uvedit_edge_select_set_with_sticky(const Scene *scene, switch (sticky) { case SI_STICKY_DISABLE: { if (uvedit_face_visible_test(scene, l->f)) { - uvedit_edge_select_set(scene, em, l, select, do_history, cd_loop_uv_offset); + uvedit_edge_select_set(scene, em->bm, l, select, do_history, cd_loop_uv_offset); } break; } @@ -501,7 +500,7 @@ void uvedit_edge_select_set_noflush(const Scene *scene, } void uvedit_edge_select_set(const Scene *scene, - BMEditMesh *em, + BMesh *bm, BMLoop *l, const bool select, const bool do_history, @@ -509,36 +508,33 @@ void uvedit_edge_select_set(const Scene *scene, { if (select) { - uvedit_edge_select_enable(scene, em, l, do_history, cd_loop_uv_offset); + uvedit_edge_select_enable(scene, bm, l, do_history, cd_loop_uv_offset); } else { - uvedit_edge_select_disable(scene, em, l, cd_loop_uv_offset); + uvedit_edge_select_disable(scene, bm, l, cd_loop_uv_offset); } } -void uvedit_edge_select_enable(const Scene *scene, - BMEditMesh *em, - BMLoop *l, - const bool do_history, - const int cd_loop_uv_offset) +void uvedit_edge_select_enable( + const Scene *scene, BMesh *bm, BMLoop *l, const bool do_history, const int cd_loop_uv_offset) { const ToolSettings *ts = scene->toolsettings; if (ts->uv_flag & UV_SYNC_SELECTION) { if (ts->selectmode & SCE_SELECT_FACE) { - BM_face_select_set(em->bm, l->f, true); + BM_face_select_set(bm, l->f, true); } else if (ts->selectmode & SCE_SELECT_EDGE) { - BM_edge_select_set(em->bm, l->e, true); + BM_edge_select_set(bm, l->e, true); } else { - BM_vert_select_set(em->bm, l->e->v1, true); - BM_vert_select_set(em->bm, l->e->v2, true); + BM_vert_select_set(bm, l->e->v1, true); + BM_vert_select_set(bm, l->e->v2, true); } if (do_history) { - BM_select_history_store(em->bm, (BMElem *)l->e); + BM_select_history_store(bm, (BMElem *)l->e); } } else { @@ -552,7 +548,7 @@ void uvedit_edge_select_enable(const Scene *scene, } void uvedit_edge_select_disable(const Scene *scene, - BMEditMesh *em, + BMesh *bm, BMLoop *l, const int cd_loop_uv_offset) @@ -561,14 +557,14 @@ void uvedit_edge_select_disable(const Scene *scene, if (ts->uv_flag & UV_SYNC_SELECTION) { if (ts->selectmode & SCE_SELECT_FACE) { - BM_face_select_set(em->bm, l->f, false); + BM_face_select_set(bm, l->f, false); } else if (ts->selectmode & SCE_SELECT_EDGE) { - BM_edge_select_set(em->bm, l->e, false); + BM_edge_select_set(bm, l->e, false); } else { - BM_vert_select_set(em->bm, l->e->v1, false); - BM_vert_select_set(em->bm, l->e->v2, false); + BM_vert_select_set(bm, l->e->v1, false); + BM_vert_select_set(bm, l->e->v2, false); } } else { @@ -629,11 +625,11 @@ void uvedit_uv_select_set_with_sticky(const Scene *scene, BMLoop *l, const bool select, const bool do_history, - const uint cd_loop_uv_offset) + const int cd_loop_uv_offset) { const ToolSettings *ts = scene->toolsettings; if (ts->uv_flag & UV_SYNC_SELECTION) { - uvedit_uv_select_set(scene, em, l, select, do_history, cd_loop_uv_offset); + uvedit_uv_select_set(scene, em->bm, l, select, do_history, cd_loop_uv_offset); return; } @@ -641,7 +637,7 @@ void uvedit_uv_select_set_with_sticky(const Scene *scene, switch (sticky) { case SI_STICKY_DISABLE: { if (uvedit_face_visible_test(scene, l->f)) { - uvedit_uv_select_set(scene, em, l, select, do_history, cd_loop_uv_offset); + uvedit_uv_select_set(scene, em->bm, l, select, do_history, cd_loop_uv_offset); } break; } @@ -695,7 +691,8 @@ void uvedit_uv_select_shared_vert(const Scene *scene, } if (do_select) { - uvedit_uv_select_set(scene, em, l_radial_iter, select, do_history, cd_loop_uv_offset); + uvedit_uv_select_set( + scene, em->bm, l_radial_iter, select, do_history, cd_loop_uv_offset); } } } @@ -704,25 +701,22 @@ void uvedit_uv_select_shared_vert(const Scene *scene, } void uvedit_uv_select_set(const Scene *scene, - BMEditMesh *em, + BMesh *bm, BMLoop *l, const bool select, const bool do_history, const int cd_loop_uv_offset) { if (select) { - uvedit_uv_select_enable(scene, em, l, do_history, cd_loop_uv_offset); + uvedit_uv_select_enable(scene, bm, l, do_history, cd_loop_uv_offset); } else { - uvedit_uv_select_disable(scene, em, l, cd_loop_uv_offset); + uvedit_uv_select_disable(scene, bm, l, cd_loop_uv_offset); } } -void uvedit_uv_select_enable(const Scene *scene, - BMEditMesh *em, - BMLoop *l, - const bool do_history, - const int cd_loop_uv_offset) +void uvedit_uv_select_enable( + const Scene *scene, BMesh *bm, BMLoop *l, const bool do_history, const int cd_loop_uv_offset) { const ToolSettings *ts = scene->toolsettings; @@ -732,14 +726,14 @@ void uvedit_uv_select_enable(const Scene *scene, if (ts->uv_flag & UV_SYNC_SELECTION) { if (ts->selectmode & SCE_SELECT_FACE) { - BM_face_select_set(em->bm, l->f, true); + BM_face_select_set(bm, l->f, true); } else { - BM_vert_select_set(em->bm, l->v, true); + BM_vert_select_set(bm, l->v, true); } if (do_history) { - BM_select_history_store(em->bm, (BMElem *)l->v); + BM_select_history_store(bm, (BMElem *)l->v); } } else { @@ -749,7 +743,7 @@ void uvedit_uv_select_enable(const Scene *scene, } void uvedit_uv_select_disable(const Scene *scene, - BMEditMesh *em, + BMesh *bm, BMLoop *l, const int cd_loop_uv_offset) { @@ -757,10 +751,10 @@ void uvedit_uv_select_disable(const Scene *scene, if (ts->uv_flag & UV_SYNC_SELECTION) { if (ts->selectmode & SCE_SELECT_FACE) { - BM_face_select_set(em->bm, l->f, false); + BM_face_select_set(bm, l->f, false); } else { - BM_vert_select_set(em->bm, l->v, false); + BM_vert_select_set(bm, l->v, false); } } else { @@ -1140,7 +1134,7 @@ BMLoop *uv_find_nearest_loop_from_vert(struct Scene *scene, const float co[2]) { BMEditMesh *em = BKE_editmesh_from_object(obedit); - const uint cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV); + const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV); BMIter liter; BMLoop *l; @@ -1168,7 +1162,8 @@ BMLoop *uv_find_nearest_loop_from_edge(struct Scene *scene, const float co[2]) { BMEditMesh *em = BKE_editmesh_from_object(obedit); - const uint cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV); + const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV); + BLI_assert(cd_loop_uv_offset >= 0); BMIter eiter; BMLoop *l; @@ -1975,7 +1970,7 @@ static void uv_select_linked_multi(Scene *scene, BM_face_select_set(em->bm, efa, value); \ } \ else { \ - uvedit_face_select_set(scene, em, efa, value, false, cd_loop_uv_offset); \ + uvedit_face_select_set(scene, em->bm, efa, value, false, cd_loop_uv_offset); \ } \ (void)0 @@ -2053,7 +2048,7 @@ static int uv_select_more_less(bContext *C, const bool select) uint objects_len = 0; Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data_with_uvs( - view_layer, ((View3D *)NULL), &objects_len); + scene, view_layer, ((View3D *)NULL), &objects_len); const bool is_uv_face_selectmode = (ts->uv_selectmode == UV_SELECT_FACE); @@ -2408,7 +2403,7 @@ static int uv_select_all_exec(bContext *C, wmOperator *op) uint objects_len = 0; Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data_with_uvs( - view_layer, ((View3D *)NULL), &objects_len); + scene, view_layer, ((View3D *)NULL), &objects_len); uv_select_all_perform_multi(scene, objects, objects_len, action); @@ -2670,10 +2665,11 @@ static bool uv_mouse_select_multi(bContext *C, } static bool uv_mouse_select(bContext *C, const float co[2], const struct SelectPick_Params *params) { + const Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); uint objects_len = 0; Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data_with_uvs( - view_layer, ((View3D *)NULL), &objects_len); + scene, view_layer, ((View3D *)NULL), &objects_len); bool changed = uv_mouse_select_multi(C, objects, objects_len, co, params); MEM_freeN(objects); return changed; @@ -2822,10 +2818,11 @@ static int uv_mouse_select_loop_generic(bContext *C, const bool extend, enum eUVLoopGenericType loop_type) { + const Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); uint objects_len = 0; Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data_with_uvs( - view_layer, ((View3D *)NULL), &objects_len); + scene, view_layer, ((View3D *)NULL), &objects_len); int ret = uv_mouse_select_loop_generic_multi(C, objects, objects_len, co, extend, loop_type); MEM_freeN(objects); return ret; @@ -2982,7 +2979,7 @@ static int uv_select_linked_internal(bContext *C, wmOperator *op, const wmEvent uint objects_len = 0; Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data_with_uvs( - view_layer, ((View3D *)NULL), &objects_len); + scene, view_layer, ((View3D *)NULL), &objects_len); if (pick) { float co[2]; @@ -3140,7 +3137,7 @@ static int uv_select_split_exec(bContext *C, wmOperator *op) uint objects_len = 0; Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data_with_uvs( - view_layer, ((View3D *)NULL), &objects_len); + scene, view_layer, ((View3D *)NULL), &objects_len); for (uint ob_index = 0; ob_index < objects_len; ob_index++) { Object *obedit = objects[ob_index]; @@ -3247,7 +3244,7 @@ static void uv_select_flush_from_tag_sticky_loc_internal(const Scene *scene, UvMapVert *start_vlist = NULL, *vlist_iter; BMFace *efa_vlist; - uvedit_uv_select_set(scene, em, l, select, false, cd_loop_uv_offset); + uvedit_uv_select_set(scene, em->bm, l, select, false, cd_loop_uv_offset); vlist_iter = BM_uv_vert_map_at_index(vmap, BM_elem_index_get(l->v)); @@ -3265,7 +3262,6 @@ static void uv_select_flush_from_tag_sticky_loc_internal(const Scene *scene, vlist_iter = start_vlist; while (vlist_iter) { - if (vlist_iter != start_vlist && vlist_iter->separate) { break; } @@ -3278,7 +3274,7 @@ static void uv_select_flush_from_tag_sticky_loc_internal(const Scene *scene, l_other = BM_iter_at_index( em->bm, BM_LOOPS_OF_FACE, efa_vlist, vlist_iter->loop_of_poly_index); - uvedit_uv_select_set(scene, em, l_other, select, false, cd_loop_uv_offset); + uvedit_uv_select_set(scene, em->bm, l_other, select, false, cd_loop_uv_offset); } vlist_iter = vlist_iter->next; } @@ -3345,7 +3341,7 @@ static void uv_select_flush_from_tag_face(const Scene *scene, Object *obedit, co else { /* SI_STICKY_DISABLE or ts->uv_flag & UV_SYNC_SELECTION */ BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { if (BM_elem_flag_test(efa, BM_ELEM_TAG)) { - uvedit_face_select_set(scene, em, efa, select, false, cd_loop_uv_offset); + uvedit_face_select_set(scene, em->bm, efa, select, false, cd_loop_uv_offset); } } } @@ -3394,7 +3390,7 @@ static void uv_select_flush_from_tag_loop(const Scene *scene, Object *obedit, co BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { if (BM_elem_flag_test(l->v, BM_ELEM_TAG)) { - uvedit_uv_select_set(scene, em, l, select, false, cd_loop_uv_offset); + uvedit_uv_select_set(scene, em->bm, l, select, false, cd_loop_uv_offset); } } } @@ -3423,7 +3419,7 @@ static void uv_select_flush_from_tag_loop(const Scene *scene, Object *obedit, co BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { if (BM_elem_flag_test(l, BM_ELEM_TAG)) { - uvedit_uv_select_set(scene, em, l, select, false, cd_loop_uv_offset); + uvedit_uv_select_set(scene, em->bm, l, select, false, cd_loop_uv_offset); } } } @@ -3544,7 +3540,7 @@ static int uv_box_select_exec(bContext *C, wmOperator *op) uint objects_len = 0; Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data_with_uvs( - view_layer, ((View3D *)NULL), &objects_len); + scene, view_layer, ((View3D *)NULL), &objects_len); if (use_pre_deselect) { uv_select_all_perform_multi(scene, objects, objects_len, SEL_DESELECT); @@ -3644,14 +3640,14 @@ static int uv_box_select_exec(bContext *C, wmOperator *op) if (!pinned || (ts->uv_flag & UV_SYNC_SELECTION)) { /* UV_SYNC_SELECTION - can't do pinned selection */ if (BLI_rctf_isect_pt_v(&rectf, luv->uv)) { - uvedit_uv_select_set(scene, em, l, select, false, cd_loop_uv_offset); + uvedit_uv_select_set(scene, em->bm, l, select, false, cd_loop_uv_offset); BM_elem_flag_enable(l->v, BM_ELEM_TAG); has_selected = true; } } else if (pinned) { if ((luv->flag & MLOOPUV_PINNED) && BLI_rctf_isect_pt_v(&rectf, luv->uv)) { - uvedit_uv_select_set(scene, em, l, select, false, cd_loop_uv_offset); + uvedit_uv_select_set(scene, em->bm, l, select, false, cd_loop_uv_offset); BM_elem_flag_enable(l->v, BM_ELEM_TAG); } } @@ -3718,9 +3714,9 @@ void UV_OT_select_box(wmOperatorType *ot) /** \name Circle Select Operator * \{ */ -static int uv_circle_select_is_point_inside(const float uv[2], - const float offset[2], - const float ellipse[2]) +static bool uv_circle_select_is_point_inside(const float uv[2], + const float offset[2], + const float ellipse[2]) { /* normalized ellipse: ell[0] = scaleX, ell[1] = scaleY */ const float co[2] = { @@ -3730,10 +3726,10 @@ static int uv_circle_select_is_point_inside(const float uv[2], return len_squared_v2(co) < 1.0f; } -static int uv_circle_select_is_edge_inside(const float uv_a[2], - const float uv_b[2], - const float offset[2], - const float ellipse[2]) +static bool uv_circle_select_is_edge_inside(const float uv_a[2], + const float uv_b[2], + const float offset[2], + const float ellipse[2]) { /* normalized ellipse: ell[0] = scaleX, ell[1] = scaleY */ const float co_a[2] = { @@ -3791,7 +3787,7 @@ static int uv_circle_select_exec(bContext *C, wmOperator *op) uint objects_len = 0; Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data_with_uvs( - view_layer, ((View3D *)NULL), &objects_len); + scene, view_layer, ((View3D *)NULL), &objects_len); const eSelectOp sel_op = ED_select_op_modal(RNA_enum_get(op->ptr, "mode"), WM_gesture_is_modal_first(op->customdata)); @@ -3864,7 +3860,7 @@ static int uv_circle_select_exec(bContext *C, wmOperator *op) luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); if (uv_circle_select_is_point_inside(luv->uv, offset, ellipse)) { changed = true; - uvedit_uv_select_set(scene, em, l, select, false, cd_loop_uv_offset); + uvedit_uv_select_set(scene, em->bm, l, select, false, cd_loop_uv_offset); BM_elem_flag_enable(l->v, BM_ELEM_TAG); has_selected = true; } @@ -3997,7 +3993,7 @@ static bool do_lasso_select_mesh_uv(bContext *C, uint objects_len = 0; Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data_with_uvs( - view_layer, ((View3D *)NULL), &objects_len); + scene, view_layer, ((View3D *)NULL), &objects_len); if (use_pre_deselect) { uv_select_all_perform_multi(scene, objects, objects_len, SEL_DESELECT); @@ -4094,7 +4090,7 @@ static bool do_lasso_select_mesh_uv(bContext *C, MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); if (do_lasso_select_mesh_uv_is_point_inside( region, &rect, mcoords, mcoords_len, luv->uv)) { - uvedit_uv_select_set(scene, em, l, select, false, cd_loop_uv_offset); + uvedit_uv_select_set(scene, em->bm, l, select, false, cd_loop_uv_offset); changed = true; BM_elem_flag_enable(l->v, BM_ELEM_TAG); has_selected = true; @@ -4196,7 +4192,7 @@ static int uv_select_pinned_exec(bContext *C, wmOperator *op) uint objects_len = 0; Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data_with_uvs( - view_layer, ((View3D *)NULL), &objects_len); + scene, view_layer, ((View3D *)NULL), &objects_len); for (uint ob_index = 0; ob_index < objects_len; ob_index++) { Object *obedit = objects[ob_index]; @@ -4214,7 +4210,7 @@ static int uv_select_pinned_exec(bContext *C, wmOperator *op) luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); if (luv->flag & MLOOPUV_PINNED) { - uvedit_uv_select_enable(scene, em, l, false, cd_loop_uv_offset); + uvedit_uv_select_enable(scene, em->bm, l, false, cd_loop_uv_offset); changed = true; } } @@ -4331,7 +4327,7 @@ static int uv_select_overlap(bContext *C, const bool extend) uint objects_len = 0; Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data_with_uvs( - view_layer, ((View3D *)NULL), &objects_len); + scene, view_layer, ((View3D *)NULL), &objects_len); /* Calculate maximum number of tree nodes and prepare initial selection. */ uint uv_tri_len = 0; @@ -4467,8 +4463,8 @@ static int uv_select_overlap(bContext *C, const bool extend) /* Main tri-tri overlap test. */ const float endpoint_bias = -1e-4f; if (overlap_tri_tri_uv_test(o_a->tri, o_b->tri, endpoint_bias)) { - uvedit_face_select_enable(scene, em_a, face_a, false, cd_loop_uv_offset_a); - uvedit_face_select_enable(scene, em_b, face_b, false, cd_loop_uv_offset_b); + uvedit_face_select_enable(scene, em_a->bm, face_a, false, cd_loop_uv_offset_a); + uvedit_face_select_enable(scene, em_b->bm, face_b, false, cd_loop_uv_offset_b); } } @@ -4679,7 +4675,7 @@ static int uv_select_similar_vert_exec(bContext *C, wmOperator *op) uint objects_len = 0; Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data_with_uvs( - view_layer, ((View3D *)NULL), &objects_len); + scene, view_layer, ((View3D *)NULL), &objects_len); int max_verts_selected_all = 0; for (uint ob_index = 0; ob_index < objects_len; ob_index++) { @@ -4764,7 +4760,7 @@ static int uv_select_similar_vert_exec(bContext *C, wmOperator *op) const float needle = get_uv_vert_needle(type, l->v, ob_m3, luv, cd_loop_uv_offset); bool select = ED_select_similar_compare_float_tree(tree_1d, needle, threshold, compare); if (select) { - uvedit_uv_select_set(scene, em, l, select, false, cd_loop_uv_offset); + uvedit_uv_select_set(scene, em->bm, l, select, false, cd_loop_uv_offset); changed = true; } } @@ -4792,7 +4788,7 @@ static int uv_select_similar_edge_exec(bContext *C, wmOperator *op) uint objects_len = 0; Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data_with_uvs( - view_layer, ((View3D *)NULL), &objects_len); + scene, view_layer, ((View3D *)NULL), &objects_len); int max_edges_selected_all = 0; for (uint ob_index = 0; ob_index < objects_len; ob_index++) { @@ -4883,7 +4879,7 @@ static int uv_select_similar_edge_exec(bContext *C, wmOperator *op) float needle = get_uv_edge_needle(type, l->e, ob_m3, luv_a, luv_b, cd_loop_uv_offset); bool select = ED_select_similar_compare_float_tree(tree_1d, needle, threshold, compare); if (select) { - uvedit_edge_select_set(scene, em, l, select, false, cd_loop_uv_offset); + uvedit_edge_select_set(scene, em->bm, l, select, false, cd_loop_uv_offset); changed = true; } } @@ -4911,7 +4907,7 @@ static int uv_select_similar_face_exec(bContext *C, wmOperator *op) uint objects_len = 0; Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data_with_uvs( - view_layer, ((View3D *)NULL), &objects_len); + scene, view_layer, ((View3D *)NULL), &objects_len); int max_faces_selected_all = 0; for (uint ob_index = 0; ob_index < objects_len; ob_index++) { @@ -4983,7 +4979,7 @@ static int uv_select_similar_face_exec(bContext *C, wmOperator *op) bool select = ED_select_similar_compare_float_tree(tree_1d, needle, threshold, compare); if (select) { - uvedit_face_select_set(scene, em, face, select, do_history, cd_loop_uv_offset); + uvedit_face_select_set(scene, em->bm, face, select, do_history, cd_loop_uv_offset); changed = true; } } @@ -5016,7 +5012,7 @@ static int uv_select_similar_island_exec(bContext *C, wmOperator *op) uint objects_len = 0; Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data_with_uvs( - view_layer, ((View3D *)NULL), &objects_len); + scene, view_layer, ((View3D *)NULL), &objects_len); ListBase *island_list_ptr = MEM_callocN(sizeof(*island_list_ptr) * objects_len, __func__); int island_list_len = 0; @@ -5103,7 +5099,7 @@ static int uv_select_similar_island_exec(bContext *C, wmOperator *op) bool do_history = false; for (int j = 0; j < island->faces_len; j++) { uvedit_face_select_set( - scene, em, island->faces[j], select, do_history, island->cd_loop_uv_offset); + scene, em->bm, island->faces[j], select, do_history, island->cd_loop_uv_offset); } changed = true; } @@ -5390,7 +5386,7 @@ static void uv_isolate_selected_islands(const Scene *scene, BLI_assert((scene->toolsettings->uv_flag & UV_SYNC_SELECTION) == 0); BMFace *efa; BMIter iter, liter; - UvElementMap *elementmap = BM_uv_element_map_create(em->bm, scene, false, false, true); + UvElementMap *elementmap = BM_uv_element_map_create(em->bm, scene, false, false, true, true); if (elementmap == NULL) { return; } @@ -5487,7 +5483,7 @@ void ED_uvedit_selectmode_clean(const Scene *scene, Object *obedit) if (uvedit_face_select_test(scene, efa, cd_loop_uv_offset)) { BM_elem_flag_enable(efa, BM_ELEM_TAG); } - uvedit_face_select_set(scene, em, efa, false, false, cd_loop_uv_offset); + uvedit_face_select_set(scene, em->bm, efa, false, false, cd_loop_uv_offset); } } uv_select_flush_from_tag_face(scene, obedit, true); @@ -5509,7 +5505,7 @@ void ED_uvedit_selectmode_clean_multi(bContext *C) uint objects_len = 0; Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data_with_uvs( - view_layer, ((View3D *)NULL), &objects_len); + scene, view_layer, ((View3D *)NULL), &objects_len); for (uint ob_index = 0; ob_index < objects_len; ob_index++) { Object *obedit = objects[ob_index]; diff --git a/source/blender/editors/uvedit/uvedit_smart_stitch.c b/source/blender/editors/uvedit/uvedit_smart_stitch.c index 4a2ea5c3aa6..05b98ab9627 100644 --- a/source/blender/editors/uvedit/uvedit_smart_stitch.c +++ b/source/blender/editors/uvedit/uvedit_smart_stitch.c @@ -916,7 +916,7 @@ static void stitch_propagate_uv_final_position(Scene *scene, if (final) { copy_v2_v2(luv->uv, final_position[index].uv); - uvedit_uv_select_enable(scene, state->em, l, false, cd_loop_uv_offset); + uvedit_uv_select_enable(scene, state->em->bm, l, false, cd_loop_uv_offset); } else { int face_preview_pos = @@ -1664,7 +1664,7 @@ static void stitch_calculate_edge_normal(BMEditMesh *em, UvEdge *edge, float *no static void stitch_draw_vbo(GPUVertBuf *vbo, GPUPrimType prim_type, const float col[4]) { GPUBatch *batch = GPU_batch_create_ex(prim_type, vbo, NULL, GPU_BATCH_OWNS_VBO); - GPU_batch_program_set_builtin(batch, GPU_SHADER_2D_UNIFORM_COLOR); + GPU_batch_program_set_builtin(batch, GPU_SHADER_3D_UNIFORM_COLOR); GPU_batch_uniform_4fv(batch, "color", col); GPU_batch_draw(batch); GPU_batch_discard(batch); @@ -1855,7 +1855,7 @@ static StitchState *stitch_init(bContext *C, * for stitch this isn't useful behavior, see T86924. */ const int selectmode_orig = scene->toolsettings->selectmode; scene->toolsettings->selectmode = SCE_SELECT_VERTEX; - state->element_map = BM_uv_element_map_create(state->em->bm, scene, false, true, true); + state->element_map = BM_uv_element_map_create(state->em->bm, scene, false, true, true, true); scene->toolsettings->selectmode = selectmode_orig; if (!state->element_map) { @@ -2215,7 +2215,7 @@ static int stitch_init_all(bContext *C, wmOperator *op) View3D *v3d = CTX_wm_view3d(C); uint objects_len = 0; Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data_with_uvs( - view_layer, v3d, &objects_len); + scene, view_layer, v3d, &objects_len); if (objects_len == 0) { MEM_freeN(objects); diff --git a/source/blender/editors/uvedit/uvedit_unwrap_ops.c b/source/blender/editors/uvedit/uvedit_unwrap_ops.c index 2c7ad012dd2..e66629f8fb0 100644 --- a/source/blender/editors/uvedit/uvedit_unwrap_ops.c +++ b/source/blender/editors/uvedit/uvedit_unwrap_ops.c @@ -798,7 +798,7 @@ static bool minimize_stretch_init(bContext *C, wmOperator *op) uint objects_len = 0; Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data_with_uvs( - view_layer, CTX_wm_view3d(C), &objects_len); + scene, view_layer, CTX_wm_view3d(C), &objects_len); if (!uvedit_have_selection_multi(scene, objects, objects_len, &options)) { MEM_freeN(objects); @@ -1116,7 +1116,7 @@ static int pack_islands_exec(bContext *C, wmOperator *op) uint objects_len = 0; Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data_with_uvs( - view_layer, CTX_wm_view3d(C), &objects_len); + scene, view_layer, CTX_wm_view3d(C), &objects_len); /* Early exit in case no UVs are selected. */ if (!uvedit_have_selection_multi(scene, objects, objects_len, &options)) { @@ -1208,7 +1208,7 @@ static int average_islands_scale_exec(bContext *C, wmOperator *op) uint objects_len = 0; Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data_with_uvs( - view_layer, CTX_wm_view3d(C), &objects_len); + scene, view_layer, CTX_wm_view3d(C), &objects_len); if (!uvedit_have_selection_multi(scene, objects, objects_len, &options)) { MEM_freeN(objects); @@ -1714,10 +1714,12 @@ static void uv_map_clip_correct_properties(wmOperatorType *ot) * such as "Unwrap" & "Smart UV Projections" will need to handle aspect correction themselves. * For now keep using a single aspect for all faces in this case. */ -static void uv_map_clip_correct_multi(Object **objects, - uint objects_len, - wmOperator *op, - bool per_face_aspect) +static void uv_map_clip_correct(const Scene *scene, + Object **objects, + uint objects_len, + wmOperator *op, + bool per_face_aspect, + bool only_selected_uvs) { BMFace *efa; BMLoop *l; @@ -1754,6 +1756,10 @@ static void uv_map_clip_correct_multi(Object **objects, continue; } + if (only_selected_uvs && !uvedit_face_select_test(scene, efa, cd_loop_uv_offset)) { + continue; + } + BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); minmax_v2v2_v2(min, max, luv->uv); @@ -1767,6 +1773,10 @@ static void uv_map_clip_correct_multi(Object **objects, continue; } + if (only_selected_uvs && !uvedit_face_select_test(scene, efa, cd_loop_uv_offset)) { + continue; + } + BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); clamp_v2(luv->uv, 0.0f, 1.0f); @@ -1803,6 +1813,10 @@ static void uv_map_clip_correct_multi(Object **objects, continue; } + if (only_selected_uvs && !uvedit_face_select_test(scene, efa, cd_loop_uv_offset)) { + continue; + } + BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); @@ -1814,18 +1828,13 @@ static void uv_map_clip_correct_multi(Object **objects, } } -static void uv_map_clip_correct(Object *ob, wmOperator *op) -{ - uv_map_clip_correct_multi(&ob, 1, op, true); -} - /** \} */ /* -------------------------------------------------------------------- */ /** \name UV Unwrap Operator * \{ */ -/* Assumes UV Map exists, doesn't run update funcs. */ +/* Assumes UV Map exists, doesn't run update functions. */ static void uvedit_unwrap(const Scene *scene, Object *obedit, const UnwrapOptions *options, @@ -1911,7 +1920,7 @@ static int unwrap_exec(bContext *C, wmOperator *op) uint objects_len = 0; Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data( - view_layer, CTX_wm_view3d(C), &objects_len); + scene, view_layer, CTX_wm_view3d(C), &objects_len); UnwrapOptions options = { .topology_from_uvs = false, @@ -2245,6 +2254,12 @@ static int smart_project_exec(bContext *C, wmOperator *op) /* May be NULL. */ View3D *v3d = CTX_wm_view3d(C); + bool only_selected_uvs = false; + if (CTX_wm_space_image(C)) { + /* Inside the UV Editor, only project selected UVs. */ + only_selected_uvs = true; + } + const float project_angle_limit = RNA_float_get(op->ptr, "angle_limit"); const float island_margin = RNA_float_get(op->ptr, "island_margin"); const float area_weight = RNA_float_get(op->ptr, "area_weight"); @@ -2257,7 +2272,7 @@ static int smart_project_exec(bContext *C, wmOperator *op) uint objects_len = 0; Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data( - view_layer, v3d, &objects_len); + scene, view_layer, v3d, &objects_len); Object **objects_changed = MEM_mallocN(sizeof(*objects_changed) * objects_len, __func__); uint object_changed_len = 0; @@ -2275,7 +2290,8 @@ static int smart_project_exec(bContext *C, wmOperator *op) continue; } - const uint cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV); + const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV); + BLI_assert(cd_loop_uv_offset >= 0); ThickFace *thick_faces = MEM_mallocN(sizeof(*thick_faces) * em->bm->totface, __func__); uint thick_faces_len = 0; @@ -2283,6 +2299,14 @@ static int smart_project_exec(bContext *C, wmOperator *op) if (!BM_elem_flag_test(efa, BM_ELEM_SELECT)) { continue; } + + if (only_selected_uvs) { + if (!uvedit_face_select_test(scene, efa, cd_loop_uv_offset)) { + uvedit_face_select_disable(scene, em->bm, efa, cd_loop_uv_offset); + continue; + } + } + thick_faces[thick_faces_len].area = BM_face_calc_area(efa); thick_faces[thick_faces_len].efa = efa; thick_faces_len++; @@ -2397,6 +2421,7 @@ static int smart_project_exec(bContext *C, wmOperator *op) .rotate = true, /* We could make this optional. */ .rotate_align_axis = 1, + .only_selected_uvs = true, .only_selected_faces = true, .correct_aspect = correct_aspect, .use_seams = true, @@ -2404,7 +2429,8 @@ static int smart_project_exec(bContext *C, wmOperator *op) /* #ED_uvedit_pack_islands_multi only supports `per_face_aspect = false`. */ const bool per_face_aspect = false; - uv_map_clip_correct_multi(objects_changed, object_changed_len, op, per_face_aspect); + uv_map_clip_correct( + scene, objects_changed, object_changed_len, op, per_face_aspect, only_selected_uvs); } MEM_freeN(objects_changed); @@ -2511,7 +2537,7 @@ static int uv_from_view_exec(bContext *C, wmOperator *op) /* NOTE: objects that aren't touched are set to NULL (to skip clipping). */ uint objects_len = 0; Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data( - view_layer, v3d, &objects_len); + scene, view_layer, v3d, &objects_len); if (use_orthographic) { /* Calculate average object position. */ @@ -2606,7 +2632,9 @@ static int uv_from_view_exec(bContext *C, wmOperator *op) } if (changed_multi) { - uv_map_clip_correct_multi(objects, objects_len, op, true); + const bool per_face_aspect = true; + const bool only_selected_uvs = false; + uv_map_clip_correct(scene, objects, objects_len, op, per_face_aspect, only_selected_uvs); } MEM_freeN(objects); @@ -2660,12 +2688,13 @@ void UV_OT_project_from_view(wmOperatorType *ot) static int reset_exec(bContext *C, wmOperator *UNUSED(op)) { + const Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); View3D *v3d = CTX_wm_view3d(C); uint objects_len = 0; Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data( - view_layer, v3d, &objects_len); + scene, view_layer, v3d, &objects_len); for (uint ob_index = 0; ob_index < objects_len; ob_index++) { Object *obedit = objects[ob_index]; Mesh *me = (Mesh *)obedit->data; @@ -2766,10 +2795,16 @@ static int sphere_project_exec(bContext *C, wmOperator *op) const Scene *scene = CTX_data_scene(C); View3D *v3d = CTX_wm_view3d(C); + bool only_selected_uvs = false; + if (CTX_wm_space_image(C)) { + /* Inside the UV Editor, only project selected UVs. */ + only_selected_uvs = true; + } + ViewLayer *view_layer = CTX_data_view_layer(C); uint objects_len = 0; Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data( - view_layer, v3d, &objects_len); + scene, view_layer, v3d, &objects_len); for (uint ob_index = 0; ob_index < objects_len; ob_index++) { Object *obedit = objects[ob_index]; BMEditMesh *em = BKE_editmesh_from_object(obedit); @@ -2798,6 +2833,13 @@ static int sphere_project_exec(bContext *C, wmOperator *op) continue; } + if (only_selected_uvs) { + if (!uvedit_face_select_test(scene, efa, cd_loop_uv_offset)) { + uvedit_face_select_disable(scene, em->bm, efa, cd_loop_uv_offset); + continue; + } + } + BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); @@ -2807,7 +2849,8 @@ static int sphere_project_exec(bContext *C, wmOperator *op) uv_map_mirror(em, efa); } - uv_map_clip_correct(obedit, op); + const bool per_face_aspect = true; + uv_map_clip_correct(scene, &obedit, 1, op, per_face_aspect, only_selected_uvs); DEG_id_tag_update(obedit->data, ID_RECALC_GEOMETRY); WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data); @@ -2864,10 +2907,16 @@ static int cylinder_project_exec(bContext *C, wmOperator *op) const Scene *scene = CTX_data_scene(C); View3D *v3d = CTX_wm_view3d(C); + bool only_selected_uvs = false; + if (CTX_wm_space_image(C)) { + /* Inside the UV Editor, only project selected UVs. */ + only_selected_uvs = true; + } + ViewLayer *view_layer = CTX_data_view_layer(C); uint objects_len = 0; Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data( - view_layer, v3d, &objects_len); + scene, view_layer, v3d, &objects_len); for (uint ob_index = 0; ob_index < objects_len; ob_index++) { Object *obedit = objects[ob_index]; BMEditMesh *em = BKE_editmesh_from_object(obedit); @@ -2896,16 +2945,21 @@ static int cylinder_project_exec(bContext *C, wmOperator *op) continue; } + if (only_selected_uvs && !uvedit_face_select_test(scene, efa, cd_loop_uv_offset)) { + uvedit_face_select_disable(scene, em->bm, efa, cd_loop_uv_offset); + continue; + } + BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); - uv_cylinder_project(luv->uv, l->v->co, center, rotmat); } uv_map_mirror(em, efa); } - uv_map_clip_correct(obedit, op); + const bool per_face_aspect = true; + uv_map_clip_correct(scene, &obedit, 1, op, per_face_aspect, only_selected_uvs); DEG_id_tag_update(obedit->data, ID_RECALC_GEOMETRY); WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data); @@ -2939,9 +2993,11 @@ void UV_OT_cylinder_project(wmOperatorType *ot) /** \name Cube UV Project Operator * \{ */ -static void uvedit_unwrap_cube_project(BMesh *bm, +static void uvedit_unwrap_cube_project(const Scene *scene, + BMesh *bm, float cube_size, - bool use_select, + const bool use_select, + const bool only_selected_uvs, const float center[3]) { BMFace *efa; @@ -2973,6 +3029,10 @@ static void uvedit_unwrap_cube_project(BMesh *bm, if (use_select && !BM_elem_flag_test(efa, BM_ELEM_SELECT)) { continue; } + if (only_selected_uvs && !uvedit_face_select_test(scene, efa, cd_loop_uv_offset)) { + uvedit_face_select_disable(scene, bm, efa, cd_loop_uv_offset); + continue; + } axis_dominant_v3(&cox, &coy, efa->no); @@ -2989,13 +3049,19 @@ static int cube_project_exec(bContext *C, wmOperator *op) const Scene *scene = CTX_data_scene(C); View3D *v3d = CTX_wm_view3d(C); + bool only_selected_uvs = false; + if (CTX_wm_space_image(C)) { + /* Inside the UV Editor, only cube project selected UVs. */ + only_selected_uvs = true; + } + PropertyRNA *prop_cube_size = RNA_struct_find_property(op->ptr, "cube_size"); const float cube_size_init = RNA_property_float_get(op->ptr, prop_cube_size); ViewLayer *view_layer = CTX_data_view_layer(C); uint objects_len = 0; Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data( - view_layer, v3d, &objects_len); + scene, view_layer, v3d, &objects_len); for (uint ob_index = 0; ob_index < objects_len; ob_index++) { Object *obedit = objects[ob_index]; BMEditMesh *em = BKE_editmesh_from_object(obedit); @@ -3031,9 +3097,10 @@ static int cube_project_exec(bContext *C, wmOperator *op) } } - uvedit_unwrap_cube_project(em->bm, cube_size, true, center); + uvedit_unwrap_cube_project(scene, em->bm, cube_size, true, only_selected_uvs, center); - uv_map_clip_correct(obedit, op); + const bool per_face_aspect = true; + uv_map_clip_correct(scene, &obedit, 1, op, per_face_aspect, only_selected_uvs); DEG_id_tag_update(obedit->data, ID_RECALC_GEOMETRY); WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data); @@ -3100,7 +3167,7 @@ void ED_uvedit_add_simple_uvs(Main *bmain, const Scene *scene, Object *ob) /* select all uv loops first - pack parameters needs this to make sure charts are registered */ ED_uvedit_select_all(bm); /* A cube size of 2.0 maps [-1..1] vertex coords to [0.0..1.0] in UV coords. */ - uvedit_unwrap_cube_project(bm, 2.0, false, NULL); + uvedit_unwrap_cube_project(scene, bm, 2.0, false, false, NULL); /* Set the margin really quickly before the packing operation. */ scene->toolsettings->uvcalc_margin = 0.001f; uvedit_pack_islands(scene, ob, bm); |