Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'source/blender/editors')
-rw-r--r--source/blender/editors/animation/anim_channels_defines.c2
-rw-r--r--source/blender/editors/animation/anim_filter.c4
-rw-r--r--source/blender/editors/animation/anim_markers.c67
-rw-r--r--source/blender/editors/animation/drivers.c2
-rw-r--r--source/blender/editors/animation/keyframes_draw.c3
-rw-r--r--source/blender/editors/animation/keyframing.c2
-rw-r--r--source/blender/editors/armature/pose_slide.c24
-rw-r--r--source/blender/editors/armature/pose_utils.c6
-rw-r--r--source/blender/editors/curve/editfont.c2
-rw-r--r--source/blender/editors/gpencil/gpencil_ops_versioning.c4
-rw-r--r--source/blender/editors/include/ED_screen.h3
-rw-r--r--source/blender/editors/include/UI_resources.h1
-rw-r--r--source/blender/editors/interface/CMakeLists.txt1
-rw-r--r--source/blender/editors/interface/interface.c4
-rw-r--r--source/blender/editors/interface/interface_eyedropper.c1
-rw-r--r--source/blender/editors/interface/interface_eyedropper_gpencil_color.c324
-rw-r--r--source/blender/editors/interface/interface_handlers.c12
-rw-r--r--source/blender/editors/interface/interface_icons.c1
-rw-r--r--source/blender/editors/interface/interface_icons_event.c7
-rw-r--r--source/blender/editors/interface/interface_intern.h3
-rw-r--r--source/blender/editors/interface/interface_ops.c1
-rw-r--r--source/blender/editors/interface/interface_region_popover.c3
-rw-r--r--source/blender/editors/interface/interface_widgets.c10
-rw-r--r--source/blender/editors/interface/resources.c4
-rw-r--r--source/blender/editors/mesh/editmesh_extrude_spin_gizmo.c1
-rw-r--r--source/blender/editors/mesh/editmesh_loopcut.c1
-rw-r--r--source/blender/editors/mesh/editmesh_mask_extract.c21
-rw-r--r--source/blender/editors/mesh/editmesh_tools.c12
-rw-r--r--source/blender/editors/mesh/mesh_data.c8
-rw-r--r--source/blender/editors/object/object_add.c36
-rw-r--r--source/blender/editors/object/object_bake_api.c8
-rw-r--r--source/blender/editors/object/object_edit.c10
-rw-r--r--source/blender/editors/object/object_relations.c2
-rw-r--r--source/blender/editors/object/object_remesh.c97
-rw-r--r--source/blender/editors/object/object_select.c4
-rw-r--r--source/blender/editors/physics/particle_edit.c6
-rw-r--r--source/blender/editors/physics/rigidbody_constraint.c8
-rw-r--r--source/blender/editors/physics/rigidbody_object.c2
-rw-r--r--source/blender/editors/render/render_internal.c2
-rw-r--r--source/blender/editors/render/render_preview.c4
-rw-r--r--source/blender/editors/render/render_shading.c14
-rw-r--r--source/blender/editors/render/render_view.c4
-rw-r--r--source/blender/editors/screen/area.c2
-rw-r--r--source/blender/editors/screen/screen_draw.c2
-rw-r--r--source/blender/editors/screen/screen_edit.c5
-rw-r--r--source/blender/editors/screen/screen_ops.c35
-rw-r--r--source/blender/editors/sculpt_paint/paint_cursor.c15
-rw-r--r--source/blender/editors/sculpt_paint/paint_image.c2
-rw-r--r--source/blender/editors/sculpt_paint/paint_image_2d.c73
-rw-r--r--source/blender/editors/sculpt_paint/paint_intern.h2
-rw-r--r--source/blender/editors/sculpt_paint/paint_mask.c12
-rw-r--r--source/blender/editors/sculpt_paint/paint_stroke.c19
-rw-r--r--source/blender/editors/sculpt_paint/paint_vertex.c33
-rw-r--r--source/blender/editors/sculpt_paint/sculpt.c708
-rw-r--r--source/blender/editors/sculpt_paint/sculpt_intern.h13
-rw-r--r--source/blender/editors/sculpt_paint/sculpt_undo.c101
-rw-r--r--source/blender/editors/sound/sound_ops.c3
-rw-r--r--source/blender/editors/space_action/action_select.c150
-rw-r--r--source/blender/editors/space_clip/tracking_ops_solve.c6
-rw-r--r--source/blender/editors/space_file/file_ops.c82
-rw-r--r--source/blender/editors/space_file/filelist.c2
-rw-r--r--source/blender/editors/space_file/filesel.c14
-rw-r--r--source/blender/editors/space_image/image_ops.c7
-rw-r--r--source/blender/editors/space_image/image_undo.c30
-rw-r--r--source/blender/editors/space_nla/nla_select.c47
-rw-r--r--source/blender/editors/space_node/drawnode.c51
-rw-r--r--source/blender/editors/space_node/node_group.c106
-rw-r--r--source/blender/editors/space_node/node_select.c76
-rw-r--r--source/blender/editors/space_outliner/outliner_collections.c2
-rw-r--r--source/blender/editors/space_outliner/outliner_draw.c1
-rw-r--r--source/blender/editors/space_outliner/outliner_edit.c18
-rw-r--r--source/blender/editors/space_outliner/outliner_select.c5
-rw-r--r--source/blender/editors/space_outliner/outliner_tree.c8
-rw-r--r--source/blender/editors/space_sequencer/sequencer_edit.c2
-rw-r--r--source/blender/editors/space_sequencer/sequencer_select.c50
-rw-r--r--source/blender/editors/space_text/text_format_lua.c34
-rw-r--r--source/blender/editors/space_text/text_format_osl.c10
-rw-r--r--source/blender/editors/space_text/text_format_pov.c10
-rw-r--r--source/blender/editors/space_text/text_format_pov_ini.c6
-rw-r--r--source/blender/editors/space_text/text_format_py.c10
-rw-r--r--source/blender/editors/space_view3d/space_view3d.c11
-rw-r--r--source/blender/editors/space_view3d/view3d_draw.c8
-rw-r--r--source/blender/editors/space_view3d/view3d_draw_legacy.c4
-rw-r--r--source/blender/editors/space_view3d/view3d_gizmo_armature.c1
-rw-r--r--source/blender/editors/space_view3d/view3d_gizmo_camera.c1
-rw-r--r--source/blender/editors/space_view3d/view3d_gizmo_empty.c1
-rw-r--r--source/blender/editors/space_view3d/view3d_gizmo_forcefield.c1
-rw-r--r--source/blender/editors/space_view3d/view3d_gizmo_light.c1
-rw-r--r--source/blender/editors/space_view3d/view3d_gizmo_ruler.c18
-rw-r--r--source/blender/editors/space_view3d/view3d_ops.c12
-rw-r--r--source/blender/editors/space_view3d/view3d_select.c10
-rw-r--r--source/blender/editors/space_view3d/view3d_view.c8
-rw-r--r--source/blender/editors/space_view3d/view3d_walk.c21
-rw-r--r--source/blender/editors/transform/transform.c8
-rw-r--r--source/blender/editors/transform/transform_convert.c10
-rw-r--r--source/blender/editors/transform/transform_convert_mesh.c2
-rw-r--r--source/blender/editors/transform/transform_generics.c12
-rw-r--r--source/blender/editors/transform/transform_gizmo_3d.c35
-rw-r--r--source/blender/editors/transform/transform_orientations.c1
-rw-r--r--source/blender/editors/transform/transform_snap_object.c3
100 files changed, 1587 insertions, 1064 deletions
diff --git a/source/blender/editors/animation/anim_channels_defines.c b/source/blender/editors/animation/anim_channels_defines.c
index d80b96f0d74..8951677b32f 100644
--- a/source/blender/editors/animation/anim_channels_defines.c
+++ b/source/blender/editors/animation/anim_channels_defines.c
@@ -3411,7 +3411,7 @@ static void acf_nlatrack_color(bAnimContext *UNUSED(ac), bAnimListElem *ale, flo
}
/* set color for nla track */
- UI_GetThemeColorShade3fv(TH_HEADER, ((nonSolo == false) ? 20 : -20), r_color);
+ UI_GetThemeColorShade3fv(TH_NLA_TRACK, ((nonSolo == false) ? 20 : -20), r_color);
}
/* name for nla track entries */
diff --git a/source/blender/editors/animation/anim_filter.c b/source/blender/editors/animation/anim_filter.c
index 48493c9e961..f73c8a5b71a 100644
--- a/source/blender/editors/animation/anim_filter.c
+++ b/source/blender/editors/animation/anim_filter.c
@@ -1818,7 +1818,7 @@ static size_t animdata_filter_gpencil(bAnimContext *ac,
!(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) == 0) {
+ if ((base->flag & BASE_VISIBLE_DEPSGRAPH) == 0) {
continue;
}
@@ -3017,7 +3017,7 @@ static bool animdata_filter_base_is_ok(bDopeSheet *ads, Base *base, int filter_m
*/
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) == 0) {
+ if ((base->flag & BASE_VISIBLE_DEPSGRAPH) == 0) {
return false;
}
diff --git a/source/blender/editors/animation/anim_markers.c b/source/blender/editors/animation/anim_markers.c
index 2a35acdefcb..36583ecf060 100644
--- a/source/blender/editors/animation/anim_markers.c
+++ b/source/blender/editors/animation/anim_markers.c
@@ -1148,33 +1148,48 @@ static void deselect_markers(ListBase *markers)
}
/* select/deselect TimeMarker at current frame */
-static void select_timeline_marker_frame(ListBase *markers, int frame, bool extend)
+static int select_timeline_marker_frame(ListBase *markers,
+ int frame,
+ bool extend,
+ bool wait_to_deselect_others)
{
- TimeMarker *marker, *marker_first = NULL;
+ TimeMarker *marker, *marker_selected = NULL;
+ int ret_val = OPERATOR_FINISHED;
+
+ if (extend) {
+ wait_to_deselect_others = false;
+ }
/* support for selection cycling */
for (marker = markers->first; marker; marker = marker->next) {
if (marker->frame == frame) {
if (marker->flag & SELECT) {
- marker_first = marker->next;
+ marker_selected = marker->next;
break;
}
}
}
- /* if extend is not set, then deselect markers */
- if (extend == false) {
- deselect_markers(markers);
+ if (wait_to_deselect_others && marker_selected) {
+ ret_val = OPERATOR_RUNNING_MODAL;
}
+ /* if extend is not set, then deselect markers */
+ else {
+ if (extend == false) {
+ deselect_markers(markers);
+ }
- LISTBASE_CIRCULAR_FORWARD_BEGIN (markers, marker, marker_first) {
- /* this way a not-extend select will always give 1 selected marker */
- if (marker->frame == frame) {
- marker->flag ^= SELECT;
- break;
+ LISTBASE_CIRCULAR_FORWARD_BEGIN (markers, marker, marker_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_selected);
}
- LISTBASE_CIRCULAR_FORWARD_END(markers, marker, marker_first);
+
+ return ret_val;
}
static void select_marker_camera_switch(
@@ -1221,17 +1236,17 @@ static void select_marker_camera_switch(
#endif
}
-static int ed_marker_select(bContext *C, const wmEvent *event, bool extend, bool camera)
+static int ed_marker_select(
+ bContext *C, const int mval[2], bool extend, bool camera, bool wait_to_deselect_others)
{
ListBase *markers = ED_context_get_markers(C);
- ARegion *ar = CTX_wm_region(C);
View2D *v2d = UI_view2d_fromcontext(C);
+ int ret_val = OPERATOR_FINISHED;
- float mouse_region_x = event->x - ar->winrct.xmin;
- if (region_position_is_over_marker(v2d, markers, mouse_region_x)) {
- float frame_at_mouse_position = UI_view2d_region_to_view_x(v2d, mouse_region_x);
+ if (region_position_is_over_marker(v2d, markers, mval[0])) {
+ float frame_at_mouse_position = UI_view2d_region_to_view_x(v2d, mval[0]);
int cfra = ED_markers_find_nearest_marker_time(markers, frame_at_mouse_position);
- select_timeline_marker_frame(markers, cfra, extend);
+ ret_val = select_timeline_marker_frame(markers, cfra, extend, wait_to_deselect_others);
select_marker_camera_switch(C, camera, extend, markers, cfra);
}
@@ -1243,17 +1258,22 @@ static int ed_marker_select(bContext *C, const wmEvent *event, bool extend, bool
WM_event_add_notifier(C, NC_ANIMATION | ND_MARKERS, NULL);
/* allowing tweaks, but needs OPERATOR_FINISHED, otherwise renaming fails... [#25987] */
- return OPERATOR_FINISHED | OPERATOR_PASS_THROUGH;
+ return ret_val | OPERATOR_PASS_THROUGH;
}
-static int ed_marker_select_invoke(bContext *C, wmOperator *op, const wmEvent *event)
+static int ed_marker_select_exec(bContext *C, wmOperator *op)
{
const bool extend = RNA_boolean_get(op->ptr, "extend");
+ const bool wait_to_deselect_others = RNA_boolean_get(op->ptr, "wait_to_deselect_others");
bool camera = false;
#ifdef DURIAN_CAMERA_SWITCH
camera = RNA_boolean_get(op->ptr, "camera");
#endif
- return ed_marker_select(C, event, extend, camera);
+ int mval[2];
+ mval[0] = RNA_int_get(op->ptr, "mouse_x");
+ mval[1] = RNA_int_get(op->ptr, "mouse_y");
+
+ return ed_marker_select(C, mval, extend, camera, wait_to_deselect_others);
}
static void MARKER_OT_select(wmOperatorType *ot)
@@ -1266,12 +1286,15 @@ static void MARKER_OT_select(wmOperatorType *ot)
ot->idname = "MARKER_OT_select";
/* api callbacks */
- ot->invoke = ed_marker_select_invoke;
ot->poll = ed_markers_poll_markers_exist;
+ ot->exec = ed_marker_select_exec;
+ ot->invoke = WM_generic_select_invoke;
+ ot->modal = WM_generic_select_modal;
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ WM_operator_properties_generic_select(ot);
prop = RNA_def_boolean(ot->srna, "extend", 0, "Extend", "Extend the selection");
RNA_def_property_flag(prop, PROP_SKIP_SAVE);
#ifdef DURIAN_CAMERA_SWITCH
diff --git a/source/blender/editors/animation/drivers.c b/source/blender/editors/animation/drivers.c
index 61c8da08954..64f7fe034dc 100644
--- a/source/blender/editors/animation/drivers.c
+++ b/source/blender/editors/animation/drivers.c
@@ -111,7 +111,7 @@ struct FCurve *alloc_driver_fcurve(const char rna_path[],
FCurve *fcu = MEM_callocN(sizeof(FCurve), "FCurve");
fcu->flag = (FCURVE_VISIBLE | FCURVE_SELECTED);
- fcu->auto_smoothing = FCURVE_SMOOTH_CONT_ACCEL;
+ fcu->auto_smoothing = U.auto_smoothing_new;
/* store path - make copy, and store that */
if (rna_path) {
diff --git a/source/blender/editors/animation/keyframes_draw.c b/source/blender/editors/animation/keyframes_draw.c
index c174ce83bea..479e7192b0e 100644
--- a/source/blender/editors/animation/keyframes_draw.c
+++ b/source/blender/editors/animation/keyframes_draw.c
@@ -545,8 +545,7 @@ int actkeyblock_get_valid_hold(ActKeyColumn *ac)
return 0;
}
- const int hold_mask = (ACTKEYBLOCK_FLAG_ANY_HOLD | ACTKEYBLOCK_FLAG_STATIC_HOLD |
- ACTKEYBLOCK_FLAG_ANY_HOLD);
+ const int hold_mask = (ACTKEYBLOCK_FLAG_ANY_HOLD | ACTKEYBLOCK_FLAG_STATIC_HOLD);
return (ac->block.flag & ~ac->block.conflict) & hold_mask;
}
diff --git a/source/blender/editors/animation/keyframing.c b/source/blender/editors/animation/keyframing.c
index 0f8b8742659..8203a9131fa 100644
--- a/source/blender/editors/animation/keyframing.c
+++ b/source/blender/editors/animation/keyframing.c
@@ -202,7 +202,7 @@ FCurve *verify_fcurve(Main *bmain,
fcu = MEM_callocN(sizeof(FCurve), "FCurve");
fcu->flag = (FCURVE_VISIBLE | FCURVE_SELECTED);
- fcu->auto_smoothing = FCURVE_SMOOTH_CONT_ACCEL;
+ fcu->auto_smoothing = U.auto_smoothing_new;
if (BLI_listbase_is_empty(&act->curves)) {
fcu->flag |= FCURVE_ACTIVE; /* first one added active */
}
diff --git a/source/blender/editors/armature/pose_slide.c b/source/blender/editors/armature/pose_slide.c
index 616daf94e57..7ed41b5b4d0 100644
--- a/source/blender/editors/armature/pose_slide.c
+++ b/source/blender/editors/armature/pose_slide.c
@@ -368,30 +368,14 @@ static void pose_slide_apply_val(tPoseSlideOp *pso, FCurve *fcu, Object *ob, flo
switch (pso->mode) {
case POSESLIDE_PUSH: /* make the current pose more pronounced */
{
- /* perform a weighted average here, favoring the middle pose
- * - numerator should be larger than denominator to 'expand' the result
- * - perform this weighting a number of times given by the percentage...
- */
- /* TODO: maybe a sensitivity ctrl on top of this is needed */
- int iters = (int)ceil(10.0f * pso->percentage);
-
- while (iters-- > 0) {
- (*val) = (-((sVal * w2) + (eVal * w1)) + ((*val) * 6.0f)) / 5.0f;
- }
+ /* Slide the pose away from the breakdown pose in the timeline */
+ (*val) -= ((sVal * w2) + (eVal * w1) - (*val)) * pso->percentage;
break;
}
case POSESLIDE_RELAX: /* make the current pose more like its surrounding ones */
{
- /* perform a weighted average here, favoring the middle pose
- * - numerator should be smaller than denominator to 'relax' the result
- * - perform this weighting a number of times given by the percentage...
- */
- /* TODO: maybe a sensitivity ctrl on top of this is needed */
- int iters = (int)ceil(10.0f * pso->percentage);
-
- while (iters-- > 0) {
- (*val) = (((sVal * w2) + (eVal * w1)) + ((*val) * 5.0f)) / 6.0f;
- }
+ /* Slide the pose towards the breakdown pose in the timeline */
+ (*val) += ((sVal * w2) + (eVal * w1) - (*val)) * pso->percentage;
break;
}
case POSESLIDE_BREAKDOWN: /* make the current pose slide around between the endpoints */
diff --git a/source/blender/editors/armature/pose_utils.c b/source/blender/editors/armature/pose_utils.c
index 3f6db956643..8d2d7d790d2 100644
--- a/source/blender/editors/armature/pose_utils.c
+++ b/source/blender/editors/armature/pose_utils.c
@@ -32,6 +32,7 @@
#include "DNA_scene_types.h"
#include "BKE_action.h"
+#include "BKE_animsys.h"
#include "BKE_armature.h"
#include "BKE_idprop.h"
#include "BKE_layer.h"
@@ -223,6 +224,11 @@ void poseAnim_mapping_refresh(bContext *C, Scene *UNUSED(scene), Object *ob)
{
DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
WM_event_add_notifier(C, NC_OBJECT | ND_POSE, ob);
+
+ AnimData *adt = BKE_animdata_from_id(&ob->id);
+ if (adt && adt->action) {
+ DEG_id_tag_update(&adt->action->id, ID_RECALC_ANIMATION_NO_FLUSH);
+ }
}
/* reset changes made to current pose */
diff --git a/source/blender/editors/curve/editfont.c b/source/blender/editors/curve/editfont.c
index 603b0967ace..e11807d818f 100644
--- a/source/blender/editors/curve/editfont.c
+++ b/source/blender/editors/curve/editfont.c
@@ -1876,6 +1876,7 @@ void ED_curve_editfont_make(Object *obedit)
memcpy(ef->textbufinfo, cu->strinfo, ef->len * sizeof(CharInfo));
+ ef->pos = cu->pos;
if (ef->pos > ef->len) {
ef->pos = ef->len;
}
@@ -1883,7 +1884,6 @@ void ED_curve_editfont_make(Object *obedit)
cu->curinfo = ef->textbufinfo[ef->pos ? ef->pos - 1 : 0];
/* Other vars */
- ef->pos = cu->pos;
ef->selstart = cu->selstart;
ef->selend = cu->selend;
diff --git a/source/blender/editors/gpencil/gpencil_ops_versioning.c b/source/blender/editors/gpencil/gpencil_ops_versioning.c
index af49587f9ad..3d56cb0fcb1 100644
--- a/source/blender/editors/gpencil/gpencil_ops_versioning.c
+++ b/source/blender/editors/gpencil/gpencil_ops_versioning.c
@@ -54,6 +54,9 @@
#include "ED_object.h"
#include "ED_gpencil.h"
+#include "DEG_depsgraph.h"
+#include "DEG_depsgraph_query.h"
+
#include "gpencil_intern.h"
/* Free all of a gp-colors */
@@ -111,6 +114,7 @@ static int gpencil_convert_old_files_exec(bContext *C, wmOperator *op)
ob = BKE_object_add_for_data(
bmain, view_layer, OB_GPENCIL, "GP_Scene", &scene->gpd->id, false);
zero_v3(ob->loc);
+ DEG_relations_tag_update(bmain); /* added object */
/* convert grease pencil palettes (version >= 2.78) to materials and weights */
for (const bGPDpalette *palette = gpd->palettes.first; palette; palette = palette->next) {
diff --git a/source/blender/editors/include/ED_screen.h b/source/blender/editors/include/ED_screen.h
index 7c3aac6c688..c3e61f5f2b2 100644
--- a/source/blender/editors/include/ED_screen.h
+++ b/source/blender/editors/include/ED_screen.h
@@ -246,7 +246,8 @@ ScrArea *ED_screen_temp_space_open(struct bContext *C,
int sizex,
int sizey,
eSpace_Type space_type,
- int display_type);
+ int display_type,
+ bool dialog);
void ED_screens_header_tools_menu_create(struct bContext *C, struct uiLayout *layout, void *arg);
void ED_screens_footer_tools_menu_create(struct bContext *C, struct uiLayout *layout, void *arg);
void ED_screens_navigation_bar_tools_menu_create(struct bContext *C,
diff --git a/source/blender/editors/include/UI_resources.h b/source/blender/editors/include/UI_resources.h
index 76ab4a53eb8..89579b88d24 100644
--- a/source/blender/editors/include/UI_resources.h
+++ b/source/blender/editors/include/UI_resources.h
@@ -283,6 +283,7 @@ typedef enum ThemeColorID {
TH_NLA_TWEAK, /* 'tweaking' track in NLA */
TH_NLA_TWEAK_DUPLI, /* error/warning flag for other strips referencing dupli strip */
+ TH_NLA_TRACK,
TH_NLA_TRANSITION,
TH_NLA_TRANSITION_SEL,
TH_NLA_META,
diff --git a/source/blender/editors/interface/CMakeLists.txt b/source/blender/editors/interface/CMakeLists.txt
index bc8d25e8d9e..d33023c69a1 100644
--- a/source/blender/editors/interface/CMakeLists.txt
+++ b/source/blender/editors/interface/CMakeLists.txt
@@ -50,6 +50,7 @@ set(SRC
interface_eyedropper_datablock.c
interface_eyedropper_depth.c
interface_eyedropper_driver.c
+ interface_eyedropper_gpencil_color.c
interface_handlers.c
interface_icons.c
interface_icons_event.c
diff --git a/source/blender/editors/interface/interface.c b/source/blender/editors/interface/interface.c
index f05100e9065..54fd91e5361 100644
--- a/source/blender/editors/interface/interface.c
+++ b/source/blender/editors/interface/interface.c
@@ -786,6 +786,8 @@ static bool ui_but_update_from_old_block(const bContext *C,
oldbut->flag = (oldbut->flag & ~flag_copy) | (but->flag & flag_copy);
oldbut->drawflag = (oldbut->drawflag & ~drawflag_copy) | (but->drawflag & drawflag_copy);
+ SWAP(ListBase, but->extra_op_icons, oldbut->extra_op_icons);
+
/* copy hardmin for list rows to prevent 'sticking' highlight to mouse position
* when scrolling without moving mouse (see [#28432]) */
if (ELEM(oldbut->type, UI_BTYPE_ROW, UI_BTYPE_LISTROW)) {
@@ -3389,7 +3391,7 @@ static void ui_but_build_drawstr_float(uiBut *but, double value)
if (value == (double)FLT_MAX) {
STR_CONCAT(but->drawstr, slen, "inf");
}
- else if (value == (double)-FLT_MIN) {
+ else if (value == (double)-FLT_MAX) {
STR_CONCAT(but->drawstr, slen, "-inf");
}
else if (subtype == PROP_PERCENTAGE) {
diff --git a/source/blender/editors/interface/interface_eyedropper.c b/source/blender/editors/interface/interface_eyedropper.c
index 3c26c37b610..988dea270f5 100644
--- a/source/blender/editors/interface/interface_eyedropper.c
+++ b/source/blender/editors/interface/interface_eyedropper.c
@@ -69,6 +69,7 @@ wmKeyMap *eyedropper_modal_keymap(wmKeyConfig *keyconf)
WM_modalkeymap_assign(keymap, "UI_OT_eyedropper_id");
WM_modalkeymap_assign(keymap, "UI_OT_eyedropper_depth");
WM_modalkeymap_assign(keymap, "UI_OT_eyedropper_driver");
+ WM_modalkeymap_assign(keymap, "UI_OT_eyedropper_gpencil_color");
return keymap;
}
diff --git a/source/blender/editors/interface/interface_eyedropper_gpencil_color.c b/source/blender/editors/interface/interface_eyedropper_gpencil_color.c
new file mode 100644
index 00000000000..02d4596e93c
--- /dev/null
+++ b/source/blender/editors/interface/interface_eyedropper_gpencil_color.c
@@ -0,0 +1,324 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2009 Blender Foundation.
+ * All rights reserved.
+ */
+
+/** \file
+ * \ingroup edinterface
+ *
+ * Eyedropper (RGB Color)
+ *
+ * Defines:
+ * - #UI_OT_eyedropper_gpencil_color
+ */
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_string.h"
+
+#include "BLT_translation.h"
+
+#include "DNA_gpencil_types.h"
+#include "DNA_space_types.h"
+
+#include "BKE_context.h"
+#include "BKE_gpencil.h"
+#include "BKE_main.h"
+#include "BKE_material.h"
+#include "BKE_report.h"
+
+#include "UI_interface.h"
+
+#include "IMB_colormanagement.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+
+#include "RNA_access.h"
+#include "RNA_define.h"
+
+#include "ED_gpencil.h"
+#include "ED_screen.h"
+#include "ED_undo.h"
+
+#include "DEG_depsgraph.h"
+#include "DEG_depsgraph_build.h"
+
+#include "interface_intern.h"
+#include "interface_eyedropper_intern.h"
+
+typedef struct EyedropperGPencil {
+ struct ColorManagedDisplay *display;
+ /** color under cursor RGB */
+ float color[3];
+} EyedropperGPencil;
+
+/* Helper: Draw status message while the user is running the operator */
+static void eyedropper_gpencil_status_indicators(bContext *C)
+{
+ char msg_str[UI_MAX_DRAW_STR];
+ BLI_strncpy(
+ msg_str, TIP_("LMB: Stroke - Shift: Fill - Shift+Ctrl: Stroke + Fill"), UI_MAX_DRAW_STR);
+
+ ED_workspace_status_text(C, msg_str);
+}
+
+/* Initialize. */
+static bool eyedropper_gpencil_init(bContext *C, wmOperator *op)
+{
+ EyedropperGPencil *eye = MEM_callocN(sizeof(EyedropperGPencil), __func__);
+
+ op->customdata = eye;
+ Scene *scene = CTX_data_scene(C);
+
+ const char *display_device;
+ display_device = scene->display_settings.display_device;
+ eye->display = IMB_colormanagement_display_get_named(display_device);
+
+ return true;
+}
+
+/* Exit and free memory. */
+static void eyedropper_gpencil_exit(bContext *C, wmOperator *op)
+{
+ /* Clear status message area. */
+ ED_workspace_status_text(C, NULL);
+
+ MEM_SAFE_FREE(op->customdata);
+}
+
+/* Set the material. */
+static void eyedropper_gpencil_color_set(bContext *C, const wmEvent *event, EyedropperGPencil *eye)
+{
+ Main *bmain = CTX_data_main(C);
+ Object *ob = CTX_data_active_object(C);
+ Material *ma = NULL;
+
+ const bool only_stroke = ((!event->ctrl) && (!event->shift));
+ const bool only_fill = ((!event->ctrl) && (event->shift));
+ const bool both = ((event->ctrl) && (event->shift));
+
+ float col_conv[4];
+ bool found = false;
+
+ /* Convert from linear rgb space to display space because grease pencil colors are in display
+ * space, and this conversion is needed to undo the conversion to linear performed by
+ * eyedropper_color_sample_fl. */
+ if (eye->display) {
+ copy_v3_v3(col_conv, eye->color);
+ IMB_colormanagement_scene_linear_to_display_v3(col_conv, eye->display);
+ }
+ else {
+ copy_v3_v3(col_conv, eye->color);
+ }
+
+ /* Look for a similar material in grease pencil slots. */
+ short *totcol = give_totcolp(ob);
+ for (short i = 0; i < *totcol; i++) {
+ ma = give_current_material(ob, i + 1);
+ if (ma == NULL) {
+ continue;
+ }
+
+ MaterialGPencilStyle *gp_style = ma->gp_style;
+ if (gp_style != NULL) {
+ /* Check stroke color. */
+ bool found_stroke = compare_v3v3(gp_style->stroke_rgba, col_conv, 0.01f) &&
+ (gp_style->flag & GP_STYLE_STROKE_SHOW);
+ /* Check fill color. */
+ bool found_fill = compare_v3v3(gp_style->fill_rgba, col_conv, 0.01f) &&
+ (gp_style->flag & GP_STYLE_FILL_SHOW);
+
+ if ((only_stroke) && (found_stroke) && ((gp_style->flag & GP_STYLE_FILL_SHOW) == 0)) {
+ found = true;
+ }
+ else if ((only_fill) && (found_fill) && ((gp_style->flag & GP_STYLE_STROKE_SHOW) == 0)) {
+ found = true;
+ }
+ else if ((both) && (found_stroke) && (found_fill)) {
+ found = true;
+ }
+
+ /* Found existing material. */
+ if (found) {
+ ob->actcol = i + 1;
+ WM_main_add_notifier(NC_MATERIAL | ND_SHADING_LINKS, NULL);
+ WM_main_add_notifier(NC_SPACE | ND_SPACE_VIEW3D, NULL);
+ return;
+ }
+ }
+ }
+
+ /* If material was not found add a new material with stroke and/or fill color
+ * depending of the secondary key (LMB: Stroke, Shift: Fill, Shift+Ctrl: Stroke/Fill)
+ */
+ int idx;
+ Material *ma_new = BKE_gpencil_object_material_new(bmain, ob, "Material", &idx);
+ WM_main_add_notifier(NC_OBJECT | ND_OB_SHADING, &ob->id);
+ WM_main_add_notifier(NC_MATERIAL | ND_SHADING_LINKS, NULL);
+ DEG_relations_tag_update(bmain);
+
+ BLI_assert(ma_new != NULL);
+
+ MaterialGPencilStyle *gp_style_new = ma_new->gp_style;
+ BLI_assert(gp_style_new != NULL);
+
+ /* Only create Stroke (default option). */
+ if (only_stroke) {
+ /* Stroke color. */
+ gp_style_new->flag |= GP_STYLE_STROKE_SHOW;
+ gp_style_new->flag &= ~GP_STYLE_FILL_SHOW;
+ copy_v3_v3(gp_style_new->stroke_rgba, col_conv);
+ zero_v4(gp_style_new->fill_rgba);
+ }
+ /* Fill Only. */
+ else if (only_fill) {
+ /* Fill color. */
+ gp_style_new->flag &= ~GP_STYLE_STROKE_SHOW;
+ gp_style_new->flag |= GP_STYLE_FILL_SHOW;
+ zero_v4(gp_style_new->stroke_rgba);
+ copy_v3_v3(gp_style_new->fill_rgba, col_conv);
+ }
+ /* Stroke and Fill. */
+ else if (both) {
+ gp_style_new->flag |= GP_STYLE_STROKE_SHOW | GP_STYLE_FILL_SHOW;
+ copy_v3_v3(gp_style_new->stroke_rgba, col_conv);
+ copy_v3_v3(gp_style_new->fill_rgba, col_conv);
+ }
+ /* Push undo for new created material. */
+ ED_undo_push(C, "Add Grease Pencil Material");
+}
+
+/* Sample the color below cursor. */
+static void eyedropper_gpencil_color_sample(bContext *C, EyedropperGPencil *eye, int mx, int my)
+{
+ eyedropper_color_sample_fl(C, mx, my, eye->color);
+}
+
+/* Cancel operator. */
+static void eyedropper_gpencil_cancel(bContext *C, wmOperator *op)
+{
+ eyedropper_gpencil_exit(C, op);
+}
+
+/* Main modal status check. */
+static int eyedropper_gpencil_modal(bContext *C, wmOperator *op, const wmEvent *event)
+{
+ EyedropperGPencil *eye = (EyedropperGPencil *)op->customdata;
+ /* Handle modal keymap */
+ switch (event->type) {
+ case EVT_MODAL_MAP: {
+ switch (event->val) {
+ case EYE_MODAL_SAMPLE_BEGIN: {
+ return OPERATOR_RUNNING_MODAL;
+ }
+ case EYE_MODAL_CANCEL: {
+ eyedropper_gpencil_cancel(C, op);
+ return OPERATOR_CANCELLED;
+ }
+ case EYE_MODAL_SAMPLE_CONFIRM: {
+ eyedropper_gpencil_color_sample(C, eye, event->x, event->y);
+
+ /* Create material. */
+ eyedropper_gpencil_color_set(C, event, eye);
+ WM_main_add_notifier(NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
+
+ eyedropper_gpencil_exit(C, op);
+ return OPERATOR_FINISHED;
+ break;
+ }
+ default: {
+ break;
+ }
+ }
+ break;
+ }
+ case MOUSEMOVE:
+ case INBETWEEN_MOUSEMOVE: {
+ eyedropper_gpencil_color_sample(C, eye, event->x, event->y);
+ break;
+ }
+ default: {
+ break;
+ }
+ }
+
+ return OPERATOR_RUNNING_MODAL;
+}
+
+/* Modal Operator init */
+static int eyedropper_gpencil_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
+{
+ /* Init. */
+ if (eyedropper_gpencil_init(C, op)) {
+ /* Add modal temp handler. */
+ WM_event_add_modal_handler(C, op);
+ /* Status message. */
+ eyedropper_gpencil_status_indicators(C);
+
+ return OPERATOR_RUNNING_MODAL;
+ }
+ else {
+ return OPERATOR_PASS_THROUGH;
+ }
+}
+
+/* Repeat operator */
+static int eyedropper_gpencil_exec(bContext *C, wmOperator *op)
+{
+ /* init */
+ if (eyedropper_gpencil_init(C, op)) {
+
+ /* cleanup */
+ eyedropper_gpencil_exit(C, op);
+
+ return OPERATOR_FINISHED;
+ }
+ else {
+ return OPERATOR_PASS_THROUGH;
+ }
+}
+
+static bool eyedropper_gpencil_poll(bContext *C)
+{
+ /* Only valid if the current active object is grease pencil. */
+ Object *obact = CTX_data_active_object(C);
+ if ((obact == NULL) || (obact->type != OB_GPENCIL)) {
+ return false;
+ }
+
+ /* Test we have a window below. */
+ return (CTX_wm_window(C) != NULL);
+}
+
+void UI_OT_eyedropper_gpencil_color(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Grease Pencil Eyedropper";
+ ot->idname = "UI_OT_eyedropper_gpencil_color";
+ ot->description = "Sample a color from the Blender Window and create Grease Pencil material";
+
+ /* api callbacks */
+ ot->invoke = eyedropper_gpencil_invoke;
+ ot->modal = eyedropper_gpencil_modal;
+ ot->cancel = eyedropper_gpencil_cancel;
+ ot->exec = eyedropper_gpencil_exec;
+ ot->poll = eyedropper_gpencil_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_UNDO | OPTYPE_BLOCKING;
+}
diff --git a/source/blender/editors/interface/interface_handlers.c b/source/blender/editors/interface/interface_handlers.c
index e0442ebcca2..83820c919c8 100644
--- a/source/blender/editors/interface/interface_handlers.c
+++ b/source/blender/editors/interface/interface_handlers.c
@@ -108,6 +108,7 @@ static int ui_do_but_EXIT(bContext *C,
const wmEvent *event);
static bool ui_but_find_select_in_enum__cmp(const uiBut *but_a, const uiBut *but_b);
static void ui_textedit_string_set(uiBut *but, struct uiHandleButtonData *data, const char *str);
+static void button_tooltip_timer_reset(bContext *C, uiBut *but);
#ifdef USE_KEYNAV_LIMIT
static void ui_mouse_motion_keynav_init(struct uiKeyNavLock *keynav, const wmEvent *event);
@@ -3967,8 +3968,11 @@ static bool ui_do_but_extra_operator_icon(bContext *C,
uiButExtraOpIcon *op_icon = ui_but_extra_operator_icon_mouse_over_get(but, data, event);
if (op_icon) {
+ ED_region_tag_redraw(data->region);
+ button_tooltip_timer_reset(C, but);
+
ui_but_extra_operator_icon_apply(C, but, op_icon);
- button_activate_exit(C, but, data, false, false);
+ /* Note: 'but', 'data' may now be freed, don't access. */
return true;
}
@@ -7493,6 +7497,7 @@ static void button_activate_init(bContext *C, ARegion *ar, uiBut *but, uiButtonA
data = MEM_callocN(sizeof(uiHandleButtonData), "uiHandleButtonData");
data->wm = CTX_wm_manager(C);
data->window = CTX_wm_window(C);
+ BLI_assert(ar != NULL);
data->region = ar;
#ifdef USE_CONT_MOUSE_CORRECT
@@ -8005,6 +8010,7 @@ void ui_but_execute_begin(struct bContext *UNUSED(C),
*active_back = but->active;
data = MEM_callocN(sizeof(uiHandleButtonData), "uiHandleButtonData_Fake");
but->active = data;
+ BLI_assert(ar != NULL);
data->region = ar;
}
@@ -9816,9 +9822,7 @@ static int ui_pie_handler(bContext *C, const wmEvent *event, uiPopupBlockHandle
if (but && (U.pie_menu_confirm > 0) &&
(dist >= U.dpi_fac * (U.pie_menu_threshold + U.pie_menu_confirm))) {
- if (but) {
- return ui_but_pie_menu_apply(C, menu, but, true);
- }
+ return ui_but_pie_menu_apply(C, menu, but, true);
}
retval = ui_but_pie_menu_apply(C, menu, but, true);
diff --git a/source/blender/editors/interface/interface_icons.c b/source/blender/editors/interface/interface_icons.c
index b844e237366..1495fb7e716 100644
--- a/source/blender/editors/interface/interface_icons.c
+++ b/source/blender/editors/interface/interface_icons.c
@@ -1583,7 +1583,6 @@ static struct {
IconTextureDrawCall normal;
IconTextureDrawCall border;
bool enabled;
- float mat[4][4];
} g_icon_draw_cache = {{{{{0}}}}};
void UI_icon_draw_cache_begin(void)
diff --git a/source/blender/editors/interface/interface_icons_event.c b/source/blender/editors/interface/interface_icons_event.c
index e1ce77b8b61..b7fd953ed63 100644
--- a/source/blender/editors/interface/interface_icons_event.c
+++ b/source/blender/editors/interface/interface_icons_event.c
@@ -171,12 +171,13 @@ void icon_draw_rect_input(float x,
const bool simple_text = false;
- if ((event_type >= AKEY) || (ZKEY <= event_type)) {
+ if ((event_type >= AKEY) && (event_type <= ZKEY)) {
char str[2] = {'A' + (event_type - AKEY), '\0'};
icon_draw_rect_input_default_text(&rect, color, margin, str);
}
- if ((event_type >= F1KEY) || (F12KEY <= event_type)) {
- char str[3] = {'F', '1' + (event_type - F1KEY), '\0'};
+ else if ((event_type >= F1KEY) && (event_type <= F12KEY)) {
+ char str[4];
+ SNPRINTF(str, "F%d", 1 + (event_type - F1KEY));
icon_draw_rect_input_default_text(&rect, color, margin, str);
}
else if (event_type == LEFTSHIFTKEY) {
diff --git a/source/blender/editors/interface/interface_intern.h b/source/blender/editors/interface/interface_intern.h
index 4351b75eb86..81979b1fc8f 100644
--- a/source/blender/editors/interface/interface_intern.h
+++ b/source/blender/editors/interface/interface_intern.h
@@ -971,6 +971,9 @@ void UI_OT_eyedropper_depth(struct wmOperatorType *ot);
/* interface_eyedropper_driver.c */
void UI_OT_eyedropper_driver(struct wmOperatorType *ot);
+/* interface_eyedropper_gpencil_color.c */
+void UI_OT_eyedropper_gpencil_color(struct wmOperatorType *ot);
+
/* interface_util.c */
/**
diff --git a/source/blender/editors/interface/interface_ops.c b/source/blender/editors/interface/interface_ops.c
index 4e56a02997b..7ce4242c697 100644
--- a/source/blender/editors/interface/interface_ops.c
+++ b/source/blender/editors/interface/interface_ops.c
@@ -1751,6 +1751,7 @@ void ED_operatortypes_ui(void)
WM_operatortype_append(UI_OT_eyedropper_id);
WM_operatortype_append(UI_OT_eyedropper_depth);
WM_operatortype_append(UI_OT_eyedropper_driver);
+ WM_operatortype_append(UI_OT_eyedropper_gpencil_color);
}
/**
diff --git a/source/blender/editors/interface/interface_region_popover.c b/source/blender/editors/interface/interface_region_popover.c
index 028d99ac052..cd0421dde09 100644
--- a/source/blender/editors/interface/interface_region_popover.c
+++ b/source/blender/editors/interface/interface_region_popover.c
@@ -334,7 +334,8 @@ int UI_popover_panel_invoke(bContext *C, const char *idname, bool keep_open, Rep
}
if (block) {
- UI_block_active_only_flagged_buttons(C, CTX_wm_region(C), block);
+ uiPopupBlockHandle *handle = block->handle;
+ UI_block_active_only_flagged_buttons(C, handle->region, block);
}
return OPERATOR_INTERFACE;
}
diff --git a/source/blender/editors/interface/interface_widgets.c b/source/blender/editors/interface/interface_widgets.c
index 9f1b11d1354..b3e039292e1 100644
--- a/source/blender/editors/interface/interface_widgets.c
+++ b/source/blender/editors/interface/interface_widgets.c
@@ -4638,9 +4638,6 @@ void ui_draw_but(const bContext *C, ARegion *ar, uiStyle *style, uiBut *but, rct
case UI_BTYPE_SEARCH_MENU:
wt = widget_type(UI_WTYPE_NAME);
- if (but->block->theme_style == UI_BLOCK_THEME_STYLE_POPUP) {
- wt->wcol_theme = &btheme->tui.wcol_menu_back;
- }
break;
case UI_BTYPE_TAB:
@@ -4914,9 +4911,10 @@ static void ui_draw_popover_back_impl(const uiWidgetColors *wcol,
{
/* tsk, this isn't nice. */
const float unit_half = unit_size / 2;
- const float cent_x = mval_origin ?
- CLAMPIS(mval_origin[0], rect->xmin + unit_size, rect->xmax - unit_size) :
- BLI_rcti_cent_x(rect);
+ const float cent_x = mval_origin ? CLAMPIS(mval_origin[0],
+ rect->xmin + unit_size,
+ rect->xmax - unit_size) :
+ BLI_rcti_cent_x(rect);
rect->ymax -= unit_half;
rect->ymin += unit_half;
diff --git a/source/blender/editors/interface/resources.c b/source/blender/editors/interface/resources.c
index 8a570933a33..99594cf0803 100644
--- a/source/blender/editors/interface/resources.c
+++ b/source/blender/editors/interface/resources.c
@@ -371,7 +371,6 @@ const uchar *UI_ThemeGetColorPtr(bTheme *btheme, int spacetype, int colorid)
case TH_OBCENTER_DIA:
cp = &ts->obcenter_dia;
break;
- break;
case TH_EDGE:
cp = ts->edge;
break;
@@ -841,6 +840,9 @@ const uchar *UI_ThemeGetColorPtr(bTheme *btheme, int spacetype, int colorid)
cp = ts->nla_tweakdupli;
break;
+ case TH_NLA_TRACK:
+ cp = ts->nla_track;
+ break;
case TH_NLA_TRANSITION:
cp = ts->nla_transition;
break;
diff --git a/source/blender/editors/mesh/editmesh_extrude_spin_gizmo.c b/source/blender/editors/mesh/editmesh_extrude_spin_gizmo.c
index 7155348fed5..993898bddd5 100644
--- a/source/blender/editors/mesh/editmesh_extrude_spin_gizmo.c
+++ b/source/blender/editors/mesh/editmesh_extrude_spin_gizmo.c
@@ -522,7 +522,6 @@ typedef struct GizmoGroupData_SpinRedo {
PropertyRNA *prop_axis_no;
PropertyRNA *prop_angle;
- float rotate_axis[3];
#ifdef USE_ANGLE_Z_ORIENT
/* Apply 'orient_mat' for the final value. */
float orient_axis_relative[3];
diff --git a/source/blender/editors/mesh/editmesh_loopcut.c b/source/blender/editors/mesh/editmesh_loopcut.c
index 3be94cf99c1..3c3e91e8afe 100644
--- a/source/blender/editors/mesh/editmesh_loopcut.c
+++ b/source/blender/editors/mesh/editmesh_loopcut.c
@@ -386,7 +386,6 @@ static int loopcut_init(bContext *C, wmOperator *op, const wmEvent *event)
bool ok = true;
if (is_interactive == false) {
if (exec_data.base_index >= bases_len) {
- return OPERATOR_CANCELLED;
ok = false;
}
else {
diff --git a/source/blender/editors/mesh/editmesh_mask_extract.c b/source/blender/editors/mesh/editmesh_mask_extract.c
index d066e9ecddc..8d98a3bf231 100644
--- a/source/blender/editors/mesh/editmesh_mask_extract.c
+++ b/source/blender/editors/mesh/editmesh_mask_extract.c
@@ -101,16 +101,21 @@ static int paint_mask_extract_exec(bContext *C, wmOperator *op)
BMIter face_iter;
/* Delete all unmasked faces */
+ const int cd_vert_mask_offset = CustomData_get_offset(&bm->vdata, CD_PAINT_MASK);
+ BLI_assert(cd_vert_mask_offset != -1);
BM_mesh_elem_hflag_disable_all(bm, BM_VERT | BM_EDGE | BM_FACE, BM_ELEM_TAG, false);
float mask_threshold = RNA_float_get(op->ptr, "mask_threshold");
BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) {
- bool delete_face = false;
+ bool keep_face = true;
BM_ITER_ELEM (v, &face_iter, f, BM_VERTS_OF_FACE) {
- float mask = BM_elem_float_data_get(&bm->vdata, v, CD_PAINT_MASK);
- delete_face = mask < mask_threshold;
+ const float mask = BM_ELEM_CD_GET_FLOAT(v, cd_vert_mask_offset);
+ if (mask < mask_threshold) {
+ keep_face = false;
+ break;
+ }
}
- BM_elem_flag_set(f, BM_ELEM_TAG, delete_face);
+ BM_elem_flag_set(f, BM_ELEM_TAG, !keep_face);
}
BM_mesh_delete_hflag_context(bm, BM_ELEM_TAG, DEL_FACES);
@@ -173,7 +178,6 @@ static int paint_mask_extract_exec(bContext *C, wmOperator *op)
}
BM_mesh_elem_hflag_disable_all(bm, BM_VERT | BM_EDGE | BM_FACE, BM_ELEM_SELECT, false);
- BKE_editmesh_free_derivedmesh(em);
BKE_mesh_free(new_mesh);
new_mesh = BKE_mesh_from_bmesh_nomain(bm,
@@ -182,7 +186,8 @@ static int paint_mask_extract_exec(bContext *C, wmOperator *op)
}),
mesh);
- BM_mesh_free(bm);
+ BKE_editmesh_free(em);
+ MEM_freeN(em);
if (new_mesh->totvert == 0) {
BKE_mesh_free(new_mesh);
@@ -196,8 +201,6 @@ static int paint_mask_extract_exec(bContext *C, wmOperator *op)
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_free(new_mesh);
-
if (RNA_boolean_get(op->ptr, "apply_shrinkwrap")) {
BKE_shrinkwrap_mesh_nearest_surface_deform(C, new_ob, ob);
}
@@ -212,6 +215,8 @@ static int paint_mask_extract_exec(bContext *C, wmOperator *op)
}
}
+ BKE_mesh_calc_normals(new_ob->data);
+
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);
DEG_relations_tag_update(bmain);
diff --git a/source/blender/editors/mesh/editmesh_tools.c b/source/blender/editors/mesh/editmesh_tools.c
index 4636d1ee71e..cf3170b5446 100644
--- a/source/blender/editors/mesh/editmesh_tools.c
+++ b/source/blender/editors/mesh/editmesh_tools.c
@@ -2044,11 +2044,7 @@ static int edbm_edge_rotate_selected_exec(bContext *C, wmOperator *op)
}
if (tot_failed_all != 0) {
- BKE_reportf(op->reports,
- RPT_WARNING,
- tot_failed_all == 1 ? "Unable to rotate %d edge" :
- "Unable to rotate %d edges",
- tot_failed_all);
+ BKE_reportf(op->reports, RPT_WARNING, "Unable to rotate %d edge(s)", tot_failed_all);
}
return OPERATOR_FINISHED;
@@ -3165,11 +3161,7 @@ static int edbm_remove_doubles_exec(bContext *C, wmOperator *op)
}
MEM_freeN(objects);
- BKE_reportf(op->reports,
- RPT_INFO,
- count_multi == 1 ? "Removed %d vertex" :
- "Removed %d vertices",
- count_multi);
+ BKE_reportf(op->reports, RPT_INFO, "Removed %d vertice(s)", count_multi);
return OPERATOR_FINISHED;
}
diff --git a/source/blender/editors/mesh/mesh_data.c b/source/blender/editors/mesh/mesh_data.c
index 569994bead1..a0d424e083c 100644
--- a/source/blender/editors/mesh/mesh_data.c
+++ b/source/blender/editors/mesh/mesh_data.c
@@ -880,14 +880,14 @@ void MESH_OT_customdata_custom_splitnormals_clear(wmOperatorType *ot)
void ED_mesh_update(Mesh *mesh, bContext *C, bool calc_edges, bool calc_edges_loose)
{
- if (calc_edges_loose && mesh->totedge) {
- BKE_mesh_calc_edges_loose(mesh);
- }
-
if (calc_edges || ((mesh->totpoly || mesh->totface) && mesh->totedge == 0)) {
BKE_mesh_calc_edges(mesh, calc_edges, true);
}
+ if (calc_edges_loose && mesh->totedge) {
+ BKE_mesh_calc_edges_loose(mesh);
+ }
+
/* Default state is not to have tessface's so make sure this is the case. */
BKE_mesh_tessface_clear(mesh);
diff --git a/source/blender/editors/object/object_add.c b/source/blender/editors/object/object_add.c
index d6816ddbe73..bdb23c5ce6f 100644
--- a/source/blender/editors/object/object_add.c
+++ b/source/blender/editors/object/object_add.c
@@ -1030,7 +1030,7 @@ static int empty_drop_named_image_invoke(bContext *C, wmOperator *op, const wmEv
return OPERATOR_CANCELLED;
}
/* handled below */
- id_us_min((ID *)ima);
+ id_us_min(&ima->id);
Object *ob = NULL;
Object *ob_cursor = ED_view3d_give_object_under_cursor(C, event->mval);
@@ -1581,11 +1581,7 @@ static int object_delete_exec(bContext *C, wmOperator *op)
}
CTX_DATA_END;
- BKE_reportf(op->reports,
- RPT_INFO,
- changed_count == 1 ? "Deleted %u object" :
- "Deleted %u objects",
- changed_count);
+ BKE_reportf(op->reports, RPT_INFO, "Deleted %u object(s)", changed_count);
if (changed_count == 0) {
return OPERATOR_CANCELLED;
@@ -2149,6 +2145,7 @@ static int convert_exec(bContext *C, wmOperator *op)
const short target = RNA_enum_get(op->ptr, "target");
bool keep_original = RNA_boolean_get(op->ptr, "keep_original");
int a, mballConverted = 0;
+ bool gpencilConverted = false;
/* don't forget multiple users! */
@@ -2389,20 +2386,20 @@ static int convert_exec(bContext *C, wmOperator *op)
}
else if (target == OB_GPENCIL) {
if (ob->type != OB_CURVE) {
+ ob->flag &= ~OB_DONE;
BKE_report(
op->reports, RPT_ERROR, "Convert Surfaces to Grease Pencil is not supported.");
}
else {
- /* Create a new grease pencil object only if it was not created before.
- * All curves selected are converted as strokes of the same grease pencil object.
+ /* Create a new grease pencil object and copy transformations.
* Nurbs Surface are not supported.
*/
- if (gpencil_ob == NULL) {
- const float *cur = scene->cursor.location;
- ushort local_view_bits = (v3d && v3d->localvd) ? v3d->local_view_uuid : 0;
- gpencil_ob = ED_gpencil_add_object(C, scene, cur, local_view_bits);
- }
+ ushort local_view_bits = (v3d && v3d->localvd) ? v3d->local_view_uuid : 0;
+ gpencil_ob = ED_gpencil_add_object(C, scene, ob->loc, local_view_bits);
+ copy_v3_v3(gpencil_ob->rot, ob->rot);
+ copy_v3_v3(gpencil_ob->scale, ob->scale);
BKE_gpencil_convert_curve(bmain, scene, gpencil_ob, ob, false, false, true);
+ gpencilConverted = true;
}
}
}
@@ -2502,6 +2499,17 @@ static int convert_exec(bContext *C, wmOperator *op)
}
FOREACH_SCENE_OBJECT_END;
}
+ /* Remove curves converted to Grease Pencil object. */
+ if (gpencilConverted) {
+ FOREACH_SCENE_OBJECT_BEGIN (scene, ob_curve) {
+ if (ob_curve->type == OB_CURVE) {
+ if (ob_curve->flag & OB_DONE) {
+ ED_object_base_free_and_unlink(bmain, scene, ob_curve);
+ }
+ }
+ }
+ FOREACH_SCENE_OBJECT_END;
+ }
}
// XXX ED_object_editmode_enter(C, 0);
@@ -2580,7 +2588,7 @@ static Base *object_add_duplicate_internal(
DEG_id_tag_update(&obn->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
base = BKE_view_layer_base_find(view_layer, ob);
- if ((base != NULL) && (base->flag & BASE_VISIBLE)) {
+ if ((base != NULL) && (base->flag & BASE_VISIBLE_DEPSGRAPH)) {
BKE_collection_object_add_from(bmain, scene, ob, obn);
}
else {
diff --git a/source/blender/editors/object/object_bake_api.c b/source/blender/editors/object/object_bake_api.c
index d9baec7c3ca..9e9cfe1beed 100644
--- a/source/blender/editors/object/object_bake_api.c
+++ b/source/blender/editors/object/object_bake_api.c
@@ -879,7 +879,7 @@ static int bake(Render *re,
else {
ob_cage_eval = DEG_get_evaluated_object(depsgraph, ob_cage);
ob_cage_eval->restrictflag |= OB_RESTRICT_RENDER;
- ob_cage_eval->base_flag &= ~(BASE_VISIBLE | BASE_ENABLED_RENDER);
+ ob_cage_eval->base_flag &= ~(BASE_VISIBLE_DEPSGRAPH | BASE_ENABLED_RENDER);
}
}
}
@@ -976,7 +976,7 @@ static int bake(Render *re,
highpoly[i].ob = ob_iter;
highpoly[i].ob_eval = DEG_get_evaluated_object(depsgraph, ob_iter);
highpoly[i].ob_eval->restrictflag &= ~OB_RESTRICT_RENDER;
- highpoly[i].ob_eval->base_flag |= (BASE_VISIBLE | BASE_ENABLED_RENDER);
+ highpoly[i].ob_eval->base_flag |= (BASE_VISIBLE_DEPSGRAPH | BASE_ENABLED_RENDER);
highpoly[i].me = BKE_mesh_new_from_object(NULL, highpoly[i].ob_eval, false);
/* lowpoly to highpoly transformation matrix */
@@ -992,10 +992,10 @@ static int bake(Render *re,
if (ob_cage != NULL) {
ob_cage_eval->restrictflag |= OB_RESTRICT_RENDER;
- ob_cage_eval->base_flag &= ~(BASE_VISIBLE | BASE_ENABLED_RENDER);
+ ob_cage_eval->base_flag &= ~(BASE_VISIBLE_DEPSGRAPH | BASE_ENABLED_RENDER);
}
ob_low_eval->restrictflag |= OB_RESTRICT_RENDER;
- ob_low_eval->base_flag &= ~(BASE_VISIBLE | BASE_ENABLED_RENDER);
+ ob_low_eval->base_flag &= ~(BASE_VISIBLE_DEPSGRAPH | BASE_ENABLED_RENDER);
/* populate the pixel arrays with the corresponding face data for each high poly object */
if (!RE_bake_pixels_populate_from_objects(me_low,
diff --git a/source/blender/editors/object/object_edit.c b/source/blender/editors/object/object_edit.c
index 4759a3cb0db..70d024c7902 100644
--- a/source/blender/editors/object/object_edit.c
+++ b/source/blender/editors/object/object_edit.c
@@ -218,7 +218,7 @@ static int object_hide_view_set_exec(bContext *C, wmOperator *op)
/* Hide selected or unselected objects. */
for (Base *base = view_layer->object_bases.first; base; base = base->next) {
- if (!(base->flag & BASE_VISIBLE)) {
+ if (!(base->flag & BASE_VISIBLE_DEPSGRAPH)) {
continue;
}
@@ -292,7 +292,7 @@ static int object_hide_collection_exec(bContext *C, wmOperator *op)
DEG_id_tag_update(&scene->id, ID_RECALC_BASE_FLAGS);
if (v3d->flag & V3D_LOCAL_COLLECTIONS) {
- if ((lc->runtime_flag & LAYER_COLLECTION_VISIBLE) == 0) {
+ if (lc->runtime_flag & LAYER_COLLECTION_RESTRICT_VIEWPORT) {
return OPERATOR_CANCELLED;
}
if (toggle) {
@@ -300,11 +300,11 @@ static int object_hide_collection_exec(bContext *C, wmOperator *op)
BKE_layer_collection_local_sync(view_layer, v3d);
}
else {
- BKE_layer_collection_local_isolate(view_layer, v3d, lc, extend);
+ BKE_layer_collection_isolate_local(view_layer, v3d, lc, extend);
}
}
else {
- BKE_layer_collection_isolate(scene, view_layer, lc, extend);
+ BKE_layer_collection_isolate_global(scene, view_layer, lc, extend);
}
WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene);
@@ -1547,7 +1547,7 @@ static int move_to_collection_exec(bContext *C, wmOperator *op)
}
int collection_index = RNA_property_int_get(op->ptr, prop);
- collection = BKE_collection_from_index(CTX_data_scene(C), collection_index);
+ collection = BKE_collection_from_index(scene, collection_index);
if (collection == NULL) {
BKE_report(op->reports, RPT_ERROR, "Unexpected error, collection not found");
return OPERATOR_CANCELLED;
diff --git a/source/blender/editors/object/object_relations.c b/source/blender/editors/object/object_relations.c
index d56791e5da0..c030c551374 100644
--- a/source/blender/editors/object/object_relations.c
+++ b/source/blender/editors/object/object_relations.c
@@ -2051,7 +2051,7 @@ void ED_object_single_users(Main *bmain,
single_object_action_users(bmain, scene, NULL, NULL, 0);
single_mat_users_expand(bmain);
/* Duplicating obdata and other IDs may require another update of the collections and objects
- * pointers, especially reguarding drivers and custom props, see T66641.
+ * pointers, especially regarding drivers and custom props, see T66641.
* Note that this whole scene duplication code and 'make single user' functions have te be
* rewritten at some point to make use of proper modern ID management code,
* but that is no small task.
diff --git a/source/blender/editors/object/object_remesh.c b/source/blender/editors/object/object_remesh.c
index 2c05ae14f2e..35762c5861e 100644
--- a/source/blender/editors/object/object_remesh.c
+++ b/source/blender/editors/object/object_remesh.c
@@ -92,6 +92,12 @@ static bool object_remesh_poll(bContext *C)
return false;
}
+ if (modifiers_usesMultires(ob)) {
+ CTX_wm_operator_poll_msg_set(
+ C, "The remesher cannot run with a Multires modifier in the modifier stack.");
+ return false;
+ }
+
return ED_operator_object_active_editable_mesh(C);
}
@@ -111,8 +117,13 @@ static int voxel_remesh_exec(bContext *C, wmOperator *op)
ED_sculpt_undo_geometry_begin(ob);
}
+ float isovalue = 0.0f;
+ if (mesh->flag & ME_REMESH_REPROJECT_VOLUME) {
+ isovalue = mesh->remesh_voxel_size * 0.3f;
+ }
+
new_mesh = BKE_mesh_remesh_voxel_to_mesh_nomain(
- mesh, mesh->remesh_voxel_size, mesh->remesh_voxel_adaptivity);
+ mesh, mesh->remesh_voxel_size, mesh->remesh_voxel_adaptivity, isovalue);
if (!new_mesh) {
return OPERATOR_CANCELLED;
@@ -204,6 +215,57 @@ typedef struct QuadriFlowJob {
int success;
} QuadriFlowJob;
+static bool mesh_is_manifold_consistent(Mesh *mesh)
+{
+ /* In this check we count boundary edges as manifold. Additionally, we also
+ * check that the direction of the faces are consistent and doesn't suddenly
+ * flip
+ */
+
+ 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(unsigned int), "remesh_consistent_check");
+
+ for (unsigned int i = 0; i < mesh->totedge; i++) {
+ edge_vert[i] = -1;
+ }
+
+ for (unsigned int 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) {
+ is_manifold_consistent = false;
+ break;
+ }
+
+ if (edge_vert[loop->e] == -1) {
+ 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;
+ }
+ }
+
+ if (is_manifold_consistent) {
+ /* check for wire edges */
+ for (unsigned int i = 0; i < mesh->totedge; i++) {
+ if (edge_faces[i] == 0) {
+ is_manifold_consistent = false;
+ break;
+ }
+ }
+ }
+
+ MEM_freeN(edge_faces);
+ MEM_freeN(edge_vert);
+
+ return is_manifold_consistent;
+}
+
static void quadriflow_free_job(void *customdata)
{
QuadriFlowJob *qj = customdata;
@@ -320,6 +382,12 @@ static void quadriflow_start_job(void *customdata, short *stop, short *do_update
Mesh *new_mesh;
Mesh *bisect_mesh;
+ /* Check if the mesh is manifold. Quadriflow requires manifold meshes */
+ if (!mesh_is_manifold_consistent(mesh)) {
+ qj->success = -2;
+ return;
+ }
+
/* Run Quadriflow bisect operations on a copy of the mesh to keep the code readable without
* freeing the original ID */
bisect_mesh = BKE_mesh_copy(qj->bmain, mesh);
@@ -390,17 +458,22 @@ static void quadriflow_end_job(void *customdata)
WM_set_locked_interface(G_MAIN->wm.first, false);
- if (qj->success > 0) {
- DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
- WM_reportf(RPT_INFO, "QuadriFlow: Completed remeshing!");
- }
- else {
- if (qj->success == 0) {
+ switch (qj->success) {
+ case 1:
+ DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
+ WM_reportf(RPT_INFO, "QuadriFlow: Completed remeshing!");
+ break;
+ case 0:
WM_reportf(RPT_ERROR, "QuadriFlow: remeshing failed!");
- }
- else {
+ break;
+ case -1:
WM_report(RPT_WARNING, "QuadriFlow: remeshing canceled!");
- }
+ break;
+ case -2:
+ WM_report(RPT_WARNING,
+ "QuadriFlow: The mesh needs to be manifold and have face normals that point in a "
+ "consistent direction.");
+ break;
}
}
@@ -602,7 +675,7 @@ void OBJECT_OT_quadriflow_remesh(wmOperatorType *ot)
RNA_def_enum(ot->srna,
"mode",
mode_type_items,
- 0,
+ QUADRIFLOW_REMESH_FACES,
"Mode",
"How to specify the amount of detail for the new mesh");
@@ -628,7 +701,7 @@ void OBJECT_OT_quadriflow_remesh(wmOperatorType *ot)
prop = RNA_def_int(ot->srna,
"target_faces",
- 1,
+ 4000,
1,
INT_MAX,
"Number of Faces",
diff --git a/source/blender/editors/object/object_select.c b/source/blender/editors/object/object_select.c
index 28242b986f1..40fa11994f4 100644
--- a/source/blender/editors/object/object_select.c
+++ b/source/blender/editors/object/object_select.c
@@ -214,7 +214,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) {
+ if (base->flag & BASE_VISIBLE_DEPSGRAPH) {
if (base->flag & BASE_SELECTABLE) {
return 3;
}
@@ -288,7 +288,7 @@ bool ED_object_jump_to_object(bContext *C, Object *ob, const bool UNUSED(reveal_
if (!(base->flag & BASE_SELECTED)) {
ED_object_base_deselect_all(view_layer, v3d, SEL_DESELECT);
- if (base->flag & BASE_VISIBLE) {
+ if (BASE_VISIBLE(v3d, base)) {
ED_object_base_select(base, BA_SELECT);
}
diff --git a/source/blender/editors/physics/particle_edit.c b/source/blender/editors/physics/particle_edit.c
index 2ea0e9dc018..3978f7ba3b5 100644
--- a/source/blender/editors/physics/particle_edit.c
+++ b/source/blender/editors/physics/particle_edit.c
@@ -3076,11 +3076,7 @@ static int remove_doubles_exec(bContext *C, wmOperator *op)
return OPERATOR_CANCELLED;
}
- BKE_reportf(op->reports,
- RPT_INFO,
- totremoved == 1 ? "Removed %d double particle" :
- "Removed %d double particles",
- totremoved);
+ BKE_reportf(op->reports, RPT_INFO, "Removed %d double particle(s)", totremoved);
DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
WM_event_add_notifier(C, NC_OBJECT | ND_PARTICLE | NA_EDITED, ob);
diff --git a/source/blender/editors/physics/rigidbody_constraint.c b/source/blender/editors/physics/rigidbody_constraint.c
index 4b1d51ee6c2..303a0714388 100644
--- a/source/blender/editors/physics/rigidbody_constraint.c
+++ b/source/blender/editors/physics/rigidbody_constraint.c
@@ -115,13 +115,7 @@ bool ED_rigidbody_constraint_add(
void ED_rigidbody_constraint_remove(Main *bmain, Scene *scene, Object *ob)
{
- RigidBodyWorld *rbw = BKE_rigidbody_get_world(scene);
-
- BKE_rigidbody_remove_constraint(scene, ob);
- if (rbw) {
- BKE_collection_object_remove(bmain, rbw->constraints, ob, false);
- DEG_id_tag_update(&rbw->constraints->id, ID_RECALC_COPY_ON_WRITE);
- }
+ BKE_rigidbody_remove_constraint(bmain, scene, ob, false);
DEG_relations_tag_update(bmain);
DEG_id_tag_update(&ob->id, ID_RECALC_TRANSFORM);
diff --git a/source/blender/editors/physics/rigidbody_object.c b/source/blender/editors/physics/rigidbody_object.c
index bc8a1799fa0..43ca421b9d0 100644
--- a/source/blender/editors/physics/rigidbody_object.c
+++ b/source/blender/editors/physics/rigidbody_object.c
@@ -105,7 +105,7 @@ bool ED_rigidbody_object_add(Main *bmain, Scene *scene, Object *ob, int type, Re
void ED_rigidbody_object_remove(Main *bmain, Scene *scene, Object *ob)
{
- BKE_rigidbody_remove_object(bmain, scene, ob);
+ BKE_rigidbody_remove_object(bmain, scene, ob, false);
DEG_relations_tag_update(bmain);
DEG_id_tag_update(&ob->id, ID_RECALC_TRANSFORM);
diff --git a/source/blender/editors/render/render_internal.c b/source/blender/editors/render/render_internal.c
index 053ca3d8f9f..7106af25a82 100644
--- a/source/blender/editors/render/render_internal.c
+++ b/source/blender/editors/render/render_internal.c
@@ -859,7 +859,7 @@ static void screen_render_cancel(bContext *C, wmOperator *op)
static void clean_viewport_memory_base(Base *base)
{
- if ((base->flag & BASE_VISIBLE) == 0) {
+ if ((base->flag & BASE_VISIBLE_DEPSGRAPH) == 0) {
return;
}
diff --git a/source/blender/editors/render/render_preview.c b/source/blender/editors/render/render_preview.c
index 3e001ef25b5..6dc3a1ec1ac 100644
--- a/source/blender/editors/render/render_preview.c
+++ b/source/blender/editors/render/render_preview.c
@@ -115,7 +115,7 @@ ImBuf *get_brush_icon(Brush *brush)
// first use the path directly to try and load the file
BLI_strncpy(path, brush->icon_filepath, sizeof(brush->icon_filepath));
- BLI_path_abs(path, BKE_main_blendfile_path_from_global());
+ BLI_path_abs(path, ID_BLEND_PATH_FROM_GLOBAL(&brush->id));
/* use default colorspaces for brushes */
brush->icon_imbuf = IMB_loadiffname(path, flags, NULL);
@@ -474,7 +474,7 @@ static Scene *preview_prepare_scene(
}
}
else if (base->object->type == OB_LAMP) {
- base->flag |= BASE_VISIBLE;
+ base->flag |= BASE_VISIBLE_DEPSGRAPH;
}
}
}
diff --git a/source/blender/editors/render/render_shading.c b/source/blender/editors/render/render_shading.c
index 9f13431f25a..7970d491877 100644
--- a/source/blender/editors/render/render_shading.c
+++ b/source/blender/editors/render/render_shading.c
@@ -103,15 +103,17 @@ static Object **object_array_for_shading(bContext *C, uint *r_objects_len)
ScrArea *sa = CTX_wm_area(C);
SpaceProperties *sbuts = NULL;
View3D *v3d = NULL;
- if (sa->spacetype == SPACE_PROPERTIES) {
- sbuts = sa->spacedata.first;
- }
- else if (sa->spacetype == SPACE_VIEW3D) {
- v3d = sa->spacedata.first;
+ if (sa != NULL) {
+ if (sa->spacetype == SPACE_PROPERTIES) {
+ sbuts = sa->spacedata.first;
+ }
+ else if (sa->spacetype == SPACE_VIEW3D) {
+ v3d = sa->spacedata.first;
+ }
}
Object **objects;
- if (sbuts && sbuts->pinid && GS(sbuts->pinid->name) == ID_OB) {
+ if (sbuts != NULL && sbuts->pinid && GS(sbuts->pinid->name) == ID_OB) {
objects = MEM_mallocN(sizeof(*objects), __func__);
objects[0] = (Object *)sbuts->pinid;
*r_objects_len = 1;
diff --git a/source/blender/editors/render/render_view.c b/source/blender/editors/render/render_view.c
index 6873495e962..a54701f8725 100644
--- a/source/blender/editors/render/render_view.c
+++ b/source/blender/editors/render/render_view.c
@@ -156,8 +156,8 @@ ScrArea *render_view_open(bContext *C, int mx, int my, ReportList *reports)
}
/* changes context! */
- if (WM_window_open_temp(C, IFACE_("Blender Render"), mx, my, sizex, sizey, SPACE_IMAGE) ==
- NULL) {
+ if (WM_window_open_temp(
+ C, IFACE_("Blender Render"), mx, my, sizex, sizey, SPACE_IMAGE, false) == NULL) {
BKE_report(reports, RPT_ERROR, "Failed to open window!");
return NULL;
}
diff --git a/source/blender/editors/screen/area.c b/source/blender/editors/screen/area.c
index c068fbdf7cb..9957fe0515c 100644
--- a/source/blender/editors/screen/area.c
+++ b/source/blender/editors/screen/area.c
@@ -2869,7 +2869,7 @@ void ED_region_info_draw(ARegion *ar,
float fill_color[4],
const bool full_redraw)
{
- ED_region_info_draw_multiline(ar, (const char * [2]){text, NULL}, fill_color, full_redraw);
+ ED_region_info_draw_multiline(ar, (const char *[2]){text, NULL}, fill_color, full_redraw);
}
#define MAX_METADATA_STR 1024
diff --git a/source/blender/editors/screen/screen_draw.c b/source/blender/editors/screen/screen_draw.c
index 316604156de..a6b8bba73e3 100644
--- a/source/blender/editors/screen/screen_draw.c
+++ b/source/blender/editors/screen/screen_draw.c
@@ -21,7 +21,7 @@
#include "ED_screen.h"
#include "GPU_batch_presets.h"
-#include "GPU_extensions.h"
+#include "GPU_platform.h"
#include "GPU_framebuffer.h"
#include "GPU_immediate.h"
#include "GPU_matrix.h"
diff --git a/source/blender/editors/screen/screen_edit.c b/source/blender/editors/screen/screen_edit.c
index c8008fe3cc7..bbdddfadc30 100644
--- a/source/blender/editors/screen/screen_edit.c
+++ b/source/blender/editors/screen/screen_edit.c
@@ -1375,13 +1375,14 @@ ScrArea *ED_screen_temp_space_open(bContext *C,
int sizex,
int sizey,
eSpace_Type space_type,
- int display_type)
+ int display_type,
+ bool dialog)
{
ScrArea *sa = NULL;
switch (display_type) {
case USER_TEMP_SPACE_DISPLAY_WINDOW:
- if (WM_window_open_temp(C, title, x, y, sizex, sizey, (int)space_type)) {
+ if (WM_window_open_temp(C, title, x, y, sizex, sizey, (int)space_type, dialog)) {
sa = CTX_wm_area(C);
}
break;
diff --git a/source/blender/editors/screen/screen_ops.c b/source/blender/editors/screen/screen_ops.c
index 0b374617cce..cc1f53eabde 100644
--- a/source/blender/editors/screen/screen_ops.c
+++ b/source/blender/editors/screen/screen_ops.c
@@ -3946,7 +3946,7 @@ static int region_toggle_exec(bContext *C, wmOperator *op)
region = CTX_wm_region(C);
}
- if (region) {
+ if (region && (region->alignment != RGN_ALIGN_NONE)) {
ED_region_toggle_hidden(C, region);
}
ED_region_tag_redraw(region);
@@ -4828,9 +4828,14 @@ static int userpref_show_invoke(bContext *C, wmOperator *op, const wmEvent *even
int sizey = 520 * UI_DPI_FAC;
/* changes context! */
- if (WM_window_open_temp(
- C, IFACE_("Blender Preferences"), event->x, event->y, sizex, sizey, SPACE_USERPREF) !=
- NULL) {
+ if (WM_window_open_temp(C,
+ IFACE_("Blender Preferences"),
+ event->x,
+ event->y,
+ sizex,
+ sizey,
+ SPACE_USERPREF,
+ false) != NULL) {
/* The header only contains the editor switcher and looks empty.
* So hiding in the temp window makes sense. */
ScrArea *area = CTX_wm_area(C);
@@ -4879,9 +4884,14 @@ static int drivers_editor_show_invoke(bContext *C, wmOperator *op, const wmEvent
but = UI_context_active_but_prop_get(C, &ptr, &prop, &index);
/* changes context! */
- if (WM_window_open_temp(
- C, IFACE_("Blender Drivers Editor"), event->x, event->y, sizex, sizey, SPACE_GRAPH) !=
- NULL) {
+ if (WM_window_open_temp(C,
+ IFACE_("Blender Drivers Editor"),
+ event->x,
+ event->y,
+ sizex,
+ sizey,
+ SPACE_GRAPH,
+ false) != NULL) {
ED_drivers_editor_init(C, CTX_wm_area(C));
/* activate driver F-Curve for the property under the cursor */
@@ -4939,9 +4949,14 @@ static int info_log_show_invoke(bContext *C, wmOperator *op, const wmEvent *even
int shift_y = 480;
/* changes context! */
- if (WM_window_open_temp(
- C, IFACE_("Blender Info Log"), event->x, event->y + shift_y, sizex, sizey, SPACE_INFO) !=
- NULL) {
+ if (WM_window_open_temp(C,
+ IFACE_("Blender Info Log"),
+ event->x,
+ event->y + shift_y,
+ sizex,
+ sizey,
+ SPACE_INFO,
+ false) != NULL) {
return OPERATOR_FINISHED;
}
else {
diff --git a/source/blender/editors/sculpt_paint/paint_cursor.c b/source/blender/editors/sculpt_paint/paint_cursor.c
index 774d4ef09b1..c59ab6279cd 100644
--- a/source/blender/editors/sculpt_paint/paint_cursor.c
+++ b/source/blender/editors/sculpt_paint/paint_cursor.c
@@ -410,7 +410,7 @@ static void load_tex_cursor_task_cb(void *__restrict userdata,
if (len <= 1.0f) {
float avg = BKE_brush_curve_strength_clamped(br, len, 1.0f); /* Falloff curve */
- buffer[index] = 255 - (GLubyte)(255 * avg);
+ buffer[index] = (GLubyte)(255 * avg);
}
else {
buffer[index] = 0;
@@ -1359,13 +1359,14 @@ static void paint_draw_cursor(bContext *C, int x, int y, void *UNUSED(unused))
if ((mode == PAINT_MODE_SCULPT) && ss && !ups->stroke_active) {
prev_active_vertex_index = ss->active_vertex_index;
is_cursor_over_mesh = sculpt_cursor_geometry_info_update(
- C, &gi, mouse, !(brush->falloff_shape & BRUSH_AIRBRUSH));
+ C, &gi, mouse, (brush->falloff_shape == PAINT_FALLOFF_SHAPE_SPHERE));
}
/* Use special paint crosshair cursor in all paint modes*/
wmWindow *win = CTX_wm_window(C);
WM_cursor_set(win, WM_CURSOR_PAINT);
- if ((mode == PAINT_MODE_SCULPT) && ss && !(brush->falloff_shape & BRUSH_AIRBRUSH)) {
+ if ((mode == PAINT_MODE_SCULPT) && ss &&
+ (brush->falloff_shape == PAINT_FALLOFF_SHAPE_SPHERE)) {
Sculpt *sd = CTX_data_tool_settings(C)->sculpt;
if (!ups->stroke_active) {
@@ -1393,7 +1394,7 @@ static void paint_draw_cursor(bContext *C, int x, int y, void *UNUSED(unused))
}
/* Draw pose brush origin */
- if (brush->sculpt_tool == SCULPT_TOOL_POSE && !is_multires) {
+ if (brush->sculpt_tool == SCULPT_TOOL_POSE) {
immUniformColor4f(1.0f, 1.0f, 1.0f, 0.8f);
if (update_previews) {
BKE_sculpt_update_object_for_edit(depsgraph, vc.obact, true, false);
@@ -1439,14 +1440,14 @@ static void paint_draw_cursor(bContext *C, int x, int y, void *UNUSED(unused))
GPU_matrix_mul(vc.obact->obmat);
if (brush->sculpt_tool == SCULPT_TOOL_GRAB && (brush->flag & BRUSH_GRAB_ACTIVE_VERTEX) &&
!is_multires) {
- if (BKE_pbvh_type(ss->pbvh) == PBVH_FACES && ss->modifiers_active) {
+ if (BKE_pbvh_type(ss->pbvh) == PBVH_FACES && ss->deform_modifiers_active) {
sculpt_geometry_preview_lines_update(C, ss, rds);
sculpt_geometry_preview_lines_draw(pos, ss);
}
}
/* Draw pose brush line preview */
- if (brush->sculpt_tool == SCULPT_TOOL_POSE && !is_multires) {
+ if (brush->sculpt_tool == SCULPT_TOOL_POSE) {
immUniformColor4f(1.0f, 1.0f, 1.0f, 0.8f);
GPU_line_width(2.0f);
immBegin(GPU_PRIM_LINES, 2);
@@ -1492,7 +1493,7 @@ static void paint_draw_cursor(bContext *C, int x, int y, void *UNUSED(unused))
/* Draw cached dynamic mesh preview lines */
if (brush->sculpt_tool == SCULPT_TOOL_GRAB && (brush->flag & BRUSH_GRAB_ACTIVE_VERTEX) &&
!is_multires) {
- if (BKE_pbvh_type(ss->pbvh) == PBVH_FACES && ss->modifiers_active) {
+ if (BKE_pbvh_type(ss->pbvh) == PBVH_FACES && ss->deform_modifiers_active) {
GPU_matrix_push_projection();
ED_view3d_draw_setup_view(CTX_wm_window(C),
CTX_data_depsgraph_pointer(C),
diff --git a/source/blender/editors/sculpt_paint/paint_image.c b/source/blender/editors/sculpt_paint/paint_image.c
index 24c2dfb6c6b..b4388f6c324 100644
--- a/source/blender/editors/sculpt_paint/paint_image.c
+++ b/source/blender/editors/sculpt_paint/paint_image.c
@@ -540,7 +540,7 @@ static void paint_stroke_update_step(bContext *C, struct PaintStroke *stroke, Po
RNA_float_get_array(itemptr, "mouse", mouse);
pressure = RNA_float_get(itemptr, "pressure");
eraser = RNA_boolean_get(itemptr, "pen_flip");
- size = max_ff(1.0f, RNA_float_get(itemptr, "size"));
+ size = RNA_float_get(itemptr, "size");
/* stroking with fill tool only acts on stroke end */
if (brush->imagepaint_tool == PAINT_TOOL_FILL) {
diff --git a/source/blender/editors/sculpt_paint/paint_image_2d.c b/source/blender/editors/sculpt_paint/paint_image_2d.c
index 4f1ae10aa62..9c95a3cee4d 100644
--- a/source/blender/editors/sculpt_paint/paint_image_2d.c
+++ b/source/blender/editors/sculpt_paint/paint_image_2d.c
@@ -374,25 +374,65 @@ static void brush_painter_mask_imbuf_partial_update(BrushPainter *painter,
/* create a mask with the falloff strength */
static unsigned short *brush_painter_curve_mask_new(BrushPainter *painter,
int diameter,
- float radius)
+ float radius,
+ const float pos[2])
{
Brush *brush = painter->brush;
- int xoff = -radius;
- int yoff = -radius;
+ int offset = (int)floorf(diameter / 2.0f);
unsigned short *mask, *m;
- int x, y;
mask = MEM_mallocN(sizeof(unsigned short) * diameter * diameter, "brush_painter_mask");
m = mask;
- for (y = 0; y < diameter; y++) {
- for (x = 0; x < diameter; x++, m++) {
- float xy[2] = {x + xoff, y + yoff};
- float len = len_v2(xy);
+ int aa_samples = 1.0f / (radius * 0.20f);
+ aa_samples = clamp_i(aa_samples, 3, 16);
- *m = (unsigned short)(65535.0f * BKE_brush_curve_strength_clamped(brush, len, radius));
+ /* Temporal until we have the brush properties */
+ const float hardness = 1.0f;
+ const float rotation = 0.0f;
+
+ float aa_offset = 1.0f / (2.0f * (float)aa_samples);
+ float aa_step = 1.0f / (float)aa_samples;
+
+ float bpos[2];
+ bpos[0] = pos[0] - floorf(pos[0]) + offset + aa_offset;
+ bpos[1] = pos[1] - floorf(pos[1]) + offset + aa_offset;
+
+ const float co = cosf(DEG2RADF(rotation));
+ const float si = sinf(DEG2RADF(rotation));
+
+ float norm_factor = 65535.0f / (float)(aa_samples * aa_samples);
+
+ for (int y = 0; y < diameter; y++) {
+ for (int x = 0; x < diameter; x++, m++) {
+ float total_samples = 0;
+ for (int i = 0; i < aa_samples; i++) {
+ for (int j = 0; j < aa_samples; j++) {
+ float pixel_xy[2] = {x + (aa_step * i), y + (aa_step * j)};
+ float xy_rot[2];
+ sub_v2_v2(pixel_xy, bpos);
+
+ xy_rot[0] = co * pixel_xy[0] - si * pixel_xy[1];
+ xy_rot[1] = si * pixel_xy[0] + co * pixel_xy[1];
+
+ float len = len_v2(xy_rot);
+ float p = len / radius;
+ if (hardness < 1.0f) {
+ p = (p - hardness) / (1 - hardness);
+ p = 1.0f - p;
+ CLAMP(p, 0, 1);
+ }
+ else {
+ p = 1.0;
+ }
+ float hardness_factor = 3.0f * p * p - 2.0f * p * p * p;
+ float curve = BKE_brush_curve_strength_clamped(brush, len, radius);
+ total_samples += curve * hardness_factor;
+ }
+ }
+ *m = (unsigned short)(total_samples * norm_factor);
}
}
@@ -721,7 +761,8 @@ static void brush_painter_2d_refresh_cache(ImagePaintState *s,
UnifiedPaintSettings *ups = &scene->toolsettings->unified_paint_settings;
Brush *brush = painter->brush;
BrushPainterCache *cache = &painter->cache;
- const int diameter = 2 * size;
+ /* Adding 4 pixels of padding for brush antialiasing */
+ const int diameter = MAX2(1, size * 2) + 4;
bool do_random = false;
bool do_partial_update = false;
@@ -802,15 +843,13 @@ static void brush_painter_2d_refresh_cache(ImagePaintState *s,
}
/* curve mask can only change if the size changes */
- if (diameter != cache->lastdiameter) {
- if (cache->curve_mask) {
- MEM_freeN(cache->curve_mask);
- cache->curve_mask = NULL;
- }
-
- cache->curve_mask = brush_painter_curve_mask_new(painter, diameter, size);
+ if (cache->curve_mask) {
+ MEM_freeN(cache->curve_mask);
+ cache->curve_mask = NULL;
}
+ cache->curve_mask = brush_painter_curve_mask_new(painter, diameter, size, pos);
+
/* detect if we need to recreate image brush buffer */
if ((diameter != cache->lastdiameter) || (tex_rotation != cache->last_tex_rotation) ||
do_random || update_color) {
diff --git a/source/blender/editors/sculpt_paint/paint_intern.h b/source/blender/editors/sculpt_paint/paint_intern.h
index 69eed84fe2b..19380fb9022 100644
--- a/source/blender/editors/sculpt_paint/paint_intern.h
+++ b/source/blender/editors/sculpt_paint/paint_intern.h
@@ -29,7 +29,6 @@ struct Brush;
struct ColorManagedDisplay;
struct ColorSpace;
struct ImagePool;
-struct ListBase;
struct MTex;
struct Object;
struct Paint;
@@ -37,7 +36,6 @@ struct PaintStroke;
struct PointerRNA;
struct RegionView3D;
struct Scene;
-struct UndoStep;
struct VPaint;
struct ViewContext;
struct bContext;
diff --git a/source/blender/editors/sculpt_paint/paint_mask.c b/source/blender/editors/sculpt_paint/paint_mask.c
index a93e55685d2..d160fba4013 100644
--- a/source/blender/editors/sculpt_paint/paint_mask.c
+++ b/source/blender/editors/sculpt_paint/paint_mask.c
@@ -166,9 +166,9 @@ static int mask_flood_fill_exec(bContext *C, wmOperator *op)
.value = value,
};
- TaskParallelSettings settings;
+ PBVHParallelSettings settings;
BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP), totnode);
- BLI_task_parallel_range(0, totnode, &data, mask_flood_fill_task_cb, &settings);
+ BKE_pbvh_parallel_range(0, totnode, &data, mask_flood_fill_task_cb, &settings);
if (multires) {
multires_mark_as_modified(depsgraph, ob, MULTIRES_COORDS_MODIFIED);
@@ -343,9 +343,9 @@ bool ED_sculpt_mask_box_select(struct bContext *C, ViewContext *vc, const rcti *
.clip_planes_final = clip_planes_final,
};
- TaskParallelSettings settings;
+ PBVHParallelSettings settings;
BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP), totnode);
- BLI_task_parallel_range(0, totnode, &data, mask_box_select_task_cb, &settings);
+ BKE_pbvh_parallel_range(0, totnode, &data, mask_box_select_task_cb, &settings);
if (nodes) {
MEM_freeN(nodes);
@@ -532,9 +532,9 @@ static int paint_mask_gesture_lasso_exec(bContext *C, wmOperator *op)
data.task_data.mode = mode;
data.task_data.value = value;
- TaskParallelSettings settings;
+ PBVHParallelSettings settings;
BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP), totnode);
- BLI_task_parallel_range(0, totnode, &data, mask_gesture_lasso_task_cb, &settings);
+ BKE_pbvh_parallel_range(0, totnode, &data, mask_gesture_lasso_task_cb, &settings);
if (nodes) {
MEM_freeN(nodes);
diff --git a/source/blender/editors/sculpt_paint/paint_stroke.c b/source/blender/editors/sculpt_paint/paint_stroke.c
index d8be345cc84..36418045551 100644
--- a/source/blender/editors/sculpt_paint/paint_stroke.c
+++ b/source/blender/editors/sculpt_paint/paint_stroke.c
@@ -256,6 +256,7 @@ static bool paint_tool_require_inbetween_mouse_events(Brush *brush, ePaintMode m
SCULPT_TOOL_GRAB,
SCULPT_TOOL_ROTATE,
SCULPT_TOOL_THUMB,
+ SCULPT_TOOL_SNAKE_HOOK,
SCULPT_TOOL_ELASTIC_DEFORM,
SCULPT_TOOL_POSE)) {
return false;
@@ -668,7 +669,7 @@ static float paint_space_stroke_spacing(bContext *C,
return max_ff(0.001f, size_clamp * spacing / 50.f);
}
else {
- return max_ff(1.0, size_clamp * spacing / 50.0f);
+ return max_ff(stroke->zoom_2d, size_clamp * spacing / 50.0f);
}
}
@@ -909,16 +910,21 @@ PaintStroke *paint_stroke_new(bContext *C,
void paint_stroke_free(bContext *C, wmOperator *op)
{
RegionView3D *rv3d = CTX_wm_region_view3d(C);
+ if (rv3d) {
+ rv3d->rflag &= ~RV3D_PAINTING;
+ }
+
+ BKE_paint_set_overlay_override(0);
+
PaintStroke *stroke = op->customdata;
- UnifiedPaintSettings *ups = stroke->ups;
+ if (stroke == NULL) {
+ return;
+ }
+ UnifiedPaintSettings *ups = stroke->ups;
ups->draw_anchored = false;
ups->stroke_active = false;
- if (rv3d) {
- rv3d->rflag &= ~RV3D_PAINTING;
- }
-
if (stroke->timer) {
WM_event_remove_timer(CTX_wm_manager(C), CTX_wm_window(C), stroke->timer);
}
@@ -933,7 +939,6 @@ void paint_stroke_free(bContext *C, wmOperator *op)
BLI_freelistN(&stroke->line);
- BKE_paint_set_overlay_override(0);
MEM_SAFE_FREE(op->customdata);
}
diff --git a/source/blender/editors/sculpt_paint/paint_vertex.c b/source/blender/editors/sculpt_paint/paint_vertex.c
index 3554a6cc546..77c95c6acb3 100644
--- a/source/blender/editors/sculpt_paint/paint_vertex.c
+++ b/source/blender/editors/sculpt_paint/paint_vertex.c
@@ -2072,9 +2072,9 @@ static void calculate_average_weight(SculptThreadedTaskData *data,
struct WPaintAverageAccum *accum = MEM_mallocN(sizeof(*accum) * totnode, __func__);
data->custom_data = accum;
- TaskParallelSettings settings;
+ PBVHParallelSettings settings;
BKE_pbvh_parallel_range_settings(&settings, (data->sd->flags & SCULPT_USE_OPENMP), totnode);
- BLI_task_parallel_range(0, totnode, data, do_wpaint_brush_calc_average_weight_cb_ex, &settings);
+ BKE_pbvh_parallel_range(0, totnode, data, do_wpaint_brush_calc_average_weight_cb_ex, &settings);
uint accum_len = 0;
double accum_weight = 0.0;
@@ -2120,22 +2120,22 @@ static void wpaint_paint_leaves(bContext *C,
data.strength = BKE_brush_weight_get(scene, brush);
/* NOTE: current mirroring code cannot be run in parallel */
- TaskParallelSettings settings;
+ PBVHParallelSettings settings;
BKE_pbvh_parallel_range_settings(&settings, !(me->editflag & ME_EDIT_MIRROR_X), totnode);
switch ((eBrushWeightPaintTool)brush->weightpaint_tool) {
case WPAINT_TOOL_AVERAGE:
calculate_average_weight(&data, nodes, totnode);
- BLI_task_parallel_range(0, totnode, &data, do_wpaint_brush_draw_task_cb_ex, &settings);
+ BKE_pbvh_parallel_range(0, totnode, &data, do_wpaint_brush_draw_task_cb_ex, &settings);
break;
case WPAINT_TOOL_SMEAR:
- BLI_task_parallel_range(0, totnode, &data, do_wpaint_brush_smear_task_cb_ex, &settings);
+ BKE_pbvh_parallel_range(0, totnode, &data, do_wpaint_brush_smear_task_cb_ex, &settings);
break;
case WPAINT_TOOL_BLUR:
- BLI_task_parallel_range(0, totnode, &data, do_wpaint_brush_blur_task_cb_ex, &settings);
+ BKE_pbvh_parallel_range(0, totnode, &data, do_wpaint_brush_blur_task_cb_ex, &settings);
break;
case WPAINT_TOOL_DRAW:
- BLI_task_parallel_range(0, totnode, &data, do_wpaint_brush_draw_task_cb_ex, &settings);
+ BKE_pbvh_parallel_range(0, totnode, &data, do_wpaint_brush_draw_task_cb_ex, &settings);
break;
}
}
@@ -2587,11 +2587,6 @@ void PAINT_OT_vertex_paint_toggle(wmOperatorType *ot)
* - revise whether op->customdata should be added in object, in set_vpaint
*/
-typedef struct PolyFaceMap {
- struct PolyFaceMap *next, *prev;
- int facenr;
-} PolyFaceMap;
-
struct VPaintData {
ViewContext vc;
struct NormalAnglePrecalc normal_angle_precalc;
@@ -3131,9 +3126,9 @@ static void calculate_average_color(SculptThreadedTaskData *data,
struct VPaintAverageAccum *accum = MEM_mallocN(sizeof(*accum) * totnode, __func__);
data->custom_data = accum;
- TaskParallelSettings settings;
+ PBVHParallelSettings settings;
BKE_pbvh_parallel_range_settings(&settings, true, totnode);
- BLI_task_parallel_range(0, totnode, data, do_vpaint_brush_calc_average_color_cb_ex, &settings);
+ BKE_pbvh_parallel_range(0, totnode, data, do_vpaint_brush_calc_average_color_cb_ex, &settings);
uint accum_len = 0;
uint accum_value[3] = {0};
@@ -3177,21 +3172,21 @@ static void vpaint_paint_leaves(bContext *C,
.lcol = (uint *)me->mloopcol,
.me = me,
};
- TaskParallelSettings settings;
+ PBVHParallelSettings settings;
BKE_pbvh_parallel_range_settings(&settings, true, totnode);
switch ((eBrushVertexPaintTool)brush->vertexpaint_tool) {
case VPAINT_TOOL_AVERAGE:
calculate_average_color(&data, nodes, totnode);
- BLI_task_parallel_range(0, totnode, &data, do_vpaint_brush_draw_task_cb_ex, &settings);
+ BKE_pbvh_parallel_range(0, totnode, &data, do_vpaint_brush_draw_task_cb_ex, &settings);
break;
case VPAINT_TOOL_BLUR:
- BLI_task_parallel_range(0, totnode, &data, do_vpaint_brush_blur_task_cb_ex, &settings);
+ BKE_pbvh_parallel_range(0, totnode, &data, do_vpaint_brush_blur_task_cb_ex, &settings);
break;
case VPAINT_TOOL_SMEAR:
- BLI_task_parallel_range(0, totnode, &data, do_vpaint_brush_smear_task_cb_ex, &settings);
+ BKE_pbvh_parallel_range(0, totnode, &data, do_vpaint_brush_smear_task_cb_ex, &settings);
break;
case VPAINT_TOOL_DRAW:
- BLI_task_parallel_range(0, totnode, &data, do_vpaint_brush_draw_task_cb_ex, &settings);
+ BKE_pbvh_parallel_range(0, totnode, &data, do_vpaint_brush_draw_task_cb_ex, &settings);
break;
}
}
diff --git a/source/blender/editors/sculpt_paint/sculpt.c b/source/blender/editors/sculpt_paint/sculpt.c
index b9d621fc1fb..d2d424745da 100644
--- a/source/blender/editors/sculpt_paint/sculpt.c
+++ b/source/blender/editors/sculpt_paint/sculpt.c
@@ -64,6 +64,7 @@
#include "BKE_report.h"
#include "BKE_scene.h"
#include "BKE_screen.h"
+#include "BKE_subdiv_ccg.h"
#include "BKE_subsurf.h"
#include "DEG_depsgraph.h"
@@ -185,7 +186,6 @@ static float sculpt_vertex_mask_get(SculptSession *ss, int index)
static int sculpt_active_vertex_get(SculptSession *ss)
{
- BLI_assert(BKE_pbvh_type(ss->pbvh) != PBVH_GRIDS);
switch (BKE_pbvh_type(ss->pbvh)) {
case PBVH_FACES:
return ss->active_vertex_index;
@@ -211,14 +211,19 @@ static void sculpt_active_vertex_normal_get(SculptSession *ss, float normal[3])
#define SCULPT_VERTEX_NEIGHBOR_FIXED_CAPACITY 256
typedef struct SculptVertexNeighborIter {
+ /* Storage */
int *neighbors;
int size;
int capacity;
-
int neighbors_fixed[SCULPT_VERTEX_NEIGHBOR_FIXED_CAPACITY];
- int index;
+ /* Internal iterator. */
+ int num_duplicates;
int i;
+
+ /* Public */
+ int index;
+ bool is_duplicate;
} SculptVertexNeighborIter;
static void sculpt_vertex_neighbor_add(SculptVertexNeighborIter *iter, int neighbor_index)
@@ -254,6 +259,7 @@ static void sculpt_vertex_neighbors_get_bmesh(SculptSession *ss,
BMIter liter;
BMLoop *l;
iter->size = 0;
+ iter->num_duplicates = 0;
iter->capacity = SCULPT_VERTEX_NEIGHBOR_FIXED_CAPACITY;
iter->neighbors = iter->neighbors_fixed;
@@ -276,6 +282,7 @@ static void sculpt_vertex_neighbors_get_faces(SculptSession *ss,
int i;
MeshElemMap *vert_map = &ss->pmap[(int)index];
iter->size = 0;
+ iter->num_duplicates = 0;
iter->capacity = SCULPT_VERTEX_NEIGHBOR_FIXED_CAPACITY;
iter->neighbors = iter->neighbors_fixed;
@@ -293,20 +300,44 @@ static void sculpt_vertex_neighbors_get_faces(SculptSession *ss,
}
}
-static void sculpt_vertex_neighbors_get_grids(SculptSession *UNUSED(ss),
- int UNUSED(index),
+static void sculpt_vertex_neighbors_get_grids(SculptSession *ss,
+ const int index,
+ const bool include_duplicates,
SculptVertexNeighborIter *iter)
{
- /* TODO: implement this for multires. It might also be worth changing this
- * iterator to provide a coordinate and mask pointer directly for effiency,
- * rather than converting back and forth between CCGElem and global index. */
+ /* TODO: optimize this. We could fill SculptVertexNeighborIter directly,
+ * maybe provide coordinate and mask pointers directly rather than converting
+ * back and forth between CCGElem and global index. */
+ const CCGKey *key = BKE_pbvh_get_grid_key(ss->pbvh);
+ const int grid_index = index / key->grid_area;
+ const int vertex_index = index - grid_index * key->grid_area;
+
+ SubdivCCGCoord coord = {.grid_index = grid_index,
+ .x = vertex_index % key->grid_size,
+ .y = vertex_index / key->grid_size};
+
+ SubdivCCGNeighbors neighbors;
+ BKE_subdiv_ccg_neighbor_coords_get(ss->subdiv_ccg, &coord, include_duplicates, &neighbors);
+
iter->size = 0;
+ iter->num_duplicates = neighbors.num_duplicates;
iter->capacity = SCULPT_VERTEX_NEIGHBOR_FIXED_CAPACITY;
iter->neighbors = iter->neighbors_fixed;
+
+ for (int i = 0; i < neighbors.size; i++) {
+ sculpt_vertex_neighbor_add(iter,
+ neighbors.coords[i].grid_index * key->grid_area +
+ neighbors.coords[i].y * key->grid_size + neighbors.coords[i].x);
+ }
+
+ if (neighbors.coords != neighbors.coords_fixed) {
+ MEM_freeN(neighbors.coords);
+ }
}
static void sculpt_vertex_neighbors_get(SculptSession *ss,
- int index,
+ const int index,
+ const bool include_duplicates,
SculptVertexNeighborIter *iter)
{
switch (BKE_pbvh_type(ss->pbvh)) {
@@ -317,17 +348,28 @@ static void sculpt_vertex_neighbors_get(SculptSession *ss,
sculpt_vertex_neighbors_get_bmesh(ss, index, iter);
return;
case PBVH_GRIDS:
- sculpt_vertex_neighbors_get_grids(ss, index, iter);
+ sculpt_vertex_neighbors_get_grids(ss, index, include_duplicates, iter);
return;
}
}
+/* Iterator over neighboring vertices. */
#define sculpt_vertex_neighbors_iter_begin(ss, v_index, neighbor_iterator) \
- sculpt_vertex_neighbors_get(ss, v_index, &neighbor_iterator); \
+ sculpt_vertex_neighbors_get(ss, v_index, false, &neighbor_iterator); \
for (neighbor_iterator.i = 0; neighbor_iterator.i < neighbor_iterator.size; \
neighbor_iterator.i++) { \
neighbor_iterator.index = ni.neighbors[ni.i];
+/* Iterate over neighboring and duplicate vertices (for PBVH_GRIDS). Duplicates come
+ * first since they are nearest for floodfill. */
+#define sculpt_vertex_duplicates_and_neighbors_iter_begin(ss, v_index, neighbor_iterator) \
+ sculpt_vertex_neighbors_get(ss, v_index, true, &neighbor_iterator); \
+ for (neighbor_iterator.i = neighbor_iterator.size - 1; neighbor_iterator.i >= 0; \
+ neighbor_iterator.i--) { \
+ neighbor_iterator.index = ni.neighbors[ni.i]; \
+ neighbor_iterator.is_duplicate = (ni.i >= \
+ neighbor_iterator.size - neighbor_iterator.num_duplicates);
+
#define sculpt_vertex_neighbors_iter_end(neighbor_iterator) \
} \
if (neighbor_iterator.neighbors != neighbor_iterator.neighbors_fixed) { \
@@ -381,16 +423,19 @@ static void do_nearest_vertex_get_task_cb(void *__restrict userdata,
BKE_pbvh_vertex_iter_end;
}
-static void nearest_vertex_get_finalize(void *__restrict userdata, void *__restrict tls)
+static void nearest_vertex_get_reduce(const void *__restrict UNUSED(userdata),
+ void *__restrict chunk_join,
+ void *__restrict chunk)
{
- SculptThreadedTaskData *data = userdata;
- NearestVertexTLSData *nvtd = tls;
- if (data->nearest_vertex_index == -1) {
- data->nearest_vertex_index = nvtd->nearest_vertex_index;
+ NearestVertexTLSData *join = chunk_join;
+ NearestVertexTLSData *nvtd = chunk;
+ if (join->nearest_vertex_index == -1) {
+ join->nearest_vertex_index = nvtd->nearest_vertex_index;
+ join->nearest_vertex_distance_squared = nvtd->nearest_vertex_distance_squared;
}
- else if (nvtd->nearest_vertex_distance_squared < data->nearest_vertex_distance_squared) {
- data->nearest_vertex_index = nvtd->nearest_vertex_index;
- data->nearest_vertex_distance_squared = nvtd->nearest_vertex_distance_squared;
+ else if (nvtd->nearest_vertex_distance_squared < join->nearest_vertex_distance_squared) {
+ join->nearest_vertex_index = nvtd->nearest_vertex_index;
+ join->nearest_vertex_distance_squared = nvtd->nearest_vertex_distance_squared;
}
}
@@ -417,25 +462,23 @@ static int sculpt_nearest_vertex_get(
.ob = ob,
.nodes = nodes,
.max_distance_squared = max_distance * max_distance,
- .nearest_vertex_index = -1,
};
copy_v3_v3(task_data.nearest_vertex_search_co, co);
- task_data.nearest_vertex_distance_squared = FLT_MAX;
NearestVertexTLSData nvtd;
nvtd.nearest_vertex_index = -1;
nvtd.nearest_vertex_distance_squared = FLT_MAX;
- TaskParallelSettings settings;
+ PBVHParallelSettings settings;
BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP), totnode);
- settings.func_finalize = nearest_vertex_get_finalize;
+ settings.func_reduce = nearest_vertex_get_reduce;
settings.userdata_chunk = &nvtd;
settings.userdata_chunk_size = sizeof(NearestVertexTLSData);
- BLI_task_parallel_range(0, totnode, &task_data, do_nearest_vertex_get_task_cb, &settings);
+ BKE_pbvh_parallel_range(0, totnode, &task_data, do_nearest_vertex_get_task_cb, &settings);
MEM_SAFE_FREE(nodes);
- return task_data.nearest_vertex_index;
+ return nvtd.nearest_vertex_index;
}
static bool is_symmetry_iteration_valid(char i, char symm)
@@ -470,28 +513,18 @@ typedef struct SculptFloodFill {
char *visited_vertices;
} SculptFloodFill;
-typedef struct SculptFloodFillIterator {
- int v;
- int it;
- float edge_factor;
-} SculptFloodFillIterator;
-
static void sculpt_floodfill_init(SculptSession *ss, SculptFloodFill *flood)
{
int vertex_count = sculpt_vertex_count_get(ss);
sculpt_vertex_random_access_init(ss);
- flood->queue = BLI_gsqueue_new(sizeof(SculptFloodFillIterator));
+ flood->queue = BLI_gsqueue_new(sizeof(int));
flood->visited_vertices = MEM_callocN(vertex_count * sizeof(char), "visited vertices");
}
static void sculpt_floodfill_add_initial(SculptFloodFill *flood, int index)
{
- SculptFloodFillIterator mevit;
- mevit.v = index;
- mevit.it = 0;
- mevit.edge_factor = 1.0f;
- BLI_gsqueue_push(flood->queue, &mevit);
+ BLI_gsqueue_push(flood->queue, &index);
}
static void sculpt_floodfill_add_active(
@@ -518,32 +551,24 @@ static void sculpt_floodfill_add_active(
}
}
-static void sculpt_floodfill_execute(SculptSession *ss,
- SculptFloodFill *flood,
- bool (*func)(SculptSession *ss,
- const SculptFloodFillIterator *from,
- SculptFloodFillIterator *to,
- void *userdata),
- void *userdata)
+static void sculpt_floodfill_execute(
+ SculptSession *ss,
+ SculptFloodFill *flood,
+ bool (*func)(SculptSession *ss, int from_v, int to_v, bool is_duplicate, void *userdata),
+ void *userdata)
{
- /* TODO: multires support, taking into account duplicate vertices and
- * correctly handling them in the pose, automask and mask expand callbacks. */
while (!BLI_gsqueue_is_empty(flood->queue)) {
- SculptFloodFillIterator from;
- BLI_gsqueue_pop(flood->queue, &from);
+ int from_v;
+ BLI_gsqueue_pop(flood->queue, &from_v);
SculptVertexNeighborIter ni;
- sculpt_vertex_neighbors_iter_begin(ss, from.v, ni)
+ sculpt_vertex_duplicates_and_neighbors_iter_begin(ss, from_v, ni)
{
- if (flood->visited_vertices[ni.index] == 0) {
- flood->visited_vertices[ni.index] = 1;
+ const int to_v = ni.index;
+ if (flood->visited_vertices[to_v] == 0) {
+ flood->visited_vertices[to_v] = 1;
- SculptFloodFillIterator to;
- to.v = ni.index;
- to.it = from.it + 1;
- to.edge_factor = 0.0f;
-
- if (func(ss, &from, &to, userdata)) {
- BLI_gsqueue_push(flood->queue, &to);
+ if (func(ss, from_v, to_v, ni.is_duplicate, userdata)) {
+ BLI_gsqueue_push(flood->queue, &to_v);
}
}
}
@@ -912,9 +937,9 @@ static void paint_mesh_restore_co(Sculpt *sd, Object *ob)
.nodes = nodes,
};
- TaskParallelSettings settings;
+ PBVHParallelSettings settings;
BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP) && !ss->bm, totnode);
- BLI_task_parallel_range(0, totnode, &data, paint_mesh_restore_co_task_cb, &settings);
+ BKE_pbvh_parallel_range(0, totnode, &data, paint_mesh_restore_co_task_cb, &settings);
MEM_SAFE_FREE(nodes);
}
@@ -1097,9 +1122,8 @@ bool sculpt_brush_test_cube(SculptBrushTest *test, const float co[3], float loca
local_co[1] = fabsf(local_co[1]);
local_co[2] = fabsf(local_co[2]);
+ const float p = 8.0f;
if (local_co[0] <= side && local_co[1] <= side && local_co[2] <= side) {
- float p = 4.0f;
-
test->dist = ((powf(local_co[0], p) + powf(local_co[1], p) + powf(local_co[2], p)) /
powf(side, p));
@@ -1194,11 +1218,6 @@ static bool sculpt_brush_test_cyl(SculptBrushTest *test,
static bool sculpt_automasking_enabled(SculptSession *ss, const Brush *br)
{
- // REMOVE WITH PBVH_GRIDS
- if (ss->pbvh && BKE_pbvh_type(ss->pbvh) == PBVH_GRIDS) {
- return false;
- }
-
if (sculpt_stroke_is_dynamic_topology(ss, br)) {
return false;
}
@@ -1229,7 +1248,7 @@ static void sculpt_automasking_end(Object *ob)
static bool sculpt_automasking_is_constrained_by_radius(Brush *br)
{
/* 2D falloff is not constrained by radius */
- if (br->falloff_shape & BRUSH_AIRBRUSH) {
+ if (br->falloff_shape == PAINT_FALLOFF_SHAPE_TUBE) {
return false;
}
@@ -1247,17 +1266,15 @@ typedef struct AutomaskFloodFillData {
char symm;
} AutomaskFloodFillData;
-static bool automask_floodfill_cb(SculptSession *ss,
- const SculptFloodFillIterator *UNUSED(from),
- SculptFloodFillIterator *to,
- void *userdata)
+static bool automask_floodfill_cb(
+ SculptSession *ss, int UNUSED(from_v), int to_v, bool UNUSED(is_duplicate), void *userdata)
{
AutomaskFloodFillData *data = userdata;
- data->automask_factor[to->v] = 1.0f;
+ data->automask_factor[to_v] = 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));
+ 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)
@@ -1396,9 +1413,10 @@ static float calc_symmetry_feather(Sculpt *sd, StrokeCache *cache)
* \{ */
typedef struct AreaNormalCenterTLSData {
- float private_co[2][3];
- float private_no[2][3];
- int private_count[2];
+ /* 0=towards view, 1=flipped */
+ float area_cos[2][3];
+ float area_nos[2][3];
+ int area_count[2];
} AreaNormalCenterTLSData;
static void calc_area_normal_and_center_task_cb(void *__restrict userdata,
@@ -1408,8 +1426,8 @@ static void calc_area_normal_and_center_task_cb(void *__restrict userdata,
SculptThreadedTaskData *data = userdata;
SculptSession *ss = data->ob->sculpt;
AreaNormalCenterTLSData *anctd = tls->userdata_chunk;
- float(*area_nos)[3] = data->area_nos;
- float(*area_cos)[3] = data->area_cos;
+ const bool use_area_nos = data->use_area_nos;
+ const bool use_area_cos = data->use_area_cos;
PBVHVertexIter vd;
SculptUndoNode *unode = NULL;
@@ -1428,7 +1446,10 @@ static void calc_area_normal_and_center_task_cb(void *__restrict userdata,
/* Update the test radius to sample the normal using the normal radius of the brush */
if (data->brush->ob_mode == OB_MODE_SCULPT) {
float test_radius = sqrtf(test.radius_squared);
- test_radius *= data->brush->normal_radius_factor;
+ /* Layer brush produces artifacts with normal radius */
+ if (!(ss->cache && data->brush->sculpt_tool == SCULPT_TOOL_LAYER)) {
+ test_radius *= data->brush->normal_radius_factor;
+ }
test.radius_squared = test_radius * test_radius;
}
@@ -1459,13 +1480,13 @@ static void calc_area_normal_and_center_task_cb(void *__restrict userdata,
normal_tri_v3(no, UNPACK3(co_tri));
flip_index = (dot_v3v3(ss->cache->view_normal, no) <= 0.0f);
- if (area_cos) {
- add_v3_v3(anctd->private_co[flip_index], co);
+ if (use_area_cos) {
+ add_v3_v3(anctd->area_cos[flip_index], co);
}
- if (area_nos) {
- add_v3_v3(anctd->private_no[flip_index], no);
+ if (use_area_nos) {
+ add_v3_v3(anctd->area_nos[flip_index], no);
}
- anctd->private_count[flip_index] += 1;
+ anctd->area_count[flip_index] += 1;
}
}
}
@@ -1511,40 +1532,37 @@ static void calc_area_normal_and_center_task_cb(void *__restrict userdata,
flip_index = (dot_v3v3(ss->cache ? ss->cache->view_normal : ss->cursor_view_normal, no) <=
0.0f);
- if (area_cos) {
- add_v3_v3(anctd->private_co[flip_index], co);
+ if (use_area_cos) {
+ add_v3_v3(anctd->area_cos[flip_index], co);
}
- if (area_nos) {
- add_v3_v3(anctd->private_no[flip_index], no);
+ if (use_area_nos) {
+ add_v3_v3(anctd->area_nos[flip_index], no);
}
- anctd->private_count[flip_index] += 1;
+ anctd->area_count[flip_index] += 1;
}
}
BKE_pbvh_vertex_iter_end;
}
}
-static void calc_area_normal_and_center_finalize(void *__restrict userdata, void *__restrict tls)
+static void calc_area_normal_and_center_reduce(const void *__restrict UNUSED(userdata),
+ void *__restrict chunk_join,
+ void *__restrict chunk)
{
- SculptThreadedTaskData *data = userdata;
- AreaNormalCenterTLSData *anctd = tls;
- float(*area_nos)[3] = data->area_nos;
- float(*area_cos)[3] = data->area_cos;
+ AreaNormalCenterTLSData *join = chunk_join;
+ AreaNormalCenterTLSData *anctd = chunk;
+
/* for flatten center */
- if (area_cos) {
- add_v3_v3(area_cos[0], anctd->private_co[0]);
- add_v3_v3(area_cos[1], anctd->private_co[1]);
- }
+ add_v3_v3(join->area_cos[0], anctd->area_cos[0]);
+ add_v3_v3(join->area_cos[1], anctd->area_cos[1]);
/* for area normal */
- if (area_nos) {
- add_v3_v3(area_nos[0], anctd->private_no[0]);
- add_v3_v3(area_nos[1], anctd->private_no[1]);
- }
+ add_v3_v3(join->area_nos[0], anctd->area_nos[0]);
+ add_v3_v3(join->area_nos[1], anctd->area_nos[1]);
/* weights */
- data->count[0] += anctd->private_count[0];
- data->count[1] += anctd->private_count[1];
+ join->area_count[0] += anctd->area_count[0];
+ join->area_count[1] += anctd->area_count[1];
}
static void calc_area_center(
@@ -1555,11 +1573,6 @@ static void calc_area_center(
const bool has_bm_orco = ss->bm && sculpt_stroke_is_dynamic_topology(ss, brush);
int n;
- /* 0=towards view, 1=flipped */
- float area_cos[2][3] = {{0.0f}};
-
- int count[2] = {0};
-
/* Intentionally set 'sd' to NULL since we share logic with vertex paint. */
SculptThreadedTaskData data = {
.sd = NULL,
@@ -1568,24 +1581,22 @@ static void calc_area_center(
.nodes = nodes,
.totnode = totnode,
.has_bm_orco = has_bm_orco,
- .area_cos = area_cos,
- .area_nos = NULL,
- .count = count,
+ .use_area_cos = true,
};
AreaNormalCenterTLSData anctd = {{{0}}};
- TaskParallelSettings settings;
+ PBVHParallelSettings settings;
BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP), totnode);
- settings.func_finalize = calc_area_normal_and_center_finalize;
+ settings.func_reduce = calc_area_normal_and_center_reduce;
settings.userdata_chunk = &anctd;
settings.userdata_chunk_size = sizeof(AreaNormalCenterTLSData);
- BLI_task_parallel_range(0, totnode, &data, calc_area_normal_and_center_task_cb, &settings);
+ BKE_pbvh_parallel_range(0, totnode, &data, calc_area_normal_and_center_task_cb, &settings);
/* for flatten center */
- for (n = 0; n < ARRAY_SIZE(area_cos); n++) {
- if (count[n] != 0) {
- mul_v3_v3fl(r_area_co, area_cos[n], 1.0f / count[n]);
+ for (n = 0; n < ARRAY_SIZE(anctd.area_cos); n++) {
+ if (anctd.area_count[n] != 0) {
+ mul_v3_v3fl(r_area_co, anctd.area_cos[n], 1.0f / anctd.area_count[n]);
break;
}
}
@@ -1613,11 +1624,6 @@ bool sculpt_pbvh_calc_area_normal(const Brush *brush,
SculptSession *ss = ob->sculpt;
const bool has_bm_orco = ss->bm && sculpt_stroke_is_dynamic_topology(ss, brush);
- /* 0=towards view, 1=flipped */
- float area_nos[2][3] = {{0.0f}};
-
- int count[2] = {0};
-
/* Intentionally set 'sd' to NULL since this is used for vertex paint too. */
SculptThreadedTaskData data = {
.sd = NULL,
@@ -1626,24 +1632,22 @@ bool sculpt_pbvh_calc_area_normal(const Brush *brush,
.nodes = nodes,
.totnode = totnode,
.has_bm_orco = has_bm_orco,
- .area_cos = NULL,
- .area_nos = area_nos,
- .count = count,
+ .use_area_nos = true,
.any_vertex_sampled = false,
};
AreaNormalCenterTLSData anctd = {{{0}}};
- TaskParallelSettings settings;
+ PBVHParallelSettings settings;
BKE_pbvh_parallel_range_settings(&settings, use_threading, totnode);
- settings.func_finalize = calc_area_normal_and_center_finalize;
+ settings.func_reduce = calc_area_normal_and_center_reduce;
settings.userdata_chunk = &anctd;
settings.userdata_chunk_size = sizeof(AreaNormalCenterTLSData);
- BLI_task_parallel_range(0, totnode, &data, calc_area_normal_and_center_task_cb, &settings);
+ BKE_pbvh_parallel_range(0, totnode, &data, calc_area_normal_and_center_task_cb, &settings);
/* for area normal */
- for (int i = 0; i < ARRAY_SIZE(area_nos); i++) {
- if (normalize_v3_v3(r_area_no, area_nos[i]) != 0.0f) {
+ for (int i = 0; i < ARRAY_SIZE(anctd.area_nos); i++) {
+ if (normalize_v3_v3(r_area_no, anctd.area_nos[i]) != 0.0f) {
break;
}
}
@@ -1661,12 +1665,6 @@ static void calc_area_normal_and_center(
const bool has_bm_orco = ss->bm && sculpt_stroke_is_dynamic_topology(ss, brush);
int n;
- /* 0=towards view, 1=flipped */
- float area_cos[2][3] = {{0.0f}};
- float area_nos[2][3] = {{0.0f}};
-
- int count[2] = {0};
-
/* Intentionally set 'sd' to NULL since this is used for vertex paint too. */
SculptThreadedTaskData data = {
.sd = NULL,
@@ -1675,24 +1673,23 @@ static void calc_area_normal_and_center(
.nodes = nodes,
.totnode = totnode,
.has_bm_orco = has_bm_orco,
- .area_cos = area_cos,
- .area_nos = area_nos,
- .count = count,
+ .use_area_cos = true,
+ .use_area_nos = true,
};
AreaNormalCenterTLSData anctd = {{{0}}};
- TaskParallelSettings settings;
+ PBVHParallelSettings settings;
BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP), totnode);
- settings.func_finalize = calc_area_normal_and_center_finalize;
+ settings.func_reduce = calc_area_normal_and_center_reduce;
settings.userdata_chunk = &anctd;
settings.userdata_chunk_size = sizeof(AreaNormalCenterTLSData);
- BLI_task_parallel_range(0, totnode, &data, calc_area_normal_and_center_task_cb, &settings);
+ BKE_pbvh_parallel_range(0, totnode, &data, calc_area_normal_and_center_task_cb, &settings);
/* for flatten center */
- for (n = 0; n < ARRAY_SIZE(area_cos); n++) {
- if (count[n] != 0) {
- mul_v3_v3fl(r_area_co, area_cos[n], 1.0f / count[n]);
+ for (n = 0; n < ARRAY_SIZE(anctd.area_cos); n++) {
+ if (anctd.area_count[n] != 0) {
+ mul_v3_v3fl(r_area_co, anctd.area_cos[n], 1.0f / anctd.area_count[n]);
break;
}
}
@@ -1701,8 +1698,8 @@ static void calc_area_normal_and_center(
}
/* for area normal */
- for (n = 0; n < ARRAY_SIZE(area_nos); n++) {
- if (normalize_v3_v3(r_area_no, area_nos[n]) != 0.0f) {
+ for (n = 0; n < ARRAY_SIZE(anctd.area_nos); n++) {
+ if (normalize_v3_v3(r_area_no, anctd.area_nos[n]) != 0.0f) {
break;
}
}
@@ -1736,11 +1733,13 @@ static float brush_strength(const Sculpt *sd,
switch (brush->sculpt_tool) {
case SCULPT_TOOL_CLAY:
- case SCULPT_TOOL_CLAY_STRIPS:
case SCULPT_TOOL_DRAW:
case SCULPT_TOOL_DRAW_SHARP:
case SCULPT_TOOL_LAYER:
return alpha * flip * pressure * overlap * feather;
+ case SCULPT_TOOL_CLAY_STRIPS:
+ /* Clay Strips needs extra strength to compensate for its default normal radius */
+ return alpha * flip * pressure * overlap * feather * 1.3f;
case SCULPT_TOOL_MASK:
overlap = (1 + overlap) / 2;
@@ -2083,9 +2082,15 @@ static void update_sculpt_normal(Sculpt *sd, Object *ob, PBVHNode **nodes, int t
{
const Brush *brush = BKE_paint_brush(&sd->paint);
StrokeCache *cache = ob->sculpt->cache;
+ /* Grab brush does not update the sculpt normal during a stroke */
+ const bool update_normal = !(brush->flag & BRUSH_ORIGINAL_NORMAL) &&
+ !(brush->sculpt_tool == SCULPT_TOOL_GRAB) &&
+ !(brush->sculpt_tool == SCULPT_TOOL_ELASTIC_DEFORM) &&
+ !(brush->sculpt_tool == SCULPT_TOOL_SNAKE_HOOK &&
+ cache->normal_weight > 0.0f);
if (cache->mirror_symmetry_pass == 0 && cache->radial_symmetry_pass == 0 &&
- (cache->first_time || !(brush->flag & BRUSH_ORIGINAL_NORMAL))) {
+ (cache->first_time || update_normal)) {
calc_sculpt_normal(sd, ob, nodes, totnode, cache->sculpt_normal);
if (brush->falloff_shape == PAINT_FALLOFF_SHAPE_TUBE) {
project_plane_v3_v3v3(cache->sculpt_normal, cache->sculpt_normal, cache->view_normal);
@@ -2796,7 +2801,7 @@ static void smooth(Sculpt *sd,
.strength = strength,
};
- TaskParallelSettings settings;
+ PBVHParallelSettings settings;
BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP), totnode);
switch (type) {
@@ -2814,16 +2819,16 @@ static void smooth(Sculpt *sd,
settings.userdata_chunk = data_chunk;
settings.userdata_chunk_size = size;
- BLI_task_parallel_range(0, totnode, &data, do_smooth_brush_multires_task_cb_ex, &settings);
+ BKE_pbvh_parallel_range(0, totnode, &data, do_smooth_brush_multires_task_cb_ex, &settings);
MEM_freeN(data_chunk);
break;
}
case PBVH_FACES:
- BLI_task_parallel_range(0, totnode, &data, do_smooth_brush_mesh_task_cb_ex, &settings);
+ BKE_pbvh_parallel_range(0, totnode, &data, do_smooth_brush_mesh_task_cb_ex, &settings);
break;
case PBVH_BMESH:
- BLI_task_parallel_range(0, totnode, &data, do_smooth_brush_bmesh_task_cb_ex, &settings);
+ BKE_pbvh_parallel_range(0, totnode, &data, do_smooth_brush_bmesh_task_cb_ex, &settings);
break;
}
@@ -2855,10 +2860,10 @@ static void bmesh_topology_rake(
.nodes = nodes,
.strength = factor,
};
- TaskParallelSettings settings;
+ PBVHParallelSettings settings;
BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP), totnode);
- BLI_task_parallel_range(0, totnode, &data, do_topology_rake_bmesh_task_cb_ex, &settings);
+ BKE_pbvh_parallel_range(0, totnode, &data, do_topology_rake_bmesh_task_cb_ex, &settings);
}
}
@@ -2912,9 +2917,9 @@ static void do_mask_brush_draw(Sculpt *sd, Object *ob, PBVHNode **nodes, int tot
.nodes = nodes,
};
- TaskParallelSettings settings;
+ PBVHParallelSettings settings;
BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP), totnode);
- BLI_task_parallel_range(0, totnode, &data, do_mask_brush_draw_task_cb_ex, &settings);
+ BKE_pbvh_parallel_range(0, totnode, &data, do_mask_brush_draw_task_cb_ex, &settings);
}
static void do_mask_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode)
@@ -2999,9 +3004,9 @@ static void do_draw_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode)
.offset = offset,
};
- TaskParallelSettings settings;
+ PBVHParallelSettings settings;
BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP), totnode);
- BLI_task_parallel_range(0, totnode, &data, do_draw_brush_task_cb_ex, &settings);
+ BKE_pbvh_parallel_range(0, totnode, &data, do_draw_brush_task_cb_ex, &settings);
}
static void do_draw_sharp_brush_task_cb_ex(void *__restrict userdata,
@@ -3075,9 +3080,9 @@ static void do_draw_sharp_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int to
.offset = offset,
};
- TaskParallelSettings settings;
+ PBVHParallelSettings settings;
BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP), totnode);
- BLI_task_parallel_range(0, totnode, &data, do_draw_sharp_brush_task_cb_ex, &settings);
+ BKE_pbvh_parallel_range(0, totnode, &data, do_draw_sharp_brush_task_cb_ex, &settings);
}
/**
@@ -3191,9 +3196,9 @@ static void do_crease_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnod
.flippedbstrength = flippedbstrength,
};
- TaskParallelSettings settings;
+ PBVHParallelSettings settings;
BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP), totnode);
- BLI_task_parallel_range(0, totnode, &data, do_crease_brush_task_cb_ex, &settings);
+ BKE_pbvh_parallel_range(0, totnode, &data, do_crease_brush_task_cb_ex, &settings);
}
static void do_pinch_brush_task_cb_ex(void *__restrict userdata,
@@ -3253,9 +3258,9 @@ static void do_pinch_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode
.nodes = nodes,
};
- TaskParallelSettings settings;
+ PBVHParallelSettings settings;
BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP), totnode);
- BLI_task_parallel_range(0, totnode, &data, do_pinch_brush_task_cb_ex, &settings);
+ BKE_pbvh_parallel_range(0, totnode, &data, do_pinch_brush_task_cb_ex, &settings);
}
static void do_grab_brush_task_cb_ex(void *__restrict userdata,
@@ -3325,9 +3330,9 @@ static void do_grab_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode)
.grab_delta = grab_delta,
};
- TaskParallelSettings settings;
+ PBVHParallelSettings settings;
BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP), totnode);
- BLI_task_parallel_range(0, totnode, &data, do_grab_brush_task_cb_ex, &settings);
+ BKE_pbvh_parallel_range(0, totnode, &data, do_grab_brush_task_cb_ex, &settings);
}
/* Regularized Kelvinlets: Sculpting Brushes based on Fundamental Solutions of Elasticity
@@ -3566,6 +3571,10 @@ static void do_elastic_deform_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, in
copy_v3_v3(grab_delta, ss->cache->grab_delta_symmetry);
+ if (ss->cache->normal_weight > 0.0f) {
+ sculpt_project_v3_normal_align(ss, ss->cache->normal_weight, grab_delta);
+ }
+
SculptThreadedTaskData data = {
.sd = sd,
.ob = ob,
@@ -3574,9 +3583,9 @@ static void do_elastic_deform_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, in
.grab_delta = grab_delta,
};
- TaskParallelSettings settings;
+ PBVHParallelSettings settings;
BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP), totnode);
- BLI_task_parallel_range(0, totnode, &data, do_elastic_deform_brush_task_cb_ex, &settings);
+ BKE_pbvh_parallel_range(0, totnode, &data, do_elastic_deform_brush_task_cb_ex, &settings);
}
static void do_pose_brush_task_cb_ex(void *__restrict userdata,
@@ -3628,10 +3637,6 @@ static void do_pose_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode)
float pose_initial_co[3];
float transform_rot[4][4], transform_trans[4][4], transform_trans_inv[4][4];
- if (BKE_pbvh_type(ss->pbvh) == PBVH_GRIDS) {
- return;
- }
-
copy_v3_v3(grab_delta, ss->cache->grab_delta_symmetry);
copy_v3_v3(pose_origin, ss->cache->pose_origin);
@@ -3667,14 +3672,14 @@ static void do_pose_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode)
.transform_trans_inv = transform_trans_inv,
};
- TaskParallelSettings settings;
+ PBVHParallelSettings settings;
BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP), totnode);
- BLI_task_parallel_range(0, totnode, &data, do_pose_brush_task_cb_ex, &settings);
+ BKE_pbvh_parallel_range(0, totnode, &data, do_pose_brush_task_cb_ex, &settings);
}
typedef struct PoseGrowFactorTLSData {
float pos_avg[3];
- int tot_pos_avg;
+ int pos_count;
} PoseGrowFactorTLSData;
static void pose_brush_grow_factor_task_cb_ex(void *__restrict userdata,
@@ -3703,7 +3708,7 @@ static void pose_brush_grow_factor_task_cb_ex(void *__restrict userdata,
data->pose_factor[vd.index] = max;
if (check_vertex_pivot_symmetry(vd.co, active_co, symm)) {
add_v3_v3(gftd->pos_avg, vd.co);
- gftd->tot_pos_avg++;
+ gftd->pos_count++;
}
}
}
@@ -3711,12 +3716,14 @@ static void pose_brush_grow_factor_task_cb_ex(void *__restrict userdata,
BKE_pbvh_vertex_iter_end;
}
-static void pose_brush_grow_factor_finalize(void *__restrict userdata, void *__restrict tls)
+static void pose_brush_grow_factor_reduce(const void *__restrict UNUSED(userdata),
+ void *__restrict chunk_join,
+ void *__restrict chunk)
{
- SculptThreadedTaskData *data = userdata;
- PoseGrowFactorTLSData *gftd = tls;
- add_v3_v3(data->tot_pos_avg, gftd->pos_avg);
- data->tot_pos_count += gftd->tot_pos_avg;
+ PoseGrowFactorTLSData *join = chunk_join;
+ PoseGrowFactorTLSData *gftd = chunk;
+ add_v3_v3(join->pos_avg, gftd->pos_avg);
+ join->pos_count += gftd->pos_count;
}
/* Grow the factor until its boundary is near to the offset pose origin */
@@ -3735,12 +3742,12 @@ static void sculpt_pose_grow_pose_factor(
.totnode = totnode,
.pose_factor = pose_factor,
};
- TaskParallelSettings settings;
+ PBVHParallelSettings settings;
PoseGrowFactorTLSData gftd;
- gftd.tot_pos_avg = 0;
+ gftd.pos_count = 0;
zero_v3(gftd.pos_avg);
BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP), totnode);
- settings.func_finalize = pose_brush_grow_factor_finalize;
+ settings.func_reduce = pose_brush_grow_factor_reduce;
settings.userdata_chunk = &gftd;
settings.userdata_chunk_size = sizeof(PoseGrowFactorTLSData);
@@ -3748,15 +3755,13 @@ static void sculpt_pose_grow_pose_factor(
float prev_len = FLT_MAX;
data.prev_mask = MEM_mallocN(sculpt_vertex_count_get(ss) * sizeof(float), "prev mask");
while (grow_next_iteration) {
- zero_v3(data.tot_pos_avg);
- data.tot_pos_count = 0;
zero_v3(gftd.pos_avg);
- gftd.tot_pos_avg = 0;
+ gftd.pos_count = 0;
memcpy(data.prev_mask, pose_factor, sculpt_vertex_count_get(ss) * sizeof(float));
- BLI_task_parallel_range(0, totnode, &data, pose_brush_grow_factor_task_cb_ex, &settings);
- if (data.tot_pos_count != 0) {
- mul_v3_fl(data.tot_pos_avg, 1.0f / (float)data.tot_pos_count);
- float len = len_v3v3(data.tot_pos_avg, pose_origin);
+ BKE_pbvh_parallel_range(0, totnode, &data, pose_brush_grow_factor_task_cb_ex, &settings);
+ if (gftd.pos_count != 0) {
+ mul_v3_fl(gftd.pos_avg, 1.0f / (float)gftd.pos_count);
+ float len = len_v3v3(gftd.pos_avg, pose_origin);
if (len < prev_len) {
prev_len = len;
grow_next_iteration = true;
@@ -3806,25 +3811,25 @@ typedef struct PoseFloodFillData {
int tot_co;
} PoseFloodFillData;
-static bool pose_floodfill_cb(SculptSession *ss,
- const SculptFloodFillIterator *UNUSED(from),
- SculptFloodFillIterator *to,
- void *userdata)
+static bool pose_floodfill_cb(
+ SculptSession *ss, int UNUSED(from_v), int to_v, bool is_duplicate, void *userdata)
{
PoseFloodFillData *data = userdata;
if (data->pose_factor) {
- data->pose_factor[to->v] = 1.0f;
+ data->pose_factor[to_v] = 1.0f;
}
- const float *co = sculpt_vertex_co_get(ss, to->v);
+ const float *co = sculpt_vertex_co_get(ss, to_v);
if (sculpt_pose_brush_is_vertex_inside_brush_radius(
co, data->pose_initial_co, data->radius, data->symm)) {
return true;
}
else if (check_vertex_pivot_symmetry(co, data->pose_initial_co, data->symm)) {
- add_v3_v3(data->pose_origin, co);
- data->tot_co++;
+ if (!is_duplicate) {
+ add_v3_v3(data->pose_origin, co);
+ data->tot_co++;
+ }
}
return false;
@@ -3925,9 +3930,9 @@ static void sculpt_pose_brush_init(
/* Smooth the pose brush factor for cleaner deformation */
for (int i = 0; i < 4; i++) {
- TaskParallelSettings settings;
+ PBVHParallelSettings settings;
BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP), totnode);
- BLI_task_parallel_range(0, totnode, &data, pose_brush_init_task_cb_ex, &settings);
+ BKE_pbvh_parallel_range(0, totnode, &data, pose_brush_init_task_cb_ex, &settings);
}
MEM_SAFE_FREE(nodes);
@@ -3995,9 +4000,9 @@ static void do_nudge_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode
.cono = cono,
};
- TaskParallelSettings settings;
+ PBVHParallelSettings settings;
BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP), totnode);
- BLI_task_parallel_range(0, totnode, &data, do_nudge_brush_task_cb_ex, &settings);
+ BKE_pbvh_parallel_range(0, totnode, &data, do_nudge_brush_task_cb_ex, &settings);
}
static void do_snake_hook_brush_task_cb_ex(void *__restrict userdata,
@@ -4116,9 +4121,9 @@ static void do_snake_hook_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int to
.grab_delta = grab_delta,
};
- TaskParallelSettings settings;
+ PBVHParallelSettings settings;
BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP), totnode);
- BLI_task_parallel_range(0, totnode, &data, do_snake_hook_brush_task_cb_ex, &settings);
+ BKE_pbvh_parallel_range(0, totnode, &data, do_snake_hook_brush_task_cb_ex, &settings);
}
static void do_thumb_brush_task_cb_ex(void *__restrict userdata,
@@ -4188,9 +4193,9 @@ static void do_thumb_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode
.cono = cono,
};
- TaskParallelSettings settings;
+ PBVHParallelSettings settings;
BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP), totnode);
- BLI_task_parallel_range(0, totnode, &data, do_thumb_brush_task_cb_ex, &settings);
+ BKE_pbvh_parallel_range(0, totnode, &data, do_thumb_brush_task_cb_ex, &settings);
}
static void do_rotate_brush_task_cb_ex(void *__restrict userdata,
@@ -4261,9 +4266,9 @@ static void do_rotate_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnod
.angle = angle,
};
- TaskParallelSettings settings;
+ PBVHParallelSettings settings;
BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP), totnode);
- BLI_task_parallel_range(0, totnode, &data, do_rotate_brush_task_cb_ex, &settings);
+ BKE_pbvh_parallel_range(0, totnode, &data, do_rotate_brush_task_cb_ex, &settings);
}
static void do_layer_brush_task_cb_ex(void *__restrict userdata,
@@ -4358,9 +4363,9 @@ static void do_layer_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode
};
BLI_mutex_init(&data.mutex);
- TaskParallelSettings settings;
+ PBVHParallelSettings settings;
BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP), totnode);
- BLI_task_parallel_range(0, totnode, &data, do_layer_brush_task_cb_ex, &settings);
+ BKE_pbvh_parallel_range(0, totnode, &data, do_layer_brush_task_cb_ex, &settings);
BLI_mutex_end(&data.mutex);
}
@@ -4426,9 +4431,9 @@ static void do_inflate_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totno
.nodes = nodes,
};
- TaskParallelSettings settings;
+ PBVHParallelSettings settings;
BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP), totnode);
- BLI_task_parallel_range(0, totnode, &data, do_inflate_brush_task_cb_ex, &settings);
+ BKE_pbvh_parallel_range(0, totnode, &data, do_inflate_brush_task_cb_ex, &settings);
}
static void calc_sculpt_plane(
@@ -4635,9 +4640,9 @@ static void do_flatten_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totno
.area_co = area_co,
};
- TaskParallelSettings settings;
+ PBVHParallelSettings settings;
BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP), totnode);
- BLI_task_parallel_range(0, totnode, &data, do_flatten_brush_task_cb_ex, &settings);
+ BKE_pbvh_parallel_range(0, totnode, &data, do_flatten_brush_task_cb_ex, &settings);
}
static void do_clay_brush_task_cb_ex(void *__restrict userdata,
@@ -4733,9 +4738,9 @@ static void do_clay_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode)
.area_co = area_co,
};
- TaskParallelSettings settings;
+ PBVHParallelSettings settings;
BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP), totnode);
- BLI_task_parallel_range(0, totnode, &data, do_clay_brush_task_cb_ex, &settings);
+ BKE_pbvh_parallel_range(0, totnode, &data, do_clay_brush_task_cb_ex, &settings);
}
static void do_clay_strips_brush_task_cb_ex(void *__restrict userdata,
@@ -4863,9 +4868,9 @@ static void do_clay_strips_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int t
.mat = mat,
};
- TaskParallelSettings settings;
+ PBVHParallelSettings settings;
BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP), totnode);
- BLI_task_parallel_range(0, totnode, &data, do_clay_strips_brush_task_cb_ex, &settings);
+ BKE_pbvh_parallel_range(0, totnode, &data, do_clay_strips_brush_task_cb_ex, &settings);
}
static void do_fill_brush_task_cb_ex(void *__restrict userdata,
@@ -4956,9 +4961,9 @@ static void do_fill_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode)
.area_co = area_co,
};
- TaskParallelSettings settings;
+ PBVHParallelSettings settings;
BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP), totnode);
- BLI_task_parallel_range(0, totnode, &data, do_fill_brush_task_cb_ex, &settings);
+ BKE_pbvh_parallel_range(0, totnode, &data, do_fill_brush_task_cb_ex, &settings);
}
static void do_scrape_brush_task_cb_ex(void *__restrict userdata,
@@ -5048,9 +5053,9 @@ static void do_scrape_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnod
.area_co = area_co,
};
- TaskParallelSettings settings;
+ PBVHParallelSettings settings;
BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP), totnode);
- BLI_task_parallel_range(0, totnode, &data, do_scrape_brush_task_cb_ex, &settings);
+ BKE_pbvh_parallel_range(0, totnode, &data, do_scrape_brush_task_cb_ex, &settings);
}
static void do_gravity_task_cb_ex(void *__restrict userdata,
@@ -5117,9 +5122,9 @@ static void do_gravity(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode, fl
.offset = offset,
};
- TaskParallelSettings settings;
+ PBVHParallelSettings settings;
BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP), totnode);
- BLI_task_parallel_range(0, totnode, &data, do_gravity_task_cb_ex, &settings);
+ BKE_pbvh_parallel_range(0, totnode, &data, do_gravity_task_cb_ex, &settings);
}
void sculpt_vertcos_to_key(Object *ob, KeyBlock *kb, const float (*vertCos)[3])
@@ -5271,7 +5276,12 @@ static void do_brush_action(Sculpt *sd, Object *ob, Brush *brush, UnifiedPaintSe
else {
const bool use_original = sculpt_tool_needs_original(brush->sculpt_tool) ? true :
ss->cache->original;
- const float radius_scale = 1.0f;
+ float radius_scale = 1.0f;
+ /* With these options enabled not all required nodes are inside the original brush radius, so
+ * the brush can produce artifacts in some situations */
+ if (brush->sculpt_tool == SCULPT_TOOL_DRAW && brush->flag & BRUSH_ORIGINAL_NORMAL) {
+ radius_scale = 2.0f;
+ }
nodes = sculpt_pbvh_gather_generic(ob, sd, brush, use_original, radius_scale, &totnode);
}
@@ -5286,9 +5296,9 @@ static void do_brush_action(Sculpt *sd, Object *ob, Brush *brush, UnifiedPaintSe
.nodes = nodes,
};
- TaskParallelSettings settings;
+ PBVHParallelSettings settings;
BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP), totnode);
- BLI_task_parallel_range(0, totnode, &task_data, do_brush_action_task_cb, &settings);
+ BKE_pbvh_parallel_range(0, totnode, &task_data, do_brush_action_task_cb, &settings);
if (sculpt_brush_needs_normal(ss, brush)) {
update_sculpt_normal(sd, ob, nodes, totnode);
@@ -5306,9 +5316,7 @@ static void do_brush_action(Sculpt *sd, Object *ob, Brush *brush, UnifiedPaintSe
if (brush->sculpt_tool == SCULPT_TOOL_POSE && ss->cache->first_time &&
ss->cache->mirror_symmetry_pass == 0) {
- if (BKE_pbvh_type(ss->pbvh) != PBVH_GRIDS) {
- sculpt_pose_brush_init(sd, ob, ss, brush, ss->cache->location, ss->cache->radius);
- }
+ sculpt_pose_brush_init(sd, ob, ss, brush, ss->cache->location, ss->cache->radius);
}
/* Apply one type of brush action */
@@ -5425,7 +5433,7 @@ 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);
- if (!ss->kb) {
+ if (!ss->shapekey_active) {
copy_v3_v3(me->mvert[index].co, newco);
}
}
@@ -5481,7 +5489,7 @@ static void sculpt_combine_proxies_task_cb(void *__restrict userdata,
sculpt_clip(sd, ss, vd.co, val);
- if (ss->modifiers_active) {
+ if (ss->deform_modifiers_active) {
sculpt_flush_pbvhvert_deform(ob, &vd);
}
}
@@ -5508,9 +5516,9 @@ static void sculpt_combine_proxies(Sculpt *sd, Object *ob)
.nodes = nodes,
};
- TaskParallelSettings settings;
+ PBVHParallelSettings settings;
BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP), totnode);
- BLI_task_parallel_range(0, totnode, &data, sculpt_combine_proxies_task_cb, &settings);
+ BKE_pbvh_parallel_range(0, totnode, &data, sculpt_combine_proxies_task_cb, &settings);
}
MEM_SAFE_FREE(nodes);
@@ -5532,7 +5540,7 @@ static void sculpt_update_keyblock(Object *ob)
}
if (vertCos) {
- sculpt_vertcos_to_key(ob, ss->kb, vertCos);
+ sculpt_vertcos_to_key(ob, ss->shapekey_active, vertCos);
if (vertCos != ss->orig_cos) {
MEM_freeN(vertCos);
@@ -5578,7 +5586,7 @@ static void sculpt_flush_stroke_deform(Sculpt *sd, Object *ob, bool is_proxy_use
PBVHNode **nodes;
float(*vertCos)[3] = NULL;
- if (ss->kb) {
+ if (ss->shapekey_active) {
vertCos = MEM_mallocN(sizeof(*vertCos) * me->totvert, "flushStrokeDeofrm keyVerts");
/* mesh could have isolated verts which wouldn't be in BVH,
@@ -5598,12 +5606,12 @@ static void sculpt_flush_stroke_deform(Sculpt *sd, Object *ob, bool is_proxy_use
.vertCos = vertCos,
};
- TaskParallelSettings settings;
+ PBVHParallelSettings settings;
BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP), totnode);
- BLI_task_parallel_range(0, totnode, &data, sculpt_flush_stroke_deform_task_cb, &settings);
+ BKE_pbvh_parallel_range(0, totnode, &data, sculpt_flush_stroke_deform_task_cb, &settings);
if (vertCos) {
- sculpt_vertcos_to_key(ob, ss->kb, vertCos);
+ sculpt_vertcos_to_key(ob, ss->shapekey_active, vertCos);
MEM_freeN(vertCos);
}
@@ -5614,7 +5622,7 @@ static void sculpt_flush_stroke_deform(Sculpt *sd, Object *ob, bool is_proxy_use
* after applying coords from keyblock on base mesh */
BKE_mesh_calc_normals(me);
}
- else if (ss->kb) {
+ else if (ss->shapekey_active) {
sculpt_update_keyblock(ob);
}
}
@@ -6378,7 +6386,8 @@ static void sculpt_stroke_modifiers_check(const bContext *C, Object *ob, const B
View3D *v3d = CTX_wm_view3d(C);
bool need_pmap = sculpt_needs_conectivity_info(brush, ss, 0);
- if (ss->kb || ss->modifiers_active || (!BKE_sculptsession_use_pbvh_draw(ob, v3d) && need_pmap)) {
+ if (ss->shapekey_active || ss->deform_modifiers_active ||
+ (!BKE_sculptsession_use_pbvh_draw(ob, v3d) && need_pmap)) {
Depsgraph *depsgraph = CTX_data_depsgraph_pointer(C);
BKE_sculpt_update_object_for_edit(depsgraph, ob, need_pmap, false);
}
@@ -6559,13 +6568,7 @@ bool sculpt_cursor_geometry_info_update(bContext *C,
/* Update the active vertex of the SculptSession */
ss->active_vertex_index = srd.active_vertex_index;
-
- if (!ss->multires) {
- copy_v3_v3(out->active_vertex_co, sculpt_active_vertex_co_get(ss));
- }
- else {
- zero_v3(out->active_vertex_co);
- }
+ copy_v3_v3(out->active_vertex_co, sculpt_active_vertex_co_get(ss));
copy_v3_v3(out->location, ray_normal);
mul_v3_fl(out->location, srd.depth);
@@ -6877,7 +6880,7 @@ static void sculpt_flush_update_done(const bContext *C, Object *ob, SculptUpdate
/* optimization: if there is locked key and active modifiers present in */
/* the stack, keyblock is updating at each step. otherwise we could update */
/* keyblock only when stroke is finished */
- if (ss->kb && !ss->modifiers_active) {
+ if (ss->shapekey_active && !ss->deform_modifiers_active) {
sculpt_update_keyblock(ob);
}
@@ -6970,10 +6973,10 @@ static void sculpt_stroke_update_step(bContext *C,
* Same applies to the DEG_id_tag_update() invoked from
* sculpt_flush_update_step().
*/
- if (ss->modifiers_active) {
+ if (ss->deform_modifiers_active) {
sculpt_flush_stroke_deform(sd, ob, sculpt_tool_is_proxy_used(brush->sculpt_tool));
}
- else if (ss->kb) {
+ else if (ss->shapekey_active) {
sculpt_update_keyblock(ob);
}
@@ -8146,43 +8149,36 @@ static void filter_cache_init_task_cb(void *__restrict userdata,
const TaskParallelTLS *__restrict UNUSED(tls))
{
SculptThreadedTaskData *data = userdata;
- SculptSession *ss = data->ob->sculpt;
PBVHNode *node = data->nodes[i];
- PBVHVertexIter vd;
- BKE_pbvh_vertex_iter_begin(ss->pbvh, node, vd, PBVH_ITER_UNIQUE)
- {
- if (!vd.mask || (vd.mask && *vd.mask < 1.0f)) {
- data->node_mask[i] = 1;
- }
- }
- BKE_pbvh_vertex_iter_end;
-
- if (data->node_mask[i] == 1) {
- sculpt_undo_push_node(data->ob, node, SCULPT_UNDO_COORDS);
- }
+ sculpt_undo_push_node(data->ob, node, SCULPT_UNDO_COORDS);
}
static void sculpt_filter_cache_init(Object *ob, Sculpt *sd)
{
SculptSession *ss = ob->sculpt;
PBVH *pbvh = ob->sculpt->pbvh;
- PBVHNode **nodes;
- int totnode;
ss->filter_cache = MEM_callocN(sizeof(FilterCache), "filter cache");
ss->filter_cache->random_seed = rand();
+ float center[3] = {0.0f};
SculptSearchSphereData search_data = {
.original = true,
- };
- BKE_pbvh_search_gather(pbvh, NULL, &search_data, &nodes, &totnode);
+ .center = center,
+ .radius_squared = FLT_MAX,
+ .ignore_fully_masked = true,
- int *node_mask = MEM_callocN((unsigned int)totnode * sizeof(int), "node mask");
+ };
+ BKE_pbvh_search_gather(pbvh,
+ sculpt_search_sphere_cb,
+ &search_data,
+ &ss->filter_cache->nodes,
+ &ss->filter_cache->totnode);
- for (int i = 0; i < totnode; i++) {
- BKE_pbvh_node_mark_normals_update(nodes[i]);
+ for (int i = 0; i < ss->filter_cache->totnode; i++) {
+ BKE_pbvh_node_mark_normals_update(ss->filter_cache->nodes[i]);
}
/* mesh->runtime.subdiv_ccg is not available. Updating of the normals is done during drawing.
@@ -8194,40 +8190,14 @@ static void sculpt_filter_cache_init(Object *ob, Sculpt *sd)
SculptThreadedTaskData data = {
.sd = sd,
.ob = ob,
- .nodes = nodes,
- .node_mask = node_mask,
+ .nodes = ss->filter_cache->nodes,
};
- TaskParallelSettings settings;
- BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP), totnode);
- BLI_task_parallel_range(0, totnode, &data, filter_cache_init_task_cb, &settings);
-
- int tot_active_nodes = 0;
- int active_node_index = 0;
- PBVHNode **active_nodes;
-
- /* Count number of PBVH nodes that are not fully masked */
- for (int i = 0; i < totnode; i++) {
- if (node_mask[i] == 1) {
- tot_active_nodes++;
- }
- }
-
- /* Create the final list of nodes that is going to be processed in the filter */
- active_nodes = MEM_callocN(tot_active_nodes * sizeof(PBVHNode *), "active nodes");
-
- for (int i = 0; i < totnode; i++) {
- if (node_mask[i] == 1) {
- active_nodes[active_node_index] = nodes[i];
- active_node_index++;
- }
- }
-
- ss->filter_cache->nodes = active_nodes;
- ss->filter_cache->totnode = tot_active_nodes;
-
- MEM_SAFE_FREE(nodes);
- MEM_SAFE_FREE(node_mask);
+ PBVHParallelSettings settings;
+ BKE_pbvh_parallel_range_settings(
+ &settings, (sd->flags & SCULPT_USE_OPENMP), ss->filter_cache->totnode);
+ BKE_pbvh_parallel_range(
+ 0, ss->filter_cache->totnode, &data, filter_cache_init_task_cb, &settings);
}
static void sculpt_filter_cache_free(SculptSession *ss)
@@ -8299,6 +8269,11 @@ static void mesh_filter_task_cb(void *__restrict userdata,
float fade = vd.mask ? *vd.mask : 0.0f;
fade = 1 - fade;
fade *= data->filter_strength;
+
+ if (fade == 0.0f) {
+ continue;
+ }
+
copy_v3_v3(orig_co, orig_data.co);
switch (filter_type) {
case MESH_FILTER_SMOOTH:
@@ -8417,12 +8392,12 @@ static int sculpt_mesh_filter_modal(bContext *C, wmOperator *op, const wmEvent *
.filter_strength = filter_strength,
};
- TaskParallelSettings settings;
+ PBVHParallelSettings settings;
BKE_pbvh_parallel_range_settings(
&settings, (sd->flags & SCULPT_USE_OPENMP), ss->filter_cache->totnode);
- BLI_task_parallel_range(0, ss->filter_cache->totnode, &data, mesh_filter_task_cb, &settings);
+ BKE_pbvh_parallel_range(0, ss->filter_cache->totnode, &data, mesh_filter_task_cb, &settings);
- if (ss->modifiers_active || ss->kb) {
+ if (ss->deform_modifiers_active || ss->shapekey_active) {
sculpt_flush_stroke_deform(sd, ob, true);
}
@@ -8440,10 +8415,6 @@ static int sculpt_mesh_filter_invoke(bContext *C, wmOperator *op, const wmEvent
SculptSession *ss = ob->sculpt;
PBVH *pbvh = ob->sculpt->pbvh;
- if (BKE_pbvh_type(ss->pbvh) == PBVH_GRIDS) {
- return OPERATOR_CANCELLED;
- }
-
int deform_axis = RNA_enum_get(op->ptr, "deform_axis");
if (deform_axis == 0) {
return OPERATOR_CANCELLED;
@@ -8654,10 +8625,6 @@ static int sculpt_mask_filter_exec(bContext *C, wmOperator *op)
int totnode;
int filter_type = RNA_enum_get(op->ptr, "filter_type");
- if (BKE_pbvh_type(ss->pbvh) == PBVH_GRIDS) {
- return OPERATOR_CANCELLED;
- }
-
BKE_sculpt_update_object_for_edit(depsgraph, ob, true, true);
sculpt_vertex_random_access_init(ss);
@@ -8702,9 +8669,9 @@ static int sculpt_mask_filter_exec(bContext *C, wmOperator *op)
.prev_mask = prev_mask,
};
- TaskParallelSettings settings;
+ PBVHParallelSettings settings;
BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP), totnode);
- BLI_task_parallel_range(0, totnode, &data, mask_filter_task_cb, &settings);
+ BKE_pbvh_parallel_range(0, totnode, &data, mask_filter_task_cb, &settings);
if (ELEM(filter_type, MASK_FILTER_GROW, MASK_FILTER_SHRINK)) {
MEM_freeN(prev_mask);
@@ -8813,13 +8780,14 @@ static void dirty_mask_compute_range_task_cb(void *__restrict userdata,
BKE_pbvh_vertex_iter_end;
}
-static void dirty_mask_compute_range_finalize(void *__restrict userdata, void *__restrict tls)
+static void dirty_mask_compute_range_reduce(const void *__restrict UNUSED(userdata),
+ void *__restrict chunk_join,
+ void *__restrict chunk)
{
- SculptThreadedTaskData *data = userdata;
- DirtyMaskRangeData *range = tls;
-
- data->dirty_mask_min = min_ff(range->min, data->dirty_mask_min);
- data->dirty_mask_max = max_ff(range->max, data->dirty_mask_max);
+ DirtyMaskRangeData *join = chunk_join;
+ DirtyMaskRangeData *range = chunk;
+ join->min = min_ff(range->min, join->min);
+ join->max = max_ff(range->max, join->max);
}
static void dirty_mask_apply_task_cb(void *__restrict userdata,
@@ -8871,10 +8839,6 @@ static int sculpt_dirty_mask_exec(bContext *C, wmOperator *op)
Sculpt *sd = CTX_data_tool_settings(C)->sculpt;
int totnode;
- if (BKE_pbvh_type(ss->pbvh) == PBVH_GRIDS) {
- return OPERATOR_CANCELLED;
- }
-
BKE_sculpt_update_object_for_edit(depsgraph, ob, true, true);
sculpt_vertex_random_access_init(ss);
@@ -8894,8 +8858,6 @@ static int sculpt_dirty_mask_exec(bContext *C, wmOperator *op)
.sd = sd,
.ob = ob,
.nodes = nodes,
- .dirty_mask_min = FLT_MAX,
- .dirty_mask_max = -FLT_MAX,
.dirty_mask_dirty_only = RNA_boolean_get(op->ptr, "dirty_only"),
};
DirtyMaskRangeData range = {
@@ -8903,15 +8865,17 @@ static int sculpt_dirty_mask_exec(bContext *C, wmOperator *op)
.max = -FLT_MAX,
};
- TaskParallelSettings settings;
+ PBVHParallelSettings settings;
BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP), totnode);
- settings.func_finalize = dirty_mask_compute_range_finalize;
+ settings.func_reduce = dirty_mask_compute_range_reduce;
settings.userdata_chunk = &range;
settings.userdata_chunk_size = sizeof(DirtyMaskRangeData);
- BLI_task_parallel_range(0, totnode, &data, dirty_mask_compute_range_task_cb, &settings);
- BLI_task_parallel_range(0, totnode, &data, dirty_mask_apply_task_cb, &settings);
+ BKE_pbvh_parallel_range(0, totnode, &data, dirty_mask_compute_range_task_cb, &settings);
+ data.dirty_mask_min = range.min;
+ data.dirty_mask_max = range.max;
+ BKE_pbvh_parallel_range(0, totnode, &data, dirty_mask_apply_task_cb, &settings);
MEM_SAFE_FREE(nodes);
@@ -9070,10 +9034,10 @@ static int sculpt_mask_expand_modal(bContext *C, wmOperator *op, const wmEvent *
int smooth_iterations = RNA_int_get(op->ptr, "smooth_iterations");
BKE_sculpt_update_object_for_edit(depsgraph, ob, true, false);
for (int i = 0; i < smooth_iterations; i++) {
- TaskParallelSettings settings;
+ PBVHParallelSettings settings;
BKE_pbvh_parallel_range_settings(
&settings, (sd->flags & SCULPT_USE_OPENMP), ss->filter_cache->totnode);
- BLI_task_parallel_range(0, ss->filter_cache->totnode, &data, mask_filter_task_cb, &settings);
+ BKE_pbvh_parallel_range(0, ss->filter_cache->totnode, &data, mask_filter_task_cb, &settings);
}
/* Pivot position */
@@ -9139,10 +9103,10 @@ static int sculpt_mask_expand_modal(bContext *C, wmOperator *op, const wmEvent *
.mask_expand_invert_mask = RNA_boolean_get(op->ptr, "invert"),
.mask_expand_keep_prev_mask = RNA_boolean_get(op->ptr, "keep_previous_mask"),
};
- TaskParallelSettings settings;
+ PBVHParallelSettings settings;
BKE_pbvh_parallel_range_settings(
&settings, (sd->flags & SCULPT_USE_OPENMP), ss->filter_cache->totnode);
- BLI_task_parallel_range(0, ss->filter_cache->totnode, &data, sculpt_expand_task_cb, &settings);
+ BKE_pbvh_parallel_range(0, ss->filter_cache->totnode, &data, sculpt_expand_task_cb, &settings);
ss->filter_cache->mask_update_current_it = mask_expand_update_it;
}
@@ -9157,26 +9121,37 @@ typedef struct MaskExpandFloodFillData {
bool use_normals;
} MaskExpandFloodFillData;
-static bool mask_expand_floodfill_cb(SculptSession *ss,
- const SculptFloodFillIterator *from,
- SculptFloodFillIterator *to,
- void *userdata)
+static bool mask_expand_floodfill_cb(
+ SculptSession *ss, int from_v, int to_v, bool is_duplicate, void *userdata)
{
MaskExpandFloodFillData *data = userdata;
- ss->filter_cache->mask_update_it[to->v] = to->it;
- if (to->it > ss->filter_cache->mask_update_last_it) {
- ss->filter_cache->mask_update_last_it = to->it;
- }
+ if (!is_duplicate) {
+ int to_it = ss->filter_cache->mask_update_it[from_v] + 1;
+ ss->filter_cache->mask_update_it[to_v] = to_it;
+ if (to_it > ss->filter_cache->mask_update_last_it) {
+ ss->filter_cache->mask_update_last_it = to_it;
+ }
- if (data->use_normals) {
- float current_normal[3], prev_normal[3];
- sculpt_vertex_normal_get(ss, to->v, current_normal);
- sculpt_vertex_normal_get(ss, from->v, prev_normal);
- to->edge_factor = dot_v3v3(current_normal, prev_normal) * from->edge_factor;
- ss->filter_cache->normal_factor[to->v] = dot_v3v3(data->original_normal, current_normal) *
- powf(from->edge_factor, data->edge_sensitivity);
- CLAMP(ss->filter_cache->normal_factor[to->v], 0.0f, 1.0f);
+ if (data->use_normals) {
+ float current_normal[3], prev_normal[3];
+ sculpt_vertex_normal_get(ss, to_v, current_normal);
+ sculpt_vertex_normal_get(ss, from_v, prev_normal);
+ const float from_edge_factor = ss->filter_cache->edge_factor[from_v];
+ ss->filter_cache->edge_factor[to_v] = dot_v3v3(current_normal, prev_normal) *
+ from_edge_factor;
+ ss->filter_cache->normal_factor[to_v] = dot_v3v3(data->original_normal, current_normal) *
+ powf(from_edge_factor, data->edge_sensitivity);
+ CLAMP(ss->filter_cache->normal_factor[to_v], 0.0f, 1.0f);
+ }
+ }
+ else {
+ /* PBVH_GRIDS duplicate handling */
+ ss->filter_cache->mask_update_it[to_v] = ss->filter_cache->mask_update_it[from_v];
+ if (data->use_normals) {
+ ss->filter_cache->edge_factor[to_v] = ss->filter_cache->edge_factor[from_v];
+ ss->filter_cache->normal_factor[to_v] = ss->filter_cache->normal_factor[from_v];
+ }
}
return true;
@@ -9197,10 +9172,6 @@ static int sculpt_mask_expand_invoke(bContext *C, wmOperator *op, const wmEvent
mouse[0] = event->mval[0];
mouse[1] = event->mval[1];
- if (BKE_pbvh_type(ss->pbvh) == PBVH_GRIDS) {
- return OPERATOR_CANCELLED;
- }
-
sculpt_vertex_random_access_init(ss);
op->customdata = MEM_mallocN(2 * sizeof(float), "initial mouse position");
@@ -9228,6 +9199,11 @@ static int sculpt_mask_expand_invoke(bContext *C, wmOperator *op, const wmEvent
if (use_normals) {
ss->filter_cache->normal_factor = MEM_callocN(sizeof(float) * vertex_count,
"mask update normal factor");
+ ss->filter_cache->edge_factor = MEM_callocN(sizeof(float) * vertex_count,
+ "mask update normal factor");
+ for (int i = 0; i < vertex_count; i++) {
+ ss->filter_cache->edge_factor[i] = 1.0f;
+ }
}
ss->filter_cache->prev_mask = MEM_callocN(sizeof(float) * vertex_count, "prev mask");
@@ -9266,6 +9242,8 @@ static int sculpt_mask_expand_invoke(bContext *C, wmOperator *op, const wmEvent
ss->filter_cache->normal_factor[i] = avg / ni.size;
}
}
+
+ MEM_SAFE_FREE(ss->filter_cache->edge_factor);
}
SculptThreadedTaskData data = {
@@ -9277,10 +9255,10 @@ static int sculpt_mask_expand_invoke(bContext *C, wmOperator *op, const wmEvent
.mask_expand_invert_mask = RNA_boolean_get(op->ptr, "invert"),
.mask_expand_keep_prev_mask = RNA_boolean_get(op->ptr, "keep_previous_mask"),
};
- TaskParallelSettings settings;
+ PBVHParallelSettings settings;
BKE_pbvh_parallel_range_settings(
&settings, (sd->flags & SCULPT_USE_OPENMP), ss->filter_cache->totnode);
- BLI_task_parallel_range(0, ss->filter_cache->totnode, &data, sculpt_expand_task_cb, &settings);
+ BKE_pbvh_parallel_range(0, ss->filter_cache->totnode, &data, sculpt_expand_task_cb, &settings);
const char *status_str = TIP_(
"Move the mouse to expand the mask from the active vertex. LBM: confirm mask, ESC/RMB: "
@@ -9594,13 +9572,13 @@ void ED_sculpt_update_modal_transform(struct bContext *C)
mul_m4_m4m4(data.transform_mats[i], pivot_mat, data.transform_mats[i]);
}
- TaskParallelSettings settings;
+ PBVHParallelSettings settings;
BKE_pbvh_parallel_range_settings(
&settings, (sd->flags & SCULPT_USE_OPENMP), ss->filter_cache->totnode);
- BLI_task_parallel_range(
+ BKE_pbvh_parallel_range(
0, ss->filter_cache->totnode, &data, sculpt_transform_task_cb, &settings);
- if (ss->modifiers_active || ss->kb) {
+ if (ss->deform_modifiers_active || ss->shapekey_active) {
sculpt_flush_stroke_deform(sd, ob, true);
}
diff --git a/source/blender/editors/sculpt_paint/sculpt_intern.h b/source/blender/editors/sculpt_paint/sculpt_intern.h
index e9af49a0b5a..93e4a777569 100644
--- a/source/blender/editors/sculpt_paint/sculpt_intern.h
+++ b/source/blender/editors/sculpt_paint/sculpt_intern.h
@@ -194,12 +194,9 @@ typedef struct SculptThreadedTaskData {
int filter_type;
float filter_strength;
- int *node_mask;
- /* 0=towards view, 1=flipped */
- float (*area_cos)[3];
- float (*area_nos)[3];
- int *count;
+ bool use_area_cos;
+ bool use_area_nos;
bool any_vertex_sampled;
float *prev_mask;
@@ -209,13 +206,8 @@ typedef struct SculptThreadedTaskData {
float *pose_factor;
float (*transform_rot)[4], (*transform_trans)[4], (*transform_trans_inv)[4];
- float tot_pos_avg[3];
- int tot_pos_count;
-
float max_distance_squared;
float nearest_vertex_search_co[3];
- int nearest_vertex_index;
- float nearest_vertex_distance_squared;
int mask_expand_update_it;
bool mask_expand_invert_mask;
@@ -418,6 +410,7 @@ typedef struct FilterCache {
int mask_update_last_it;
int *mask_update_it;
float *normal_factor;
+ float *edge_factor;
float *prev_mask;
float mask_expand_initial_co[3];
} FilterCache;
diff --git a/source/blender/editors/sculpt_paint/sculpt_undo.c b/source/blender/editors/sculpt_paint/sculpt_undo.c
index 788d07f6e78..5d95cc80280 100644
--- a/source/blender/editors/sculpt_paint/sculpt_undo.c
+++ b/source/blender/editors/sculpt_paint/sculpt_undo.c
@@ -86,6 +86,7 @@ static void update_cb(PBVHNode *node, void *rebuild)
struct PartialUpdateData {
PBVH *pbvh;
bool rebuild;
+ char *modified_grids;
};
/**
@@ -94,8 +95,24 @@ struct PartialUpdateData {
static void update_cb_partial(PBVHNode *node, void *userdata)
{
struct PartialUpdateData *data = userdata;
- if (BKE_pbvh_node_vert_update_check_any(data->pbvh, node)) {
- update_cb(node, &(data->rebuild));
+ if (BKE_pbvh_type(data->pbvh) == PBVH_GRIDS) {
+ int *node_grid_indices;
+ int totgrid;
+ bool update = false;
+ BKE_pbvh_node_get_grids(data->pbvh, node, &node_grid_indices, &totgrid, NULL, NULL, NULL);
+ for (int i = 0; i < totgrid; i++) {
+ if (data->modified_grids[node_grid_indices[i]] == 1) {
+ update = true;
+ }
+ }
+ if (update) {
+ update_cb(node, &(data->rebuild));
+ }
+ }
+ else {
+ if (BKE_pbvh_node_vert_update_check_any(data->pbvh, node)) {
+ update_cb(node, &(data->rebuild));
+ }
}
}
@@ -135,7 +152,7 @@ static bool sculpt_undo_restore_coords(bContext *C, Depsgraph *depsgraph, Sculpt
if (unode->maxvert) {
/* regular mesh restore */
- if (ss->kb && !STREQ(ss->kb->name, unode->shapeName)) {
+ if (ss->shapekey_active && !STREQ(ss->shapekey_active->name, unode->shapeName)) {
/* shape key has been changed before calling undo operator */
Key *key = BKE_key_from_object(ob);
@@ -157,12 +174,12 @@ static bool sculpt_undo_restore_coords(bContext *C, Depsgraph *depsgraph, Sculpt
index = unode->index;
mvert = ss->mvert;
- if (ss->kb) {
+ if (ss->shapekey_active) {
float(*vertCos)[3];
- vertCos = BKE_keyblock_convert_to_vertcos(ob, ss->kb);
+ vertCos = BKE_keyblock_convert_to_vertcos(ob, ss->shapekey_active);
if (unode->orig_co) {
- if (ss->modifiers_active) {
+ if (ss->deform_modifiers_active) {
for (int i = 0; i < unode->totvert; i++) {
sculpt_undo_restore_deformed(ss, unode, i, index[i], vertCos[index[i]]);
}
@@ -180,36 +197,33 @@ static bool sculpt_undo_restore_coords(bContext *C, Depsgraph *depsgraph, Sculpt
}
/* propagate new coords to keyblock */
- sculpt_vertcos_to_key(ob, ss->kb, vertCos);
+ sculpt_vertcos_to_key(ob, ss->shapekey_active, vertCos);
/* pbvh uses it's own mvert array, so coords should be */
/* propagated to pbvh here */
- BKE_pbvh_vert_coords_apply(ss->pbvh, vertCos, ss->kb->totelem);
+ BKE_pbvh_vert_coords_apply(ss->pbvh, vertCos, ss->shapekey_active->totelem);
MEM_freeN(vertCos);
}
else {
if (unode->orig_co) {
- if (ss->modifiers_active) {
+ if (ss->deform_modifiers_active) {
for (int i = 0; i < unode->totvert; i++) {
- if (sculpt_undo_restore_deformed(ss, unode, i, index[i], mvert[index[i]].co)) {
- mvert[index[i]].flag |= ME_VERT_PBVH_UPDATE;
- }
+ sculpt_undo_restore_deformed(ss, unode, i, index[i], mvert[index[i]].co);
+ mvert[index[i]].flag |= ME_VERT_PBVH_UPDATE;
}
}
else {
for (int i = 0; i < unode->totvert; i++) {
- if (test_swap_v3_v3(mvert[index[i]].co, unode->orig_co[i])) {
- mvert[index[i]].flag |= ME_VERT_PBVH_UPDATE;
- }
+ swap_v3_v3(mvert[index[i]].co, unode->orig_co[i]);
+ mvert[index[i]].flag |= ME_VERT_PBVH_UPDATE;
}
}
}
else {
for (int i = 0; i < unode->totvert; i++) {
- if (test_swap_v3_v3(mvert[index[i]].co, unode->co[i])) {
- mvert[index[i]].flag |= ME_VERT_PBVH_UPDATE;
- }
+ swap_v3_v3(mvert[index[i]].co, unode->co[i]);
+ mvert[index[i]].flag |= ME_VERT_PBVH_UPDATE;
}
}
}
@@ -346,9 +360,9 @@ static void sculpt_undo_bmesh_restore_generic(bContext *C,
BKE_pbvh_search_gather(ss->pbvh, NULL, NULL, &nodes, &totnode);
- TaskParallelSettings settings;
+ PBVHParallelSettings settings;
BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP), totnode);
- BLI_task_parallel_range(
+ BKE_pbvh_parallel_range(
0, totnode, nodes, sculpt_undo_bmesh_restore_generic_task_cb, &settings);
if (nodes) {
@@ -485,7 +499,6 @@ static void sculpt_undo_restore_list(bContext *C, Depsgraph *depsgraph, ListBase
SculptUndoNode *unode;
bool update = false, rebuild = false;
bool need_mask = false;
- bool partial_update = true;
for (unode = lb->first; unode; unode = unode->next) {
/* restore pivot */
@@ -527,6 +540,9 @@ static void sculpt_undo_restore_list(bContext *C, Depsgraph *depsgraph, ListBase
return;
}
+ char *undo_modified_grids = NULL;
+ bool use_multires_undo = false;
+
for (unode = lb->first; unode; unode = unode->next) {
if (!STREQ(unode->idname, ob->id.name)) {
@@ -546,8 +562,7 @@ static void sculpt_undo_restore_list(bContext *C, Depsgraph *depsgraph, ListBase
continue;
}
- /* multi-res can't do partial updates since it doesn't flag edited vertices */
- partial_update = false;
+ use_multires_undo = true;
}
switch (unode->type) {
@@ -577,21 +592,29 @@ static void sculpt_undo_restore_list(bContext *C, Depsgraph *depsgraph, ListBase
}
}
+ if (use_multires_undo) {
+ int max_grid;
+ unode = lb->first;
+ max_grid = unode->maxgrid;
+ undo_modified_grids = MEM_callocN(sizeof(char) * max_grid, "undo_grids");
+ for (unode = lb->first; unode; unode = unode->next) {
+ for (int i = 0; i < unode->totgrid; i++) {
+ undo_modified_grids[unode->grids[i]] = 1;
+ }
+ }
+ }
+
if (update || rebuild) {
bool tag_update = false;
/* we update all nodes still, should be more clever, but also
* needs to work correct when exiting/entering sculpt mode and
* the nodes get recreated, though in that case it could do all */
- if (partial_update) {
- struct PartialUpdateData data = {
- .rebuild = rebuild,
- .pbvh = ss->pbvh,
- };
- BKE_pbvh_search_callback(ss->pbvh, NULL, NULL, update_cb_partial, &data);
- }
- else {
- BKE_pbvh_search_callback(ss->pbvh, NULL, NULL, update_cb, &rebuild);
- }
+ struct PartialUpdateData data = {
+ .rebuild = rebuild,
+ .pbvh = ss->pbvh,
+ .modified_grids = undo_modified_grids,
+ };
+ BKE_pbvh_search_callback(ss->pbvh, NULL, NULL, update_cb_partial, &data);
BKE_pbvh_update_bounds(ss->pbvh, PBVH_UpdateBB | PBVH_UpdateOriginalBB | PBVH_UpdateRedraw);
if (BKE_sculpt_multires_active(scene, ob)) {
@@ -605,7 +628,7 @@ static void sculpt_undo_restore_list(bContext *C, Depsgraph *depsgraph, ListBase
tag_update |= ((Mesh *)ob->data)->id.us > 1 || !BKE_sculptsession_use_pbvh_draw(ob, v3d);
- if (ss->kb || ss->modifiers_active) {
+ if (ss->shapekey_active || ss->deform_modifiers_active) {
Mesh *mesh = ob->data;
BKE_mesh_calc_normals(mesh);
@@ -620,6 +643,8 @@ static void sculpt_undo_restore_list(bContext *C, Depsgraph *depsgraph, ListBase
sculpt_update_object_bounding_box(ob);
}
}
+
+ MEM_SAFE_FREE(undo_modified_grids);
}
static void sculpt_undo_free_list(ListBase *lb)
@@ -806,7 +831,7 @@ static SculptUndoNode *sculpt_undo_alloc_node(Object *ob, PBVHNode *node, Sculpt
unode->index = MEM_mapallocN(sizeof(int) * allvert, "SculptUndoNode.index");
}
- if (ss->modifiers_active) {
+ if (ss->deform_modifiers_active) {
unode->orig_co = MEM_callocN(allvert * sizeof(*unode->orig_co), "undoSculpt orig_cos");
}
@@ -828,7 +853,7 @@ static void sculpt_undo_store_coords(Object *ob, SculptUndoNode *unode)
normal_float_to_short_v3(unode->no[vd.i], vd.fno);
}
- if (ss->modifiers_active) {
+ if (ss->deform_modifiers_active) {
copy_v3_v3(unode->orig_co[vd.i], ss->orig_cos[unode->index[vd.i]]);
}
}
@@ -1057,8 +1082,8 @@ SculptUndoNode *sculpt_undo_push_node(Object *ob, PBVHNode *node, SculptUndoType
copy_v3_v3(unode->pivot_rot, ss->pivot_rot);
/* store active shape key */
- if (ss->kb) {
- BLI_strncpy(unode->shapeName, ss->kb->name, sizeof(ss->kb->name));
+ if (ss->shapekey_active) {
+ BLI_strncpy(unode->shapeName, ss->shapekey_active->name, sizeof(ss->shapekey_active->name));
}
else {
unode->shapeName[0] = '\0';
diff --git a/source/blender/editors/sound/sound_ops.c b/source/blender/editors/sound/sound_ops.c
index 4e710d31cbb..69745663c02 100644
--- a/source/blender/editors/sound/sound_ops.c
+++ b/source/blender/editors/sound/sound_ops.c
@@ -273,8 +273,11 @@ static void sound_update_animation_flags(Scene *scene)
static int sound_update_animation_flags_exec(bContext *C, wmOperator *UNUSED(op))
{
+ Scene *scene = CTX_data_scene(C);
+
BKE_main_id_tag_idcode(CTX_data_main(C), ID_SCE, LIB_TAG_DOIT, false);
sound_update_animation_flags(CTX_data_scene(C));
+ DEG_id_tag_update(&scene->id, ID_RECALC_SEQUENCER_STRIPS);
return OPERATOR_FINISHED;
}
diff --git a/source/blender/editors/space_action/action_select.c b/source/blender/editors/space_action/action_select.c
index 4a4ff5f5605..ca6efb5f69e 100644
--- a/source/blender/editors/space_action/action_select.c
+++ b/source/blender/editors/space_action/action_select.c
@@ -153,7 +153,8 @@ static void actkeys_find_key_in_list_element(bAnimContext *ac,
float region_x,
float *r_selx,
float *r_frame,
- bool *r_found)
+ bool *r_found,
+ bool *r_is_selected)
{
*r_found = false;
@@ -182,6 +183,7 @@ static void actkeys_find_key_in_list_element(bAnimContext *ac,
*r_selx = BKE_nla_tweakedit_remap(adt, ak->cfra, NLATIME_CONVERT_UNMAP);
*r_frame = ak->cfra;
*r_found = true;
+ *r_is_selected = (ak->sel & SELECT) != 0;
break;
}
}
@@ -197,14 +199,16 @@ static void actkeys_find_key_at_position(bAnimContext *ac,
bAnimListElem **r_ale,
float *r_selx,
float *r_frame,
- bool *r_found)
+ bool *r_found,
+ bool *r_is_selected)
{
*r_found = false;
*r_ale = actkeys_find_list_element_at_position(ac, filter, region_x, region_y);
if (*r_ale != NULL) {
- actkeys_find_key_in_list_element(ac, *r_ale, region_x, r_selx, r_frame, r_found);
+ actkeys_find_key_in_list_element(
+ ac, *r_ale, region_x, r_selx, r_frame, r_found, r_is_selected);
}
}
@@ -213,9 +217,11 @@ static bool actkeys_is_key_at_position(bAnimContext *ac, float region_x, float r
bAnimListElem *ale;
float selx, frame;
bool found;
+ bool is_selected;
int filter = ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_LIST_CHANNELS;
- actkeys_find_key_at_position(ac, filter, region_x, region_y, &ale, &selx, &frame, &found);
+ actkeys_find_key_at_position(
+ ac, filter, region_x, region_y, &ale, &selx, &frame, &found, &is_selected);
if (ale != NULL) {
MEM_freeN(ale);
@@ -1681,20 +1687,29 @@ static void actkeys_mselect_channel_only(bAnimContext *ac, bAnimListElem *ale, s
/* ------------------- */
-static void mouse_action_keys(bAnimContext *ac,
- const int mval[2],
- short select_mode,
- const bool deselect_all,
- const bool column,
- const bool same_channel)
+static int mouse_action_keys(bAnimContext *ac,
+ const int mval[2],
+ short select_mode,
+ const bool deselect_all,
+ const bool column,
+ const bool same_channel,
+ bool wait_to_deselect_others)
{
int filter = ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_LIST_CHANNELS;
bAnimListElem *ale = NULL;
bool found = false;
+ bool is_selected = false;
float frame = 0.0f; /* frame of keyframe under mouse - NLA corrections not applied/included */
float selx = 0.0f; /* frame of keyframe under mouse */
- actkeys_find_key_at_position(ac, filter, mval[0], mval[1], &ale, &selx, &frame, &found);
+ int ret_value = OPERATOR_FINISHED;
+
+ actkeys_find_key_at_position(
+ ac, filter, mval[0], mval[1], &ale, &selx, &frame, &found, &is_selected);
+
+ if (select_mode != SELECT_REPLACE) {
+ wait_to_deselect_others = false;
+ }
/* For replacing selection, if we have something to select, we have to clear existing selection.
* The same goes if we found nothing to select, and deselect_all is true
@@ -1703,56 +1718,61 @@ static void mouse_action_keys(bAnimContext *ac,
/* reset selection mode for next steps */
select_mode = SELECT_ADD;
- /* deselect all keyframes */
- deselect_action_keys(ac, 0, SELECT_SUBTRACT);
-
- /* highlight channel clicked on */
- if (ELEM(ac->datatype, ANIMCONT_ACTION, ANIMCONT_DOPESHEET, ANIMCONT_TIMELINE)) {
- /* deselect all other channels first */
- ANIM_deselect_anim_channels(ac, ac->data, ac->datatype, 0, ACHANNEL_SETFLAG_CLEAR);
-
- /* Highlight Action-Group or F-Curve? */
- if (ale != NULL && ale->data) {
- if (ale->type == ANIMTYPE_GROUP) {
- bActionGroup *agrp = ale->data;
-
- agrp->flag |= AGRP_SELECTED;
- ANIM_set_active_channel(ac, ac->data, ac->datatype, filter, agrp, ANIMTYPE_GROUP);
- }
- else if (ELEM(ale->type, ANIMTYPE_FCURVE, ANIMTYPE_NLACURVE)) {
- FCurve *fcu = ale->data;
-
- fcu->flag |= FCURVE_SELECTED;
- ANIM_set_active_channel(ac, ac->data, ac->datatype, filter, fcu, ale->type);
+ if (wait_to_deselect_others && is_selected) {
+ ret_value = OPERATOR_RUNNING_MODAL;
+ }
+ else {
+ /* deselect all keyframes */
+ deselect_action_keys(ac, 0, SELECT_SUBTRACT);
+
+ /* highlight channel clicked on */
+ if (ELEM(ac->datatype, ANIMCONT_ACTION, ANIMCONT_DOPESHEET, ANIMCONT_TIMELINE)) {
+ /* deselect all other channels first */
+ ANIM_deselect_anim_channels(ac, ac->data, ac->datatype, 0, ACHANNEL_SETFLAG_CLEAR);
+
+ /* Highlight Action-Group or F-Curve? */
+ if (ale != NULL && ale->data) {
+ if (ale->type == ANIMTYPE_GROUP) {
+ bActionGroup *agrp = ale->data;
+
+ agrp->flag |= AGRP_SELECTED;
+ ANIM_set_active_channel(ac, ac->data, ac->datatype, filter, agrp, ANIMTYPE_GROUP);
+ }
+ else if (ELEM(ale->type, ANIMTYPE_FCURVE, ANIMTYPE_NLACURVE)) {
+ FCurve *fcu = ale->data;
+
+ fcu->flag |= FCURVE_SELECTED;
+ ANIM_set_active_channel(ac, ac->data, ac->datatype, filter, fcu, ale->type);
+ }
}
}
- }
- else if (ac->datatype == ANIMCONT_GPENCIL) {
- /* deselect all other channels first */
- ANIM_deselect_anim_channels(ac, ac->data, ac->datatype, 0, ACHANNEL_SETFLAG_CLEAR);
-
- /* Highlight GPencil Layer */
- if (ale != NULL && ale->data != NULL && ale->type == ANIMTYPE_GPLAYER) {
- bGPdata *gpd = (bGPdata *)ale->id;
- bGPDlayer *gpl = ale->data;
-
- gpl->flag |= GP_LAYER_SELECT;
- /* Update other layer status. */
- if (BKE_gpencil_layer_getactive(gpd) != gpl) {
- BKE_gpencil_layer_setactive(gpd, gpl);
- BKE_gpencil_layer_autolock_set(gpd, false);
- WM_main_add_notifier(NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
+ else if (ac->datatype == ANIMCONT_GPENCIL) {
+ /* deselect all other channels first */
+ ANIM_deselect_anim_channels(ac, ac->data, ac->datatype, 0, ACHANNEL_SETFLAG_CLEAR);
+
+ /* Highlight GPencil Layer */
+ if (ale != NULL && ale->data != NULL && ale->type == ANIMTYPE_GPLAYER) {
+ bGPdata *gpd = (bGPdata *)ale->id;
+ bGPDlayer *gpl = ale->data;
+
+ gpl->flag |= GP_LAYER_SELECT;
+ /* Update other layer status. */
+ if (BKE_gpencil_layer_getactive(gpd) != gpl) {
+ BKE_gpencil_layer_setactive(gpd, gpl);
+ BKE_gpencil_layer_autolock_set(gpd, false);
+ WM_main_add_notifier(NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
+ }
}
}
- }
- else if (ac->datatype == ANIMCONT_MASK) {
- /* deselect all other channels first */
- ANIM_deselect_anim_channels(ac, ac->data, ac->datatype, 0, ACHANNEL_SETFLAG_CLEAR);
+ else if (ac->datatype == ANIMCONT_MASK) {
+ /* deselect all other channels first */
+ ANIM_deselect_anim_channels(ac, ac->data, ac->datatype, 0, ACHANNEL_SETFLAG_CLEAR);
- if (ale != NULL && ale->data != NULL && ale->type == ANIMTYPE_MASKLAYER) {
- MaskLayer *masklay = ale->data;
+ if (ale != NULL && ale->data != NULL && ale->type == ANIMTYPE_MASKLAYER) {
+ MaskLayer *masklay = ale->data;
- masklay->flag |= MASK_LAYERFLAG_SELECT;
+ masklay->flag |= MASK_LAYERFLAG_SELECT;
+ }
}
}
}
@@ -1787,12 +1807,15 @@ static void mouse_action_keys(bAnimContext *ac,
/* free this channel */
MEM_freeN(ale);
}
+
+ return ret_value;
}
/* handle clicking */
-static int actkeys_clickselect_invoke(bContext *C, wmOperator *op, const wmEvent *event)
+static int actkeys_clickselect_exec(bContext *C, wmOperator *op)
{
bAnimContext ac;
+ int ret_value;
/* get editor data */
if (ANIM_animdata_get_context(C, &ac) == 0) {
@@ -1805,20 +1828,26 @@ static int actkeys_clickselect_invoke(bContext *C, wmOperator *op, const wmEvent
/* select mode is either replace (deselect all, then add) or add/extend */
const short selectmode = RNA_boolean_get(op->ptr, "extend") ? SELECT_INVERT : SELECT_REPLACE;
const bool deselect_all = RNA_boolean_get(op->ptr, "deselect_all");
+ const bool wait_to_deselect_others = RNA_boolean_get(op->ptr, "wait_to_deselect_others");
+ int mval[2];
/* column selection */
const bool column = RNA_boolean_get(op->ptr, "column");
const bool channel = RNA_boolean_get(op->ptr, "channel");
+ mval[0] = RNA_int_get(op->ptr, "mouse_x");
+ mval[1] = RNA_int_get(op->ptr, "mouse_y");
+
/* select keyframe(s) based upon mouse position*/
- mouse_action_keys(&ac, event->mval, selectmode, deselect_all, column, channel);
+ ret_value = mouse_action_keys(
+ &ac, mval, selectmode, deselect_all, column, channel, wait_to_deselect_others);
/* set notifier that keyframe selection (and channels too) have changed */
WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_SELECTED, NULL);
WM_event_add_notifier(C, NC_ANIMATION | ND_ANIMCHAN | NA_SELECTED, NULL);
/* for tweak grab to work */
- return OPERATOR_FINISHED | OPERATOR_PASS_THROUGH;
+ return ret_value | OPERATOR_PASS_THROUGH;
}
void ACTION_OT_clickselect(wmOperatorType *ot)
@@ -1831,13 +1860,16 @@ void ACTION_OT_clickselect(wmOperatorType *ot)
ot->description = "Select keyframes by clicking on them";
/* callbacks */
- ot->invoke = actkeys_clickselect_invoke;
ot->poll = ED_operator_action_active;
+ ot->exec = actkeys_clickselect_exec;
+ ot->invoke = WM_generic_select_invoke;
+ ot->modal = WM_generic_select_modal;
/* flags */
ot->flag = OPTYPE_UNDO;
/* properties */
+ WM_operator_properties_generic_select(ot);
prop = RNA_def_boolean(
ot->srna,
"extend",
diff --git a/source/blender/editors/space_clip/tracking_ops_solve.c b/source/blender/editors/space_clip/tracking_ops_solve.c
index 1d2fc239a89..7e2671382b9 100644
--- a/source/blender/editors/space_clip/tracking_ops_solve.c
+++ b/source/blender/editors/space_clip/tracking_ops_solve.c
@@ -118,7 +118,11 @@ static void solve_camera_freejob(void *scv)
MovieClip *clip = scj->clip;
int solved;
- WM_set_locked_interface(scj->wm, false);
+ /* WindowManager is missing in the job when initialization is incomplete.
+ * In this case the interface is not locked either. */
+ if (scj->wm != NULL) {
+ WM_set_locked_interface(scj->wm, false);
+ }
if (!scj->context) {
/* job weren't fully initialized due to some error */
diff --git a/source/blender/editors/space_file/file_ops.c b/source/blender/editors/space_file/file_ops.c
index b4b51de302d..3cdcc07f081 100644
--- a/source/blender/editors/space_file/file_ops.c
+++ b/source/blender/editors/space_file/file_ops.c
@@ -2395,60 +2395,49 @@ void FILE_OT_filenum(struct wmOperatorType *ot)
RNA_def_int(ot->srna, "increment", 1, -100, 100, "Increment", "", -100, 100);
}
-static int file_rename_exec(bContext *C, wmOperator *UNUSED(op))
+static void file_rename_state_activate(SpaceFile *sfile, int file_idx, bool require_selected)
{
- ScrArea *sa = CTX_wm_area(C);
- SpaceFile *sfile = (SpaceFile *)CTX_wm_space_data(C);
+ const int numfiles = filelist_files_ensure(sfile->files);
- if (sfile->params) {
- int idx = sfile->params->highlight_file;
- int numfiles = filelist_files_ensure(sfile->files);
- if ((0 <= idx) && (idx < numfiles)) {
- FileDirEntry *file = filelist_file(sfile->files, idx);
+ if ((file_idx >= 0) && (file_idx < numfiles)) {
+ FileDirEntry *file = filelist_file(sfile->files, file_idx);
+
+ if ((require_selected == false) ||
+ (filelist_entry_select_get(sfile->files, file, CHECK_ALL) & FILE_SEL_SELECTED)) {
filelist_entry_select_index_set(
- sfile->files, idx, FILE_SEL_ADD, FILE_SEL_EDITING, CHECK_ALL);
+ sfile->files, file_idx, FILE_SEL_ADD, FILE_SEL_EDITING, CHECK_ALL);
BLI_strncpy(sfile->params->renamefile, file->relpath, FILE_MAXFILE);
/* We can skip the pending state,
* as we can directly set FILE_SEL_EDITING on the expected entry here. */
sfile->params->rename_flag = FILE_PARAMS_RENAME_ACTIVE;
}
+ }
+}
+
+static int file_rename_invoke(bContext *C, wmOperator *UNUSED(op), const wmEvent *UNUSED(event))
+{
+ ScrArea *sa = CTX_wm_area(C);
+ SpaceFile *sfile = (SpaceFile *)CTX_wm_space_data(C);
+
+ if (sfile->params) {
+ file_rename_state_activate(sfile, sfile->params->active_file, true);
ED_area_tag_redraw(sa);
}
return OPERATOR_FINISHED;
}
-static bool file_rename_poll(bContext *C)
+static int file_rename_exec(bContext *C, wmOperator *UNUSED(op))
{
- bool poll = ED_operator_file_active(C);
- SpaceFile *sfile = CTX_wm_space_file(C);
-
- if (sfile && sfile->params) {
- int idx = sfile->params->highlight_file;
- int numfiles = filelist_files_ensure(sfile->files);
-
- if ((0 <= idx) && (idx < numfiles)) {
- FileDirEntry *file = filelist_file(sfile->files, idx);
- if (FILENAME_IS_CURRPAR(file->relpath)) {
- poll = false;
- }
- }
+ ScrArea *sa = CTX_wm_area(C);
+ SpaceFile *sfile = (SpaceFile *)CTX_wm_space_data(C);
- if (sfile->params->highlight_file < 0) {
- poll = false;
- }
- else {
- char dir[FILE_MAX_LIBEXTRA];
- if (filelist_islibrary(sfile->files, dir, NULL)) {
- poll = false;
- }
- }
- }
- else {
- poll = false;
+ if (sfile->params) {
+ file_rename_state_activate(sfile, sfile->params->highlight_file, false);
+ ED_area_tag_redraw(sa);
}
- return poll;
+ return OPERATOR_FINISHED;
}
void FILE_OT_rename(struct wmOperatorType *ot)
@@ -2459,8 +2448,9 @@ void FILE_OT_rename(struct wmOperatorType *ot)
ot->idname = "FILE_OT_rename";
/* api callbacks */
+ ot->invoke = file_rename_invoke;
ot->exec = file_rename_exec;
- ot->poll = file_rename_poll;
+ ot->poll = ED_operator_file_active;
}
static bool file_delete_poll(bContext *C)
@@ -2504,23 +2494,29 @@ int file_delete_exec(bContext *C, wmOperator *op)
int numfiles = filelist_files_ensure(sfile->files);
int i;
+ const char *error_message = NULL;
bool report_error = false;
errno = 0;
for (i = 0; i < numfiles; i++) {
if (filelist_entry_select_index_get(sfile->files, i, CHECK_FILES)) {
file = filelist_file(sfile->files, i);
BLI_make_file_string(BKE_main_blendfile_path(bmain), str, sfile->params->dir, file->relpath);
- if (BLI_delete(str, false, false) != 0 || BLI_exists(str)) {
+ if (BLI_delete_soft(str, &error_message) != 0 || BLI_exists(str)) {
report_error = true;
}
}
}
if (report_error) {
- BKE_reportf(op->reports,
- RPT_ERROR,
- "Could not delete file: %s",
- errno ? strerror(errno) : "unknown error");
+ if (error_message != NULL) {
+ BKE_reportf(op->reports, RPT_ERROR, "Could not delete file or directory: %s", error_message);
+ }
+ else {
+ BKE_reportf(op->reports,
+ RPT_ERROR,
+ "Could not delete file or directory: %s",
+ errno ? strerror(errno) : "unknown error");
+ }
}
ED_fileselect_clear(wm, sa, sfile);
@@ -2533,7 +2529,7 @@ void FILE_OT_delete(struct wmOperatorType *ot)
{
/* identifiers */
ot->name = "Delete Selected Files";
- ot->description = "Delete selected files";
+ ot->description = "Move selected files to the trash or recycle bin";
ot->idname = "FILE_OT_delete";
/* api callbacks */
diff --git a/source/blender/editors/space_file/filelist.c b/source/blender/editors/space_file/filelist.c
index 27cccf6bab1..d29233618de 100644
--- a/source/blender/editors/space_file/filelist.c
+++ b/source/blender/editors/space_file/filelist.c
@@ -831,7 +831,7 @@ void filelist_setfilter_options(FileList *filelist,
}
if ((filelist->filter_data.filter != filter) || (filelist->filter_data.filter_id != filter_id)) {
filelist->filter_data.filter = filter;
- filelist->filter_data.filter_id = filter_id;
+ filelist->filter_data.filter_id = (filter & FILE_TYPE_BLENDERLIB) ? filter_id : FILTER_ID_ALL;
update = true;
}
if (!STREQ(filelist->filter_data.filter_glob, filter_glob)) {
diff --git a/source/blender/editors/space_file/filesel.c b/source/blender/editors/space_file/filesel.c
index e2c9bb8d6e5..ba4ccb4fba9 100644
--- a/source/blender/editors/space_file/filesel.c
+++ b/source/blender/editors/space_file/filesel.c
@@ -247,13 +247,7 @@ short ED_fileselect_set_params(SpaceFile *sfile)
}
/* For now, always init filterid to 'all true' */
- params->filter_id = FILTER_ID_AC | FILTER_ID_AR | FILTER_ID_BR | FILTER_ID_CA | FILTER_ID_CU |
- FILTER_ID_GD | FILTER_ID_GR | FILTER_ID_IM | FILTER_ID_LA | FILTER_ID_LS |
- FILTER_ID_LT | FILTER_ID_MA | FILTER_ID_MB | FILTER_ID_MC | FILTER_ID_ME |
- FILTER_ID_MSK | FILTER_ID_NT | FILTER_ID_OB | FILTER_ID_PA |
- FILTER_ID_PAL | FILTER_ID_PC | FILTER_ID_SCE | FILTER_ID_SPK |
- FILTER_ID_SO | FILTER_ID_TE | FILTER_ID_TXT | FILTER_ID_VF | FILTER_ID_WO |
- FILTER_ID_CF | FILTER_ID_WS | FILTER_ID_LP;
+ params->filter_id = FILTER_ID_ALL;
if (U.uiflag & USER_HIDE_DOT) {
params->flag |= FILE_HIDE_DOT;
@@ -362,10 +356,10 @@ void ED_fileselect_set_params_from_userdef(SpaceFile *sfile)
/**
* Update the user-preference data for the file space. In fact, this also contains some
- * non-FileSelectParams data, but it's neglectable.
+ * non-FileSelectParams data, but we can safely ignore this.
*
- * \param temp_win_size: If the browser was opened in a temporary window, pass its size here so we
- * can store that in the preferences. Otherwise NULL.
+ * \param temp_win_size: If the browser was opened in a temporary window,
+ * pass its size here so we can store that in the preferences. Otherwise NULL.
*/
void ED_fileselect_params_to_userdef(SpaceFile *sfile, int temp_win_size[2])
{
diff --git a/source/blender/editors/space_image/image_ops.c b/source/blender/editors/space_image/image_ops.c
index 39f7bf001f3..a8dfad85232 100644
--- a/source/blender/editors/space_image/image_ops.c
+++ b/source/blender/editors/space_image/image_ops.c
@@ -2298,12 +2298,7 @@ static int image_save_sequence_exec(bContext *C, wmOperator *op)
/* get a filename for menu */
BLI_split_dir_part(first_ibuf->name, di, sizeof(di));
- BKE_reportf(op->reports,
- RPT_INFO,
- tot == 1 ? "%d image will be saved in %s" :
- "%d images will be saved in %s",
- tot,
- di);
+ BKE_reportf(op->reports, RPT_INFO, "%d image(s) will be saved in %s", tot, di);
iter = IMB_moviecacheIter_new(image->cache);
while (!IMB_moviecacheIter_done(iter)) {
diff --git a/source/blender/editors/space_image/image_undo.c b/source/blender/editors/space_image/image_undo.c
index c450d5122eb..577c4e24b11 100644
--- a/source/blender/editors/space_image/image_undo.c
+++ b/source/blender/editors/space_image/image_undo.c
@@ -70,7 +70,7 @@ static CLG_LogRef LOG = {"ed.image.undo"};
/** \name Thread Locking
* \{ */
-/* this is a static resource for non-globality,
+/* This is a non-global static resource,
* Maybe it should be exposed as part of the
* paint operation, but for now just give a public interface */
static SpinLock paint_tiles_lock;
@@ -457,6 +457,31 @@ static void ubuf_from_image_all_tiles(UndoImageBuf *ubuf, const ImBuf *ibuf)
IMB_freeImBuf(tmpibuf);
}
+/** Ensure we can copy the ubuf into the ibuf. */
+static void ubuf_ensure_compat_ibuf(const UndoImageBuf *ubuf, ImBuf *ibuf)
+{
+ /* We could have both float and rect buffers,
+ * in this case free the float buffer if it's unused. */
+ if ((ibuf->rect_float != NULL) && (ubuf->image_state.use_float == false)) {
+ imb_freerectfloatImBuf(ibuf);
+ }
+
+ if (ibuf->x == ubuf->image_dims[0] && ibuf->y == ubuf->image_dims[1] &&
+ (ubuf->image_state.use_float ? (void *)ibuf->rect_float : (void *)ibuf->rect)) {
+ return;
+ }
+
+ imb_freerectImbuf_all(ibuf);
+ IMB_rect_size_set(ibuf, ubuf->image_dims);
+
+ if (ubuf->image_state.use_float) {
+ imb_addrectfloatImBuf(ibuf);
+ }
+ else {
+ imb_addrectImBuf(ibuf);
+ }
+}
+
static void ubuf_free(UndoImageBuf *ubuf)
{
UndoImageBuf *ubuf_post = ubuf->post;
@@ -510,7 +535,8 @@ static void uhandle_restore_list(ListBase *undo_handles, bool use_init)
bool changed = false;
for (UndoImageBuf *ubuf_iter = uh->buffers.first; ubuf_iter; ubuf_iter = ubuf_iter->next) {
UndoImageBuf *ubuf = use_init ? ubuf_iter : ubuf_iter->post;
- IMB_rect_size_set(ibuf, ubuf->image_dims);
+ ubuf_ensure_compat_ibuf(ubuf, ibuf);
+
int i = 0;
for (uint y_tile = 0; y_tile < ubuf->tiles_dims[1]; y_tile += 1) {
uint y = y_tile << ED_IMAGE_UNDO_TILE_BITS;
diff --git a/source/blender/editors/space_nla/nla_select.c b/source/blender/editors/space_nla/nla_select.c
index 1abf1a64263..938e7f09881 100644
--- a/source/blender/editors/space_nla/nla_select.c
+++ b/source/blender/editors/space_nla/nla_select.c
@@ -597,13 +597,19 @@ void NLA_OT_select_leftright(wmOperatorType *ot)
/* ******************** Mouse-Click Select Operator *********************** */
/* select strip directly under mouse */
-static void mouse_nla_strips(
- bContext *C, bAnimContext *ac, const int mval[2], short select_mode, const bool deselect_all)
+static int mouse_nla_strips(bContext *C,
+ bAnimContext *ac,
+ const int mval[2],
+ short select_mode,
+ const bool deselect_all,
+ bool wait_to_deselect_others)
{
Scene *scene = ac->scene;
bAnimListElem *ale = NULL;
NlaStrip *strip = NULL;
+ int ret_value = OPERATOR_FINISHED;
+
nlaedit_strip_at_region_position(ac, mval[0], mval[1], &ale, &strip);
/* if currently in tweakmode, exit tweakmode before changing selection states
@@ -613,6 +619,10 @@ static void mouse_nla_strips(
WM_operator_name_call(C, "NLA_OT_tweakmode_exit", WM_OP_EXEC_DEFAULT, NULL);
}
+ if (select_mode != SELECT_REPLACE) {
+ wait_to_deselect_others = false;
+ }
+
/* For replacing selection, if we have something to select, we have to clear existing selection.
* The same goes if we found nothing to select, and deselect_all is true
* (deselect on nothing behavior). */
@@ -620,11 +630,16 @@ static void mouse_nla_strips(
/* reset selection mode for next steps */
select_mode = SELECT_ADD;
- /* deselect all strips */
- deselect_nla_strips(ac, 0, SELECT_SUBTRACT);
+ if (strip && wait_to_deselect_others && (strip->flag & DESELECT_STRIPS_CLEARACTIVE)) {
+ ret_value = OPERATOR_RUNNING_MODAL;
+ }
+ else {
+ /* deselect all strips */
+ deselect_nla_strips(ac, 0, SELECT_SUBTRACT);
- /* deselect all other channels first */
- ANIM_deselect_anim_channels(ac, ac->data, ac->datatype, 0, ACHANNEL_SETFLAG_CLEAR);
+ /* deselect all other channels first */
+ ANIM_deselect_anim_channels(ac, ac->data, ac->datatype, 0, ACHANNEL_SETFLAG_CLEAR);
+ }
}
/* only select strip if we clicked on a valid channel and hit something */
@@ -658,14 +673,17 @@ static void mouse_nla_strips(
/* free this channel */
MEM_freeN(ale);
}
+
+ return ret_value;
}
/* ------------------- */
/* handle clicking */
-static int nlaedit_clickselect_invoke(bContext *C, wmOperator *op, const wmEvent *event)
+static int nlaedit_clickselect_exec(bContext *C, wmOperator *op)
{
bAnimContext ac;
+ int ret_value;
/* get editor data */
if (ANIM_animdata_get_context(C, &ac) == 0) {
@@ -675,15 +693,19 @@ static int nlaedit_clickselect_invoke(bContext *C, wmOperator *op, const wmEvent
/* select mode is either replace (deselect all, then add) or add/extend */
const short selectmode = RNA_boolean_get(op->ptr, "extend") ? SELECT_INVERT : SELECT_REPLACE;
const bool deselect_all = RNA_boolean_get(op->ptr, "deselect_all");
+ const bool wait_to_deselect_others = RNA_boolean_get(op->ptr, "wait_to_deselect_others");
+ int mval[2];
+ mval[0] = RNA_int_get(op->ptr, "mouse_x");
+ mval[1] = RNA_int_get(op->ptr, "mouse_y");
/* select strips based upon mouse position */
- mouse_nla_strips(C, &ac, event->mval, selectmode, deselect_all);
+ ret_value = mouse_nla_strips(C, &ac, mval, selectmode, deselect_all, wait_to_deselect_others);
/* set notifier that things have changed */
WM_event_add_notifier(C, NC_ANIMATION | ND_NLA | NA_SELECTED, NULL);
/* for tweak grab to work */
- return OPERATOR_FINISHED | OPERATOR_PASS_THROUGH;
+ return ret_value | OPERATOR_PASS_THROUGH;
}
void NLA_OT_click_select(wmOperatorType *ot)
@@ -695,14 +717,17 @@ void NLA_OT_click_select(wmOperatorType *ot)
ot->idname = "NLA_OT_click_select";
ot->description = "Handle clicks to select NLA Strips";
- /* api callbacks - absolutely no exec() this yet... */
- ot->invoke = nlaedit_clickselect_invoke;
+ /* callbacks */
ot->poll = ED_operator_nla_active;
+ ot->exec = nlaedit_clickselect_exec;
+ ot->invoke = WM_generic_select_invoke;
+ ot->modal = WM_generic_select_modal;
/* flags */
ot->flag = OPTYPE_UNDO;
/* properties */
+ WM_operator_properties_generic_select(ot);
prop = RNA_def_boolean(ot->srna, "extend", 0, "Extend Select", ""); // SHIFTKEY
RNA_def_property_flag(prop, PROP_SKIP_SAVE);
diff --git a/source/blender/editors/space_node/drawnode.c b/source/blender/editors/space_node/drawnode.c
index 3beb12fbb2a..a5b18ff7589 100644
--- a/source/blender/editors/space_node/drawnode.c
+++ b/source/blender/editors/space_node/drawnode.c
@@ -47,7 +47,7 @@
#include "GPU_batch.h"
#include "GPU_batch_presets.h"
-#include "GPU_extensions.h"
+#include "GPU_platform.h"
#include "GPU_immediate.h"
#include "GPU_matrix.h"
#include "GPU_state.h"
@@ -816,51 +816,8 @@ static void node_shader_buts_tex_environment(uiLayout *layout, bContext *C, Poin
static void node_shader_buts_tex_environment_ex(uiLayout *layout, bContext *C, PointerRNA *ptr)
{
- PointerRNA imaptr = RNA_pointer_get(ptr, "image");
PointerRNA iuserptr = RNA_pointer_get(ptr, "image_user");
- Image *ima = imaptr.data;
-
- uiLayoutSetContextPointer(layout, "image_user", &iuserptr);
- uiTemplateID(layout,
- C,
- ptr,
- "image",
- "IMAGE_OT_new",
- "IMAGE_OT_open",
- NULL,
- UI_TEMPLATE_ID_FILTER_ALL,
- false);
-
- if (!ima) {
- return;
- }
-
- uiItemR(layout, &imaptr, "source", 0, IFACE_("Source"), ICON_NONE);
-
- if (!(ELEM(ima->source, IMA_SRC_GENERATED, IMA_SRC_VIEWER))) {
- uiLayout *row = uiLayoutRow(layout, true);
- const bool is_packed = BKE_image_has_packedfile(ima);
-
- if (is_packed) {
- uiItemO(row, "", ICON_PACKAGE, "image.unpack");
- }
- else {
- uiItemO(row, "", ICON_UGLYPACKAGE, "image.pack");
- }
-
- row = uiLayoutRow(row, true);
- uiLayoutSetEnabled(row, !is_packed);
- uiItemR(row, &imaptr, "filepath", 0, "", ICON_NONE);
- uiItemO(row, "", ICON_FILE_REFRESH, "image.reload");
- }
-
- /* multilayer? */
- if (ima->type == IMA_TYPE_MULTILAYER && ima->rr) {
- uiTemplateImageLayers(layout, C, ima, iuserptr.data);
- }
- else if (ima->source != IMA_SRC_GENERATED) {
- uiTemplateImageInfo(layout, C, ima, iuserptr.data);
- }
+ uiTemplateImage(layout, C, ptr, "image", &iuserptr, 0, 0);
uiItemR(layout, ptr, "interpolation", 0, IFACE_("Interpolation"), ICON_NONE);
uiItemR(layout, ptr, "projection", 0, IFACE_("Projection"), ICON_NONE);
@@ -3890,9 +3847,7 @@ static void nodelink_batch_draw(SpaceNode *snode)
void nodelink_batch_start(SpaceNode *UNUSED(snode))
{
- /* TODO: partial workaround for NVIDIA driver bug on recent GTX/RTX cards,
- * that breaks instancing when using indirect draw-call (see T70011). */
- g_batch_link.enabled = !GPU_type_matches(GPU_DEVICE_NVIDIA, GPU_OS_ANY, GPU_DRIVER_ANY);
+ g_batch_link.enabled = true;
}
void nodelink_batch_end(SpaceNode *snode)
diff --git a/source/blender/editors/space_node/node_group.c b/source/blender/editors/space_node/node_group.c
index 08ac84cbb2f..5d020ff5ab4 100644
--- a/source/blender/editors/space_node/node_group.c
+++ b/source/blender/editors/space_node/node_group.c
@@ -241,6 +241,8 @@ static int node_group_ungroup(Main *bmain, bNodeTree *ntree, bNode *gnode)
node->flag |= NODE_SELECT;
}
+ bNodeLink *glinks_first = ntree->links.last;
+
/* Add internal links to the ntree */
for (link = wgroup->links.first; link; link = linkn) {
linkn = link->next;
@@ -248,6 +250,8 @@ static int node_group_ungroup(Main *bmain, bNodeTree *ntree, bNode *gnode)
BLI_addtail(&ntree->links, link);
}
+ bNodeLink *glinks_last = ntree->links.last;
+
/* and copy across the animation,
* note that the animation data's action can be NULL here */
if (wgroup->adt) {
@@ -280,70 +284,64 @@ static int node_group_ungroup(Main *bmain, bNodeTree *ntree, bNode *gnode)
BKE_id_free(bmain, wgroup);
/* restore external links to and from the gnode */
- /* note: the nodes have been copied to intermediate wgroup first (so need to use new_node),
- * then transferred to ntree (new_node pointers remain valid).
- */
/* input links */
- for (link = ngroup->links.first; link; link = link->next) {
- if (link->fromnode->type == NODE_GROUP_INPUT) {
- const char *identifier = link->fromsock->identifier;
- int num_external_links = 0;
-
- /* find external links to this input */
- for (tlink = ntree->links.first; tlink; tlink = tlink->next) {
- if (tlink->tonode == gnode && STREQ(tlink->tosock->identifier, identifier)) {
- nodeAddLink(ntree,
- tlink->fromnode,
- tlink->fromsock,
- link->tonode->new_node,
- link->tosock->new_sock);
- num_external_links++;
+ if (glinks_first != NULL) {
+ for (link = glinks_first->next; link != glinks_last->next; link = link->next) {
+ if (link->fromnode->type == NODE_GROUP_INPUT) {
+ const char *identifier = link->fromsock->identifier;
+ int num_external_links = 0;
+
+ /* find external links to this input */
+ for (tlink = ntree->links.first; tlink != glinks_first->next; tlink = tlink->next) {
+ if (tlink->tonode == gnode && STREQ(tlink->tosock->identifier, identifier)) {
+ nodeAddLink(ntree, tlink->fromnode, tlink->fromsock, link->tonode, link->tosock);
+ num_external_links++;
+ }
}
- }
- /* if group output is not externally linked,
- * convert the constant input value to ensure somewhat consistent behavior */
- if (num_external_links == 0) {
- /* XXX TODO bNodeSocket *sock = node_group_find_input_socket(gnode, identifier);
- BLI_assert(sock);*/
+ /* if group output is not externally linked,
+ * convert the constant input value to ensure somewhat consistent behavior */
+ if (num_external_links == 0) {
+ /* XXX TODO bNodeSocket *sock = node_group_find_input_socket(gnode, identifier);
+ BLI_assert(sock);*/
- /* XXX TODO
- * nodeSocketCopy(ntree, link->tosock->new_sock, link->tonode->new_node,
- * ntree, sock, gnode);*/
+ /* XXX TODO
+ * nodeSocketCopy(ntree, link->tosock->new_sock, link->tonode->new_node,
+ * ntree, sock, gnode);*/
+ }
}
}
- }
- /* output links */
- for (link = ntree->links.first; link; link = link->next) {
- if (link->fromnode == gnode) {
- const char *identifier = link->fromsock->identifier;
- int num_internal_links = 0;
-
- /* find internal links to this output */
- for (tlink = ngroup->links.first; tlink; tlink = tlink->next) {
- /* only use active output node */
- if (tlink->tonode->type == NODE_GROUP_OUTPUT && (tlink->tonode->flag & NODE_DO_OUTPUT)) {
- if (STREQ(tlink->tosock->identifier, identifier)) {
- nodeAddLink(ntree,
- tlink->fromnode->new_node,
- tlink->fromsock->new_sock,
- link->tonode,
- link->tosock);
- num_internal_links++;
+ /* Also iterate over new links to cover passthrough links. */
+ glinks_last = ntree->links.last;
+
+ /* output links */
+ for (link = ntree->links.first; link != glinks_first->next; link = link->next) {
+ if (link->fromnode == gnode) {
+ const char *identifier = link->fromsock->identifier;
+ int num_internal_links = 0;
+
+ /* find internal links to this output */
+ for (tlink = glinks_first->next; tlink != glinks_last->next; tlink = tlink->next) {
+ /* only use active output node */
+ if (tlink->tonode->type == NODE_GROUP_OUTPUT && (tlink->tonode->flag & NODE_DO_OUTPUT)) {
+ if (STREQ(tlink->tosock->identifier, identifier)) {
+ nodeAddLink(ntree, tlink->fromnode, tlink->fromsock, link->tonode, link->tosock);
+ num_internal_links++;
+ }
}
}
- }
- /* if group output is not internally linked,
- * convert the constant output value to ensure somewhat consistent behavior */
- if (num_internal_links == 0) {
- /* XXX TODO bNodeSocket *sock = node_group_find_output_socket(gnode, identifier);
- BLI_assert(sock);*/
+ /* if group output is not internally linked,
+ * convert the constant output value to ensure somewhat consistent behavior */
+ if (num_internal_links == 0) {
+ /* XXX TODO bNodeSocket *sock = node_group_find_output_socket(gnode, identifier);
+ BLI_assert(sock);*/
- /* XXX TODO
- * nodeSocketCopy(ntree, link->tosock, link->tonode, ntree, sock, gnode); */
+ /* XXX TODO
+ * nodeSocketCopy(ntree, link->tosock, link->tonode, ntree, sock, gnode); */
+ }
}
}
}
@@ -893,7 +891,7 @@ static void node_group_make_insert_selected(const bContext *C, bNodeTree *ntree,
}
}
if (sock->flag & (SOCK_HIDDEN | SOCK_UNAVAIL)) {
- skip = true;
+ skip = true;
}
if (skip) {
continue;
@@ -917,7 +915,7 @@ static void node_group_make_insert_selected(const bContext *C, bNodeTree *ntree,
}
}
if (sock->flag & (SOCK_HIDDEN | SOCK_UNAVAIL)) {
- skip = true;
+ skip = true;
}
if (skip) {
continue;
diff --git a/source/blender/editors/space_node/node_select.c b/source/blender/editors/space_node/node_select.c
index b66cd0d3069..e22ef389516 100644
--- a/source/blender/editors/space_node/node_select.c
+++ b/source/blender/editors/space_node/node_select.c
@@ -557,100 +557,40 @@ static int node_mouse_select(bContext *C,
static int node_select_exec(bContext *C, wmOperator *op)
{
+ const bool wait_to_deselect_others = RNA_boolean_get(op->ptr, "wait_to_deselect_others");
+
/* get settings from RNA properties for operator */
int mval[2];
mval[0] = RNA_int_get(op->ptr, "mouse_x");
mval[1] = RNA_int_get(op->ptr, "mouse_y");
/* perform the select */
- const int ret_value = node_mouse_select(C, op, mval, false);
+ const int ret_value = node_mouse_select(C, op, mval, wait_to_deselect_others);
/* allow tweak event to work too */
return ret_value | OPERATOR_PASS_THROUGH;
}
-static int node_select_modal(bContext *C, wmOperator *op, const wmEvent *event)
-{
- const short init_event_type = (short)POINTER_AS_INT(op->customdata);
-
- /* get settings from RNA properties for operator */
- int mval[2];
- mval[0] = RNA_int_get(op->ptr, "mouse_x");
- mval[1] = RNA_int_get(op->ptr, "mouse_y");
-
- if (init_event_type == 0) {
- if (event->val == KM_PRESS) {
- const int ret_value = node_mouse_select(C, op, mval, true);
-
- op->customdata = POINTER_FROM_INT((int)event->type);
- if (ret_value & OPERATOR_RUNNING_MODAL) {
- WM_event_add_modal_handler(C, op);
- }
- return ret_value | OPERATOR_PASS_THROUGH;
- }
- else {
- /* If we are in init phase, and cannot validate init of modal operations,
- * just fall back to basic exec.
- */
- const int ret_value = node_mouse_select(C, op, mval, false);
- return ret_value | OPERATOR_PASS_THROUGH;
- }
- }
- else if (event->type == init_event_type && event->val == KM_RELEASE) {
- const int ret_value = node_mouse_select(C, op, mval, false);
- return ret_value | OPERATOR_PASS_THROUGH;
- }
- else if (ELEM(event->type, MOUSEMOVE, INBETWEEN_MOUSEMOVE)) {
- const int drag_delta[2] = {
- mval[0] - event->mval[0],
- mval[1] - event->mval[1],
- };
- /* If user moves mouse more than defined threshold, we consider select operator as
- * finished. Otherwise, it is still running until we get an 'release' event. In any
- * case, we pass through event, but select op is not finished yet. */
- if (WM_event_drag_test_with_delta(event, drag_delta)) {
- return OPERATOR_FINISHED | OPERATOR_PASS_THROUGH;
- }
- else {
- /* Important not to return anything other than PASS_THROUGH here,
- * otherwise it prevents underlying tweak detection code to work properly. */
- return OPERATOR_PASS_THROUGH;
- }
- }
-
- return OPERATOR_FINISHED | OPERATOR_PASS_THROUGH;
-}
-
-static int node_select_invoke(bContext *C, wmOperator *op, const wmEvent *event)
-{
- RNA_int_set(op->ptr, "mouse_x", event->mval[0]);
- RNA_int_set(op->ptr, "mouse_y", event->mval[1]);
-
- op->customdata = POINTER_FROM_INT(0);
-
- return node_select_modal(C, op, event);
-}
-
void NODE_OT_select(wmOperatorType *ot)
{
+ PropertyRNA *prop;
+
/* identifiers */
ot->name = "Select";
ot->idname = "NODE_OT_select";
ot->description = "Select the node under the cursor";
/* api callbacks */
- ot->invoke = node_select_invoke;
ot->exec = node_select_exec;
- ot->modal = node_select_modal;
+ ot->invoke = WM_generic_select_invoke;
+ ot->modal = WM_generic_select_modal;
ot->poll = ED_operator_node_active;
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
/* properties */
- PropertyRNA *prop;
- RNA_def_int(ot->srna, "mouse_x", 0, INT_MIN, INT_MAX, "Mouse X", "", INT_MIN, INT_MAX);
- RNA_def_int(ot->srna, "mouse_y", 0, INT_MIN, INT_MAX, "Mouse Y", "", INT_MIN, INT_MAX);
+ WM_operator_properties_generic_select(ot);
RNA_def_boolean(ot->srna, "extend", false, "Extend", "");
RNA_def_boolean(ot->srna, "socket_select", false, "Socket Select", "");
prop = RNA_def_boolean(ot->srna,
diff --git a/source/blender/editors/space_outliner/outliner_collections.c b/source/blender/editors/space_outliner/outliner_collections.c
index 309446db83b..03606282fcd 100644
--- a/source/blender/editors/space_outliner/outliner_collections.c
+++ b/source/blender/editors/space_outliner/outliner_collections.c
@@ -965,7 +965,7 @@ static int collection_isolate_exec(bContext *C, wmOperator *op)
LayerCollection *layer_collection = BLI_gsetIterator_getKey(&collections_to_edit_iter);
if (extend) {
- BKE_layer_collection_isolate(scene, view_layer, layer_collection, true);
+ BKE_layer_collection_isolate_global(scene, view_layer, layer_collection, true);
}
else {
PointerRNA ptr;
diff --git a/source/blender/editors/space_outliner/outliner_draw.c b/source/blender/editors/space_outliner/outliner_draw.c
index a2ca3254b30..3b86e04308e 100644
--- a/source/blender/editors/space_outliner/outliner_draw.c
+++ b/source/blender/editors/space_outliner/outliner_draw.c
@@ -2419,7 +2419,6 @@ TreeElementIcon tree_element_get_icon(TreeStoreElem *tselem, TreeElement *te)
case OB_GPENCIL:
data.icon = ICON_OUTLINER_OB_GREASEPENCIL;
break;
- break;
}
}
else {
diff --git a/source/blender/editors/space_outliner/outliner_edit.c b/source/blender/editors/space_outliner/outliner_edit.c
index c81d292a859..c55140db46f 100644
--- a/source/blender/editors/space_outliner/outliner_edit.c
+++ b/source/blender/editors/space_outliner/outliner_edit.c
@@ -770,11 +770,7 @@ static int outliner_id_copy_exec(bContext *C, wmOperator *op)
BLI_make_file_string("/", str, BKE_tempdir_base(), "copybuffer.blend");
BKE_copybuffer_save(bmain, str, op->reports);
- BKE_reportf(op->reports,
- RPT_INFO,
- num_ids == 1 ? "Copied %d selected data-block" :
- "Copied %d selected data-blocks",
- num_ids);
+ BKE_reportf(op->reports, RPT_INFO, "Copied %d selected data-block(s)", num_ids);
return OPERATOR_FINISHED;
}
@@ -808,11 +804,7 @@ static int outliner_id_paste_exec(bContext *C, wmOperator *op)
WM_event_add_notifier(C, NC_WINDOW, NULL);
- BKE_reportf(op->reports,
- RPT_INFO,
- num_pasted == 1 ? "%d data-block pasted" :
- "%d data-blocks pasted",
- num_pasted);
+ BKE_reportf(op->reports, RPT_INFO, "%d data-block(s) pasted", num_pasted);
return OPERATOR_FINISHED;
}
@@ -2265,11 +2257,7 @@ static int outliner_orphans_purge_exec(bContext *C, wmOperator *op)
BKE_id_multi_tagged_delete(bmain);
- BKE_reportf(op->reports,
- RPT_INFO,
- num_tagged[INDEX_ID_NULL] == 1 ? "Deleted %d data-block" :
- "Deleted %d data-blocks",
- num_tagged[INDEX_ID_NULL]);
+ BKE_reportf(op->reports, RPT_INFO, "Deleted %d data-block(s)", num_tagged[INDEX_ID_NULL]);
/* XXX: tree management normally happens from draw_outliner(), but when
* you're clicking to fast on Delete object from context menu in
diff --git a/source/blender/editors/space_outliner/outliner_select.c b/source/blender/editors/space_outliner/outliner_select.c
index 44e67fa1508..f1e884adc3d 100644
--- a/source/blender/editors/space_outliner/outliner_select.c
+++ b/source/blender/editors/space_outliner/outliner_select.c
@@ -263,7 +263,8 @@ static void do_outliner_object_select_recursive(ViewLayer *view_layer,
for (base = FIRSTBASE(view_layer); base; base = base->next) {
Object *ob = base->object;
- if ((((base->flag & BASE_VISIBLE) != 0) && BKE_object_is_child_recursive(ob_parent, ob))) {
+ if ((((base->flag & BASE_VISIBLE_DEPSGRAPH) != 0) &&
+ BKE_object_is_child_recursive(ob_parent, ob))) {
ED_object_base_select(base, select ? BA_SELECT : BA_DESELECT);
}
}
@@ -1198,7 +1199,7 @@ static void do_outliner_item_activate_tree_element(bContext *C,
Object *ob = (Object *)outliner_search_back(soops, te, ID_OB);
if ((ob != NULL) && (ob->data == tselem->id)) {
Base *base = BKE_view_layer_base_find(view_layer, ob);
- if ((base != NULL) && (base->flag & BASE_VISIBLE)) {
+ if ((base != NULL) && (base->flag & BASE_VISIBLE_DEPSGRAPH)) {
do_outliner_activate_obdata(C, scene, view_layer, base, extend);
}
}
diff --git a/source/blender/editors/space_outliner/outliner_tree.c b/source/blender/editors/space_outliner/outliner_tree.c
index fd6a052b84d..7f7cfff12ef 100644
--- a/source/blender/editors/space_outliner/outliner_tree.c
+++ b/source/blender/editors/space_outliner/outliner_tree.c
@@ -1365,7 +1365,7 @@ static void outliner_add_layer_collection_objects(
TreeElement *te_object = outliner_add_element(soops, tree, base->object, ten, 0, 0);
te_object->directdata = base;
- if (!(base->flag & BASE_VISIBLE)) {
+ if (!(base->flag & BASE_VISIBLE_DEPSGRAPH)) {
te_object->flag |= TE_DISABLED;
}
}
@@ -1398,7 +1398,7 @@ static void outliner_add_layer_collections_recursive(SpaceOutliner *soops,
tselem->flag &= ~TSE_CLOSED;
}
- if (exclude || (lc->runtime_flag & LAYER_COLLECTION_VISIBLE) == 0) {
+ if (exclude || (lc->runtime_flag & LAYER_COLLECTION_VISIBLE_VIEW_LAYER) == 0) {
ten->flag |= TE_DISABLED;
}
}
@@ -2085,12 +2085,12 @@ static bool outliner_element_visible_get(ViewLayer *view_layer,
}
if (exclude_filter & SO_FILTER_OB_STATE_VISIBLE) {
- if ((base->flag & BASE_VISIBLE) == 0) {
+ if ((base->flag & BASE_VISIBLE_DEPSGRAPH) == 0) {
return false;
}
}
else if (exclude_filter & SO_FILTER_OB_STATE_HIDDEN) {
- if ((base->flag & BASE_VISIBLE) != 0) {
+ if ((base->flag & BASE_VISIBLE_DEPSGRAPH) != 0) {
return false;
}
}
diff --git a/source/blender/editors/space_sequencer/sequencer_edit.c b/source/blender/editors/space_sequencer/sequencer_edit.c
index 9d7163cd6d9..865dfb45278 100644
--- a/source/blender/editors/space_sequencer/sequencer_edit.c
+++ b/source/blender/editors/space_sequencer/sequencer_edit.c
@@ -1600,6 +1600,7 @@ static int sequencer_slip_exec(bContext *C, wmOperator *op)
if (success) {
WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
+ DEG_id_tag_update(&scene->id, ID_RECALC_SEQUENCER_STRIPS);
return OPERATOR_FINISHED;
}
else {
@@ -1693,6 +1694,7 @@ static int sequencer_slip_modal(bContext *C, wmOperator *op, const wmEvent *even
if (sa) {
ED_area_status_text(sa, NULL);
}
+ DEG_id_tag_update(&scene->id, ID_RECALC_SEQUENCER_STRIPS);
WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
return OPERATOR_FINISHED;
}
diff --git a/source/blender/editors/space_sequencer/sequencer_select.c b/source/blender/editors/space_sequencer/sequencer_select.c
index affb6d3fd88..4c20fc1707a 100644
--- a/source/blender/editors/space_sequencer/sequencer_select.c
+++ b/source/blender/editors/space_sequencer/sequencer_select.c
@@ -319,7 +319,7 @@ void SEQUENCER_OT_select_inverse(struct wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
-static int sequencer_select_invoke(bContext *C, wmOperator *op, const wmEvent *event)
+static int sequencer_select_exec(bContext *C, wmOperator *op)
{
View2D *v2d = UI_view2d_fromcontext(C);
Scene *scene = CTX_data_scene(C);
@@ -328,7 +328,13 @@ static int sequencer_select_invoke(bContext *C, wmOperator *op, const wmEvent *e
const bool deselect_all = RNA_boolean_get(op->ptr, "deselect_all");
const bool linked_handle = RNA_boolean_get(op->ptr, "linked_handle");
const bool linked_time = RNA_boolean_get(op->ptr, "linked_time");
+ bool wait_to_deselect_others = RNA_boolean_get(op->ptr, "wait_to_deselect_others");
int left_right = RNA_enum_get(op->ptr, "left_right");
+ int mval[2];
+ int ret_value = OPERATOR_CANCELLED;
+
+ mval[0] = RNA_int_get(op->ptr, "mouse_x");
+ mval[1] = RNA_int_get(op->ptr, "mouse_y");
Sequence *seq, *neighbor, *act_orig;
int hand, sel_side;
@@ -338,9 +344,13 @@ static int sequencer_select_invoke(bContext *C, wmOperator *op, const wmEvent *e
return OPERATOR_CANCELLED;
}
+ if (extend) {
+ wait_to_deselect_others = false;
+ }
+
marker = find_nearest_marker(SCE_MARKERS, 1); // XXX - dummy function for now
- seq = find_nearest_seq(scene, v2d, &hand, event->mval);
+ seq = find_nearest_seq(scene, v2d, &hand, mval);
// XXX - not nice, Ctrl+RMB needs to do left_right only when not over a strip
if (seq && linked_time && (left_right == SEQ_SELECT_LR_MOUSE)) {
@@ -364,6 +374,8 @@ static int sequencer_select_invoke(bContext *C, wmOperator *op, const wmEvent *e
/* deselect_markers(0, 0); */
marker->flag |= SELECT;
}
+
+ ret_value = OPERATOR_FINISHED;
}
else if (left_right != SEQ_SELECT_LR_NONE) {
/* use different logic for this */
@@ -374,7 +386,7 @@ static int sequencer_select_invoke(bContext *C, wmOperator *op, const wmEvent *e
switch (left_right) {
case SEQ_SELECT_LR_MOUSE:
- x = UI_view2d_region_to_view_x(v2d, event->mval[0]);
+ x = UI_view2d_region_to_view_x(v2d, mval[0]);
break;
case SEQ_SELECT_LR_LEFT:
x = CFRA - 1.0f;
@@ -409,13 +421,27 @@ static int sequencer_select_invoke(bContext *C, wmOperator *op, const wmEvent *e
}
}
}
+
+ ret_value = OPERATOR_FINISHED;
}
else {
act_orig = ed->act_seq;
if (seq) {
- if (!extend && !linked_handle) {
+ /* Are we trying to select a handle that's already selected? */
+ const bool handle_selected = ((hand == SEQ_SIDE_LEFT) && (seq->flag & SEQ_LEFTSEL)) ||
+ ((hand == SEQ_SIDE_RIGHT) && (seq->flag & SEQ_RIGHTSEL));
+
+ if (wait_to_deselect_others && (seq->flag & SELECT) &&
+ (hand == SEQ_SIDE_NONE || handle_selected)) {
+ ret_value = OPERATOR_RUNNING_MODAL;
+ }
+ else if (!extend && !linked_handle) {
ED_sequencer_deselect_all(scene);
+ ret_value = OPERATOR_FINISHED;
+ }
+ else {
+ ret_value = OPERATOR_FINISHED;
}
BKE_sequencer_active_set(scene, seq);
@@ -509,6 +535,8 @@ static int sequencer_select_invoke(bContext *C, wmOperator *op, const wmEvent *e
select_active_side(ed->seqbasep, sel_side, seq->machine, seq->startdisp);
}
}
+
+ ret_value = OPERATOR_FINISHED;
}
else {
if (extend && (seq->flag & SELECT) && ed->act_seq == act_orig) {
@@ -525,6 +553,7 @@ static int sequencer_select_invoke(bContext *C, wmOperator *op, const wmEvent *e
seq->flag ^= SEQ_RIGHTSEL;
break;
}
+ ret_value = OPERATOR_FINISHED;
}
else {
seq->flag |= SELECT;
@@ -542,9 +571,12 @@ static int sequencer_select_invoke(bContext *C, wmOperator *op, const wmEvent *e
if (linked_time) {
select_linked_time(ed->seqbasep, seq);
}
+
+ BLI_assert((ret_value & OPERATOR_CANCELLED) == 0);
}
else if (deselect_all) {
ED_sequencer_deselect_all(scene);
+ ret_value = OPERATOR_FINISHED;
}
}
@@ -552,8 +584,7 @@ static int sequencer_select_invoke(bContext *C, wmOperator *op, const wmEvent *e
WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER | NA_SELECTED, scene);
- /* allowing tweaks */
- return OPERATOR_FINISHED | OPERATOR_PASS_THROUGH;
+ return ret_value;
}
void SEQUENCER_OT_select(wmOperatorType *ot)
@@ -565,6 +596,7 @@ void SEQUENCER_OT_select(wmOperatorType *ot)
{SEQ_SELECT_LR_RIGHT, "RIGHT", 0, "Right", "Select right"},
{0, NULL, 0, NULL, NULL},
};
+ PropertyRNA *prop;
/* identifiers */
ot->name = "Select";
@@ -572,14 +604,16 @@ void SEQUENCER_OT_select(wmOperatorType *ot)
ot->description = "Select a strip (last selected becomes the \"active strip\")";
/* api callbacks */
- ot->invoke = sequencer_select_invoke;
+ ot->exec = sequencer_select_exec;
+ ot->invoke = WM_generic_select_invoke;
+ ot->modal = WM_generic_select_modal;
ot->poll = ED_operator_sequencer_active;
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
/* properties */
- PropertyRNA *prop;
+ WM_operator_properties_generic_select(ot);
RNA_def_boolean(ot->srna, "extend", 0, "Extend", "Extend the selection");
prop = RNA_def_boolean(ot->srna,
"deselect_all",
diff --git a/source/blender/editors/space_text/text_format_lua.c b/source/blender/editors/space_text/text_format_lua.c
index 347d46a4234..935e288c7be 100644
--- a/source/blender/editors/space_text/text_format_lua.c
+++ b/source/blender/editors/space_text/text_format_lua.c
@@ -48,7 +48,7 @@ static int txtfmt_lua_find_keyword(const char *string)
/* Keep aligned args for readability. */
/* clang-format off */
- if (STR_LITERAL_STARTSWITH(string, "and", len)) { i = len;
+ if (STR_LITERAL_STARTSWITH(string, "and", len)) { i = len;
} else if (STR_LITERAL_STARTSWITH(string, "break", len)) { i = len;
} else if (STR_LITERAL_STARTSWITH(string, "do", len)) { i = len;
} else if (STR_LITERAL_STARTSWITH(string, "else", len)) { i = len;
@@ -66,8 +66,7 @@ static int txtfmt_lua_find_keyword(const char *string)
} else if (STR_LITERAL_STARTSWITH(string, "then", len)) { i = len;
} else if (STR_LITERAL_STARTSWITH(string, "until", len)) { i = len;
} else if (STR_LITERAL_STARTSWITH(string, "while", len)) { i = len;
- } else { i = 0;
-}
+ } else { i = 0; }
/* clang-format on */
@@ -96,7 +95,7 @@ static int txtfmt_lua_find_specialvar(const char *string)
/* Keep aligned args for readability. */
/* clang-format off */
- if (STR_LITERAL_STARTSWITH(string, "assert", len)) { i = len;
+ if (STR_LITERAL_STARTSWITH(string, "assert", len)) { i = len;
} else if (STR_LITERAL_STARTSWITH(string, "collectgarbage", len)) { i = len;
} else if (STR_LITERAL_STARTSWITH(string, "dofile", len)) { i = len;
} else if (STR_LITERAL_STARTSWITH(string, "error", len)) { i = len;
@@ -124,8 +123,7 @@ static int txtfmt_lua_find_specialvar(const char *string)
} else if (STR_LITERAL_STARTSWITH(string, "unpack", len)) { i = len;
} else if (STR_LITERAL_STARTSWITH(string, "_VERSION", len)) { i = len;
} else if (STR_LITERAL_STARTSWITH(string, "xpcall", len)) { i = len;
- } else { i = 0;
-}
+ } else { i = 0; }
/* clang-format on */
@@ -140,18 +138,13 @@ static int txtfmt_lua_find_bool(const char *string)
{
int i, len;
- if (STR_LITERAL_STARTSWITH(string, "nil", len)) {
- i = len;
- }
- else if (STR_LITERAL_STARTSWITH(string, "true", len)) {
- i = len;
- }
- else if (STR_LITERAL_STARTSWITH(string, "false", len)) {
- i = len;
- }
- else {
- i = 0;
- }
+ /* Keep aligned args for readability. */
+ /* clang-format off */
+
+ if (STR_LITERAL_STARTSWITH(string, "nil", len)) { i = len;
+ } else if (STR_LITERAL_STARTSWITH(string, "true", len)) { i = len;
+ } else if (STR_LITERAL_STARTSWITH(string, "false", len)) { i = len;
+ } else { i = 0; }
/* clang-format on */
@@ -169,10 +162,9 @@ static char txtfmt_lua_format_identifier(const char *str)
/* Keep aligned args for readability. */
/* clang-format off */
- if ((txtfmt_lua_find_specialvar(str)) != -1) { fmt = FMT_TYPE_SPECIAL;
+ if ((txtfmt_lua_find_specialvar(str)) != -1) { fmt = FMT_TYPE_SPECIAL;
} else if ((txtfmt_lua_find_keyword(str)) != -1) { fmt = FMT_TYPE_KEYWORD;
- } else { fmt = FMT_TYPE_DEFAULT;
-}
+ } else { fmt = FMT_TYPE_DEFAULT; }
/* clang-format on */
diff --git a/source/blender/editors/space_text/text_format_osl.c b/source/blender/editors/space_text/text_format_osl.c
index fb9ddcb09cb..2da4488e901 100644
--- a/source/blender/editors/space_text/text_format_osl.c
+++ b/source/blender/editors/space_text/text_format_osl.c
@@ -40,7 +40,7 @@ static int txtfmt_osl_find_builtinfunc(const char *string)
/* list is from
* https://github.com/imageworks/OpenShadingLanguage/raw/master/src/doc/osl-languagespec.pdf
*/
- if (STR_LITERAL_STARTSWITH(string, "break", len)) { i = len;
+ if (STR_LITERAL_STARTSWITH(string, "break", len)) { i = len;
} else if (STR_LITERAL_STARTSWITH(string, "closure", len)) { i = len;
} else if (STR_LITERAL_STARTSWITH(string, "color", len)) { i = len;
} else if (STR_LITERAL_STARTSWITH(string, "continue", len)) { i = len;
@@ -86,7 +86,7 @@ static int txtfmt_osl_find_reserved(const char *string)
/* list is from...
* https://github.com/imageworks/OpenShadingLanguage/raw/master/src/doc/osl-languagespec.pdf
*/
- if (STR_LITERAL_STARTSWITH(string, "bool", len)) { i = len;
+ if (STR_LITERAL_STARTSWITH(string, "bool", len)) { i = len;
} else if (STR_LITERAL_STARTSWITH(string, "case", len)) { i = len;
} else if (STR_LITERAL_STARTSWITH(string, "catch", len)) { i = len;
} else if (STR_LITERAL_STARTSWITH(string, "char", len)) { i = len;
@@ -149,7 +149,7 @@ static int txtfmt_osl_find_specialvar(const char *string)
/* clang-format off */
/* OSL shader types */
- if (STR_LITERAL_STARTSWITH(string, "shader", len)) { i = len;
+ if (STR_LITERAL_STARTSWITH(string, "shader", len)) { i = len;
} else if (STR_LITERAL_STARTSWITH(string, "surface", len)) { i = len;
} else if (STR_LITERAL_STARTSWITH(string, "volume", len)) { i = len;
} else if (STR_LITERAL_STARTSWITH(string, "displacement", len)) { i = len;
@@ -189,7 +189,7 @@ static char txtfmt_osl_format_identifier(const char *str)
/* Keep aligned args for readability. */
/* clang-format off */
- if ((txtfmt_osl_find_specialvar(str)) != -1) { fmt = FMT_TYPE_SPECIAL;
+ if ((txtfmt_osl_find_specialvar(str)) != -1) { fmt = FMT_TYPE_SPECIAL;
} else if ((txtfmt_osl_find_builtinfunc(str)) != -1) { fmt = FMT_TYPE_KEYWORD;
} else if ((txtfmt_osl_find_reserved(str)) != -1) { fmt = FMT_TYPE_RESERVED;
} else if ((txtfmt_osl_find_preprocessor(str)) != -1) { fmt = FMT_TYPE_DIRECTIVE;
@@ -323,7 +323,7 @@ static void txtfmt_osl_format_line(SpaceText *st, TextLine *line, const bool do_
/* Special vars(v) or built-in keywords(b) */
/* keep in sync with 'txtfmt_osl_format_identifier()' */
- if ((i = txtfmt_osl_find_specialvar(str)) != -1) { prev = FMT_TYPE_SPECIAL;
+ if ((i = txtfmt_osl_find_specialvar(str)) != -1) { prev = FMT_TYPE_SPECIAL;
} else if ((i = txtfmt_osl_find_builtinfunc(str)) != -1) { prev = FMT_TYPE_KEYWORD;
} else if ((i = txtfmt_osl_find_reserved(str)) != -1) { prev = FMT_TYPE_RESERVED;
} else if ((i = txtfmt_osl_find_preprocessor(str)) != -1) { prev = FMT_TYPE_DIRECTIVE;
diff --git a/source/blender/editors/space_text/text_format_pov.c b/source/blender/editors/space_text/text_format_pov.c
index a5e1a3845cf..21df7b5b76a 100644
--- a/source/blender/editors/space_text/text_format_pov.c
+++ b/source/blender/editors/space_text/text_format_pov.c
@@ -48,7 +48,7 @@ static int txtfmt_pov_find_keyword(const char *string)
int i, len;
/* Language Directives */
- if (STR_LITERAL_STARTSWITH(string, "deprecated", len)) { i = len;
+ if (STR_LITERAL_STARTSWITH(string, "deprecated", len)) { i = len;
} else if (STR_LITERAL_STARTSWITH(string, "persistent", len)) { i = len;
} else if (STR_LITERAL_STARTSWITH(string, "statistics", len)) { i = len;
} else if (STR_LITERAL_STARTSWITH(string, "version", len)) { i = len;
@@ -101,7 +101,7 @@ static int txtfmt_pov_find_reserved_keywords(const char *string)
/* clang-format off */
/* Float Functions */
- if (STR_LITERAL_STARTSWITH(string, "conserve_energy", len)) { i = len;
+ if (STR_LITERAL_STARTSWITH(string, "conserve_energy", len)) { i = len;
} else if (STR_LITERAL_STARTSWITH(string, "max_intersections", len)) { i = len;
} else if (STR_LITERAL_STARTSWITH(string, "dimension_size", len)) { i = len;
} else if (STR_LITERAL_STARTSWITH(string, "bitwise_and", len)) { i = len;
@@ -261,7 +261,7 @@ static int txtfmt_pov_find_reserved_builtins(const char *string)
/* clang-format off */
/* Language Keywords */
- if (STR_LITERAL_STARTSWITH(string, "reflection_exponent", len)) { i = len;
+ if (STR_LITERAL_STARTSWITH(string, "reflection_exponent", len)) { i = len;
} else if (STR_LITERAL_STARTSWITH(string, "area_illumination", len)) { i = len;
} else if (STR_LITERAL_STARTSWITH(string, "all_intersections", len)) { i = len;
} else if (STR_LITERAL_STARTSWITH(string, "cutaway_textures", len)) { i = len;
@@ -500,7 +500,7 @@ static int txtfmt_pov_find_specialvar(const char *string)
{
int i, len;
/* Modifiers */
- if (STR_LITERAL_STARTSWITH(string, "dispersion_samples", len)) { i = len;
+ if (STR_LITERAL_STARTSWITH(string, "dispersion_samples", len)) { i = len;
} else if (STR_LITERAL_STARTSWITH(string, "projected_through", len)) { i = len;
} else if (STR_LITERAL_STARTSWITH(string, "double_illuminate", len)) { i = len;
} else if (STR_LITERAL_STARTSWITH(string, "expand_thresholds", len)) { i = len;
@@ -710,7 +710,7 @@ static int txtfmt_pov_find_bool(const char *string)
/* clang-format off */
/* Built-in Constants */
- if (STR_LITERAL_STARTSWITH(string, "unofficial", len)) { i = len;
+ if (STR_LITERAL_STARTSWITH(string, "unofficial", len)) { i = len;
} else if (STR_LITERAL_STARTSWITH(string, "false", len)) { i = len;
} else if (STR_LITERAL_STARTSWITH(string, "no", len)) { i = len;
} else if (STR_LITERAL_STARTSWITH(string, "off", len)) { i = len;
diff --git a/source/blender/editors/space_text/text_format_pov_ini.c b/source/blender/editors/space_text/text_format_pov_ini.c
index 04f4b992cc6..b349b38e551 100644
--- a/source/blender/editors/space_text/text_format_pov_ini.c
+++ b/source/blender/editors/space_text/text_format_pov_ini.c
@@ -49,7 +49,7 @@ static int txtfmt_ini_find_keyword(const char *string)
/* clang-format off */
/* Language Directives */
- if (STR_LITERAL_STARTSWITH(string, "deprecated", len)) { i = len;
+ if (STR_LITERAL_STARTSWITH(string, "deprecated", len)) { i = len;
} else if (STR_LITERAL_STARTSWITH(string, "statistics", len)) { i = len;
} else if (STR_LITERAL_STARTSWITH(string, "declare", len)) { i = len;
} else if (STR_LITERAL_STARTSWITH(string, "default", len)) { i = len;
@@ -111,7 +111,7 @@ static int txtfmt_ini_find_reserved(const char *string)
* list is from...
* http://www.povray.org/documentation/view/3.7.0/212/
*/
- if (STR_LITERAL_STARTSWITH(string, "RenderCompleteSoundEnabled", len)) { i = len;
+ if (STR_LITERAL_STARTSWITH(string, "RenderCompleteSoundEnabled", len)) { i = len;
} else if (STR_LITERAL_STARTSWITH(string, "Create_Continue_Trace_Log", len)) { i = len;
} else if (STR_LITERAL_STARTSWITH(string, "ParseErrorSoundEnabled", len)) { i = len;
} else if (STR_LITERAL_STARTSWITH(string, "RenderErrorSoundEnabled", len)) { i = len;
@@ -321,7 +321,7 @@ static int txtfmt_ini_find_bool(const char *string)
/* clang-format off */
/* Built-in Constants */
- if (STR_LITERAL_STARTSWITH(string, "false", len)) { i = len;
+ if (STR_LITERAL_STARTSWITH(string, "false", len)) { i = len;
} else if (STR_LITERAL_STARTSWITH(string, "no", len)) { i = len;
} else if (STR_LITERAL_STARTSWITH(string, "off", len)) { i = len;
} else if (STR_LITERAL_STARTSWITH(string, "true", len)) { i = len;
diff --git a/source/blender/editors/space_text/text_format_py.c b/source/blender/editors/space_text/text_format_py.c
index 98eeee61c3a..d84beb79be6 100644
--- a/source/blender/editors/space_text/text_format_py.c
+++ b/source/blender/editors/space_text/text_format_py.c
@@ -58,11 +58,11 @@ static int txtfmt_py_find_builtinfunc(const char *string)
/* Keep aligned args for readability. */
/* clang-format off */
- if (STR_LITERAL_STARTSWITH(string, "and", len)) { i = len;
- } else if (STR_LITERAL_STARTSWITH(string, "as", len)) { i = len;
- } else if (STR_LITERAL_STARTSWITH(string, "assert", len)) { i = len;
+ if (STR_LITERAL_STARTSWITH(string, "assert", len)) { i = len;
} else if (STR_LITERAL_STARTSWITH(string, "async", len)) { i = len;
} else if (STR_LITERAL_STARTSWITH(string, "await", len)) { i = len;
+ } else if (STR_LITERAL_STARTSWITH(string, "and", len)) { i = len;
+ } else if (STR_LITERAL_STARTSWITH(string, "as", len)) { i = len;
} else if (STR_LITERAL_STARTSWITH(string, "break", len)) { i = len;
} else if (STR_LITERAL_STARTSWITH(string, "continue", len)) { i = len;
} else if (STR_LITERAL_STARTSWITH(string, "del", len)) { i = len;
@@ -114,7 +114,7 @@ static int txtfmt_py_find_specialvar(const char *string)
/* Keep aligned args for readability. */
/* clang-format off */
- if (STR_LITERAL_STARTSWITH(string, "def", len)) { i = len;
+ if (STR_LITERAL_STARTSWITH(string, "def", len)) { i = len;
} else if (STR_LITERAL_STARTSWITH(string, "class", len)) { i = len;
} else { i = 0;
}
@@ -155,7 +155,7 @@ static int txtfmt_py_find_bool(const char *string)
/* Keep aligned args for readability. */
/* clang-format off */
- if (STR_LITERAL_STARTSWITH(string, "None", len)) { i = len;
+ if (STR_LITERAL_STARTSWITH(string, "None", len)) { i = len;
} else if (STR_LITERAL_STARTSWITH(string, "True", len)) { i = len;
} else if (STR_LITERAL_STARTSWITH(string, "False", len)) { i = len;
} else { i = 0;
diff --git a/source/blender/editors/space_view3d/space_view3d.c b/source/blender/editors/space_view3d/space_view3d.c
index fbb6dfb8f8f..8b02a52d7f9 100644
--- a/source/blender/editors/space_view3d/space_view3d.c
+++ b/source/blender/editors/space_view3d/space_view3d.c
@@ -341,6 +341,9 @@ static SpaceLink *view3d_duplicate(SpaceLink *sl)
v3dn->runtime.properties_storage = NULL;
}
+ v3dn->local_collections_uuid = 0;
+ v3dn->flag &= ~V3D_LOCAL_COLLECTIONS;
+
if (v3dn->shading.type == OB_RENDER) {
v3dn->shading.type = OB_SOLID;
}
@@ -1096,6 +1099,9 @@ static void view3d_header_region_listener(wmWindow *UNUSED(win),
if (wmn->data & ND_GPENCIL_EDITMODE) {
ED_region_tag_redraw(ar);
}
+ else if (wmn->action == NA_EDITED) {
+ ED_region_tag_redraw(ar);
+ }
break;
case NC_BRUSH:
ED_region_tag_redraw(ar);
@@ -1460,7 +1466,7 @@ static int view3d_context(const bContext *C, const char *member, bContextDataRes
if (view_layer->basact) {
Object *ob = view_layer->basact->object;
/* if hidden but in edit mode, we still display, can happen with animation */
- if ((view_layer->basact->flag & BASE_VISIBLE) != 0 || (ob->mode & OB_MODE_EDIT)) {
+ if ((view_layer->basact->flag & BASE_VISIBLE_DEPSGRAPH) != 0 || (ob->mode & OB_MODE_EDIT)) {
CTX_data_pointer_set(result, &scene->id, &RNA_ObjectBase, view_layer->basact);
}
}
@@ -1472,7 +1478,8 @@ static int view3d_context(const bContext *C, const char *member, bContextDataRes
if (view_layer->basact) {
Object *ob = view_layer->basact->object;
/* if hidden but in edit mode, we still display, can happen with animation */
- if ((view_layer->basact->flag & BASE_VISIBLE) != 0 || (ob->mode & OB_MODE_EDIT) != 0) {
+ if ((view_layer->basact->flag & BASE_VISIBLE_DEPSGRAPH) != 0 ||
+ (ob->mode & OB_MODE_EDIT) != 0) {
CTX_data_id_pointer_set(result, &ob->id);
}
}
diff --git a/source/blender/editors/space_view3d/view3d_draw.c b/source/blender/editors/space_view3d/view3d_draw.c
index aafd36a5bb8..3ee9755cb06 100644
--- a/source/blender/editors/space_view3d/view3d_draw.c
+++ b/source/blender/editors/space_view3d/view3d_draw.c
@@ -1422,18 +1422,24 @@ static void draw_grid_unit_name(
{
if (!rv3d->is_persp && RV3D_VIEW_IS_AXIS(rv3d->view)) {
const char *grid_unit = NULL;
+ int font_id = BLF_default();
ED_view3d_grid_view_scale(scene, v3d, rv3d, &grid_unit);
if (grid_unit) {
char numstr[32] = "";
- UI_FontThemeColor(BLF_default(), TH_TEXT_HI);
+ UI_FontThemeColor(font_id, TH_TEXT_HI);
if (v3d->grid != 1.0f) {
BLI_snprintf(numstr, sizeof(numstr), "%s x %.4g", grid_unit, v3d->grid);
}
*yoffset -= U.widget_unit;
+ BLF_enable(font_id, BLF_SHADOW);
+ BLF_shadow(font_id, 5, (const float[4]){0.0f, 0.0f, 0.0f, 1.0f});
+ BLF_shadow_offset(font_id, 1, -1);
BLF_draw_default_ascii(
xoffset, *yoffset, 0.0f, numstr[0] ? numstr : grid_unit, sizeof(numstr));
+
+ BLF_disable(font_id, BLF_SHADOW);
}
}
}
diff --git a/source/blender/editors/space_view3d/view3d_draw_legacy.c b/source/blender/editors/space_view3d/view3d_draw_legacy.c
index acc46935eb5..17b575cedae 100644
--- a/source/blender/editors/space_view3d/view3d_draw_legacy.c
+++ b/source/blender/editors/space_view3d/view3d_draw_legacy.c
@@ -179,7 +179,7 @@ static void validate_object_select_id(
return;
}
- if (obact_eval && ((obact_eval->base_flag & BASE_VISIBLE) != 0)) {
+ if (obact_eval && ((obact_eval->base_flag & BASE_VISIBLE_DEPSGRAPH) != 0)) {
Base *base = BKE_view_layer_base_find(view_layer, obact);
DRW_select_buffer_context_create(&base, 1, -1);
}
@@ -226,7 +226,7 @@ void ED_view3d_backbuf_depth_validate(ViewContext *vc)
ARegion *ar = vc->ar;
Object *obact_eval = DEG_get_evaluated_object(vc->depsgraph, vc->obact);
- if (obact_eval && ((obact_eval->base_flag & BASE_VISIBLE) != 0)) {
+ if (obact_eval && ((obact_eval->base_flag & BASE_VISIBLE_DEPSGRAPH) != 0)) {
GPUViewport *viewport = WM_draw_region_get_viewport(ar, 0);
DRW_draw_depth_object(vc->ar, viewport, obact_eval);
}
diff --git a/source/blender/editors/space_view3d/view3d_gizmo_armature.c b/source/blender/editors/space_view3d/view3d_gizmo_armature.c
index 615589347da..dbad06da5ec 100644
--- a/source/blender/editors/space_view3d/view3d_gizmo_armature.c
+++ b/source/blender/editors/space_view3d/view3d_gizmo_armature.c
@@ -25,6 +25,7 @@
#include "BKE_armature.h"
#include "BKE_action.h"
#include "BKE_context.h"
+#include "BKE_layer.h"
#include "BKE_object.h"
#include "DNA_object_types.h"
diff --git a/source/blender/editors/space_view3d/view3d_gizmo_camera.c b/source/blender/editors/space_view3d/view3d_gizmo_camera.c
index 42931d5abb5..ba5ca5fbd15 100644
--- a/source/blender/editors/space_view3d/view3d_gizmo_camera.c
+++ b/source/blender/editors/space_view3d/view3d_gizmo_camera.c
@@ -24,6 +24,7 @@
#include "BKE_camera.h"
#include "BKE_context.h"
+#include "BKE_layer.h"
#include "DNA_object_types.h"
#include "DNA_camera_types.h"
diff --git a/source/blender/editors/space_view3d/view3d_gizmo_empty.c b/source/blender/editors/space_view3d/view3d_gizmo_empty.c
index b37f1e41294..793aec42dcd 100644
--- a/source/blender/editors/space_view3d/view3d_gizmo_empty.c
+++ b/source/blender/editors/space_view3d/view3d_gizmo_empty.c
@@ -22,6 +22,7 @@
#include "BLI_utildefines.h"
#include "BKE_context.h"
+#include "BKE_layer.h"
#include "BKE_object.h"
#include "BKE_image.h"
diff --git a/source/blender/editors/space_view3d/view3d_gizmo_forcefield.c b/source/blender/editors/space_view3d/view3d_gizmo_forcefield.c
index 44ad1d14dba..90b1539c8a7 100644
--- a/source/blender/editors/space_view3d/view3d_gizmo_forcefield.c
+++ b/source/blender/editors/space_view3d/view3d_gizmo_forcefield.c
@@ -21,6 +21,7 @@
#include "BLI_utildefines.h"
#include "BKE_context.h"
+#include "BKE_layer.h"
#include "BKE_object.h"
#include "DNA_object_types.h"
diff --git a/source/blender/editors/space_view3d/view3d_gizmo_light.c b/source/blender/editors/space_view3d/view3d_gizmo_light.c
index 35677b2e4c2..890de0ae611 100644
--- a/source/blender/editors/space_view3d/view3d_gizmo_light.c
+++ b/source/blender/editors/space_view3d/view3d_gizmo_light.c
@@ -22,6 +22,7 @@
#include "BLI_utildefines.h"
#include "BKE_context.h"
+#include "BKE_layer.h"
#include "BKE_object.h"
#include "DEG_depsgraph.h"
diff --git a/source/blender/editors/space_view3d/view3d_gizmo_ruler.c b/source/blender/editors/space_view3d/view3d_gizmo_ruler.c
index 5625333d837..a5b7fac624d 100644
--- a/source/blender/editors/space_view3d/view3d_gizmo_ruler.c
+++ b/source/blender/editors/space_view3d/view3d_gizmo_ruler.c
@@ -407,6 +407,17 @@ static bool view3d_ruler_item_mousemove(RulerInfo *ruler_info,
/** \name Ruler/Grease Pencil Conversion
* \{ */
+/* Helper: Find the layer created as ruler. */
+static bGPDlayer *view3d_ruler_layer_get(bGPdata *gpd)
+{
+ for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) {
+ if (gpl->flag & GP_LAYER_IS_RULER) {
+ return gpl;
+ }
+ }
+ return NULL;
+}
+
#define RULER_ID "RulerData3D"
static bool view3d_ruler_to_gpencil(bContext *C, wmGizmoGroup *gzgroup)
{
@@ -427,12 +438,12 @@ static bool view3d_ruler_to_gpencil(bContext *C, wmGizmoGroup *gzgroup)
}
gpd = scene->gpd;
- gpl = BLI_findstring(&gpd->layers, ruler_name, offsetof(bGPDlayer, info));
+ gpl = view3d_ruler_layer_get(gpd);
if (gpl == NULL) {
gpl = BKE_gpencil_layer_addnew(gpd, ruler_name, false);
copy_v4_v4(gpl->color, U.gpencil_new_layer_col);
gpl->thickness = 1;
- gpl->flag |= GP_LAYER_HIDE;
+ gpl->flag |= GP_LAYER_HIDE | GP_LAYER_IS_RULER;
}
gpf = BKE_gpencil_layer_getframe(gpl, CFRA, GP_GETFRAME_ADD_NEW);
@@ -485,8 +496,7 @@ static bool view3d_ruler_from_gpencil(const bContext *C, wmGizmoGroup *gzgroup)
if (scene->gpd) {
bGPDlayer *gpl;
- const char *ruler_name = RULER_ID;
- gpl = BLI_findstring(&scene->gpd->layers, ruler_name, offsetof(bGPDlayer, info));
+ gpl = view3d_ruler_layer_get(scene->gpd);
if (gpl) {
bGPDframe *gpf;
gpf = BKE_gpencil_layer_getframe(gpl, CFRA, GP_GETFRAME_USE_PREV);
diff --git a/source/blender/editors/space_view3d/view3d_ops.c b/source/blender/editors/space_view3d/view3d_ops.c
index 37eea6b03d7..cfdd3dcbb6f 100644
--- a/source/blender/editors/space_view3d/view3d_ops.c
+++ b/source/blender/editors/space_view3d/view3d_ops.c
@@ -79,11 +79,7 @@ static int view3d_copybuffer_exec(bContext *C, wmOperator *op)
BLI_make_file_string("/", str, BKE_tempdir_base(), "copybuffer.blend");
BKE_copybuffer_save(bmain, str, op->reports);
- BKE_reportf(op->reports,
- RPT_INFO,
- num_copied == 1 ? "Copied %d selected object" :
- "Copied %d selected objects",
- num_copied);
+ BKE_reportf(op->reports, RPT_INFO, "Copied %d selected object(s)", num_copied);
return OPERATOR_FINISHED;
}
@@ -122,11 +118,7 @@ static int view3d_pastebuffer_exec(bContext *C, wmOperator *op)
WM_event_add_notifier(C, NC_WINDOW, NULL);
- BKE_reportf(op->reports,
- RPT_INFO,
- num_pasted == 1 ? "%d object pasted" :
- "%d objects pasted",
- num_pasted);
+ BKE_reportf(op->reports, RPT_INFO, "%d object(s) pasted", num_pasted);
return OPERATOR_FINISHED;
}
diff --git a/source/blender/editors/space_view3d/view3d_select.c b/source/blender/editors/space_view3d/view3d_select.c
index 198b5d05540..3eee76277e8 100644
--- a/source/blender/editors/space_view3d/view3d_select.c
+++ b/source/blender/editors/space_view3d/view3d_select.c
@@ -1020,10 +1020,12 @@ static void do_lasso_select_armature__doSelectBone(void *userData,
is_ignore_flag |= BONESEL_TIP;
}
- if (is_inside_flag == (BONE_ROOTSEL | BONE_TIPSEL) ||
- BLI_lasso_is_edge_inside(
- data->mcords, data->moves, UNPACK2(screen_co_a), UNPACK2(screen_co_b), INT_MAX)) {
- is_inside_flag |= BONESEL_BONE;
+ if (is_ignore_flag == 0) {
+ if (is_inside_flag == (BONE_ROOTSEL | BONE_TIPSEL) ||
+ BLI_lasso_is_edge_inside(
+ data->mcords, data->moves, UNPACK2(screen_co_a), UNPACK2(screen_co_b), INT_MAX)) {
+ is_inside_flag |= BONESEL_BONE;
+ }
}
ebone->temp.i = is_inside_flag | (is_ignore_flag >> 16);
diff --git a/source/blender/editors/space_view3d/view3d_view.c b/source/blender/editors/space_view3d/view3d_view.c
index dd8e2e07271..d7af307bc53 100644
--- a/source/blender/editors/space_view3d/view3d_view.c
+++ b/source/blender/editors/space_view3d/view3d_view.c
@@ -1583,7 +1583,13 @@ static uint free_localcollection_bit(Main *bmain,
static void local_collections_reset_uuid(LayerCollection *layer_collection,
const unsigned short local_view_bit)
{
- layer_collection->local_collections_bits |= local_view_bit;
+ if (layer_collection->flag & LAYER_COLLECTION_HIDE) {
+ layer_collection->local_collections_bits &= ~local_view_bit;
+ }
+ else {
+ layer_collection->local_collections_bits |= local_view_bit;
+ }
+
LISTBASE_FOREACH (LayerCollection *, child, &layer_collection->layer_collections) {
local_collections_reset_uuid(child, local_view_bit);
}
diff --git a/source/blender/editors/space_view3d/view3d_walk.c b/source/blender/editors/space_view3d/view3d_walk.c
index ac9ad30d719..a7402a622d5 100644
--- a/source/blender/editors/space_view3d/view3d_walk.c
+++ b/source/blender/editors/space_view3d/view3d_walk.c
@@ -204,6 +204,8 @@ typedef struct WalkInfo {
* (this would need to un-key all previous frames).
*/
bool anim_playing;
+ bool need_rotation_keyframe;
+ bool need_translation_keyframe;
/** Previous 2D mouse values. */
int prev_mval[2];
@@ -538,6 +540,8 @@ static bool initWalkInfo(bContext *C, WalkInfo *walk, wmOperator *op)
#endif
walk->anim_playing = ED_screen_animation_playing(wm);
+ walk->need_rotation_keyframe = false;
+ walk->need_translation_keyframe = false;
walk->time_lastdraw = PIL_check_seconds_timer();
@@ -930,9 +934,12 @@ static void walkMoveCamera(bContext *C,
/* we only consider autokeying on playback or if user confirmed walk on the same frame
* otherwise we get a keyframe even if the user cancels. */
const bool use_autokey = is_confirm || walk->anim_playing;
-
ED_view3d_cameracontrol_update(
walk->v3d_camera_control, use_autokey, C, do_rotate, do_translate);
+ if (use_autokey) {
+ walk->need_rotation_keyframe = false;
+ walk->need_translation_keyframe = false;
+ }
}
static float getFreeFallDistance(const float gravity, const float time)
@@ -1280,9 +1287,10 @@ static int walkApply(bContext *C, WalkInfo *walk, bool is_confirm)
add_v3_v3(rv3d->ofs, dvec_tmp);
if (rv3d->persp == RV3D_CAMOB) {
- const bool do_rotate = (moffset[0] || moffset[1]);
- const bool do_translate = (walk->speed != 0.0f);
- walkMoveCamera(C, walk, do_rotate, do_translate, is_confirm);
+ walk->need_rotation_keyframe |= (moffset[0] || moffset[1]);
+ walk->need_translation_keyframe |= (len_squared_v3(dvec_tmp) > FLT_EPSILON);
+ walkMoveCamera(
+ C, walk, walk->need_rotation_keyframe, walk->need_translation_keyframe, is_confirm);
}
}
else {
@@ -1322,7 +1330,10 @@ static void walkApply_ndof(bContext *C, WalkInfo *walk, bool is_confirm)
walk->redraw = true;
if (walk->rv3d->persp == RV3D_CAMOB) {
- walkMoveCamera(C, walk, has_rotate, has_translate, is_confirm);
+ walk->need_rotation_keyframe |= has_rotate;
+ walk->need_translation_keyframe |= has_translate;
+ walkMoveCamera(
+ C, walk, walk->need_rotation_keyframe, walk->need_translation_keyframe, is_confirm);
}
}
}
diff --git a/source/blender/editors/transform/transform.c b/source/blender/editors/transform/transform.c
index 67ea0f255fc..b98c14150d5 100644
--- a/source/blender/editors/transform/transform.c
+++ b/source/blender/editors/transform/transform.c
@@ -2346,9 +2346,11 @@ bool initTransform(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *eve
}
}
- Object *ob = CTX_data_active_object(C);
- if (ob && ob->mode == OB_MODE_SCULPT && ob->sculpt) {
- options |= CTX_SCULPT;
+ if (CTX_wm_view3d(C) != NULL) {
+ Object *ob = CTX_data_active_object(C);
+ if (ob && ob->mode == OB_MODE_SCULPT && ob->sculpt) {
+ options |= CTX_SCULPT;
+ }
}
t->options = options;
diff --git a/source/blender/editors/transform/transform_convert.c b/source/blender/editors/transform/transform_convert.c
index 5862faaf667..64ad8b2091e 100644
--- a/source/blender/editors/transform/transform_convert.c
+++ b/source/blender/editors/transform/transform_convert.c
@@ -429,7 +429,7 @@ static void bone_children_clear_transflag(int mode, short around, ListBase *lb)
bone->flag |= BONE_TRANSFORM_CHILD;
}
else {
- bone->flag &= ~(BONE_TRANSFORM | BONE_TRANSFORM_MIRROR);
+ bone->flag &= ~BONE_TRANSFORM;
}
bone_children_clear_transflag(mode, around, &bone->childbase);
@@ -455,14 +455,14 @@ int count_set_pose_transflags(Object *ob,
bone->flag |= BONE_TRANSFORM;
}
else {
- bone->flag &= ~(BONE_TRANSFORM | BONE_TRANSFORM_MIRROR);
+ bone->flag &= ~BONE_TRANSFORM;
}
bone->flag &= ~BONE_HINGE_CHILD_TRANSFORM;
bone->flag &= ~BONE_TRANSFORM_CHILD;
}
else {
- bone->flag &= ~(BONE_TRANSFORM | BONE_TRANSFORM_MIRROR);
+ bone->flag &= ~BONE_TRANSFORM;
}
}
@@ -1542,8 +1542,8 @@ void autokeyframe_pose(bContext *C, Scene *scene, Object *ob, int tmode, short t
}
for (pchan = pose->chanbase.first; pchan; pchan = pchan->next) {
- if (pchan->bone->flag & (BONE_TRANSFORM | BONE_TRANSFORM_MIRROR)) {
-
+ if ((pchan->bone->flag & BONE_TRANSFORM) ||
+ ((pose->flag & POSE_MIRROR_EDIT) && (pchan->bone->flag & BONE_TRANSFORM_MIRROR))) {
ListBase dsources = {NULL, NULL};
/* clear any 'unkeyed' flag it may have */
diff --git a/source/blender/editors/transform/transform_convert_mesh.c b/source/blender/editors/transform/transform_convert_mesh.c
index 7f9c4ee2fcc..f1928433491 100644
--- a/source/blender/editors/transform/transform_convert_mesh.c
+++ b/source/blender/editors/transform/transform_convert_mesh.c
@@ -1451,7 +1451,7 @@ void createTransUVs(bContext *C, TransInfo *t)
const bool use_facesel = (ts->uv_flag & UV_SYNC_SELECTION) == 0;
elementmap = BM_uv_element_map_create(em->bm, use_facesel, false, true);
if (elementmap == NULL) {
- return;
+ continue;
}
if (is_prop_connected) {
diff --git a/source/blender/editors/transform/transform_generics.c b/source/blender/editors/transform/transform_generics.c
index 53e36f86a64..2e4f4344481 100644
--- a/source/blender/editors/transform/transform_generics.c
+++ b/source/blender/editors/transform/transform_generics.c
@@ -794,6 +794,12 @@ static void pose_transform_mirror_update(Object *ob, PoseInitData_Mirror *pid)
for (bPoseChannel *pchan_orig = ob->pose->chanbase.first; pchan_orig;
pchan_orig = pchan_orig->next) {
+ /* Clear the MIRROR flag from previous runs */
+ pchan_orig->bone->flag &= ~BONE_TRANSFORM_MIRROR;
+ }
+
+ for (bPoseChannel *pchan_orig = ob->pose->chanbase.first; pchan_orig;
+ pchan_orig = pchan_orig->next) {
/* no layer check, correct mirror is more important */
if (pchan_orig->bone->flag & BONE_TRANSFORM) {
bPoseChannel *pchan = BKE_pose_channel_get_mirrored(ob->pose, pchan_orig->name);
@@ -1707,7 +1713,9 @@ void initTransInfo(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *eve
}
}
else {
- if (ISMOUSE(t->launch_event) && (U.flag & USER_RELEASECONFIRM)) {
+ /* Release confirms preference should not affect node editor (T69288, T70504). */
+ if (ISMOUSE(t->launch_event) &&
+ ((U.flag & USER_RELEASECONFIRM) || (t->spacetype == SPACE_NODE))) {
/* Global "release confirm" on mouse bindings */
t->flag |= T_RELEASE_CONFIRM;
}
@@ -1832,7 +1840,7 @@ static void freeTransCustomData(TransInfo *t, TransDataContainer *tc, TransCusto
custom_data->data = NULL;
}
/* In case modes are switched in the same transform session. */
- custom_data->free_cb = false;
+ custom_data->free_cb = NULL;
custom_data->use_free = false;
}
diff --git a/source/blender/editors/transform/transform_gizmo_3d.c b/source/blender/editors/transform/transform_gizmo_3d.c
index 65fd9c6f5e9..157cf96a85e 100644
--- a/source/blender/editors/transform/transform_gizmo_3d.c
+++ b/source/blender/editors/transform/transform_gizmo_3d.c
@@ -516,9 +516,15 @@ static void protectflag_to_drawflags(short protectflag, short *drawflags)
}
/* for pose mode */
-static void protectflag_to_drawflags_pchan(RegionView3D *rv3d, const bPoseChannel *pchan)
+static void protectflag_to_drawflags_pchan(RegionView3D *rv3d,
+ const bPoseChannel *pchan,
+ short orientation_type)
{
- protectflag_to_drawflags(pchan->protectflag, &rv3d->twdrawflag);
+ /* Protect-flags apply to local space in pose mode, so only let them influence axis
+ * visibility if we show the global orientation, otherwise it's confusing. */
+ if (orientation_type == V3D_ORIENT_LOCAL) {
+ protectflag_to_drawflags(pchan->protectflag, &rv3d->twdrawflag);
+ }
}
/* for editmode*/
@@ -742,7 +748,14 @@ int ED_transform_calc_gizmo_stats(const bContext *C,
bGPdata *gpd = CTX_data_gpencil_data(C);
const bool is_gp_edit = GPENCIL_ANY_MODE(gpd);
int a, totsel = 0;
+
const int pivot_point = scene->toolsettings->transform_pivot_point;
+ const short orientation_type = params->orientation_type ?
+ (params->orientation_type - 1) :
+ scene->orientation_slots[SCE_ORIENT_DEFAULT].type;
+ const short orientation_index_custom =
+ params->orientation_type ? params->orientation_index_custom :
+ scene->orientation_slots[SCE_ORIENT_DEFAULT].index_custom;
/* transform widget matrix */
unit_m4(rv3d->twmat);
@@ -756,12 +769,6 @@ int ED_transform_calc_gizmo_stats(const bContext *C,
/* global, local or normal orientation?
* if we could check 'totsel' now, this should be skipped with no selection. */
if (ob) {
- const short orientation_type = params->orientation_type ?
- (params->orientation_type - 1) :
- scene->orientation_slots[SCE_ORIENT_DEFAULT].type;
- const short orientation_index_custom =
- params->orientation_type ? params->orientation_index_custom :
- scene->orientation_slots[SCE_ORIENT_DEFAULT].index_custom;
float mat[3][3];
ED_transform_calc_orientation_from_type_ex(
C, mat, scene, rv3d, ob, obedit, orientation_type, orientation_index_custom, pivot_point);
@@ -888,7 +895,7 @@ int ED_transform_calc_gizmo_stats(const bContext *C,
calc_tw_center_with_matrix(tbounds, ebo->head, use_mat_local, mat_local);
totsel++;
}
- if (ebo->flag & BONE_SELECTED) {
+ if (ebo->flag & (BONE_SELECTED | BONE_ROOTSEL | BONE_TIPSEL)) {
protectflag_to_drawflags_ebone(rv3d, ebo);
}
}
@@ -1038,7 +1045,7 @@ int ED_transform_calc_gizmo_stats(const bContext *C,
Bone *bone = pchan->bone;
if (bone && (bone->flag & BONE_TRANSFORM)) {
calc_tw_center_with_matrix(tbounds, pchan->pose_head, use_mat_local, mat_local);
- protectflag_to_drawflags_pchan(rv3d, pchan);
+ protectflag_to_drawflags_pchan(rv3d, pchan, orientation_type);
}
}
totsel += totsel_iter;
@@ -1122,7 +1129,12 @@ int ED_transform_calc_gizmo_stats(const bContext *C,
calc_tw_center(tbounds, co);
}
}
- protectflag_to_drawflags(base->object->protectflag, &rv3d->twdrawflag);
+
+ /* Protect-flags apply to world space in object mode, so only let them influence axis
+ * visibility if we show the global orientation, otherwise it's confusing. */
+ if (orientation_type == V3D_ORIENT_GLOBAL) {
+ protectflag_to_drawflags(base->object->protectflag, &rv3d->twdrawflag);
+ }
totsel++;
}
@@ -1338,6 +1350,7 @@ static void gizmo_xform_message_subscribe(wmGizmoGroup *gzgroup,
}
WM_msg_subscribe_rna_anon_prop(mbus, Window, view_layer, &msg_sub_value_gz_tag_refresh);
+ WM_msg_subscribe_rna_anon_prop(mbus, EditBone, lock, &msg_sub_value_gz_tag_refresh);
}
void drawDial3d(const TransInfo *t)
diff --git a/source/blender/editors/transform/transform_orientations.c b/source/blender/editors/transform/transform_orientations.c
index cbe9505d3f2..3159464072e 100644
--- a/source/blender/editors/transform/transform_orientations.c
+++ b/source/blender/editors/transform/transform_orientations.c
@@ -44,6 +44,7 @@
#include "BKE_curve.h"
#include "BKE_context.h"
#include "BKE_editmesh.h"
+#include "BKE_layer.h"
#include "BKE_report.h"
#include "BKE_scene.h"
#include "BKE_workspace.h"
diff --git a/source/blender/editors/transform/transform_snap_object.c b/source/blender/editors/transform/transform_snap_object.c
index 1601acb1c8f..f35a2808f22 100644
--- a/source/blender/editors/transform/transform_snap_object.c
+++ b/source/blender/editors/transform/transform_snap_object.c
@@ -47,6 +47,7 @@
#include "BKE_object.h"
#include "BKE_anim.h" /* for duplis */
#include "BKE_editmesh.h"
+#include "BKE_layer.h"
#include "BKE_main.h"
#include "BKE_tracking.h"
#include "BKE_context.h"
@@ -2367,6 +2368,7 @@ static short snapEditMesh(SnapObjectContext *sctx,
if (treedata_vert && (snapdata->snap_to_flag & SCE_SNAP_MODE_VERTEX)) {
BM_mesh_elem_table_ensure(em->bm, BM_VERT);
+ BM_mesh_elem_index_ensure(em->bm, BM_VERT);
BLI_bvhtree_find_nearest_projected(treedata_vert->tree,
lpmat,
snapdata->win_size,
@@ -2382,6 +2384,7 @@ static short snapEditMesh(SnapObjectContext *sctx,
int last_index = nearest.index;
nearest.index = -1;
BM_mesh_elem_table_ensure(em->bm, BM_EDGE | BM_VERT);
+ BM_mesh_elem_index_ensure(em->bm, BM_EDGE | BM_VERT);
BLI_bvhtree_find_nearest_projected(treedata_edge->tree,
lpmat,
snapdata->win_size,