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:
authorBrecht Van Lommel <brechtvanlommel@gmail.com>2019-07-18 17:14:20 +0300
committerBrecht Van Lommel <brechtvanlommel@gmail.com>2019-07-18 17:14:20 +0300
commit786f5ccea2c2ab25cef2e4723cc129e41d95ff1a (patch)
treead2c0395841f4835dc3338d1eaf074d25995ae93
parent93985e4517779b8d0af7514a18b474c1ff39e133 (diff)
parent4b2e6d4e22dc16cd521da777bd4493b49f34e034 (diff)
Merge branch 'master' into blender-v2.80-release
-rw-r--r--release/scripts/presets/keyconfig/keymap_data/blender_default.py19
-rw-r--r--release/scripts/presets/keyconfig/keymap_data/industry_compatible_data.py6
-rw-r--r--release/scripts/startup/bl_ui/space_userpref.py25
-rw-r--r--source/blender/blenkernel/BKE_action.h1
-rw-r--r--source/blender/blenkernel/BKE_armature.h2
-rw-r--r--source/blender/blenkernel/BKE_text.h47
-rw-r--r--source/blender/blenkernel/intern/action.c33
-rw-r--r--source/blender/blenkernel/intern/armature.c18
-rw-r--r--source/blender/blenkernel/intern/blendfile.c9
-rw-r--r--source/blender/blenkernel/intern/layer.c7
-rw-r--r--source/blender/blenkernel/intern/pointcache.c4
-rw-r--r--source/blender/blenkernel/intern/text.c1405
-rw-r--r--source/blender/depsgraph/intern/builder/deg_builder_relations.cc8
-rw-r--r--source/blender/draw/engines/eevee/eevee_effects.c6
-rw-r--r--source/blender/draw/engines/eevee/eevee_temporal_sampling.c1
-rw-r--r--source/blender/draw/engines/workbench/workbench_materials.c46
-rw-r--r--source/blender/draw/intern/draw_armature.c25
-rw-r--r--source/blender/draw/modes/shaders/particle_strand_vert.glsl7
-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/pose_edit.c4
-rw-r--r--source/blender/editors/armature/pose_select.c48
-rw-r--r--source/blender/editors/gpencil/gpencil_brush.c23
-rw-r--r--source/blender/editors/gpencil/gpencil_primitive.c4
-rw-r--r--source/blender/editors/include/ED_armature.h6
-rw-r--r--source/blender/editors/include/ED_text.h4
-rw-r--r--source/blender/editors/interface/interface_context_menu.c34
-rw-r--r--source/blender/editors/interface/interface_ops.c3
-rw-r--r--source/blender/editors/interface/interface_region_color_picker.c20
-rw-r--r--source/blender/editors/mask/mask_ops.c3
-rw-r--r--source/blender/editors/object/object_constraint.c14
-rw-r--r--source/blender/editors/sculpt_paint/paint_cursor.c6
-rw-r--r--source/blender/editors/sculpt_paint/paint_vertex.c52
-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_outliner/outliner_draw.c70
-rw-r--r--source/blender/editors/space_text/text_autocomplete.c16
-rw-r--r--source/blender/editors/space_text/text_ops.c66
-rw-r--r--source/blender/editors/space_text/text_undo.c175
-rw-r--r--source/blender/editors/space_userpref/userpref_ops.c32
-rw-r--r--source/blender/editors/space_view3d/space_view3d.c3
-rw-r--r--source/blender/editors/space_view3d/view3d_edit.c3
-rw-r--r--source/blender/editors/space_view3d/view3d_select.c13
-rw-r--r--source/blender/editors/space_view3d/view3d_view.c22
-rw-r--r--source/blender/editors/transform/transform.c52
-rw-r--r--source/blender/editors/transform/transform_conversions.c4
-rw-r--r--source/blender/imbuf/intern/openexr/openexr_api.cpp27
-rw-r--r--source/blender/makesdna/DNA_text_types.h2
-rw-r--r--source/blender/makesrna/intern/rna_armature.c15
-rw-r--r--source/blender/makesrna/intern/rna_object_api.c82
-rw-r--r--source/blender/makesrna/intern/rna_object_force.c2
-rw-r--r--source/blender/makesrna/intern/rna_space.c7
-rw-r--r--source/blender/makesrna/intern/rna_text_api.c4
-rw-r--r--source/blender/modifiers/intern/MOD_bevel.c4
-rw-r--r--source/blender/modifiers/intern/MOD_mirror.c2
-rw-r--r--source/blender/windowmanager/intern/wm_event_system.c6
-rw-r--r--source/blender/windowmanager/intern/wm_files.c18
59 files changed, 835 insertions, 1717 deletions
diff --git a/release/scripts/presets/keyconfig/keymap_data/blender_default.py b/release/scripts/presets/keyconfig/keymap_data/blender_default.py
index 57f65c73619..cc4dc4d00e0 100644
--- a/release/scripts/presets/keyconfig/keymap_data/blender_default.py
+++ b/release/scripts/presets/keyconfig/keymap_data/blender_default.py
@@ -3483,15 +3483,17 @@ def km_paint_curve(params):
items.extend([
("paintcurve.add_point_slide", {"type": params.action_mouse, "value": 'PRESS', "ctrl": True}, None),
- ("paintcurve.select", {"type": params.select_mouse, "value": params.select_mouse_value}, None),
- ("paintcurve.select", {"type": params.select_mouse, "value": params.select_mouse_value, "shift": True},
+ ("paintcurve.select", {"type": params.select_mouse, "value": 'PRESS'},
+ {"properties": [("extend", False)]}),
+ ("paintcurve.select", {"type": params.select_mouse, "value": 'PRESS', "shift": True},
{"properties": [("extend", True)]}),
- ("paintcurve.slide", {"type": params.action_mouse, "value": 'PRESS'}, None),
+ ("paintcurve.slide", {"type": params.action_mouse, "value": 'PRESS'},
+ {"properties": [("align", False)]}),
("paintcurve.slide", {"type": params.action_mouse, "value": 'PRESS', "shift": True},
{"properties": [("align", True)]}),
("paintcurve.select", {"type": 'A', "value": 'PRESS'},
{"properties": [("toggle", True)]}),
- ("paintcurve.cursor", {"type": params.action_mouse, "value": 'PRESS'}, None),
+ ("paintcurve.cursor", {"type": params.action_mouse, "value": 'PRESS', "shift": True, "ctrl": True}, None),
("paintcurve.delete_point", {"type": 'X', "value": 'PRESS'}, None),
("paintcurve.delete_point", {"type": 'DEL', "value": 'PRESS'}, None),
("paintcurve.draw", {"type": 'RET', "value": 'PRESS'}, None),
@@ -4155,6 +4157,13 @@ def km_particle(params):
{"properties": [("data_path_primary", 'tool_settings.particle_edit.brush.strength')]}),
op_menu("VIEW3D_MT_particle_context_menu", params.context_menu_event),
("particle.weight_set", {"type": 'K', "value": 'PRESS', "shift": True}, None),
+ *(
+ (("wm.context_set_enum",
+ {"type": NUMBERS_1[i], "value": 'PRESS'},
+ {"properties": [("data_path", "tool_settings.particle_edit.select_mode"), ("value", value)]})
+ for i, value in enumerate(('PATH', 'POINT', 'TIP'))
+ )
+ ),
*_template_items_proportional_editing(connected=False),
])
@@ -5618,7 +5627,7 @@ def km_3d_view_tool_sculpt_box_hide(params):
{"properties": [("action", 'HIDE')]}),
("paint.hide_show", {"type": params.tool_tweak, "value": 'ANY', "ctrl": True},
{"properties": [("action", 'SHOW')]}),
- ("paint.hide_show", {"type": params.select_mouse, "value": 'PRESS'},
+ ("paint.hide_show", {"type": params.select_mouse, "value": params.select_mouse_value},
{"properties": [("action", 'SHOW'), ("area", 'ALL')]}),
]},
)
diff --git a/release/scripts/presets/keyconfig/keymap_data/industry_compatible_data.py b/release/scripts/presets/keyconfig/keymap_data/industry_compatible_data.py
index 2b7dd2357ab..fb451d1f6d4 100644
--- a/release/scripts/presets/keyconfig/keymap_data/industry_compatible_data.py
+++ b/release/scripts/presets/keyconfig/keymap_data/industry_compatible_data.py
@@ -2697,10 +2697,12 @@ def km_paint_curve(params):
items.extend([
("paintcurve.add_point_slide", {"type": 'LEFTMOUSE', "value": 'PRESS', "ctrl": True}, None),
- ("paintcurve.select", {"type": 'LEFTMOUSE', "value": 'PRESS'}, None),
+ ("paintcurve.select", {"type": 'LEFTMOUSE', "value": 'PRESS'},
+ {"properties": [("extend", False)]}),
("paintcurve.select", {"type": 'LEFTMOUSE', "value": 'PRESS', "shift": True},
{"properties": [("extend", True)]}),
- ("paintcurve.slide", {"type": 'LEFTMOUSE', "value": 'PRESS'}, None),
+ ("paintcurve.slide", {"type": 'LEFTMOUSE', "value": 'PRESS'},
+ {"properties": [("align", False)]}),
("paintcurve.slide", {"type": 'LEFTMOUSE', "value": 'PRESS', "shift": True},
{"properties": [("align", True)]}),
("paintcurve.select", {"type": 'A', "value": 'PRESS'},
diff --git a/release/scripts/startup/bl_ui/space_userpref.py b/release/scripts/startup/bl_ui/space_userpref.py
index 2f573d83132..02d9f797581 100644
--- a/release/scripts/startup/bl_ui/space_userpref.py
+++ b/release/scripts/startup/bl_ui/space_userpref.py
@@ -40,22 +40,9 @@ class USERPREF_HT_header(Header):
row = layout.row()
row.menu("USERPREF_MT_save_load", text="", icon='COLLAPSEMENU')
- # Use '_is_startup' so once factory settings are loaded
- # this display option will show, since it's confusing if disabling
- # the option makes it dissapiers.
- if prefs.use_preferences_save:
- use_userpref_skip_save_on_exit = bpy.app.use_userpref_skip_save_on_exit
- if use_userpref_skip_save_on_exit or getattr(USERPREF_HT_header, "_is_startup", False):
- USERPREF_HT_header._is_startup = True
-
- sub = row.row(align=True)
- sub.alignment = 'LEFT'
- props = sub.operator(
- "preferences.autosave_override_toggle",
- text="Skip Auto-Save",
- emboss=False,
- icon='CHECKBOX_HLT' if use_userpref_skip_save_on_exit else 'CHECKBOX_DEHLT',
- )
+
+ if prefs.use_preferences_save and (not bpy.app.use_userpref_skip_save_on_exit):
+ pass
else:
sub = row.row(align=True)
sub.active = prefs.is_dirty
@@ -103,13 +90,13 @@ class USERPREF_MT_save_load(Menu):
layout.operator_context = 'EXEC_AREA'
if prefs.use_preferences_save:
- layout.operator("wm.save_userpref", text="Save Current State")
+ layout.operator("wm.save_userpref", text="Save Preferences")
sub_revert = layout.column(align=True)
sub_revert.active = prefs.is_dirty
- sub_revert.operator("wm.read_userpref", text="Revert to Saved")
+ sub_revert.operator("wm.read_userpref", text="Revert to Saved Preferences")
layout.operator_context = 'INVOKE_AREA'
- layout.operator("wm.read_factory_userpref", text="Load Factory Settings")
+ layout.operator("wm.read_factory_userpref", text="Load Factory Preferences")
class USERPREF_PT_save_preferences(Panel):
diff --git a/source/blender/blenkernel/BKE_action.h b/source/blender/blenkernel/BKE_action.h
index 69f3070fcba..a4863780d2e 100644
--- a/source/blender/blenkernel/BKE_action.h
+++ b/source/blender/blenkernel/BKE_action.h
@@ -160,6 +160,7 @@ void BKE_pose_copy_data(struct bPose **dst, const struct bPose *src, const bool
void BKE_pose_channel_copy_data(struct bPoseChannel *pchan, const struct bPoseChannel *pchan_from);
struct bPoseChannel *BKE_pose_channel_find_name(const struct bPose *pose, const char *name);
struct bPoseChannel *BKE_pose_channel_active(struct Object *ob);
+struct bPoseChannel *BKE_pose_channel_active_or_first_selected(struct Object *ob);
struct bPoseChannel *BKE_pose_channel_verify(struct bPose *pose, const char *name);
struct bPoseChannel *BKE_pose_channel_get_mirrored(const struct bPose *pose, const char *name);
diff --git a/source/blender/blenkernel/BKE_armature.h b/source/blender/blenkernel/BKE_armature.h
index 6839e13ffe1..73e62f6a7b3 100644
--- a/source/blender/blenkernel/BKE_armature.h
+++ b/source/blender/blenkernel/BKE_armature.h
@@ -90,6 +90,8 @@ void BKE_armature_bone_hash_free(struct bArmature *arm);
bool BKE_armature_bone_flag_test_recursive(const struct Bone *bone, int flag);
+void BKE_armature_refresh_layer_used(struct bArmature *arm);
+
float distfactor_to_bone(
const float vec[3], const float b1[3], const float b2[3], float r1, float r2, float rdist);
diff --git a/source/blender/blenkernel/BKE_text.h b/source/blender/blenkernel/BKE_text.h
index c78faa9dd18..6509788932c 100644
--- a/source/blender/blenkernel/BKE_text.h
+++ b/source/blender/blenkernel/BKE_text.h
@@ -30,7 +30,6 @@ extern "C" {
struct Main;
struct Text;
struct TextLine;
-struct TextUndoBuf;
void BKE_text_free_lines(struct Text *text);
void BKE_text_free(struct Text *text);
@@ -49,8 +48,8 @@ void BKE_text_copy_data(struct Main *bmain,
const int flag);
struct Text *BKE_text_copy(struct Main *bmain, const struct Text *ta);
void BKE_text_make_local(struct Main *bmain, struct Text *text, const bool lib_local);
-void BKE_text_clear(struct Text *text, struct TextUndoBuf *utxt);
-void BKE_text_write(struct Text *text, struct TextUndoBuf *utxt, const char *str);
+void BKE_text_clear(struct Text *text);
+void BKE_text_write(struct Text *text, const char *str);
int BKE_text_file_modified_check(struct Text *text);
void BKE_text_file_modified_ignore(struct Text *text);
@@ -77,29 +76,26 @@ void txt_move_eol(struct Text *text, const bool sel);
void txt_move_toline(struct Text *text, unsigned int line, const bool sel);
void txt_move_to(struct Text *text, unsigned int line, unsigned int ch, const bool sel);
void txt_pop_sel(struct Text *text);
-void txt_delete_char(struct Text *text, struct TextUndoBuf *utxt);
-void txt_delete_word(struct Text *text, struct TextUndoBuf *utxt);
-void txt_delete_selected(struct Text *text, struct TextUndoBuf *utxt);
+void txt_delete_char(struct Text *text);
+void txt_delete_word(struct Text *text);
+void txt_delete_selected(struct Text *text);
void txt_sel_all(struct Text *text);
void txt_sel_clear(struct Text *text);
void txt_sel_line(struct Text *text);
char *txt_sel_to_buf(struct Text *text, int *r_buf_strlen);
-void txt_insert_buf(struct Text *text, struct TextUndoBuf *utxt, const char *in_buffer);
-void txt_undo_add_op(struct Text *text, struct TextUndoBuf *utxt, int op);
-void txt_do_undo(struct Text *text, struct TextUndoBuf *utxt);
-void txt_do_redo(struct Text *text, struct TextUndoBuf *utxt);
-void txt_split_curline(struct Text *text, struct TextUndoBuf *utxt);
-void txt_backspace_char(struct Text *text, struct TextUndoBuf *utxt);
-void txt_backspace_word(struct Text *text, struct TextUndoBuf *utxt);
-bool txt_add_char(struct Text *text, struct TextUndoBuf *utxt, unsigned int add);
-bool txt_add_raw_char(struct Text *text, struct TextUndoBuf *utxt, unsigned int add);
-bool txt_replace_char(struct Text *text, struct TextUndoBuf *utxt, unsigned int add);
-void txt_unindent(struct Text *text, struct TextUndoBuf *utxt);
-void txt_comment(struct Text *text, struct TextUndoBuf *utxt);
-void txt_indent(struct Text *text, struct TextUndoBuf *utxt);
-void txt_uncomment(struct Text *text, struct TextUndoBuf *utxt);
-void txt_move_lines(struct Text *text, struct TextUndoBuf *utxt, const int direction);
-void txt_duplicate_line(struct Text *text, struct TextUndoBuf *utxt);
+void txt_insert_buf(struct Text *text, const char *in_buffer);
+void txt_split_curline(struct Text *text);
+void txt_backspace_char(struct Text *text);
+void txt_backspace_word(struct Text *text);
+bool txt_add_char(struct Text *text, unsigned int add);
+bool txt_add_raw_char(struct Text *text, unsigned int add);
+bool txt_replace_char(struct Text *text, unsigned int add);
+void txt_unindent(struct Text *text);
+void txt_comment(struct Text *text);
+void txt_indent(struct Text *text);
+void txt_uncomment(struct Text *text);
+void txt_move_lines(struct Text *text, const int direction);
+void txt_duplicate_line(struct Text *text);
int txt_setcurr_tab_spaces(struct Text *text, int space);
bool txt_cursor_is_line_start(struct Text *text);
bool txt_cursor_is_line_end(struct Text *text);
@@ -125,10 +121,9 @@ enum {
TXT_MOVE_LINE_DOWN = 1,
};
-typedef struct TextUndoBuf {
- char *buf;
- int pos, len;
-} TextUndoBuf;
+/* Fast non-validating buffer conversion for undo. */
+char *txt_to_buf_for_undo(struct Text *text, int *r_buf_strlen);
+void txt_from_buf_for_undo(struct Text *text, const char *buf, int buf_len);
#ifdef __cplusplus
}
diff --git a/source/blender/blenkernel/intern/action.c b/source/blender/blenkernel/intern/action.c
index 3e3a533275b..a7159f85dc2 100644
--- a/source/blender/blenkernel/intern/action.c
+++ b/source/blender/blenkernel/intern/action.c
@@ -43,6 +43,7 @@
#include "BLT_translation.h"
#include "BKE_action.h"
+#include "BKE_armature.h"
#include "BKE_anim.h"
#include "BKE_animsys.h"
#include "BKE_constraint.h"
@@ -525,6 +526,38 @@ bPoseChannel *BKE_pose_channel_active(Object *ob)
}
/**
+ * Use this when detecting the "other selected bone",
+ * when we have multiple armatures in pose mode.
+ *
+ * In this case the active-selected is an obvious choice when finding the target for a
+ * constraint for eg. however from the users perspective the active pose bone of the
+ * active object is the _real_ active bone, so any other non-active selected bone
+ * is a candidate for being the other selected bone, see: T58447.
+ */
+bPoseChannel *BKE_pose_channel_active_or_first_selected(struct Object *ob)
+{
+ bArmature *arm = (ob) ? ob->data : NULL;
+
+ if (ELEM(NULL, ob, ob->pose, arm)) {
+ return NULL;
+ }
+
+ bPoseChannel *pchan = BKE_pose_channel_active(ob);
+ if (pchan && (pchan->bone->flag & BONE_SELECTED) && PBONE_VISIBLE(arm, pchan->bone)) {
+ return pchan;
+ }
+
+ for (pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) {
+ if (pchan->bone != NULL) {
+ if ((pchan->bone->flag & BONE_SELECTED) && PBONE_VISIBLE(arm, pchan->bone)) {
+ return pchan;
+ }
+ }
+ }
+ return NULL;
+}
+
+/**
* \see #ED_armature_ebone_get_mirrored (edit-mode, matching function)
*/
bPoseChannel *BKE_pose_channel_get_mirrored(const bPose *pose, const char *name)
diff --git a/source/blender/blenkernel/intern/armature.c b/source/blender/blenkernel/intern/armature.c
index 65de951b190..c36acd1eae1 100644
--- a/source/blender/blenkernel/intern/armature.c
+++ b/source/blender/blenkernel/intern/armature.c
@@ -324,6 +324,24 @@ bool BKE_armature_bone_flag_test_recursive(const Bone *bone, int flag)
}
}
+static void armature_refresh_layer_used_recursive(bArmature *arm, ListBase *bones)
+{
+ for (Bone *bone = bones->first; bone; bone = bone->next) {
+ arm->layer_used |= bone->layer;
+ armature_refresh_layer_used_recursive(arm, &bone->childbase);
+ }
+}
+
+/* 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 BKE_armature_refresh_layer_used(bArmature *arm)
+{
+ arm->layer_used = 0;
+ armature_refresh_layer_used_recursive(arm, &arm->bonebase);
+}
+
/* Finds the best possible extension to the name on a particular axis. (For renaming, check for
* unique names afterwards) strip_number: removes number extensions (TODO: not used)
* axis: the axis to name on
diff --git a/source/blender/blenkernel/intern/blendfile.c b/source/blender/blenkernel/intern/blendfile.c
index 570805a01d0..afbd2627a2a 100644
--- a/source/blender/blenkernel/intern/blendfile.c
+++ b/source/blender/blenkernel/intern/blendfile.c
@@ -670,9 +670,14 @@ WorkspaceConfigFileData *BKE_blendfile_workspace_config_read(const char *filepat
}
if (bfd) {
- workspace_config = MEM_mallocN(sizeof(*workspace_config), __func__);
+ workspace_config = MEM_callocN(sizeof(*workspace_config), __func__);
workspace_config->main = bfd->main;
- workspace_config->workspaces = bfd->main->workspaces;
+
+ /* Only 2.80+ files have actual workspaces, don't try to use screens
+ * from older versions. */
+ if (bfd->main->versionfile >= 280) {
+ workspace_config->workspaces = bfd->main->workspaces;
+ }
MEM_freeN(bfd);
}
diff --git a/source/blender/blenkernel/intern/layer.c b/source/blender/blenkernel/intern/layer.c
index 2b064c6b2a7..7dc04214ba5 100644
--- a/source/blender/blenkernel/intern/layer.c
+++ b/source/blender/blenkernel/intern/layer.c
@@ -745,9 +745,6 @@ static short layer_collection_sync(ViewLayer *view_layer,
}
lc->runtime_flag |= LAYER_COLLECTION_HAS_OBJECTS;
-
- /* Make sure flags on base are usable right away. */
- BKE_base_eval_flags(base);
}
runtime_flag |= lc->runtime_flag;
@@ -814,6 +811,10 @@ void BKE_layer_collection_sync(const Scene *scene, ViewLayer *view_layer)
BLI_freelistN(&view_layer->object_bases);
view_layer->object_bases = new_object_bases;
+ for (Base *base = view_layer->object_bases.first; base; base = base->next) {
+ BKE_base_eval_flags(base);
+ }
+
/* Always set a valid active collection. */
LayerCollection *active = view_layer->active_collection;
diff --git a/source/blender/blenkernel/intern/pointcache.c b/source/blender/blenkernel/intern/pointcache.c
index d441ffdc8ff..b577efd2a22 100644
--- a/source/blender/blenkernel/intern/pointcache.c
+++ b/source/blender/blenkernel/intern/pointcache.c
@@ -1590,7 +1590,7 @@ void BKE_ptcache_id_from_softbody(PTCacheID *pid, Object *ob, SoftBody *sb)
pid->stack_index = pid->cache->index;
- pid->default_step = 10;
+ pid->default_step = 1;
pid->max_step = 20;
pid->file_type = PTCACHE_FILE_PTCACHE;
}
@@ -1655,7 +1655,7 @@ void BKE_ptcache_id_from_particles(PTCacheID *pid, Object *ob, ParticleSystem *p
pid->info_types = (1 << BPHYS_DATA_TIMES);
- pid->default_step = 10;
+ pid->default_step = 1;
pid->max_step = 20;
pid->file_type = PTCACHE_FILE_PTCACHE;
}
diff --git a/source/blender/blenkernel/intern/text.c b/source/blender/blenkernel/intern/text.c
index 1d6de646255..b922aabc171 100644
--- a/source/blender/blenkernel/intern/text.c
+++ b/source/blender/blenkernel/intern/text.c
@@ -79,96 +79,24 @@
*
* Display
* --
+ *
* The st->top determines at what line the top of the text is displayed.
* If the user moves the cursor the st containing that cursor should
* be popped ... other st's retain their own top location.
- *
- * Undo
- * --
- * Undo/Redo works by storing
- * events in a queue, and a pointer
- * to the current position in the
- * queue...
- *
- * Events are stored using an
- * arbitrary op-code system
- * to keep track of
- * a) the two cursors (normal and selected)
- * b) input (visible and control (ie backspace))
- *
- * input data is stored as its
- * ASCII value, the opcodes are
- * then selected to not conflict.
- *
- * opcodes with data in between are
- * written at the beginning and end
- * of the data to allow undo and redo
- * to simply check the code at the current
- * undo position
*/
-/* Undo opcodes */
-
-enum {
- /* Complex editing */
- /* 1 - opcode is followed by 1 byte for ascii character and opcode (repeat)) */
- /* 2 - opcode is followed by 2 bytes for utf-8 character and opcode (repeat)) */
- /* 3 - opcode is followed by 3 bytes for utf-8 character and opcode (repeat)) */
- /* 4 - opcode is followed by 4 bytes for unicode character and opcode (repeat)) */
- UNDO_INSERT_1 = 013,
- UNDO_INSERT_2 = 014,
- UNDO_INSERT_3 = 015,
- UNDO_INSERT_4 = 016,
-
- UNDO_BS_1 = 017,
- UNDO_BS_2 = 020,
- UNDO_BS_3 = 021,
- UNDO_BS_4 = 022,
-
- UNDO_DEL_1 = 023,
- UNDO_DEL_2 = 024,
- UNDO_DEL_3 = 025,
- UNDO_DEL_4 = 026,
-
- /* Text block (opcode is followed
- * by 4 character length ID + the text
- * block itself + the 4 character length
- * ID (repeat) and opcode (repeat)) */
- UNDO_DBLOCK = 027, /* Delete block */
- UNDO_IBLOCK = 030, /* Insert block */
-
- /* Misc */
- UNDO_INDENT = 032,
- UNDO_UNINDENT = 033,
- UNDO_COMMENT = 034,
- UNDO_UNCOMMENT = 035,
-
- UNDO_MOVE_LINES_UP = 036,
- UNDO_MOVE_LINES_DOWN = 037,
-
- UNDO_DUPLICATE = 040,
-};
-
/***/
static void txt_pop_first(Text *text);
static void txt_pop_last(Text *text);
-static void txt_undo_add_blockop(Text *text, TextUndoBuf *utxt, int op, const char *buf);
static void txt_delete_line(Text *text, TextLine *line);
-static void txt_delete_sel(Text *text, TextUndoBuf *utxt);
+static void txt_delete_sel(Text *text);
static void txt_make_dirty(Text *text);
/***/
/**
- * Set to true when undoing (so we don't generate undo steps while undoing).
- *
- * Also use to disable undo entirely.
- */
-static bool undoing;
-
-/**
- * \note caller must handle `undo_buf` and `compiled` members.
+ * \note caller must handle `compiled` member.
*/
void BKE_text_free_lines(Text *text)
{
@@ -516,29 +444,17 @@ void BKE_text_make_local(Main *bmain, Text *text, const bool lib_local)
BKE_id_make_local_generic(bmain, &text->id, true, lib_local);
}
-void BKE_text_clear(Text *text, TextUndoBuf *utxt) /* called directly from rna */
+void BKE_text_clear(Text *text) /* called directly from rna */
{
- const bool undoing_orig = undoing;
- undoing = (utxt == NULL);
-
txt_sel_all(text);
- txt_delete_sel(text, utxt);
-
- undoing = undoing_orig;
-
+ txt_delete_sel(text);
txt_make_dirty(text);
}
-void BKE_text_write(Text *text, TextUndoBuf *utxt, const char *str) /* called directly from rna */
+void BKE_text_write(Text *text, const char *str) /* called directly from rna */
{
- const bool undoing_orig = undoing;
- undoing = (utxt == NULL);
-
- txt_insert_buf(text, utxt, str);
+ txt_insert_buf(text, str);
txt_move_eof(text, 0);
-
- undoing = undoing_orig;
-
txt_make_dirty(text);
}
@@ -1270,7 +1186,7 @@ bool txt_has_sel(Text *text)
return ((text->curl != text->sell) || (text->curc != text->selc));
}
-static void txt_delete_sel(Text *text, TextUndoBuf *utxt)
+static void txt_delete_sel(Text *text)
{
TextLine *tmpl;
char *buf;
@@ -1288,12 +1204,6 @@ static void txt_delete_sel(Text *text, TextUndoBuf *utxt)
txt_order_cursors(text, false);
- if (!undoing) {
- buf = txt_sel_to_buf(text, NULL);
- txt_undo_add_blockop(text, utxt, UNDO_DBLOCK, buf);
- MEM_freeN(buf);
- }
-
buf = MEM_mallocN(text->curc + (text->sell->len - text->selc) + 1, "textline_string");
strncpy(buf, text->curl->line, text->curc);
@@ -1349,6 +1259,106 @@ void txt_sel_line(Text *text)
text->selc = text->sell->len;
}
+/* -------------------------------------------------------------------- */
+/** \name Buffer Conversion for Undo/Redo
+ *
+ * Buffer conversion functions that rely on the buffer already being validated.
+ *
+ * The only requirement for these functions is that they're reverse-able,
+ * the undo logic doesn't inspect their content.
+ *
+ * Currently buffers:
+ * - Always ends with a new-line.
+ * - Are not null terminated.
+ * \{ */
+
+/**
+ * Create a buffer, the only requirement is #txt_from_buf_for_undo can decode it.
+ */
+char *txt_to_buf_for_undo(Text *text, int *r_buf_len)
+{
+ int buf_len = 0;
+ for (const TextLine *l = text->lines.first; l; l = l->next) {
+ buf_len += l->len + 1;
+ }
+ char *buf = MEM_mallocN(buf_len, __func__);
+ char *buf_step = buf;
+ for (const TextLine *l = text->lines.first; l; l = l->next) {
+ memcpy(buf_step, l->line, l->len);
+ buf_step += l->len;
+ *buf_step++ = '\n';
+ }
+ *r_buf_len = buf_len;
+ return buf;
+}
+
+/**
+ * Decode a buffer from #txt_to_buf_for_undo.
+ */
+void txt_from_buf_for_undo(Text *text, const char *buf, int buf_len)
+{
+ const char *buf_end = buf + buf_len;
+ const char *buf_step = buf;
+
+ /* First re-use existing lines.
+ * Good for undo since it means in practice many operations re-use all
+ * except for the modified line. */
+ TextLine *l_src = text->lines.first;
+ BLI_listbase_clear(&text->lines);
+ while (buf_step != buf_end && l_src) {
+ /* New lines are ensured by #txt_to_buf_for_undo. */
+ const char *buf_step_next = strchr(buf_step, '\n');
+ const int len = buf_step_next - buf_step;
+
+ TextLine *l = l_src;
+ l_src = l_src->next;
+ if (l->len != len) {
+ l->line = MEM_reallocN(l->line, len + 1);
+ l->len = len;
+ }
+ MEM_SAFE_FREE(l->format);
+
+ memcpy(l->line, buf_step, len);
+ l->line[len] = '\0';
+ BLI_addtail(&text->lines, l);
+ buf_step = buf_step_next + 1;
+ }
+
+ /* If we have extra lines. */
+ while (l_src != NULL) {
+ TextLine *l_src_next = l_src->next;
+ MEM_freeN(l_src->line);
+ if (l_src->format) {
+ MEM_freeN(l_src->format);
+ }
+ MEM_freeN(l_src);
+ l_src = l_src_next;
+ }
+
+ while (buf_step != buf_end) {
+ /* New lines are ensured by #txt_to_buf_for_undo. */
+ const char *buf_step_next = strchr(buf_step, '\n');
+ const int len = buf_step_next - buf_step;
+
+ TextLine *l = MEM_mallocN(sizeof(TextLine), "textline");
+ l->line = MEM_mallocN(len + 1, "textline_string");
+ l->len = len;
+ l->format = NULL;
+
+ memcpy(l->line, buf_step, len);
+ l->line[len] = '\0';
+ BLI_addtail(&text->lines, l);
+ buf_step = buf_step_next + 1;
+ }
+
+ text->curl = text->sell = text->lines.first;
+ text->curc = text->selc = 0;
+
+ txt_make_dirty(text);
+}
+
+/** \} */
+
/***************************/
/* Cut and paste functions */
/***************************/
@@ -1575,9 +1585,8 @@ char *txt_sel_to_buf(Text *text, int *r_buf_strlen)
return buf;
}
-void txt_insert_buf(Text *text, TextUndoBuf *utxt, const char *in_buffer)
+void txt_insert_buf(Text *text, const char *in_buffer)
{
- const bool undoing_orig = undoing;
int l = 0, len;
size_t i = 0, j;
TextLine *add;
@@ -1587,24 +1596,19 @@ void txt_insert_buf(Text *text, TextUndoBuf *utxt, const char *in_buffer)
return;
}
- txt_delete_sel(text, utxt);
+ txt_delete_sel(text);
len = strlen(in_buffer);
buffer = BLI_strdupn(in_buffer, len);
len += txt_extended_ascii_as_utf8(&buffer);
- if (!undoing) {
- txt_undo_add_blockop(text, utxt, UNDO_IBLOCK, buffer);
- }
- undoing = true;
-
/* Read the first line (or as close as possible */
while (buffer[i] && buffer[i] != '\n') {
- txt_add_raw_char(text, utxt, BLI_str_utf8_as_unicode_step(buffer, &i));
+ txt_add_raw_char(text, BLI_str_utf8_as_unicode_step(buffer, &i));
}
if (buffer[i] == '\n') {
- txt_split_curline(text, utxt);
+ txt_split_curline(text);
i++;
while (i < len) {
@@ -1622,7 +1626,7 @@ void txt_insert_buf(Text *text, TextUndoBuf *utxt, const char *in_buffer)
}
else {
for (j = i - l; j < i && j < len;) {
- txt_add_raw_char(text, utxt, BLI_str_utf8_as_unicode_step(buffer, &j));
+ txt_add_raw_char(text, BLI_str_utf8_as_unicode_step(buffer, &j));
}
break;
}
@@ -1630,1046 +1634,13 @@ void txt_insert_buf(Text *text, TextUndoBuf *utxt, const char *in_buffer)
}
MEM_freeN(buffer);
- undoing = undoing_orig;
-}
-
-/******************/
-/* Undo functions */
-/******************/
-
-static bool max_undo_test(TextUndoBuf *utxt, int x)
-{
- /* Normally over-allocating is preferred,
- * however in this case the buffer is small enough and re-allocation
- * fast enough for each undo step that it's not a problem to allocate each time.
- * This also saves on some memory when we have many text buffers
- * that would have an empty undo memory allocated.
- */
-
- /* Add one for the null terminator. */
- utxt->len = utxt->pos + x + 1;
- if (utxt->len > TXT_MAX_UNDO) {
- /* XXX error("Undo limit reached, buffer cleared\n"); */
- MEM_freeN(utxt->buf);
- return false;
- }
- else {
- /* Small reallocations on each undo step is fine. */
- utxt->buf = MEM_recallocN(utxt->buf, utxt->len);
- }
- return true;
-}
-
-static void txt_undo_end(Text *UNUSED(text), TextUndoBuf *utxt)
-{
- int undo_pos_end = utxt->pos + 1;
- BLI_assert(undo_pos_end + 1 == utxt->len);
- utxt->buf[undo_pos_end] = '\0';
-}
-
-/* Call once undo is done. */
-#ifndef NDEBUG
-
-#endif
-
-#if 0 /* UNUSED */
-static void dump_buffer(TextUndoBuf *utxt)
-{
- int i = 0;
-
- while (i++ < utxt->undo_pos)
- printf("%d: %d %c\n", i, utxt->buf[i], utxt->buf[i]);
-}
-
-/* Note: this function is outdated and must be updated if needed for future use */
-void txt_print_undo(Text *text)
-{
- int i = 0;
- int op;
- const char *ops;
- int linep, charp;
-
- dump_buffer(text);
-
- printf("---< Undo Buffer >---\n");
-
- printf("UndoPosition is %d\n", utxt->pos);
-
- while (i <= utxt->pos) {
- op = utxt->buf[i];
-
- if (op == UNDO_INSERT_1) {
- ops = "Insert ascii ";
- }
- else if (op == UNDO_INSERT_2) {
- ops = "Insert 2 bytes ";
- }
- else if (op == UNDO_INSERT_3) {
- ops = "Insert 3 bytes ";
- }
- else if (op == UNDO_INSERT_4) {
- ops = "Insert unicode ";
- }
- else if (op == UNDO_BS_1) {
- ops = "Backspace for ascii ";
- }
- else if (op == UNDO_BS_2) {
- ops = "Backspace for 2 bytes ";
- }
- else if (op == UNDO_BS_3) {
- ops = "Backspace for 3 bytes ";
- }
- else if (op == UNDO_BS_4) {
- ops = "Backspace for unicode ";
- }
- else if (op == UNDO_DEL_1) {
- ops = "Delete ascii ";
- }
- else if (op == UNDO_DEL_2) {
- ops = "Delete 2 bytes ";
- }
- else if (op == UNDO_DEL_3) {
- ops = "Delete 3 bytes ";
- }
- else if (op == UNDO_DEL_4) {
- ops = "Delete unicode ";
- }
- else if (op == UNDO_DBLOCK) {
- ops = "Delete text block";
- }
- else if (op == UNDO_IBLOCK) {
- ops = "Insert text block";
- }
- else if (op == UNDO_INDENT) {
- ops = "Indent ";
- }
- else if (op == UNDO_UNINDENT) {
- ops = "Unindent ";
- }
- else if (op == UNDO_COMMENT) {
- ops = "Comment ";
- }
- else if (op == UNDO_UNCOMMENT) {
- ops = "Uncomment ";
- }
- else {
- ops = "Unknown";
- }
-
- printf("Op (%o) at %d = %s", op, i, ops);
- if (op >= UNDO_INSERT_1 && op <= UNDO_DEL_4) {
- i++;
- printf(" - Char is ");
- switch (op) {
- case UNDO_INSERT_1:
- case UNDO_BS_1:
- case UNDO_DEL_1:
- printf("%c", utxt->buf[i]);
- i++;
- break;
- case UNDO_INSERT_2:
- case UNDO_BS_2:
- case UNDO_DEL_2:
- printf("%c%c", utxt->buf[i], utxt->buf[i + 1]);
- i += 2;
- break;
- case UNDO_INSERT_3:
- case UNDO_BS_3:
- case UNDO_DEL_3:
- printf("%c%c%c", utxt->buf[i], utxt->buf[i + 1], utxt->buf[i + 2]);
- i += 3;
- break;
- case UNDO_INSERT_4:
- case UNDO_BS_4:
- case UNDO_DEL_4: {
- unsigned int uc;
- char c[BLI_UTF8_MAX + 1];
- size_t c_len;
- uc = utxt->buf[i];
- i++;
- uc = uc + (utxt->buf[i] << 8);
- i++;
- uc = uc + (utxt->buf[i] << 16);
- i++;
- uc = uc + (utxt->buf[i] << 24);
- i++;
- c_len = BLI_str_utf8_from_unicode(uc, c);
- c[c_len] = '\0';
- puts(c);
- break;
- }
- }
- }
- else if (op == UNDO_DBLOCK || op == UNDO_IBLOCK) {
- i++;
-
- linep = utxt->buf[i];
- i++;
- linep = linep + (utxt->buf[i] << 8);
- i++;
- linep = linep + (utxt->buf[i] << 16);
- i++;
- linep = linep + (utxt->buf[i] << 24);
- i++;
-
- printf(" (length %d) <", linep);
-
- while (linep > 0) {
- putchar(utxt->buf[i]);
- linep--;
- i++;
- }
-
- linep = utxt->buf[i];
- i++;
- linep = linep + (utxt->buf[i] << 8);
- i++;
- linep = linep + (utxt->buf[i] << 16);
- i++;
- linep = linep + (utxt->buf[i] << 24);
- i++;
- printf("> (%d)", linep);
- }
- else if (op == UNDO_INDENT || op == UNDO_UNINDENT) {
- i++;
-
- charp = utxt->buf[i];
- i++;
- charp = charp + (utxt->buf[i] << 8);
- i++;
-
- linep = utxt->buf[i];
- i++;
- linep = linep + (utxt->buf[i] << 8);
- i++;
- linep = linep + (utxt->buf[i] << 16);
- i++;
- linep = linep + (utxt->buf[i] << 24);
- i++;
-
- printf("to <%d, %d> ", linep, charp);
-
- charp = utxt->buf[i];
- i++;
- charp = charp + (utxt->buf[i] << 8);
- i++;
-
- linep = utxt->buf[i];
- i++;
- linep = linep + (utxt->buf[i] << 8);
- i++;
- linep = linep + (utxt->buf[i] << 16);
- i++;
- linep = linep + (utxt->buf[i] << 24);
- i++;
-
- printf("from <%d, %d>", linep, charp);
- }
-
- printf(" %d\n", i);
- i++;
- }
-}
-#endif
-
-static void txt_undo_store_uint16(char *undo_buf, int *undo_pos, unsigned short value)
-{
- undo_buf[*undo_pos] = (value)&0xff;
- (*undo_pos)++;
- undo_buf[*undo_pos] = (value >> 8) & 0xff;
- (*undo_pos)++;
-}
-
-static void txt_undo_store_uint32(char *undo_buf, int *undo_pos, unsigned int value)
-{
- undo_buf[*undo_pos] = (value)&0xff;
- (*undo_pos)++;
- undo_buf[*undo_pos] = (value >> 8) & 0xff;
- (*undo_pos)++;
- undo_buf[*undo_pos] = (value >> 16) & 0xff;
- (*undo_pos)++;
- undo_buf[*undo_pos] = (value >> 24) & 0xff;
- (*undo_pos)++;
-}
-
-/* store the cur cursor to the undo buffer (6 bytes)*/
-static void txt_undo_store_cur(Text *text, TextUndoBuf *utxt)
-{
- txt_undo_store_uint16(utxt->buf, &utxt->pos, text->curc);
- txt_undo_store_uint32(utxt->buf, &utxt->pos, txt_get_span(text->lines.first, text->curl));
-}
-
-/* store the sel cursor to the undo buffer (6 bytes) */
-static void txt_undo_store_sel(Text *text, TextUndoBuf *utxt)
-{
- txt_undo_store_uint16(utxt->buf, &utxt->pos, text->selc);
- txt_undo_store_uint32(utxt->buf, &utxt->pos, txt_get_span(text->lines.first, text->sell));
-}
-
-/* store both cursors to the undo buffer (12 bytes) */
-static void txt_undo_store_cursors(Text *text, TextUndoBuf *utxt)
-{
- txt_undo_store_cur(text, utxt);
- txt_undo_store_sel(text, utxt);
-}
-
-/* store an operator along with a block of data */
-static void txt_undo_add_blockop(Text *text, TextUndoBuf *utxt, int op, const char *buf)
-{
- unsigned int length = strlen(buf);
-
- if (!max_undo_test(utxt, 2 + 12 + 4 + length + 4 + 1)) {
- return;
- }
- /* 2 bytes */
- utxt->pos++;
- utxt->buf[utxt->pos] = op;
- utxt->pos++;
- /* 12 bytes */
- txt_undo_store_cursors(text, utxt);
- /* 4 bytes */
- txt_undo_store_uint32(utxt->buf, &utxt->pos, length);
- /* 'length' bytes */
- memcpy(utxt->buf + utxt->pos, buf, length);
- utxt->pos += length;
- /* 4 bytes */
- txt_undo_store_uint32(utxt->buf, &utxt->pos, length);
- /* 1 byte */
- utxt->buf[utxt->pos] = op;
-
- txt_undo_end(text, utxt);
-}
-
-/* store a regular operator */
-void txt_undo_add_op(Text *text, TextUndoBuf *utxt, int op)
-{
- if (!max_undo_test(utxt, 2 + 12 + 1)) {
- return;
- }
-
- /* 2 bytes */
- utxt->pos++;
- utxt->buf[utxt->pos] = op;
- utxt->pos++;
- /* 12 bytes */
- txt_undo_store_cursors(text, utxt);
- /* 1 byte */
- utxt->buf[utxt->pos] = op;
-
- txt_undo_end(text, utxt);
-}
-
-/* store an operator for a single character */
-static void txt_undo_add_charop(Text *text, TextUndoBuf *utxt, int op_start, unsigned int c)
-{
- char utf8[BLI_UTF8_MAX];
- size_t i, utf8_size = BLI_str_utf8_from_unicode(c, utf8);
-
- if (utf8_size < 4 && 0) {
- if (!max_undo_test(utxt, 2 + 6 + utf8_size + 1)) {
- return;
- }
- /* 2 bytes */
- utxt->pos++;
- utxt->buf[utxt->pos] = op_start + utf8_size - 1;
- utxt->pos++;
- /* 6 bytes */
- txt_undo_store_cur(text, utxt);
- /* 'utf8_size' bytes */
- for (i = 0; i < utf8_size; i++) {
- utxt->buf[utxt->pos] = utf8[i];
- utxt->pos++;
- }
- /* 1 byte */
- utxt->buf[utxt->pos] = op_start + utf8_size - 1;
- }
- else {
- if (!max_undo_test(utxt, 2 + 6 + 4 + 1)) {
- return;
- }
- /* 2 bytes */
- utxt->pos++;
- utxt->buf[utxt->pos] = op_start + 3;
- utxt->pos++;
- /* 6 bytes */
- txt_undo_store_cur(text, utxt);
- /* 4 bytes */
- txt_undo_store_uint32(utxt->buf, &utxt->pos, c);
- /* 1 byte */
- utxt->buf[utxt->pos] = op_start + 3;
- }
-
- txt_undo_end(text, utxt);
-}
-
-/* extends Link */
-struct LinkInt {
- struct LinkInt *next, *prev;
- int value;
-};
-
-/**
- * UnindentLines points to a #ListBase composed of #LinkInt elements, listing the numbers
- * of the lines that should not be indented back.
- */
-static void txt_undo_add_unprefix_op(Text *text,
- TextUndoBuf *utxt,
- char undo_op,
- const ListBase *line_index_mask,
- const int line_index_mask_len)
-{
- struct LinkInt *idata;
-
- BLI_assert(BLI_listbase_count(line_index_mask) == line_index_mask_len);
-
- /* OP byte + u32 count + counted u32 line numbers + u32 count + 12-bytes selection + OP byte. */
- if (!max_undo_test(utxt, 2 + 4 + (line_index_mask_len * 4) + 4 + 12 + 1)) {
- return;
- }
-
- /* 2 bytes */
- utxt->pos++;
- utxt->buf[utxt->pos] = undo_op;
- utxt->pos++;
- /* Adding number of line numbers to read
- * 4 bytes */
- txt_undo_store_uint32(utxt->buf, &utxt->pos, line_index_mask_len);
-
- /* Adding line-numbers of lines that shall not be indented if undoing.
- * 'line_index_mask_len * 4' bytes */
- for (idata = line_index_mask->first; idata; idata = idata->next) {
- txt_undo_store_uint32(utxt->buf, &utxt->pos, idata->value);
- }
-
- /* Adding number of line numbers to read again.
- * 4 bytes */
- txt_undo_store_uint32(utxt->buf, &utxt->pos, line_index_mask_len);
- /* Adding current selection.
- * 12 bytes */
- txt_undo_store_cursors(text, utxt);
- /* Closing with OP (same as above).
- * 1 byte */
- utxt->buf[utxt->pos] = undo_op;
- /* Marking as last undo operation */
- txt_undo_end(text, utxt);
-}
-
-static unsigned short txt_undo_read_uint16(const char *undo_buf, int *undo_pos)
-{
- unsigned short val;
- val = undo_buf[*undo_pos];
- (*undo_pos)--;
- val = (val << 8) + undo_buf[*undo_pos];
- (*undo_pos)--;
- return val;
-}
-
-static unsigned int txt_undo_read_uint32(const char *undo_buf, int *undo_pos)
-{
- unsigned int val;
- val = undo_buf[*undo_pos];
- (*undo_pos)--;
- val = (val << 8) + undo_buf[*undo_pos];
- (*undo_pos)--;
- val = (val << 8) + undo_buf[*undo_pos];
- (*undo_pos)--;
- val = (val << 8) + undo_buf[*undo_pos];
- (*undo_pos)--;
- return val;
-}
-
-/* read the cur cursor from the undo buffer */
-static void txt_undo_read_cur(const char *undo_buf,
- int *undo_pos,
- unsigned int *curln,
- unsigned short *curc)
-{
- *curln = txt_undo_read_uint32(undo_buf, undo_pos);
- *curc = txt_undo_read_uint16(undo_buf, undo_pos);
-}
-
-/* read the sel cursor from the undo buffer */
-static void txt_undo_read_sel(const char *undo_buf,
- int *undo_pos,
- unsigned int *selln,
- unsigned short *selc)
-{
- *selln = txt_undo_read_uint32(undo_buf, undo_pos);
- *selc = txt_undo_read_uint16(undo_buf, undo_pos);
-}
-
-/* read both cursors from the undo buffer */
-static void txt_undo_read_cursors(const char *undo_buf,
- int *undo_pos,
- unsigned int *curln,
- unsigned short *curc,
- unsigned int *selln,
- unsigned short *selc)
-{
- txt_undo_read_sel(undo_buf, undo_pos, selln, selc);
- txt_undo_read_cur(undo_buf, undo_pos, curln, curc);
-}
-
-static unsigned int txt_undo_read_unicode(const char *undo_buf, int *undo_pos, short bytes)
-{
- unsigned int unicode;
- char utf8[BLI_UTF8_MAX + 1];
-
- switch (bytes) {
- case 1: /* ascii */
- unicode = undo_buf[*undo_pos];
- (*undo_pos)--;
- break;
- case 2: /* 2-byte symbol */
- utf8[2] = '\0';
- utf8[1] = undo_buf[*undo_pos];
- (*undo_pos)--;
- utf8[0] = undo_buf[*undo_pos];
- (*undo_pos)--;
- unicode = BLI_str_utf8_as_unicode(utf8);
- break;
- case 3: /* 3-byte symbol */
- utf8[3] = '\0';
- utf8[2] = undo_buf[*undo_pos];
- (*undo_pos)--;
- utf8[1] = undo_buf[*undo_pos];
- (*undo_pos)--;
- utf8[0] = undo_buf[*undo_pos];
- (*undo_pos)--;
- unicode = BLI_str_utf8_as_unicode(utf8);
- break;
- case 4: /* 32-bit unicode symbol */
- unicode = txt_undo_read_uint32(undo_buf, undo_pos);
- break;
- default:
- /* should never happen */
- BLI_assert(0);
- unicode = 0;
- break;
- }
-
- return unicode;
-}
-
-static unsigned short txt_redo_read_uint16(const char *undo_buf, int *undo_pos)
-{
- unsigned short val;
- val = undo_buf[*undo_pos];
- (*undo_pos)++;
- val = val + (undo_buf[*undo_pos] << 8);
- (*undo_pos)++;
- return val;
-}
-
-static unsigned int txt_redo_read_uint32(const char *undo_buf, int *undo_pos)
-{
- unsigned int val;
- val = undo_buf[*undo_pos];
- (*undo_pos)++;
- val = val + (undo_buf[*undo_pos] << 8);
- (*undo_pos)++;
- val = val + (undo_buf[*undo_pos] << 16);
- (*undo_pos)++;
- val = val + (undo_buf[*undo_pos] << 24);
- (*undo_pos)++;
- return val;
-}
-
-/* redo read cur cursor from the undo buffer */
-static void txt_redo_read_cur(const char *undo_buf,
- int *undo_pos,
- unsigned int *curln,
- unsigned short *curc)
-{
- *curc = txt_redo_read_uint16(undo_buf, undo_pos);
- *curln = txt_redo_read_uint32(undo_buf, undo_pos);
-}
-
-/* redo read sel cursor from the undo buffer */
-static void txt_redo_read_sel(const char *undo_buf,
- int *undo_pos,
- unsigned int *selln,
- unsigned short *selc)
-{
- *selc = txt_redo_read_uint16(undo_buf, undo_pos);
- *selln = txt_redo_read_uint32(undo_buf, undo_pos);
-}
-
-/* redo read both cursors from the undo buffer */
-static void txt_redo_read_cursors(const char *undo_buf,
- int *undo_pos,
- unsigned int *curln,
- unsigned short *curc,
- unsigned int *selln,
- unsigned short *selc)
-{
- txt_redo_read_cur(undo_buf, undo_pos, curln, curc);
- txt_redo_read_sel(undo_buf, undo_pos, selln, selc);
-}
-
-static unsigned int txt_redo_read_unicode(const char *undo_buf, int *undo_pos, short bytes)
-{
- unsigned int unicode;
- char utf8[BLI_UTF8_MAX + 1];
-
- switch (bytes) {
- case 1: /* ascii */
- unicode = undo_buf[*undo_pos];
- (*undo_pos)++;
- break;
- case 2: /* 2-byte symbol */
- utf8[0] = undo_buf[*undo_pos];
- (*undo_pos)++;
- utf8[1] = undo_buf[*undo_pos];
- (*undo_pos)++;
- utf8[2] = '\0';
- unicode = BLI_str_utf8_as_unicode(utf8);
- break;
- case 3: /* 3-byte symbol */
- utf8[0] = undo_buf[*undo_pos];
- (*undo_pos)++;
- utf8[1] = undo_buf[*undo_pos];
- (*undo_pos)++;
- utf8[2] = undo_buf[*undo_pos];
- (*undo_pos)++;
- utf8[3] = '\0';
- unicode = BLI_str_utf8_as_unicode(utf8);
- break;
- case 4: /* 32-bit unicode symbol */
- unicode = txt_redo_read_uint32(undo_buf, undo_pos);
- break;
- default:
- /* should never happen */
- BLI_assert(0);
- unicode = 0;
- break;
- }
-
- return unicode;
-}
-
-void txt_do_undo(Text *text, TextUndoBuf *utxt)
-{
- int op = utxt->buf[utxt->pos];
- int prev_flags;
- unsigned int linep;
- unsigned int uni_char;
- unsigned int curln, selln;
- unsigned short curc, selc;
- unsigned short charp;
- char *buf;
-
- if (utxt->pos < 0) {
- return;
- }
-
- utxt->pos--;
-
- undoing = 1;
-
- switch (op) {
- case UNDO_INSERT_1:
- case UNDO_INSERT_2:
- case UNDO_INSERT_3:
- case UNDO_INSERT_4:
- utxt->pos -= op - UNDO_INSERT_1 + 1;
-
- /* get and restore the cursors */
- txt_undo_read_cur(utxt->buf, &utxt->pos, &curln, &curc);
- txt_move_to(text, curln, curc, 0);
- txt_move_to(text, curln, curc, 1);
-
- txt_delete_char(text, utxt);
-
- utxt->pos--;
- break;
-
- case UNDO_BS_1:
- case UNDO_BS_2:
- case UNDO_BS_3:
- case UNDO_BS_4:
- charp = op - UNDO_BS_1 + 1;
- uni_char = txt_undo_read_unicode(utxt->buf, &utxt->pos, charp);
-
- /* get and restore the cursors */
- txt_undo_read_cur(utxt->buf, &utxt->pos, &curln, &curc);
- txt_move_to(text, curln, curc, 0);
- txt_move_to(text, curln, curc, 1);
-
- txt_add_char(text, utxt, uni_char);
-
- utxt->pos--;
- break;
-
- case UNDO_DEL_1:
- case UNDO_DEL_2:
- case UNDO_DEL_3:
- case UNDO_DEL_4:
- charp = op - UNDO_DEL_1 + 1;
- uni_char = txt_undo_read_unicode(utxt->buf, &utxt->pos, charp);
-
- /* get and restore the cursors */
- txt_undo_read_cur(utxt->buf, &utxt->pos, &curln, &curc);
- txt_move_to(text, curln, curc, 0);
- txt_move_to(text, curln, curc, 1);
-
- txt_add_char(text, utxt, uni_char);
-
- txt_move_left(text, 0);
-
- utxt->pos--;
- break;
-
- case UNDO_DBLOCK: {
- int i;
- /* length of the string in the buffer */
- linep = txt_undo_read_uint32(utxt->buf, &utxt->pos);
-
- buf = MEM_mallocN(linep + 1, "dblock buffer");
- for (i = 0; i < linep; i++) {
- buf[(linep - 1) - i] = utxt->buf[utxt->pos];
- utxt->pos--;
- }
- buf[i] = 0;
-
- /* skip over the length that was stored again */
- utxt->pos -= 4;
-
- /* Get the cursor positions */
- txt_undo_read_cursors(utxt->buf, &utxt->pos, &curln, &curc, &selln, &selc);
-
- /* move cur to location that needs buff inserted */
- txt_move_to(text, curln, curc, 0);
-
- txt_insert_buf(text, utxt, buf);
- MEM_freeN(buf);
-
- /* restore the cursors */
- txt_move_to(text, curln, curc, 0);
- txt_move_to(text, selln, selc, 1);
-
- utxt->pos--;
-
- break;
- }
- case UNDO_IBLOCK: {
- int i;
- /* length of the string in the buffer */
- linep = txt_undo_read_uint32(utxt->buf, &utxt->pos);
-
- /* txt_backspace_char removes utf8-characters, not bytes */
- buf = MEM_mallocN(linep + 1, "iblock buffer");
- for (i = 0; i < linep; i++) {
- buf[(linep - 1) - i] = utxt->buf[utxt->pos];
- utxt->pos--;
- }
- buf[i] = 0;
- linep = BLI_strlen_utf8(buf);
- MEM_freeN(buf);
-
- /* skip over the length that was stored again */
- utxt->pos -= 4;
-
- /* get and restore the cursors */
- txt_undo_read_cursors(utxt->buf, &utxt->pos, &curln, &curc, &selln, &selc);
-
- txt_move_to(text, curln, curc, 0);
- txt_move_to(text, selln, selc, 1);
-
- if ((curln == selln) && (curc == selc)) {
- /* disable tabs to spaces since moving right may involve skipping multiple spaces */
- prev_flags = text->flags;
- text->flags &= ~TXT_TABSTOSPACES;
-
- for (i = 0; i < linep; i++) {
- txt_move_right(text, 1);
- }
-
- text->flags = prev_flags;
- }
-
- txt_delete_selected(text, utxt);
-
- utxt->pos--;
- break;
- }
- case UNDO_INDENT:
- case UNDO_COMMENT:
- case UNDO_DUPLICATE:
- case UNDO_MOVE_LINES_UP:
- case UNDO_MOVE_LINES_DOWN:
- /* get and restore the cursors */
- txt_undo_read_cursors(utxt->buf, &utxt->pos, &curln, &curc, &selln, &selc);
- txt_move_to(text, curln, curc, 0);
- txt_move_to(text, selln, selc, 1);
-
- if (op == UNDO_INDENT) {
- txt_unindent(text, utxt);
- }
- else if (op == UNDO_COMMENT) {
- txt_uncomment(text, utxt);
- }
- else if (op == UNDO_DUPLICATE) {
- txt_delete_line(text, text->curl->next);
- }
- else if (op == UNDO_MOVE_LINES_UP) {
- txt_move_lines(text, utxt, TXT_MOVE_LINE_DOWN);
- }
- else if (op == UNDO_MOVE_LINES_DOWN) {
- txt_move_lines(text, utxt, TXT_MOVE_LINE_UP);
- }
-
- utxt->pos--;
- break;
- case UNDO_UNINDENT:
- case UNDO_UNCOMMENT: {
- void (*txt_prefix_fn)(Text *, TextUndoBuf *);
- void (*txt_unprefix_fn)(Text *, TextUndoBuf *);
- int count;
- int i;
- /* Get and restore the cursors */
- txt_undo_read_cursors(utxt->buf, &utxt->pos, &curln, &curc, &selln, &selc);
- txt_move_to(text, curln, curc, 0);
- txt_move_to(text, selln, selc, 1);
-
- /* Un-unindent */
- if (op == UNDO_UNINDENT) {
- txt_prefix_fn = txt_indent;
- txt_unprefix_fn = txt_unindent;
- }
- else {
- txt_prefix_fn = txt_comment;
- txt_unprefix_fn = txt_uncomment;
- }
-
- txt_prefix_fn(text, utxt);
-
- /* Get the count */
- count = txt_undo_read_uint32(utxt->buf, &utxt->pos);
- /* Iterate! */
- txt_pop_sel(text);
-
- for (i = 0; i < count; i++) {
- txt_move_to(text, txt_undo_read_uint32(utxt->buf, &utxt->pos), 0, 0);
- /* Un-un-unindent/comment */
- txt_unprefix_fn(text, utxt);
- }
- /* Restore selection */
- txt_move_to(text, curln, curc, 0);
- txt_move_to(text, selln, selc, 1);
- /* Jumo over count */
- txt_undo_read_uint32(utxt->buf, &utxt->pos);
- /* Jump over closing OP byte */
- utxt->pos--;
- break;
- }
- default:
- // XXX error("Undo buffer error - resetting");
- utxt->pos = -1;
-
- break;
- }
-
- undoing = 0;
-}
-
-void txt_do_redo(Text *text, TextUndoBuf *utxt)
-{
- char op;
- char *buf;
- unsigned int linep;
- unsigned short charp;
- unsigned int uni_uchar;
- unsigned int curln, selln;
- unsigned short curc, selc;
-
- utxt->pos++;
- op = utxt->buf[utxt->pos];
-
- if (!op) {
- utxt->pos--;
- return;
- }
-
- undoing = 1;
-
- switch (op) {
- case UNDO_INSERT_1:
- case UNDO_INSERT_2:
- case UNDO_INSERT_3:
- case UNDO_INSERT_4:
- utxt->pos++;
-
- /* get and restore the cursors */
- txt_redo_read_cur(utxt->buf, &utxt->pos, &curln, &curc);
- txt_move_to(text, curln, curc, 0);
- txt_move_to(text, curln, curc, 1);
-
- charp = op - UNDO_INSERT_1 + 1;
- uni_uchar = txt_redo_read_unicode(utxt->buf, &utxt->pos, charp);
-
- txt_add_char(text, utxt, uni_uchar);
- break;
-
- case UNDO_BS_1:
- case UNDO_BS_2:
- case UNDO_BS_3:
- case UNDO_BS_4:
- utxt->pos++;
-
- /* get and restore the cursors */
- txt_redo_read_cur(utxt->buf, &utxt->pos, &curln, &curc);
- txt_move_to(text, curln, curc, 0);
- txt_move_to(text, curln, curc, 1);
-
- utxt->pos += op - UNDO_BS_1 + 1;
-
- /* move right so we backspace the correct char */
- txt_move_right(text, 0);
- txt_backspace_char(text, utxt);
-
- break;
-
- case UNDO_DEL_1:
- case UNDO_DEL_2:
- case UNDO_DEL_3:
- case UNDO_DEL_4:
- utxt->pos++;
-
- /* get and restore the cursors */
- txt_redo_read_cur(utxt->buf, &utxt->pos, &curln, &curc);
- txt_move_to(text, curln, curc, 0);
- txt_move_to(text, curln, curc, 1);
-
- utxt->pos += op - UNDO_DEL_1 + 1;
-
- txt_delete_char(text, utxt);
-
- break;
-
- case UNDO_DBLOCK:
- utxt->pos++;
-
- /* get and restore the cursors */
- txt_redo_read_cursors(utxt->buf, &utxt->pos, &curln, &curc, &selln, &selc);
- txt_move_to(text, curln, curc, 0);
- txt_move_to(text, selln, selc, 1);
-
- /* length of the block */
- linep = txt_redo_read_uint32(utxt->buf, &utxt->pos);
-
- utxt->pos += linep;
-
- /* skip over the length that was stored again */
- utxt->pos += 4;
-
- txt_delete_sel(text, utxt);
-
- break;
-
- case UNDO_IBLOCK:
- utxt->pos++;
-
- /* get and restore the cursors */
- txt_redo_read_cursors(utxt->buf, &utxt->pos, &curln, &curc, &selln, &selc);
- txt_move_to(text, curln, curc, 0);
- txt_move_to(text, curln, curc, 1);
-
- /* length of the block */
- linep = txt_redo_read_uint32(utxt->buf, &utxt->pos);
-
- buf = MEM_mallocN(linep + 1, "iblock buffer");
- memcpy(buf, &utxt->buf[utxt->pos], linep);
- utxt->pos += linep;
- buf[linep] = 0;
-
- txt_insert_buf(text, utxt, buf);
- MEM_freeN(buf);
-
- /* skip over the length that was stored again */
- utxt->pos += 4;
-
- break;
-
- case UNDO_INDENT:
- case UNDO_COMMENT:
- case UNDO_UNCOMMENT:
- case UNDO_DUPLICATE:
- case UNDO_MOVE_LINES_UP:
- case UNDO_MOVE_LINES_DOWN:
- utxt->pos++;
-
- /* get and restore the cursors */
- txt_redo_read_cursors(utxt->buf, &utxt->pos, &curln, &curc, &selln, &selc);
- txt_move_to(text, curln, curc, 0);
- txt_move_to(text, selln, selc, 1);
-
- if (op == UNDO_INDENT) {
- txt_indent(text, utxt);
- }
- else if (op == UNDO_COMMENT) {
- txt_comment(text, utxt);
- }
- else if (op == UNDO_UNCOMMENT) {
- txt_uncomment(text, utxt);
- }
- else if (op == UNDO_DUPLICATE) {
- txt_duplicate_line(text, utxt);
- }
- else if (op == UNDO_MOVE_LINES_UP) {
- /* offset the cursor by + 1 */
- txt_move_to(text, curln + 1, curc, 0);
- txt_move_to(text, selln + 1, selc, 1);
-
- txt_move_lines(text, utxt, TXT_MOVE_LINE_UP);
- }
- else if (op == UNDO_MOVE_LINES_DOWN) {
- /* offset the cursor by - 1 */
- txt_move_to(text, curln - 1, curc, 0);
- txt_move_to(text, selln - 1, selc, 1);
-
- txt_move_lines(text, utxt, TXT_MOVE_LINE_DOWN);
- }
-
- /* re-restore the cursors since they got moved when redoing */
- txt_move_to(text, curln, curc, 0);
- txt_move_to(text, selln, selc, 1);
-
- break;
- case UNDO_UNINDENT: {
- int count;
- int i;
-
- utxt->pos++;
- /* Scan all the stuff described in txt_undo_add_unindent_op */
- count = txt_redo_read_uint32(utxt->buf, &utxt->pos);
- for (i = 0; i < count; i++) {
- txt_redo_read_uint32(utxt->buf, &utxt->pos);
- }
- /* Count again */
- txt_redo_read_uint32(utxt->buf, &utxt->pos);
- /* Get the selection and re-unindent */
- txt_redo_read_cursors(utxt->buf, &utxt->pos, &curln, &curc, &selln, &selc);
- txt_move_to(text, curln, curc, 0);
- txt_move_to(text, selln, selc, 1);
- txt_unindent(text, utxt);
- break;
- }
- default:
- // XXX error("Undo buffer error - resetting");
- utxt->pos = -1;
-
- break;
- }
-
- undoing = 0;
}
/**************************/
/* Line editing functions */
/**************************/
-void txt_split_curline(Text *text, TextUndoBuf *utxt)
+void txt_split_curline(Text *text)
{
TextLine *ins;
char *left, *right;
@@ -2678,11 +1649,7 @@ void txt_split_curline(Text *text, TextUndoBuf *utxt)
return;
}
- txt_delete_sel(text, utxt);
-
- if (!undoing) {
- txt_undo_add_charop(text, utxt, UNDO_INSERT_1, '\n');
- }
+ txt_delete_sel(text);
/* Make the two half strings */
@@ -2765,7 +1732,7 @@ static void txt_combine_lines(Text *text, TextLine *linea, TextLine *lineb)
txt_clean_text(text);
}
-void txt_duplicate_line(Text *text, TextUndoBuf *utxt)
+void txt_duplicate_line(Text *text)
{
TextLine *textline;
@@ -2779,14 +1746,10 @@ void txt_duplicate_line(Text *text, TextUndoBuf *utxt)
txt_make_dirty(text);
txt_clean_text(text);
-
- if (!undoing) {
- txt_undo_add_op(text, utxt, UNDO_DUPLICATE);
- }
}
}
-void txt_delete_char(Text *text, TextUndoBuf *utxt)
+void txt_delete_char(Text *text)
{
unsigned int c = '\n';
@@ -2795,7 +1758,7 @@ void txt_delete_char(Text *text, TextUndoBuf *utxt)
}
if (txt_has_sel(text)) { /* deleting a selection */
- txt_delete_sel(text, utxt);
+ txt_delete_sel(text);
txt_make_dirty(text);
return;
}
@@ -2811,6 +1774,7 @@ void txt_delete_char(Text *text, TextUndoBuf *utxt)
else { /* Just deleting a char */
size_t c_len = 0;
c = BLI_str_utf8_as_unicode_and_size(text->curl->line + text->curc, &c_len);
+ UNUSED_VARS(c);
memmove(text->curl->line + text->curc,
text->curl->line + text->curc + c_len,
@@ -2823,20 +1787,16 @@ void txt_delete_char(Text *text, TextUndoBuf *utxt)
txt_make_dirty(text);
txt_clean_text(text);
-
- if (!undoing) {
- txt_undo_add_charop(text, utxt, UNDO_DEL_1, c);
- }
}
-void txt_delete_word(Text *text, TextUndoBuf *utxt)
+void txt_delete_word(Text *text)
{
txt_jump_right(text, true, true);
- txt_delete_sel(text, utxt);
+ txt_delete_sel(text);
txt_make_dirty(text);
}
-void txt_backspace_char(Text *text, TextUndoBuf *utxt)
+void txt_backspace_char(Text *text)
{
unsigned int c = '\n';
@@ -2845,7 +1805,7 @@ void txt_backspace_char(Text *text, TextUndoBuf *utxt)
}
if (txt_has_sel(text)) { /* deleting a selection */
- txt_delete_sel(text, utxt);
+ txt_delete_sel(text);
txt_make_dirty(text);
return;
}
@@ -2864,6 +1824,7 @@ void txt_backspace_char(Text *text, TextUndoBuf *utxt)
size_t c_len = 0;
const char *prev = BLI_str_prev_char_utf8(text->curl->line + text->curc);
c = BLI_str_utf8_as_unicode_and_size(prev, &c_len);
+ UNUSED_VARS(c);
/* source and destination overlap, don't use memcpy() */
memmove(text->curl->line + text->curc - c_len,
@@ -2878,16 +1839,12 @@ void txt_backspace_char(Text *text, TextUndoBuf *utxt)
txt_make_dirty(text);
txt_clean_text(text);
-
- if (!undoing) {
- txt_undo_add_charop(text, utxt, UNDO_BS_1, c);
- }
}
-void txt_backspace_word(Text *text, TextUndoBuf *utxt)
+void txt_backspace_word(Text *text)
{
txt_jump_left(text, true, true);
- txt_delete_sel(text, utxt);
+ txt_delete_sel(text);
txt_make_dirty(text);
}
@@ -2896,17 +1853,17 @@ void txt_backspace_word(Text *text, TextUndoBuf *utxt)
* Remember to change this string according to max tab size */
static char tab_to_spaces[] = " ";
-static void txt_convert_tab_to_spaces(Text *text, TextUndoBuf *utxt)
+static void txt_convert_tab_to_spaces(Text *text)
{
/* sb aims to pad adjust the tab-width needed so that the right number of spaces
* is added so that the indention of the line is the right width (i.e. aligned
* to multiples of TXT_TABSIZE)
*/
const char *sb = &tab_to_spaces[text->curc % TXT_TABSIZE];
- txt_insert_buf(text, utxt, sb);
+ txt_insert_buf(text, sb);
}
-static bool txt_add_char_intern(Text *text, TextUndoBuf *utxt, unsigned int add, bool replace_tabs)
+static bool txt_add_char_intern(Text *text, unsigned int add, bool replace_tabs)
{
char *tmp, ch[BLI_UTF8_MAX];
size_t add_len;
@@ -2916,21 +1873,17 @@ static bool txt_add_char_intern(Text *text, TextUndoBuf *utxt, unsigned int add,
}
if (add == '\n') {
- txt_split_curline(text, utxt);
+ txt_split_curline(text);
return true;
}
/* insert spaces rather than tabs */
if (add == '\t' && replace_tabs) {
- txt_convert_tab_to_spaces(text, utxt);
+ txt_convert_tab_to_spaces(text);
return true;
}
- txt_delete_sel(text, utxt);
-
- if (!undoing) {
- txt_undo_add_charop(text, utxt, UNDO_INSERT_1, add);
- }
+ txt_delete_sel(text);
add_len = BLI_str_utf8_from_unicode(add, ch);
@@ -2953,23 +1906,23 @@ static bool txt_add_char_intern(Text *text, TextUndoBuf *utxt, unsigned int add,
return 1;
}
-bool txt_add_char(Text *text, TextUndoBuf *utxt, unsigned int add)
+bool txt_add_char(Text *text, unsigned int add)
{
- return txt_add_char_intern(text, utxt, add, (text->flags & TXT_TABSTOSPACES) != 0);
+ return txt_add_char_intern(text, add, (text->flags & TXT_TABSTOSPACES) != 0);
}
-bool txt_add_raw_char(Text *text, TextUndoBuf *utxt, unsigned int add)
+bool txt_add_raw_char(Text *text, unsigned int add)
{
- return txt_add_char_intern(text, utxt, add, 0);
+ return txt_add_char_intern(text, add, 0);
}
-void txt_delete_selected(Text *text, TextUndoBuf *utxt)
+void txt_delete_selected(Text *text)
{
- txt_delete_sel(text, utxt);
+ txt_delete_sel(text);
txt_make_dirty(text);
}
-bool txt_replace_char(Text *text, TextUndoBuf *utxt, unsigned int add)
+bool txt_replace_char(Text *text, unsigned int add)
{
unsigned int del;
size_t del_size = 0, add_size;
@@ -2981,10 +1934,11 @@ bool txt_replace_char(Text *text, TextUndoBuf *utxt, unsigned int add)
/* If text is selected or we're at the end of the line just use txt_add_char */
if (text->curc == text->curl->len || txt_has_sel(text) || add == '\n') {
- return txt_add_char(text, utxt, add);
+ return txt_add_char(text, add);
}
del = BLI_str_utf8_as_unicode_and_size(text->curl->line + text->curc, &del_size);
+ UNUSED_VARS(del);
add_size = BLI_str_utf8_from_unicode(add, ch);
if (add_size > del_size) {
@@ -3010,16 +1964,6 @@ bool txt_replace_char(Text *text, TextUndoBuf *utxt, unsigned int add)
txt_pop_sel(text);
txt_make_dirty(text);
txt_clean_text(text);
-
- /* Should probably create a new op for this */
- if (!undoing) {
- txt_undo_add_charop(text, utxt, UNDO_INSERT_1, add);
- text->curc -= add_size;
- txt_pop_sel(text);
- txt_undo_add_charop(text, utxt, UNDO_DEL_1, del);
- text->curc += add_size;
- txt_pop_sel(text);
- }
return true;
}
@@ -3098,26 +2042,14 @@ static void txt_select_prefix(Text *text, const char *add)
*
* \note caller must handle undo.
*/
-static void txt_select_unprefix(Text *text,
- const char *remove,
- ListBase *r_line_index_mask,
- int *r_line_index_mask_len)
+static void txt_select_unprefix(Text *text, const char *remove)
{
int num = 0;
const int indentlen = strlen(remove);
bool unindented_first = false;
- int curl_span_init = 0;
-
BLI_assert(!ELEM(NULL, text->curl, text->sell));
- BLI_listbase_clear(r_line_index_mask);
- *r_line_index_mask_len = 0;
-
- if (!undoing) {
- curl_span_init = txt_get_span(text->lines.first, text->curl);
- }
-
while (true) {
bool changed = false;
if (STREQLEN(text->curl->line, remove, indentlen)) {
@@ -3128,16 +2060,6 @@ static void txt_select_unprefix(Text *text,
memmove(text->curl->line, text->curl->line + indentlen, text->curl->len + 1);
changed = true;
}
- else {
- if (!undoing) {
- /* Create list element for 0 indent line */
- struct LinkInt *idata = MEM_mallocN(sizeof(struct LinkInt), __func__);
- idata->value = curl_span_init + num;
- BLI_assert(idata->value == txt_get_span(text->lines.first, text->curl));
- BLI_addtail(r_line_index_mask, idata);
- (*r_line_index_mask_len) += 1;
- }
- }
txt_make_dirty(text);
txt_clean_text(text);
@@ -3166,7 +2088,7 @@ static void txt_select_unprefix(Text *text,
/* caller must handle undo */
}
-void txt_comment(Text *text, TextUndoBuf *utxt)
+void txt_comment(Text *text)
{
const char *prefix = "#";
@@ -3175,32 +2097,20 @@ void txt_comment(Text *text, TextUndoBuf *utxt)
}
txt_select_prefix(text, prefix);
-
- if (!undoing) {
- txt_undo_add_op(text, utxt, UNDO_COMMENT);
- }
}
-void txt_uncomment(Text *text, TextUndoBuf *utxt)
+void txt_uncomment(Text *text)
{
const char *prefix = "#";
- ListBase line_index_mask;
- int line_index_mask_len;
if (ELEM(NULL, text->curl, text->sell)) {
return;
}
- txt_select_unprefix(text, prefix, &line_index_mask, &line_index_mask_len);
-
- if (!undoing) {
- txt_undo_add_unprefix_op(text, utxt, UNDO_UNCOMMENT, &line_index_mask, line_index_mask_len);
- }
-
- BLI_freelistN(&line_index_mask);
+ txt_select_unprefix(text, prefix);
}
-void txt_indent(Text *text, TextUndoBuf *utxt)
+void txt_indent(Text *text)
{
const char *prefix = (text->flags & TXT_TABSTOSPACES) ? tab_to_spaces : "\t";
@@ -3209,32 +2119,20 @@ void txt_indent(Text *text, TextUndoBuf *utxt)
}
txt_select_prefix(text, prefix);
-
- if (!undoing) {
- txt_undo_add_op(text, utxt, UNDO_INDENT);
- }
}
-void txt_unindent(Text *text, TextUndoBuf *utxt)
+void txt_unindent(Text *text)
{
const char *prefix = (text->flags & TXT_TABSTOSPACES) ? tab_to_spaces : "\t";
- ListBase line_index_mask;
- int line_index_mask_len;
if (ELEM(NULL, text->curl, text->sell)) {
return;
}
- txt_select_unprefix(text, prefix, &line_index_mask, &line_index_mask_len);
-
- if (!undoing) {
- txt_undo_add_unprefix_op(text, utxt, UNDO_UNINDENT, &line_index_mask, line_index_mask_len);
- }
-
- BLI_freelistN(&line_index_mask);
+ txt_select_unprefix(text, prefix);
}
-void txt_move_lines(struct Text *text, TextUndoBuf *utxt, const int direction)
+void txt_move_lines(struct Text *text, const int direction)
{
TextLine *line_other;
@@ -3263,11 +2161,6 @@ void txt_move_lines(struct Text *text, TextUndoBuf *utxt, const int direction)
txt_make_dirty(text);
txt_clean_text(text);
-
- if (!undoing) {
- txt_undo_add_op(
- text, utxt, (direction == TXT_MOVE_LINE_DOWN) ? UNDO_MOVE_LINES_DOWN : UNDO_MOVE_LINES_UP);
- }
}
int txt_setcurr_tab_spaces(Text *text, int space)
diff --git a/source/blender/depsgraph/intern/builder/deg_builder_relations.cc b/source/blender/depsgraph/intern/builder/deg_builder_relations.cc
index c59fb5f2a38..86cbb330170 100644
--- a/source/blender/depsgraph/intern/builder/deg_builder_relations.cc
+++ b/source/blender/depsgraph/intern/builder/deg_builder_relations.cc
@@ -379,6 +379,14 @@ void DepsgraphRelationBuilder::add_particle_forcefield_relations(const Operation
{
ListBase *relations = build_effector_relations(graph_, eff->group);
+ /* Make sure physics effects like wind are properly re-evaluating the modifier stack. */
+ if (!BLI_listbase_is_empty(relations)) {
+ TimeSourceKey time_src_key;
+ ComponentKey geometry_key(&object->id, NodeType::GEOMETRY);
+ add_relation(
+ time_src_key, geometry_key, "Effector Time -> Particle", RELATION_CHECK_BEFORE_ADD);
+ }
+
LISTBASE_FOREACH (EffectorRelation *, relation, relations) {
if (relation->ob != object) {
/* Relation to forcefield object, optionally including geometry. */
diff --git a/source/blender/draw/engines/eevee/eevee_effects.c b/source/blender/draw/engines/eevee/eevee_effects.c
index 021afa64fee..1b152afa3bf 100644
--- a/source/blender/draw/engines/eevee/eevee_effects.c
+++ b/source/blender/draw/engines/eevee/eevee_effects.c
@@ -161,6 +161,12 @@ void EEVEE_effects_init(EEVEE_ViewLayerData *sldata,
effects->enabled_effects |= EEVEE_occlusion_init(sldata, vedata);
effects->enabled_effects |= EEVEE_screen_raytrace_init(sldata, vedata);
+ if ((effects->enabled_effects & EFFECT_TAA) && effects->taa_current_sample > 1) {
+ /* Update matrices here because EEVEE_screen_raytrace_init can have reset the
+ * taa_current_sample. (See T66811) */
+ EEVEE_temporal_sampling_update_matrices(vedata);
+ }
+
EEVEE_volumes_init(sldata, vedata);
EEVEE_subsurface_init(sldata, vedata);
diff --git a/source/blender/draw/engines/eevee/eevee_temporal_sampling.c b/source/blender/draw/engines/eevee/eevee_temporal_sampling.c
index 099147a82dd..96924efa8bc 100644
--- a/source/blender/draw/engines/eevee/eevee_temporal_sampling.c
+++ b/source/blender/draw/engines/eevee/eevee_temporal_sampling.c
@@ -253,7 +253,6 @@ int EEVEE_temporal_sampling_init(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data
if (!DRW_state_is_image_render()) {
effects->taa_current_sample += 1;
repro_flag = 0;
- EEVEE_temporal_sampling_update_matrices(vedata);
}
}
else {
diff --git a/source/blender/draw/engines/workbench/workbench_materials.c b/source/blender/draw/engines/workbench/workbench_materials.c
index 1473b7df279..6699a1954ba 100644
--- a/source/blender/draw/engines/workbench/workbench_materials.c
+++ b/source/blender/draw/engines/workbench/workbench_materials.c
@@ -317,33 +317,31 @@ void workbench_material_shgroup_uniform(WORKBENCH_PrivateData *wpd,
const bool deferred,
const int interp)
{
- if (deferred && !workbench_is_matdata_pass_enabled(wpd)) {
- return;
- }
-
- if (workbench_material_determine_color_type(wpd, material->ima, ob, false) ==
- V3D_SHADING_TEXTURE_COLOR) {
- GPUTexture *tex = GPU_texture_from_blender(material->ima, material->iuser, GL_TEXTURE_2D);
- DRW_shgroup_uniform_texture(grp, "image", tex);
- DRW_shgroup_uniform_bool_copy(
- grp, "imagePremultiplied", (material->ima->alpha_mode == IMA_ALPHA_PREMUL));
- DRW_shgroup_uniform_bool_copy(grp, "imageNearest", (interp == SHD_INTERP_CLOSEST));
- }
- else {
- DRW_shgroup_uniform_vec3(grp,
- "materialDiffuseColor",
- (use_metallic) ? material->base_color : material->diffuse_color,
- 1);
- }
-
- if (SPECULAR_HIGHLIGHT_ENABLED(wpd)) {
- if (use_metallic) {
- DRW_shgroup_uniform_float(grp, "materialMetallic", &material->metallic, 1);
+ if (!deferred || workbench_is_matdata_pass_enabled(wpd)) {
+ if (workbench_material_determine_color_type(wpd, material->ima, ob, false) ==
+ V3D_SHADING_TEXTURE_COLOR) {
+ GPUTexture *tex = GPU_texture_from_blender(material->ima, material->iuser, GL_TEXTURE_2D);
+ DRW_shgroup_uniform_texture(grp, "image", tex);
+ DRW_shgroup_uniform_bool_copy(
+ grp, "imagePremultiplied", (material->ima->alpha_mode == IMA_ALPHA_PREMUL));
+ DRW_shgroup_uniform_bool_copy(grp, "imageNearest", (interp == SHD_INTERP_CLOSEST));
}
else {
- DRW_shgroup_uniform_vec3(grp, "materialSpecularColor", material->specular_color, 1);
+ DRW_shgroup_uniform_vec3(grp,
+ "materialDiffuseColor",
+ (use_metallic) ? material->base_color : material->diffuse_color,
+ 1);
+ }
+
+ if (SPECULAR_HIGHLIGHT_ENABLED(wpd)) {
+ if (use_metallic) {
+ DRW_shgroup_uniform_float(grp, "materialMetallic", &material->metallic, 1);
+ }
+ else {
+ DRW_shgroup_uniform_vec3(grp, "materialSpecularColor", material->specular_color, 1);
+ }
+ DRW_shgroup_uniform_float(grp, "materialRoughness", &material->roughness, 1);
}
- DRW_shgroup_uniform_float(grp, "materialRoughness", &material->roughness, 1);
}
if (WORLD_CLIPPING_ENABLED(wpd)) {
diff --git a/source/blender/draw/intern/draw_armature.c b/source/blender/draw/intern/draw_armature.c
index f97efa9aed9..30e51333f0f 100644
--- a/source/blender/draw/intern/draw_armature.c
+++ b/source/blender/draw/intern/draw_armature.c
@@ -1978,6 +1978,7 @@ static void draw_armature_edit(Object *ob)
static void draw_armature_pose(Object *ob, const float const_color[4])
{
const DRWContextState *draw_ctx = DRW_context_state_get();
+ const Scene *scene = draw_ctx->scene;
bArmature *arm = ob->data;
bPoseChannel *pchan;
int index = -1;
@@ -1990,19 +1991,35 @@ static void draw_armature_pose(Object *ob, const float const_color[4])
return;
}
- // if (!(base->flag & OB_FROMDUPLI)) // TODO
- {
+ bool is_pose_select = false;
+ /* Object can be edited in the scene. */
+ if ((ob->base_flag & (BASE_FROM_SET | BASE_FROM_DUPLI)) == 0) {
if ((draw_ctx->object_mode & OB_MODE_POSE) || (ob == draw_ctx->object_pose)) {
arm->flag |= ARM_POSEMODE;
}
+ is_pose_select =
+ /* If we're in pose-mode or object-mode with the ability to enter pose mode. */
+ (
+ /* Draw as if in pose mode (when selection is possible). */
+ (arm->flag & ARM_POSEMODE) ||
+ /* When we're in object mode, which may select bones. */
+ ((ob->mode & OB_MODE_POSE) &&
+ (
+ /* Switch from object mode when object lock is disabled. */
+ ((draw_ctx->object_mode == OB_MODE_OBJECT) &&
+ (scene->toolsettings->object_flag & SCE_OBJECT_MODE_LOCK) == 0) ||
+ /* Allow selection when in weight-paint mode
+ * (selection code ensures this wont become active). */
+ ((draw_ctx->object_mode == OB_MODE_WEIGHT_PAINT) &&
+ (draw_ctx->object_pose != NULL))))) &&
+ DRW_state_is_select();
- if (arm->flag & ARM_POSEMODE) {
+ if (is_pose_select) {
const Object *ob_orig = DEG_get_original_object(ob);
index = ob_orig->runtime.select_id;
}
}
- const bool is_pose_select = (arm->flag & ARM_POSEMODE) && DRW_state_is_select();
const bool show_text = DRW_state_show_text();
const bool show_relations = ((draw_ctx->v3d->flag & V3D_HIDE_HELPLINES) == 0);
diff --git a/source/blender/draw/modes/shaders/particle_strand_vert.glsl b/source/blender/draw/modes/shaders/particle_strand_vert.glsl
index c3f8fb89c17..45fadb4ed5e 100644
--- a/source/blender/draw/modes/shaders/particle_strand_vert.glsl
+++ b/source/blender/draw/modes/shaders/particle_strand_vert.glsl
@@ -55,16 +55,17 @@ void main()
#endif
#ifdef USE_POINTS
- gl_PointSize = sizeVertex;
+ float size = sizeVertex * 2.0;
+ gl_PointSize = size;
/* calculate concentric radii in pixels */
- float radius = 0.5 * sizeVertex;
+ float radius = sizeVertex;
/* start at the outside and progress toward the center */
radii[0] = radius;
radii[1] = radius - 1.0;
/* convert to PointCoord units */
- radii /= sizeVertex;
+ radii /= size;
#endif
}
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/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/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_primitive.c b/source/blender/editors/gpencil/gpencil_primitive.c
index 540dd14fe1d..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) {
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_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/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_ops.c b/source/blender/editors/interface/interface_ops.c
index 7d2ccd9c3ec..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;
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/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/object/object_constraint.c b/source/blender/editors/object/object_constraint.c
index 9c23daab923..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"
@@ -1815,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/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_vertex.c b/source/blender/editors/sculpt_paint/paint_vertex.c
index 0c08af2b020..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);
+ }
+ }
+ }
+ }
+ }
+ }
}
}
}
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_outliner/outliner_draw.c b/source/blender/editors/space_outliner/outliner_draw.c
index 31783e09aeb..55130ae8894 100644
--- a/source/blender/editors/space_outliner/outliner_draw.c
+++ b/source/blender/editors/space_outliner/outliner_draw.c
@@ -933,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,
@@ -1337,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) {
@@ -1563,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);
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 33bacb0a95f..4992a73f936 100644
--- a/source/blender/editors/space_text/text_ops.c
+++ b/source/blender/editors/space_text/text_ops.c
@@ -840,7 +840,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 +849,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 +893,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);
@@ -971,8 +971,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 +1008,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 +1049,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 +1090,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 +1139,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 +1177,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 +1446,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 +2230,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 +2252,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 +2274,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);
@@ -3190,18 +3190,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);
}
}
@@ -3319,8 +3319,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;
diff --git a/source/blender/editors/space_text/text_undo.c b/source/blender/editors/space_text/text_undo.c
index 66cbaa8bb5b..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,104 +105,66 @@ 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;
+
+ 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_p->is_applied = true;
+ us->data.state = BLI_array_store_state_add(g_text_buffers.buffer_store, buf, buf_len, NULL);
+ MEM_freeN(buf);
- us->text_ref.ptr = text;
+ us->cursor.line = txt_get_span(text->lines.first, text->curl);
+ us->cursor.column = text->curc;
- us->step.data_size = us->data.len;
-
- return true;
-}
-
-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(TextUndoStep *us, bool is_final)
-{
- 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;
- }
- Text *text_prev = NULL;
- while ((us_iter != us) || (is_final && us_iter == us)) {
- Text *text = us_iter->text_ref.ptr;
- text_undosys_step_decode_undo_impl(text, us_iter);
- if (text_prev != text) {
- text_update_edited(text);
- text_prev = text;
- }
- if (is_final) {
- break;
- }
- us_iter = (TextUndoStep *)us_iter->step.prev;
- }
-}
+ us_p->is_applied = true;
-static void text_undosys_step_decode_redo(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;
- }
- Text *text_prev = NULL;
- while (us_iter && (us_iter->step.is_applied == false)) {
- Text *text = us_iter->text_ref.ptr;
- text_undosys_step_decode_redo_impl(text, us_iter);
- if (text_prev != text) {
- text_update_edited(text);
- text_prev = text;
- }
- 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, bool is_final)
+static void text_undosys_step_decode(struct bContext *C,
+ struct Main *UNUSED(bmain),
+ UndoStep *us_p,
+ 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(us, is_final);
+ {
+ 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(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);
- Text *text = us->text_ref.ptr;
SpaceText *st = CTX_wm_space_text(C);
if (st) {
/* Not essential, always show text being undo where possible. */
@@ -204,7 +178,14 @@ static void text_undosys_step_decode(
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,
@@ -240,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 c932d537b54..1ec459ccfca 100644
--- a/source/blender/editors/space_userpref/userpref_ops.c
+++ b/source/blender/editors/space_userpref/userpref_ops.c
@@ -72,39 +72,7 @@ static void PREFERENCES_OT_reset_default_theme(wmOperatorType *ot)
/** \} */
-/* -------------------------------------------------------------------- */
-/** \name Toggle Auto-Save Override
- *
- * This operator only exists so there is a useful tool-tip for for adjusting the global flag.
- * \{ */
-
-static int preferences_autosave_override_toggle_exec(bContext *UNUSED(C), wmOperator *UNUSED(op))
-{
- G.f ^= G_FLAG_USERPREF_NO_SAVE_ON_EXIT;
- return OPERATOR_FINISHED;
-}
-
-static void PREFERENCES_OT_autosave_override_toggle(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name = "Toggle Override Auto-Save";
- ot->idname = "PREFERENCES_OT_autosave_override_toggle";
- ot->description =
- "The current session has \"Factory Preferences\" loaded "
- "which disables automatically saving.\n"
- "Disable this to auto-save the preferences";
-
- /* callbacks */
- ot->exec = preferences_autosave_override_toggle_exec;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER;
-}
-
-/** \} */
-
void ED_operatortypes_userpref(void)
{
WM_operatortype_append(PREFERENCES_OT_reset_default_theme);
- WM_operatortype_append(PREFERENCES_OT_autosave_override_toggle);
}
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_edit.c b/source/blender/editors/space_view3d/view3d_edit.c
index 38cec8add6b..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 {
diff --git a/source/blender/editors/space_view3d/view3d_select.c b/source/blender/editors/space_view3d/view3d_select.c
index 0df5652c539..61de61c8e31 100644
--- a/source/blender/editors/space_view3d/view3d_select.c
+++ b/source/blender/editors/space_view3d/view3d_select.c
@@ -2321,10 +2321,15 @@ static bool ed_object_select_pick(bContext *C,
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;
}
}
@@ -2395,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);
}
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 7c4f9f1d95b..a316567fc63 100644
--- a/source/blender/editors/transform/transform.c
+++ b/source/blender/editors/transform/transform.c
@@ -6703,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);
@@ -7679,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,
@@ -7705,7 +7728,7 @@ void freeEdgeSlideVerts(TransInfo *UNUSED(t),
{
EdgeSlideData *sld = custom_data->data;
- if (!sld) {
+ if (sld == NULL) {
return;
}
@@ -7847,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 */
@@ -7968,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;
@@ -7979,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);
@@ -7992,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];
@@ -8028,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_conversions.c b/source/blender/editors/transform/transform_conversions.c
index f7158244cc7..d13c0f8e8f1 100644
--- a/source/blender/editors/transform/transform_conversions.c
+++ b/source/blender/editors/transform/transform_conversions.c
@@ -7100,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/imbuf/intern/openexr/openexr_api.cpp b/source/blender/imbuf/intern/openexr/openexr_api.cpp
index 69dec88e727..c9883d5df86 100644
--- a/source/blender/imbuf/intern/openexr/openexr_api.cpp
+++ b/source/blender/imbuf/intern/openexr/openexr_api.cpp
@@ -1762,32 +1762,11 @@ static bool imb_exr_is_multilayer_file(MultiPartInputFile &file)
const ChannelList &channels = file.header(0).channels();
std::set<std::string> layerNames;
- /* will not include empty layer names */
+ /* This will not include empty layer names, so files with just R/G/B/A
+ * channels without a layer name will be single layer. */
channels.layers(layerNames);
- if (layerNames.size() > 1) {
- return true;
- }
-
- if (layerNames.size()) {
- /* if layerNames is not empty, it means at least one layer is non-empty,
- * but it also could be layers without names in the file and such case
- * shall be considered a multilayer exr
- *
- * that's what we do here: test whether they're empty layer names together
- * with non-empty ones in the file
- */
- for (ChannelList::ConstIterator i = channels.begin(); i != channels.end(); i++) {
- std::string layerName = i.name();
- size_t pos = layerName.rfind('.');
-
- if (pos == std::string::npos) {
- return true;
- }
- }
- }
-
- return false;
+ return (layerNames.size() > 0);
}
static void imb_exr_type_by_channels(ChannelList &channels,
diff --git a/source/blender/makesdna/DNA_text_types.h b/source/blender/makesdna/DNA_text_types.h
index 8dfaf95a10a..4eec2c1fde8 100644
--- a/source/blender/makesdna/DNA_text_types.h
+++ b/source/blender/makesdna/DNA_text_types.h
@@ -55,8 +55,6 @@ typedef struct Text {
} Text;
#define TXT_TABSIZE 4
-#define TXT_INIT_UNDO 1024
-#define TXT_MAX_UNDO (TXT_INIT_UNDO * TXT_INIT_UNDO)
/* text flags */
enum {
diff --git a/source/blender/makesrna/intern/rna_armature.c b/source/blender/makesrna/intern/rna_armature.c
index aef35684ff7..6737363bae4 100644
--- a/source/blender/makesrna/intern/rna_armature.c
+++ b/source/blender/makesrna/intern/rna_armature.c
@@ -268,18 +268,6 @@ static IDProperty *rna_EditBone_idprops(PointerRNA *ptr, bool create)
return ebone->prop;
}
-/* 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.
- */
-static void rna_Armature_layer_used_refresh(bArmature *arm, ListBase *bones)
-{
- for (Bone *bone = bones->first; bone; bone = bone->next) {
- arm->layer_used |= bone->layer;
- rna_Armature_layer_used_refresh(arm, &bone->childbase);
- }
-}
-
static void rna_bone_layer_set(int *layer, const bool *values)
{
int i, tot = 0;
@@ -312,8 +300,7 @@ static void rna_Bone_layer_set(PointerRNA *ptr, const bool *values)
rna_bone_layer_set(&bone->layer, values);
- arm->layer_used = 0;
- rna_Armature_layer_used_refresh(arm, &arm->bonebase);
+ BKE_armature_refresh_layer_used(arm);
}
static void rna_Armature_layer_set(PointerRNA *ptr, const bool *values)
diff --git a/source/blender/makesrna/intern/rna_object_api.c b/source/blender/makesrna/intern/rna_object_api.c
index a891e11a944..15f79ea3e89 100644
--- a/source/blender/makesrna/intern/rna_object_api.c
+++ b/source/blender/makesrna/intern/rna_object_api.c
@@ -98,11 +98,13 @@ static void rna_Object_select_set(
Base *base = BKE_view_layer_base_find(view_layer, ob);
if (!base) {
- BKE_reportf(reports,
- RPT_ERROR,
- "Object '%s' not in View Layer '%s'!",
- ob->id.name + 2,
- view_layer->name);
+ if (select) {
+ BKE_reportf(reports,
+ RPT_ERROR,
+ "Object '%s' can't be selected because it is not in View Layer '%s'!",
+ ob->id.name + 2,
+ view_layer->name);
+ }
return;
}
@@ -113,10 +115,7 @@ static void rna_Object_select_set(
WM_main_add_notifier(NC_SCENE | ND_OB_SELECT, scene);
}
-static bool rna_Object_select_get(Object *ob,
- bContext *C,
- ReportList *reports,
- ViewLayer *view_layer)
+static bool rna_Object_select_get(Object *ob, bContext *C, ViewLayer *view_layer)
{
if (view_layer == NULL) {
view_layer = CTX_data_view_layer(C);
@@ -124,11 +123,6 @@ static bool rna_Object_select_get(Object *ob,
Base *base = BKE_view_layer_base_find(view_layer, ob);
if (!base) {
- BKE_reportf(reports,
- RPT_ERROR,
- "Object '%s' not in View Layer '%s'!",
- ob->id.name + 2,
- view_layer->name);
return false;
}
@@ -144,11 +138,13 @@ static void rna_Object_hide_set(
Base *base = BKE_view_layer_base_find(view_layer, ob);
if (!base) {
- BKE_reportf(reports,
- RPT_ERROR,
- "Object '%s' not in View Layer '%s'!",
- ob->id.name + 2,
- view_layer->name);
+ if (hide) {
+ BKE_reportf(reports,
+ RPT_ERROR,
+ "Object '%s' can't be hidden because it is not in View Layer '%s'!",
+ ob->id.name + 2,
+ view_layer->name);
+ }
return;
}
@@ -165,10 +161,7 @@ static void rna_Object_hide_set(
WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene);
}
-static bool rna_Object_hide_get(Object *ob,
- bContext *C,
- ReportList *reports,
- ViewLayer *view_layer)
+static bool rna_Object_hide_get(Object *ob, bContext *C, ViewLayer *view_layer)
{
if (view_layer == NULL) {
view_layer = CTX_data_view_layer(C);
@@ -176,19 +169,13 @@ static bool rna_Object_hide_get(Object *ob,
Base *base = BKE_view_layer_base_find(view_layer, ob);
if (!base) {
- BKE_reportf(reports,
- RPT_ERROR,
- "Object '%s' not in View Layer '%s'!",
- ob->id.name + 2,
- view_layer->name);
return false;
}
return ((base->flag & BASE_HIDDEN) != 0);
}
-static bool rna_Object_visible_get(
- Object *ob, bContext *C, ReportList *reports, ViewLayer *view_layer, View3D *v3d)
+static bool rna_Object_visible_get(Object *ob, bContext *C, ViewLayer *view_layer, View3D *v3d)
{
if (view_layer == NULL) {
view_layer = CTX_data_view_layer(C);
@@ -199,21 +186,13 @@ static bool rna_Object_visible_get(
Base *base = BKE_view_layer_base_find(view_layer, ob);
if (!base) {
- BKE_reportf(reports,
- RPT_ERROR,
- "Object '%s' not in View Layer '%s'!",
- ob->id.name + 2,
- view_layer->name);
return false;
}
return BASE_VISIBLE(v3d, base);
}
-static bool rna_Object_holdout_get(Object *ob,
- bContext *C,
- ReportList *reports,
- ViewLayer *view_layer)
+static bool rna_Object_holdout_get(Object *ob, bContext *C, ViewLayer *view_layer)
{
if (view_layer == NULL) {
view_layer = CTX_data_view_layer(C);
@@ -221,21 +200,13 @@ static bool rna_Object_holdout_get(Object *ob,
Base *base = BKE_view_layer_base_find(view_layer, ob);
if (!base) {
- BKE_reportf(reports,
- RPT_ERROR,
- "Object '%s' not in View Layer '%s'!",
- ob->id.name + 2,
- view_layer->name);
return false;
}
return ((base->flag & BASE_HOLDOUT) != 0);
}
-static bool rna_Object_indirect_only_get(Object *ob,
- bContext *C,
- ReportList *reports,
- ViewLayer *view_layer)
+static bool rna_Object_indirect_only_get(Object *ob, bContext *C, ViewLayer *view_layer)
{
if (view_layer == NULL) {
view_layer = CTX_data_view_layer(C);
@@ -243,11 +214,6 @@ static bool rna_Object_indirect_only_get(Object *ob,
Base *base = BKE_view_layer_base_find(view_layer, ob);
if (!base) {
- BKE_reportf(reports,
- RPT_ERROR,
- "Object '%s' not in View Layer '%s'!",
- ob->id.name + 2,
- view_layer->name);
return false;
}
@@ -741,7 +707,7 @@ void RNA_api_object(StructRNA *srna)
func = RNA_def_function(srna, "select_get", "rna_Object_select_get");
RNA_def_function_ui_description(
func, "Test if the object is selected. The selection state is per view layer");
- RNA_def_function_flag(func, FUNC_USE_CONTEXT | FUNC_USE_REPORTS);
+ RNA_def_function_flag(func, FUNC_USE_CONTEXT);
parm = RNA_def_pointer(
func, "view_layer", "ViewLayer", "", "Use this instead of the active view layer");
parm = RNA_def_boolean(func, "result", 0, "", "Object selected");
@@ -760,7 +726,7 @@ void RNA_api_object(StructRNA *srna)
RNA_def_function_ui_description(
func,
"Test if the object is hidden for viewport editing. This hiding state is per view layer");
- RNA_def_function_flag(func, FUNC_USE_CONTEXT | FUNC_USE_REPORTS);
+ RNA_def_function_flag(func, FUNC_USE_CONTEXT);
parm = RNA_def_pointer(
func, "view_layer", "ViewLayer", "", "Use this instead of the active view layer");
parm = RNA_def_boolean(func, "result", 0, "", "Object hideed");
@@ -779,7 +745,7 @@ void RNA_api_object(StructRNA *srna)
RNA_def_function_ui_description(func,
"Test if the object is visible in the 3D viewport, taking into "
"account all visibility settings");
- RNA_def_function_flag(func, FUNC_USE_CONTEXT | FUNC_USE_REPORTS);
+ RNA_def_function_flag(func, FUNC_USE_CONTEXT);
parm = RNA_def_pointer(
func, "view_layer", "ViewLayer", "", "Use this instead of the active view layer");
parm = RNA_def_pointer(
@@ -789,7 +755,7 @@ void RNA_api_object(StructRNA *srna)
func = RNA_def_function(srna, "holdout_get", "rna_Object_holdout_get");
RNA_def_function_ui_description(func, "Test if object is masked in the view layer");
- RNA_def_function_flag(func, FUNC_USE_CONTEXT | FUNC_USE_REPORTS);
+ RNA_def_function_flag(func, FUNC_USE_CONTEXT);
parm = RNA_def_pointer(
func, "view_layer", "ViewLayer", "", "Use this instead of the active view layer");
parm = RNA_def_boolean(func, "result", 0, "", "Object holdout");
@@ -799,7 +765,7 @@ void RNA_api_object(StructRNA *srna)
RNA_def_function_ui_description(func,
"Test if object is set to contribute only indirectly (through "
"shadows and reflections) in the view layer");
- RNA_def_function_flag(func, FUNC_USE_CONTEXT | FUNC_USE_REPORTS);
+ RNA_def_function_flag(func, FUNC_USE_CONTEXT);
parm = RNA_def_pointer(
func, "view_layer", "ViewLayer", "", "Use this instead of the active view layer");
parm = RNA_def_boolean(func, "result", 0, "", "Object indirect only");
diff --git a/source/blender/makesrna/intern/rna_object_force.c b/source/blender/makesrna/intern/rna_object_force.c
index c97491a92c6..ab6cffe615d 100644
--- a/source/blender/makesrna/intern/rna_object_force.c
+++ b/source/blender/makesrna/intern/rna_object_force.c
@@ -523,6 +523,8 @@ static void rna_FieldSettings_shape_update(Main *bmain, Scene *scene, PointerRNA
if (!particle_id_check(ptr)) {
Object *ob = (Object *)ptr->id.data;
ED_object_check_force_modifiers(bmain, scene, ob);
+
+ DEG_id_tag_update(&ob->id, ID_RECALC_TRANSFORM);
WM_main_add_notifier(NC_OBJECT | ND_DRAW, ob);
WM_main_add_notifier(NC_OBJECT | ND_MODIFIER, ob);
}
diff --git a/source/blender/makesrna/intern/rna_space.c b/source/blender/makesrna/intern/rna_space.c
index 2ba5e2ae68c..6dc0cf045cd 100644
--- a/source/blender/makesrna/intern/rna_space.c
+++ b/source/blender/makesrna/intern/rna_space.c
@@ -2105,6 +2105,13 @@ static void rna_SpaceClipEditor_clip_mode_update(Main *UNUSED(bmain),
{
SpaceClip *sc = (SpaceClip *)(ptr->data);
+ 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;
+ ScrArea *sa = rna_area_from_space(ptr);
+ ED_area_tag_refresh(sa);
+ }
+
sc->scopes.ok = 0;
}
diff --git a/source/blender/makesrna/intern/rna_text_api.c b/source/blender/makesrna/intern/rna_text_api.c
index ad36a56ac6a..4ca48226ee9 100644
--- a/source/blender/makesrna/intern/rna_text_api.c
+++ b/source/blender/makesrna/intern/rna_text_api.c
@@ -34,13 +34,13 @@
static void rna_Text_clear(Text *text)
{
- BKE_text_clear(text, NULL);
+ BKE_text_clear(text);
WM_main_add_notifier(NC_TEXT | NA_EDITED, text);
}
static void rna_Text_write(Text *text, const char *str)
{
- BKE_text_write(text, NULL, str);
+ BKE_text_write(text, str);
WM_main_add_notifier(NC_TEXT | NA_EDITED, text);
}
diff --git a/source/blender/modifiers/intern/MOD_bevel.c b/source/blender/modifiers/intern/MOD_bevel.c
index 26b45bbef0d..2677f8ddfdd 100644
--- a/source/blender/modifiers/intern/MOD_bevel.c
+++ b/source/blender/modifiers/intern/MOD_bevel.c
@@ -187,7 +187,9 @@ static Mesh *applyModifier(ModifierData *md, const ModifierEvalContext *ctx, Mes
}
}
- if (harden_normals && !(((Mesh *)ctx->object->data)->flag & ME_AUTOSMOOTH)) {
+ Object *ob = ctx->object;
+
+ if (harden_normals && (ob->type == OB_MESH) && !(((Mesh *)ob->data)->flag & ME_AUTOSMOOTH)) {
modifier_setError(md, "Enable 'Auto Smooth' option in mesh settings for hardening");
harden_normals = false;
}
diff --git a/source/blender/modifiers/intern/MOD_mirror.c b/source/blender/modifiers/intern/MOD_mirror.c
index 857c69eab50..11f001d7a85 100644
--- a/source/blender/modifiers/intern/MOD_mirror.c
+++ b/source/blender/modifiers/intern/MOD_mirror.c
@@ -335,7 +335,7 @@ static Mesh *doMirrorOnAxis(MirrorModifierData *mmd,
}
/* handle custom split normals */
- if ((((Mesh *)ob->data)->flag & ME_AUTOSMOOTH) &&
+ if (ob->type == OB_MESH && (((Mesh *)ob->data)->flag & ME_AUTOSMOOTH) &&
CustomData_has_layer(&result->ldata, CD_CUSTOMLOOPNORMAL)) {
const int totloop = result->totloop;
const int totpoly = result->totpoly;
diff --git a/source/blender/windowmanager/intern/wm_event_system.c b/source/blender/windowmanager/intern/wm_event_system.c
index 4bda5167f60..76cb78b1e04 100644
--- a/source/blender/windowmanager/intern/wm_event_system.c
+++ b/source/blender/windowmanager/intern/wm_event_system.c
@@ -3235,7 +3235,11 @@ void wm_event_do_handlers(bContext *C)
if (scene_eval != NULL) {
const int is_playing_sound = BKE_sound_scene_playing(scene_eval);
- if (is_playing_sound != -1) {
+ 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. */
+ }
+ else if (is_playing_sound != -1) {
bool is_playing_screen;
is_playing_screen = (ED_screen_animation_playing(wm) != NULL);
diff --git a/source/blender/windowmanager/intern/wm_files.c b/source/blender/windowmanager/intern/wm_files.c
index d517622645c..48b09b0d329 100644
--- a/source/blender/windowmanager/intern/wm_files.c
+++ b/source/blender/windowmanager/intern/wm_files.c
@@ -623,8 +623,6 @@ bool WM_file_read(bContext *C, const char *filepath, ReportList *reports)
/* we didn't succeed, now try to read Blender file */
if (retval == BKE_READ_EXOTIC_OK_BLEND) {
- bool use_data = true;
- bool use_userdef = false;
const int G_f_orig = G.f;
ListBase wmbase;
@@ -670,18 +668,14 @@ bool WM_file_read(bContext *C, const char *filepath, ReportList *reports)
wm_window_match_do(C, &wmbase, &bmain->wm, &bmain->wm);
WM_check(C); /* opens window(s), checks keymaps */
- if (retval == BKE_BLENDFILE_READ_OK_USERPREFS) {
- /* in case a userdef is read from regular .blend */
- wm_init_userdef(bmain, false);
- use_userdef = true;
- }
-
if (retval != BKE_BLENDFILE_READ_FAIL) {
if (do_history) {
wm_history_file_update();
}
}
+ const bool use_data = true;
+ const bool use_userdef = false;
wm_file_read_post(C, false, false, use_data, use_userdef, false);
success = true;
@@ -1871,7 +1865,9 @@ void WM_OT_read_factory_userpref(wmOperatorType *ot)
{
ot->name = "Load Factory Preferences";
ot->idname = "WM_OT_read_factory_userpref";
- ot->description = "Load default preferences";
+ ot->description =
+ "Load factory default preferences. "
+ "To make changes to preferences permanent, use \"Save Preferences\"";
ot->invoke = WM_operator_confirm;
ot->exec = wm_userpref_read_exec;
@@ -2044,7 +2040,9 @@ void WM_OT_read_factory_settings(wmOperatorType *ot)
{
ot->name = "Load Factory Settings";
ot->idname = "WM_OT_read_factory_settings";
- ot->description = "Load default file and preferences";
+ ot->description =
+ "Load factory default startup file and preferences. "
+ "To make changes permanent, use \"Save Startup File\" and \"Save Preferences\"";
ot->invoke = WM_operator_confirm;
ot->exec = wm_homefile_read_exec;