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:
authorAntonioya <blendergit@gmail.com>2019-07-23 10:46:29 +0300
committerAntonioya <blendergit@gmail.com>2019-07-23 10:46:29 +0300
commit2204bfcf9e1c3a38e60830bd97775dd72158f4d6 (patch)
tree4f9c827389a23a431f8771b4ca02f410860c0242 /source/blender/editors
parentf64db794ee690f05905ace0a66d81d2e75549b90 (diff)
parent34ad6da4a06ef46cd19945f61cc5f968538546a8 (diff)
Merge branch 'master' into temp-gpencil-drw-engine
Diffstat (limited to 'source/blender/editors')
-rw-r--r--source/blender/editors/animation/anim_channels_edit.c3
-rw-r--r--source/blender/editors/animation/anim_filter.c6
-rw-r--r--source/blender/editors/animation/anim_motion_paths.c4
-rw-r--r--source/blender/editors/animation/keyframing.c33
-rw-r--r--source/blender/editors/armature/armature_add.c2
-rw-r--r--source/blender/editors/armature/armature_edit.c5
-rw-r--r--source/blender/editors/armature/armature_relations.c5
-rw-r--r--source/blender/editors/armature/armature_utils.c12
-rw-r--r--source/blender/editors/armature/editarmature_undo.c3
-rw-r--r--source/blender/editors/armature/pose_edit.c4
-rw-r--r--source/blender/editors/armature/pose_select.c48
-rw-r--r--source/blender/editors/armature/pose_slide.c2
-rw-r--r--source/blender/editors/curve/editcurve_undo.c6
-rw-r--r--source/blender/editors/curve/editfont.c16
-rw-r--r--source/blender/editors/curve/editfont_undo.c11
-rw-r--r--source/blender/editors/gizmo_library/gizmo_types/cage2d_gizmo.c1
-rw-r--r--source/blender/editors/gizmo_library/gizmo_types/dial3d_gizmo.c21
-rw-r--r--source/blender/editors/gpencil/drawgpencil.c2
-rw-r--r--source/blender/editors/gpencil/gpencil_brush.c23
-rw-r--r--source/blender/editors/gpencil/gpencil_data.c58
-rw-r--r--source/blender/editors/gpencil/gpencil_edit.c84
-rw-r--r--source/blender/editors/gpencil/gpencil_interpolate.c5
-rw-r--r--source/blender/editors/gpencil/gpencil_paint.c2
-rw-r--r--source/blender/editors/gpencil/gpencil_primitive.c9
-rw-r--r--source/blender/editors/include/BIF_glutil.h2
-rw-r--r--source/blender/editors/include/ED_armature.h6
-rw-r--r--source/blender/editors/include/ED_mesh.h3
-rw-r--r--source/blender/editors/include/ED_object.h3
-rw-r--r--source/blender/editors/include/ED_render.h3
-rw-r--r--source/blender/editors/include/ED_screen.h1
-rw-r--r--source/blender/editors/include/ED_text.h4
-rw-r--r--source/blender/editors/include/ED_transform_snap_object_context.h20
-rw-r--r--source/blender/editors/include/ED_undo.h3
-rw-r--r--source/blender/editors/include/UI_icons.h6
-rw-r--r--source/blender/editors/include/UI_interface.h2
-rw-r--r--source/blender/editors/include/UI_resources.h1
-rw-r--r--source/blender/editors/include/UI_view2d.h2
-rw-r--r--source/blender/editors/interface/interface.c3
-rw-r--r--source/blender/editors/interface/interface_align.c2
-rw-r--r--source/blender/editors/interface/interface_context_menu.c34
-rw-r--r--source/blender/editors/interface/interface_eyedropper_colorband.c48
-rw-r--r--source/blender/editors/interface/interface_eyedropper_depth.c6
-rw-r--r--source/blender/editors/interface/interface_handlers.c56
-rw-r--r--source/blender/editors/interface/interface_icons.c5
-rw-r--r--source/blender/editors/interface/interface_ops.c25
-rw-r--r--source/blender/editors/interface/interface_region_color_picker.c20
-rw-r--r--source/blender/editors/interface/interface_region_hud.c6
-rw-r--r--source/blender/editors/interface/interface_region_popover.c4
-rw-r--r--source/blender/editors/interface/interface_templates.c2
-rw-r--r--source/blender/editors/interface/interface_widgets.c2
-rw-r--r--source/blender/editors/interface/resources.c20
-rw-r--r--source/blender/editors/io/io_collada.c12
-rw-r--r--source/blender/editors/lattice/editlattice_undo.c17
-rw-r--r--source/blender/editors/mask/mask_add.c6
-rw-r--r--source/blender/editors/mask/mask_ops.c3
-rw-r--r--source/blender/editors/mesh/editmesh_bevel.c4
-rw-r--r--source/blender/editors/mesh/editmesh_tools.c709
-rw-r--r--source/blender/editors/mesh/editmesh_undo.c3
-rw-r--r--source/blender/editors/mesh/mesh_data.c34
-rw-r--r--source/blender/editors/metaball/editmball_undo.c3
-rw-r--r--source/blender/editors/object/object_add.c161
-rw-r--r--source/blender/editors/object/object_bake_api.c36
-rw-r--r--source/blender/editors/object/object_constraint.c182
-rw-r--r--source/blender/editors/object/object_select.c19
-rw-r--r--source/blender/editors/object/object_transform.c37
-rw-r--r--source/blender/editors/object/object_vgroup.c19
-rw-r--r--source/blender/editors/physics/particle_edit.c40
-rw-r--r--source/blender/editors/physics/particle_edit_undo.c3
-rw-r--r--source/blender/editors/physics/physics_fluid.c3
-rw-r--r--source/blender/editors/render/render_internal.c19
-rw-r--r--source/blender/editors/render/render_preview.c33
-rw-r--r--source/blender/editors/screen/glutil.c14
-rw-r--r--source/blender/editors/screen/screen_ops.c23
-rw-r--r--source/blender/editors/screen/screen_user_menu.c2
-rw-r--r--source/blender/editors/screen/screendump.c21
-rw-r--r--source/blender/editors/screen/workspace_edit.c64
-rw-r--r--source/blender/editors/sculpt_paint/paint_cursor.c6
-rw-r--r--source/blender/editors/sculpt_paint/paint_curve_undo.c3
-rw-r--r--source/blender/editors/sculpt_paint/paint_hide.c7
-rw-r--r--source/blender/editors/sculpt_paint/paint_image_proj.c5
-rw-r--r--source/blender/editors/sculpt_paint/paint_image_undo.c6
-rw-r--r--source/blender/editors/sculpt_paint/paint_mask.c6
-rw-r--r--source/blender/editors/sculpt_paint/paint_vertex.c59
-rw-r--r--source/blender/editors/sculpt_paint/sculpt.c4
-rw-r--r--source/blender/editors/sculpt_paint/sculpt_undo.c10
-rw-r--r--source/blender/editors/sound/sound_ops.c7
-rw-r--r--source/blender/editors/space_clip/clip_draw.c6
-rw-r--r--source/blender/editors/space_clip/clip_ops.c5
-rw-r--r--source/blender/editors/space_clip/space_clip.c8
-rw-r--r--source/blender/editors/space_clip/tracking_ops_plane.c6
-rw-r--r--source/blender/editors/space_file/file_ops.c8
-rw-r--r--source/blender/editors/space_image/image_draw.c5
-rw-r--r--source/blender/editors/space_image/image_ops.c10
-rw-r--r--source/blender/editors/space_image/space_image.c10
-rw-r--r--source/blender/editors/space_info/info_ops.c17
-rw-r--r--source/blender/editors/space_node/node_edit.c2
-rw-r--r--source/blender/editors/space_node/node_view.c2
-rw-r--r--source/blender/editors/space_outliner/outliner_collections.c2
-rw-r--r--source/blender/editors/space_outliner/outliner_draw.c79
-rw-r--r--source/blender/editors/space_outliner/outliner_tools.c97
-rw-r--r--source/blender/editors/space_outliner/outliner_tree.c4
-rw-r--r--source/blender/editors/space_sequencer/sequencer_draw.c8
-rw-r--r--source/blender/editors/space_text/text_autocomplete.c16
-rw-r--r--source/blender/editors/space_text/text_ops.c82
-rw-r--r--source/blender/editors/space_text/text_undo.c155
-rw-r--r--source/blender/editors/space_userpref/userpref_ops.c4
-rw-r--r--source/blender/editors/space_view3d/space_view3d.c3
-rw-r--r--source/blender/editors/space_view3d/view3d_draw.c14
-rw-r--r--source/blender/editors/space_view3d/view3d_edit.c5
-rw-r--r--source/blender/editors/space_view3d/view3d_gizmo_preselect_type.c2
-rw-r--r--source/blender/editors/space_view3d/view3d_gizmo_ruler.c41
-rw-r--r--source/blender/editors/space_view3d/view3d_iterators.c12
-rw-r--r--source/blender/editors/space_view3d/view3d_select.c94
-rw-r--r--source/blender/editors/space_view3d/view3d_snap.c36
-rw-r--r--source/blender/editors/space_view3d/view3d_view.c22
-rw-r--r--source/blender/editors/transform/transform.c58
-rw-r--r--source/blender/editors/transform/transform_constraints.c26
-rw-r--r--source/blender/editors/transform/transform_conversions.c113
-rw-r--r--source/blender/editors/transform/transform_gizmo_3d.c12
-rw-r--r--source/blender/editors/transform/transform_ops.c13
-rw-r--r--source/blender/editors/transform/transform_snap.c9
-rw-r--r--source/blender/editors/transform/transform_snap_object.c22
-rw-r--r--source/blender/editors/undo/ed_undo.c41
-rw-r--r--source/blender/editors/undo/memfile_undo.c6
-rw-r--r--source/blender/editors/util/ed_util.c16
-rw-r--r--source/blender/editors/util/select_buffer_utils.c6
-rw-r--r--source/blender/editors/uvedit/uvedit_draw.c9
-rw-r--r--source/blender/editors/uvedit/uvedit_unwrap_ops.c1
128 files changed, 2056 insertions, 1265 deletions
diff --git a/source/blender/editors/animation/anim_channels_edit.c b/source/blender/editors/animation/anim_channels_edit.c
index 21b9c7252d2..b93d52a1b2d 100644
--- a/source/blender/editors/animation/anim_channels_edit.c
+++ b/source/blender/editors/animation/anim_channels_edit.c
@@ -1711,8 +1711,7 @@ static void update_dependencies_on_delete(bAnimListElem *ale)
AnimData *adt = BKE_animdata_from_id(id);
/* TODO(sergey): Technically, if the animation element is being deleted
* from a driver we don't have to tag action. This is something we can check
- * for in the future. For now just do most reliable tag whic hwas always
- * happening. */
+ * for in the future. For now just do most reliable tag which was always happening. */
if (adt != NULL) {
DEG_id_tag_update(id, ID_RECALC_ANIMATION);
if (adt->action != NULL) {
diff --git a/source/blender/editors/animation/anim_filter.c b/source/blender/editors/animation/anim_filter.c
index 8d30076103b..2d16ce30d31 100644
--- a/source/blender/editors/animation/anim_filter.c
+++ b/source/blender/editors/animation/anim_filter.c
@@ -2231,7 +2231,7 @@ static size_t animdata_filter_ds_textures(
}
}
- /* Firstly check that we actuallly have some textures,
+ /* Firstly check that we actually have some textures,
* by gathering all textures in a temp list. */
for (a = 0; a < MAX_MTEX; a++) {
Tex *tex = (mtex[a]) ? mtex[a]->tex : NULL;
@@ -3151,7 +3151,9 @@ static size_t animdata_filter_dopesheet(bAnimContext *ac,
}
/* movie clip's animation */
- items += animdata_filter_dopesheet_movieclips(ac, anim_data, ads, filter_mode);
+ if (!(ads->filterflag2 & ADS_FILTER_NOMOVIECLIPS) && !(ads->filterflag & ADS_FILTER_ONLYSEL)) {
+ items += animdata_filter_dopesheet_movieclips(ac, anim_data, ads, filter_mode);
+ }
/* Scene-linked animation - e.g. world, compositing nodes, scene anim
* (including sequencer currently). */
diff --git a/source/blender/editors/animation/anim_motion_paths.c b/source/blender/editors/animation/anim_motion_paths.c
index d3c6109afcd..7a5b57b1ce6 100644
--- a/source/blender/editors/animation/anim_motion_paths.c
+++ b/source/blender/editors/animation/anim_motion_paths.c
@@ -322,8 +322,8 @@ void animviz_calc_motionpaths(Depsgraph *depsgraph,
/* reset original environment */
/* NOTE: We don't always need to reevaluate the main scene, as the depsgraph
- * may be a temporary one that works on a subset of the data. We always have
- * to resoture the current frame though. */
+ * may be a temporary one that works on a subset of the data.
+ * We always have to restore the current frame though. */
CFRA = cfra;
if (!current_frame_only && restore) {
motionpaths_calc_update_scene(bmain, depsgraph);
diff --git a/source/blender/editors/animation/keyframing.c b/source/blender/editors/animation/keyframing.c
index 31f7a337d57..2e7ed7eae34 100644
--- a/source/blender/editors/animation/keyframing.c
+++ b/source/blender/editors/animation/keyframing.c
@@ -532,7 +532,7 @@ int insert_vert_fcurve(
* introduced discontinuities in how the param worked. */
beztr.back = 1.70158f;
- /* "elastic" easing - values here were hand-optimised for a default duration of
+ /* "elastic" easing - values here were hand-optimized for a default duration of
* ~10 frames (typical mograph motion length) */
beztr.amplitude = 0.8f;
beztr.period = 4.1f;
@@ -2249,10 +2249,16 @@ static int delete_key_v3d_exec(bContext *C, wmOperator *op)
Scene *scene = CTX_data_scene(C);
float cfra = (float)CFRA;
+ int selected_objects_len = 0;
+ int selected_objects_success_len = 0;
+ int success_multi = 0;
+
CTX_DATA_BEGIN (C, Object *, ob, selected_objects) {
ID *id = &ob->id;
int success = 0;
+ selected_objects_len += 1;
+
/* just those in active action... */
if ((ob->adt) && (ob->adt->action)) {
AnimData *adt = ob->adt;
@@ -2317,22 +2323,29 @@ static int delete_key_v3d_exec(bContext *C, wmOperator *op)
DEG_id_tag_update(&ob->adt->action->id, ID_RECALC_ANIMATION_NO_FLUSH);
}
- /* report success (or failure) */
+ /* Only for reporting. */
if (success) {
- BKE_reportf(op->reports,
- RPT_INFO,
- "Object '%s' successfully had %d keyframes removed",
- id->name + 2,
- success);
- }
- else {
- BKE_reportf(op->reports, RPT_ERROR, "No keyframes removed from Object '%s'", id->name + 2);
+ selected_objects_success_len += 1;
+ success_multi += success;
}
DEG_id_tag_update(&ob->id, ID_RECALC_TRANSFORM);
}
CTX_DATA_END;
+ /* report success (or failure) */
+ if (selected_objects_success_len) {
+ BKE_reportf(op->reports,
+ RPT_INFO,
+ "%d object(s) successfully had %d keyframes removed",
+ selected_objects_success_len,
+ success_multi);
+ }
+ else {
+ BKE_reportf(
+ op->reports, RPT_ERROR, "No keyframes removed from %d object(s)", selected_objects_len);
+ }
+
/* send updates */
WM_event_add_notifier(C, NC_OBJECT | ND_KEYS, NULL);
diff --git a/source/blender/editors/armature/armature_add.c b/source/blender/editors/armature/armature_add.c
index d02e58d48a9..d2fa77f90be 100644
--- a/source/blender/editors/armature/armature_add.c
+++ b/source/blender/editors/armature/armature_add.c
@@ -1121,6 +1121,8 @@ static int armature_bone_primitive_add_exec(bContext *C, wmOperator *op)
add_v3_v3v3(bone->tail, bone->head, imat[2]); // bone with unit length 1, pointing up Z
}
+ ED_armature_edit_refresh_layer_used(obedit->data);
+
/* note, notifier might evolve */
WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, obedit);
diff --git a/source/blender/editors/armature/armature_edit.c b/source/blender/editors/armature/armature_edit.c
index c5430e06b6e..4e6661b1d15 100644
--- a/source/blender/editors/armature/armature_edit.c
+++ b/source/blender/editors/armature/armature_edit.c
@@ -862,6 +862,7 @@ static int armature_fill_bones_exec(bContext *C, wmOperator *op)
}
/* updates */
+ ED_armature_edit_refresh_layer_used(arm);
WM_event_add_notifier(C, NC_OBJECT | ND_POSE, obedit);
/* free points */
@@ -1053,6 +1054,7 @@ static int armature_merge_exec(bContext *C, wmOperator *op)
/* updates */
ED_armature_edit_sync_selection(arm->edbo);
+ ED_armature_edit_refresh_layer_used(arm);
WM_event_add_notifier(C, NC_OBJECT | ND_POSE, obedit);
}
MEM_freeN(objects);
@@ -1460,8 +1462,8 @@ static int armature_delete_selected_exec(bContext *C, wmOperator *UNUSED(op))
changed_multi = true;
ED_armature_edit_sync_selection(arm->edbo);
+ ED_armature_edit_refresh_layer_used(arm);
BKE_pose_tag_recalc(CTX_data_main(C), obedit->pose);
-
WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, obedit);
}
}
@@ -1635,6 +1637,7 @@ static int armature_dissolve_selected_exec(bContext *C, wmOperator *UNUSED(op))
if (changed) {
changed_multi = true;
ED_armature_edit_sync_selection(arm->edbo);
+ ED_armature_edit_refresh_layer_used(arm);
WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, obedit);
}
}
diff --git a/source/blender/editors/armature/armature_relations.c b/source/blender/editors/armature/armature_relations.c
index 2c61818d902..8722e575d15 100644
--- a/source/blender/editors/armature/armature_relations.c
+++ b/source/blender/editors/armature/armature_relations.c
@@ -38,6 +38,7 @@
#include "BKE_action.h"
#include "BKE_animsys.h"
+#include "BKE_armature.h"
#include "BKE_constraint.h"
#include "BKE_context.h"
#include "BKE_fcurve.h"
@@ -426,6 +427,7 @@ int join_armature_exec(bContext *C, wmOperator *op)
ED_armature_from_edit(bmain, arm);
ED_armature_edit_free(arm);
+ BKE_armature_refresh_layer_used(arm);
DEG_id_tag_update(&scene->id, ID_RECALC_SELECT);
WM_event_add_notifier(C, NC_SCENE | ND_OB_ACTIVE, scene);
@@ -671,6 +673,9 @@ static int separate_armature_exec(bContext *C, wmOperator *op)
ED_armature_to_edit(obedit->data);
+ ED_armature_edit_refresh_layer_used(obedit->data);
+ BKE_armature_refresh_layer_used(newob->data);
+
/* parents tips remain selected when connected children are removed. */
ED_armature_edit_deselect_all(obedit);
diff --git a/source/blender/editors/armature/armature_utils.c b/source/blender/editors/armature/armature_utils.c
index 5d424594229..d8777b7e0b7 100644
--- a/source/blender/editors/armature/armature_utils.c
+++ b/source/blender/editors/armature/armature_utils.c
@@ -85,6 +85,18 @@ void ED_armature_edit_validate_active(struct bArmature *arm)
}
}
+/* Update the layers_used variable after bones are moved between layer
+ * NOTE: Used to be done in drawing code in 2.7, but that won't work with
+ * Copy-on-Write, as drawing uses evaluated copies.
+ */
+void ED_armature_edit_refresh_layer_used(bArmature *arm)
+{
+ arm->layer_used = 0;
+ for (EditBone *ebo = arm->edbo->first; ebo; ebo = ebo->next) {
+ arm->layer_used |= ebo->layer;
+ }
+}
+
/* *************************************************************** */
/* Bone Operations */
diff --git a/source/blender/editors/armature/editarmature_undo.c b/source/blender/editors/armature/editarmature_undo.c
index 3a2440af2da..4a82a8fccee 100644
--- a/source/blender/editors/armature/editarmature_undo.c
+++ b/source/blender/editors/armature/editarmature_undo.c
@@ -174,7 +174,8 @@ static bool armature_undosys_step_encode(struct bContext *C,
static void armature_undosys_step_decode(struct bContext *C,
struct Main *UNUSED(bmain),
UndoStep *us_p,
- int UNUSED(dir))
+ int UNUSED(dir),
+ bool UNUSED(is_final))
{
ArmatureUndoStep *us = (ArmatureUndoStep *)us_p;
diff --git a/source/blender/editors/armature/pose_edit.c b/source/blender/editors/armature/pose_edit.c
index 745af06c7af..5daf6b584e5 100644
--- a/source/blender/editors/armature/pose_edit.c
+++ b/source/blender/editors/armature/pose_edit.c
@@ -872,6 +872,8 @@ static int pose_bone_layers_exec(bContext *C, wmOperator *op)
RNA_boolean_set_array(&ptr, "layers", layers);
if (prev_ob != ob) {
+ BKE_armature_refresh_layer_used(ob->data);
+
/* Note, notifier might evolve. */
WM_event_add_notifier(C, NC_OBJECT | ND_POSE, ob);
DEG_id_tag_update((ID *)ob->data, ID_RECALC_COPY_ON_WRITE);
@@ -949,6 +951,8 @@ static int armature_bone_layers_exec(bContext *C, wmOperator *op)
}
CTX_DATA_END;
+ ED_armature_edit_refresh_layer_used(ob->data);
+
/* note, notifier might evolve */
WM_event_add_notifier(C, NC_OBJECT | ND_POSE, ob);
diff --git a/source/blender/editors/armature/pose_select.c b/source/blender/editors/armature/pose_select.c
index e9ea49aaf03..8434fee6e78 100644
--- a/source/blender/editors/armature/pose_select.c
+++ b/source/blender/editors/armature/pose_select.c
@@ -40,6 +40,7 @@
#include "BKE_object.h"
#include "BKE_report.h"
#include "BKE_layer.h"
+#include "BKE_modifier.h"
#include "DEG_depsgraph.h"
@@ -181,10 +182,17 @@ bool ED_armature_pose_select_pick_with_buffer(ViewLayer *view_layer,
if (!extend && !deselect && !toggle) {
{
- uint bases_len = 0;
- Base **bases = BKE_object_pose_base_array_get_unique(view_layer, v3d, &bases_len);
- ED_pose_deselect_all_multi_ex(bases, bases_len, SEL_DESELECT, true);
- MEM_freeN(bases);
+ /* Don't use 'BKE_object_pose_base_array_get_unique'
+ * because we may be selecting from object mode. */
+ FOREACH_VISIBLE_BASE_BEGIN (view_layer, v3d, base_iter) {
+ Object *ob_iter = base_iter->object;
+ if ((ob_iter->type == OB_ARMATURE) && (ob_iter->mode & OB_MODE_POSE)) {
+ if (ED_pose_deselect_all(ob_iter, SEL_DESELECT, true)) {
+ ED_pose_bone_select_tag_update(ob_iter);
+ }
+ }
+ }
+ FOREACH_VISIBLE_BASE_END;
}
nearBone->flag |= (BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
arm->act_bone = nearBone;
@@ -240,6 +248,38 @@ bool ED_armature_pose_select_pick_with_buffer(ViewLayer *view_layer,
return nearBone != NULL;
}
+/**
+ * While in weight-paint mode, a single pose may be active as well.
+ * While not common, it's possible we have multiple armatures deforming a mesh.
+ *
+ * This function de-selects all other objects, and selects the new base.
+ * It can't be set to the active object because we need
+ * to keep this set to the weight paint object.
+ */
+void ED_armature_pose_select_in_wpaint_mode(ViewLayer *view_layer, Base *base_select)
+{
+ BLI_assert(base_select && (base_select->object->type == OB_ARMATURE));
+ Object *ob_active = OBACT(view_layer);
+ BLI_assert(ob_active && (ob_active->mode & OB_MODE_WEIGHT_PAINT));
+ VirtualModifierData virtualModifierData;
+ ModifierData *md = modifiers_getVirtualModifierList(ob_active, &virtualModifierData);
+ for (; md; md = md->next) {
+ if (md->type == eModifierType_Armature) {
+ ArmatureModifierData *amd = (ArmatureModifierData *)md;
+ Object *ob_arm = amd->object;
+ if (ob_arm != NULL) {
+ Base *base_arm = BKE_view_layer_base_find(view_layer, ob_arm);
+ if ((base_arm != NULL) && (base_arm != base_select) && (base_arm->flag & BASE_SELECTED)) {
+ ED_object_base_select(base_arm, BA_DESELECT);
+ }
+ }
+ }
+ }
+ if ((base_select->flag & BASE_SELECTED) == 0) {
+ ED_object_base_select(base_select, BA_SELECT);
+ }
+}
+
/* 'select_mode' is usual SEL_SELECT/SEL_DESELECT/SEL_TOGGLE/SEL_INVERT.
* When true, 'ignore_visibility' makes this func also affect invisible bones
* (hidden or on hidden layers). */
diff --git a/source/blender/editors/armature/pose_slide.c b/source/blender/editors/armature/pose_slide.c
index 97317a86104..4c5a42cade6 100644
--- a/source/blender/editors/armature/pose_slide.c
+++ b/source/blender/editors/armature/pose_slide.c
@@ -584,7 +584,7 @@ static void pose_slide_apply_quat(tPoseSlideOp *pso, tPChanFCurveLink *pfl)
/* perform blending */
if (pso->mode == POSESLIDE_BREAKDOWN) {
- /* Just perform the interpol between quat_prev and
+ /* Just perform the interpolation between quat_prev and
* quat_next using pso->percentage as a guide. */
interp_qt_qtqt(quat_final, quat_prev, quat_next, pso->percentage);
}
diff --git a/source/blender/editors/curve/editcurve_undo.c b/source/blender/editors/curve/editcurve_undo.c
index d0c2afcb1d2..835abd1a630 100644
--- a/source/blender/editors/curve/editcurve_undo.c
+++ b/source/blender/editors/curve/editcurve_undo.c
@@ -238,10 +238,8 @@ static bool curve_undosys_step_encode(struct bContext *C,
return true;
}
-static void curve_undosys_step_decode(struct bContext *C,
- struct Main *bmain,
- UndoStep *us_p,
- int UNUSED(dir))
+static void curve_undosys_step_decode(
+ struct bContext *C, struct Main *bmain, UndoStep *us_p, int UNUSED(dir), bool UNUSED(is_final))
{
CurveUndoStep *us = (CurveUndoStep *)us_p;
diff --git a/source/blender/editors/curve/editfont.c b/source/blender/editors/curve/editfont.c
index ffbfb692ca9..db3d5ad401d 100644
--- a/source/blender/editors/curve/editfont.c
+++ b/source/blender/editors/curve/editfont.c
@@ -73,9 +73,9 @@ static int kill_selection(Object *obedit, int ins);
/************************* utilities ******************************/
-static char findaccent(char char1, unsigned int code)
+static wchar_t findaccent(wchar_t char1, unsigned int code)
{
- char new = 0;
+ wchar_t new = 0;
if (char1 == 'a') {
if (code == '`') {
@@ -170,7 +170,7 @@ static char findaccent(char char1, unsigned int code)
new = 186;
}
else if (code == 'e') {
- new = 143;
+ new = 339;
}
else if (code == 'c') {
new = 169;
@@ -191,7 +191,7 @@ static char findaccent(char char1, unsigned int code)
}
else if (char1 == 't') {
if (code == 'm') {
- new = 153;
+ new = 8482;
}
}
else if (char1 == 'u') {
@@ -342,7 +342,7 @@ static char findaccent(char char1, unsigned int code)
new = 247;
}
if (code == '|') {
- new = 135;
+ new = 8224;
}
if (code == '+') {
new = 177;
@@ -350,15 +350,15 @@ static char findaccent(char char1, unsigned int code)
}
else if (char1 == '|') {
if (code == '-') {
- new = 135;
+ new = 8224;
}
if (code == '=') {
- new = 136;
+ new = 8225;
}
}
else if (char1 == '=') {
if (code == '|') {
- new = 136;
+ new = 8225;
}
}
else if (char1 == '+') {
diff --git a/source/blender/editors/curve/editfont_undo.c b/source/blender/editors/curve/editfont_undo.c
index 82c19db7a4a..2f8f15bc6c7 100644
--- a/source/blender/editors/curve/editfont_undo.c
+++ b/source/blender/editors/curve/editfont_undo.c
@@ -62,7 +62,7 @@ typedef struct UndoFont {
wchar_t *textbuf;
struct CharInfo *textbufinfo;
- int len, pos;
+ int len, pos, selstart, selend;
#ifdef USE_ARRAY_STORE
struct {
@@ -241,10 +241,10 @@ static void undofont_to_editfont(UndoFont *uf, Curve *cu)
memcpy(ef->textbufinfo, uf->textbufinfo, final_size);
ef->pos = uf->pos;
+ ef->selstart = uf->selstart;
+ ef->selend = uf->selend;
ef->len = uf->len;
- ef->selstart = ef->selend = 0;
-
#ifdef USE_ARRAY_STORE
uf_arraystore_expand_clear(uf);
#endif
@@ -269,6 +269,8 @@ static void *undofont_from_editfont(UndoFont *uf, Curve *cu)
memcpy(uf->textbufinfo, ef->textbufinfo, final_size);
uf->pos = ef->pos;
+ uf->selstart = ef->selstart;
+ uf->selend = ef->selend;
uf->len = ef->len;
#ifdef USE_ARRAY_STORE
@@ -356,7 +358,8 @@ static bool font_undosys_step_encode(struct bContext *C,
static void font_undosys_step_decode(struct bContext *C,
struct Main *UNUSED(bmain),
UndoStep *us_p,
- int UNUSED(dir))
+ int UNUSED(dir),
+ bool UNUSED(is_final))
{
/* TODO(campbell): undo_system: use low-level API to set mode. */
ED_object_mode_set(C, OB_MODE_EDIT);
diff --git a/source/blender/editors/gizmo_library/gizmo_types/cage2d_gizmo.c b/source/blender/editors/gizmo_library/gizmo_types/cage2d_gizmo.c
index 780cca66fb9..ba3b8c2602e 100644
--- a/source/blender/editors/gizmo_library/gizmo_types/cage2d_gizmo.c
+++ b/source/blender/editors/gizmo_library/gizmo_types/cage2d_gizmo.c
@@ -101,6 +101,7 @@ static bool gizmo_calc_rect_view_margin(const wmGizmo *gz, const float dims[2],
handle_size *= gz->scale_final;
float scale_xy[2];
if (!gizmo_calc_rect_view_scale(gz, dims, scale_xy)) {
+ zero_v2(margin);
return false;
}
margin[0] = ((handle_size * scale_xy[0]));
diff --git a/source/blender/editors/gizmo_library/gizmo_types/dial3d_gizmo.c b/source/blender/editors/gizmo_library/gizmo_types/dial3d_gizmo.c
index 31e30a0dd1a..6d8ab096a26 100644
--- a/source/blender/editors/gizmo_library/gizmo_types/dial3d_gizmo.c
+++ b/source/blender/editors/gizmo_library/gizmo_types/dial3d_gizmo.c
@@ -129,7 +129,26 @@ static void dial_geom_draw(const float color[4],
immUniformColor4fv(color);
if (filled) {
- imm_draw_circle_fill_2d(pos, 0, 0, 1.0, DIAL_RESOLUTION);
+ if (arc_partial_angle == 0.0f) {
+ if (arc_inner_factor == 0.0f) {
+ imm_draw_circle_fill_2d(pos, 0, 0, 1.0, DIAL_RESOLUTION);
+ }
+ else {
+ imm_draw_disk_partial_fill_2d(
+ pos, 0, 0, arc_inner_factor, 1.0f, DIAL_RESOLUTION, 0, RAD2DEGF(M_PI * 2));
+ }
+ }
+ else {
+ float arc_partial_deg = RAD2DEGF((M_PI * 2) - arc_partial_angle);
+ imm_draw_disk_partial_fill_2d(pos,
+ 0,
+ 0,
+ arc_inner_factor,
+ 1.0f,
+ DIAL_RESOLUTION,
+ -arc_partial_deg / 2,
+ arc_partial_deg);
+ }
}
else {
if (arc_partial_angle == 0.0f) {
diff --git a/source/blender/editors/gpencil/drawgpencil.c b/source/blender/editors/gpencil/drawgpencil.c
index 5f08035a56b..809acc3b322 100644
--- a/source/blender/editors/gpencil/drawgpencil.c
+++ b/source/blender/editors/gpencil/drawgpencil.c
@@ -888,7 +888,7 @@ static void gp_draw_strokes(tGPDdraw *tgpw)
/* if disable fill, the colors with fill must be omitted too except fill boundary strokes */
if ((tgpw->disable_fill == 1) && (gp_style->fill_rgba[3] > 0.0f) &&
- ((gps->flag & GP_STROKE_NOFILL) == 0)) {
+ ((gps->flag & GP_STROKE_NOFILL) == 0) && (gp_style->flag & GP_STYLE_FILL_SHOW)) {
continue;
}
diff --git a/source/blender/editors/gpencil/gpencil_brush.c b/source/blender/editors/gpencil/gpencil_brush.c
index f5b27d8268d..7d866aedd87 100644
--- a/source/blender/editors/gpencil/gpencil_brush.c
+++ b/source/blender/editors/gpencil/gpencil_brush.c
@@ -579,6 +579,7 @@ static bool gp_brush_push_apply(
mul_v3_v3fl(delta, gso->dvec, inf);
/* apply */
+ mul_mat3_m4_v3(gso->object->obmat, delta); /* only rotation component */
add_v3_v3(&pt->x, delta);
/* compute lock axis */
@@ -646,7 +647,9 @@ static bool gp_brush_pinch_apply(
inf = gp_brush_influence_calc(gso, radius, co) / 5.0f;
/* 1) Make this point relative to the cursor/midpoint (dvec) */
- sub_v3_v3v3(vec, &pt->x, gso->dvec);
+ float fpt[3];
+ mul_v3_m4v3(fpt, gso->object->obmat, &pt->x);
+ sub_v3_v3v3(vec, fpt, gso->dvec);
/* 2) Shrink the distance by pulling the point towards the midpoint
* (0.0 = at midpoint, 1 = at edge of brush region)
@@ -664,7 +667,8 @@ static bool gp_brush_pinch_apply(
mul_v3_fl(vec, fac);
/* 3) Translate back to original space, with the shrinkage applied */
- add_v3_v3v3(&pt->x, gso->dvec, vec);
+ add_v3_v3v3(fpt, gso->dvec, vec);
+ mul_v3_m4v3(&pt->x, gso->object->imat, fpt);
/* compute lock axis */
gpsculpt_compute_lock_axis(gso, pt, save_pt);
@@ -713,11 +717,14 @@ static bool gp_brush_twist_apply(
axis_angle_normalized_to_mat3(rmat, axis, angle);
- /* Rotate point (no matrix-space transforms needed, as GP points are in world space) */
- sub_v3_v3v3(vec, &pt->x, gso->dvec); /* make relative to center
- * (center is stored in dvec) */
+ /* Rotate point */
+ float fpt[3];
+ mul_v3_m4v3(fpt, gso->object->obmat, &pt->x);
+ sub_v3_v3v3(vec, fpt, gso->dvec); /* make relative to center
+ * (center is stored in dvec) */
mul_m3_v3(rmat, vec);
- add_v3_v3v3(&pt->x, vec, gso->dvec); /* restore */
+ add_v3_v3v3(fpt, vec, gso->dvec); /* restore */
+ mul_v3_m4v3(&pt->x, gso->object->imat, fpt);
/* compute lock axis */
gpsculpt_compute_lock_axis(gso, pt, save_pt);
@@ -1090,8 +1097,12 @@ static void gp_brush_clone_add(bContext *C, tGP_BrushEditData *gso)
* get pasted relative to where the cursor is now
*/
for (i = 0, pt = new_stroke->points; i < new_stroke->totpoints; i++, pt++) {
+ /* Rotate around center new position */
+ mul_mat3_m4_v3(gso->object->obmat, &pt->x); /* only rotation component */
+
/* assume that the delta can just be applied, and then everything works */
add_v3_v3(&pt->x, delta);
+ mul_m4_v3(gso->object->imat, &pt->x);
}
/* Store ref for later */
diff --git a/source/blender/editors/gpencil/gpencil_data.c b/source/blender/editors/gpencil/gpencil_data.c
index 941c7645dc0..90a2b2d613c 100644
--- a/source/blender/editors/gpencil/gpencil_data.c
+++ b/source/blender/editors/gpencil/gpencil_data.c
@@ -1521,8 +1521,10 @@ static int gp_stroke_lock_color_exec(bContext *C, wmOperator *UNUSED(op))
/* first lock all colors */
for (short i = 0; i < *totcol; i++) {
Material *tmp_ma = give_current_material(ob, i + 1);
- tmp_ma->gp_style->flag |= GP_STYLE_COLOR_LOCKED;
- DEG_id_tag_update(&tmp_ma->id, ID_RECALC_COPY_ON_WRITE);
+ if (tmp_ma) {
+ tmp_ma->gp_style->flag |= GP_STYLE_COLOR_LOCKED;
+ DEG_id_tag_update(&tmp_ma->id, ID_RECALC_COPY_ON_WRITE);
+ }
}
/* loop all selected strokes and unlock any color */
@@ -2433,10 +2435,12 @@ static int gpencil_lock_layer_exec(bContext *C, wmOperator *UNUSED(op))
for (short i = 0; i < *totcol; i++) {
ma = give_current_material(ob, i + 1);
- gp_style = ma->gp_style;
- gp_style->flag |= GP_STYLE_COLOR_LOCKED;
- gp_style->flag |= GP_STYLE_COLOR_HIDE;
- DEG_id_tag_update(&ma->id, ID_RECALC_COPY_ON_WRITE);
+ if (ma) {
+ gp_style = ma->gp_style;
+ gp_style->flag |= GP_STYLE_COLOR_LOCKED;
+ gp_style->flag |= GP_STYLE_COLOR_HIDE;
+ DEG_id_tag_update(&ma->id, ID_RECALC_COPY_ON_WRITE);
+ }
}
/* loop all selected strokes and unlock any color used in active layer */
@@ -2515,7 +2519,7 @@ static int gpencil_color_isolate_exec(bContext *C, wmOperator *op)
for (short i = 0; i < *totcol; i++) {
ma = give_current_material(ob, i + 1);
/* Skip if this is the active one */
- if (ma == active_ma) {
+ if ((ma == NULL) || (ma == active_ma)) {
continue;
}
@@ -2534,6 +2538,9 @@ static int gpencil_color_isolate_exec(bContext *C, wmOperator *op)
/* Set flags on all "other" colors */
for (short i = 0; i < *totcol; i++) {
ma = give_current_material(ob, i + 1);
+ if (ma == NULL) {
+ continue;
+ }
gp_style = ma->gp_style;
if (gp_style == active_color) {
continue;
@@ -2548,6 +2555,9 @@ static int gpencil_color_isolate_exec(bContext *C, wmOperator *op)
/* Clear flags - Restore everything else */
for (short i = 0; i < *totcol; i++) {
ma = give_current_material(ob, i + 1);
+ if (ma == NULL) {
+ continue;
+ }
gp_style = ma->gp_style;
gp_style->flag &= ~flags;
DEG_id_tag_update(&ma->id, ID_RECALC_COPY_ON_WRITE);
@@ -2610,10 +2620,12 @@ static int gpencil_color_hide_exec(bContext *C, wmOperator *op)
MaterialGPencilStyle *color = NULL;
for (short i = 0; i < *totcol; i++) {
ma = give_current_material(ob, i + 1);
- color = ma->gp_style;
- if (active_color != color) {
- color->flag |= GP_STYLE_COLOR_HIDE;
- DEG_id_tag_update(&ma->id, ID_RECALC_COPY_ON_WRITE);
+ if (ma) {
+ color = ma->gp_style;
+ if (active_color != color) {
+ color->flag |= GP_STYLE_COLOR_HIDE;
+ DEG_id_tag_update(&ma->id, ID_RECALC_COPY_ON_WRITE);
+ }
}
}
}
@@ -2671,9 +2683,11 @@ static int gpencil_color_reveal_exec(bContext *C, wmOperator *UNUSED(op))
for (short i = 0; i < *totcol; i++) {
ma = give_current_material(ob, i + 1);
- gp_style = ma->gp_style;
- gp_style->flag &= ~GP_STYLE_COLOR_HIDE;
- DEG_id_tag_update(&ma->id, ID_RECALC_COPY_ON_WRITE);
+ if (ma) {
+ gp_style = ma->gp_style;
+ gp_style->flag &= ~GP_STYLE_COLOR_HIDE;
+ DEG_id_tag_update(&ma->id, ID_RECALC_COPY_ON_WRITE);
+ }
}
/* updates */
@@ -2722,9 +2736,11 @@ static int gpencil_color_lock_all_exec(bContext *C, wmOperator *UNUSED(op))
for (short i = 0; i < *totcol; i++) {
ma = give_current_material(ob, i + 1);
- gp_style = ma->gp_style;
- gp_style->flag |= GP_STYLE_COLOR_LOCKED;
- DEG_id_tag_update(&ma->id, ID_RECALC_COPY_ON_WRITE);
+ if (ma) {
+ gp_style = ma->gp_style;
+ gp_style->flag |= GP_STYLE_COLOR_LOCKED;
+ DEG_id_tag_update(&ma->id, ID_RECALC_COPY_ON_WRITE);
+ }
}
/* updates */
@@ -2773,9 +2789,11 @@ static int gpencil_color_unlock_all_exec(bContext *C, wmOperator *UNUSED(op))
for (short i = 0; i < *totcol; i++) {
ma = give_current_material(ob, i + 1);
- gp_style = ma->gp_style;
- gp_style->flag &= ~GP_STYLE_COLOR_LOCKED;
- DEG_id_tag_update(&ma->id, ID_RECALC_COPY_ON_WRITE);
+ if (ma) {
+ gp_style = ma->gp_style;
+ gp_style->flag &= ~GP_STYLE_COLOR_LOCKED;
+ DEG_id_tag_update(&ma->id, ID_RECALC_COPY_ON_WRITE);
+ }
}
/* updates */
diff --git a/source/blender/editors/gpencil/gpencil_edit.c b/source/blender/editors/gpencil/gpencil_edit.c
index 5459cd09e53..0c1c24a9432 100644
--- a/source/blender/editors/gpencil/gpencil_edit.c
+++ b/source/blender/editors/gpencil/gpencil_edit.c
@@ -883,7 +883,7 @@ static void gpencil_add_move_points(bGPDframe *gpf, bGPDstroke *gps)
}
gps->flag |= GP_STROKE_RECALC_GEOMETRY;
- /* if first point, add new point at the begining */
+ /* If first point, add new point at the beginning. */
if (do_first) {
copy_move_point(gps, temp_points, temp_dverts, 0, 0, true);
/* deselect old */
@@ -2804,6 +2804,9 @@ static int gp_stroke_cyclical_set_exec(bContext *C, wmOperator *op)
Object *ob = CTX_data_active_object(C);
const int type = RNA_enum_get(op->ptr, "type");
+ const bool geometry = RNA_boolean_get(op->ptr, "geometry");
+ const bool is_multiedit = (bool)GPENCIL_MULTIEDIT_SESSIONS_ON(gpd);
+ bGPDstroke *gps = NULL;
/* sanity checks */
if (ELEM(NULL, gpd)) {
@@ -2812,39 +2815,55 @@ static int gp_stroke_cyclical_set_exec(bContext *C, wmOperator *op)
/* loop all selected strokes */
CTX_DATA_BEGIN (C, bGPDlayer *, gpl, editable_gpencil_layers) {
- if (gpl->actframe == NULL) {
- continue;
- }
+ bGPDframe *init_gpf = (is_multiedit) ? gpl->frames.first : gpl->actframe;
- for (bGPDstroke *gps = gpl->actframe->strokes.last; gps; gps = gps->prev) {
- MaterialGPencilStyle *gp_style = BKE_material_gpencil_settings_get(ob, gps->mat_nr + 1);
+ for (bGPDframe *gpf = init_gpf; gpf; gpf = gpf->next) {
+ if ((gpf == gpl->actframe) || ((gpf->flag & GP_FRAME_SELECT) && (is_multiedit))) {
+ if (gpf == NULL) {
+ continue;
+ }
- /* skip strokes that are not selected or invalid for current view */
- if (((gps->flag & GP_STROKE_SELECT) == 0) || ED_gpencil_stroke_can_use(C, gps) == false) {
- continue;
- }
- /* skip hidden or locked colors */
- if (!gp_style || (gp_style->flag & GP_STYLE_COLOR_HIDE) ||
- (gp_style->flag & GP_STYLE_COLOR_LOCKED)) {
- continue;
- }
+ for (gps = gpf->strokes.first; gps; gps = gps->next) {
+ MaterialGPencilStyle *gp_style = BKE_material_gpencil_settings_get(ob, gps->mat_nr + 1);
+ /* skip strokes that are not selected or invalid for current view */
+ if (((gps->flag & GP_STROKE_SELECT) == 0) ||
+ ED_gpencil_stroke_can_use(C, gps) == false) {
+ continue;
+ }
+ /* skip hidden or locked colors */
+ if (!gp_style || (gp_style->flag & GP_STYLE_COLOR_HIDE) ||
+ (gp_style->flag & GP_STYLE_COLOR_LOCKED)) {
+ continue;
+ }
- switch (type) {
- case GP_STROKE_CYCLIC_CLOSE:
- /* Close all (enable) */
- gps->flag |= GP_STROKE_CYCLIC;
- break;
- case GP_STROKE_CYCLIC_OPEN:
- /* Open all (disable) */
- gps->flag &= ~GP_STROKE_CYCLIC;
- break;
- case GP_STROKE_CYCLIC_TOGGLE:
- /* Just toggle flag... */
- gps->flag ^= GP_STROKE_CYCLIC;
- break;
- default:
- BLI_assert(0);
+ switch (type) {
+ case GP_STROKE_CYCLIC_CLOSE:
+ /* Close all (enable) */
+ gps->flag |= GP_STROKE_CYCLIC;
+ break;
+ case GP_STROKE_CYCLIC_OPEN:
+ /* Open all (disable) */
+ gps->flag &= ~GP_STROKE_CYCLIC;
+ break;
+ case GP_STROKE_CYCLIC_TOGGLE:
+ /* Just toggle flag... */
+ gps->flag ^= GP_STROKE_CYCLIC;
+ break;
+ default:
+ BLI_assert(0);
+ break;
+ }
+
+ /* Create new geometry. */
+ if ((gps->flag & GP_STROKE_CYCLIC) && (geometry)) {
+ BKE_gpencil_close_stroke(gps);
+ }
+ }
+
+ /* if not multiedit, exit loop*/
+ if (!is_multiedit) {
break;
+ }
}
}
}
@@ -2863,6 +2882,8 @@ static int gp_stroke_cyclical_set_exec(bContext *C, wmOperator *op)
*/
void GPENCIL_OT_stroke_cyclical_set(wmOperatorType *ot)
{
+ PropertyRNA *prop;
+
static const EnumPropertyItem cyclic_type[] = {
{GP_STROKE_CYCLIC_CLOSE, "CLOSE", 0, "Close all", ""},
{GP_STROKE_CYCLIC_OPEN, "OPEN", 0, "Open all", ""},
@@ -2884,6 +2905,9 @@ void GPENCIL_OT_stroke_cyclical_set(wmOperatorType *ot)
/* properties */
ot->prop = RNA_def_enum(ot->srna, "type", cyclic_type, GP_STROKE_CYCLIC_TOGGLE, "Type", "");
+ prop = RNA_def_boolean(
+ ot->srna, "geometry", false, "Create Geometry", "Create new geometry for closing stroke");
+ RNA_def_property_flag(prop, PROP_SKIP_SAVE);
}
/* ******************* Flat Stroke Caps ************************** */
diff --git a/source/blender/editors/gpencil/gpencil_interpolate.c b/source/blender/editors/gpencil/gpencil_interpolate.c
index 8a9f7c1224a..4d5548dcdf3 100644
--- a/source/blender/editors/gpencil/gpencil_interpolate.c
+++ b/source/blender/editors/gpencil/gpencil_interpolate.c
@@ -996,8 +996,9 @@ static int gpencil_interpolate_seq_exec(bContext *C, wmOperator *op)
float factor;
/* get interpolation factor */
- factor = (float)(cframe - prevFrame->framenum) /
- (nextFrame->framenum - prevFrame->framenum + 1);
+ float framerange = nextFrame->framenum - prevFrame->framenum;
+ CLAMP_MIN(framerange, 1.0f);
+ factor = (float)(cframe - prevFrame->framenum) / framerange;
if (ipo_settings->type == GP_IPO_CURVEMAP) {
/* custom curvemap */
diff --git a/source/blender/editors/gpencil/gpencil_paint.c b/source/blender/editors/gpencil/gpencil_paint.c
index f6691f4813b..b49094c4fd6 100644
--- a/source/blender/editors/gpencil/gpencil_paint.c
+++ b/source/blender/editors/gpencil/gpencil_paint.c
@@ -3708,7 +3708,7 @@ static int gpencil_draw_modal(bContext *C, wmOperator *op, const wmEvent *event)
/* handle drawing event */
/* printf("\t\tGP - add point\n"); */
- if (((p->flags & GP_PAINTFLAG_FIRSTRUN) == 0)) {
+ if (((p->flags & GP_PAINTFLAG_FIRSTRUN) == 0) && (p->paintmode != GP_PAINTMODE_ERASER)) {
gpencil_add_missing_events(C, op, event, p);
}
diff --git a/source/blender/editors/gpencil/gpencil_primitive.c b/source/blender/editors/gpencil/gpencil_primitive.c
index 21bee0a9d4e..cca94925e6e 100644
--- a/source/blender/editors/gpencil/gpencil_primitive.c
+++ b/source/blender/editors/gpencil/gpencil_primitive.c
@@ -225,8 +225,8 @@ static void gp_primitive_update_cps(tGPDprimitive *tgpi)
}
else if (tgpi->type == GP_STROKE_CURVE) {
mid_v2_v2v2(tgpi->midpoint, tgpi->start, tgpi->end);
- copy_v2_v2(tgpi->cp1, tgpi->midpoint);
- copy_v2_v2(tgpi->cp2, tgpi->cp1);
+ interp_v2_v2v2(tgpi->cp1, tgpi->midpoint, tgpi->start, 0.33f);
+ interp_v2_v2v2(tgpi->cp2, tgpi->midpoint, tgpi->end, 0.33f);
}
else if (tgpi->type == GP_STROKE_ARC) {
if (tgpi->flip) {
@@ -1284,6 +1284,11 @@ static void gpencil_primitive_interaction_end(bContext *C,
}
}
+ /* Close stroke with geometry */
+ if ((tgpi->type == GP_STROKE_BOX) || (tgpi->type == GP_STROKE_CIRCLE)) {
+ BKE_gpencil_close_stroke(gps);
+ }
+
DEG_id_tag_update(&tgpi->gpd->id, ID_RECALC_COPY_ON_WRITE);
DEG_id_tag_update(&tgpi->gpd->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
diff --git a/source/blender/editors/include/BIF_glutil.h b/source/blender/editors/include/BIF_glutil.h
index 7d4b6dbeea2..101a65d151a 100644
--- a/source/blender/editors/include/BIF_glutil.h
+++ b/source/blender/editors/include/BIF_glutil.h
@@ -172,8 +172,6 @@ int ED_draw_imbuf_method(struct ImBuf *ibuf);
/* OpenGL drawing utility functions. Do not use these in new code, these
* are intended to be moved or removed in the future. */
-void set_inverted_drawing(int enable);
-
/* own working polygon offset */
float bglPolygonOffsetCalc(const float winmat[16], float viewdist, float dist);
void bglPolygonOffset(float viewdist, float dist);
diff --git a/source/blender/editors/include/ED_armature.h b/source/blender/editors/include/ED_armature.h
index aca59e2868f..6629eed8328 100644
--- a/source/blender/editors/include/ED_armature.h
+++ b/source/blender/editors/include/ED_armature.h
@@ -170,6 +170,10 @@ bool ED_armature_pose_select_pick_with_buffer(struct ViewLayer *view_layer,
bool deselect,
bool toggle,
bool do_nearest);
+
+void ED_armature_pose_select_in_wpaint_mode(struct ViewLayer *view_layer,
+ struct Base *base_select);
+
bool ED_armature_edit_select_pick(
struct bContext *C, const int mval[2], bool extend, bool deselect, bool toggle);
@@ -184,6 +188,8 @@ EditBone *ED_armature_ebone_get_mirrored(const struct ListBase *edbo, EditBone *
void ED_armature_edit_sync_selection(struct ListBase *edbo);
void ED_armature_edit_validate_active(struct bArmature *arm);
+void ED_armature_edit_refresh_layer_used(struct bArmature *arm);
+
struct Base *ED_armature_base_and_ebone_from_select_buffer(struct Base **bases,
uint bases_len,
int hit,
diff --git a/source/blender/editors/include/ED_mesh.h b/source/blender/editors/include/ED_mesh.h
index 5d8038d0b28..d2613facd83 100644
--- a/source/blender/editors/include/ED_mesh.h
+++ b/source/blender/editors/include/ED_mesh.h
@@ -393,6 +393,9 @@ bool ED_mesh_color_remove_named(struct Mesh *me, const char *name);
void ED_mesh_report_mirror(struct wmOperator *op, int totmirr, int totfail);
void ED_mesh_report_mirror_ex(struct wmOperator *op, int totmirr, int totfail, char selectmode);
+/* Returns the pinned mesh, the mesh from the pinned object, or the mesh from the active object. */
+struct Mesh *ED_mesh_context(struct bContext *C);
+
/* mesh backup */
typedef struct BMBackup {
struct BMesh *bmcopy;
diff --git a/source/blender/editors/include/ED_object.h b/source/blender/editors/include/ED_object.h
index a4c68c2c5ad..038f1bf52a6 100644
--- a/source/blender/editors/include/ED_object.h
+++ b/source/blender/editors/include/ED_object.h
@@ -121,6 +121,9 @@ void ED_object_parent_clear(struct Object *ob, const int type);
void ED_object_base_select(struct Base *base, eObjectSelect_Mode mode);
void ED_object_base_activate(struct bContext *C, struct Base *base);
+void ED_object_base_active_refresh(struct Main *bmain,
+ struct Scene *scene,
+ struct ViewLayer *view_layer);
void ED_object_base_free_and_unlink(struct Main *bmain, struct Scene *scene, struct Object *ob);
bool ED_object_base_deselect_all_ex(struct ViewLayer *view_layer,
struct View3D *v3d,
diff --git a/source/blender/editors/include/ED_render.h b/source/blender/editors/include/ED_render.h
index 7689a9f97cd..d36d2559f26 100644
--- a/source/blender/editors/include/ED_render.h
+++ b/source/blender/editors/include/ED_render.h
@@ -93,7 +93,8 @@ void ED_preview_icon_job(const struct bContext *C,
struct ID *id,
unsigned int *rect,
int sizex,
- int sizey);
+ int sizey,
+ const bool delay);
void ED_preview_kill_jobs(struct wmWindowManager *wm, struct Main *bmain);
void ED_preview_draw(const struct bContext *C, void *idp, void *parentp, void *slot, rcti *rect);
diff --git a/source/blender/editors/include/ED_screen.h b/source/blender/editors/include/ED_screen.h
index fc43144417a..e67a3b003fc 100644
--- a/source/blender/editors/include/ED_screen.h
+++ b/source/blender/editors/include/ED_screen.h
@@ -337,6 +337,7 @@ bool ED_operator_object_active(struct bContext *C);
bool ED_operator_object_active_editable(struct bContext *C);
bool ED_operator_object_active_editable_mesh(struct bContext *C);
bool ED_operator_object_active_editable_font(struct bContext *C);
+bool ED_operator_editable_mesh(struct bContext *C);
bool ED_operator_editmesh(struct bContext *C);
bool ED_operator_editmesh_view3d(struct bContext *C);
bool ED_operator_editmesh_region_view3d(struct bContext *C);
diff --git a/source/blender/editors/include/ED_text.h b/source/blender/editors/include/ED_text.h
index 7638249d49a..ed71439bd37 100644
--- a/source/blender/editors/include/ED_text.h
+++ b/source/blender/editors/include/ED_text.h
@@ -26,7 +26,7 @@
struct ARegion;
struct SpaceText;
-struct TextUndoBuf;
+struct UndoStep;
struct UndoType;
bool ED_text_region_location_from_cursor(struct SpaceText *st,
@@ -37,6 +37,6 @@ bool ED_text_region_location_from_cursor(struct SpaceText *st,
/* text_undo.c */
void ED_text_undosys_type(struct UndoType *ut);
-struct TextUndoBuf *ED_text_undo_push_init(struct bContext *C);
+struct UndoStep *ED_text_undo_push_init(struct bContext *C);
#endif /* __ED_TEXT_H__ */
diff --git a/source/blender/editors/include/ED_transform_snap_object_context.h b/source/blender/editors/include/ED_transform_snap_object_context.h
index 75564ddd947..f27523bb1f8 100644
--- a/source/blender/editors/include/ED_transform_snap_object_context.h
+++ b/source/blender/editors/include/ED_transform_snap_object_context.h
@@ -121,16 +121,16 @@ bool ED_transform_snap_object_project_ray_all(SnapObjectContext *sctx,
bool sort,
struct ListBase *r_hit_list);
-bool ED_transform_snap_object_project_view3d_ex(struct SnapObjectContext *sctx,
- const unsigned short snap_to,
- const struct SnapObjectParams *params,
- const float mval[2],
- float *dist_px,
- float r_loc[3],
- float r_no[3],
- int *r_index,
- struct Object **r_ob,
- float r_obmat[4][4]);
+short ED_transform_snap_object_project_view3d_ex(struct SnapObjectContext *sctx,
+ const unsigned short snap_to,
+ const struct SnapObjectParams *params,
+ const float mval[2],
+ float *dist_px,
+ float r_loc[3],
+ float r_no[3],
+ int *r_index,
+ struct Object **r_ob,
+ float r_obmat[4][4]);
bool ED_transform_snap_object_project_view3d(struct SnapObjectContext *sctx,
const unsigned short snap_to,
const struct SnapObjectParams *params,
diff --git a/source/blender/editors/include/ED_undo.h b/source/blender/editors/include/ED_undo.h
index ebc50e186a2..fa2630ba726 100644
--- a/source/blender/editors/include/ED_undo.h
+++ b/source/blender/editors/include/ED_undo.h
@@ -54,6 +54,9 @@ bool ED_undo_is_valid(const struct bContext *C, const char *undoname);
bool ED_undo_is_memfile_compatible(const struct bContext *C);
+/* Unfortunate workaround for limits mixing undo systems. */
+bool ED_undo_is_legacy_compatible_for_property(struct bContext *C, struct ID *id);
+
void ED_undo_object_editmode_restore_helper(struct bContext *C,
struct Object **object_array,
uint object_array_len,
diff --git a/source/blender/editors/include/UI_icons.h b/source/blender/editors/include/UI_icons.h
index 3d2052f1fa9..47cf827ed66 100644
--- a/source/blender/editors/include/UI_icons.h
+++ b/source/blender/editors/include/UI_icons.h
@@ -45,6 +45,9 @@
#ifndef DEF_ICON_COLOR
# define DEF_ICON_COLOR DEF_ICON
#endif
+#ifndef DEF_ICON_FUND
+# define DEF_ICON_FUND DEF_ICON
+#endif
/* ICON_ prefix added */
DEF_ICON_COLOR(NONE)
@@ -289,7 +292,7 @@ DEF_ICON(DECORATE_LIBRARY_OVERRIDE)
DEF_ICON(DECORATE_UNLOCKED)
DEF_ICON(DECORATE_LOCKED)
DEF_ICON(DECORATE_OVERRIDE)
-DEF_ICON_BLANK(111)
+DEF_ICON_FUND(FUND)
DEF_ICON(TRACKER_DATA)
DEF_ICON(HEART)
DEF_ICON(ORPHAN_DATA)
@@ -1033,4 +1036,5 @@ DEF_ICON_COLOR(EVENT_RETURN)
#undef DEF_ICON_SHADING
#undef DEF_ICON_VECTOR
#undef DEF_ICON_COLOR
+#undef DEF_ICON_FUND
#undef DEF_ICON_BLANK
diff --git a/source/blender/editors/include/UI_interface.h b/source/blender/editors/include/UI_interface.h
index bf728ec7772..3b2a80c1e05 100644
--- a/source/blender/editors/include/UI_interface.h
+++ b/source/blender/editors/include/UI_interface.h
@@ -723,7 +723,7 @@ bool UI_block_active_only_flagged_buttons(const struct bContext *C,
struct ARegion *ar,
struct uiBlock *block);
-void UI_but_execute(const struct bContext *C, uiBut *but);
+void UI_but_execute(const struct bContext *C, struct ARegion *ar, uiBut *but);
bool UI_but_online_manual_id(const uiBut *but,
char *r_str,
diff --git a/source/blender/editors/include/UI_resources.h b/source/blender/editors/include/UI_resources.h
index db6bb35560d..3b080b6df95 100644
--- a/source/blender/editors/include/UI_resources.h
+++ b/source/blender/editors/include/UI_resources.h
@@ -272,6 +272,7 @@ typedef enum ThemeColorID {
TH_ICON_OBJECT_DATA,
TH_ICON_MODIFIER,
TH_ICON_SHADING,
+ TH_ICON_FUND,
TH_SCROLL_TEXT,
diff --git a/source/blender/editors/include/UI_view2d.h b/source/blender/editors/include/UI_view2d.h
index 137c431e3bf..0dbf3c710d6 100644
--- a/source/blender/editors/include/UI_view2d.h
+++ b/source/blender/editors/include/UI_view2d.h
@@ -71,7 +71,7 @@ enum eView2D_CommonViewTypes {
#define V2D_SCROLL_HANDLE_SIZE_HOTSPOT (0.6f * U.widget_unit)
/** Don't allow scroll thumb to show below this size (so it's never too small to click on). */
-#define V2D_SCROLL_THUMB_SIZE_MIN (50.0 * UI_DPI_FAC)
+#define V2D_SCROLL_THUMB_SIZE_MIN (30.0 * UI_DPI_FAC)
/* ------ Define for UI_view2d_sync ----- */
diff --git a/source/blender/editors/interface/interface.c b/source/blender/editors/interface/interface.c
index 697c289491a..a2138a1b3a5 100644
--- a/source/blender/editors/interface/interface.c
+++ b/source/blender/editors/interface/interface.c
@@ -896,9 +896,8 @@ bool UI_block_active_only_flagged_buttons(const bContext *C, ARegion *ar, uiBloc
}
/* simulate button click */
-void UI_but_execute(const bContext *C, uiBut *but)
+void UI_but_execute(const bContext *C, ARegion *ar, uiBut *but)
{
- ARegion *ar = CTX_wm_region(C);
void *active_back;
ui_but_execute_begin((bContext *)C, ar, but, &active_back);
/* Value is applied in begin. No further action required. */
diff --git a/source/blender/editors/interface/interface_align.c b/source/blender/editors/interface/interface_align.c
index be02def1693..cc68e303e4a 100644
--- a/source/blender/editors/interface/interface_align.c
+++ b/source/blender/editors/interface/interface_align.c
@@ -251,7 +251,7 @@ static void block_align_proximity_compute(ButAlign *butal, ButAlign *butal_other
}
}
/* We assume two buttons can only share one side at most - for until
- * we have sperical UI... */
+ * we have spherical UI. */
return;
}
}
diff --git a/source/blender/editors/interface/interface_context_menu.c b/source/blender/editors/interface/interface_context_menu.c
index 36e197a0591..7cec8af46de 100644
--- a/source/blender/editors/interface/interface_context_menu.c
+++ b/source/blender/editors/interface/interface_context_menu.c
@@ -1030,23 +1030,6 @@ bool ui_popup_context_menu_for_button(bContext *C, uiBut *but)
0,
"");
UI_but_func_set(but2, popup_change_shortcut_func, but, NULL);
-
- but2 = uiDefIconTextBut(block,
- UI_BTYPE_BUT,
- 0,
- ICON_BLANK1,
- CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Remove Shortcut"),
- 0,
- 0,
- w,
- UI_UNIT_Y,
- NULL,
- 0,
- 0,
- 0,
- 0,
- "");
- UI_but_func_set(but2, remove_shortcut_func, but, NULL);
}
else {
but2 = uiDefIconTextBut(block,
@@ -1067,6 +1050,23 @@ bool ui_popup_context_menu_for_button(bContext *C, uiBut *but)
"please use User Preferences otherwise"));
UI_but_flag_enable(but2, UI_BUT_DISABLED);
}
+
+ but2 = uiDefIconTextBut(block,
+ UI_BTYPE_BUT,
+ 0,
+ ICON_BLANK1,
+ CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Remove Shortcut"),
+ 0,
+ 0,
+ w,
+ UI_UNIT_Y,
+ NULL,
+ 0,
+ 0,
+ 0,
+ 0,
+ "");
+ UI_but_func_set(but2, remove_shortcut_func, but, NULL);
}
/* only show 'assign' if there's a suitable key map for it to go in */
else if (WM_keymap_guess_opname(C, idname)) {
diff --git a/source/blender/editors/interface/interface_eyedropper_colorband.c b/source/blender/editors/interface/interface_eyedropper_colorband.c
index 67e5a6c806c..ffe93e48936 100644
--- a/source/blender/editors/interface/interface_eyedropper_colorband.c
+++ b/source/blender/editors/interface/interface_eyedropper_colorband.c
@@ -84,22 +84,40 @@ static bool eyedropper_colorband_init(bContext *C, wmOperator *op)
uiBut *but = UI_context_active_but_get(C);
+ PointerRNA rna_update_ptr = PointerRNA_NULL;
+ PropertyRNA *rna_update_prop = NULL;
+ bool is_undo = true;
+
if (but == NULL) {
/* pass */
}
- else if (but->type == UI_BTYPE_COLORBAND) {
- /* When invoked with a hotkey, we can find the band in 'but->poin'. */
- band = (ColorBand *)but->poin;
- }
else {
- /* When invoked from a button it's in custom_data field. */
- band = (ColorBand *)but->custom_data;
+ if (but->type == UI_BTYPE_COLORBAND) {
+ /* When invoked with a hotkey, we can find the band in 'but->poin'. */
+ band = (ColorBand *)but->poin;
+ }
+ else {
+ /* When invoked from a button it's in custom_data field. */
+ band = (ColorBand *)but->custom_data;
+ }
+
+ if (band) {
+ rna_update_ptr = ((Colorband_RNAUpdateCb *)but->func_argN)->ptr;
+ rna_update_prop = ((Colorband_RNAUpdateCb *)but->func_argN)->prop;
+ is_undo = UI_but_flag_is_set(but, UI_BUT_UNDO);
+ }
}
if (!band) {
PointerRNA ptr = CTX_data_pointer_get_type(C, "color_ramp", &RNA_ColorRamp);
if (ptr.data != NULL) {
band = ptr.data;
+
+ /* Set this to a sub-member of the property to trigger an update. */
+ extern PropertyRNA rna_ColorRamp_color_mode;
+ rna_update_ptr = ptr;
+ rna_update_prop = &rna_ColorRamp_color_mode;
+ is_undo = RNA_struct_undo_check(ptr.type);
}
}
@@ -113,9 +131,9 @@ static bool eyedropper_colorband_init(bContext *C, wmOperator *op)
eye->color_buffer_len = 0;
eye->color_band = band;
eye->init_color_band = *eye->color_band;
- eye->ptr = ((Colorband_RNAUpdateCb *)but->func_argN)->ptr;
- eye->prop = ((Colorband_RNAUpdateCb *)but->func_argN)->prop;
- eye->is_undo = UI_but_flag_is_set(but, UI_BUT_UNDO);
+ eye->ptr = rna_update_ptr;
+ eye->prop = rna_update_prop;
+ eye->is_undo = is_undo;
op->customdata = eye;
@@ -186,7 +204,9 @@ static void eyedropper_colorband_apply(bContext *C, wmOperator *op)
BKE_colorband_init_from_table_rgba(
eye->color_band, eye->color_buffer, eye->color_buffer_len, filter_samples);
eye->is_set = true;
- RNA_property_update(C, &eye->ptr, eye->prop);
+ if (eye->prop) {
+ RNA_property_update(C, &eye->ptr, eye->prop);
+ }
}
static void eyedropper_colorband_cancel(bContext *C, wmOperator *op)
@@ -194,7 +214,9 @@ static void eyedropper_colorband_cancel(bContext *C, wmOperator *op)
EyedropperColorband *eye = op->customdata;
if (eye->is_set) {
*eye->color_band = eye->init_color_band;
- RNA_property_update(C, &eye->ptr, eye->prop);
+ if (eye->prop) {
+ RNA_property_update(C, &eye->ptr, eye->prop);
+ }
}
eyedropper_colorband_exit(C, op);
}
@@ -267,7 +289,9 @@ static int eyedropper_colorband_point_modal(bContext *C, wmOperator *op, const w
break;
case EYE_MODAL_SAMPLE_RESET:
*eye->color_band = eye->init_color_band;
- RNA_property_update(C, &eye->ptr, eye->prop);
+ if (eye->prop) {
+ RNA_property_update(C, &eye->ptr, eye->prop);
+ }
eye->color_buffer_len = 0;
break;
}
diff --git a/source/blender/editors/interface/interface_eyedropper_depth.c b/source/blender/editors/interface/interface_eyedropper_depth.c
index adb317f488c..fc60fc06ac0 100644
--- a/source/blender/editors/interface/interface_eyedropper_depth.c
+++ b/source/blender/editors/interface/interface_eyedropper_depth.c
@@ -31,6 +31,7 @@
#include "DNA_space_types.h"
#include "DNA_screen_types.h"
#include "DNA_object_types.h"
+#include "DNA_camera_types.h"
#include "DNA_view3d_types.h"
#include "BLI_string.h"
@@ -102,8 +103,9 @@ static int depthdropper_init(bContext *C, wmOperator *op)
if (rv3d && rv3d->persp == RV3D_CAMOB) {
View3D *v3d = CTX_wm_view3d(C);
if (v3d->camera && v3d->camera->data && !ID_IS_LINKED(v3d->camera->data)) {
- RNA_id_pointer_create(v3d->camera->data, &ddr->ptr);
- ddr->prop = RNA_struct_find_property(&ddr->ptr, "dof_distance");
+ Camera *camera = (Camera *)v3d->camera->data;
+ RNA_pointer_create(&camera->id, &RNA_CameraDOFSettings, &camera->dof, &ddr->ptr);
+ ddr->prop = RNA_struct_find_property(&ddr->ptr, "focus_distance");
ddr->is_undo = true;
}
}
diff --git a/source/blender/editors/interface/interface_handlers.c b/source/blender/editors/interface/interface_handlers.c
index e59431d265d..a7fc0cfec25 100644
--- a/source/blender/editors/interface/interface_handlers.c
+++ b/source/blender/editors/interface/interface_handlers.c
@@ -551,12 +551,15 @@ static bool ui_but_dragedit_update_mval(uiHandleButtonData *data, int mx)
return true;
}
-static void ui_but_update_preferences_dirty(uiBut *but)
+static void ui_rna_update_preferences_dirty(PointerRNA *ptr, PropertyRNA *prop)
{
/* Not very elegant, but ensures preference changes force re-save. */
bool tag = false;
- if (but->rnaprop) {
- StructRNA *base = RNA_struct_base(but->rnapoin.type);
+ if (prop && !(RNA_property_flag(prop) & PROP_NO_DEG_UPDATE)) {
+ StructRNA *base = RNA_struct_base(ptr->type);
+ if (base == NULL) {
+ base = ptr->type;
+ }
if (ELEM(base, &RNA_AddonPreferences, &RNA_KeyConfigPreferences, &RNA_KeyMapItem)) {
tag = true;
}
@@ -568,6 +571,16 @@ static void ui_but_update_preferences_dirty(uiBut *but)
}
}
+static void ui_but_update_preferences_dirty(uiBut *but)
+{
+ ui_rna_update_preferences_dirty(&but->rnapoin, but->rnaprop);
+}
+
+static void ui_afterfunc_update_preferences_dirty(uiAfterFunc *after)
+{
+ ui_rna_update_preferences_dirty(&after->rnapoin, after->rnaprop);
+}
+
/** \} */
/* -------------------------------------------------------------------- */
@@ -743,6 +756,22 @@ static void ui_apply_but_undo(uiBut *but)
str = "Unknown Action";
}
+ /* Optionally override undo when undo system doesn't support storing properties. */
+ if (but->rnapoin.id.data) {
+ /* Exception for renaming ID data, we always need undo pushes in this case,
+ * because undo systems track data by their ID, see: T67002. */
+ extern PropertyRNA rna_ID_name;
+ if (but->rnaprop == &rna_ID_name) {
+ /* pass */
+ }
+ else {
+ ID *id = but->rnapoin.id.data;
+ if (!ED_undo_is_legacy_compatible_for_property(but->block->evil_C, id)) {
+ str = "";
+ }
+ }
+ }
+
/* delayed, after all other funcs run, popups are closed, etc */
after = ui_afterfunc_new();
BLI_strncpy(after->undostr, str, sizeof(after->undostr));
@@ -843,6 +872,8 @@ static void ui_apply_but_funcs_after(bContext *C)
MEM_freeN(after.rename_orig);
}
+ ui_afterfunc_update_preferences_dirty(&after);
+
if (after.undostr[0]) {
ED_undo_push(C, after.undostr);
}
@@ -1347,7 +1378,7 @@ static bool ui_drag_toggle_set_xy_xy(
/* is it pressed? */
int pushed_state_but = ui_drag_toggle_but_pushed_state(C, but);
if (pushed_state_but != pushed_state) {
- UI_but_execute(C, but);
+ UI_but_execute(C, ar, but);
if (do_check) {
ui_but_update_edited(but);
}
@@ -7278,7 +7309,11 @@ static void button_activate_state(bContext *C, uiBut *but, uiHandleButtonState s
button_tooltip_timer_reset(C, but);
/* automatic open pulldown block timer */
- if (ELEM(but->type, UI_BTYPE_BLOCK, UI_BTYPE_PULLDOWN, UI_BTYPE_POPOVER)) {
+ if (ELEM(but->type, UI_BTYPE_BLOCK, UI_BTYPE_PULLDOWN, UI_BTYPE_POPOVER) ||
+ /* Menu button types may draw as popovers, check for this case
+ * ignoring other kinds of menus (mainly enums). (see T66538). */
+ ((but->type == UI_BTYPE_MENU) &&
+ (UI_but_paneltype_get(but) || ui_but_menu_draw_as_popover(but)))) {
if (data->used_mouse && !data->autoopentimer) {
int time;
@@ -7939,6 +7974,8 @@ void ui_but_execute_begin(struct bContext *UNUSED(C),
uiBut *but,
void **active_back)
{
+ BLI_assert(ar != NULL);
+ BLI_assert(BLI_findindex(&ar->uiblocks, but->block) != -1);
/* note: ideally we would not have to change 'but->active' however
* some functions we call don't use data (as they should be doing) */
uiHandleButtonData *data;
@@ -9269,7 +9306,7 @@ static int ui_handle_menu_event(bContext *C,
for (but = block->buttons.first; but; but = but->next) {
if (!(but->flag & UI_BUT_DISABLED) && but->menu_key == event->type) {
if (but->type == UI_BTYPE_BUT) {
- UI_but_execute(C, but);
+ UI_but_execute(C, ar, but);
}
else {
ui_handle_button_activate_by_type(C, ar, but);
@@ -9350,7 +9387,7 @@ static int ui_handle_menu_event(bContext *C,
ar, UI_BUT_ACTIVE_DEFAULT, UI_HIDDEN);
if ((but_default != NULL) && (but_default->active == NULL)) {
if (but_default->type == UI_BTYPE_BUT) {
- UI_but_execute(C, but_default);
+ UI_but_execute(C, ar, but_default);
}
else {
ui_handle_button_activate_by_type(C, ar, but_default);
@@ -10100,9 +10137,10 @@ static int ui_handler_region_menu(bContext *C, const wmEvent *event, void *UNUSE
if ((data->state == BUTTON_STATE_MENU_OPEN) &&
/* make sure mouse isn't inside another menu (see T43247) */
- (is_inside_menu == false) && (ELEM(but->type, UI_BTYPE_PULLDOWN, UI_BTYPE_POPOVER)) &&
+ (is_inside_menu == false) &&
+ (ELEM(but->type, UI_BTYPE_PULLDOWN, UI_BTYPE_POPOVER, UI_BTYPE_MENU)) &&
(but_other = ui_but_find_mouse_over(ar, event)) && (but != but_other) &&
- (ELEM(but_other->type, UI_BTYPE_PULLDOWN, UI_BTYPE_POPOVER))) {
+ (ELEM(but_other->type, UI_BTYPE_PULLDOWN, UI_BTYPE_POPOVER, UI_BTYPE_MENU))) {
/* if mouse moves to a different root-level menu button,
* open it to replace the current menu */
if ((but_other->flag & UI_BUT_DISABLED) == 0) {
diff --git a/source/blender/editors/interface/interface_icons.c b/source/blender/editors/interface/interface_icons.c
index 6f1f4dde1ab..ea5ef94d90d 100644
--- a/source/blender/editors/interface/interface_icons.c
+++ b/source/blender/editors/interface/interface_icons.c
@@ -169,6 +169,7 @@ static const IconType icontypes[] = {
# define DEF_ICON_OBJECT_DATA(name) {ICON_TYPE_MONO_TEXTURE, TH_ICON_OBJECT_DATA},
# define DEF_ICON_MODIFIER(name) {ICON_TYPE_MONO_TEXTURE, TH_ICON_MODIFIER},
# define DEF_ICON_SHADING(name) {ICON_TYPE_MONO_TEXTURE, TH_ICON_SHADING},
+# define DEF_ICON_FUND(name) {ICON_TYPE_MONO_TEXTURE, TH_ICON_FUND},
# define DEF_ICON_VECTOR(name) {ICON_TYPE_VECTOR, 0},
# define DEF_ICON_COLOR(name) {ICON_TYPE_COLOR_TEXTURE, 0},
# define DEF_ICON_BLANK(name) {ICON_TYPE_BLANK, 0},
@@ -1417,11 +1418,13 @@ static void icon_set_image(const bContext *C,
return;
}
+ const bool delay = prv_img->rect[size] != NULL;
icon_create_rect(prv_img, size);
if (use_job) {
/* Job (background) version */
- ED_preview_icon_job(C, prv_img, id, prv_img->rect[size], prv_img->w[size], prv_img->h[size]);
+ ED_preview_icon_job(
+ C, prv_img, id, prv_img->rect[size], prv_img->w[size], prv_img->h[size], delay);
}
else {
if (!scene) {
diff --git a/source/blender/editors/interface/interface_ops.c b/source/blender/editors/interface/interface_ops.c
index aa7e7f97478..f2b2a478ba9 100644
--- a/source/blender/editors/interface/interface_ops.c
+++ b/source/blender/editors/interface/interface_ops.c
@@ -1052,8 +1052,7 @@ static int reports_to_text_exec(bContext *C, wmOperator *UNUSED(op))
str = BKE_reports_string(reports, (G.debug & G_DEBUG) ? RPT_DEBUG : RPT_INFO);
if (str) {
- TextUndoBuf *utxt = NULL; // FIXME
- BKE_text_write(txt, utxt, str);
+ BKE_text_write(txt, str);
MEM_freeN(str);
return OPERATOR_FINISHED;
@@ -1507,29 +1506,21 @@ static void UI_OT_reloadtranslation(wmOperatorType *ot)
/** \name Press Button Operator
* \{ */
-static ARegion *region_event_inside_for_screen(bContext *C, const int xy[2])
-{
- bScreen *sc = CTX_wm_screen(C);
- if (sc) {
- for (ARegion *ar = sc->regionbase.first; ar; ar = ar->next) {
- if (BLI_rcti_isect_pt_v(&ar->winrct, xy)) {
- return ar;
- }
- }
- }
- return NULL;
-}
-
static int ui_button_press_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
+ bScreen *sc = CTX_wm_screen(C);
const bool skip_depressed = RNA_boolean_get(op->ptr, "skip_depressed");
ARegion *ar_prev = CTX_wm_region(C);
- ARegion *ar = region_event_inside_for_screen(C, &event->x);
+ ARegion *ar = sc ? BKE_screen_find_region_xy(sc, RGN_TYPE_ANY, event->x, event->y) : NULL;
if (ar == NULL) {
ar = ar_prev;
}
+ if (ar == NULL) {
+ return OPERATOR_PASS_THROUGH;
+ }
+
CTX_wm_region_set(C, ar);
uiBut *but = UI_context_active_but_get(C);
CTX_wm_region_set(C, ar_prev);
@@ -1545,7 +1536,7 @@ static int ui_button_press_invoke(bContext *C, wmOperator *op, const wmEvent *ev
* having this avoids a minor drawing glitch. */
void *but_optype = but->optype;
- UI_but_execute(C, but);
+ UI_but_execute(C, ar, but);
but->optype = but_optype;
diff --git a/source/blender/editors/interface/interface_region_color_picker.c b/source/blender/editors/interface/interface_region_color_picker.c
index 5c231f5e51a..917c35f0135 100644
--- a/source/blender/editors/interface/interface_region_color_picker.c
+++ b/source/blender/editors/interface/interface_region_color_picker.c
@@ -63,6 +63,21 @@ enum ePickerType {
/** \name Color Conversion
* \{ */
+static void ui_color_picker_rgb_round(float rgb[3])
+{
+ /* Handle small rounding errors in color space conversions. Doing these for
+ * all color space conversions would be expensive, but for the color picker
+ * we can do the extra work. */
+ for (int i = 0; i < 3; i++) {
+ if (fabsf(rgb[i]) < 1e-6f) {
+ rgb[i] = 0.0f;
+ }
+ else if (fabsf(1.0f - rgb[i]) < 1e-6f) {
+ rgb[i] = 1.0f;
+ }
+ }
+}
+
void ui_rgb_to_color_picker_compat_v(const float rgb[3], float r_cp[3])
{
switch (U.color_picker_type) {
@@ -131,6 +146,7 @@ void ui_scene_linear_to_color_picker_space(uiBut *but, float rgb[3])
* space for intuitive color picking. */
if (!ui_but_is_color_gamma(but)) {
IMB_colormanagement_scene_linear_to_color_picking_v3(rgb);
+ ui_color_picker_rgb_round(rgb);
}
}
@@ -138,6 +154,7 @@ void ui_color_picker_to_scene_linear_space(uiBut *but, float rgb[3])
{
if (!ui_but_is_color_gamma(but)) {
IMB_colormanagement_color_picking_to_scene_linear_v3(rgb);
+ ui_color_picker_rgb_round(rgb);
}
}
@@ -201,6 +218,7 @@ static void ui_update_color_picker_buts_rgb(uiBut *from_but,
copy_v3_v3(rgb_hex, rgb);
if (from_but && !ui_but_is_color_gamma(from_but)) {
IMB_colormanagement_scene_linear_to_srgb_v3(rgb_hex);
+ ui_color_picker_rgb_round(rgb_hex);
}
rgb_float_to_uchar(rgb_hex_uchar, rgb_hex);
@@ -287,6 +305,7 @@ static void ui_colorpicker_hex_rna_cb(bContext *UNUSED(C), void *bt1, void *hexc
/* Hex code is assumed to be in sRGB space (coming from other applications, web, etc) */
if (!ui_but_is_color_gamma(but)) {
IMB_colormanagement_srgb_to_scene_linear_v3(rgb);
+ ui_color_picker_rgb_round(rgb);
}
ui_update_color_picker_buts_rgb(but, but->block, cpicker, rgb);
@@ -765,6 +784,7 @@ static void ui_block_colorpicker(uiBlock *block, uiBut *from_but, float rgba[4],
if (!ui_but_is_color_gamma(from_but)) {
IMB_colormanagement_scene_linear_to_srgb_v3(rgb_hex);
+ ui_color_picker_rgb_round(rgb_hex);
}
rgb_float_to_uchar(rgb_hex_uchar, rgb_hex);
diff --git a/source/blender/editors/interface/interface_region_hud.c b/source/blender/editors/interface/interface_region_hud.c
index 6d1b2baeff9..43afdc534ad 100644
--- a/source/blender/editors/interface/interface_region_hud.c
+++ b/source/blender/editors/interface/interface_region_hud.c
@@ -27,6 +27,7 @@
#include "MEM_guardedalloc.h"
+#include "DNA_screen_types.h"
#include "DNA_userdef_types.h"
#include "BLI_string.h"
@@ -231,6 +232,11 @@ ARegionType *ED_area_type_hud(int space_type)
art->init = hud_region_init;
art->free = hud_region_free;
+ /* We need to indicate a preferred size to avoid false `RGN_FLAG_TOO_SMALL`
+ * the first time the region is created. */
+ art->prefsizex = AREAMINX;
+ art->prefsizey = HEADERY;
+
hud_panels_register(art, space_type, art->regionid);
art->lock = 1; /* can become flag, see BKE_spacedata_draw_locks */
diff --git a/source/blender/editors/interface/interface_region_popover.c b/source/blender/editors/interface/interface_region_popover.c
index 22c62ecd6f7..53c96fb72a7 100644
--- a/source/blender/editors/interface/interface_region_popover.c
+++ b/source/blender/editors/interface/interface_region_popover.c
@@ -355,7 +355,7 @@ uiPopover *UI_popover_begin(bContext *C, int ui_size_x)
}
pup->ui_size_x = ui_size_x;
- /* Opertor context default same as menus, change if needed. */
+ /* Operator context default same as menus, change if needed. */
ui_popover_create_block(C, pup, WM_OP_EXEC_REGION_WIN);
/* create in advance so we can let buttons point to retval already */
@@ -404,7 +404,7 @@ void UI_popover_end(bContext *C, uiPopover *pup, wmKeyMap *keymap)
/* TODO(campbell): we may want to make this configurable.
* The begin/end stype of calling popups doesn't allow to 'can_refresh' to be set.
- * For now close this style of popvers when accessed. */
+ * For now close this style of popovers when accessed. */
UI_block_flag_disable(pup->block, UI_BLOCK_KEEP_OPEN);
/* panels are created flipped (from event handling pov) */
diff --git a/source/blender/editors/interface/interface_templates.c b/source/blender/editors/interface/interface_templates.c
index 5d3ef5c625e..1fc1af9815f 100644
--- a/source/blender/editors/interface/interface_templates.c
+++ b/source/blender/editors/interface/interface_templates.c
@@ -952,7 +952,7 @@ static void template_ID(bContext *C,
/* Due to space limit in UI - skip the "open" icon for packed data, and allow to unpack.
* Only for images, sound and fonts */
- if (id && BKE_pack_check(id)) {
+ if (id && BKE_packedfile_id_check(id)) {
but = uiDefIconButO(block,
UI_BTYPE_BUT,
"FILE_OT_unpack_item",
diff --git a/source/blender/editors/interface/interface_widgets.c b/source/blender/editors/interface/interface_widgets.c
index ec0b01d4341..0bf8247dc17 100644
--- a/source/blender/editors/interface/interface_widgets.c
+++ b/source/blender/editors/interface/interface_widgets.c
@@ -2636,7 +2636,7 @@ static void widget_state_numslider(uiWidgetType *wt, int state, int drawflag)
wt->wcol.item[0] = wt->wcol.item[1] = wt->wcol.item[2] = rgb_to_grayscale_byte(
(const uchar *)wt->wcol.item);
widget_state_blend(wt->wcol.item, color_blend, wcol_state->blend);
- rgb_ensure_contrast(wt->wcol.item, wt->wcol.inner, 20);
+ rgb_ensure_contrast(wt->wcol.item, wt->wcol.inner, 30);
}
if (state & UI_SELECT) {
diff --git a/source/blender/editors/interface/resources.c b/source/blender/editors/interface/resources.c
index e281c6c9e9c..25116934b06 100644
--- a/source/blender/editors/interface/resources.c
+++ b/source/blender/editors/interface/resources.c
@@ -901,6 +901,12 @@ const uchar *UI_ThemeGetColorPtr(bTheme *btheme, int spacetype, int colorid)
case TH_ICON_SHADING:
cp = btheme->tui.icon_shading;
break;
+ case TH_ICON_FUND: {
+ /* Development fund icon color is not part of theme. */
+ static const char red[4] = {204, 48, 72, 255};
+ cp = red;
+ break;
+ }
case TH_SCROLL_TEXT:
cp = btheme->tui.wcol_scroll.text;
@@ -1377,12 +1383,14 @@ bool UI_GetIconThemeColor4ubv(int colorid, uchar col[4])
if (colorid == 0) {
return false;
}
-
- /* Only colored icons in outliner and popups, overall UI is intended
- * to stay monochrome and out of the way except a few places where it
- * is important to communicate different data types. */
- if (!((theme_spacetype == SPACE_OUTLINER && theme_regionid == RGN_TYPE_WINDOW) ||
- (theme_spacetype == SPACE_PROPERTIES && theme_regionid == RGN_TYPE_NAV_BAR))) {
+ else if (colorid == TH_ICON_FUND) {
+ /* Always color development fund icon. */
+ }
+ else if (!((theme_spacetype == SPACE_OUTLINER && theme_regionid == RGN_TYPE_WINDOW) ||
+ (theme_spacetype == SPACE_PROPERTIES && theme_regionid == RGN_TYPE_NAV_BAR))) {
+ /* Only colored icons in outliner and popups, overall UI is intended
+ * to stay monochrome and out of the way except a few places where it
+ * is important to communicate different data types. */
return false;
}
diff --git a/source/blender/editors/io/io_collada.c b/source/blender/editors/io/io_collada.c
index 1f844961d19..dad84c87fd7 100644
--- a/source/blender/editors/io/io_collada.c
+++ b/source/blender/editors/io/io_collada.c
@@ -593,8 +593,8 @@ void WM_OT_collada_export(wmOperatorType *ot)
"apply_global_orientation",
false,
"Apply Global Orientation",
- "enabled: Rotate all root objects to match the global orientation "
- "settings.\ndisabled: set global orientation in Collada assets");
+ "Rotate all root objects to match the global orientation settings "
+ "otherwise set the global orientation per Collada asset");
RNA_def_boolean(func, "selected", false, "Selection Only", "Export only selected elements");
@@ -726,8 +726,8 @@ void WM_OT_collada_export(wmOperatorType *ot)
INT_MIN,
INT_MAX,
"Transform",
- "Transformation type for translation, scale and rotation\n"
- "Note: The Animation transformation type in the Anim Tab\n"
+ "Transformation type for translation, scale and rotation. "
+ "Note: The Animation transformation type in the Anim Tab "
"is always equal to the Object transformation type in the Geom tab",
INT_MIN,
INT_MAX);
@@ -737,8 +737,8 @@ void WM_OT_collada_export(wmOperatorType *ot)
prop_bc_export_transformation_type,
0,
"Transform",
- "Transformation type for translation, scale and rotation\n"
- "Note: The Animation transformation type in the Anim Tab\n"
+ "Transformation type for translation, scale and rotation. "
+ "Note: The Animation transformation type in the Anim Tab "
"is always equal to the Object transformation type in the Geom tab");
RNA_def_boolean(func,
diff --git a/source/blender/editors/lattice/editlattice_undo.c b/source/blender/editors/lattice/editlattice_undo.c
index 166201adc15..abc5224c4d6 100644
--- a/source/blender/editors/lattice/editlattice_undo.c
+++ b/source/blender/editors/lattice/editlattice_undo.c
@@ -68,9 +68,19 @@ typedef struct UndoLattice {
static void undolatt_to_editlatt(UndoLattice *ult, EditLatt *editlatt)
{
- int len = editlatt->latt->pntsu * editlatt->latt->pntsv * editlatt->latt->pntsw;
+ const int len_src = ult->pntsu * ult->pntsv * ult->pntsw;
+ const int len_dst = editlatt->latt->pntsu * editlatt->latt->pntsv * editlatt->latt->pntsw;
+ if (len_src != len_dst) {
+ MEM_freeN(editlatt->latt->def);
+ editlatt->latt->def = MEM_dupallocN(ult->def);
+ }
+ else {
+ memcpy(editlatt->latt->def, ult->def, sizeof(BPoint) * len_src);
+ }
- memcpy(editlatt->latt->def, ult->def, sizeof(BPoint) * len);
+ editlatt->latt->pntsu = ult->pntsu;
+ editlatt->latt->pntsv = ult->pntsv;
+ editlatt->latt->pntsw = ult->pntsw;
editlatt->latt->actbp = ult->actbp;
}
@@ -176,7 +186,8 @@ static bool lattice_undosys_step_encode(struct bContext *C,
static void lattice_undosys_step_decode(struct bContext *C,
struct Main *UNUSED(bmain),
UndoStep *us_p,
- int UNUSED(dir))
+ int UNUSED(dir),
+ bool UNUSED(is_final))
{
LatticeUndoStep *us = (LatticeUndoStep *)us_p;
diff --git a/source/blender/editors/mask/mask_add.c b/source/blender/editors/mask/mask_add.c
index fc85eab6e66..883dfe9ad7c 100644
--- a/source/blender/editors/mask/mask_add.c
+++ b/source/blender/editors/mask/mask_add.c
@@ -869,7 +869,7 @@ static int primitive_add_invoke(bContext *C, wmOperator *op, const wmEvent *UNUS
return op->type->exec(C, op);
}
-static void define_prinitive_add_properties(wmOperatorType *ot)
+static void define_primitive_add_properties(wmOperatorType *ot)
{
RNA_def_float(
ot->srna, "size", 100, -FLT_MAX, FLT_MAX, "Size", "Size of new circle", -FLT_MAX, FLT_MAX);
@@ -913,7 +913,7 @@ void MASK_OT_primitive_circle_add(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
/* properties */
- define_prinitive_add_properties(ot);
+ define_primitive_add_properties(ot);
}
/******************** primitive add suqare *********************/
@@ -944,5 +944,5 @@ void MASK_OT_primitive_square_add(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
/* properties */
- define_prinitive_add_properties(ot);
+ define_primitive_add_properties(ot);
}
diff --git a/source/blender/editors/mask/mask_ops.c b/source/blender/editors/mask/mask_ops.c
index a205f6878e3..8e4efddd8a7 100644
--- a/source/blender/editors/mask/mask_ops.c
+++ b/source/blender/editors/mask/mask_ops.c
@@ -441,6 +441,7 @@ static int masklay_new_exec(bContext *C, wmOperator *op)
mask->masklay_act = mask->masklay_tot - 1;
WM_event_add_notifier(C, NC_MASK | NA_EDITED, mask);
+ DEG_id_tag_update(&mask->id, ID_RECALC_COPY_ON_WRITE);
return OPERATOR_FINISHED;
}
@@ -474,6 +475,7 @@ static int masklay_remove_exec(bContext *C, wmOperator *UNUSED(op))
BKE_mask_layer_remove(mask, masklay);
WM_event_add_notifier(C, NC_MASK | NA_EDITED, mask);
+ DEG_id_tag_update(&mask->id, ID_RECALC_COPY_ON_WRITE);
}
return OPERATOR_FINISHED;
@@ -2206,6 +2208,7 @@ static int mask_layer_move_exec(bContext *C, wmOperator *op)
}
WM_event_add_notifier(C, NC_MASK | NA_EDITED, mask);
+ DEG_id_tag_update(&mask->id, ID_RECALC_COPY_ON_WRITE);
return OPERATOR_FINISHED;
}
diff --git a/source/blender/editors/mesh/editmesh_bevel.c b/source/blender/editors/mesh/editmesh_bevel.c
index 78b4cfe38d4..b4ef2620895 100644
--- a/source/blender/editors/mesh/editmesh_bevel.c
+++ b/source/blender/editors/mesh/editmesh_bevel.c
@@ -263,14 +263,14 @@ static bool edbm_bevel_init(bContext *C, wmOperator *op, const bool is_modal)
initNumInput(&opdata->num_input[i]);
opdata->num_input[i].idx_max = 0;
opdata->num_input[i].val_flag[0] |= NUM_NO_NEGATIVE;
+ opdata->num_input[i].unit_type[0] = B_UNIT_NONE;
if (i == SEGMENTS_VALUE) {
opdata->num_input[i].val_flag[0] |= NUM_NO_FRACTION | NUM_NO_ZERO;
}
if (i == OFFSET_VALUE) {
opdata->num_input[i].unit_sys = scene->unit.system;
+ opdata->num_input[i].unit_type[0] = B_UNIT_LENGTH;
}
- /* Not sure this is a factor or a unit? */
- opdata->num_input[i].unit_type[0] = B_UNIT_NONE;
}
/* avoid the cost of allocating a bm copy */
diff --git a/source/blender/editors/mesh/editmesh_tools.c b/source/blender/editors/mesh/editmesh_tools.c
index 26d830ccaec..919de4cdb20 100644
--- a/source/blender/editors/mesh/editmesh_tools.c
+++ b/source/blender/editors/mesh/editmesh_tools.c
@@ -534,6 +534,9 @@ static int edbm_delete_exec(bContext *C, wmOperator *op)
EDBM_flag_disable_all(em, BM_ELEM_SELECT);
EDBM_update_generic(em, true, true);
+
+ DEG_id_tag_update(obedit->data, ID_RECALC_SELECT);
+ WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
}
MEM_freeN(objects);
@@ -7415,7 +7418,7 @@ void MESH_OT_symmetry_snap(struct wmOperatorType *ot)
#ifdef WITH_FREESTYLE
/* -------------------------------------------------------------------- */
-/** \name Mark Edge (FreeStyle) Operator
+/** \name Mark Edge (Freestyle) Operator
* \{ */
static int edbm_mark_freestyle_edge_exec(bContext *C, wmOperator *op)
@@ -7495,7 +7498,7 @@ void MESH_OT_mark_freestyle_edge(wmOperatorType *ot)
/** \} */
/* -------------------------------------------------------------------- */
-/** \name Mark Face (FreeStyle) Operator
+/** \name Mark Face (Freestyle) Operator
* \{ */
static int edbm_mark_freestyle_face_exec(bContext *C, wmOperator *op)
@@ -8015,6 +8018,7 @@ static int edbm_point_normals_invoke(bContext *C, wmOperator *op, const wmEvent
return OPERATOR_RUNNING_MODAL;
}
+/* TODO: make this work on multiple objects at once */
static int edbm_point_normals_exec(bContext *C, wmOperator *op)
{
Object *obedit = CTX_data_edit_object(C);
@@ -8237,44 +8241,54 @@ static void normals_split(BMesh *bm)
static int normals_split_merge(bContext *C, const bool do_merge)
{
- Object *obedit = CTX_data_edit_object(C);
- BMEditMesh *em = BKE_editmesh_from_object(obedit);
- BMesh *bm = em->bm;
- BMEdge *e;
- BMIter eiter;
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ uint objects_len = 0;
+ Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(
+ view_layer, CTX_wm_view3d(C), &objects_len);
- BKE_editmesh_ensure_autosmooth(em);
- BKE_editmesh_lnorspace_update(em);
+ for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
+ Object *obedit = objects[ob_index];
+ BMEditMesh *em = BKE_editmesh_from_object(obedit);
+ BMesh *bm = em->bm;
+ BMEdge *e;
+ BMIter eiter;
- /* Note that we need temp lnor editing data for all loops of all affected vertices, since by
- * setting some faces/edges as smooth we are going to change clnors spaces... See also T65809. */
- BMLoopNorEditDataArray *lnors_ed_arr = do_merge ? BM_loop_normal_editdata_array_init(bm, true) :
- NULL;
+ BKE_editmesh_ensure_autosmooth(em);
+ BKE_editmesh_lnorspace_update(em);
- mesh_set_smooth_faces(em, do_merge);
+ /* Note that we need temp lnor editing data for all loops of all affected vertices, since by
+ * setting some faces/edges as smooth we are going to change clnors spaces... See also T65809.
+ */
+ BMLoopNorEditDataArray *lnors_ed_arr = do_merge ?
+ BM_loop_normal_editdata_array_init(bm, true) :
+ NULL;
- BM_ITER_MESH (e, &eiter, bm, BM_EDGES_OF_MESH) {
- if (BM_elem_flag_test(e, BM_ELEM_SELECT)) {
- BM_elem_flag_set(e, BM_ELEM_SMOOTH, do_merge);
+ mesh_set_smooth_faces(em, do_merge);
+
+ BM_ITER_MESH (e, &eiter, bm, BM_EDGES_OF_MESH) {
+ if (BM_elem_flag_test(e, BM_ELEM_SELECT)) {
+ BM_elem_flag_set(e, BM_ELEM_SMOOTH, do_merge);
+ }
}
- }
- bm->spacearr_dirty |= BM_SPACEARR_DIRTY_ALL;
- BKE_editmesh_lnorspace_update(em);
+ bm->spacearr_dirty |= BM_SPACEARR_DIRTY_ALL;
+ BKE_editmesh_lnorspace_update(em);
- if (do_merge) {
- normals_merge(bm, lnors_ed_arr);
- }
- else {
- normals_split(bm);
- }
+ if (do_merge) {
+ normals_merge(bm, lnors_ed_arr);
+ }
+ else {
+ normals_split(bm);
+ }
- if (lnors_ed_arr) {
- BM_loop_normal_editdata_array_free(lnors_ed_arr);
- }
+ if (lnors_ed_arr) {
+ BM_loop_normal_editdata_array_free(lnors_ed_arr);
+ }
- EDBM_update_generic(em, true, false);
+ EDBM_update_generic(em, true, false);
+ }
+ MEM_freeN(objects);
return OPERATOR_FINISHED;
}
@@ -8343,131 +8357,140 @@ static EnumPropertyItem average_method_items[] = {
static int edbm_average_normals_exec(bContext *C, wmOperator *op)
{
- Object *obedit = CTX_data_edit_object(C);
- BMEditMesh *em = BKE_editmesh_from_object(obedit);
- BMesh *bm = em->bm;
- BMFace *f;
- BMLoop *l, *l_curr, *l_first;
- BMIter fiter;
-
- BKE_editmesh_ensure_autosmooth(em);
- bm->spacearr_dirty |= BM_SPACEARR_DIRTY_ALL;
- BKE_editmesh_lnorspace_update(em);
-
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ uint objects_len = 0;
+ Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(
+ view_layer, CTX_wm_view3d(C), &objects_len);
const int average_type = RNA_enum_get(op->ptr, "average_type");
- const int cd_clnors_offset = CustomData_get_offset(&bm->ldata, CD_CUSTOMLOOPNORMAL);
const float absweight = (float)RNA_int_get(op->ptr, "weight");
const float threshold = RNA_float_get(op->ptr, "threshold");
- float weight = absweight / 50.0f;
- if (absweight == 100.0f) {
- weight = (float)SHRT_MAX;
- }
- else if (absweight == 1.0f) {
- weight = 1 / (float)SHRT_MAX;
- }
- else if ((weight - 1) * 25 > 1) {
- weight = (weight - 1) * 25;
- }
+ for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
+ Object *obedit = objects[ob_index];
+ BMEditMesh *em = BKE_editmesh_from_object(obedit);
+ BMesh *bm = em->bm;
+ BMFace *f;
+ BMLoop *l, *l_curr, *l_first;
+ BMIter fiter;
- BM_normals_loops_edges_tag(bm, true);
+ BKE_editmesh_ensure_autosmooth(em);
+ bm->spacearr_dirty |= BM_SPACEARR_DIRTY_ALL;
+ BKE_editmesh_lnorspace_update(em);
- HeapSimple *loop_weight = BLI_heapsimple_new();
+ const int cd_clnors_offset = CustomData_get_offset(&bm->ldata, CD_CUSTOMLOOPNORMAL);
- BM_ITER_MESH (f, &fiter, bm, BM_FACES_OF_MESH) {
- l_curr = l_first = BM_FACE_FIRST_LOOP(f);
- do {
- if (BM_elem_flag_test(l_curr->v, BM_ELEM_SELECT) &&
- (!BM_elem_flag_test(l_curr->e, BM_ELEM_TAG) ||
- (!BM_elem_flag_test(l_curr, BM_ELEM_TAG) && BM_loop_check_cyclic_smooth_fan(l_curr)))) {
- if (!BM_elem_flag_test(l_curr->e, BM_ELEM_TAG) &&
- !BM_elem_flag_test(l_curr->prev->e, BM_ELEM_TAG)) {
- const int loop_index = BM_elem_index_get(l_curr);
- short *clnors = BM_ELEM_CD_GET_VOID_P(l_curr, cd_clnors_offset);
- BKE_lnor_space_custom_normal_to_data(
- bm->lnor_spacearr->lspacearr[loop_index], f->no, clnors);
- }
- else {
- BMVert *v_pivot = l_curr->v;
- UNUSED_VARS_NDEBUG(v_pivot);
- BMEdge *e_next;
- const BMEdge *e_org = l_curr->e;
- BMLoop *lfan_pivot, *lfan_pivot_next;
+ float weight = absweight / 50.0f;
+ if (absweight == 100.0f) {
+ weight = (float)SHRT_MAX;
+ }
+ else if (absweight == 1.0f) {
+ weight = 1 / (float)SHRT_MAX;
+ }
+ else if ((weight - 1) * 25 > 1) {
+ weight = (weight - 1) * 25;
+ }
- lfan_pivot = l_curr;
- e_next = lfan_pivot->e;
+ BM_normals_loops_edges_tag(bm, true);
- while (true) {
- lfan_pivot_next = BM_vert_step_fan_loop(lfan_pivot, &e_next);
- if (lfan_pivot_next) {
- BLI_assert(lfan_pivot_next->v == v_pivot);
- }
- else {
- e_next = (lfan_pivot->e == e_next) ? lfan_pivot->prev->e : lfan_pivot->e;
- }
+ HeapSimple *loop_weight = BLI_heapsimple_new();
- float val = 1.0f;
- if (average_type == EDBM_CLNOR_AVERAGE_FACE_AREA) {
- val = 1.0f / BM_face_calc_area(lfan_pivot->f);
- }
- else if (average_type == EDBM_CLNOR_AVERAGE_ANGLE) {
- val = 1.0f / BM_loop_calc_face_angle(lfan_pivot);
- }
+ BM_ITER_MESH (f, &fiter, bm, BM_FACES_OF_MESH) {
+ l_curr = l_first = BM_FACE_FIRST_LOOP(f);
+ do {
+ if (BM_elem_flag_test(l_curr->v, BM_ELEM_SELECT) &&
+ (!BM_elem_flag_test(l_curr->e, BM_ELEM_TAG) ||
+ (!BM_elem_flag_test(l_curr, BM_ELEM_TAG) &&
+ BM_loop_check_cyclic_smooth_fan(l_curr)))) {
+ if (!BM_elem_flag_test(l_curr->e, BM_ELEM_TAG) &&
+ !BM_elem_flag_test(l_curr->prev->e, BM_ELEM_TAG)) {
+ const int loop_index = BM_elem_index_get(l_curr);
+ short *clnors = BM_ELEM_CD_GET_VOID_P(l_curr, cd_clnors_offset);
+ BKE_lnor_space_custom_normal_to_data(
+ bm->lnor_spacearr->lspacearr[loop_index], f->no, clnors);
+ }
+ else {
+ BMVert *v_pivot = l_curr->v;
+ UNUSED_VARS_NDEBUG(v_pivot);
+ BMEdge *e_next;
+ const BMEdge *e_org = l_curr->e;
+ BMLoop *lfan_pivot, *lfan_pivot_next;
+
+ lfan_pivot = l_curr;
+ e_next = lfan_pivot->e;
+
+ while (true) {
+ lfan_pivot_next = BM_vert_step_fan_loop(lfan_pivot, &e_next);
+ if (lfan_pivot_next) {
+ BLI_assert(lfan_pivot_next->v == v_pivot);
+ }
+ else {
+ e_next = (lfan_pivot->e == e_next) ? lfan_pivot->prev->e : lfan_pivot->e;
+ }
- BLI_heapsimple_insert(loop_weight, val, lfan_pivot);
+ float val = 1.0f;
+ if (average_type == EDBM_CLNOR_AVERAGE_FACE_AREA) {
+ val = 1.0f / BM_face_calc_area(lfan_pivot->f);
+ }
+ else if (average_type == EDBM_CLNOR_AVERAGE_ANGLE) {
+ val = 1.0f / BM_loop_calc_face_angle(lfan_pivot);
+ }
- if (!BM_elem_flag_test(e_next, BM_ELEM_TAG) || (e_next == e_org)) {
- break;
- }
- lfan_pivot = lfan_pivot_next;
- }
+ BLI_heapsimple_insert(loop_weight, val, lfan_pivot);
- BLI_SMALLSTACK_DECLARE(loops, BMLoop *);
- float wnor[3], avg_normal[3] = {0.0f}, count = 0;
- float val = BLI_heapsimple_top_value(loop_weight);
-
- while (!BLI_heapsimple_is_empty(loop_weight)) {
- const float cur_val = BLI_heapsimple_top_value(loop_weight);
- if (!compare_ff(val, cur_val, threshold)) {
- count++;
- val = cur_val;
+ if (!BM_elem_flag_test(e_next, BM_ELEM_TAG) || (e_next == e_org)) {
+ break;
+ }
+ lfan_pivot = lfan_pivot_next;
}
- l = BLI_heapsimple_pop_min(loop_weight);
- BLI_SMALLSTACK_PUSH(loops, l);
- const float n_weight = pow(weight, count);
+ BLI_SMALLSTACK_DECLARE(loops, BMLoop *);
+ float wnor[3], avg_normal[3] = {0.0f}, count = 0;
+ float val = BLI_heapsimple_top_value(loop_weight);
+
+ while (!BLI_heapsimple_is_empty(loop_weight)) {
+ const float cur_val = BLI_heapsimple_top_value(loop_weight);
+ if (!compare_ff(val, cur_val, threshold)) {
+ count++;
+ val = cur_val;
+ }
+ l = BLI_heapsimple_pop_min(loop_weight);
+ BLI_SMALLSTACK_PUSH(loops, l);
+
+ const float n_weight = pow(weight, count);
+
+ if (average_type == EDBM_CLNOR_AVERAGE_LOOP) {
+ const int l_index = BM_elem_index_get(l);
+ short *clnors = BM_ELEM_CD_GET_VOID_P(l, cd_clnors_offset);
+ BKE_lnor_space_custom_data_to_normal(
+ bm->lnor_spacearr->lspacearr[l_index], clnors, wnor);
+ }
+ else {
+ copy_v3_v3(wnor, l->f->no);
+ }
+ mul_v3_fl(wnor, (1.0f / cur_val) * (1.0f / n_weight));
+ add_v3_v3(avg_normal, wnor);
+ }
- if (average_type == EDBM_CLNOR_AVERAGE_LOOP) {
+ if (normalize_v3(avg_normal) < CLNORS_VALID_VEC_LEN) {
+ /* If avg normal is nearly 0, set clnor to default value. */
+ zero_v3(avg_normal);
+ }
+ while ((l = BLI_SMALLSTACK_POP(loops))) {
const int l_index = BM_elem_index_get(l);
short *clnors = BM_ELEM_CD_GET_VOID_P(l, cd_clnors_offset);
- BKE_lnor_space_custom_data_to_normal(
- bm->lnor_spacearr->lspacearr[l_index], clnors, wnor);
- }
- else {
- copy_v3_v3(wnor, l->f->no);
+ BKE_lnor_space_custom_normal_to_data(
+ bm->lnor_spacearr->lspacearr[l_index], avg_normal, clnors);
}
- mul_v3_fl(wnor, (1.0f / cur_val) * (1.0f / n_weight));
- add_v3_v3(avg_normal, wnor);
- }
-
- if (normalize_v3(avg_normal) < CLNORS_VALID_VEC_LEN) {
- /* If avg normal is nearly 0, set clnor to default value. */
- zero_v3(avg_normal);
- }
- while ((l = BLI_SMALLSTACK_POP(loops))) {
- const int l_index = BM_elem_index_get(l);
- short *clnors = BM_ELEM_CD_GET_VOID_P(l, cd_clnors_offset);
- BKE_lnor_space_custom_normal_to_data(
- bm->lnor_spacearr->lspacearr[l_index], avg_normal, clnors);
}
}
- }
- } while ((l_curr = l_curr->next) != l_first);
- }
+ } while ((l_curr = l_curr->next) != l_first);
+ }
- BLI_heapsimple_free(loop_weight, NULL);
- EDBM_update_generic(em, true, false);
+ BLI_heapsimple_free(loop_weight, NULL);
+ EDBM_update_generic(em, true, false);
+ }
+ MEM_freeN(objects);
return OPERATOR_FINISHED;
}
@@ -8566,135 +8589,151 @@ static EnumPropertyItem normal_vector_tool_items[] = {
static int edbm_normals_tools_exec(bContext *C, wmOperator *op)
{
- Object *obedit = CTX_data_edit_object(C);
Scene *scene = CTX_data_scene(C);
- BMEditMesh *em = BKE_editmesh_from_object(obedit);
- BMesh *bm = em->bm;
-
- if (bm->totloop == 0) {
- return OPERATOR_CANCELLED;
- }
-
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ uint objects_len = 0;
+ Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(
+ view_layer, CTX_wm_view3d(C), &objects_len);
const int mode = RNA_enum_get(op->ptr, "mode");
const bool absolute = RNA_boolean_get(op->ptr, "absolute");
+ float *normal_vector = scene->toolsettings->normal_vector;
+ bool done_copy = false;
- BKE_editmesh_ensure_autosmooth(em);
- BKE_editmesh_lnorspace_update(em);
- BMLoopNorEditDataArray *lnors_ed_arr = BM_loop_normal_editdata_array_init(bm, false);
- BMLoopNorEditData *lnor_ed = lnors_ed_arr->lnor_editdata;
+ for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
+ Object *obedit = objects[ob_index];
+ BMEditMesh *em = BKE_editmesh_from_object(obedit);
+ BMesh *bm = em->bm;
- float *normal_vector = scene->toolsettings->normal_vector;
+ if (bm->totloop == 0) {
+ continue;
+ }
- switch (mode) {
- case EDBM_CLNOR_TOOLS_COPY:
- if (bm->totfacesel != 1 && lnors_ed_arr->totloop != 1 && bm->totvertsel != 1) {
- BKE_report(op->reports,
- RPT_ERROR,
- "Can only copy one custom normal, vertex normal or face normal");
- BM_loop_normal_editdata_array_free(lnors_ed_arr);
- return OPERATOR_CANCELLED;
- }
- if (lnors_ed_arr->totloop == 1) {
- copy_v3_v3(scene->toolsettings->normal_vector, lnors_ed_arr->lnor_editdata->nloc);
- }
- else if (bm->totfacesel == 1) {
- BMFace *f;
- BMIter fiter;
- BM_ITER_MESH (f, &fiter, bm, BM_FACES_OF_MESH) {
- if (BM_elem_flag_test(f, BM_ELEM_SELECT)) {
- copy_v3_v3(scene->toolsettings->normal_vector, f->no);
- }
+ BKE_editmesh_ensure_autosmooth(em);
+ BKE_editmesh_lnorspace_update(em);
+ BMLoopNorEditDataArray *lnors_ed_arr = BM_loop_normal_editdata_array_init(bm, false);
+ BMLoopNorEditData *lnor_ed = lnors_ed_arr->lnor_editdata;
+
+ switch (mode) {
+ case EDBM_CLNOR_TOOLS_COPY:
+ if (bm->totfacesel == 0 || bm->totvertsel == 0) {
+ BM_loop_normal_editdata_array_free(lnors_ed_arr);
+ continue;
}
- }
- else {
- /* 'Vertex' normal, i.e. common set of loop normals on the same vertex,
- * only if they are all the same. */
- bool are_same_lnors = true;
- for (int i = 0; i < lnors_ed_arr->totloop; i++, lnor_ed++) {
- if (!compare_v3v3(lnors_ed_arr->lnor_editdata->nloc, lnor_ed->nloc, 1e-4f)) {
- are_same_lnors = false;
- }
+
+ if (done_copy ||
+ (bm->totfacesel != 1 && lnors_ed_arr->totloop != 1 && bm->totvertsel != 1)) {
+ BKE_report(op->reports,
+ RPT_ERROR,
+ "Can only copy one custom normal, vertex normal or face normal");
+ BM_loop_normal_editdata_array_free(lnors_ed_arr);
+ continue;
}
- if (are_same_lnors) {
+ if (lnors_ed_arr->totloop == 1) {
copy_v3_v3(scene->toolsettings->normal_vector, lnors_ed_arr->lnor_editdata->nloc);
}
- }
- break;
+ else if (bm->totfacesel == 1) {
+ BMFace *f;
+ BMIter fiter;
+ BM_ITER_MESH (f, &fiter, bm, BM_FACES_OF_MESH) {
+ if (BM_elem_flag_test(f, BM_ELEM_SELECT)) {
+ copy_v3_v3(scene->toolsettings->normal_vector, f->no);
+ }
+ }
+ }
+ else {
+ /* 'Vertex' normal, i.e. common set of loop normals on the same vertex,
+ * only if they are all the same. */
+ bool are_same_lnors = true;
+ for (int i = 0; i < lnors_ed_arr->totloop; i++, lnor_ed++) {
+ if (!compare_v3v3(lnors_ed_arr->lnor_editdata->nloc, lnor_ed->nloc, 1e-4f)) {
+ are_same_lnors = false;
+ }
+ }
+ if (are_same_lnors) {
+ copy_v3_v3(scene->toolsettings->normal_vector, lnors_ed_arr->lnor_editdata->nloc);
+ }
+ }
+ done_copy = true;
+ break;
- case EDBM_CLNOR_TOOLS_PASTE:
- if (!absolute) {
- if (normalize_v3(normal_vector) < CLNORS_VALID_VEC_LEN) {
- /* If normal is nearly 0, do nothing. */
- break;
+ case EDBM_CLNOR_TOOLS_PASTE:
+ if (!absolute) {
+ if (normalize_v3(normal_vector) < CLNORS_VALID_VEC_LEN) {
+ /* If normal is nearly 0, do nothing. */
+ break;
+ }
}
- }
- for (int i = 0; i < lnors_ed_arr->totloop; i++, lnor_ed++) {
- if (absolute) {
- float abs_normal[3];
- copy_v3_v3(abs_normal, lnor_ed->loc);
- negate_v3(abs_normal);
- add_v3_v3(abs_normal, normal_vector);
+ for (int i = 0; i < lnors_ed_arr->totloop; i++, lnor_ed++) {
+ if (absolute) {
+ float abs_normal[3];
+ copy_v3_v3(abs_normal, lnor_ed->loc);
+ negate_v3(abs_normal);
+ add_v3_v3(abs_normal, normal_vector);
+
+ if (normalize_v3(abs_normal) < CLNORS_VALID_VEC_LEN) {
+ /* If abs normal is nearly 0, set clnor to initial value. */
+ copy_v3_v3(abs_normal, lnor_ed->niloc);
+ }
+ BKE_lnor_space_custom_normal_to_data(bm->lnor_spacearr->lspacearr[lnor_ed->loop_index],
+ abs_normal,
+ lnor_ed->clnors_data);
+ }
+ else {
+ BKE_lnor_space_custom_normal_to_data(bm->lnor_spacearr->lspacearr[lnor_ed->loop_index],
+ normal_vector,
+ lnor_ed->clnors_data);
+ }
+ }
+ break;
- if (normalize_v3(abs_normal) < CLNORS_VALID_VEC_LEN) {
+ case EDBM_CLNOR_TOOLS_MULTIPLY:
+ for (int i = 0; i < lnors_ed_arr->totloop; i++, lnor_ed++) {
+ mul_v3_v3(lnor_ed->nloc, normal_vector);
+
+ if (normalize_v3(lnor_ed->nloc) < CLNORS_VALID_VEC_LEN) {
/* If abs normal is nearly 0, set clnor to initial value. */
- copy_v3_v3(abs_normal, lnor_ed->niloc);
+ copy_v3_v3(lnor_ed->nloc, lnor_ed->niloc);
}
- BKE_lnor_space_custom_normal_to_data(
- bm->lnor_spacearr->lspacearr[lnor_ed->loop_index], abs_normal, lnor_ed->clnors_data);
- }
- else {
BKE_lnor_space_custom_normal_to_data(bm->lnor_spacearr->lspacearr[lnor_ed->loop_index],
- normal_vector,
+ lnor_ed->nloc,
lnor_ed->clnors_data);
}
- }
- break;
+ break;
- case EDBM_CLNOR_TOOLS_MULTIPLY:
- for (int i = 0; i < lnors_ed_arr->totloop; i++, lnor_ed++) {
- mul_v3_v3(lnor_ed->nloc, normal_vector);
+ case EDBM_CLNOR_TOOLS_ADD:
+ for (int i = 0; i < lnors_ed_arr->totloop; i++, lnor_ed++) {
+ add_v3_v3(lnor_ed->nloc, normal_vector);
- if (normalize_v3(lnor_ed->nloc) < CLNORS_VALID_VEC_LEN) {
- /* If abs normal is nearly 0, set clnor to initial value. */
- copy_v3_v3(lnor_ed->nloc, lnor_ed->niloc);
+ if (normalize_v3(lnor_ed->nloc) < CLNORS_VALID_VEC_LEN) {
+ /* If abs normal is nearly 0, set clnor to initial value. */
+ copy_v3_v3(lnor_ed->nloc, lnor_ed->niloc);
+ }
+ BKE_lnor_space_custom_normal_to_data(bm->lnor_spacearr->lspacearr[lnor_ed->loop_index],
+ lnor_ed->nloc,
+ lnor_ed->clnors_data);
}
- BKE_lnor_space_custom_normal_to_data(bm->lnor_spacearr->lspacearr[lnor_ed->loop_index],
- lnor_ed->nloc,
- lnor_ed->clnors_data);
- }
- break;
-
- case EDBM_CLNOR_TOOLS_ADD:
- for (int i = 0; i < lnors_ed_arr->totloop; i++, lnor_ed++) {
- add_v3_v3(lnor_ed->nloc, normal_vector);
+ break;
- if (normalize_v3(lnor_ed->nloc) < CLNORS_VALID_VEC_LEN) {
- /* If abs normal is nearly 0, set clnor to initial value. */
- copy_v3_v3(lnor_ed->nloc, lnor_ed->niloc);
+ case EDBM_CLNOR_TOOLS_RESET:
+ zero_v3(normal_vector);
+ for (int i = 0; i < lnors_ed_arr->totloop; i++, lnor_ed++) {
+ BKE_lnor_space_custom_normal_to_data(bm->lnor_spacearr->lspacearr[lnor_ed->loop_index],
+ normal_vector,
+ lnor_ed->clnors_data);
}
- BKE_lnor_space_custom_normal_to_data(bm->lnor_spacearr->lspacearr[lnor_ed->loop_index],
- lnor_ed->nloc,
- lnor_ed->clnors_data);
- }
- break;
+ break;
- case EDBM_CLNOR_TOOLS_RESET:
- zero_v3(normal_vector);
- for (int i = 0; i < lnors_ed_arr->totloop; i++, lnor_ed++) {
- BKE_lnor_space_custom_normal_to_data(bm->lnor_spacearr->lspacearr[lnor_ed->loop_index],
- normal_vector,
- lnor_ed->clnors_data);
- }
- break;
+ default:
+ BLI_assert(0);
+ break;
+ }
- default:
- BLI_assert(0);
- break;
- }
+ BM_loop_normal_editdata_array_free(lnors_ed_arr);
- BM_loop_normal_editdata_array_free(lnors_ed_arr);
+ EDBM_update_generic(em, true, false);
+ }
- EDBM_update_generic(em, true, false);
+ MEM_freeN(objects);
return OPERATOR_FINISHED;
}
@@ -8841,8 +8880,8 @@ static int edbm_set_normals_from_faces_exec(bContext *C, wmOperator *op)
MEM_freeN(vnors);
EDBM_update_generic(em, true, false);
}
- MEM_freeN(objects);
+ MEM_freeN(objects);
return OPERATOR_FINISHED;
}
@@ -8865,77 +8904,86 @@ void MESH_OT_set_normals_from_faces(struct wmOperatorType *ot)
static int edbm_smoothen_normals_exec(bContext *C, wmOperator *op)
{
- Object *obedit = CTX_data_edit_object(C);
- BMEditMesh *em = BKE_editmesh_from_object(obedit);
- BMesh *bm = em->bm;
- BMFace *f;
- BMLoop *l;
- BMIter fiter, liter;
-
- BKE_editmesh_ensure_autosmooth(em);
- BKE_editmesh_lnorspace_update(em);
- BMLoopNorEditDataArray *lnors_ed_arr = BM_loop_normal_editdata_array_init(bm, false);
-
- float(*smooth_normal)[3] = MEM_callocN(sizeof(*smooth_normal) * lnors_ed_arr->totloop, __func__);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ uint objects_len = 0;
+ Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(
+ view_layer, CTX_wm_view3d(C), &objects_len);
- /* This is weird choice of operation, taking all loops of faces of current vertex.
- * Could lead to some rather far away loops weighting as much as very close ones
- * (topologically speaking), with complex polygons.
- * Using topological distance here (rather than geometrical one)
- * makes sense imho, but would rather go with a more consistent and flexible code,
- * we could even add max topological distance to take into account, * and a weighting curve.
- * Would do that later though, think for now we can live with that choice. --mont29. */
- BMLoopNorEditData *lnor_ed = lnors_ed_arr->lnor_editdata;
- for (int i = 0; i < lnors_ed_arr->totloop; i++, lnor_ed++) {
- l = lnor_ed->loop;
- float loop_normal[3];
+ for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
+ Object *obedit = objects[ob_index];
+ BMEditMesh *em = BKE_editmesh_from_object(obedit);
+ BMesh *bm = em->bm;
+ BMFace *f;
+ BMLoop *l;
+ BMIter fiter, liter;
- BM_ITER_ELEM (f, &fiter, l->v, BM_FACES_OF_VERT) {
- BMLoop *l_other;
- BM_ITER_ELEM (l_other, &liter, f, BM_LOOPS_OF_FACE) {
- const int l_index_other = BM_elem_index_get(l_other);
- short *clnors = BM_ELEM_CD_GET_VOID_P(l_other, lnors_ed_arr->cd_custom_normal_offset);
- BKE_lnor_space_custom_data_to_normal(
- bm->lnor_spacearr->lspacearr[l_index_other], clnors, loop_normal);
- add_v3_v3(smooth_normal[i], loop_normal);
+ BKE_editmesh_ensure_autosmooth(em);
+ BKE_editmesh_lnorspace_update(em);
+ BMLoopNorEditDataArray *lnors_ed_arr = BM_loop_normal_editdata_array_init(bm, false);
+
+ float(*smooth_normal)[3] = MEM_callocN(sizeof(*smooth_normal) * lnors_ed_arr->totloop,
+ __func__);
+
+ /* This is weird choice of operation, taking all loops of faces of current vertex.
+ * Could lead to some rather far away loops weighting as much as very close ones
+ * (topologically speaking), with complex polygons.
+ * Using topological distance here (rather than geometrical one)
+ * makes sense imho, but would rather go with a more consistent and flexible code,
+ * we could even add max topological distance to take into account, * and a weighting curve.
+ * Would do that later though, think for now we can live with that choice. --mont29. */
+ BMLoopNorEditData *lnor_ed = lnors_ed_arr->lnor_editdata;
+ for (int i = 0; i < lnors_ed_arr->totloop; i++, lnor_ed++) {
+ l = lnor_ed->loop;
+ float loop_normal[3];
+
+ BM_ITER_ELEM (f, &fiter, l->v, BM_FACES_OF_VERT) {
+ BMLoop *l_other;
+ BM_ITER_ELEM (l_other, &liter, f, BM_LOOPS_OF_FACE) {
+ const int l_index_other = BM_elem_index_get(l_other);
+ short *clnors = BM_ELEM_CD_GET_VOID_P(l_other, lnors_ed_arr->cd_custom_normal_offset);
+ BKE_lnor_space_custom_data_to_normal(
+ bm->lnor_spacearr->lspacearr[l_index_other], clnors, loop_normal);
+ add_v3_v3(smooth_normal[i], loop_normal);
+ }
}
}
- }
- const float factor = RNA_float_get(op->ptr, "factor");
+ const float factor = RNA_float_get(op->ptr, "factor");
- lnor_ed = lnors_ed_arr->lnor_editdata;
- for (int i = 0; i < lnors_ed_arr->totloop; i++, lnor_ed++) {
- float current_normal[3];
+ lnor_ed = lnors_ed_arr->lnor_editdata;
+ for (int i = 0; i < lnors_ed_arr->totloop; i++, lnor_ed++) {
+ float current_normal[3];
- if (normalize_v3(smooth_normal[i]) < CLNORS_VALID_VEC_LEN) {
- /* Skip in case smoothen normal is invalid... */
- continue;
- }
+ if (normalize_v3(smooth_normal[i]) < CLNORS_VALID_VEC_LEN) {
+ /* Skip in case smoothen normal is invalid... */
+ continue;
+ }
- BKE_lnor_space_custom_data_to_normal(
- bm->lnor_spacearr->lspacearr[lnor_ed->loop_index], lnor_ed->clnors_data, current_normal);
+ BKE_lnor_space_custom_data_to_normal(
+ bm->lnor_spacearr->lspacearr[lnor_ed->loop_index], lnor_ed->clnors_data, current_normal);
- /* Note: again, this is not true spherical interpolation that normals would need...
- * But it's probably good enough for now. */
- mul_v3_fl(current_normal, 1.0f - factor);
- mul_v3_fl(smooth_normal[i], factor);
- add_v3_v3(current_normal, smooth_normal[i]);
+ /* Note: again, this is not true spherical interpolation that normals would need...
+ * But it's probably good enough for now. */
+ mul_v3_fl(current_normal, 1.0f - factor);
+ mul_v3_fl(smooth_normal[i], factor);
+ add_v3_v3(current_normal, smooth_normal[i]);
- if (normalize_v3(current_normal) < CLNORS_VALID_VEC_LEN) {
- /* Skip in case smoothen normal is invalid... */
- continue;
- }
+ if (normalize_v3(current_normal) < CLNORS_VALID_VEC_LEN) {
+ /* Skip in case smoothen normal is invalid... */
+ continue;
+ }
- BKE_lnor_space_custom_normal_to_data(
- bm->lnor_spacearr->lspacearr[lnor_ed->loop_index], current_normal, lnor_ed->clnors_data);
- }
+ BKE_lnor_space_custom_normal_to_data(
+ bm->lnor_spacearr->lspacearr[lnor_ed->loop_index], current_normal, lnor_ed->clnors_data);
+ }
- BM_loop_normal_editdata_array_free(lnors_ed_arr);
- MEM_freeN(smooth_normal);
+ BM_loop_normal_editdata_array_free(lnors_ed_arr);
+ MEM_freeN(smooth_normal);
- EDBM_update_generic(em, true, false);
+ EDBM_update_generic(em, true, false);
+ }
+ MEM_freeN(objects);
return OPERATOR_FINISHED;
}
@@ -8968,50 +9016,59 @@ void MESH_OT_smoothen_normals(struct wmOperatorType *ot)
static int edbm_mod_weighted_strength_exec(bContext *C, wmOperator *op)
{
- Object *obedit = CTX_data_edit_object(C);
- BMEditMesh *em = BKE_editmesh_from_object(obedit);
- BMesh *bm = em->bm;
- BMFace *f;
- BMIter fiter;
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ uint objects_len = 0;
+ Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(
+ view_layer, CTX_wm_view3d(C), &objects_len);
- BM_select_history_clear(bm);
+ for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
+ Object *obedit = objects[ob_index];
+ BMEditMesh *em = BKE_editmesh_from_object(obedit);
+ BMesh *bm = em->bm;
+ BMFace *f;
+ BMIter fiter;
+ const int face_strength = RNA_enum_get(op->ptr, "face_strength");
+ const bool set = RNA_boolean_get(op->ptr, "set");
- const char *layer_id = MOD_WEIGHTEDNORMALS_FACEWEIGHT_CDLAYER_ID;
- int cd_prop_int_index = CustomData_get_named_layer_index(&bm->pdata, CD_PROP_INT, layer_id);
- if (cd_prop_int_index == -1) {
- BM_data_layer_add_named(bm, &bm->pdata, CD_PROP_INT, layer_id);
- cd_prop_int_index = CustomData_get_named_layer_index(&bm->pdata, CD_PROP_INT, layer_id);
- }
- cd_prop_int_index -= CustomData_get_layer_index(&bm->pdata, CD_PROP_INT);
- const int cd_prop_int_offset = CustomData_get_n_offset(
- &bm->pdata, CD_PROP_INT, cd_prop_int_index);
+ BM_select_history_clear(bm);
- const int face_strength = RNA_enum_get(op->ptr, "face_strength");
- const bool set = RNA_boolean_get(op->ptr, "set");
- BM_mesh_elem_index_ensure(bm, BM_FACE);
+ const char *layer_id = MOD_WEIGHTEDNORMALS_FACEWEIGHT_CDLAYER_ID;
+ int cd_prop_int_index = CustomData_get_named_layer_index(&bm->pdata, CD_PROP_INT, layer_id);
+ if (cd_prop_int_index == -1) {
+ BM_data_layer_add_named(bm, &bm->pdata, CD_PROP_INT, layer_id);
+ cd_prop_int_index = CustomData_get_named_layer_index(&bm->pdata, CD_PROP_INT, layer_id);
+ }
+ cd_prop_int_index -= CustomData_get_layer_index(&bm->pdata, CD_PROP_INT);
+ const int cd_prop_int_offset = CustomData_get_n_offset(
+ &bm->pdata, CD_PROP_INT, cd_prop_int_index);
- if (set) {
- BM_ITER_MESH (f, &fiter, bm, BM_FACES_OF_MESH) {
- if (BM_elem_flag_test(f, BM_ELEM_SELECT)) {
- int *strength = BM_ELEM_CD_GET_VOID_P(f, cd_prop_int_offset);
- *strength = face_strength;
+ BM_mesh_elem_index_ensure(bm, BM_FACE);
+
+ if (set) {
+ BM_ITER_MESH (f, &fiter, bm, BM_FACES_OF_MESH) {
+ if (BM_elem_flag_test(f, BM_ELEM_SELECT)) {
+ int *strength = BM_ELEM_CD_GET_VOID_P(f, cd_prop_int_offset);
+ *strength = face_strength;
+ }
}
}
- }
- else {
- BM_ITER_MESH (f, &fiter, bm, BM_FACES_OF_MESH) {
- int *strength = BM_ELEM_CD_GET_VOID_P(f, cd_prop_int_offset);
- if (*strength == face_strength) {
- BM_face_select_set(bm, f, true);
- BM_select_history_store(bm, f);
- }
- else {
- BM_face_select_set(bm, f, false);
+ else {
+ BM_ITER_MESH (f, &fiter, bm, BM_FACES_OF_MESH) {
+ int *strength = BM_ELEM_CD_GET_VOID_P(f, cd_prop_int_offset);
+ if (*strength == face_strength) {
+ BM_face_select_set(bm, f, true);
+ BM_select_history_store(bm, f);
+ }
+ else {
+ BM_face_select_set(bm, f, false);
+ }
}
}
+
+ EDBM_update_generic(em, false, false);
}
- EDBM_update_generic(em, false, false);
+ MEM_freeN(objects);
return OPERATOR_FINISHED;
}
diff --git a/source/blender/editors/mesh/editmesh_undo.c b/source/blender/editors/mesh/editmesh_undo.c
index 28b14b0060d..e823fb46140 100644
--- a/source/blender/editors/mesh/editmesh_undo.c
+++ b/source/blender/editors/mesh/editmesh_undo.c
@@ -741,7 +741,8 @@ static bool mesh_undosys_step_encode(struct bContext *C,
static void mesh_undosys_step_decode(struct bContext *C,
struct Main *UNUSED(bmain),
UndoStep *us_p,
- int UNUSED(dir))
+ int UNUSED(dir),
+ bool UNUSED(is_final))
{
MeshUndoStep *us = (MeshUndoStep *)us_p;
diff --git a/source/blender/editors/mesh/mesh_data.c b/source/blender/editors/mesh/mesh_data.c
index a6934326d68..ee8de9d8ea9 100644
--- a/source/blender/editors/mesh/mesh_data.c
+++ b/source/blender/editors/mesh/mesh_data.c
@@ -41,6 +41,7 @@
#include "DEG_depsgraph.h"
+#include "RNA_access.h"
#include "RNA_define.h"
#include "WM_api.h"
@@ -629,8 +630,7 @@ void MESH_OT_vertex_color_remove(wmOperatorType *ot)
static int mesh_customdata_clear_exec__internal(bContext *C, char htype, int type)
{
- Object *obedit = ED_object_context(C);
- Mesh *me = obedit->data;
+ Mesh *me = ED_mesh_context(C);
int tot;
CustomData *data = mesh_customdata_get_type(me, htype, &tot);
@@ -788,8 +788,7 @@ void MESH_OT_customdata_skin_clear(wmOperatorType *ot)
/* Clear custom loop normals */
static int mesh_customdata_custom_splitnormals_add_exec(bContext *C, wmOperator *UNUSED(op))
{
- Object *ob = ED_object_context(C);
- Mesh *me = ob->data;
+ Mesh *me = ED_mesh_context(C);
if (!BKE_mesh_has_custom_loop_normals(me)) {
CustomData *data = GET_CD_DATA(me, ldata);
@@ -853,7 +852,7 @@ void MESH_OT_customdata_custom_splitnormals_add(wmOperatorType *ot)
/* api callbacks */
ot->exec = mesh_customdata_custom_splitnormals_add_exec;
- ot->poll = ED_operator_object_active_editable_mesh;
+ ot->poll = ED_operator_editable_mesh;
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
@@ -861,8 +860,7 @@ void MESH_OT_customdata_custom_splitnormals_add(wmOperatorType *ot)
static int mesh_customdata_custom_splitnormals_clear_exec(bContext *C, wmOperator *UNUSED(op))
{
- Object *ob = ED_object_context(C);
- Mesh *me = ob->data;
+ Mesh *me = ED_mesh_context(C);
if (BKE_mesh_has_custom_loop_normals(me)) {
return mesh_customdata_clear_exec__internal(C, BM_LOOP, CD_CUSTOMLOOPNORMAL);
@@ -879,7 +877,7 @@ void MESH_OT_customdata_custom_splitnormals_clear(wmOperatorType *ot)
/* api callbacks */
ot->exec = mesh_customdata_custom_splitnormals_clear_exec;
- ot->poll = ED_operator_object_active_editable_mesh;
+ ot->poll = ED_operator_editable_mesh;
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
@@ -1289,3 +1287,23 @@ void ED_mesh_report_mirror(wmOperator *op, int totmirr, int totfail)
{
ED_mesh_report_mirror_ex(op, totmirr, totfail, SCE_SELECT_VERTEX);
}
+
+Mesh *ED_mesh_context(struct bContext *C)
+{
+ Mesh *mesh = CTX_data_pointer_get_type(C, "mesh", &RNA_Mesh).data;
+ if (mesh != NULL) {
+ return mesh;
+ }
+
+ Object *ob = ED_object_active_context(C);
+ if (ob == NULL) {
+ return NULL;
+ }
+
+ ID *data = (ID *)ob->data;
+ if (data == NULL || GS(data->name) != ID_ME) {
+ return NULL;
+ }
+
+ return (Mesh *)data;
+}
diff --git a/source/blender/editors/metaball/editmball_undo.c b/source/blender/editors/metaball/editmball_undo.c
index d255fac26ad..9a95560ccdd 100644
--- a/source/blender/editors/metaball/editmball_undo.c
+++ b/source/blender/editors/metaball/editmball_undo.c
@@ -185,7 +185,8 @@ static bool mball_undosys_step_encode(struct bContext *C,
static void mball_undosys_step_decode(struct bContext *C,
struct Main *UNUSED(bmain),
UndoStep *us_p,
- int UNUSED(dir))
+ int UNUSED(dir),
+ bool UNUSED(is_final))
{
MBallUndoStep *us = (MBallUndoStep *)us_p;
diff --git a/source/blender/editors/object/object_add.c b/source/blender/editors/object/object_add.c
index 0fdb1cec16f..f8cf55933aa 100644
--- a/source/blender/editors/object/object_add.c
+++ b/source/blender/editors/object/object_add.c
@@ -1658,54 +1658,80 @@ static void copy_object_set_idnew(bContext *C)
/** \name Make Instanced Objects Real Operator
* \{ */
+/* XXX TODO That whole hierarchy handling based on persistent_id tricks is
+ * very confusing and convoluted, and it will fail in many cases besides basic ones.
+ * Think this should be replaced by a proper tree-like representation of the instantiations,
+ * should help a lot in both readability, and precise consistent rebuilding of hierarchy.
+ */
+
/**
- * \note regarding hashing dupli-objects when using OB_DUPLICOLLECTION,
+ * \note regarding hashing dupli-objects which come from OB_DUPLICOLLECTION,
* skip the first member of #DupliObject.persistent_id
* since its a unique index and we only want to know if the group objects are from the same
* dupli-group instance.
+ *
+ * \note regarding hashing dupli-objects which come from non-OB_DUPLICOLLECTION,
+ * include the first member of #DupliObject.persistent_id
+ * since its the index of the vertex/face the object is instantiated on and we want to identify
+ * objects on the same vertex/face.
+ * In other words, we consider each group of objects from a same item as being
+ * the 'local group' where to check for parents.
*/
-static unsigned int dupliobject_group_hash(const void *ptr)
+static unsigned int dupliobject_hash(const void *ptr)
{
const DupliObject *dob = ptr;
unsigned int hash = BLI_ghashutil_ptrhash(dob->ob);
- unsigned int i;
- for (i = 1; (i < MAX_DUPLI_RECUR) && dob->persistent_id[i] != INT_MAX; i++) {
- hash ^= (dob->persistent_id[i] ^ i);
+
+ if (dob->type == OB_DUPLICOLLECTION) {
+ for (int i = 1; (i < MAX_DUPLI_RECUR) && dob->persistent_id[i] != INT_MAX; i++) {
+ hash ^= (dob->persistent_id[i] ^ i);
+ }
+ }
+ else {
+ hash ^= (dob->persistent_id[0] ^ 0);
}
return hash;
}
/**
- * \note regarding hashing dupli-objects when NOT using OB_DUPLICOLLECTION,
- * include the first member of #DupliObject.persistent_id
- * since its the index of the vertex/face the object is instantiated on and we want to identify
- * objects on the same vertex/face.
+ * \note regarding hashing dupli-objects when using OB_DUPLICOLLECTION,
+ * skip the first member of #DupliObject.persistent_id
+ * since its a unique index and we only want to know if the group objects are from the same
+ * dupli-group instance.
*/
-static unsigned int dupliobject_hash(const void *ptr)
+static unsigned int dupliobject_instancer_hash(const void *ptr)
{
const DupliObject *dob = ptr;
- unsigned int hash = BLI_ghashutil_ptrhash(dob->ob);
- hash ^= (dob->persistent_id[0] ^ 0);
+ unsigned int hash = BLI_ghashutil_inthash(dob->persistent_id[0]);
+ for (int i = 1; (i < MAX_DUPLI_RECUR) && dob->persistent_id[i] != INT_MAX; i++) {
+ hash ^= (dob->persistent_id[i] ^ i);
+ }
return hash;
}
-/* Compare function that matches dupliobject_group_hash */
-static bool dupliobject_group_cmp(const void *a_, const void *b_)
+/* Compare function that matches dupliobject_hash */
+static bool dupliobject_cmp(const void *a_, const void *b_)
{
const DupliObject *a = a_;
const DupliObject *b = b_;
- unsigned int i;
if (a->ob != b->ob) {
return true;
}
- for (i = 1; (i < MAX_DUPLI_RECUR); i++) {
- if (a->persistent_id[i] != b->persistent_id[i]) {
- return true;
+ if (ELEM(a->type, b->type, OB_DUPLICOLLECTION)) {
+ for (int i = 1; (i < MAX_DUPLI_RECUR); i++) {
+ if (a->persistent_id[i] != b->persistent_id[i]) {
+ return true;
+ }
+ else if (a->persistent_id[i] == INT_MAX) {
+ break;
+ }
}
- else if (a->persistent_id[i] == INT_MAX) {
- break;
+ }
+ else {
+ if (a->persistent_id[0] != b->persistent_id[0]) {
+ return true;
}
}
@@ -1713,18 +1739,19 @@ static bool dupliobject_group_cmp(const void *a_, const void *b_)
return false;
}
-/* Compare function that matches dupliobject_hash */
-static bool dupliobject_cmp(const void *a_, const void *b_)
+/* Compare function that matches dupliobject_instancer_hash. */
+static bool dupliobject_instancer_cmp(const void *a_, const void *b_)
{
const DupliObject *a = a_;
const DupliObject *b = b_;
- if (a->ob != b->ob) {
- return true;
- }
-
- if (a->persistent_id[0] != b->persistent_id[0]) {
- return true;
+ for (int i = 0; (i < MAX_DUPLI_RECUR); i++) {
+ if (a->persistent_id[i] != b->persistent_id[i]) {
+ return true;
+ }
+ else if (a->persistent_id[i] == INT_MAX) {
+ break;
+ }
}
/* matching */
@@ -1739,7 +1766,7 @@ static void make_object_duplilist_real(
Depsgraph *depsgraph = CTX_data_depsgraph(C);
ListBase *lb_duplis;
DupliObject *dob;
- GHash *dupli_gh, *parent_gh = NULL;
+ GHash *dupli_gh, *parent_gh = NULL, *instancer_gh = NULL;
if (!(base->object->transflag & OB_DUPLI)) {
return;
@@ -1750,11 +1777,11 @@ static void make_object_duplilist_real(
dupli_gh = BLI_ghash_ptr_new(__func__);
if (use_hierarchy) {
- if (base->object->transflag & OB_DUPLICOLLECTION) {
- parent_gh = BLI_ghash_new(dupliobject_group_hash, dupliobject_group_cmp, __func__);
- }
- else {
- parent_gh = BLI_ghash_new(dupliobject_hash, dupliobject_cmp, __func__);
+ parent_gh = BLI_ghash_new(dupliobject_hash, dupliobject_cmp, __func__);
+
+ if (use_base_parent) {
+ instancer_gh = BLI_ghash_new(
+ dupliobject_instancer_hash, dupliobject_instancer_cmp, __func__);
}
}
@@ -1788,7 +1815,12 @@ static void make_object_duplilist_real(
ob_dst->parent = NULL;
BKE_constraints_free(&ob_dst->constraints);
ob_dst->runtime.curve_cache = NULL;
+ const bool is_dupli_instancer = (ob_dst->transflag & OB_DUPLI) != 0;
ob_dst->transflag &= ~OB_DUPLI;
+ /* Remove instantiated collection, it's annoying to keep it here
+ * (and get potentially a lot of usages of it then...). */
+ id_us_min((ID *)ob_dst->instance_collection);
+ ob_dst->instance_collection = NULL;
copy_m4_m4(ob_dst->obmat, dob->mat);
BKE_object_apply_mat4(ob_dst, ob_dst->obmat, false, false);
@@ -1802,6 +1834,13 @@ static void make_object_duplilist_real(
if (!BLI_ghash_ensure_p(parent_gh, dob, &val)) {
*val = ob_dst;
}
+
+ if (is_dupli_instancer && instancer_gh) {
+ /* Same as above, we may have several 'hits'. */
+ if (!BLI_ghash_ensure_p(instancer_gh, dob, &val)) {
+ *val = ob_dst;
+ }
+ }
}
}
@@ -1825,7 +1864,8 @@ static void make_object_duplilist_real(
* they won't be read, this is simply for a hash lookup. */
DupliObject dob_key;
dob_key.ob = ob_src_par;
- if (base->object->transflag & OB_DUPLICOLLECTION) {
+ dob_key.type = dob->type;
+ if (dob->type == OB_DUPLICOLLECTION) {
memcpy(&dob_key.persistent_id[1],
&dob->persistent_id[1],
sizeof(dob->persistent_id[1]) * (MAX_DUPLI_RECUR - 1));
@@ -1848,15 +1888,30 @@ static void make_object_duplilist_real(
ob_dst->parent = ob_dst_par;
}
- else if (use_base_parent) {
- ob_dst->parent = base->object;
- ob_dst->partype = PAROBJECT;
- }
}
- else if (use_base_parent) {
- /* since we are ignoring the internal hierarchy - parent all to the
- * base object */
- ob_dst->parent = base->object;
+ if (use_base_parent && ob_dst->parent == NULL) {
+ Object *ob_dst_par = NULL;
+
+ if (instancer_gh != NULL) {
+ /* OK to keep most of the members uninitialized,
+ * they won't be read, this is simply for a hash lookup. */
+ DupliObject dob_key;
+ /* We are looking one step upper in hierarchy, so we need to 'shift' the persitent_id,
+ * ignoring the first item.
+ * We only check on persistent_id here, since we have no idea what object it might be. */
+ memcpy(&dob_key.persistent_id[0],
+ &dob->persistent_id[1],
+ sizeof(dob_key.persistent_id[0]) * (MAX_DUPLI_RECUR - 1));
+ ob_dst_par = BLI_ghash_lookup(instancer_gh, &dob_key);
+ }
+
+ if (ob_dst_par == NULL) {
+ /* Default to parenting to root object...
+ * Always the case when use_hierarchy is false. */
+ ob_dst_par = base->object;
+ }
+
+ ob_dst->parent = ob_dst_par;
ob_dst->partype = PAROBJECT;
}
@@ -1878,12 +1933,16 @@ static void make_object_duplilist_real(
DEG_id_tag_update(&ob->id, ID_RECALC_TRANSFORM);
}
}
+ base->object->instance_collection = NULL;
}
BLI_ghash_free(dupli_gh, NULL, NULL);
if (parent_gh) {
BLI_ghash_free(parent_gh, NULL, NULL);
}
+ if (instancer_gh) {
+ BLI_ghash_free(instancer_gh, NULL, NULL);
+ }
free_object_duplilist(lb_duplis);
@@ -1977,7 +2036,13 @@ static void curvetomesh(Main *bmain, Depsgraph *depsgraph, Object *ob)
{
Object *object_eval = DEG_get_evaluated_object(depsgraph, ob);
Curve *curve = ob->data;
+
Mesh *mesh = BKE_mesh_new_from_object_to_bmain(bmain, depsgraph, object_eval, true);
+ if (mesh == NULL) {
+ /* Unable to convert the curve to a mesh. */
+ return;
+ }
+
BKE_object_free_modifiers(ob, 0);
/* Replace curve used by the object itself. */
ob->data = mesh;
@@ -2066,7 +2131,7 @@ static Base *duplibase_for_convert(
static int convert_exec(bContext *C, wmOperator *op)
{
Main *bmain = CTX_data_main(C);
- Depsgraph *depsgraph = CTX_data_depsgraph(C);
+ Depsgraph *depsgraph = CTX_data_evaluated_depsgraph(C);
Scene *scene = CTX_data_scene(C);
ViewLayer *view_layer = CTX_data_view_layer(C);
Base *basen = NULL, *basact = NULL;
@@ -2285,8 +2350,9 @@ static int convert_exec(bContext *C, wmOperator *op)
BKE_curve_curve_dimension_update(cu);
if (target == OB_MESH) {
+ /* No assumption should be made that the resulting objects is a mesh, as conversion can
+ * fail. */
curvetomesh(bmain, depsgraph, newob);
-
/* meshes doesn't use displist */
BKE_object_free_curve_cache(newob);
}
@@ -2309,8 +2375,9 @@ static int convert_exec(bContext *C, wmOperator *op)
newob = ob;
}
+ /* No assumption should be made that the resulting objects is a mesh, as conversion can
+ * fail. */
curvetomesh(bmain, depsgraph, newob);
-
/* meshes doesn't use displist */
BKE_object_free_curve_cache(newob);
}
@@ -2826,7 +2893,7 @@ void OBJECT_OT_join_shapes(wmOperatorType *ot)
{
/* identifiers */
ot->name = "Join as Shapes";
- ot->description = "Merge selected objects to shapes of active object";
+ ot->description = "Copy the current resulting shape of another selected object to this one";
ot->idname = "OBJECT_OT_join_shapes";
/* api callbacks */
diff --git a/source/blender/editors/object/object_bake_api.c b/source/blender/editors/object/object_bake_api.c
index 6164958bf2c..410ccccbd0d 100644
--- a/source/blender/editors/object/object_bake_api.c
+++ b/source/blender/editors/object/object_bake_api.c
@@ -707,7 +707,7 @@ static size_t initialize_internal_images(BakeImages *bake_images, ReportList *re
/* create new mesh with edit mode changes and modifiers applied */
static Mesh *bake_mesh_new_from_object(Object *object)
{
- Mesh *me = BKE_object_to_mesh(NULL, object, false);
+ Mesh *me = BKE_mesh_new_from_object(NULL, object, false);
if (me->flag & ME_AUTOSMOOTH) {
BKE_mesh_split_faces(me, true);
@@ -927,7 +927,7 @@ static int bake(Render *re,
}
}
else if (is_cage) {
- BKE_object_eval_reset(ob_low_eval);
+ bool is_changed = false;
ModifierData *md = ob_low_eval->modifiers.first;
while (md) {
@@ -942,11 +942,23 @@ static int bake(Render *re,
if (md->type == eModifierType_EdgeSplit) {
BLI_remlink(&ob_low_eval->modifiers, md);
modifier_free(md);
+ is_changed = true;
}
md = md_next;
}
- me_cage = BKE_object_to_mesh(NULL, ob_low_eval, false);
+ if (is_changed) {
+ /* Make sure object is evaluated with the new modifier settings.
+ *
+ * NOTE: Since the dependency graph was fully evaluated prior to bake, and we only made
+ * single modification to this object all the possible dependencies for evaluation are
+ * already up to date. This means we can do a cheap single object update
+ * (as an opposite of full depsgraph update). */
+ BKE_object_eval_reset(ob_low_eval);
+ BKE_object_handle_data_update(depsgraph, scene, ob_low_eval);
+ }
+
+ me_cage = BKE_mesh_new_from_object(NULL, ob_low_eval, false);
RE_bake_pixels_populate(me_cage, pixel_array_low, num_pixels, &bake_images, uv_layer);
}
@@ -965,7 +977,7 @@ static int bake(Render *re,
highpoly[i].ob_eval = DEG_get_evaluated_object(depsgraph, ob_iter);
highpoly[i].ob_eval->restrictflag &= ~OB_RESTRICT_RENDER;
highpoly[i].ob_eval->base_flag |= (BASE_VISIBLE | BASE_ENABLED_RENDER);
- highpoly[i].me = BKE_object_to_mesh(NULL, highpoly[i].ob_eval, false);
+ highpoly[i].me = BKE_mesh_new_from_object(NULL, highpoly[i].ob_eval, false);
/* lowpoly to highpoly transformation matrix */
copy_m4_m4(highpoly[i].obmat, highpoly[i].ob->obmat);
@@ -1088,7 +1100,7 @@ static int bake(Render *re,
}
/* Evaluate modifiers again. */
- me_nores = BKE_object_to_mesh(NULL, ob_low_eval, false);
+ me_nores = BKE_mesh_new_from_object(NULL, ob_low_eval, false);
RE_bake_pixels_populate(me_nores, pixel_array_low, num_pixels, &bake_images, uv_layer);
RE_bake_normal_world_to_tangent(pixel_array_low,
@@ -1098,7 +1110,7 @@ static int bake(Render *re,
me_nores,
normal_swizzle,
ob_low_eval->obmat);
- BKE_object_to_mesh_clear(ob_low_eval);
+ BKE_id_free(NULL, &me_nores->id);
if (md) {
md->mode = mode;
@@ -1221,8 +1233,8 @@ cleanup:
if (highpoly) {
int i;
for (i = 0; i < tot_highpoly; i++) {
- if (highpoly[i].ob_eval) {
- BKE_object_to_mesh_clear(highpoly[i].ob_eval);
+ if (highpoly[i].me != NULL) {
+ BKE_id_free(NULL, &highpoly[i].me->id);
}
}
MEM_freeN(highpoly);
@@ -1252,12 +1264,12 @@ cleanup:
MEM_freeN(result);
}
- if (ob_low_eval) {
- BKE_object_to_mesh_clear(ob_low_eval);
+ if (me_low != NULL) {
+ BKE_id_free(NULL, &me_low->id);
}
- if (ob_cage_eval) {
- BKE_object_to_mesh_clear(ob_cage_eval);
+ if (me_cage != NULL) {
+ BKE_id_free(NULL, &me_cage->id);
}
DEG_graph_free(depsgraph);
diff --git a/source/blender/editors/object/object_constraint.c b/source/blender/editors/object/object_constraint.c
index 53bc037c736..5ef133e87de 100644
--- a/source/blender/editors/object/object_constraint.c
+++ b/source/blender/editors/object/object_constraint.c
@@ -34,6 +34,7 @@
#include "BLT_translation.h"
#include "DNA_anim_types.h"
+#include "DNA_armature_types.h"
#include "DNA_constraint_types.h"
#include "DNA_curve_types.h"
#include "DNA_scene_types.h"
@@ -53,6 +54,7 @@
#include "DEG_depsgraph.h"
#include "DEG_depsgraph_build.h"
+#include "DEG_depsgraph_query.h"
#ifdef WITH_PYTHON
# include "BPY_extern.h"
@@ -861,94 +863,107 @@ void CONSTRAINT_OT_limitdistance_reset(wmOperatorType *ot)
/* ------------- Child-Of Constraint ------------------ */
-static void child_get_inverse_matrix(const bContext *C,
- Scene *scene,
- Object *ob,
- bConstraint *con,
- float invmat[4][4],
- const int owner)
+static void child_get_inverse_matrix_owner_bone(
+ const bContext *C, wmOperator *op, Scene *scene, Object *ob, float invmat[4][4])
{
+ /* For bone owner we want to do this in evaluated domain.
+ * BKE_pose_where_is / BKE_pose_where_is_bone relies on (re)evaluating parts of the scene
+ * and copying new evaluated stuff back to original.
+ */
Depsgraph *depsgraph = CTX_data_depsgraph(C);
+ Object *ob_eval = DEG_get_evaluated_object(depsgraph, ob);
+ bConstraint *con_eval = edit_constraint_property_get(op, ob_eval, CONSTRAINT_TYPE_CHILDOF);
/* nullify inverse matrix first */
unit_m4(invmat);
- if (owner == EDIT_CONSTRAINT_OWNER_BONE) {
- bPoseChannel *pchan;
- /* try to find a pose channel - assume that this is the constraint owner */
- /* TODO: get from context instead? */
- if (ob && ob->pose && (pchan = BKE_pose_channel_active(ob))) {
- bConstraint *con_last;
- /* calculate/set inverse matrix:
- * We just calculate all transform-stack eval up to but not including this constraint.
- * This is because inverse should just inverse correct for just the constraint's influence
- * when it gets applied; that is, at the time of application, we don't know anything about
- * what follows.
- */
- float imat[4][4], tmat[4][4];
- float pmat[4][4];
+ bPoseChannel *pchan_eval = BKE_pose_channel_active(ob_eval);
- /* make sure we passed the correct constraint */
- BLI_assert(BLI_findindex(&pchan->constraints, con) != -1);
+ /* try to find a pose channel - assume that this is the constraint owner */
+ /* TODO: get from context instead? */
+ if (ob_eval && ob_eval->pose && pchan_eval) {
+ bConstraint *con_last;
- /* 1. calculate posemat where inverse doesn't exist yet (inverse was cleared above),
- * to use as baseline ("pmat") to derive delta from. This extra calc saves users
- * from having pressing "Clear Inverse" first
- */
- BKE_pose_where_is(depsgraph, scene, ob);
- copy_m4_m4(pmat, pchan->pose_mat);
+ /* calculate/set inverse matrix:
+ * We just calculate all transform-stack eval up to but not including this constraint.
+ * This is because inverse should just inverse correct for just the constraint's influence
+ * when it gets applied; that is, at the time of application, we don't know anything about
+ * what follows.
+ */
+ float imat[4][4], tmat[4][4];
+ float pmat[4][4];
- /* 2. knock out constraints starting from this one */
- con_last = pchan->constraints.last;
- pchan->constraints.last = con->prev;
+ /* make sure we passed the correct constraint */
+ BLI_assert(BLI_findindex(&pchan_eval->constraints, con_eval) != -1);
- if (con->prev) {
- /* new end must not point to this one, else this chain cutting is useless */
- con->prev->next = NULL;
- }
- else {
- /* constraint was first */
- pchan->constraints.first = NULL;
- }
+ /* 1. calculate posemat where inverse doesn't exist yet (inverse was cleared above),
+ * to use as baseline ("pmat") to derive delta from. This extra calc saves users
+ * from having pressing "Clear Inverse" first
+ */
+ BKE_pose_where_is(depsgraph, scene, ob_eval);
+ copy_m4_m4(pmat, pchan_eval->pose_mat);
- /* 3. solve pose without disabled constraints */
- BKE_pose_where_is(depsgraph, scene, ob);
+ /* 2. knock out constraints starting from this one */
+ con_last = pchan_eval->constraints.last;
+ pchan_eval->constraints.last = con_eval->prev;
- /* 4. determine effect of constraint by removing the newly calculated
- * pchan->pose_mat from the original pchan->pose_mat, thus determining
- * the effect of the constraint
- */
- invert_m4_m4(imat, pchan->pose_mat);
- mul_m4_m4m4(tmat, pmat, imat);
- invert_m4_m4(invmat, tmat);
+ if (con_eval->prev) {
+ /* new end must not point to this one, else this chain cutting is useless */
+ con_eval->prev->next = NULL;
+ }
+ else {
+ /* constraint was first */
+ pchan_eval->constraints.first = NULL;
+ }
- /* 5. restore constraints */
- pchan->constraints.last = con_last;
+ /* 3. solve pose without disabled constraints */
+ BKE_pose_where_is(depsgraph, scene, ob_eval);
- if (con->prev) {
- /* hook up prev to this one again */
- con->prev->next = con;
- }
- else {
- /* set as first again */
- pchan->constraints.first = con;
- }
+ /* 4. determine effect of constraint by removing the newly calculated
+ * pchan->pose_mat from the original pchan->pose_mat, thus determining
+ * the effect of the constraint
+ */
+ invert_m4_m4(imat, pchan_eval->pose_mat);
+ mul_m4_m4m4(tmat, pmat, imat);
+ invert_m4_m4(invmat, tmat);
+
+ /* 5. restore constraints */
+ pchan_eval->constraints.last = con_last;
- /* 6. recalculate pose with new inv-mat applied */
- BKE_pose_where_is(depsgraph, scene, ob);
+ if (con_eval->prev) {
+ /* hook up prev to this one again */
+ con_eval->prev->next = con_eval;
}
+ else {
+ /* set as first again */
+ pchan_eval->constraints.first = con_eval;
+ }
+
+ /* 6. recalculate pose with new inv-mat applied */
+ /* this one is unnecessary? (DEG seems to update correctly without)
+ + if we leave this in, we have to click "Set Inverse" twice to see updates...
+ BKE_pose_where_is(depsgraph, scene, ob_eval); */
}
- if (owner == EDIT_CONSTRAINT_OWNER_OBJECT) {
- if (ob) {
- Object workob;
+}
- /* make sure we passed the correct constraint */
- BLI_assert(BLI_findindex(&ob->constraints, con) != -1);
+static void child_get_inverse_matrix_owner_object(
+ const bContext *C, Scene *scene, Object *ob, bConstraint *con, float invmat[4][4])
+{
+ Depsgraph *depsgraph = CTX_data_depsgraph(C);
- /* use BKE_object_workob_calc_parent to find inverse - just like for normal parenting */
- BKE_object_workob_calc_parent(depsgraph, scene, ob, &workob);
- invert_m4_m4(invmat, workob.obmat);
- }
+ /* nullify inverse matrix first */
+ unit_m4(invmat);
+
+ if (ob) {
+ Object workob;
+
+ /* make sure we passed the correct constraint */
+ BLI_assert(BLI_findindex(&ob->constraints, con) != -1);
+ UNUSED_VARS_NDEBUG(con);
+
+ /* use BKE_object_workob_calc_parent to find inverse - just like for normal parenting */
+ BKE_object_workob_calc_parent(depsgraph, scene, ob, &workob);
+ invert_m4_m4(invmat, workob.obmat);
}
}
@@ -969,7 +984,12 @@ static int childof_set_inverse_exec(bContext *C, wmOperator *op)
return OPERATOR_CANCELLED;
}
- child_get_inverse_matrix(C, scene, ob, con, data->invmat, owner);
+ if (owner == EDIT_CONSTRAINT_OWNER_OBJECT) {
+ child_get_inverse_matrix_owner_object(C, scene, ob, con, data->invmat);
+ }
+ else if (owner == EDIT_CONSTRAINT_OWNER_BONE) {
+ child_get_inverse_matrix_owner_bone(C, op, scene, ob, data->invmat);
+ }
ED_object_constraint_update(bmain, ob);
WM_event_add_notifier(C, NC_OBJECT | ND_CONSTRAINT, ob);
@@ -1203,6 +1223,7 @@ void CONSTRAINT_OT_followpath_path_animate(wmOperatorType *ot)
static int objectsolver_set_inverse_exec(bContext *C, wmOperator *op)
{
+ Main *bmain = CTX_data_main(C);
Scene *scene = CTX_data_scene(C);
Object *ob = ED_object_active_context(C);
bConstraint *con = edit_constraint_property_get(op, ob, CONSTRAINT_TYPE_OBJECTSOLVER);
@@ -1216,8 +1237,14 @@ static int objectsolver_set_inverse_exec(bContext *C, wmOperator *op)
return OPERATOR_CANCELLED;
}
- child_get_inverse_matrix(C, scene, ob, con, data->invmat, owner);
+ if (owner == EDIT_CONSTRAINT_OWNER_OBJECT) {
+ child_get_inverse_matrix_owner_object(C, scene, ob, con, data->invmat);
+ }
+ else if (owner == EDIT_CONSTRAINT_OWNER_BONE) {
+ child_get_inverse_matrix_owner_bone(C, op, scene, ob, data->invmat);
+ }
+ ED_object_constraint_update(bmain, ob);
WM_event_add_notifier(C, NC_OBJECT | ND_CONSTRAINT, ob);
return OPERATOR_FINISHED;
@@ -1789,10 +1816,15 @@ static bool get_new_constraint_target(
*/
if ((ob->type == OB_ARMATURE) && (ob->mode & OB_MODE_POSE) &&
(!only_curve && !only_mesh)) {
- /* just use the active bone, and assume that it is visible + usable */
- *tar_ob = ob;
- *tar_pchan = BKE_pose_channel_active(ob);
- found = true;
+
+ /* Only use the object & bone if the bone is visible & selected
+ * since we may have multiple objects in pose mode at once. */
+ bPoseChannel *pchan = BKE_pose_channel_active_or_first_selected(ob);
+ if (pchan != NULL) {
+ *tar_pchan = pchan;
+ *tar_ob = ob;
+ found = true;
+ }
break;
}
diff --git a/source/blender/editors/object/object_select.c b/source/blender/editors/object/object_select.c
index afdda8d6b7f..da06707ebac 100644
--- a/source/blender/editors/object/object_select.c
+++ b/source/blender/editors/object/object_select.c
@@ -119,18 +119,27 @@ void ED_object_base_select(Base *base, eObjectSelect_Mode mode)
}
/**
+ * Call when the active base has changed.
+ */
+void ED_object_base_active_refresh(Main *bmain, Scene *scene, ViewLayer *view_layer)
+{
+ WM_main_add_notifier(NC_SCENE | ND_OB_ACTIVE, scene);
+ DEG_id_tag_update(&scene->id, ID_RECALC_SELECT);
+ struct wmMsgBus *mbus = ((wmWindowManager *)bmain->wm.first)->message_bus;
+ if (mbus != NULL) {
+ WM_msg_publish_rna_prop(mbus, &scene->id, view_layer, LayerObjects, active);
+ }
+}
+
+/**
* Change active base, it includes the notifier
*/
void ED_object_base_activate(bContext *C, Base *base)
{
- struct wmMsgBus *mbus = CTX_wm_message_bus(C);
Scene *scene = CTX_data_scene(C);
ViewLayer *view_layer = CTX_data_view_layer(C);
view_layer->basact = base;
-
- WM_event_add_notifier(C, NC_SCENE | ND_OB_ACTIVE, scene);
- WM_msg_publish_rna_prop(mbus, &scene->id, view_layer, LayerObjects, active);
- DEG_id_tag_update(&CTX_data_scene(C)->id, ID_RECALC_SELECT);
+ ED_object_base_active_refresh(CTX_data_main(C), scene, view_layer);
}
bool ED_object_base_deselect_all_ex(ViewLayer *view_layer,
diff --git a/source/blender/editors/object/object_transform.c b/source/blender/editors/object/object_transform.c
index 394fea2cf27..9c98fdc2a2e 100644
--- a/source/blender/editors/object/object_transform.c
+++ b/source/blender/editors/object/object_transform.c
@@ -466,6 +466,8 @@ static void ignore_parent_tx(Main *bmain, Depsgraph *depsgraph, Scene *scene, Ob
Object workob;
Object *ob_child;
+ Scene *scene_eval = DEG_get_evaluated_scene(depsgraph);
+
/* a change was made, adjust the children to compensate */
for (ob_child = bmain->objects.first; ob_child; ob_child = ob_child->id.next) {
if (ob_child->parent == ob) {
@@ -475,6 +477,14 @@ static void ignore_parent_tx(Main *bmain, Depsgraph *depsgraph, Scene *scene, Ob
invert_m4_m4(ob_child->parentinv, workob.obmat);
/* Copy result of BKE_object_apply_mat4(). */
BKE_object_transform_copy(ob_child, ob_child_eval);
+ /* Make sure evaluated object is in a consistent state with the original one.
+ * It might be needed for applying transform on its children. */
+ copy_m4_m4(ob_child_eval->parentinv, ob_child->parentinv);
+ BKE_object_eval_transform_all(depsgraph, scene_eval, ob_child_eval);
+ /* Tag for update.
+ * This is because parent matrix did change, so in theory the child object might now be
+ * evaluated to a different location in another editing context. */
+ DEG_id_tag_update(&ob_child->id, ID_RECALC_TRANSFORM);
}
}
}
@@ -537,7 +547,7 @@ static int apply_objects_internal(bContext *C,
{
Main *bmain = CTX_data_main(C);
Scene *scene = CTX_data_scene(C);
- Depsgraph *depsgraph = CTX_data_depsgraph(C);
+ Depsgraph *depsgraph = CTX_data_evaluated_depsgraph(C);
float rsmat[3][3], obmat[3][3], iobmat[3][3], mat[4][4], scale;
bool changed = true;
@@ -965,7 +975,7 @@ static int object_origin_set_exec(bContext *C, wmOperator *op)
Scene *scene = CTX_data_scene(C);
Object *obact = CTX_data_active_object(C);
Object *obedit = CTX_data_edit_object(C);
- Depsgraph *depsgraph = CTX_data_depsgraph(C);
+ Depsgraph *depsgraph = CTX_data_evaluated_depsgraph(C);
Object *tob;
float cent[3], cent_neg[3], centn[3];
const float *cursor = scene->cursor.location;
@@ -1052,7 +1062,7 @@ static int object_origin_set_exec(bContext *C, wmOperator *op)
/* move active first */
if (ob == obact) {
- memmove(&objects[1], objects, object_index);
+ memmove(&objects[1], objects, object_index * sizeof(Object *));
objects[0] = ob;
}
}
@@ -1217,8 +1227,10 @@ static int object_origin_set_exec(bContext *C, wmOperator *op)
arm->id.tag |= LIB_TAG_DOIT;
/* do_inverse_offset = true; */ /* docenter_armature() handles this */
- BKE_object_where_is_calc(depsgraph, scene, ob);
- BKE_pose_where_is(depsgraph, scene, ob); /* needed for bone parents */
+ Object *ob_eval = DEG_get_evaluated_object(depsgraph, ob);
+ BKE_object_transform_copy(ob_eval, ob);
+ BKE_object_where_is_calc(depsgraph, scene, ob_eval);
+ BKE_pose_where_is(depsgraph, scene, ob_eval); /* needed for bone parents */
ignore_parent_tx(bmain, depsgraph, scene, ob);
@@ -1353,9 +1365,12 @@ static int object_origin_set_exec(bContext *C, wmOperator *op)
add_v3_v3(ob->loc, centn);
- BKE_object_where_is_calc(depsgraph, scene, ob);
+ Object *ob_eval = DEG_get_evaluated_object(depsgraph, ob);
+ BKE_object_transform_copy(ob_eval, ob);
+ BKE_object_where_is_calc(depsgraph, scene, ob_eval);
if (ob->type == OB_ARMATURE) {
- BKE_pose_where_is(depsgraph, scene, ob); /* needed for bone parents */
+ /* needed for bone parents */
+ BKE_pose_where_is(depsgraph, scene, ob_eval);
}
ignore_parent_tx(bmain, depsgraph, scene, ob);
@@ -1378,10 +1393,12 @@ static int object_origin_set_exec(bContext *C, wmOperator *op)
mul_v3_mat3_m4v3(centn, ob_other->obmat, cent); /* omit translation part */
add_v3_v3(ob_other->loc, centn);
- BKE_object_where_is_calc(depsgraph, scene, ob_other);
+ Object *ob_other_eval = DEG_get_evaluated_object(depsgraph, ob_other);
+ BKE_object_transform_copy(ob_other_eval, ob_other);
+ BKE_object_where_is_calc(depsgraph, scene, ob_other_eval);
if (ob_other->type == OB_ARMATURE) {
/* needed for bone parents */
- BKE_pose_where_is(depsgraph, scene, ob_other);
+ BKE_pose_where_is(depsgraph, scene, ob_other_eval);
}
ignore_parent_tx(bmain, depsgraph, scene, ob_other);
}
@@ -1490,7 +1507,7 @@ void OBJECT_OT_origin_set(wmOperatorType *ot)
/* -------------------------------------------------------------------- */
/** \name Transform Axis Target
*
- * Note this is an experemental operator to point lights/cameras at objects.
+ * Note this is an experimental operator to point lights/cameras at objects.
* We may re-work how this behaves based on user feedback.
* - campbell.
* \{ */
diff --git a/source/blender/editors/object/object_vgroup.c b/source/blender/editors/object/object_vgroup.c
index 678f6f50096..4f61443ac54 100644
--- a/source/blender/editors/object/object_vgroup.c
+++ b/source/blender/editors/object/object_vgroup.c
@@ -3278,9 +3278,18 @@ static int vertex_group_smooth_exec(bContext *C, wmOperator *op)
ViewLayer *view_layer = CTX_data_view_layer(C);
Object *ob_ctx = ED_object_context(C);
- uint objects_len = 0;
- Object **objects = BKE_view_layer_array_from_objects_in_mode_unique_data(
- view_layer, CTX_wm_view3d(C), &objects_len, ob_ctx->mode);
+ uint objects_len;
+ Object **objects;
+ if (ob_ctx->mode == OB_MODE_WEIGHT_PAINT) {
+ /* Until weight paint supports multi-edit, use only the active. */
+ objects_len = 1;
+ objects = &ob_ctx;
+ }
+ else {
+ objects = BKE_view_layer_array_from_objects_in_mode_unique_data(
+ view_layer, CTX_wm_view3d(C), &objects_len, ob_ctx->mode);
+ }
+
for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
Object *ob = objects[ob_index];
@@ -3296,7 +3305,9 @@ static int vertex_group_smooth_exec(bContext *C, wmOperator *op)
WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
WM_event_add_notifier(C, NC_GEOM | ND_DATA, ob->data);
}
- MEM_freeN(objects);
+ if (objects != &ob_ctx) {
+ MEM_freeN(objects);
+ }
return OPERATOR_FINISHED;
}
diff --git a/source/blender/editors/physics/particle_edit.c b/source/blender/editors/physics/particle_edit.c
index dc634865a0a..4e6022cf18c 100644
--- a/source/blender/editors/physics/particle_edit.c
+++ b/source/blender/editors/physics/particle_edit.c
@@ -97,23 +97,38 @@ bool PE_poll(bContext *C)
Object *ob = CTX_data_active_object(C);
if (!scene || !ob || !(ob->mode & OB_MODE_PARTICLE_EDIT)) {
- return 0;
+ return false;
+ }
+
+ PTCacheEdit *edit = PE_get_current(scene, ob);
+ if (edit == NULL) {
+ return false;
}
- return (PE_get_current(scene, ob) != NULL);
+ if (edit->psmd_eval == NULL || edit->psmd_eval->mesh_final == NULL) {
+ return false;
+ }
+
+ return true;
}
bool PE_hair_poll(bContext *C)
{
Scene *scene = CTX_data_scene(C);
Object *ob = CTX_data_active_object(C);
- PTCacheEdit *edit;
if (!scene || !ob || !(ob->mode & OB_MODE_PARTICLE_EDIT)) {
- return 0;
+ return false;
}
- edit = PE_get_current(scene, ob);
- return (edit && edit->psys);
+ PTCacheEdit *edit = PE_get_current(scene, ob);
+ if (edit == NULL || edit->psys == NULL) {
+ return false;
+ }
+ if (edit->psmd_eval == NULL || edit->psmd_eval->mesh_final == NULL) {
+ return false;
+ }
+
+ return true;
}
bool PE_poll_view3d(bContext *C)
@@ -322,10 +337,13 @@ static PTCacheEdit *pe_get_current(Depsgraph *depsgraph, Scene *scene, Object *o
}
}
- if (edit) {
+ /* Don't consider inactive or render dependency graphs, since they might be evaluated for a
+ * different number of childrem. or have different pointer to evaluated particle system or
+ * modifier which will also cause troubles. */
+ if (edit && DEG_is_active(depsgraph)) {
edit->pid = *pid;
if (edit->flags & PT_CACHE_EDIT_UPDATE_PARTICLE_FROM_EVAL) {
- if (edit->psys != NULL) {
+ if (edit->psys != NULL && edit->psys_eval != NULL) {
psys_copy_particles(edit->psys, edit->psys_eval);
pe_update_hair_particle_edit_pointers(edit);
}
@@ -1085,7 +1103,7 @@ static void PE_apply_mirror(Object *ob, ParticleSystem *psys)
edit = psys->edit;
psmd_eval = edit->psmd_eval;
- if (!psmd_eval->mesh_final) {
+ if (psmd_eval == NULL || psmd_eval->mesh_final == NULL) {
return;
}
@@ -1217,7 +1235,7 @@ static void pe_deflect_emitter(Scene *scene, Object *ob, PTCacheEdit *edit)
psys = edit->psys;
- if (!edit->psmd_eval->mesh_final) {
+ if (edit->psmd_eval == NULL || edit->psmd_eval->mesh_final == NULL) {
return;
}
@@ -1489,7 +1507,7 @@ void update_world_cos(Depsgraph *UNUSED(depsgraph), Object *ob, PTCacheEdit *edi
KEY_K;
float hairmat[4][4];
- if (psys == 0 || psys->edit == 0 || psmd_eval->mesh_final == NULL) {
+ if (psys == 0 || psys->edit == 0 || psmd_eval == NULL || psmd_eval->mesh_final == NULL) {
return;
}
diff --git a/source/blender/editors/physics/particle_edit_undo.c b/source/blender/editors/physics/particle_edit_undo.c
index be625eb939f..40d90676487 100644
--- a/source/blender/editors/physics/particle_edit_undo.c
+++ b/source/blender/editors/physics/particle_edit_undo.c
@@ -252,7 +252,8 @@ static bool particle_undosys_step_encode(struct bContext *C,
static void particle_undosys_step_decode(struct bContext *C,
struct Main *UNUSED(bmain),
UndoStep *us_p,
- int UNUSED(dir))
+ int UNUSED(dir),
+ bool UNUSED(is_final))
{
/* TODO(campbell): undo_system: use low-level API to set mode. */
ED_object_mode_set(C, OB_MODE_PARTICLE_EDIT);
diff --git a/source/blender/editors/physics/physics_fluid.c b/source/blender/editors/physics/physics_fluid.c
index dc4ce138d9d..dc3673c972f 100644
--- a/source/blender/editors/physics/physics_fluid.c
+++ b/source/blender/editors/physics/physics_fluid.c
@@ -46,6 +46,7 @@
#include "DEG_depsgraph.h"
#include "ED_screen.h"
+#include "ED_object.h"
#include "WM_types.h"
#include "WM_api.h"
@@ -1216,7 +1217,7 @@ static int fluid_bake_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(
return OPERATOR_CANCELLED;
}
- if (!fluidsimBake(C, op->reports, CTX_data_active_object(C), true)) {
+ if (!fluidsimBake(C, op->reports, ED_object_context(C), true)) {
return OPERATOR_CANCELLED;
}
diff --git a/source/blender/editors/render/render_internal.c b/source/blender/editors/render/render_internal.c
index 352593a15ad..9ac93f07300 100644
--- a/source/blender/editors/render/render_internal.c
+++ b/source/blender/editors/render/render_internal.c
@@ -914,7 +914,6 @@ static int screen_render_invoke(bContext *C, wmOperator *op, const wmEvent *even
wmJob *wm_job;
RenderJob *rj;
Image *ima;
- int jobflag;
const bool is_animation = RNA_boolean_get(op->ptr, "animation");
const bool is_write_still = RNA_boolean_get(op->ptr, "write_still");
const bool use_viewport = RNA_boolean_get(op->ptr, "use_viewport");
@@ -973,12 +972,6 @@ static int screen_render_invoke(bContext *C, wmOperator *op, const wmEvent *even
/* ensure at least 1 area shows result */
sa = render_view_open(C, event->x, event->y, op->reports);
- jobflag = WM_JOB_EXCL_RENDER | WM_JOB_PRIORITY | WM_JOB_PROGRESS;
-
- if (RNA_struct_property_is_set(op->ptr, "layer")) {
- jobflag |= WM_JOB_SUSPEND;
- }
-
/* job custom data */
rj = MEM_callocN(sizeof(RenderJob), "render job");
rj->main = bmain;
@@ -1038,12 +1031,20 @@ static int screen_render_invoke(bContext *C, wmOperator *op, const wmEvent *even
name = "Render";
}
- wm_job = WM_jobs_get(
- CTX_wm_manager(C), CTX_wm_window(C), scene, name, jobflag, WM_JOB_TYPE_RENDER);
+ wm_job = WM_jobs_get(CTX_wm_manager(C),
+ CTX_wm_window(C),
+ scene,
+ name,
+ WM_JOB_EXCL_RENDER | WM_JOB_PRIORITY | WM_JOB_PROGRESS,
+ WM_JOB_TYPE_RENDER);
WM_jobs_customdata_set(wm_job, rj, render_freejob);
WM_jobs_timer(wm_job, 0.2, NC_SCENE | ND_RENDER_RESULT, 0);
WM_jobs_callbacks(wm_job, render_startjob, NULL, NULL, render_endjob);
+ if (RNA_struct_property_is_set(op->ptr, "layer")) {
+ WM_jobs_delay_start(wm_job, 0.2);
+ }
+
/* get a render result image, and make sure it is empty */
ima = BKE_image_verify_viewer(bmain, IMA_TYPE_R_RESULT, "Render Result");
BKE_image_signal(rj->main, ima, NULL, IMA_SIGNAL_FREE);
diff --git a/source/blender/editors/render/render_preview.c b/source/blender/editors/render/render_preview.c
index 35130988aba..fbabdc2f3c1 100644
--- a/source/blender/editors/render/render_preview.c
+++ b/source/blender/editors/render/render_preview.c
@@ -1208,19 +1208,13 @@ static void icon_preview_startjob_all_sizes(void *customdata,
IconPreview *ip = (IconPreview *)customdata;
IconPreviewSize *cur_size;
- /* Wait 2s to start rendering icon previews, to not bog down user interaction.
- * Particularly important for heavy scenes and Eevee using OpenGL that blocks
- * the user interface drawing. */
- for (int i = 0; i < 20; i++) {
- PIL_sleep_ms(100);
- if (*stop) {
- return;
- }
- }
-
for (cur_size = ip->sizes.first; cur_size; cur_size = cur_size->next) {
PreviewImage *prv = ip->owner;
+ if (*stop) {
+ break;
+ }
+
if (prv->tag & PRV_TAG_DEFFERED_DELETE) {
/* Non-thread-protected reading is not an issue here. */
continue;
@@ -1265,10 +1259,6 @@ static void icon_preview_startjob_all_sizes(void *customdata,
common_preview_startjob(sp, stop, do_update, progress);
shader_preview_free(sp);
-
- if (*stop) {
- break;
- }
}
}
@@ -1350,8 +1340,13 @@ void ED_preview_icon_render(
BLI_freelistN(&ip.sizes);
}
-void ED_preview_icon_job(
- const bContext *C, void *owner, ID *id, unsigned int *rect, int sizex, int sizey)
+void ED_preview_icon_job(const bContext *C,
+ void *owner,
+ ID *id,
+ unsigned int *rect,
+ int sizex,
+ int sizey,
+ const bool delay)
{
wmJob *wm_job;
IconPreview *ip, *old_ip;
@@ -1363,7 +1358,7 @@ void ED_preview_icon_job(
CTX_wm_window(C),
owner,
"Icon Preview",
- WM_JOB_EXCL_RENDER | WM_JOB_SUSPEND,
+ WM_JOB_EXCL_RENDER,
WM_JOB_TYPE_RENDER_PREVIEW);
ip = MEM_callocN(sizeof(IconPreview), "icon preview");
@@ -1396,6 +1391,10 @@ void ED_preview_icon_job(
/* setup job */
WM_jobs_customdata_set(wm_job, ip, icon_preview_free);
WM_jobs_timer(wm_job, 0.1, NC_WINDOW, NC_WINDOW);
+ /* Wait 2s to start rendering icon previews, to not bog down user interaction.
+ * Particularly important for heavy scenes and Eevee using OpenGL that blocks
+ * the user interface drawing. */
+ WM_jobs_delay_start(wm_job, (delay) ? 2.0 : 0.0);
WM_jobs_callbacks(wm_job, icon_preview_startjob_all_sizes, NULL, NULL, icon_preview_endjob);
WM_jobs_start(CTX_wm_manager(C), wm_job);
diff --git a/source/blender/editors/screen/glutil.c b/source/blender/editors/screen/glutil.c
index fc771e0db77..af1e0eeed79 100644
--- a/source/blender/editors/screen/glutil.c
+++ b/source/blender/editors/screen/glutil.c
@@ -47,17 +47,6 @@
/* ******************************************** */
-/* Invert line handling */
-
-#define GL_TOGGLE(mode, onoff) (((onoff) ? glEnable : glDisable)(mode))
-
-void set_inverted_drawing(int enable)
-{
- glLogicOp(enable ? GL_INVERT : GL_COPY);
- GL_TOGGLE(GL_COLOR_LOGIC_OP, enable);
- GL_TOGGLE(GL_DITHER, !enable);
-}
-
static int get_cached_work_texture(int *r_w, int *r_h)
{
static GLint texid = -1;
@@ -486,6 +475,9 @@ void immDrawPixelsTex_clipping(IMMDrawPixelsTexState *state,
float bglPolygonOffsetCalc(const float winmat[16], float viewdist, float dist)
{
+ /* Seems like we have a factor of 2 more offset than 2.79 for some reason. Correct for this. */
+ dist *= 0.5f;
+
if (winmat[15] > 0.5f) {
#if 1
return 0.00001f * dist * viewdist; // ortho tweaking
diff --git a/source/blender/editors/screen/screen_ops.c b/source/blender/editors/screen/screen_ops.c
index ef99d39f990..c9a45728bc2 100644
--- a/source/blender/editors/screen/screen_ops.c
+++ b/source/blender/editors/screen/screen_ops.c
@@ -74,6 +74,7 @@
#include "ED_clip.h"
#include "ED_image.h"
#include "ED_keyframes_draw.h"
+#include "ED_mesh.h"
#include "ED_object.h"
#include "ED_screen.h"
#include "ED_screen_types.h"
@@ -371,6 +372,12 @@ bool ED_operator_object_active_editable_font(bContext *C)
return ((ob != NULL) && !ID_IS_LINKED(ob) && !ed_object_hidden(ob) && (ob->type == OB_FONT));
}
+bool ED_operator_editable_mesh(bContext *C)
+{
+ Mesh *mesh = ED_mesh_context(C);
+ return (mesh != NULL) && !ID_IS_LINKED(mesh);
+}
+
bool ED_operator_editmesh(bContext *C)
{
Object *obedit = CTX_data_edit_object(C);
@@ -4200,6 +4207,7 @@ static int match_region_with_redraws(int spacetype,
static int screen_animation_step(bContext *C, wmOperator *UNUSED(op), const wmEvent *event)
{
bScreen *screen = CTX_wm_screen(C);
+ wmWindow *win = CTX_wm_window(C);
#ifdef PROFILE_AUDIO_SYNCH
static int old_frame = 0;
@@ -4209,8 +4217,9 @@ static int screen_animation_step(bContext *C, wmOperator *UNUSED(op), const wmEv
if (screen->animtimer && screen->animtimer == event->customdata) {
Main *bmain = CTX_data_main(C);
Scene *scene = CTX_data_scene(C);
- Depsgraph *depsgraph = CTX_data_depsgraph(C);
- Scene *scene_eval = DEG_get_evaluated_scene(depsgraph);
+ ViewLayer *view_layer = WM_window_get_active_view_layer(win);
+ Depsgraph *depsgraph = BKE_scene_get_depsgraph(scene, view_layer, false);
+ Scene *scene_eval = (depsgraph != NULL) ? DEG_get_evaluated_scene(depsgraph) : NULL;
wmTimer *wt = screen->animtimer;
ScreenAnimData *sad = wt->customdata;
wmWindowManager *wm = CTX_wm_manager(C);
@@ -4230,7 +4239,11 @@ static int screen_animation_step(bContext *C, wmOperator *UNUSED(op), const wmEv
sync = (scene->flag & SCE_FRAME_DROP);
}
- if (scene_eval->id.recalc & ID_RECALC_AUDIO_SEEK) {
+ if (scene_eval == NULL) {
+ /* Happens when undo/redo system is used during playback, nothing meaningful we can do here.
+ */
+ }
+ else if (scene_eval->id.recalc & ID_RECALC_AUDIO_SEEK) {
/* Ignore seek here, the audio will be updated to the scene frame after jump during next
* dependency graph update. */
}
@@ -4335,7 +4348,9 @@ static int screen_animation_step(bContext *C, wmOperator *UNUSED(op), const wmEv
}
/* since we follow drawflags, we can't send notifier but tag regions ourselves */
- ED_update_for_newframe(bmain, depsgraph);
+ if (depsgraph != NULL) {
+ ED_update_for_newframe(bmain, depsgraph);
+ }
for (window = wm->windows.first; window; window = window->next) {
const bScreen *win_screen = WM_window_get_active_screen(window);
diff --git a/source/blender/editors/screen/screen_user_menu.c b/source/blender/editors/screen/screen_user_menu.c
index 86be939d41b..26849edeb44 100644
--- a/source/blender/editors/screen/screen_user_menu.c
+++ b/source/blender/editors/screen/screen_user_menu.c
@@ -298,7 +298,7 @@ void ED_screen_user_menu_register(void)
{
MenuType *mt = MEM_callocN(sizeof(MenuType), __func__);
strcpy(mt->idname, "SCREEN_MT_user_menu");
- strcpy(mt->label, "Quick Favorites");
+ strcpy(mt->label, N_("Quick Favorites"));
strcpy(mt->translation_context, BLT_I18NCONTEXT_DEFAULT_BPYRNA);
mt->draw = screen_user_menu_draw;
WM_menutype_add(mt);
diff --git a/source/blender/editors/screen/screendump.c b/source/blender/editors/screen/screendump.c
index e5552314a6e..005c76d26b0 100644
--- a/source/blender/editors/screen/screendump.c
+++ b/source/blender/editors/screen/screendump.c
@@ -110,24 +110,6 @@ static void screenshot_data_free(wmOperator *op)
}
}
-static void screenshot_crop(ImBuf *ibuf, rcti crop)
-{
- unsigned int *to = ibuf->rect;
- unsigned int *from = ibuf->rect + crop.ymin * ibuf->x + crop.xmin;
- int crop_x = BLI_rcti_size_x(&crop);
- int crop_y = BLI_rcti_size_y(&crop);
- int y;
-
- if (crop_x > 0 && crop_y > 0) {
- for (y = 0; y < crop_y; y++, to += crop_x, from += ibuf->x) {
- memmove(to, from, sizeof(unsigned int) * crop_x);
- }
-
- ibuf->x = crop_x;
- ibuf->y = crop_y;
- }
-}
-
static int screenshot_exec(bContext *C, wmOperator *op)
{
ScreenshotData *scd = op->customdata;
@@ -153,7 +135,8 @@ static int screenshot_exec(bContext *C, wmOperator *op)
/* crop to show only single editor */
if (!RNA_boolean_get(op->ptr, "full")) {
- screenshot_crop(ibuf, scd->crop);
+ IMB_rect_crop(ibuf, &scd->crop);
+ scd->dumprect = ibuf->rect;
}
if (scd->im_format.planes == R_IMF_PLANES_BW) {
diff --git a/source/blender/editors/screen/workspace_edit.c b/source/blender/editors/screen/workspace_edit.c
index f4138dd7847..61b737589c8 100644
--- a/source/blender/editors/screen/workspace_edit.c
+++ b/source/blender/editors/screen/workspace_edit.c
@@ -331,30 +331,6 @@ static void WORKSPACE_OT_delete(wmOperatorType *ot)
ot->exec = workspace_delete_exec;
}
-static bool workspace_append_activate_poll(bContext *C)
-{
- wmOperatorType *ot = WM_operatortype_find("WM_OT_append", false);
- return WM_operator_poll(C, ot);
-}
-
-static int workspace_append(bContext *C, const char *directory, const char *idname)
-{
- wmOperatorType *ot = WM_operatortype_find("WM_OT_append", false);
- PointerRNA opptr;
- int retval;
-
- WM_operator_properties_create_ptr(&opptr, ot);
- RNA_string_set(&opptr, "directory", directory);
- RNA_string_set(&opptr, "filename", idname);
- RNA_boolean_set(&opptr, "autoselect", false);
-
- retval = WM_operator_name_call_ptr(C, ot, WM_OP_EXEC_DEFAULT, &opptr);
-
- WM_operator_properties_free(&opptr);
-
- return retval;
-}
-
static int workspace_append_activate_exec(bContext *C, wmOperator *op)
{
Main *bmain = CTX_data_main(C);
@@ -367,23 +343,20 @@ static int workspace_append_activate_exec(bContext *C, wmOperator *op)
RNA_string_get(op->ptr, "idname", idname);
RNA_string_get(op->ptr, "filepath", filepath);
- if (workspace_append(C, filepath, idname) != OPERATOR_CANCELLED) {
- WorkSpace *appended_workspace = BLI_findstring(
- &bmain->workspaces, idname, offsetof(ID, name) + 2);
- BLI_assert(appended_workspace != NULL);
+ WorkSpace *appended_workspace = (WorkSpace *)WM_file_append_datablock(
+ C, filepath, ID_WS, idname);
- if (appended_workspace) {
- /* Set defaults. */
- BLO_update_defaults_workspace(appended_workspace, NULL);
+ if (appended_workspace) {
+ /* Set defaults. */
+ BLO_update_defaults_workspace(appended_workspace, NULL);
- /* Reorder to last position. */
- BKE_id_reorder(&bmain->workspaces, &appended_workspace->id, NULL, true);
+ /* Reorder to last position. */
+ BKE_id_reorder(&bmain->workspaces, &appended_workspace->id, NULL, true);
- /* Changing workspace changes context. Do delayed! */
- WM_event_add_notifier(C, NC_SCREEN | ND_WORKSPACE_SET, appended_workspace);
+ /* Changing workspace changes context. Do delayed! */
+ WM_event_add_notifier(C, NC_SCREEN | ND_WORKSPACE_SET, appended_workspace);
- return OPERATOR_FINISHED;
- }
+ return OPERATOR_FINISHED;
}
return OPERATOR_CANCELLED;
@@ -398,7 +371,6 @@ static void WORKSPACE_OT_append_activate(wmOperatorType *ot)
/* api callbacks */
ot->exec = workspace_append_activate_exec;
- ot->poll = workspace_append_activate_poll;
RNA_def_string(ot->srna,
"idname",
@@ -449,25 +421,21 @@ static void workspace_append_button(uiLayout *layout,
{
const ID *id = (ID *)workspace;
PointerRNA opptr;
- char lib_path[FILE_MAX_LIBEXTRA];
const char *filepath = from_main->name;
if (strlen(filepath) == 0) {
filepath = BLO_EMBEDDED_STARTUP_BLEND;
}
- BLI_path_join(lib_path, sizeof(lib_path), filepath, BKE_idcode_to_name(GS(id->name)), NULL);
-
BLI_assert(STREQ(ot_append->idname, "WORKSPACE_OT_append_activate"));
uiItemFullO_ptr(
layout, ot_append, workspace->id.name + 2, ICON_NONE, NULL, WM_OP_EXEC_DEFAULT, 0, &opptr);
RNA_string_set(&opptr, "idname", id->name + 2);
- RNA_string_set(&opptr, "filepath", lib_path);
+ RNA_string_set(&opptr, "filepath", filepath);
}
-static void workspace_add_menu(bContext *C, uiLayout *layout, void *template_v)
+static void workspace_add_menu(bContext *UNUSED(C), uiLayout *layout, void *template_v)
{
- Main *bmain = CTX_data_main(C);
const char *app_template = template_v;
bool has_startup_items = false;
@@ -479,10 +447,6 @@ static void workspace_add_menu(bContext *C, uiLayout *layout, void *template_v)
for (WorkSpace *workspace = startup_config->workspaces.first; workspace;
workspace = workspace->id.next) {
uiLayout *row = uiLayoutRow(layout, false);
- if (BLI_findstring(&bmain->workspaces, workspace->id.name, offsetof(ID, name))) {
- uiLayoutSetActive(row, false);
- }
-
workspace_append_button(row, ot_append, workspace, startup_config->main);
has_startup_items = true;
}
@@ -506,10 +470,6 @@ static void workspace_add_menu(bContext *C, uiLayout *layout, void *template_v)
}
uiLayout *row = uiLayoutRow(layout, false);
- if (BLI_findstring(&bmain->workspaces, workspace->id.name, offsetof(ID, name))) {
- uiLayoutSetActive(row, false);
- }
-
workspace_append_button(row, ot_append, workspace, builtin_config->main);
}
}
diff --git a/source/blender/editors/sculpt_paint/paint_cursor.c b/source/blender/editors/sculpt_paint/paint_cursor.c
index 65e24cecf82..ac74afce79e 100644
--- a/source/blender/editors/sculpt_paint/paint_cursor.c
+++ b/source/blender/editors/sculpt_paint/paint_cursor.c
@@ -964,9 +964,9 @@ static void paint_draw_curve_cursor(Brush *brush, ViewContext *vc)
immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
float selec_col[4], handle_col[4], pivot_col[4];
- UI_GetThemeColor4fv(TH_VERTEX_SELECT, selec_col);
- UI_GetThemeColor4fv(TH_PAINT_CURVE_HANDLE, handle_col);
- UI_GetThemeColor4fv(TH_PAINT_CURVE_PIVOT, pivot_col);
+ UI_GetThemeColorType4fv(TH_VERTEX_SELECT, SPACE_VIEW3D, selec_col);
+ UI_GetThemeColorType4fv(TH_PAINT_CURVE_HANDLE, SPACE_VIEW3D, handle_col);
+ UI_GetThemeColorType4fv(TH_PAINT_CURVE_PIVOT, SPACE_VIEW3D, pivot_col);
for (i = 0; i < pc->tot_points - 1; i++, cp++) {
int j;
diff --git a/source/blender/editors/sculpt_paint/paint_curve_undo.c b/source/blender/editors/sculpt_paint/paint_curve_undo.c
index c03cb69df88..7e283274383 100644
--- a/source/blender/editors/sculpt_paint/paint_curve_undo.c
+++ b/source/blender/editors/sculpt_paint/paint_curve_undo.c
@@ -122,7 +122,8 @@ static bool paintcurve_undosys_step_encode(struct bContext *C,
static void paintcurve_undosys_step_decode(struct bContext *UNUSED(C),
struct Main *UNUSED(bmain),
UndoStep *us_p,
- int UNUSED(dir))
+ int UNUSED(dir),
+ bool UNUSED(is_final))
{
PaintCurveUndoStep *us = (PaintCurveUndoStep *)us_p;
undocurve_to_paintcurve(&us->data, us->pc);
diff --git a/source/blender/editors/sculpt_paint/paint_hide.c b/source/blender/editors/sculpt_paint/paint_hide.c
index dded9fcf45a..d7e1b47d973 100644
--- a/source/blender/editors/sculpt_paint/paint_hide.c
+++ b/source/blender/editors/sculpt_paint/paint_hide.c
@@ -126,7 +126,8 @@ static void partialvis_update_mesh(Object *ob,
/* Hide or show elements in multires grids with a special GridFlags
* customdata layer. */
-static void partialvis_update_grids(Object *ob,
+static void partialvis_update_grids(Depsgraph *depsgraph,
+ Object *ob,
PBVH *pbvh,
PBVHNode *node,
PartialVisAction action,
@@ -208,7 +209,7 @@ static void partialvis_update_grids(Object *ob,
if (any_changed) {
BKE_pbvh_node_mark_rebuild_draw(node);
BKE_pbvh_node_fully_hidden_set(node, !any_visible);
- multires_mark_as_modified(ob, MULTIRES_HIDDEN_MODIFIED);
+ multires_mark_as_modified(depsgraph, ob, MULTIRES_HIDDEN_MODIFIED);
}
}
@@ -378,7 +379,7 @@ static int hide_show_exec(bContext *C, wmOperator *op)
partialvis_update_mesh(ob, pbvh, nodes[i], action, area, clip_planes);
break;
case PBVH_GRIDS:
- partialvis_update_grids(ob, pbvh, nodes[i], action, area, clip_planes);
+ partialvis_update_grids(depsgraph, ob, pbvh, nodes[i], action, area, clip_planes);
break;
case PBVH_BMESH:
partialvis_update_bmesh(ob, pbvh, nodes[i], action, area, clip_planes);
diff --git a/source/blender/editors/sculpt_paint/paint_image_proj.c b/source/blender/editors/sculpt_paint/paint_image_proj.c
index 79731a6752d..22de22e8e59 100644
--- a/source/blender/editors/sculpt_paint/paint_image_proj.c
+++ b/source/blender/editors/sculpt_paint/paint_image_proj.c
@@ -1554,9 +1554,8 @@ static void screen_px_from_persp(const float uv[2],
w_int[2] *= wtot_inv;
}
else {
- w[0] = w[1] = w[2] =
- /* dummy values for zero area face */
- w_int[0] = w_int[1] = w_int[2] = 1.0f / 3.0f;
+ /* Dummy values for zero area face. */
+ w[0] = w[1] = w[2] = w_int[0] = w_int[1] = w_int[2] = 1.0f / 3.0f;
}
/* done re-weighting */
diff --git a/source/blender/editors/sculpt_paint/paint_image_undo.c b/source/blender/editors/sculpt_paint/paint_image_undo.c
index bb73d424152..e7f100ebacb 100644
--- a/source/blender/editors/sculpt_paint/paint_image_undo.c
+++ b/source/blender/editors/sculpt_paint/paint_image_undo.c
@@ -540,10 +540,8 @@ static void image_undosys_step_decode_redo(ImageUndoStep *us)
}
}
-static void image_undosys_step_decode(struct bContext *C,
- struct Main *bmain,
- UndoStep *us_p,
- int dir)
+static void image_undosys_step_decode(
+ struct bContext *C, struct Main *bmain, UndoStep *us_p, int dir, bool UNUSED(is_final))
{
ImageUndoStep *us = (ImageUndoStep *)us_p;
#if 0
diff --git a/source/blender/editors/sculpt_paint/paint_mask.c b/source/blender/editors/sculpt_paint/paint_mask.c
index 0dd2e8ee968..f60ea8410ef 100644
--- a/source/blender/editors/sculpt_paint/paint_mask.c
+++ b/source/blender/editors/sculpt_paint/paint_mask.c
@@ -167,7 +167,7 @@ static int mask_flood_fill_exec(bContext *C, wmOperator *op)
0, totnode, &data, mask_flood_fill_task_cb, &settings);
if (multires) {
- multires_mark_as_modified(ob, MULTIRES_COORDS_MODIFIED);
+ multires_mark_as_modified(depsgraph, ob, MULTIRES_COORDS_MODIFIED);
}
sculpt_undo_push_end();
@@ -341,7 +341,7 @@ bool ED_sculpt_mask_box_select(struct bContext *C, ViewContext *vc, const rcti *
}
if (multires) {
- multires_mark_as_modified(ob, MULTIRES_COORDS_MODIFIED);
+ multires_mark_as_modified(depsgraph, ob, MULTIRES_COORDS_MODIFIED);
}
sculpt_undo_push_end();
@@ -528,7 +528,7 @@ static int paint_mask_gesture_lasso_exec(bContext *C, wmOperator *op)
}
if (multires) {
- multires_mark_as_modified(ob, MULTIRES_COORDS_MODIFIED);
+ multires_mark_as_modified(depsgraph, ob, MULTIRES_COORDS_MODIFIED);
}
sculpt_undo_push_end();
diff --git a/source/blender/editors/sculpt_paint/paint_vertex.c b/source/blender/editors/sculpt_paint/paint_vertex.c
index 316ae6189f0..980b043bf8b 100644
--- a/source/blender/editors/sculpt_paint/paint_vertex.c
+++ b/source/blender/editors/sculpt_paint/paint_vertex.c
@@ -56,6 +56,7 @@
#include "BKE_paint.h"
#include "BKE_report.h"
#include "BKE_subsurf.h"
+#include "BKE_layer.h"
#include "DEG_depsgraph.h"
@@ -1305,18 +1306,47 @@ static int wpaint_mode_toggle_exec(bContext *C, wmOperator *op)
BKE_paint_toolslots_brush_validate(bmain, &ts->wpaint->paint);
}
- /* When locked, it's almost impossible to select the pose
- * then the object to enter weight paint mode.
+ /* When locked, it's almost impossible to select the pose-object
+ * then the mesh-object to enter weight paint mode.
+ * Even when the object mode is not locked this is inconvenient - so allow in either case.
+ *
* In this case move our pose object in/out of pose mode.
- * This is in fits with the convention of selecting multiple objects and entering a mode. */
- if (scene->toolsettings->object_flag & SCE_OBJECT_MODE_LOCK) {
- Object *ob_arm = modifiers_isDeformedByArmature(ob);
- if (ob_arm && (ob_arm->base_flag & BASE_SELECTED)) {
- if (ob_arm->mode & OB_MODE_POSE) {
- ED_object_posemode_exit_ex(bmain, ob_arm);
- }
- else {
- ED_object_posemode_enter_ex(bmain, ob_arm);
+ * This is in fits with the convention of selecting multiple objects and entering a mode.
+ */
+ {
+ VirtualModifierData virtualModifierData;
+ ModifierData *md = modifiers_getVirtualModifierList(ob, &virtualModifierData);
+ if (md != NULL) {
+ /* Can be NULL. */
+ View3D *v3d = CTX_wm_view3d(C);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ for (; md; md = md->next) {
+ if (md->type == eModifierType_Armature) {
+ ArmatureModifierData *amd = (ArmatureModifierData *)md;
+ Object *ob_arm = amd->object;
+ if (ob_arm != NULL) {
+ const Base *base_arm = BKE_view_layer_base_find(view_layer, ob_arm);
+ if (base_arm && BASE_VISIBLE(v3d, base_arm)) {
+ if (is_mode_set) {
+ if ((ob_arm->mode & OB_MODE_POSE) != 0) {
+ ED_object_posemode_exit_ex(bmain, ob_arm);
+ }
+ }
+ else {
+ /* Only check selected status when entering weight-paint mode
+ * because we may have multiple armature objects.
+ * Selecting one will de-select the other, which would leave it in pose-mode
+ * when exiting weight paint mode. While usable, this looks like inconsistent
+ * behavior from a user perspective. */
+ if (base_arm->flag & BASE_SELECTED) {
+ if ((ob_arm->mode & OB_MODE_POSE) == 0) {
+ ED_object_posemode_enter_ex(bmain, ob_arm);
+ }
+ }
+ }
+ }
+ }
+ }
}
}
}
@@ -2271,7 +2301,6 @@ static void wpaint_stroke_update_step(bContext *C, struct PaintStroke *stroke, P
vwpaint_update_cache_variants(C, wp, ob, itemptr);
float mat[4][4];
- float mval[2];
const float brush_alpha_value = BKE_brush_alpha_get(scene, brush);
@@ -2321,7 +2350,7 @@ static void wpaint_stroke_update_step(bContext *C, struct PaintStroke *stroke, P
/* calculate pivot for rotation around seletion if needed */
/* also needed for "View Selected" on last stroke */
- paint_last_stroke_update(scene, vc->ar, mval);
+ paint_last_stroke_update(scene, vc->ar, ss->cache->mouse);
BKE_mesh_batch_cache_dirty_tag(ob->data, BKE_MESH_BATCH_DIRTY_ALL);
@@ -3273,12 +3302,12 @@ static void vpaint_stroke_update_step(bContext *C, struct PaintStroke *stroke, P
VPaint *vp = ts->vpaint;
ViewContext *vc = &vpd->vc;
Object *ob = vc->obact;
+ SculptSession *ss = ob->sculpt;
Sculpt *sd = CTX_data_tool_settings(C)->sculpt;
vwpaint_update_cache_variants(C, vp, ob, itemptr);
float mat[4][4];
- float mval[2];
ED_view3d_init_mats_rv3d(ob, vc->rv3d);
@@ -3300,7 +3329,7 @@ static void vpaint_stroke_update_step(bContext *C, struct PaintStroke *stroke, P
/* calculate pivot for rotation around seletion if needed */
/* also needed for "View Selected" on last stroke */
- paint_last_stroke_update(scene, vc->ar, mval);
+ paint_last_stroke_update(scene, vc->ar, ss->cache->mouse);
ED_region_tag_redraw(vc->ar);
diff --git a/source/blender/editors/sculpt_paint/sculpt.c b/source/blender/editors/sculpt_paint/sculpt.c
index ec7cb410f2c..173d6ed5085 100644
--- a/source/blender/editors/sculpt_paint/sculpt.c
+++ b/source/blender/editors/sculpt_paint/sculpt.c
@@ -5186,15 +5186,13 @@ static void sculpt_flush_update_step(bContext *C)
{
Depsgraph *depsgraph = CTX_data_depsgraph(C);
Object *ob = CTX_data_active_object(C);
- Object *ob_eval = DEG_get_evaluated_object(depsgraph, ob);
SculptSession *ss = ob->sculpt;
ARegion *ar = CTX_wm_region(C);
MultiresModifierData *mmd = ss->multires;
View3D *v3d = CTX_wm_view3d(C);
if (mmd != NULL) {
- /* NOTE: SubdivCCG is living in the evaluated object. */
- multires_mark_as_modified(ob_eval, MULTIRES_COORDS_MODIFIED);
+ multires_mark_as_modified(depsgraph, ob, MULTIRES_COORDS_MODIFIED);
}
DEG_id_tag_update(&ob->id, ID_RECALC_SHADING);
diff --git a/source/blender/editors/sculpt_paint/sculpt_undo.c b/source/blender/editors/sculpt_paint/sculpt_undo.c
index 8c8d4487ada..81bb9c35817 100644
--- a/source/blender/editors/sculpt_paint/sculpt_undo.c
+++ b/source/blender/editors/sculpt_paint/sculpt_undo.c
@@ -554,10 +554,10 @@ static void sculpt_undo_restore_list(bContext *C, ListBase *lb)
if (BKE_sculpt_multires_active(scene, ob)) {
if (rebuild) {
- multires_mark_as_modified(ob, MULTIRES_HIDDEN_MODIFIED);
+ multires_mark_as_modified(depsgraph, ob, MULTIRES_HIDDEN_MODIFIED);
}
else {
- multires_mark_as_modified(ob, MULTIRES_COORDS_MODIFIED);
+ multires_mark_as_modified(depsgraph, ob, MULTIRES_COORDS_MODIFIED);
}
}
@@ -1109,10 +1109,8 @@ static void sculpt_undosys_step_decode_redo(struct bContext *C, SculptUndoStep *
}
}
-static void sculpt_undosys_step_decode(struct bContext *C,
- struct Main *bmain,
- UndoStep *us_p,
- int dir)
+static void sculpt_undosys_step_decode(
+ struct bContext *C, struct Main *bmain, UndoStep *us_p, int dir, bool UNUSED(is_final))
{
/* Ensure sculpt mode. */
{
diff --git a/source/blender/editors/sound/sound_ops.c b/source/blender/editors/sound/sound_ops.c
index 30ddd8c7d33..0241a2fbe88 100644
--- a/source/blender/editors/sound/sound_ops.c
+++ b/source/blender/editors/sound/sound_ops.c
@@ -104,7 +104,7 @@ static int sound_open_exec(bContext *C, wmOperator *op)
}
if (RNA_boolean_get(op->ptr, "cache")) {
- BKE_sound_cache(sound);
+ sound->flags |= SOUND_FLAGS_CACHING;
}
/* hook into UI */
@@ -765,7 +765,8 @@ static int sound_pack_exec(bContext *C, wmOperator *op)
return OPERATOR_CANCELLED;
}
- sound->packedfile = newPackedFile(op->reports, sound->name, ID_BLEND_PATH(bmain, &sound->id));
+ sound->packedfile = BKE_packedfile_new(
+ op->reports, sound->name, ID_BLEND_PATH(bmain, &sound->id));
BKE_sound_load(bmain, sound);
return OPERATOR_FINISHED;
@@ -811,7 +812,7 @@ static int sound_unpack_exec(bContext *C, wmOperator *op)
"AutoPack is enabled, so image will be packed again on file save");
}
- unpackSound(bmain, op->reports, sound, method);
+ BKE_packedfile_unpack_sound(bmain, op->reports, sound, method);
return OPERATOR_FINISHED;
}
diff --git a/source/blender/editors/space_clip/clip_draw.c b/source/blender/editors/space_clip/clip_draw.c
index 99f9a91775e..e3fa8edd714 100644
--- a/source/blender/editors/space_clip/clip_draw.c
+++ b/source/blender/editors/space_clip/clip_draw.c
@@ -1378,10 +1378,11 @@ static void draw_plane_marker_ex(SpaceClip *sc,
immEnd();
}
}
+ immUnbindProgram();
/* Draw sliders. */
if (is_selected_track) {
- immUniform1f("dash_factor", 2.0f); /* Solid line */
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
if (draw_outline) {
immUniformThemeColor(TH_MARKER_OUTLINE);
@@ -1400,9 +1401,8 @@ static void draw_plane_marker_ex(SpaceClip *sc,
px,
shdr_pos);
}
+ immUnbindProgram();
}
-
- immUnbindProgram();
}
}
diff --git a/source/blender/editors/space_clip/clip_ops.c b/source/blender/editors/space_clip/clip_ops.c
index 83d8133a99e..45479c4253d 100644
--- a/source/blender/editors/space_clip/clip_ops.c
+++ b/source/blender/editors/space_clip/clip_ops.c
@@ -1515,6 +1515,11 @@ static int mode_set_exec(bContext *C, wmOperator *op)
sc->mode = mode;
+ if (sc->mode == SC_MODE_MASKEDIT && sc->view != SC_VIEW_CLIP) {
+ /* Make sure we are in the right view for mask editing */
+ sc->view = SC_VIEW_CLIP;
+ }
+
WM_event_add_notifier(C, NC_SPACE | ND_SPACE_CLIP, NULL);
return OPERATOR_FINISHED;
diff --git a/source/blender/editors/space_clip/space_clip.c b/source/blender/editors/space_clip/space_clip.c
index c290e3a21d1..7e19ac255f0 100644
--- a/source/blender/editors/space_clip/space_clip.c
+++ b/source/blender/editors/space_clip/space_clip.c
@@ -420,6 +420,14 @@ static void clip_listener(wmWindow *UNUSED(win), ScrArea *sa, wmNotifier *wmn, S
ED_area_tag_redraw(sa);
}
break;
+ case NC_WM:
+ switch (wmn->data) {
+ case ND_FILEREAD:
+ case ND_UNDO:
+ clip_area_sync_frame_from_scene(sa, scene);
+ break;
+ }
+ break;
}
}
diff --git a/source/blender/editors/space_clip/tracking_ops_plane.c b/source/blender/editors/space_clip/tracking_ops_plane.c
index 89478375658..b1bf88634bc 100644
--- a/source/blender/editors/space_clip/tracking_ops_plane.c
+++ b/source/blender/editors/space_clip/tracking_ops_plane.c
@@ -74,6 +74,7 @@ static int create_plane_track_tracks_exec(bContext *C, wmOperator *op)
BKE_tracking_track_plane_from_existing_motion(plane_track, framenr);
}
+ DEG_id_tag_update(&clip->id, ID_RECALC_COPY_ON_WRITE);
WM_event_add_notifier(C, NC_MOVIECLIP | NA_EDITED, clip);
return OPERATOR_FINISHED;
@@ -337,8 +338,7 @@ static int slide_plane_marker_modal(bContext *C, wmOperator *op, const wmEvent *
data->previous_mval[1] = event->mval[1];
copy_v2_v2(data->previous_corner, data->corner);
- DEG_id_tag_update(&sc->clip->id, 0);
-
+ DEG_id_tag_update(&clip->id, ID_RECALC_COPY_ON_WRITE);
WM_event_add_notifier(C, NC_MOVIECLIP | NA_EDITED, NULL);
break;
@@ -355,7 +355,7 @@ static int slide_plane_marker_modal(bContext *C, wmOperator *op, const wmEvent *
clip_tracking_show_cursor(C);
- DEG_id_tag_update(&sc->clip->id, 0);
+ DEG_id_tag_update(&clip->id, ID_RECALC_COPY_ON_WRITE);
WM_event_add_notifier(C, NC_MOVIECLIP | NA_EDITED, clip);
return OPERATOR_FINISHED;
diff --git a/source/blender/editors/space_file/file_ops.c b/source/blender/editors/space_file/file_ops.c
index 15f87235c0d..4e50413513a 100644
--- a/source/blender/editors/space_file/file_ops.c
+++ b/source/blender/editors/space_file/file_ops.c
@@ -1736,7 +1736,7 @@ static int file_smoothscroll_invoke(bContext *C, wmOperator *UNUSED(op), const w
((numfiles % items_block_size) != 0 ? items_block_size : 0)) -
(numfiles_layout / 2);
/* Actual (physical) scrolling info, in pixels, used to detect whether we are fully at the
- * begining/end of the view. */
+ * beginning/end of the view. */
/* Note that there is a weird glitch, that sometimes tot rctf is smaller than cur rctf...
* that is why we still need to keep the min/max_middle_offset checks too. :( */
const float min_tot_scroll = is_horizontal ? ar->v2d.tot.xmin : -ar->v2d.tot.ymax;
@@ -1747,16 +1747,16 @@ static int file_smoothscroll_invoke(bContext *C, wmOperator *UNUSED(op), const w
/* Check if we have reached our final scroll position. */
/* Filelist has to be ready, otherwise it makes no sense to stop scrolling yet. */
const bool is_ready = filelist_is_ready(sfile->files);
- /* Edited item must be in the 'middle' of shown area (kind of approximative).
+ /* Edited item must be in the 'middle' of shown area (kind of approximated).
* Note that we have to do the check in 'block space', not in 'item space' here. */
const bool is_centered = (abs(middle_offset / items_block_size -
sfile->scroll_offset / items_block_size) == 0);
- /* OR edited item must be towards the begining, and we are scrolled fully to the start. */
+ /* OR edited item must be towards the beginning, and we are scrolled fully to the start. */
const bool is_full_start = ((sfile->scroll_offset < min_middle_offset) &&
(min_curr_scroll - min_tot_scroll < 1.0f) &&
(middle_offset - min_middle_offset < items_block_size));
/* OR edited item must be towards the end, and we are scrolled fully to the end.
- * This one is crucial (unlike the one for the begining), because without it we won't scroll
+ * This one is crucial (unlike the one for the beginning), because without it we won't scroll
* fully to the end, and last column or row wil end up only partially drawn. */
const bool is_full_end = ((sfile->scroll_offset > max_middle_offset) &&
(max_tot_scroll - max_curr_scroll < 1.0f) &&
diff --git a/source/blender/editors/space_image/image_draw.c b/source/blender/editors/space_image/image_draw.c
index 86db6d50fcc..97a3c7f2480 100644
--- a/source/blender/editors/space_image/image_draw.c
+++ b/source/blender/editors/space_image/image_draw.c
@@ -797,6 +797,11 @@ void draw_image_main(const bContext *C, ARegion *ar)
ima = ED_space_image(sima);
ED_space_image_get_zoom(sima, ar, &zoomx, &zoomy);
+ /* Tag image as in active use for garbage collector. */
+ if (ima) {
+ BKE_image_tag_time(ima);
+ }
+
show_viewer = (ima && ima->source == IMA_SRC_VIEWER) != 0;
show_render = (show_viewer && ima->type == IMA_TYPE_R_RESULT) != 0;
show_paint = (ima && (sima->mode == SI_MODE_PAINT) && (show_viewer == false) &&
diff --git a/source/blender/editors/space_image/image_ops.c b/source/blender/editors/space_image/image_ops.c
index 96eaa89d175..b79ed1c83c4 100644
--- a/source/blender/editors/space_image/image_ops.c
+++ b/source/blender/editors/space_image/image_ops.c
@@ -1391,7 +1391,7 @@ static int image_open_exec(bContext *C, wmOperator *op)
BKE_image_init_imageuser(ima, iuser);
}
- /* XXX unpackImage frees image buffers */
+ /* XXX BKE_packedfile_unpack_image frees image buffers */
ED_preview_kill_jobs(CTX_wm_manager(C), bmain);
BKE_image_signal(bmain, ima, iuser, IMA_SIGNAL_RELOAD);
@@ -1601,7 +1601,7 @@ static int image_replace_exec(bContext *C, wmOperator *op)
sima->image->source = IMA_SRC_FILE;
}
- /* XXX unpackImage frees image buffers */
+ /* XXX BKE_packedfile_unpack_image frees image buffers */
ED_preview_kill_jobs(CTX_wm_manager(C), CTX_data_main(C));
BKE_icon_changed(BKE_icon_id_ensure(&sima->image->id));
@@ -2401,7 +2401,7 @@ static int image_reload_exec(bContext *C, wmOperator *UNUSED(op))
return OPERATOR_CANCELLED;
}
- /* XXX unpackImage frees image buffers */
+ /* XXX BKE_packedfile_unpack_image frees image buffers */
ED_preview_kill_jobs(CTX_wm_manager(C), CTX_data_main(C));
BKE_image_signal(bmain, ima, iuser, IMA_SIGNAL_RELOAD);
@@ -2859,10 +2859,10 @@ static int image_unpack_exec(bContext *C, wmOperator *op)
"AutoPack is enabled, so image will be packed again on file save");
}
- /* XXX unpackImage frees image buffers */
+ /* XXX BKE_packedfile_unpack_image frees image buffers */
ED_preview_kill_jobs(CTX_wm_manager(C), CTX_data_main(C));
- unpackImage(CTX_data_main(C), op->reports, ima, method);
+ BKE_packedfile_unpack_image(CTX_data_main(C), op->reports, ima, method);
WM_event_add_notifier(C, NC_IMAGE | NA_EDITED, ima);
diff --git a/source/blender/editors/space_image/space_image.c b/source/blender/editors/space_image/space_image.c
index 6bf79711ae5..e8116193c1f 100644
--- a/source/blender/editors/space_image/space_image.c
+++ b/source/blender/editors/space_image/space_image.c
@@ -843,6 +843,11 @@ static void image_buttons_region_listener(wmWindow *UNUSED(win),
ED_region_tag_redraw(ar);
}
break;
+ case NC_BRUSH:
+ if (wmn->action == NA_EDITED) {
+ ED_region_tag_redraw(ar);
+ }
+ break;
}
}
@@ -946,6 +951,11 @@ static void image_header_region_listener(wmWindow *UNUSED(win),
break;
}
break;
+ case NC_BRUSH:
+ if (wmn->action == NA_EDITED) {
+ ED_region_tag_redraw(ar);
+ }
+ break;
}
}
diff --git a/source/blender/editors/space_info/info_ops.c b/source/blender/editors/space_info/info_ops.c
index bf43e493cc5..14817e9ffa1 100644
--- a/source/blender/editors/space_info/info_ops.c
+++ b/source/blender/editors/space_info/info_ops.c
@@ -65,7 +65,7 @@ static int pack_libraries_exec(bContext *C, wmOperator *op)
{
Main *bmain = CTX_data_main(C);
- packLibraries(bmain, op->reports);
+ BKE_packedfile_pack_all_libraries(bmain, op->reports);
return OPERATOR_FINISHED;
}
@@ -88,7 +88,7 @@ static int unpack_libraries_exec(bContext *C, wmOperator *op)
{
Main *bmain = CTX_data_main(C);
- unpackLibraries(bmain, op->reports);
+ BKE_packedfile_unpack_all_libraries(bmain, op->reports);
return OPERATOR_FINISHED;
}
@@ -124,7 +124,7 @@ static int autopack_toggle_exec(bContext *C, wmOperator *op)
G.fileflags &= ~G_FILE_AUTOPACK;
}
else {
- packAll(bmain, op->reports, true);
+ BKE_packedfile_pack_all(bmain, op->reports, true);
G.fileflags |= G_FILE_AUTOPACK;
}
@@ -151,7 +151,7 @@ static int pack_all_exec(bContext *C, wmOperator *op)
{
Main *bmain = CTX_data_main(C);
- packAll(bmain, op->reports, true);
+ BKE_packedfile_pack_all(bmain, op->reports, true);
return OPERATOR_FINISHED;
}
@@ -221,7 +221,7 @@ static int unpack_all_exec(bContext *C, wmOperator *op)
int method = RNA_enum_get(op->ptr, "method");
if (method != PF_KEEP) {
- unpackAll(bmain, op->reports, method); /* XXX PF_ASK can't work here */
+ BKE_packedfile_unpack_all(bmain, op->reports, method); /* XXX PF_ASK can't work here */
}
G.fileflags &= ~G_FILE_AUTOPACK;
@@ -236,7 +236,7 @@ static int unpack_all_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(
char title[64];
int count = 0;
- count = countPackedFiles(bmain);
+ count = BKE_packedfile_count_all(bmain);
if (!count) {
BKE_report(op->reports, RPT_WARNING, "No packed files to unpack");
@@ -321,7 +321,7 @@ static int unpack_item_exec(bContext *C, wmOperator *op)
}
if (method != PF_KEEP) {
- BKE_unpack_id(bmain, id, op->reports, method); /* XXX PF_ASK can't work here */
+ BKE_packedfile_id_unpack(bmain, id, op->reports, method); /* XXX PF_ASK can't work here */
}
G.fileflags &= ~G_FILE_AUTOPACK;
@@ -545,7 +545,8 @@ static int update_reports_display_invoke(bContext *C, wmOperator *UNUSED(op), co
/* escape if not our timer */
if ((reports->reporttimer == NULL) || (reports->reporttimer != event->customdata) ||
- ((report = BKE_reports_last_displayable(reports)) == NULL) /* may have been deleted */
+ ((report = BKE_reports_last_displayable(reports)) == NULL)
+ /* may have been deleted */
) {
return OPERATOR_PASS_THROUGH;
}
diff --git a/source/blender/editors/space_node/node_edit.c b/source/blender/editors/space_node/node_edit.c
index a5755ae43c6..d31256a1425 100644
--- a/source/blender/editors/space_node/node_edit.c
+++ b/source/blender/editors/space_node/node_edit.c
@@ -210,6 +210,7 @@ static void compo_initjob(void *cjv)
/* NOTE: Don't update animation to preserve unkeyed changes, this means can not use
* evaluate_on_framechange. */
+ DEG_graph_flush_update(bmain, cj->compositor_depsgraph);
DEG_evaluate_on_refresh(cj->compositor_depsgraph);
bNodeTree *ntree_eval = (bNodeTree *)DEG_get_evaluated_id(cj->compositor_depsgraph,
@@ -2418,6 +2419,7 @@ static int ntree_socket_move_exec(bContext *C, wmOperator *op)
}
}
+ ntree->update |= NTREE_UPDATE_GROUP;
ntreeUpdateTree(CTX_data_main(C), ntree);
snode_notify(C, snode);
diff --git a/source/blender/editors/space_node/node_view.c b/source/blender/editors/space_node/node_view.c
index b33960bb454..7dec6f5a4ef 100644
--- a/source/blender/editors/space_node/node_view.c
+++ b/source/blender/editors/space_node/node_view.c
@@ -347,7 +347,7 @@ static int backimage_fit_exec(bContext *C, wmOperator *UNUSED(op))
BKE_image_release_ibuf(ima, ibuf, lock);
- snode->zoom *= min_ff(facx, facy);
+ snode->zoom *= min_ff(facx, facy) * U.dpi_fac;
snode->xof = 0;
snode->yof = 0;
diff --git a/source/blender/editors/space_outliner/outliner_collections.c b/source/blender/editors/space_outliner/outliner_collections.c
index 459183ff226..4740c412083 100644
--- a/source/blender/editors/space_outliner/outliner_collections.c
+++ b/source/blender/editors/space_outliner/outliner_collections.c
@@ -593,7 +593,7 @@ static int collection_link_exec(bContext *C, wmOperator *op)
if (ID_IS_LINKED(active_collection) ||
((active_collection->flag & COLLECTION_IS_MASTER) && ID_IS_LINKED(scene))) {
- BKE_report(op->reports, RPT_ERROR, "Cannot add a colection to a linked collection/scene");
+ BKE_report(op->reports, RPT_ERROR, "Cannot add a collection to a linked collection/scene");
return OPERATOR_CANCELLED;
}
diff --git a/source/blender/editors/space_outliner/outliner_draw.c b/source/blender/editors/space_outliner/outliner_draw.c
index 86f99555e12..55130ae8894 100644
--- a/source/blender/editors/space_outliner/outliner_draw.c
+++ b/source/blender/editors/space_outliner/outliner_draw.c
@@ -116,6 +116,10 @@ static void outliner_tree_dimensions(SpaceOutliner *soops, int *r_width, int *r_
*/
static bool is_object_data_in_editmode(const ID *id, const Object *obact)
{
+ if (id == NULL) {
+ return false;
+ }
+
const short id_type = GS(id->name);
if (id_type == ID_GD && obact && obact->data == id) {
@@ -929,6 +933,40 @@ static void outliner_restrict_properties_enable_layer_collection_set(
}
}
+static bool outliner_restrict_properties_collection_set(Scene *scene,
+ TreeElement *te,
+ PointerRNA *collection_ptr,
+ PointerRNA *layer_collection_ptr,
+ RestrictProperties *props,
+ RestrictPropertiesActive *props_active)
+{
+ TreeStoreElem *tselem = TREESTORE(te);
+ LayerCollection *layer_collection = (tselem->type == TSE_LAYER_COLLECTION) ? te->directdata :
+ NULL;
+ Collection *collection = outliner_collection_from_tree_element(te);
+
+ if ((collection->flag & COLLECTION_IS_MASTER) ||
+ (layer_collection && ((layer_collection->flag & LAYER_COLLECTION_EXCLUDE) != 0))) {
+ return false;
+ }
+
+ /* Create the PointerRNA. */
+ RNA_id_pointer_create(&collection->id, collection_ptr);
+ if (layer_collection != NULL) {
+ RNA_pointer_create(&scene->id, &RNA_LayerCollection, layer_collection, layer_collection_ptr);
+ }
+
+ /* Update the restriction column values for the collection children. */
+ if (layer_collection) {
+ outliner_restrict_properties_enable_layer_collection_set(
+ layer_collection_ptr, collection_ptr, props, props_active);
+ }
+ else {
+ outliner_restrict_properties_enable_collection_set(collection_ptr, props, props_active);
+ }
+ return true;
+}
+
static void outliner_draw_restrictbuts(uiBlock *block,
Scene *scene,
ViewLayer *view_layer,
@@ -1333,30 +1371,16 @@ static void outliner_draw_restrictbuts(uiBlock *block,
}
}
else if (outliner_is_collection_tree_element(te)) {
- LayerCollection *layer_collection = (tselem->type == TSE_LAYER_COLLECTION) ?
- te->directdata :
- NULL;
- Collection *collection = outliner_collection_from_tree_element(te);
- if ((!layer_collection || !(layer_collection->flag & LAYER_COLLECTION_EXCLUDE)) &&
- !(collection->flag & COLLECTION_IS_MASTER)) {
+ PointerRNA collection_ptr;
+ PointerRNA layer_collection_ptr;
- PointerRNA collection_ptr;
- PointerRNA layer_collection_ptr;
- RNA_id_pointer_create(&collection->id, &collection_ptr);
- if (layer_collection != NULL) {
- RNA_pointer_create(
- &scene->id, &RNA_LayerCollection, layer_collection, &layer_collection_ptr);
- }
+ if (outliner_restrict_properties_collection_set(
+ scene, te, &collection_ptr, &layer_collection_ptr, &props, &props_active)) {
- /* Update the restriction column values for the collection children. */
- if (layer_collection) {
- outliner_restrict_properties_enable_layer_collection_set(
- &layer_collection_ptr, &collection_ptr, &props, &props_active);
- }
- else {
- outliner_restrict_properties_enable_collection_set(
- &collection_ptr, &props, &props_active);
- }
+ LayerCollection *layer_collection = (tselem->type == TSE_LAYER_COLLECTION) ?
+ te->directdata :
+ NULL;
+ Collection *collection = outliner_collection_from_tree_element(te);
if (layer_collection != NULL) {
if (soops->show_restrict_flags & SO_RESTRICT_HIDE) {
@@ -1443,7 +1467,8 @@ static void outliner_draw_restrictbuts(uiBlock *block,
layer_collection,
(char *)"indirect_only");
UI_but_flag_enable(bt, UI_BUT_DRAG_LOCK);
- if (!props_active.layer_collection_indirect_only) {
+ if (props_active.layer_collection_holdout ||
+ !props_active.layer_collection_indirect_only) {
UI_but_flag_enable(bt, UI_BUT_INACTIVE);
}
}
@@ -1558,6 +1583,12 @@ static void outliner_draw_restrictbuts(uiBlock *block,
}
}
}
+ else if (outliner_is_collection_tree_element(te)) {
+ PointerRNA collection_ptr;
+ PointerRNA layer_collection_ptr;
+ outliner_restrict_properties_collection_set(
+ scene, te, &collection_ptr, &layer_collection_ptr, &props, &props_active);
+ }
if (TSELEM_OPEN(tselem, soops)) {
outliner_draw_restrictbuts(block, scene, view_layer, ar, soops, &te->subtree, props_active);
@@ -2202,7 +2233,7 @@ TreeElementIcon tree_element_get_icon(TreeStoreElem *tselem, TreeElement *te)
data.icon = ICON_OUTLINER_OB_LIGHTPROBE;
break;
case OB_EMPTY:
- if (ob->instance_collection) {
+ if (ob->instance_collection && (ob->transflag & OB_DUPLICOLLECTION)) {
data.icon = ICON_OUTLINER_OB_GROUP_INSTANCE;
}
else if (ob->empty_drawtype == OB_EMPTY_IMAGE) {
diff --git a/source/blender/editors/space_outliner/outliner_tools.c b/source/blender/editors/space_outliner/outliner_tools.c
index e1e7bf49606..89eb3b9d953 100644
--- a/source/blender/editors/space_outliner/outliner_tools.c
+++ b/source/blender/editors/space_outliner/outliner_tools.c
@@ -109,8 +109,9 @@ static void set_operation_types(SpaceOutliner *soops,
}
}
else {
- int idcode = GS(tselem->id->name);
- switch (idcode) {
+ const int idcode = (int)GS(tselem->id->name);
+ bool is_standard_id = false;
+ switch ((ID_Type)idcode) {
case ID_SCE:
*scenelevel = 1;
break;
@@ -134,21 +135,47 @@ static void set_operation_types(SpaceOutliner *soops,
case ID_KE:
case ID_WO:
case ID_AC:
- case ID_NLA:
case ID_TXT:
case ID_GR:
case ID_LS:
case ID_LI:
- if (*idlevel == 0) {
- *idlevel = idcode;
- }
- else if (*idlevel != idcode) {
- *idlevel = -1;
- }
- if (ELEM(*datalevel, TSE_VIEW_COLLECTION_BASE, TSE_SCENE_COLLECTION_BASE)) {
- *datalevel = 0;
- }
+ case ID_VF:
+ case ID_NT:
+ case ID_BR:
+ case ID_PA:
+ case ID_GD:
+ case ID_MC:
+ case ID_MSK:
+ case ID_PAL:
+ case ID_PC:
+ case ID_CF:
+ case ID_WS:
+ case ID_LP:
+ is_standard_id = true;
break;
+ case ID_WM:
+ case ID_SCR:
+ /* Those are ignored here. */
+ /* Note: while Screens should be manageable here, deleting a screen used by a workspace
+ * will cause crashes when trying to use that workspace, so for now let's play minimal,
+ * safe change. */
+ break;
+ }
+ if (idcode == ID_NLA) {
+ /* Fake one, not an actual ID type... */
+ is_standard_id = true;
+ }
+
+ if (is_standard_id) {
+ if (*idlevel == 0) {
+ *idlevel = idcode;
+ }
+ else if (*idlevel != idcode) {
+ *idlevel = -1;
+ }
+ if (ELEM(*datalevel, TSE_VIEW_COLLECTION_BASE, TSE_SCENE_COLLECTION_BASE)) {
+ *datalevel = 0;
+ }
}
}
}
@@ -288,31 +315,33 @@ static void unlink_object_cb(bContext *C,
TreeStoreElem *tselem,
void *UNUSED(user_data))
{
- Main *bmain = CTX_data_main(C);
- Object *ob = (Object *)tselem->id;
+ if (tsep && tsep->id) {
+ Main *bmain = CTX_data_main(C);
+ Object *ob = (Object *)tselem->id;
- if (GS(tsep->id->name) == ID_OB) {
- /* Parented objects need to find which collection to unlink from. */
- TreeElement *te_parent = te->parent;
- while (tsep && GS(tsep->id->name) == ID_OB) {
- te_parent = te_parent->parent;
- tsep = te_parent ? TREESTORE(te_parent) : NULL;
+ if (GS(tsep->id->name) == ID_OB) {
+ /* Parented objects need to find which collection to unlink from. */
+ TreeElement *te_parent = te->parent;
+ while (tsep && GS(tsep->id->name) == ID_OB) {
+ te_parent = te_parent->parent;
+ tsep = te_parent ? TREESTORE(te_parent) : NULL;
+ }
}
- }
- if (tsep) {
- if (GS(tsep->id->name) == ID_GR) {
- Collection *parent = (Collection *)tsep->id;
- BKE_collection_object_remove(bmain, parent, ob, true);
- DEG_id_tag_update(&parent->id, ID_RECALC_COPY_ON_WRITE);
- DEG_relations_tag_update(bmain);
- }
- else if (GS(tsep->id->name) == ID_SCE) {
- Scene *scene = (Scene *)tsep->id;
- Collection *parent = BKE_collection_master(scene);
- BKE_collection_object_remove(bmain, parent, ob, true);
- DEG_id_tag_update(&scene->id, ID_RECALC_COPY_ON_WRITE);
- DEG_relations_tag_update(bmain);
+ if (tsep && tsep->id) {
+ if (GS(tsep->id->name) == ID_GR) {
+ Collection *parent = (Collection *)tsep->id;
+ BKE_collection_object_remove(bmain, parent, ob, true);
+ DEG_id_tag_update(&parent->id, ID_RECALC_COPY_ON_WRITE);
+ DEG_relations_tag_update(bmain);
+ }
+ else if (GS(tsep->id->name) == ID_SCE) {
+ Scene *scene = (Scene *)tsep->id;
+ Collection *parent = BKE_collection_master(scene);
+ BKE_collection_object_remove(bmain, parent, ob, true);
+ DEG_id_tag_update(&scene->id, ID_RECALC_COPY_ON_WRITE);
+ DEG_relations_tag_update(bmain);
+ }
}
}
}
diff --git a/source/blender/editors/space_outliner/outliner_tree.c b/source/blender/editors/space_outliner/outliner_tree.c
index d428a190549..cc062467dbe 100644
--- a/source/blender/editors/space_outliner/outliner_tree.c
+++ b/source/blender/editors/space_outliner/outliner_tree.c
@@ -515,7 +515,7 @@ static void outliner_add_object_contents(SpaceOutliner *soops,
}
/* duplicated group */
- if (ob->instance_collection) {
+ if (ob->instance_collection && (ob->transflag & OB_DUPLICOLLECTION)) {
outliner_add_element(soops, &te->subtree, ob->instance_collection, te, 0, 0);
}
}
@@ -1545,7 +1545,7 @@ static void outliner_make_object_parent_hierarchy_collections(SpaceOutliner *soo
if (!found) {
/* We add the child in the tree even if it is not in the collection.
- * We deliberately clear its subtree though, to make it less proeminent. */
+ * We deliberately clear its sub-tree though, to make it less prominent. */
TreeElement *child_ob_tree_element = outliner_add_element(
soops, &parent_ob_tree_element->subtree, child, parent_ob_tree_element, 0, 0);
outliner_free_tree(&child_ob_tree_element->subtree);
diff --git a/source/blender/editors/space_sequencer/sequencer_draw.c b/source/blender/editors/space_sequencer/sequencer_draw.c
index e53a3cb02a7..76c198b3d6b 100644
--- a/source/blender/editors/space_sequencer/sequencer_draw.c
+++ b/source/blender/editors/space_sequencer/sequencer_draw.c
@@ -2042,8 +2042,6 @@ void draw_timeline_seq(const bContext *C, ARegion *ar)
if (ed) {
/* draw the data */
draw_seq_strips(C, ed, ar);
- draw_cache_view(C);
-
/* text draw cached (for sequence names), in pixelspace now */
UI_view2d_text_cache_draw(ar);
}
@@ -2063,8 +2061,12 @@ void draw_timeline_seq(const bContext *C, ARegion *ar)
}
ED_markers_draw(C, marker_draw_flag);
- /* preview range */
UI_view2d_view_ortho(v2d);
+ /* draw cache on top of markers area */
+ if (ed) {
+ draw_cache_view(C);
+ }
+ /* preview range */
ANIM_draw_previewrange(C, v2d, 1);
/* overlap playhead */
diff --git a/source/blender/editors/space_text/text_autocomplete.c b/source/blender/editors/space_text/text_autocomplete.c
index c36175489b3..b6c660ae5b2 100644
--- a/source/blender/editors/space_text/text_autocomplete.c
+++ b/source/blender/editors/space_text/text_autocomplete.c
@@ -260,7 +260,7 @@ static void get_suggest_prefix(Text *text, int offset)
texttool_suggest_prefix(line + i, len);
}
-static void confirm_suggestion(Text *text, TextUndoBuf *utxt)
+static void confirm_suggestion(Text *text)
{
SuggItem *sel;
int i, over = 0;
@@ -285,7 +285,7 @@ static void confirm_suggestion(Text *text, TextUndoBuf *utxt)
// for (i = 0; i < skipleft; i++)
// txt_move_left(text, 0);
BLI_assert(memcmp(sel->name, &line[i], over) == 0);
- txt_insert_buf(text, utxt, sel->name + over);
+ txt_insert_buf(text, sel->name + over);
// for (i = 0; i < skipleft; i++)
// txt_move_right(text, 0);
@@ -308,8 +308,8 @@ static int text_autocomplete_invoke(bContext *C, wmOperator *op, const wmEvent *
ED_area_tag_redraw(CTX_wm_area(C));
if (texttool_suggest_first() == texttool_suggest_last()) {
- TextUndoBuf *utxt = ED_text_undo_push_init(C);
- confirm_suggestion(st->text, utxt);
+ ED_text_undo_push_init(C);
+ confirm_suggestion(st->text);
text_update_line_edited(st->text->curl);
text_autocomplete_free(C, op);
ED_undo_push(C, op->type->name);
@@ -371,8 +371,8 @@ static int text_autocomplete_modal(bContext *C, wmOperator *op, const wmEvent *e
case MIDDLEMOUSE:
if (event->val == KM_PRESS) {
if (text_do_suggest_select(st, ar)) {
- TextUndoBuf *utxt = ED_text_undo_push_init(C);
- confirm_suggestion(st->text, utxt);
+ ED_text_undo_push_init(C);
+ confirm_suggestion(st->text);
text_update_line_edited(st->text->curl);
ED_undo_push(C, op->type->name);
swallow = 1;
@@ -410,8 +410,8 @@ static int text_autocomplete_modal(bContext *C, wmOperator *op, const wmEvent *e
case PADENTER:
if (event->val == KM_PRESS) {
if (tools & TOOL_SUGG_LIST) {
- TextUndoBuf *utxt = ED_text_undo_push_init(C);
- confirm_suggestion(st->text, utxt);
+ ED_text_undo_push_init(C);
+ confirm_suggestion(st->text);
text_update_line_edited(st->text->curl);
ED_undo_push(C, op->type->name);
swallow = 1;
diff --git a/source/blender/editors/space_text/text_ops.c b/source/blender/editors/space_text/text_ops.c
index 63d4f3e3119..8f7bd83cbf4 100644
--- a/source/blender/editors/space_text/text_ops.c
+++ b/source/blender/editors/space_text/text_ops.c
@@ -241,6 +241,8 @@ static int text_new_exec(bContext *C, wmOperator *UNUSED(op))
PropertyRNA *prop;
text = BKE_text_add(bmain, "Text");
+ /* Texts have no user by default... Only the 'real' user flag. */
+ id_us_min(&text->id);
/* hook into UI */
UI_context_active_but_prop_get_templateID(C, &ptr, &prop);
@@ -307,6 +309,8 @@ static int text_open_exec(bContext *C, wmOperator *op)
RNA_string_get(op->ptr, "filepath", str);
text = BKE_text_load_ex(bmain, str, BKE_main_blendfile_path(bmain), internal);
+ /* Texts have no user by default... Only the 'real' user flag. */
+ id_us_min(&text->id);
if (!text) {
if (op->customdata) {
@@ -322,8 +326,6 @@ static int text_open_exec(bContext *C, wmOperator *op)
/* hook into UI */
pprop = op->customdata;
- id_us_ensure_real(&text->id);
-
if (pprop->prop) {
RNA_id_pointer_create(&text->id, &idptr);
RNA_property_pointer_set(&pprop->ptr, pprop->prop, idptr, NULL);
@@ -840,7 +842,7 @@ static int text_paste_exec(bContext *C, wmOperator *op)
text_drawcache_tag_update(CTX_wm_space_text(C), 0);
- TextUndoBuf *utxt = ED_text_undo_push_init(C);
+ ED_text_undo_push_init(C);
/* Convert clipboard content indentation to spaces if specified */
if (text->flags & TXT_TABSTOSPACES) {
@@ -849,7 +851,7 @@ static int text_paste_exec(bContext *C, wmOperator *op)
buf = new_buf;
}
- txt_insert_buf(text, utxt, buf);
+ txt_insert_buf(text, buf);
text_update_edited(text);
MEM_freeN(buf);
@@ -893,9 +895,9 @@ static int text_duplicate_line_exec(bContext *C, wmOperator *UNUSED(op))
{
Text *text = CTX_data_edit_text(C);
- TextUndoBuf *utxt = ED_text_undo_push_init(C);
+ ED_text_undo_push_init(C);
- txt_duplicate_line(text, utxt);
+ txt_duplicate_line(text);
WM_event_add_notifier(C, NC_TEXT | NA_EDITED, text);
@@ -932,7 +934,7 @@ static void txt_copy_clipboard(Text *text)
return;
}
- buf = txt_sel_to_buf(text);
+ buf = txt_sel_to_buf(text, NULL);
if (buf) {
WM_clipboard_text_set(buf, 0);
@@ -971,8 +973,8 @@ static int text_cut_exec(bContext *C, wmOperator *UNUSED(op))
txt_copy_clipboard(text);
- TextUndoBuf *utxt = ED_text_undo_push_init(C);
- txt_delete_selected(text, utxt);
+ ED_text_undo_push_init(C);
+ txt_delete_selected(text);
text_update_cursor_moved(C);
WM_event_add_notifier(C, NC_TEXT | NA_EDITED, text);
@@ -1008,14 +1010,14 @@ static int text_indent_exec(bContext *C, wmOperator *UNUSED(op))
text_drawcache_tag_update(CTX_wm_space_text(C), 0);
- TextUndoBuf *utxt = ED_text_undo_push_init(C);
+ ED_text_undo_push_init(C);
if (txt_has_sel(text)) {
txt_order_cursors(text, false);
- txt_indent(text, utxt);
+ txt_indent(text);
}
else {
- txt_add_char(text, utxt, '\t');
+ txt_add_char(text, '\t');
}
text_update_edited(text);
@@ -1049,10 +1051,10 @@ static int text_unindent_exec(bContext *C, wmOperator *UNUSED(op))
text_drawcache_tag_update(CTX_wm_space_text(C), 0);
- TextUndoBuf *utxt = ED_text_undo_push_init(C);
+ ED_text_undo_push_init(C);
txt_order_cursors(text, false);
- txt_unindent(text, utxt);
+ txt_unindent(text);
text_update_edited(text);
@@ -1090,15 +1092,15 @@ static int text_line_break_exec(bContext *C, wmOperator *UNUSED(op))
// double check tabs/spaces before splitting the line
curts = txt_setcurr_tab_spaces(text, space);
- TextUndoBuf *utxt = ED_text_undo_push_init(C);
- txt_split_curline(text, utxt);
+ ED_text_undo_push_init(C);
+ txt_split_curline(text);
for (a = 0; a < curts; a++) {
if (text->flags & TXT_TABSTOSPACES) {
- txt_add_char(text, utxt, ' ');
+ txt_add_char(text, ' ');
}
else {
- txt_add_char(text, utxt, '\t');
+ txt_add_char(text, '\t');
}
}
@@ -1139,10 +1141,10 @@ static int text_comment_exec(bContext *C, wmOperator *UNUSED(op))
if (txt_has_sel(text)) {
text_drawcache_tag_update(CTX_wm_space_text(C), 0);
- TextUndoBuf *utxt = ED_text_undo_push_init(C);
+ ED_text_undo_push_init(C);
txt_order_cursors(text, false);
- txt_comment(text, utxt);
+ txt_comment(text);
text_update_edited(text);
text_update_cursor_moved(C);
@@ -1177,10 +1179,10 @@ static int text_uncomment_exec(bContext *C, wmOperator *UNUSED(op))
if (txt_has_sel(text)) {
text_drawcache_tag_update(CTX_wm_space_text(C), 0);
- TextUndoBuf *utxt = ED_text_undo_push_init(C);
+ ED_text_undo_push_init(C);
txt_order_cursors(text, false);
- txt_uncomment(text, utxt);
+ txt_uncomment(text);
text_update_edited(text);
text_update_cursor_moved(C);
@@ -1446,9 +1448,9 @@ static int move_lines_exec(bContext *C, wmOperator *op)
Text *text = CTX_data_edit_text(C);
const int direction = RNA_enum_get(op->ptr, "direction");
- TextUndoBuf *utxt = ED_text_undo_push_init(C);
+ ED_text_undo_push_init(C);
- txt_move_lines(text, utxt, direction);
+ txt_move_lines(text, direction);
text_update_cursor_moved(C);
WM_event_add_notifier(C, NC_TEXT | NA_EDITED, text);
@@ -2230,13 +2232,13 @@ static int text_delete_exec(bContext *C, wmOperator *op)
}
}
- TextUndoBuf *utxt = ED_text_undo_push_init(C);
+ ED_text_undo_push_init(C);
if (type == DEL_PREV_WORD) {
if (txt_cursor_is_line_start(text)) {
- txt_backspace_char(text, utxt);
+ txt_backspace_char(text);
}
- txt_backspace_word(text, utxt);
+ txt_backspace_word(text);
}
else if (type == DEL_PREV_CHAR) {
@@ -2252,13 +2254,13 @@ static int text_delete_exec(bContext *C, wmOperator *op)
}
}
- txt_backspace_char(text, utxt);
+ txt_backspace_char(text);
}
else if (type == DEL_NEXT_WORD) {
if (txt_cursor_is_line_end(text)) {
- txt_delete_char(text, utxt);
+ txt_delete_char(text);
}
- txt_delete_word(text, utxt);
+ txt_delete_word(text);
}
else if (type == DEL_NEXT_CHAR) {
@@ -2274,7 +2276,7 @@ static int text_delete_exec(bContext *C, wmOperator *op)
}
}
- txt_delete_char(text, utxt);
+ txt_delete_char(text);
}
text_update_line_edited(text->curl);
@@ -2994,7 +2996,7 @@ static void text_cursor_set_exit(bContext *C, wmOperator *op)
char *buffer;
if (txt_has_sel(text)) {
- buffer = txt_sel_to_buf(text);
+ buffer = txt_sel_to_buf(text, NULL);
WM_clipboard_text_set(buffer, 1);
MEM_freeN(buffer);
}
@@ -3190,18 +3192,18 @@ static int text_insert_exec(bContext *C, wmOperator *op)
str = RNA_string_get_alloc(op->ptr, "text", NULL, 0);
- TextUndoBuf *utxt = ED_text_undo_push_init(C);
+ ED_text_undo_push_init(C);
if (st && st->overwrite) {
while (str[i]) {
code = BLI_str_utf8_as_unicode_step(str, &i);
- done |= txt_replace_char(text, utxt, code);
+ done |= txt_replace_char(text, code);
}
}
else {
while (str[i]) {
code = BLI_str_utf8_as_unicode_step(str, &i);
- done |= txt_add_char(text, utxt, code);
+ done |= txt_add_char(text, code);
}
}
@@ -3308,7 +3310,7 @@ static int text_find_and_replace(bContext *C, wmOperator *op, short mode)
/* Replace current */
if (mode != TEXT_FIND && txt_has_sel(text)) {
- tmp = txt_sel_to_buf(text);
+ tmp = txt_sel_to_buf(text, NULL);
if (flags & ST_MATCH_CASE) {
found = STREQ(st->findstr, tmp);
@@ -3319,8 +3321,8 @@ static int text_find_and_replace(bContext *C, wmOperator *op, short mode)
if (found) {
if (mode == TEXT_REPLACE) {
- TextUndoBuf *utxt = ED_text_undo_push_init(C);
- txt_insert_buf(text, utxt, st->replacestr);
+ ED_text_undo_push_init(C);
+ txt_insert_buf(text, st->replacestr);
if (text->curl && text->curl->format) {
MEM_freeN(text->curl->format);
text->curl->format = NULL;
@@ -3406,7 +3408,7 @@ static int text_find_set_selected_exec(bContext *C, wmOperator *op)
Text *text = CTX_data_edit_text(C);
char *tmp;
- tmp = txt_sel_to_buf(text);
+ tmp = txt_sel_to_buf(text, NULL);
BLI_strncpy(st->findstr, tmp, ST_MAX_FIND_STR);
MEM_freeN(tmp);
@@ -3437,7 +3439,7 @@ static int text_replace_set_selected_exec(bContext *C, wmOperator *UNUSED(op))
Text *text = CTX_data_edit_text(C);
char *tmp;
- tmp = txt_sel_to_buf(text);
+ tmp = txt_sel_to_buf(text, NULL);
BLI_strncpy(st->replacestr, tmp, ST_MAX_FIND_STR);
MEM_freeN(tmp);
diff --git a/source/blender/editors/space_text/text_undo.c b/source/blender/editors/space_text/text_undo.c
index 7db97f15a68..6ecb2b731b0 100644
--- a/source/blender/editors/space_text/text_undo.c
+++ b/source/blender/editors/space_text/text_undo.c
@@ -25,6 +25,7 @@
#include "DNA_text_types.h"
+#include "BLI_array_store.h"
#include "BLI_array_utils.h"
#include "BLT_translation.h"
@@ -35,6 +36,7 @@
#include "BKE_report.h"
#include "BKE_text.h"
#include "BKE_undo_system.h"
+#include "BKE_main.h"
#include "WM_api.h"
#include "WM_types.h"
@@ -53,18 +55,32 @@
#include "text_intern.h"
#include "text_format.h"
-/* TODO(campbell): undo_system: move text undo out of text block. */
-
/* -------------------------------------------------------------------- */
/** \name Implements ED Undo System
* \{ */
+#define ARRAY_CHUNK_SIZE 128
+
typedef struct TextUndoStep {
UndoStep step;
UndoRefID_Text text_ref;
- TextUndoBuf data;
+ struct {
+ BArrayState *state;
+ int buf_len;
+ } data;
+
+ struct {
+ int line, line_select;
+ int column, column_select;
+ } cursor;
+
} TextUndoStep;
+static struct {
+ BArrayStore *buffer_store;
+ int users;
+} g_text_buffers = {NULL};
+
static bool text_undosys_poll(bContext *UNUSED(C))
{
/* Only use when operators initialized. */
@@ -77,12 +93,8 @@ static void text_undosys_step_encode_init(struct bContext *C, UndoStep *us_p)
TextUndoStep *us = (TextUndoStep *)us_p;
BLI_assert(BLI_array_is_zeroed(&us->data, 1));
- UNUSED_VARS(C);
+ UNUSED_VARS(C, us);
/* XXX, use to set the undo type only. */
-
- us->data.buf = NULL;
- us->data.len = 0;
- us->data.pos = -1;
}
static bool text_undosys_step_encode(struct bContext *C,
@@ -93,97 +105,71 @@ static bool text_undosys_step_encode(struct bContext *C,
Text *text = CTX_data_edit_text(C);
- /* No undo data was generated. Hint, use global undo here. */
- if ((us->data.pos == -1) || (us->data.buf == NULL)) {
- return false;
- }
+ int buf_len = 0;
- us_p->is_applied = true;
-
- us->text_ref.ptr = text;
+ uchar *buf = (uchar *)txt_to_buf_for_undo(text, &buf_len);
+ if (g_text_buffers.buffer_store == NULL) {
+ g_text_buffers.buffer_store = BLI_array_store_create(1, ARRAY_CHUNK_SIZE);
+ }
+ g_text_buffers.users += 1;
+ const size_t total_size_prev = BLI_array_store_calc_size_compacted_get(
+ g_text_buffers.buffer_store);
- us->step.data_size = us->data.len;
+ us->data.state = BLI_array_store_state_add(g_text_buffers.buffer_store, buf, buf_len, NULL);
+ MEM_freeN(buf);
- return true;
-}
+ us->cursor.line = txt_get_span(text->lines.first, text->curl);
+ us->cursor.column = text->curc;
-static void text_undosys_step_decode_undo_impl(Text *text, TextUndoStep *us)
-{
- BLI_assert(us->step.is_applied == true);
- TextUndoBuf data = us->data;
- while (data.pos > -1) {
- txt_do_undo(text, &data);
+ if (txt_has_sel(text)) {
+ us->cursor.line_select = (text->curl == text->sell) ?
+ us->cursor.line :
+ txt_get_span(text->lines.first, text->sell);
+ us->cursor.column_select = text->selc;
}
- BLI_assert(data.pos == -1);
- us->step.is_applied = false;
-}
-
-static void text_undosys_step_decode_redo_impl(Text *text, TextUndoStep *us)
-{
- BLI_assert(us->step.is_applied == false);
- TextUndoBuf data = us->data;
- data.pos = -1;
- while (data.pos < us->data.pos) {
- txt_do_redo(text, &data);
+ else {
+ us->cursor.line_select = us->cursor.line;
+ us->cursor.column_select = us->cursor.column;
}
- BLI_assert(data.pos == us->data.pos);
- us->step.is_applied = true;
-}
-static void text_undosys_step_decode_undo(Text *text, TextUndoStep *us)
-{
- TextUndoStep *us_iter = us;
- while (us_iter->step.next && (us_iter->step.next->type == us_iter->step.type)) {
- if (us_iter->step.next->is_applied == false) {
- break;
- }
- us_iter = (TextUndoStep *)us_iter->step.next;
- }
- while (us_iter != us) {
- text_undosys_step_decode_undo_impl(text, us_iter);
- us_iter = (TextUndoStep *)us_iter->step.prev;
- }
-}
+ us_p->is_applied = true;
-static void text_undosys_step_decode_redo(Text *text, TextUndoStep *us)
-{
- TextUndoStep *us_iter = us;
- while (us_iter->step.prev && (us_iter->step.prev->type == us_iter->step.type)) {
- if (us_iter->step.prev->is_applied == true) {
- break;
- }
- us_iter = (TextUndoStep *)us_iter->step.prev;
- }
- while (us_iter && (us_iter->step.is_applied == false)) {
- text_undosys_step_decode_redo_impl(text, us_iter);
- if (us_iter == us) {
- break;
- }
- us_iter = (TextUndoStep *)us_iter->step.next;
- }
+ us->text_ref.ptr = text;
+
+ us->step.data_size = BLI_array_store_calc_size_compacted_get(g_text_buffers.buffer_store) -
+ total_size_prev;
+
+ return true;
}
static void text_undosys_step_decode(struct bContext *C,
struct Main *UNUSED(bmain),
UndoStep *us_p,
- int dir)
+ int UNUSED(dir),
+ bool UNUSED(is_final))
{
TextUndoStep *us = (TextUndoStep *)us_p;
Text *text = us->text_ref.ptr;
+ size_t buf_len;
- if (dir < 0) {
- text_undosys_step_decode_undo(text, us);
+ {
+ const uchar *buf = BLI_array_store_state_data_get_alloc(us->data.state, &buf_len);
+ txt_from_buf_for_undo(text, (const char *)buf, buf_len);
+ MEM_freeN((void *)buf);
}
- else {
- text_undosys_step_decode_redo(text, us);
+
+ const bool has_select = ((us->cursor.line != us->cursor.line_select) ||
+ (us->cursor.column != us->cursor.column_select));
+ if (has_select) {
+ txt_move_to(text, us->cursor.line_select, us->cursor.column_select, false);
}
+ txt_move_to(text, us->cursor.line, us->cursor.column, has_select);
SpaceText *st = CTX_wm_space_text(C);
if (st) {
/* Not essential, always show text being undo where possible. */
st->text = text;
}
- text_update_edited(text);
text_update_cursor_moved(C);
text_drawcache_tag_update(st, 1);
WM_event_add_notifier(C, NC_TEXT | NA_EDITED, text);
@@ -192,7 +178,14 @@ static void text_undosys_step_decode(struct bContext *C,
static void text_undosys_step_free(UndoStep *us_p)
{
TextUndoStep *us = (TextUndoStep *)us_p;
- MEM_SAFE_FREE(us->data.buf);
+
+ BLI_array_store_state_remove(g_text_buffers.buffer_store, us->data.state);
+
+ g_text_buffers.users -= 1;
+ if (g_text_buffers.users == 0) {
+ BLI_array_store_destroy(g_text_buffers.buffer_store);
+ g_text_buffers.buffer_store = NULL;
+ }
}
static void text_undosys_foreach_ID_ref(UndoStep *us_p,
@@ -228,12 +221,16 @@ void ED_text_undosys_type(UndoType *ut)
* \{ */
/* Use operator system to finish the undo step. */
-TextUndoBuf *ED_text_undo_push_init(bContext *C)
+UndoStep *ED_text_undo_push_init(bContext *C)
{
UndoStack *ustack = ED_undo_stack_get();
- UndoStep *us_p = BKE_undosys_step_push_init_with_type(ustack, C, NULL, BKE_UNDOSYS_TYPE_TEXT);
- TextUndoStep *us = (TextUndoStep *)us_p;
- return &us->data;
+ Main *bmain = CTX_data_main(C);
+ wmWindowManager *wm = bmain->wm.first;
+ if (wm->op_undo_depth <= 1) {
+ UndoStep *us_p = BKE_undosys_step_push_init_with_type(ustack, C, NULL, BKE_UNDOSYS_TYPE_TEXT);
+ return us_p;
+ }
+ return NULL;
}
/** \} */
diff --git a/source/blender/editors/space_userpref/userpref_ops.c b/source/blender/editors/space_userpref/userpref_ops.c
index 04ef2ed8118..1ec459ccfca 100644
--- a/source/blender/editors/space_userpref/userpref_ops.c
+++ b/source/blender/editors/space_userpref/userpref_ops.c
@@ -26,6 +26,8 @@
#include "DNA_screen_types.h"
#include "BKE_context.h"
+#include "BKE_global.h"
+#include "BKE_main.h"
#include "BKE_report.h"
#include "RNA_types.h"
@@ -45,8 +47,10 @@
static int reset_default_theme_exec(bContext *C, wmOperator *UNUSED(op))
{
+ Main *bmain = CTX_data_main(C);
UI_theme_init_default();
UI_style_init_default();
+ WM_reinit_gizmomap_all(bmain);
WM_event_add_notifier(C, NC_WINDOW, NULL);
U.runtime.is_dirty = true;
return OPERATOR_FINISHED;
diff --git a/source/blender/editors/space_view3d/space_view3d.c b/source/blender/editors/space_view3d/space_view3d.c
index c1891865d6d..57b98ffeda3 100644
--- a/source/blender/editors/space_view3d/space_view3d.c
+++ b/source/blender/editors/space_view3d/space_view3d.c
@@ -662,7 +662,10 @@ static void view3d_widgets(void)
WM_gizmogrouptype_append_and_link(gzmap_type, VIEW3D_GGT_camera);
WM_gizmogrouptype_append_and_link(gzmap_type, VIEW3D_GGT_camera_view);
WM_gizmogrouptype_append_and_link(gzmap_type, VIEW3D_GGT_empty_image);
+ /* TODO(campbell): Not working well enough, disable for now. */
+#if 0
WM_gizmogrouptype_append_and_link(gzmap_type, VIEW3D_GGT_armature_spline);
+#endif
WM_gizmogrouptype_append(VIEW3D_GGT_xform_gizmo);
WM_gizmogrouptype_append(VIEW3D_GGT_xform_cage);
diff --git a/source/blender/editors/space_view3d/view3d_draw.c b/source/blender/editors/space_view3d/view3d_draw.c
index d14a6870a6c..eef36dae86a 100644
--- a/source/blender/editors/space_view3d/view3d_draw.c
+++ b/source/blender/editors/space_view3d/view3d_draw.c
@@ -169,7 +169,13 @@ void ED_view3d_update_viewmat(Depsgraph *depsgraph,
v2[2] = rv3d->persmat[2][1];
len_px = 2.0f / sqrtf(min_ff(len_squared_v3(v1), len_squared_v3(v2)));
- len_sc = (float)MAX2(ar->winx, ar->winy);
+
+ if (rect) {
+ len_sc = (float)max_ii(BLI_rcti_size_x(rect), BLI_rcti_size_y(rect));
+ }
+ else {
+ len_sc = (float)MAX2(ar->winx, ar->winy);
+ }
rv3d->pixsize = len_px / len_sc;
}
@@ -798,7 +804,11 @@ void ED_view3d_draw_depth(Depsgraph *depsgraph, ARegion *ar, View3D *v3d, bool a
GPU_depth_test(true);
GPUViewport *viewport = WM_draw_region_get_viewport(ar, 0);
- DRW_draw_depth_loop(depsgraph, ar, v3d, viewport);
+ /* When Blender is starting, a click event can trigger a depth test while the viewport is not
+ * yet available. */
+ if (viewport != NULL) {
+ DRW_draw_depth_loop(depsgraph, ar, v3d, viewport);
+ }
if (rv3d->rflag & RV3D_CLIPPING) {
ED_view3d_clipping_disable();
diff --git a/source/blender/editors/space_view3d/view3d_edit.c b/source/blender/editors/space_view3d/view3d_edit.c
index b6eb57a3c81..7c4b35507b9 100644
--- a/source/blender/editors/space_view3d/view3d_edit.c
+++ b/source/blender/editors/space_view3d/view3d_edit.c
@@ -4661,6 +4661,7 @@ static int background_image_add_invoke(bContext *C, wmOperator *op, const wmEven
cam->flag |= CAM_SHOW_BG_IMAGE;
WM_event_add_notifier(C, NC_CAMERA | ND_DRAW_RENDER_VIEWPORT, cam);
+ DEG_id_tag_update(&cam->id, ID_RECALC_COPY_ON_WRITE);
return OPERATOR_FINISHED;
}
@@ -4721,6 +4722,8 @@ static int background_image_remove_exec(bContext *C, wmOperator *op)
BKE_camera_background_image_remove(cam, bgpic_rem);
WM_event_add_notifier(C, NC_CAMERA | ND_DRAW_RENDER_VIEWPORT, cam);
+ DEG_id_tag_update(&cam->id, ID_RECALC_COPY_ON_WRITE);
+
return OPERATOR_FINISHED;
}
else {
@@ -4944,7 +4947,7 @@ void ED_view3d_cursor3d_position_rotation(bContext *C,
ray_no,
NULL,
&ob_dummy,
- obmat)) {
+ obmat) != 0) {
if (use_depth) {
copy_v3_v3(cursor_co, ray_co);
}
diff --git a/source/blender/editors/space_view3d/view3d_gizmo_preselect_type.c b/source/blender/editors/space_view3d/view3d_gizmo_preselect_type.c
index 9cbf179ab49..64697a59019 100644
--- a/source/blender/editors/space_view3d/view3d_gizmo_preselect_type.c
+++ b/source/blender/editors/space_view3d/view3d_gizmo_preselect_type.c
@@ -21,7 +21,7 @@
*
* Use for tools to hover over data before activation.
*
- * \note This is a slight mis-use of gizmo's, since clicking performs no action.
+ * \note This is a slight misuse of gizmo's, since clicking performs no action.
*/
#include "MEM_guardedalloc.h"
diff --git a/source/blender/editors/space_view3d/view3d_gizmo_ruler.c b/source/blender/editors/space_view3d/view3d_gizmo_ruler.c
index ebfd66008f7..e781e129540 100644
--- a/source/blender/editors/space_view3d/view3d_gizmo_ruler.c
+++ b/source/blender/editors/space_view3d/view3d_gizmo_ruler.c
@@ -113,6 +113,13 @@ typedef struct RulerInfo {
wmWindow *win;
ScrArea *sa;
ARegion *ar; /* re-assigned every modal update */
+
+ /* Track changes in state. */
+ struct {
+ bool do_snap;
+ bool do_thickness;
+ } drag_state_prev;
+
} RulerInfo;
/* -------------------------------------------------------------------- */
@@ -280,6 +287,7 @@ static void ruler_state_set(bContext *C, RulerInfo *ruler_info, int state)
/* pass */
}
else if (state == RULER_STATE_DRAG) {
+ memset(&ruler_info->drag_state_prev, 0x0, sizeof(ruler_info->drag_state_prev));
ruler_info->snap_context = ED_transform_snap_object_context_create_view3d(
bmain, CTX_data_scene(C), CTX_data_depsgraph(C), 0, ruler_info->ar, CTX_wm_view3d(C));
}
@@ -857,27 +865,43 @@ static int gizmo_ruler_test_select(bContext *UNUSED(C), wmGizmo *gz, const int m
static int gizmo_ruler_modal(bContext *C,
wmGizmo *gz,
const wmEvent *event,
- eWM_GizmoFlagTweak UNUSED(tweak_flag))
+ eWM_GizmoFlagTweak tweak_flag)
{
bool do_draw = false;
int exit_code = OPERATOR_RUNNING_MODAL;
RulerInfo *ruler_info = gz->parent_gzgroup->customdata;
RulerItem *ruler_item = (RulerItem *)gz;
ARegion *ar = CTX_wm_region(C);
+ bool do_cursor_update = false;
ruler_info->ar = ar;
switch (event->type) {
case MOUSEMOVE: {
- if (ruler_info->state == RULER_STATE_DRAG) {
- if (view3d_ruler_item_mousemove(
- ruler_info, ruler_item, event->mval, event->shift != 0, event->ctrl != 0)) {
- do_draw = true;
- }
- }
+ do_cursor_update = true;
break;
}
}
+
+ const bool do_snap = tweak_flag & WM_GIZMO_TWEAK_SNAP;
+ const bool do_thickness = tweak_flag & WM_GIZMO_TWEAK_PRECISE;
+ if ((ruler_info->drag_state_prev.do_snap != do_snap) ||
+ (ruler_info->drag_state_prev.do_thickness != do_thickness)) {
+ do_cursor_update = true;
+ }
+
+ if (do_cursor_update) {
+ if (ruler_info->state == RULER_STATE_DRAG) {
+ if (view3d_ruler_item_mousemove(
+ ruler_info, ruler_item, event->mval, do_thickness, do_snap)) {
+ do_draw = true;
+ }
+ }
+ }
+
+ ruler_info->drag_state_prev.do_snap = do_snap;
+ ruler_info->drag_state_prev.do_thickness = do_thickness;
+
if (do_draw) {
ED_region_tag_redraw(ar);
}
@@ -920,8 +944,7 @@ static int gizmo_ruler_invoke(bContext *C, wmGizmo *gz, const wmEvent *event)
}
/* update the new location */
- view3d_ruler_item_mousemove(
- ruler_info, ruler_item_pick, event->mval, event->shift != 0, event->ctrl != 0);
+ view3d_ruler_item_mousemove(ruler_info, ruler_item_pick, event->mval, false, false);
}
}
else {
diff --git a/source/blender/editors/space_view3d/view3d_iterators.c b/source/blender/editors/space_view3d/view3d_iterators.c
index 6ed0508f09f..2636062ed8b 100644
--- a/source/blender/editors/space_view3d/view3d_iterators.c
+++ b/source/blender/editors/space_view3d/view3d_iterators.c
@@ -38,6 +38,7 @@
#include "BKE_editmesh.h"
#include "BKE_mesh_runtime.h"
#include "BKE_mesh_iterators.h"
+#include "BKE_modifier.h"
#include "DEG_depsgraph.h"
#include "DEG_depsgraph_query.h"
@@ -293,8 +294,15 @@ void mesh_foreachScreenFace(
data.clip_flag = clip_flag;
BM_mesh_elem_table_ensure(vc->em->bm, BM_FACE);
- BKE_mesh_foreach_mapped_face_center(
- me, mesh_foreachScreenFace__mapFunc, &data, MESH_FOREACH_NOP);
+
+ if (modifiers_usesSubsurfFacedots(vc->scene, vc->obedit)) {
+ BKE_mesh_foreach_mapped_subdiv_face_center(
+ me, mesh_foreachScreenFace__mapFunc, &data, MESH_FOREACH_NOP);
+ }
+ else {
+ BKE_mesh_foreach_mapped_face_center(
+ me, mesh_foreachScreenFace__mapFunc, &data, MESH_FOREACH_NOP);
+ }
}
/* ------------------------------------------------------------------------ */
diff --git a/source/blender/editors/space_view3d/view3d_select.c b/source/blender/editors/space_view3d/view3d_select.c
index 3ff97cdd59a..61de61c8e31 100644
--- a/source/blender/editors/space_view3d/view3d_select.c
+++ b/source/blender/editors/space_view3d/view3d_select.c
@@ -1602,31 +1602,63 @@ static const EnumPropertyItem *object_select_menu_enum_itemf(bContext *C,
static int object_select_menu_exec(bContext *C, wmOperator *op)
{
const int name_index = RNA_enum_get(op->ptr, "name");
+ const bool extend = RNA_boolean_get(op->ptr, "extend");
+ const bool deselect = RNA_boolean_get(op->ptr, "deselect");
const bool toggle = RNA_boolean_get(op->ptr, "toggle");
bool changed = false;
const char *name = object_mouse_select_menu_data[name_index].idname;
- if (!toggle) {
- CTX_DATA_BEGIN (C, Base *, base, selectable_bases) {
- if ((base->flag & BASE_SELECTED) != 0) {
- ED_object_base_select(base, BA_DESELECT);
- changed = true;
- }
- }
- CTX_DATA_END;
- }
+ View3D *v3d = CTX_wm_view3d(C);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ const Base *oldbasact = BASACT(view_layer);
+ Base *basact = NULL;
CTX_DATA_BEGIN (C, Base *, base, selectable_bases) {
/* This is a bit dodgy, there should only be ONE object with this name,
* but library objects can mess this up. */
if (STREQ(name, base->object->id.name + 2)) {
- ED_object_base_activate(C, base);
- ED_object_base_select(base, BA_SELECT);
- changed = true;
+ basact = base;
+ break;
}
}
CTX_DATA_END;
+ if (basact == NULL) {
+ return OPERATOR_CANCELLED;
+ }
+ UNUSED_VARS_NDEBUG(v3d);
+ BLI_assert(BASE_SELECTABLE(v3d, basact));
+
+ if (extend) {
+ ED_object_base_select(basact, BA_SELECT);
+ changed = true;
+ }
+ else if (deselect) {
+ ED_object_base_select(basact, BA_DESELECT);
+ changed = true;
+ }
+ else if (toggle) {
+ if (basact->flag & BASE_SELECTED) {
+ if (basact == oldbasact) {
+ ED_object_base_select(basact, BA_DESELECT);
+ changed = true;
+ }
+ }
+ else {
+ ED_object_base_select(basact, BA_SELECT);
+ changed = true;
+ }
+ }
+ else {
+ object_deselect_all_except(view_layer, basact);
+ ED_object_base_select(basact, BA_SELECT);
+ changed = true;
+ }
+
+ if ((oldbasact != basact)) {
+ ED_object_base_activate(C, basact);
+ }
+
/* weak but ensures we activate menu again before using the enum */
memset(object_mouse_select_menu_data, 0, sizeof(object_mouse_select_menu_data));
@@ -1664,12 +1696,19 @@ void VIEW3D_OT_select_menu(wmOperatorType *ot)
RNA_def_property_flag(prop, PROP_HIDDEN | PROP_ENUM_NO_TRANSLATE);
ot->prop = prop;
- RNA_def_boolean(
- ot->srna, "toggle", 0, "Toggle", "Toggle selection instead of deselecting everything first");
+ RNA_def_boolean(ot->srna, "extend", 0, "Extend", "");
+ RNA_def_boolean(ot->srna, "deselect", 0, "Deselect", "");
+ RNA_def_boolean(ot->srna, "toggle", 0, "Toggle", "");
}
-static Base *object_mouse_select_menu(
- bContext *C, ViewContext *vc, uint *buffer, int hits, const int mval[2], bool toggle)
+static Base *object_mouse_select_menu(bContext *C,
+ ViewContext *vc,
+ uint *buffer,
+ int hits,
+ const int mval[2],
+ bool extend,
+ bool deselect,
+ bool toggle)
{
short baseCount = 0;
bool ok;
@@ -1739,6 +1778,8 @@ static Base *object_mouse_select_menu(
PointerRNA ptr;
WM_operator_properties_create_ptr(&ptr, ot);
+ RNA_boolean_set(&ptr, "extend", extend);
+ RNA_boolean_set(&ptr, "deselect", deselect);
RNA_boolean_set(&ptr, "toggle", toggle);
WM_operator_name_call_ptr(C, ot, WM_OP_INVOKE_DEFAULT, &ptr);
WM_operator_properties_free(&ptr);
@@ -2122,7 +2163,7 @@ static bool ed_object_select_pick(bContext *C,
/* note; shift+alt goes to group-flush-selecting */
if (enumerate) {
- basact = object_mouse_select_menu(C, &vc, NULL, 0, mval, toggle);
+ basact = object_mouse_select_menu(C, &vc, NULL, 0, mval, extend, deselect, toggle);
}
else {
base = startbase;
@@ -2190,7 +2231,7 @@ static bool ed_object_select_pick(bContext *C,
/* note; shift+alt goes to group-flush-selecting */
if (enumerate) {
- basact = object_mouse_select_menu(C, &vc, buffer, hits, mval, toggle);
+ basact = object_mouse_select_menu(C, &vc, buffer, hits, mval, extend, deselect, toggle);
}
else {
basact = mouse_select_eval_buffer(&vc, buffer, hits, startbase, has_bones, do_nearest);
@@ -2278,11 +2319,17 @@ static bool ed_object_select_pick(bContext *C,
retval = true;
WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, basact->object);
WM_event_add_notifier(C, NC_OBJECT | ND_BONE_ACTIVE, basact->object);
+ DEG_id_tag_update(&scene->id, ID_RECALC_BASE_FLAGS);
- /* in weightpaint, we use selected bone to select vertexgroup,
- * so no switch to new active object */
+ /* In weight-paint, we use selected bone to select vertex-group,
+ * so don't switch to new active object. */
if (oldbasact && (oldbasact->object->mode & OB_MODE_WEIGHT_PAINT)) {
- /* prevent activating */
+ /* Prevent activating.
+ * Selection causes this to be considered the 'active' pose in weight-paint mode.
+ * Eventually this limitation may be removed.
+ * For now, de-select all other pose objects deforming this mesh. */
+ ED_armature_pose_select_in_wpaint_mode(view_layer, basact);
+
basact = NULL;
}
}
@@ -2353,7 +2400,7 @@ static bool ed_object_select_pick(bContext *C,
}
else {
/* When enabled, this puts other objects out of multi pose-mode. */
- if (is_pose_mode == false) {
+ if (is_pose_mode == false || (basact->object->mode & OB_MODE_POSE) == 0) {
object_deselect_all_except(view_layer, basact);
ED_object_base_select(basact, BA_SELECT);
}
@@ -2507,6 +2554,9 @@ static int view3d_select_exec(bContext *C, wmOperator *op)
/* pass */
}
}
+ if (retval) {
+ WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
+ }
}
else if (obact && obact->mode & OB_MODE_PARTICLE_EDIT) {
retval = PE_mouse_particles(C, location, extend, deselect, toggle);
diff --git a/source/blender/editors/space_view3d/view3d_snap.c b/source/blender/editors/space_view3d/view3d_snap.c
index 51dc14f3dff..0103fd0df53 100644
--- a/source/blender/editors/space_view3d/view3d_snap.c
+++ b/source/blender/editors/space_view3d/view3d_snap.c
@@ -634,14 +634,12 @@ static bool snap_curs_to_sel_ex(bContext *C, float cursor[3])
TransVertStore tvs = {NULL};
TransVert *tv;
float bmat[3][3], vec[3], min[3], max[3], centroid[3];
- int count, a;
+ int count = 0;
- count = 0;
INIT_MINMAX(min, max);
zero_v3(centroid);
if (obedit) {
- int global_transverts_tot = 0;
ViewLayer *view_layer = CTX_data_view_layer(C);
uint objects_len = 0;
Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(
@@ -662,13 +660,13 @@ static bool snap_curs_to_sel_ex(bContext *C, float cursor[3])
ED_transverts_create_from_obedit(&tvs, obedit, TM_ALL_JOINTS | TM_SKIP_HANDLES);
}
- global_transverts_tot += tvs.transverts_tot;
+ count += tvs.transverts_tot;
if (tvs.transverts_tot != 0) {
Object *obedit_eval = DEG_get_evaluated_object(depsgraph, obedit);
copy_m3_m4(bmat, obedit_eval->obmat);
tv = tvs.transverts;
- for (a = 0; a < tvs.transverts_tot; a++, tv++) {
+ for (int i = 0; i < tvs.transverts_tot; i++, tv++) {
copy_v3_v3(vec, tv->loc);
mul_m3_v3(bmat, vec);
add_v3_v3(vec, obedit_eval->obmat[3]);
@@ -679,14 +677,6 @@ static bool snap_curs_to_sel_ex(bContext *C, float cursor[3])
ED_transverts_free(&tvs);
}
MEM_freeN(objects);
-
- if (scene->toolsettings->transform_pivot_point == V3D_AROUND_CENTER_MEDIAN) {
- mul_v3_fl(centroid, 1.0f / (float)global_transverts_tot);
- copy_v3_v3(cursor, centroid);
- }
- else {
- mid_v3_v3v3(cursor, min, max);
- }
}
else {
Object *obact = CTX_data_active_object(C);
@@ -725,18 +715,18 @@ static bool snap_curs_to_sel_ex(bContext *C, float cursor[3])
}
FOREACH_SELECTED_OBJECT_END;
}
+ }
- if (count == 0) {
- return false;
- }
+ if (count == 0) {
+ return false;
+ }
- if (scene->toolsettings->transform_pivot_point == V3D_AROUND_CENTER_MEDIAN) {
- mul_v3_fl(centroid, 1.0f / (float)count);
- copy_v3_v3(cursor, centroid);
- }
- else {
- mid_v3_v3v3(cursor, min, max);
- }
+ if (scene->toolsettings->transform_pivot_point == V3D_AROUND_CENTER_MEDIAN) {
+ mul_v3_fl(centroid, 1.0f / (float)count);
+ copy_v3_v3(cursor, centroid);
+ }
+ else {
+ mid_v3_v3v3(cursor, min, max);
}
return true;
}
diff --git a/source/blender/editors/space_view3d/view3d_view.c b/source/blender/editors/space_view3d/view3d_view.c
index 5865efa0ffa..c0902cd1cd5 100644
--- a/source/blender/editors/space_view3d/view3d_view.c
+++ b/source/blender/editors/space_view3d/view3d_view.c
@@ -30,6 +30,7 @@
#include "BLI_math.h"
#include "BLI_rect.h"
#include "BLI_utildefines.h"
+#include "BLI_linklist.h"
#include "BKE_action.h"
#include "BKE_camera.h"
@@ -38,6 +39,7 @@
#include "BKE_global.h"
#include "BKE_layer.h"
#include "BKE_main.h"
+#include "BKE_modifier.h"
#include "BKE_report.h"
#include "BKE_scene.h"
@@ -962,8 +964,8 @@ static bool drw_select_filter_object_mode_lock(Object *ob, void *user_data)
* we want to select pose bones (this doesn't switch modes). */
static bool drw_select_filter_object_mode_lock_for_weight_paint(Object *ob, void *user_data)
{
- const Object *ob_pose = user_data;
- return (DEG_get_original_object(ob) == ob_pose);
+ LinkNode *ob_pose_list = user_data;
+ return ob_pose_list && (BLI_linklist_index(ob_pose_list, DEG_get_original_object(ob)) != -1);
}
/**
@@ -1044,10 +1046,22 @@ int view3d_opengl_select(ViewContext *vc,
case VIEW3D_SELECT_FILTER_WPAINT_POSE_MODE_LOCK: {
Object *obact = vc->obact;
BLI_assert(obact && (obact->mode & OB_MODE_WEIGHT_PAINT));
- Object *ob_pose = BKE_object_pose_armature_get(obact);
+ /* While this uses 'alloca' in a loop (which we typically avoid),
+ * the number of items is nearly always 1, maybe 2..3 in rare cases. */
+ LinkNode *ob_pose_list = NULL;
+ VirtualModifierData virtualModifierData;
+ const ModifierData *md = modifiers_getVirtualModifierList(obact, &virtualModifierData);
+ for (; md; md = md->next) {
+ if (md->type == eModifierType_Armature) {
+ ArmatureModifierData *amd = (ArmatureModifierData *)md;
+ if (amd->object && (amd->object->mode & OB_MODE_POSE)) {
+ BLI_linklist_prepend_alloca(&ob_pose_list, amd->object);
+ }
+ }
+ }
object_filter.fn = drw_select_filter_object_mode_lock_for_weight_paint;
- object_filter.user_data = ob_pose;
+ object_filter.user_data = ob_pose_list;
break;
}
case VIEW3D_SELECT_FILTER_NOP:
diff --git a/source/blender/editors/transform/transform.c b/source/blender/editors/transform/transform.c
index 5b3f7d85b43..a316567fc63 100644
--- a/source/blender/editors/transform/transform.c
+++ b/source/blender/editors/transform/transform.c
@@ -617,6 +617,8 @@ static void viewRedrawForce(const bContext *C, TransInfo *t)
}
else if (t->spacetype == SPACE_SEQ) {
WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, NULL);
+ /* Keyframes on strips has been moved, so make sure related editos are informed. */
+ WM_event_add_notifier(C, NC_ANIMATION, NULL);
}
else if (t->spacetype == SPACE_IMAGE) {
if (t->options & CTX_MASK) {
@@ -6440,6 +6442,8 @@ static void slide_origdata_create_data(TransDataContainer *tc,
layer_index_dst = 0;
+ /* TODO: We don't need `sod->layer_math_map` when there are no loops linked
+ * to one of the sliding vertices. */
if (CustomData_has_math(&bm->ldata)) {
/* over alloc, only 'math' layers are indexed */
sod->layer_math_map = MEM_mallocN(bm->ldata.totlayer * sizeof(int), __func__);
@@ -6583,7 +6587,7 @@ static void slide_origdata_interp_data_vert(SlideOrigData *sod,
}
}
- if (sod->layer_math_map_num) {
+ if (sod->layer_math_map_num && sv->cd_loop_groups) {
if (do_loop_weight) {
for (j = 0; j < sod->layer_math_map_num; j++) {
BM_vert_loop_groups_data_layer_merge_weights(
@@ -6699,9 +6703,28 @@ static void slide_origdata_free_date(SlideOrigData *sod)
/** \name Transform Edge Slide
* \{ */
+/**
+ * Get the first valid EdgeSlideData.
+ *
+ * Note we cannot trust TRANS_DATA_CONTAINER_FIRST_OK because of multi-object that
+ * may leave items with invalid custom data in the transform data container.
+ */
+static EdgeSlideData *edgeSlideFirstGet(TransInfo *t)
+{
+ FOREACH_TRANS_DATA_CONTAINER (t, tc) {
+ EdgeSlideData *sld = tc->custom.mode.data;
+ if (sld == NULL) {
+ continue;
+ }
+ return sld;
+ }
+ BLI_assert(!"Should never happen, at least one EdgeSlideData should be valid");
+ return NULL;
+}
+
static void calcEdgeSlideCustomPoints(struct TransInfo *t)
{
- EdgeSlideData *sld = TRANS_DATA_CONTAINER_FIRST_OK(t)->custom.mode.data;
+ EdgeSlideData *sld = edgeSlideFirstGet(t);
setCustomPoints(t, &t->mouse, sld->mval_end, sld->mval_start);
@@ -7675,10 +7698,14 @@ void projectEdgeSlideData(TransInfo *t, bool is_final)
{
FOREACH_TRANS_DATA_CONTAINER (t, tc) {
EdgeSlideData *sld = tc->custom.mode.data;
- SlideOrigData *sod = &sld->orig_data;
+ if (sld == NULL) {
+ continue;
+ }
+
+ SlideOrigData *sod = &sld->orig_data;
if (sod->use_origfaces == false) {
- return;
+ continue;
}
slide_origdata_interp_data(tc->obedit,
@@ -7701,7 +7728,7 @@ void freeEdgeSlideVerts(TransInfo *UNUSED(t),
{
EdgeSlideData *sld = custom_data->data;
- if (!sld) {
+ if (sld == NULL) {
return;
}
@@ -7843,9 +7870,9 @@ static eRedrawFlag handleEventEdgeSlide(struct TransInfo *t, const struct wmEven
static void drawEdgeSlide(TransInfo *t)
{
- if ((t->mode == TFM_EDGE_SLIDE) && TRANS_DATA_CONTAINER_FIRST_OK(t)->custom.mode.data) {
+ if ((t->mode == TFM_EDGE_SLIDE) && edgeSlideFirstGet(t)) {
const EdgeSlideParams *slp = t->custom.mode.data;
- EdgeSlideData *sld = TRANS_DATA_CONTAINER_FIRST_OK(t)->custom.mode.data;
+ EdgeSlideData *sld = edgeSlideFirstGet(t);
const bool is_clamp = !(t->flag & T_ALT_TRANSFORM);
/* Even mode */
@@ -7964,7 +7991,7 @@ static void drawEdgeSlide(TransInfo *t)
static void doEdgeSlide(TransInfo *t, float perc)
{
EdgeSlideParams *slp = t->custom.mode.data;
- EdgeSlideData *sld_active = TRANS_DATA_CONTAINER_FIRST_OK(t)->custom.mode.data;
+ EdgeSlideData *sld_active = edgeSlideFirstGet(t);
slp->perc = perc;
@@ -7975,6 +8002,11 @@ static void doEdgeSlide(TransInfo *t, float perc)
const float perc_final = fabsf(perc);
FOREACH_TRANS_DATA_CONTAINER (t, tc) {
EdgeSlideData *sld = tc->custom.mode.data;
+
+ if (sld == NULL) {
+ continue;
+ }
+
TransDataEdgeSlideVert *sv = sld->sv;
for (int i = 0; i < sld->totsv; i++, sv++) {
madd_v3_v3v3fl(sv->v->co, sv->v_co_orig, sv->dir_side[side_index], perc_final);
@@ -7988,6 +8020,11 @@ static void doEdgeSlide(TransInfo *t, float perc)
const int side_index = sld_active->curr_side_unclamp;
FOREACH_TRANS_DATA_CONTAINER (t, tc) {
EdgeSlideData *sld = tc->custom.mode.data;
+
+ if (sld == NULL) {
+ continue;
+ }
+
TransDataEdgeSlideVert *sv = sld->sv;
for (int i = 0; i < sld->totsv; i++, sv++) {
float dir_flip[3];
@@ -8024,6 +8061,11 @@ static void doEdgeSlide(TransInfo *t, float perc)
FOREACH_TRANS_DATA_CONTAINER (t, tc) {
EdgeSlideData *sld = tc->custom.mode.data;
+
+ if (sld == NULL) {
+ continue;
+ }
+
TransDataEdgeSlideVert *sv = sld->sv;
for (int i = 0; i < sld->totsv; i++, sv++) {
if (sv->edge_len > FLT_EPSILON) {
diff --git a/source/blender/editors/transform/transform_constraints.c b/source/blender/editors/transform/transform_constraints.c
index 06851451461..208242d53b3 100644
--- a/source/blender/editors/transform/transform_constraints.c
+++ b/source/blender/editors/transform/transform_constraints.c
@@ -235,8 +235,7 @@ static void axisProjection(const TransInfo *t,
normalize_v3_v3_length(out, axis, -factor);
}
else {
- float v[3], i1[3], i2[3];
- float v2[3], v4[3];
+ float v[3];
float norm_center[3];
float plane[3];
@@ -261,14 +260,17 @@ static void axisProjection(const TransInfo *t,
}
}
else {
- add_v3_v3v3(v2, t_con_center, axis);
- add_v3_v3v3(v4, v, norm);
-
- isect_line_line_v3(t_con_center, v2, v, v4, i1, i2);
-
- sub_v3_v3v3(v, i2, v);
-
- sub_v3_v3v3(out, i1, t_con_center);
+ /* Use ray-ray intersection instead of line-line because this gave
+ * precision issues adding small values to large numbers. */
+ float mul;
+ if (isect_ray_ray_v3(v, norm, t_con_center, axis, &mul, NULL)) {
+ madd_v3_v3v3fl(out, t_con_center, axis, mul);
+ sub_v3_v3(out, t_con_center);
+ }
+ else {
+ /* In practice this should never fail. */
+ BLI_assert(0);
+ }
/* possible some values become nan when
* viewpoint and object are both zero */
@@ -863,9 +865,9 @@ void drawPropCircle(const struct bContext *C, TransInfo *t)
immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
immUniformThemeColor(TH_GRID);
- set_inverted_drawing(1);
+ GPU_logic_op_invert_set(true);
imm_drawcircball(t->center_global, t->prop_size, imat, pos);
- set_inverted_drawing(0);
+ GPU_logic_op_invert_set(false);
immUnbindProgram();
diff --git a/source/blender/editors/transform/transform_conversions.c b/source/blender/editors/transform/transform_conversions.c
index 1ed0d5e9221..d13c0f8e8f1 100644
--- a/source/blender/editors/transform/transform_conversions.c
+++ b/source/blender/editors/transform/transform_conversions.c
@@ -1289,7 +1289,6 @@ static void createTransPose(TransInfo *t)
bPose *pose = ob->pose;
bArmature *arm;
- short ik_on = 0;
/* check validity of state */
arm = BKE_armature_from_object(tc->poseobj);
@@ -1315,8 +1314,7 @@ static void createTransPose(TransInfo *t)
/* do we need to add temporal IK chains? */
if ((pose->flag & POSE_AUTO_IK) && t->mode == TFM_TRANSLATION) {
- ik_on = pose_grab_with_ik(bmain, ob);
- if (ik_on) {
+ if (pose_grab_with_ik(bmain, ob)) {
t->flag |= T_AUTOIK;
has_translate_rotate[0] = true;
}
@@ -1359,7 +1357,6 @@ static void createTransPose(TransInfo *t)
Object *ob = tc->poseobj;
TransData *td;
TransDataExtension *tdx;
- short ik_on = 0;
int i;
PoseInitData_Mirror *pid = tc->custom.type.data;
@@ -1407,7 +1404,7 @@ static void createTransPose(TransInfo *t)
}
/* initialize initial auto=ik chainlen's? */
- if (ik_on) {
+ if (t->flag & T_AUTOIK) {
transform_autoik_update(t, 0);
}
}
@@ -2537,6 +2534,7 @@ void flushTransParticles(TransInfo *t)
}
PE_update_object(t->depsgraph, scene, OBACT(view_layer), 1);
+ BKE_particle_batch_cache_dirty_tag(psys, BKE_PARTICLE_BATCH_DIRTY_ALL);
DEG_id_tag_update(&ob->id, ID_RECALC_PSYS_REDO);
}
}
@@ -2935,11 +2933,16 @@ static void VertsToTransData(TransInfo *t,
}
else if (t->mode == TFM_SKIN_RESIZE) {
MVertSkin *vs = CustomData_bmesh_get(&em->bm->vdata, eve->head.data, CD_MVERT_SKIN);
- /* skin node size */
- td->ext = tx;
- copy_v3_v3(tx->isize, vs->radius);
- tx->size = vs->radius;
- td->val = vs->radius;
+ if (vs) {
+ /* skin node size */
+ td->ext = tx;
+ copy_v3_v3(tx->isize, vs->radius);
+ tx->size = vs->radius;
+ td->val = vs->radius;
+ }
+ else {
+ td->flag |= TD_SKIP;
+ }
}
else if (t->mode == TFM_SHRINKFATTEN) {
td->ext = tx;
@@ -3705,50 +3708,48 @@ bool clipUVTransform(TransInfo *t, float vec[2], const bool resize)
for (a = 0, td = tc->data; a < tc->data_len; a++, td++) {
minmax_v2v2_v2(min, max, td->loc);
}
+ }
- if (resize) {
- if (min[0] < 0.0f && t->center_global[0] > 0.0f &&
- t->center_global[0] < t->aspect[0] * 0.5f) {
- vec[0] *= t->center_global[0] / (t->center_global[0] - min[0]);
- }
- else if (max[0] > t->aspect[0] && t->center_global[0] < t->aspect[0]) {
- vec[0] *= (t->center_global[0] - t->aspect[0]) / (t->center_global[0] - max[0]);
- }
- else {
- clipx = 0;
- }
+ if (resize) {
+ if (min[0] < 0.0f && t->center_global[0] > 0.0f && t->center_global[0] < t->aspect[0] * 0.5f) {
+ vec[0] *= t->center_global[0] / (t->center_global[0] - min[0]);
+ }
+ else if (max[0] > t->aspect[0] && t->center_global[0] < t->aspect[0]) {
+ vec[0] *= (t->center_global[0] - t->aspect[0]) / (t->center_global[0] - max[0]);
+ }
+ else {
+ clipx = 0;
+ }
- if (min[1] < 0.0f && t->center_global[1] > 0.0f &&
- t->center_global[1] < t->aspect[1] * 0.5f) {
- vec[1] *= t->center_global[1] / (t->center_global[1] - min[1]);
- }
- else if (max[1] > t->aspect[1] && t->center_global[1] < t->aspect[1]) {
- vec[1] *= (t->center_global[1] - t->aspect[1]) / (t->center_global[1] - max[1]);
- }
- else {
- clipy = 0;
- }
+ if (min[1] < 0.0f && t->center_global[1] > 0.0f && t->center_global[1] < t->aspect[1] * 0.5f) {
+ vec[1] *= t->center_global[1] / (t->center_global[1] - min[1]);
+ }
+ else if (max[1] > t->aspect[1] && t->center_global[1] < t->aspect[1]) {
+ vec[1] *= (t->center_global[1] - t->aspect[1]) / (t->center_global[1] - max[1]);
}
else {
- if (min[0] < 0.0f) {
- vec[0] -= min[0];
- }
- else if (max[0] > t->aspect[0]) {
- vec[0] -= max[0] - t->aspect[0];
- }
- else {
- clipx = 0;
- }
+ clipy = 0;
+ }
+ }
+ else {
+ if (min[0] < 0.0f) {
+ vec[0] -= min[0];
+ }
+ else if (max[0] > t->aspect[0]) {
+ vec[0] -= max[0] - t->aspect[0];
+ }
+ else {
+ clipx = 0;
+ }
- if (min[1] < 0.0f) {
- vec[1] -= min[1];
- }
- else if (max[1] > t->aspect[1]) {
- vec[1] -= max[1] - t->aspect[1];
- }
- else {
- clipy = 0;
- }
+ if (min[1] < 0.0f) {
+ vec[1] -= min[1];
+ }
+ else if (max[1] > t->aspect[1]) {
+ vec[1] -= max[1] - t->aspect[1];
+ }
+ else {
+ clipy = 0;
}
}
@@ -6438,19 +6439,25 @@ static void trans_object_base_deps_flag_prepare(ViewLayer *view_layer)
}
}
-static void set_trans_object_base_deps_flag_cb(ID *id, void *UNUSED(user_data))
+static void set_trans_object_base_deps_flag_cb(ID *id,
+ eDepsObjectComponentType component,
+ void *UNUSED(user_data))
{
/* Here we only handle object IDs. */
if (GS(id->name) != ID_OB) {
return;
}
+ if (!ELEM(component, DEG_OB_COMP_TRANSFORM, DEG_OB_COMP_GEOMETRY)) {
+ return;
+ }
id->tag |= LIB_TAG_DOIT;
}
static void flush_trans_object_base_deps_flag(Depsgraph *depsgraph, Object *object)
{
object->id.tag |= LIB_TAG_DOIT;
- DEG_foreach_dependent_ID(depsgraph, &object->id, set_trans_object_base_deps_flag_cb, NULL);
+ DEG_foreach_dependent_ID_component(
+ depsgraph, &object->id, DEG_OB_COMP_TRANSFORM, set_trans_object_base_deps_flag_cb, NULL);
}
static void trans_object_base_deps_flag_finish(ViewLayer *view_layer)
@@ -7093,6 +7100,10 @@ void special_aftertrans_update(bContext *C, TransInfo *t)
FOREACH_TRANS_DATA_CONTAINER (t, tc) {
EdgeSlideData *sld = tc->custom.mode.data;
+ if (sld == NULL) {
+ continue;
+ }
+
/* Free temporary faces to avoid auto-merging and deleting
* during cleanup - psy-fi. */
freeEdgeSlideTempFaces(sld);
diff --git a/source/blender/editors/transform/transform_gizmo_3d.c b/source/blender/editors/transform/transform_gizmo_3d.c
index 530abe6faff..a883b5b6ba5 100644
--- a/source/blender/editors/transform/transform_gizmo_3d.c
+++ b/source/blender/editors/transform/transform_gizmo_3d.c
@@ -1489,7 +1489,12 @@ static GizmoGroup *gizmogroup_init(wmGizmoGroup *gzgroup)
ggd->gizmos[MAN_AXIS_ROT_T]->flag |= WM_GIZMO_SELECT_BACKGROUND;
/* Prevent axis gizmos overlapping the center point, see: T63744. */
- ggd->gizmos[MAN_AXIS_SCALE_C]->select_bias = ggd->gizmos[MAN_AXIS_TRANS_C]->select_bias = 2.0f;
+ ggd->gizmos[MAN_AXIS_TRANS_C]->select_bias = 2.0f;
+
+ ggd->gizmos[MAN_AXIS_SCALE_C]->select_bias = -2.0f;
+
+ /* Use 1/6 since this is '0.2' if the main scale is 1.2. */
+ RNA_float_set(ggd->gizmos[MAN_AXIS_SCALE_C]->ptr, "arc_inner_factor", 1.0 / 6.0);
return ggd;
}
@@ -1591,6 +1596,9 @@ static void gizmogroup_init_properties_from_twtype(wmGizmoGroup *gzgroup)
WM_gizmo_set_flag(axis, WM_GIZMO_DRAW_VALUE, true);
WM_gizmo_set_scale(axis, 1.2f);
}
+ else if (axis_idx == MAN_AXIS_SCALE_C) {
+ WM_gizmo_set_scale(axis, 1.2f);
+ }
else {
WM_gizmo_set_scale(axis, 0.2f);
}
@@ -1868,7 +1876,7 @@ static void WIDGETGROUP_gizmo_invoke_prepare(const bContext *C,
GizmoGroup *ggd = gzgroup->customdata;
- /* Support gizmo spesific orientation. */
+ /* Support gizmo specific orientation. */
if (gz != ggd->gizmos[MAN_AXIS_ROT_T]) {
Scene *scene = CTX_data_scene(C);
wmGizmoOpElem *gzop = WM_gizmo_operator_get(gz, 0);
diff --git a/source/blender/editors/transform/transform_ops.c b/source/blender/editors/transform/transform_ops.c
index f028f2dc506..c6c2a441d94 100644
--- a/source/blender/editors/transform/transform_ops.c
+++ b/source/blender/editors/transform/transform_ops.c
@@ -33,6 +33,7 @@
#include "BKE_global.h"
#include "BKE_report.h"
#include "BKE_editmesh.h"
+#include "BKE_layer.h"
#include "BKE_scene.h"
#include "RNA_access.h"
@@ -754,16 +755,6 @@ static void TRANSFORM_OT_resize(struct wmOperatorType *ot)
P_OPTIONS | P_GPENCIL_EDIT | P_CENTER);
}
-static bool skin_resize_poll(bContext *C)
-{
- struct Object *obedit = CTX_data_edit_object(C);
- if (obedit && obedit->type == OB_MESH) {
- BMEditMesh *em = BKE_editmesh_from_object(obedit);
- return (em && CustomData_has_layer(&em->bm->vdata, CD_MVERT_SKIN));
- }
- return 0;
-}
-
static void TRANSFORM_OT_skin_resize(struct wmOperatorType *ot)
{
/* identifiers */
@@ -777,7 +768,7 @@ static void TRANSFORM_OT_skin_resize(struct wmOperatorType *ot)
ot->exec = transform_exec;
ot->modal = transform_modal;
ot->cancel = transform_cancel;
- ot->poll = skin_resize_poll;
+ ot->poll = ED_operator_editmesh;
ot->poll_property = transform_poll_property;
RNA_def_float_vector(
diff --git a/source/blender/editors/transform/transform_snap.c b/source/blender/editors/transform/transform_snap.c
index 58a50da9846..d45a0588003 100644
--- a/source/blender/editors/transform/transform_snap.c
+++ b/source/blender/editors/transform/transform_snap.c
@@ -566,13 +566,8 @@ static void initSnappingMode(TransInfo *t)
/* Edit mode */
if (t->tsnap.applySnap != NULL && // A snapping function actually exist
((obedit_type != -1) &&
- ELEM(obedit_type,
- OB_MESH,
- OB_ARMATURE,
- OB_CURVE,
- OB_LATTICE,
- OB_MBALL))) // Temporary limited to edit mode meshes, armature, curves, metaballs
- {
+ /* Temporary limited to edit mode meshes, armature, curves, metaballs. */
+ ELEM(obedit_type, OB_MESH, OB_ARMATURE, OB_CURVE, OB_LATTICE, OB_MBALL))) {
/* Exclude editmesh if using proportional edit */
if ((obedit_type == OB_MESH) && (t->flag & T_PROP_EDIT)) {
t->tsnap.modeSelect = SNAP_NOT_ACTIVE;
diff --git a/source/blender/editors/transform/transform_snap_object.c b/source/blender/editors/transform/transform_snap_object.c
index 03c43c8d16d..6f06f8639bd 100644
--- a/source/blender/editors/transform/transform_snap_object.c
+++ b/source/blender/editors/transform/transform_snap_object.c
@@ -2820,16 +2820,16 @@ static short transform_snap_context_project_view3d_mixed_impl(
return 0;
}
-bool ED_transform_snap_object_project_view3d_ex(SnapObjectContext *sctx,
- const unsigned short snap_to,
- const struct SnapObjectParams *params,
- const float mval[2],
- float *dist_px,
- float r_loc[3],
- float r_no[3],
- int *r_index,
- Object **r_ob,
- float r_obmat[4][4])
+short ED_transform_snap_object_project_view3d_ex(SnapObjectContext *sctx,
+ const unsigned short snap_to,
+ const struct SnapObjectParams *params,
+ const float mval[2],
+ float *dist_px,
+ float r_loc[3],
+ float r_no[3],
+ int *r_index,
+ Object **r_ob,
+ float r_obmat[4][4])
{
return transform_snap_context_project_view3d_mixed_impl(
sctx, snap_to, params, mval, dist_px, r_loc, r_no, r_index, r_ob, r_obmat) != 0;
@@ -2856,7 +2856,7 @@ bool ED_transform_snap_object_project_view3d(SnapObjectContext *sctx,
float r_no[3])
{
return ED_transform_snap_object_project_view3d_ex(
- sctx, snap_to, params, mval, dist_px, r_loc, r_no, NULL, NULL, NULL);
+ sctx, snap_to, params, mval, dist_px, r_loc, r_no, NULL, NULL, NULL) != 0;
}
/**
diff --git a/source/blender/editors/undo/ed_undo.c b/source/blender/editors/undo/ed_undo.c
index 6d5f486ebe9..183e140169d 100644
--- a/source/blender/editors/undo/ed_undo.c
+++ b/source/blender/editors/undo/ed_undo.c
@@ -99,6 +99,10 @@ void ED_undo_push(bContext *C, const char *str)
BKE_undosys_stack_limit_steps_and_memory(wm->undo_stack, 0, memory_limit);
}
+ if (CLOG_CHECK(&LOG, 1)) {
+ BKE_undosys_print(wm->undo_stack);
+ }
+
WM_file_tag_modified();
}
@@ -236,6 +240,10 @@ static int ed_undo_step_impl(
Main *bmain = CTX_data_main(C);
WM_toolsystem_refresh_screen_all(bmain);
+ if (CLOG_CHECK(&LOG, 1)) {
+ BKE_undosys_print(wm->undo_stack);
+ }
+
return OPERATOR_FINISHED;
}
@@ -322,6 +330,39 @@ bool ED_undo_is_memfile_compatible(const bContext *C)
}
/**
+ * When a property of ID changes, return false.
+ *
+ * This is to avoid changes to a property making undo pushes
+ * which are ignored by the undo-system.
+ * For example, changing a brush property isn't stored by sculpt-mode undo steps.
+ * This workaround is needed until the limitation is removed, see: T61948.
+ */
+bool ED_undo_is_legacy_compatible_for_property(struct bContext *C, ID *id)
+{
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ if (view_layer != NULL) {
+ Object *obact = OBACT(view_layer);
+ if (obact != NULL) {
+ if (obact->mode & OB_MODE_ALL_PAINT) {
+ /* Don't store property changes when painting
+ * (only do undo pushes on brush strokes which each paint operator handles on it's own). */
+ CLOG_INFO(&LOG, 1, "skipping undo for paint-mode");
+ return false;
+ }
+ else if (obact->mode & OB_MODE_EDIT) {
+ if ((id == NULL) || (obact->data == NULL) ||
+ (GS(id->name) != GS(((ID *)obact->data)->name))) {
+ /* No undo push on id type mismatch in edit-mode. */
+ CLOG_INFO(&LOG, 1, "skipping undo for edit-mode");
+ return false;
+ }
+ }
+ }
+ }
+ return true;
+}
+
+/**
* Ideally we wont access the stack directly,
* this is needed for modes which handle undo themselves (bypassing #ED_undo_push).
*
diff --git a/source/blender/editors/undo/memfile_undo.c b/source/blender/editors/undo/memfile_undo.c
index 0f495d64b29..f3e2ee92558 100644
--- a/source/blender/editors/undo/memfile_undo.c
+++ b/source/blender/editors/undo/memfile_undo.c
@@ -83,10 +83,8 @@ static bool memfile_undosys_step_encode(struct bContext *UNUSED(C),
return true;
}
-static void memfile_undosys_step_decode(struct bContext *C,
- struct Main *bmain,
- UndoStep *us_p,
- int UNUSED(dir))
+static void memfile_undosys_step_decode(
+ struct bContext *C, struct Main *bmain, UndoStep *us_p, int UNUSED(dir), bool UNUSED(is_final))
{
ED_editors_exit(bmain, false);
diff --git a/source/blender/editors/util/ed_util.c b/source/blender/editors/util/ed_util.c
index 1ee8ff6966c..c1b6a7b42b2 100644
--- a/source/blender/editors/util/ed_util.c
+++ b/source/blender/editors/util/ed_util.c
@@ -326,15 +326,15 @@ void unpack_menu(bContext *C,
BLI_split_file_part(abs_name, fi, sizeof(fi));
BLI_snprintf(local_name, sizeof(local_name), "//%s/%s", folder, fi);
if (!STREQ(abs_name, local_name)) {
- switch (checkPackedFile(BKE_main_blendfile_path(bmain), local_name, pf)) {
- case PF_NOFILE:
+ switch (BKE_packedfile_compare_to_file(BKE_main_blendfile_path(bmain), local_name, pf)) {
+ case PF_CMP_NOFILE:
BLI_snprintf(line, sizeof(line), TIP_("Create %s"), local_name);
uiItemFullO_ptr(layout, ot, line, ICON_NONE, NULL, WM_OP_EXEC_DEFAULT, 0, &props_ptr);
RNA_enum_set(&props_ptr, "method", PF_WRITE_LOCAL);
RNA_string_set(&props_ptr, "id", id_name);
break;
- case PF_EQUAL:
+ case PF_CMP_EQUAL:
BLI_snprintf(line, sizeof(line), TIP_("Use %s (identical)"), local_name);
// uiItemEnumO_ptr(layout, ot, line, 0, "method", PF_USE_LOCAL);
uiItemFullO_ptr(layout, ot, line, ICON_NONE, NULL, WM_OP_EXEC_DEFAULT, 0, &props_ptr);
@@ -342,7 +342,7 @@ void unpack_menu(bContext *C,
RNA_string_set(&props_ptr, "id", id_name);
break;
- case PF_DIFFERS:
+ case PF_CMP_DIFFERS:
BLI_snprintf(line, sizeof(line), TIP_("Use %s (differs)"), local_name);
// uiItemEnumO_ptr(layout, ot, line, 0, "method", PF_USE_LOCAL);
uiItemFullO_ptr(layout, ot, line, ICON_NONE, NULL, WM_OP_EXEC_DEFAULT, 0, &props_ptr);
@@ -359,22 +359,22 @@ void unpack_menu(bContext *C,
}
}
- switch (checkPackedFile(BKE_main_blendfile_path(bmain), abs_name, pf)) {
- case PF_NOFILE:
+ switch (BKE_packedfile_compare_to_file(BKE_main_blendfile_path(bmain), abs_name, pf)) {
+ case PF_CMP_NOFILE:
BLI_snprintf(line, sizeof(line), TIP_("Create %s"), abs_name);
// uiItemEnumO_ptr(layout, ot, line, 0, "method", PF_WRITE_ORIGINAL);
uiItemFullO_ptr(layout, ot, line, ICON_NONE, NULL, WM_OP_EXEC_DEFAULT, 0, &props_ptr);
RNA_enum_set(&props_ptr, "method", PF_WRITE_ORIGINAL);
RNA_string_set(&props_ptr, "id", id_name);
break;
- case PF_EQUAL:
+ case PF_CMP_EQUAL:
BLI_snprintf(line, sizeof(line), TIP_("Use %s (identical)"), abs_name);
// uiItemEnumO_ptr(layout, ot, line, 0, "method", PF_USE_ORIGINAL);
uiItemFullO_ptr(layout, ot, line, ICON_NONE, NULL, WM_OP_EXEC_DEFAULT, 0, &props_ptr);
RNA_enum_set(&props_ptr, "method", PF_USE_ORIGINAL);
RNA_string_set(&props_ptr, "id", id_name);
break;
- case PF_DIFFERS:
+ case PF_CMP_DIFFERS:
BLI_snprintf(line, sizeof(line), TIP_("Use %s (differs)"), abs_name);
// uiItemEnumO_ptr(layout, ot, line, 0, "method", PF_USE_ORIGINAL);
uiItemFullO_ptr(layout, ot, line, ICON_NONE, NULL, WM_OP_EXEC_DEFAULT, 0, &props_ptr);
diff --git a/source/blender/editors/util/select_buffer_utils.c b/source/blender/editors/util/select_buffer_utils.c
index 130f6819e34..79f0f48830e 100644
--- a/source/blender/editors/util/select_buffer_utils.c
+++ b/source/blender/editors/util/select_buffer_utils.c
@@ -44,7 +44,7 @@
/** \name Select Bitmap from ID's
*
* Given a buffer of select ID's, fill in a booleans (true/false) per index.
- * #BLI_bitmap is used for memory effeciency.
+ * #BLI_bitmap is used for memory efficiency.
*
* \{ */
@@ -215,7 +215,7 @@ uint ED_select_buffer_sample_point(const int center[2])
/**
* Find the selection id closest to \a center.
- * \param dist[in,out]: Use to initalize the distance,
+ * \param dist[in,out]: Use to initialize the distance,
* when found, this value is set to the distance of the selection thats returned.
*/
uint ED_select_buffer_find_nearest_to_point(const int center[2],
@@ -223,7 +223,7 @@ uint ED_select_buffer_find_nearest_to_point(const int center[2],
const uint id_max,
uint *dist)
{
- /* Smart function to sample a rect spiralling outside, nice for selection ID. */
+ /* Smart function to sample a rect spiraling outside, nice for selection ID. */
/* Create region around center (typically the mouse cursor).
* This must be square and have an odd width,
diff --git a/source/blender/editors/uvedit/uvedit_draw.c b/source/blender/editors/uvedit/uvedit_draw.c
index b1d22e12b10..ed8178d1908 100644
--- a/source/blender/editors/uvedit/uvedit_draw.c
+++ b/source/blender/editors/uvedit/uvedit_draw.c
@@ -412,10 +412,10 @@ static void draw_uvs(SpaceImage *sima, Scene *scene, Object *obedit, Depsgraph *
}
}
if (verts || facedots) {
- float pointsize = UI_GetThemeValuef(TH_VERTEX_SIZE);
UI_GetThemeColor4fv(TH_VERTEX_SELECT, col2);
if (verts) {
- float pinned_col[4] = {1.0f, 0.0f, 0.0f, 1.0f}; /* TODO Theme? */
+ const float point_size = UI_GetThemeValuef(TH_VERTEX_SIZE);
+ const float pinned_col[4] = {1.0f, 0.0f, 0.0f, 1.0f}; /* TODO Theme? */
UI_GetThemeColor4fv(TH_VERTEX, col1);
GPU_blend(true);
GPU_program_point_size(true);
@@ -424,7 +424,7 @@ static void draw_uvs(SpaceImage *sima, Scene *scene, Object *obedit, Depsgraph *
GPU_batch_uniform_4f(verts, "vertColor", col1[0], col1[1], col1[2], 1.0f);
GPU_batch_uniform_4fv(verts, "selectColor", transparent);
GPU_batch_uniform_4fv(verts, "pinnedColor", pinned_col);
- GPU_batch_uniform_1f(verts, "pointSize", (pointsize + 1.5f) * M_SQRT2);
+ GPU_batch_uniform_1f(verts, "pointSize", (point_size + 1.5f) * M_SQRT2);
GPU_batch_uniform_1f(verts, "outlineWidth", 0.75f);
GPU_batch_draw(verts);
@@ -441,7 +441,8 @@ static void draw_uvs(SpaceImage *sima, Scene *scene, Object *obedit, Depsgraph *
GPU_program_point_size(false);
}
if (facedots) {
- GPU_point_size(pointsize);
+ const float point_size = UI_GetThemeValuef(TH_FACEDOT_SIZE);
+ GPU_point_size(point_size);
UI_GetThemeColor4fv(TH_WIRE, col1);
GPU_batch_program_set_builtin(facedots, GPU_SHADER_2D_UV_FACEDOTS);
diff --git a/source/blender/editors/uvedit/uvedit_unwrap_ops.c b/source/blender/editors/uvedit/uvedit_unwrap_ops.c
index 14cdb674698..a42a6eba3ff 100644
--- a/source/blender/editors/uvedit/uvedit_unwrap_ops.c
+++ b/source/blender/editors/uvedit/uvedit_unwrap_ops.c
@@ -2282,7 +2282,6 @@ static void uvedit_unwrap_cube_project(BMesh *bm,
* component, but clusters all together around the center of map. */
BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) {
- /* tf = CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY); */ /* UNUSED */
if (use_select && !BM_elem_flag_test(efa, BM_ELEM_SELECT)) {
continue;
}