diff options
author | Jacques Lucke <mail@jlucke.com> | 2019-07-18 11:37:40 +0300 |
---|---|---|
committer | Jacques Lucke <mail@jlucke.com> | 2019-07-18 11:37:40 +0300 |
commit | 4672d7aa83c5e6b2847c92d6c1be20e251bfa33a (patch) | |
tree | 18f4d9f529c9d1fe287ff242477899c88c415415 /source/blender | |
parent | d6230d15633fbd7f5dbff0882faa4a7ff45d68b2 (diff) | |
parent | 20c725ed62f86aebf555221731c8e7b7dbd05120 (diff) |
Merge branch 'master' into functions
Diffstat (limited to 'source/blender')
61 files changed, 847 insertions, 1714 deletions
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_collection.h b/source/blender/blenkernel/BKE_collection.h index c1e36f5dd83..972ae5e8628 100644 --- a/source/blender/blenkernel/BKE_collection.h +++ b/source/blender/blenkernel/BKE_collection.h @@ -85,7 +85,7 @@ struct Scene *BKE_collection_master_scene_search(const struct Main *bmain, /* Collection Objects */ -bool BKE_collection_has_object(struct Collection *collection, struct Object *ob); +bool BKE_collection_has_object(struct Collection *collection, const struct Object *ob); bool BKE_collection_has_object_recursive(struct Collection *collection, struct Object *ob); struct Collection *BKE_collection_object_find(struct Main *bmain, struct Scene *scene, diff --git a/source/blender/blenkernel/BKE_rigidbody.h b/source/blender/blenkernel/BKE_rigidbody.h index cc3f5bbb42e..4c023f54e04 100644 --- a/source/blender/blenkernel/BKE_rigidbody.h +++ b/source/blender/blenkernel/BKE_rigidbody.h @@ -44,8 +44,10 @@ void BKE_rigidbody_free_constraint(struct Object *ob); /* ...... */ -struct RigidBodyOb *BKE_rigidbody_copy_object(const struct Object *ob, const int flag); -struct RigidBodyCon *BKE_rigidbody_copy_constraint(const struct Object *ob, const int flag); +void BKE_rigidbody_object_copy(struct Main *bmain, + struct Object *ob_dst, + const struct Object *ob_src, + const int flag); /* Callback format for performing operations on ID-pointers for rigidbody world. */ typedef void (*RigidbodyWorldIDFunc)(struct RigidBodyWorld *rbw, 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/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/collection.c b/source/blender/blenkernel/intern/collection.c index ac55846714b..965f6e4bc51 100644 --- a/source/blender/blenkernel/intern/collection.c +++ b/source/blender/blenkernel/intern/collection.c @@ -287,16 +287,6 @@ static Collection *collection_duplicate_recursive(Main *bmain, collection_object_add(bmain, collection_new, ob_new, 0, true); collection_object_remove(bmain, collection_new, ob_old, false); - - if (ob_new->rigidbody_object != NULL) { - BLI_assert(ob_old->rigidbody_object != NULL); - for (Scene *scene = bmain->scenes.first; scene != NULL; scene = scene->id.next) { - if (scene->rigidbody_world != NULL && - BKE_collection_has_object(scene->rigidbody_world->group, ob_old)) { - collection_object_add(bmain, scene->rigidbody_world->group, ob_new, 0, true); - } - } - } } } @@ -572,7 +562,7 @@ bool BKE_collection_object_cyclic_check(Main *bmain, Object *object, Collection /******************* Collection Object Membership *******************/ -bool BKE_collection_has_object(Collection *collection, Object *ob) +bool BKE_collection_has_object(Collection *collection, const Object *ob) { if (ELEM(NULL, collection, ob)) { return false; diff --git a/source/blender/blenkernel/intern/dynamicpaint.c b/source/blender/blenkernel/intern/dynamicpaint.c index 16ce62da57e..7e916feac24 100644 --- a/source/blender/blenkernel/intern/dynamicpaint.c +++ b/source/blender/blenkernel/intern/dynamicpaint.c @@ -2023,6 +2023,8 @@ static Mesh *dynamicPaint_Modifier_apply(DynamicPaintModifierData *pmd, Object * if (defgrp_index != -1 && !dvert && (surface->output_name[0] != '\0')) { dvert = CustomData_add_layer( &result->vdata, CD_MDEFORMVERT, CD_CALLOC, NULL, sData->total_points); + /* Make the dvert layer easily accessible from the mesh data. */ + result->dvert = dvert; } if (defgrp_index != -1 && dvert) { int i; 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/library_remap.c b/source/blender/blenkernel/intern/library_remap.c index 8fe2552c03f..796010205e7 100644 --- a/source/blender/blenkernel/intern/library_remap.c +++ b/source/blender/blenkernel/intern/library_remap.c @@ -1144,7 +1144,8 @@ static void id_delete(Main *bmain, const bool do_tagged_deletion) #ifdef DEBUG_PRINT printf("%s: deleting %s (%d)\n", __func__, id->name, id->us); #endif - BLI_assert(id->us == 0); + /* Text always has a single user, skip assert in this case. */ + BLI_assert((id->us == 0) || ELEM(GS(id->name), ID_TXT)); } BKE_id_free_ex(bmain, id, free_flag, !do_tagged_deletion); } diff --git a/source/blender/blenkernel/intern/object.c b/source/blender/blenkernel/intern/object.c index 2a66edc8d42..d7256cc9604 100644 --- a/source/blender/blenkernel/intern/object.c +++ b/source/blender/blenkernel/intern/object.c @@ -1417,8 +1417,7 @@ void BKE_object_copy_data(Main *bmain, Object *ob_dst, const Object *ob_src, con } } BKE_object_copy_softbody(ob_dst, ob_src, flag_subdata); - ob_dst->rigidbody_object = BKE_rigidbody_copy_object(ob_src, flag_subdata); - ob_dst->rigidbody_constraint = BKE_rigidbody_copy_constraint(ob_src, flag_subdata); + BKE_rigidbody_object_copy(bmain, ob_dst, ob_src, flag_subdata); BKE_object_copy_particlesystems(ob_dst, ob_src, flag_subdata); 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/rigidbody.c b/source/blender/blenkernel/intern/rigidbody.c index a3a0ebd6cb3..c9b18dfc7e6 100644 --- a/source/blender/blenkernel/intern/rigidbody.c +++ b/source/blender/blenkernel/intern/rigidbody.c @@ -34,6 +34,7 @@ #include "MEM_guardedalloc.h" #include "BLI_math.h" +#include "BLI_listbase.h" #ifdef WITH_BULLET # include "RBI_api.h" @@ -228,7 +229,7 @@ void BKE_rigidbody_free_constraint(Object *ob) * be added to relevant groups later... */ -RigidBodyOb *BKE_rigidbody_copy_object(const Object *ob, const int flag) +static RigidBodyOb *rigidbody_copy_object(const Object *ob, const int flag) { RigidBodyOb *rboN = NULL; @@ -249,7 +250,7 @@ RigidBodyOb *BKE_rigidbody_copy_object(const Object *ob, const int flag) return rboN; } -RigidBodyCon *BKE_rigidbody_copy_constraint(const Object *ob, const int UNUSED(flag)) +static RigidBodyCon *rigidbody_copy_constraint(const Object *ob, const int UNUSED(flag)) { RigidBodyCon *rbcN = NULL; @@ -268,6 +269,54 @@ RigidBodyCon *BKE_rigidbody_copy_constraint(const Object *ob, const int UNUSED(f return rbcN; } +void BKE_rigidbody_object_copy(Main *bmain, Object *ob_dst, const Object *ob_src, const int flag) +{ + ob_dst->rigidbody_object = rigidbody_copy_object(ob_src, flag); + ob_dst->rigidbody_constraint = rigidbody_copy_constraint(ob_src, flag); + + if (flag & LIB_ID_CREATE_NO_MAIN) { + return; + } + + /* We have to ensure that duplicated object ends up in relevant rigidbody collections... + * Otherwise duplicating the RB data itself is meaningless. */ + LISTBASE_FOREACH (Scene *, scene, &bmain->scenes) { + RigidBodyWorld *rigidbody_world = scene->rigidbody_world; + + if (rigidbody_world != NULL) { + bool need_objects_update = false; + bool need_constraints_update = false; + + if (ob_dst->rigidbody_object) { + if (BKE_collection_has_object(rigidbody_world->group, ob_src)) { + BKE_collection_object_add(bmain, rigidbody_world->group, ob_dst); + need_objects_update = true; + } + } + if (ob_dst->rigidbody_constraint) { + if (BKE_collection_has_object(rigidbody_world->constraints, ob_src)) { + BKE_collection_object_add(bmain, rigidbody_world->constraints, ob_dst); + need_constraints_update = true; + } + } + + if ((flag & LIB_ID_CREATE_NO_DEG_TAG) == 0 && + (need_objects_update || need_constraints_update)) { + BKE_rigidbody_cache_reset(rigidbody_world); + + DEG_relations_tag_update(bmain); + if (need_objects_update) { + DEG_id_tag_update(&rigidbody_world->group->id, ID_RECALC_COPY_ON_WRITE); + } + if (need_constraints_update) { + DEG_id_tag_update(&rigidbody_world->constraints->id, ID_RECALC_COPY_ON_WRITE); + } + DEG_id_tag_update(&ob_dst->id, ID_RECALC_TRANSFORM); + } + } + } +} + /* ************************************** */ /* Setup Utilities - Validate Sim Instances */ @@ -1983,13 +2032,8 @@ void BKE_rigidbody_do_simulation(Depsgraph *depsgraph, Scene *scene, float ctime # pragma GCC diagnostic ignored "-Wunused-parameter" # endif -struct RigidBodyOb *BKE_rigidbody_copy_object(const Object *ob, const int flag) -{ - return NULL; -} -struct RigidBodyCon *BKE_rigidbody_copy_constraint(const Object *ob, const int flag) +void BKE_rigidbody_object_copy(Main *bmain, Object *ob_dst, const Object *ob_src, const int flag) { - return NULL; } void BKE_rigidbody_validate_sim_world(Scene *scene, RigidBodyWorld *rbw, bool rebuild) { 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/collada/DocumentImporter.cpp b/source/blender/collada/DocumentImporter.cpp index 06f6682f401..eabd9469582 100644 --- a/source/blender/collada/DocumentImporter.cpp +++ b/source/blender/collada/DocumentImporter.cpp @@ -804,7 +804,10 @@ void DocumentImporter::write_profile_COMMON(COLLADAFW::EffectCommon *ef, Materia matNode.set_alpha(ef->getOpaqueMode(), ef->getTransparent(), ef->getTransparency()); /* following mapping still needs to be verified */ +#if 0 + // needs rework to be done for 2.81 matNode.set_shininess(ef->getShininess()); +#endif matNode.set_reflectivity(ef->getReflectivity()); /* not supported by principled BSDF */ diff --git a/source/blender/collada/EffectExporter.cpp b/source/blender/collada/EffectExporter.cpp index 394c79bb988..a784776d342 100644 --- a/source/blender/collada/EffectExporter.cpp +++ b/source/blender/collada/EffectExporter.cpp @@ -208,21 +208,20 @@ void EffectsExporter::operator()(Material *ma, Object *ob) COLLADASW::EffectProfile ep(mSW); ep.setProfileType(COLLADASW::EffectProfile::COMMON); ep.openProfile(); - set_shader_type(ep, ma); + set_shader_type(ep, ma); // creates a Lambert Shader for now COLLADASW::ColorOrTexture cot; set_diffuse_color(ep, ma); set_emission(ep, ma); set_ior(ep, ma); - set_shininess(ep, ma); set_reflectivity(ep, ma); set_transparency(ep, ma); - /* TODO: from where to get ambient, specular and reflective? */ + /* TODO: */ + // set_shininess(ep, ma); shininess not supported for lambert // set_ambient(ep, ma); // set_specular(ep, ma); - // set_reflective(ep, ma); get_images(ma, material_image_map); std::string active_uv(getActiveUVLayerName(ob)); diff --git a/source/blender/collada/Materials.cpp b/source/blender/collada/Materials.cpp index aa35b71b9db..d8a0f06c12b 100644 --- a/source/blender/collada/Materials.cpp +++ b/source/blender/collada/Materials.cpp @@ -131,18 +131,24 @@ void MaterialNode::add_link(bNode *from_node, int from_index, bNode *to_node, in void MaterialNode::set_reflectivity(COLLADAFW::FloatOrParam &val) { float reflectivity = val.getFloatValue(); - bNodeSocket *socket = nodeFindSocket(shader_node, SOCK_IN, "Metallic"); - ((bNodeSocketValueFloat *)socket->default_value)->value = reflectivity; - - material->metallic = reflectivity; + if (reflectivity >= 0) { + bNodeSocket *socket = nodeFindSocket(shader_node, SOCK_IN, "Metallic"); + ((bNodeSocketValueFloat *)socket->default_value)->value = reflectivity; + material->metallic = reflectivity; + } } +#if 0 +// needs rework to be done for 2.81 void MaterialNode::set_shininess(COLLADAFW::FloatOrParam &val) { float roughness = val.getFloatValue(); - bNodeSocket *socket = nodeFindSocket(shader_node, SOCK_IN, "Roughness"); - ((bNodeSocketValueFloat *)socket->default_value)->value = roughness; + if (roughness >= 0) { + bNodeSocket *socket = nodeFindSocket(shader_node, SOCK_IN, "Roughness"); + ((bNodeSocketValueFloat *)socket->default_value)->value = roughness; + } } +#endif void MaterialNode::set_ior(COLLADAFW::FloatOrParam &val) { diff --git a/source/blender/depsgraph/intern/builder/deg_builder_relations.cc b/source/blender/depsgraph/intern/builder/deg_builder_relations.cc index afc47797401..82a4896942e 100644 --- a/source/blender/depsgraph/intern/builder/deg_builder_relations.cc +++ b/source/blender/depsgraph/intern/builder/deg_builder_relations.cc @@ -381,6 +381,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/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/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_mesh.h b/source/blender/editors/include/ED_mesh.h index 5d8038d0b28..d2613facd83 100644 --- a/source/blender/editors/include/ED_mesh.h +++ b/source/blender/editors/include/ED_mesh.h @@ -393,6 +393,9 @@ bool ED_mesh_color_remove_named(struct Mesh *me, const char *name); void ED_mesh_report_mirror(struct wmOperator *op, int totmirr, int totfail); void ED_mesh_report_mirror_ex(struct wmOperator *op, int totmirr, int totfail, char selectmode); +/* Returns the pinned mesh, the mesh from the pinned object, or the mesh from the active object. */ +struct Mesh *ED_mesh_context(struct bContext *C); + /* mesh backup */ typedef struct BMBackup { struct BMesh *bmcopy; diff --git a/source/blender/editors/include/ED_screen.h b/source/blender/editors/include/ED_screen.h index fc43144417a..e67a3b003fc 100644 --- a/source/blender/editors/include/ED_screen.h +++ b/source/blender/editors/include/ED_screen.h @@ -337,6 +337,7 @@ bool ED_operator_object_active(struct bContext *C); bool ED_operator_object_active_editable(struct bContext *C); bool ED_operator_object_active_editable_mesh(struct bContext *C); bool ED_operator_object_active_editable_font(struct bContext *C); +bool ED_operator_editable_mesh(struct bContext *C); bool ED_operator_editmesh(struct bContext *C); bool ED_operator_editmesh_view3d(struct bContext *C); bool ED_operator_editmesh_region_view3d(struct bContext *C); diff --git a/source/blender/editors/include/ED_text.h b/source/blender/editors/include/ED_text.h index 7638249d49a..ed71439bd37 100644 --- a/source/blender/editors/include/ED_text.h +++ b/source/blender/editors/include/ED_text.h @@ -26,7 +26,7 @@ struct ARegion; struct SpaceText; -struct TextUndoBuf; +struct UndoStep; struct UndoType; bool ED_text_region_location_from_cursor(struct SpaceText *st, @@ -37,6 +37,6 @@ bool ED_text_region_location_from_cursor(struct SpaceText *st, /* text_undo.c */ void ED_text_undosys_type(struct UndoType *ut); -struct TextUndoBuf *ED_text_undo_push_init(struct bContext *C); +struct UndoStep *ED_text_undo_push_init(struct bContext *C); #endif /* __ED_TEXT_H__ */ diff --git a/source/blender/editors/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/mesh/mesh_data.c b/source/blender/editors/mesh/mesh_data.c index a6934326d68..ee8de9d8ea9 100644 --- a/source/blender/editors/mesh/mesh_data.c +++ b/source/blender/editors/mesh/mesh_data.c @@ -41,6 +41,7 @@ #include "DEG_depsgraph.h" +#include "RNA_access.h" #include "RNA_define.h" #include "WM_api.h" @@ -629,8 +630,7 @@ void MESH_OT_vertex_color_remove(wmOperatorType *ot) static int mesh_customdata_clear_exec__internal(bContext *C, char htype, int type) { - Object *obedit = ED_object_context(C); - Mesh *me = obedit->data; + Mesh *me = ED_mesh_context(C); int tot; CustomData *data = mesh_customdata_get_type(me, htype, &tot); @@ -788,8 +788,7 @@ void MESH_OT_customdata_skin_clear(wmOperatorType *ot) /* Clear custom loop normals */ static int mesh_customdata_custom_splitnormals_add_exec(bContext *C, wmOperator *UNUSED(op)) { - Object *ob = ED_object_context(C); - Mesh *me = ob->data; + Mesh *me = ED_mesh_context(C); if (!BKE_mesh_has_custom_loop_normals(me)) { CustomData *data = GET_CD_DATA(me, ldata); @@ -853,7 +852,7 @@ void MESH_OT_customdata_custom_splitnormals_add(wmOperatorType *ot) /* api callbacks */ ot->exec = mesh_customdata_custom_splitnormals_add_exec; - ot->poll = ED_operator_object_active_editable_mesh; + ot->poll = ED_operator_editable_mesh; /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; @@ -861,8 +860,7 @@ void MESH_OT_customdata_custom_splitnormals_add(wmOperatorType *ot) static int mesh_customdata_custom_splitnormals_clear_exec(bContext *C, wmOperator *UNUSED(op)) { - Object *ob = ED_object_context(C); - Mesh *me = ob->data; + Mesh *me = ED_mesh_context(C); if (BKE_mesh_has_custom_loop_normals(me)) { return mesh_customdata_clear_exec__internal(C, BM_LOOP, CD_CUSTOMLOOPNORMAL); @@ -879,7 +877,7 @@ void MESH_OT_customdata_custom_splitnormals_clear(wmOperatorType *ot) /* api callbacks */ ot->exec = mesh_customdata_custom_splitnormals_clear_exec; - ot->poll = ED_operator_object_active_editable_mesh; + ot->poll = ED_operator_editable_mesh; /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; @@ -1289,3 +1287,23 @@ void ED_mesh_report_mirror(wmOperator *op, int totmirr, int totfail) { ED_mesh_report_mirror_ex(op, totmirr, totfail, SCE_SELECT_VERTEX); } + +Mesh *ED_mesh_context(struct bContext *C) +{ + Mesh *mesh = CTX_data_pointer_get_type(C, "mesh", &RNA_Mesh).data; + if (mesh != NULL) { + return mesh; + } + + Object *ob = ED_object_active_context(C); + if (ob == NULL) { + return NULL; + } + + ID *data = (ID *)ob->data; + if (data == NULL || GS(data->name) != ID_ME) { + return NULL; + } + + return (Mesh *)data; +} diff --git a/source/blender/editors/screen/screen_ops.c b/source/blender/editors/screen/screen_ops.c index 5fc7979a631..c9a45728bc2 100644 --- a/source/blender/editors/screen/screen_ops.c +++ b/source/blender/editors/screen/screen_ops.c @@ -74,6 +74,7 @@ #include "ED_clip.h" #include "ED_image.h" #include "ED_keyframes_draw.h" +#include "ED_mesh.h" #include "ED_object.h" #include "ED_screen.h" #include "ED_screen_types.h" @@ -371,6 +372,12 @@ bool ED_operator_object_active_editable_font(bContext *C) return ((ob != NULL) && !ID_IS_LINKED(ob) && !ed_object_hidden(ob) && (ob->type == OB_FONT)); } +bool ED_operator_editable_mesh(bContext *C) +{ + Mesh *mesh = ED_mesh_context(C); + return (mesh != NULL) && !ID_IS_LINKED(mesh); +} + bool ED_operator_editmesh(bContext *C) { Object *obedit = CTX_data_edit_object(C); 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 316ae6189f0..980b043bf8b 100644 --- a/source/blender/editors/sculpt_paint/paint_vertex.c +++ b/source/blender/editors/sculpt_paint/paint_vertex.c @@ -56,6 +56,7 @@ #include "BKE_paint.h" #include "BKE_report.h" #include "BKE_subsurf.h" +#include "BKE_layer.h" #include "DEG_depsgraph.h" @@ -1305,18 +1306,47 @@ static int wpaint_mode_toggle_exec(bContext *C, wmOperator *op) BKE_paint_toolslots_brush_validate(bmain, &ts->wpaint->paint); } - /* When locked, it's almost impossible to select the pose - * then the object to enter weight paint mode. + /* When locked, it's almost impossible to select the pose-object + * then the mesh-object to enter weight paint mode. + * Even when the object mode is not locked this is inconvenient - so allow in either case. + * * In this case move our pose object in/out of pose mode. - * This is in fits with the convention of selecting multiple objects and entering a mode. */ - if (scene->toolsettings->object_flag & SCE_OBJECT_MODE_LOCK) { - Object *ob_arm = modifiers_isDeformedByArmature(ob); - if (ob_arm && (ob_arm->base_flag & BASE_SELECTED)) { - if (ob_arm->mode & OB_MODE_POSE) { - ED_object_posemode_exit_ex(bmain, ob_arm); - } - else { - ED_object_posemode_enter_ex(bmain, ob_arm); + * This is in fits with the convention of selecting multiple objects and entering a mode. + */ + { + VirtualModifierData virtualModifierData; + ModifierData *md = modifiers_getVirtualModifierList(ob, &virtualModifierData); + if (md != NULL) { + /* Can be NULL. */ + View3D *v3d = CTX_wm_view3d(C); + ViewLayer *view_layer = CTX_data_view_layer(C); + for (; md; md = md->next) { + if (md->type == eModifierType_Armature) { + ArmatureModifierData *amd = (ArmatureModifierData *)md; + Object *ob_arm = amd->object; + if (ob_arm != NULL) { + const Base *base_arm = BKE_view_layer_base_find(view_layer, ob_arm); + if (base_arm && BASE_VISIBLE(v3d, base_arm)) { + if (is_mode_set) { + if ((ob_arm->mode & OB_MODE_POSE) != 0) { + ED_object_posemode_exit_ex(bmain, ob_arm); + } + } + else { + /* Only check selected status when entering weight-paint mode + * because we may have multiple armature objects. + * Selecting one will de-select the other, which would leave it in pose-mode + * when exiting weight paint mode. While usable, this looks like inconsistent + * behavior from a user perspective. */ + if (base_arm->flag & BASE_SELECTED) { + if ((ob_arm->mode & OB_MODE_POSE) == 0) { + ED_object_posemode_enter_ex(bmain, ob_arm); + } + } + } + } + } + } } } } @@ -2271,7 +2301,6 @@ static void wpaint_stroke_update_step(bContext *C, struct PaintStroke *stroke, P vwpaint_update_cache_variants(C, wp, ob, itemptr); float mat[4][4]; - float mval[2]; const float brush_alpha_value = BKE_brush_alpha_get(scene, brush); @@ -2321,7 +2350,7 @@ static void wpaint_stroke_update_step(bContext *C, struct PaintStroke *stroke, P /* calculate pivot for rotation around seletion if needed */ /* also needed for "View Selected" on last stroke */ - paint_last_stroke_update(scene, vc->ar, mval); + paint_last_stroke_update(scene, vc->ar, ss->cache->mouse); BKE_mesh_batch_cache_dirty_tag(ob->data, BKE_MESH_BATCH_DIRTY_ALL); @@ -3273,12 +3302,12 @@ static void vpaint_stroke_update_step(bContext *C, struct PaintStroke *stroke, P VPaint *vp = ts->vpaint; ViewContext *vc = &vpd->vc; Object *ob = vc->obact; + SculptSession *ss = ob->sculpt; Sculpt *sd = CTX_data_tool_settings(C)->sculpt; vwpaint_update_cache_variants(C, vp, ob, itemptr); float mat[4][4]; - float mval[2]; ED_view3d_init_mats_rv3d(ob, vc->rv3d); @@ -3300,7 +3329,7 @@ static void vpaint_stroke_update_step(bContext *C, struct PaintStroke *stroke, P /* calculate pivot for rotation around seletion if needed */ /* also needed for "View Selected" on last stroke */ - paint_last_stroke_update(scene, vc->ar, mval); + paint_last_stroke_update(scene, vc->ar, ss->cache->mouse); ED_region_tag_redraw(vc->ar); diff --git a/source/blender/editors/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 57ff7c318f3..5aef89e4009 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/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_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; diff --git a/source/blender/windowmanager/intern/wm_operators.c b/source/blender/windowmanager/intern/wm_operators.c index 29e6c670c00..367a5a81098 100644 --- a/source/blender/windowmanager/intern/wm_operators.c +++ b/source/blender/windowmanager/intern/wm_operators.c @@ -1600,7 +1600,7 @@ static ImBuf *wm_block_splash_image(void) BLI_join_dirfile(splash_filepath, sizeof(splash_filepath), template_directory, - (U.pixelsize == 2) ? "splash_2x.png" : "splash.png"); + (U.dpi_fac > 1.0) ? "splash_2x.png" : "splash.png"); ibuf_template = IMB_loadiffname(splash_filepath, IB_rect, NULL); if (ibuf_template) { const int x_expect = ibuf->x; |