diff options
author | Himanshi Kalra <himanshikalra98@gmail.com> | 2020-12-17 15:06:26 +0300 |
---|---|---|
committer | Himanshi Kalra <himanshikalra98@gmail.com> | 2020-12-17 15:06:26 +0300 |
commit | 167eace0e73bef77cf362af04f1f0dd47c492a92 (patch) | |
tree | 715217755512456fab8dfa8e38f63d5065a1ccc1 /source/blender/blenkernel/intern | |
parent | f066bf923c234f52a6159d51f4978bf1072edaf1 (diff) | |
parent | cf2ebaf27c78b3f8f79d9d014ca2261228f87e70 (diff) |
Merge branch 'master' into soc-2020-testing-frameworks
Diffstat (limited to 'source/blender/blenkernel/intern')
-rw-r--r-- | source/blender/blenkernel/intern/appdir.c | 12 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/attribute_access.cc | 21 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/brush.c | 9 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/customdata.c | 16 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/icons.cc | 72 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/image_gpu.c | 2 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/layer.c | 2 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/lib_override.c | 38 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/mesh_fair.cc | 505 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/multires_unsubdivide.h | 2 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/node.c | 3 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/scene.c | 12 |
12 files changed, 640 insertions, 54 deletions
diff --git a/source/blender/blenkernel/intern/appdir.c b/source/blender/blenkernel/intern/appdir.c index a6b3985e80d..ae0c27635a6 100644 --- a/source/blender/blenkernel/intern/appdir.c +++ b/source/blender/blenkernel/intern/appdir.c @@ -906,14 +906,20 @@ bool BKE_appdir_program_python_search(char *fullpath, const char *python_build_def = STRINGIFY(PYTHON_EXECUTABLE_NAME); #endif const char *basename = "python"; +#if defined(WIN32) && !defined(NDEBUG) + const char *basename_debug = "python_d"; +#endif char python_version[16]; /* Check both possible names. */ const char *python_names[] = { #ifdef PYTHON_EXECUTABLE_NAME - python_build_def, + python_build_def, +#endif +#if defined(WIN32) && !defined(NDEBUG) + basename_debug, #endif - python_version, - basename, + python_version, + basename, }; bool is_found = false; diff --git a/source/blender/blenkernel/intern/attribute_access.cc b/source/blender/blenkernel/intern/attribute_access.cc index 282e9bc2962..623335f65a1 100644 --- a/source/blender/blenkernel/intern/attribute_access.cc +++ b/source/blender/blenkernel/intern/attribute_access.cc @@ -392,6 +392,8 @@ const blender::fn::CPPType *custom_data_type_to_cpp_type(const CustomDataType ty return &CPPType::get<int>(); case CD_PROP_COLOR: return &CPPType::get<Color4f>(); + case CD_PROP_BOOL: + return &CPPType::get<bool>(); default: return nullptr; } @@ -415,6 +417,9 @@ CustomDataType cpp_type_to_custom_data_type(const blender::fn::CPPType &type) if (type.is<Color4f>()) { return CD_PROP_COLOR; } + if (type.is<bool>()) { + return CD_PROP_BOOL; + } return static_cast<CustomDataType>(-1); } @@ -449,6 +454,9 @@ static ReadAttributePtr read_attribute_from_custom_data(const CustomData &custom case CD_PROP_COLOR: return std::make_unique<ArrayReadAttribute<Color4f>>( domain, Span(static_cast<Color4f *>(layer.data), size)); + case CD_PROP_BOOL: + return std::make_unique<ArrayReadAttribute<bool>>( + domain, Span(static_cast<bool *>(layer.data), size)); } } } @@ -490,6 +498,9 @@ static WriteAttributePtr write_attribute_from_custom_data( case CD_PROP_COLOR: return std::make_unique<ArrayWriteAttribute<Color4f>>( domain, MutableSpan(static_cast<Color4f *>(layer.data), size)); + case CD_PROP_BOOL: + return std::make_unique<ArrayWriteAttribute<bool>>( + domain, MutableSpan(static_cast<bool *>(layer.data), size)); } } } @@ -751,6 +762,7 @@ bool PointCloudComponent::attribute_domain_with_type_supported( const AttributeDomain domain, const CustomDataType data_type) const { return domain == ATTR_DOMAIN_POINT && ELEM(data_type, + CD_PROP_BOOL, CD_PROP_FLOAT, CD_PROP_FLOAT2, CD_PROP_FLOAT3, @@ -874,8 +886,13 @@ bool MeshComponent::attribute_domain_with_type_supported(const AttributeDomain d if (!this->attribute_domain_supported(domain)) { return false; } - return ELEM( - data_type, CD_PROP_FLOAT, CD_PROP_FLOAT2, CD_PROP_FLOAT3, CD_PROP_INT32, CD_PROP_COLOR); + return ELEM(data_type, + CD_PROP_BOOL, + CD_PROP_FLOAT, + CD_PROP_FLOAT2, + CD_PROP_FLOAT3, + CD_PROP_INT32, + CD_PROP_COLOR); } int MeshComponent::attribute_domain_size(const AttributeDomain domain) const diff --git a/source/blender/blenkernel/intern/brush.c b/source/blender/blenkernel/intern/brush.c index 33686cea4fc..9a954a89cad 100644 --- a/source/blender/blenkernel/intern/brush.c +++ b/source/blender/blenkernel/intern/brush.c @@ -1834,6 +1834,14 @@ void BKE_brush_sculpt_reset(Brush *br) br->flag &= ~BRUSH_SPACE_ATTEN; br->curve_preset = BRUSH_CURVE_SPHERE; break; + case SCULPT_TOOL_DISPLACEMENT_SMEAR: + br->alpha = 1.0f; + br->spacing = 5; + br->hardness = 0.7f; + br->flag &= ~BRUSH_ALPHA_PRESSURE; + br->flag &= ~BRUSH_SPACE_ATTEN; + br->curve_preset = BRUSH_CURVE_SMOOTHER; + break; default: break; } @@ -1898,6 +1906,7 @@ void BKE_brush_sculpt_reset(Brush *br) case SCULPT_TOOL_MASK: case SCULPT_TOOL_DRAW_FACE_SETS: case SCULPT_TOOL_DISPLACEMENT_ERASER: + case SCULPT_TOOL_DISPLACEMENT_SMEAR: br->add_col[0] = 0.75f; br->add_col[1] = 0.75f; br->add_col[2] = 0.75f; diff --git a/source/blender/blenkernel/intern/customdata.c b/source/blender/blenkernel/intern/customdata.c index fdb3e246382..1e2bc570c65 100644 --- a/source/blender/blenkernel/intern/customdata.c +++ b/source/blender/blenkernel/intern/customdata.c @@ -1837,6 +1837,21 @@ static const LayerTypeInfo LAYERTYPEINFO[CD_NUMTYPES] = { layerMultiply_propfloat2, NULL, layerAdd_propfloat2}, + /* 50: CD_PROP_POOL */ + {sizeof(bool), + "bool", + 1, + N_("Boolean"), + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL}, }; static const char *LAYERTYPENAMES[CD_NUMTYPES] = { @@ -1892,6 +1907,7 @@ static const char *LAYERTYPENAMES[CD_NUMTYPES] = { "CDPropCol", "CDPropFloat3", "CDPropFloat2", + "CDPropBoolean", }; const CustomData_MeshMasks CD_MASK_BAREMESH = { diff --git a/source/blender/blenkernel/intern/icons.cc b/source/blender/blenkernel/intern/icons.cc index 48f5e11778c..fbf69357478 100644 --- a/source/blender/blenkernel/intern/icons.cc +++ b/source/blender/blenkernel/intern/icons.cc @@ -78,7 +78,7 @@ enum { static CLG_LogRef LOG = {"bke.icons"}; /* Protected by gIconMutex. */ -static GHash *gIcons = NULL; +static GHash *gIcons = nullptr; /* Protected by gIconMutex. */ static int gNextIconId = 1; @@ -89,7 +89,7 @@ static int gFirstIconId = 1; std::mutex gIconMutex; /* Not mutex-protected! */ -static GHash *gCachedPreviews = NULL; +static GHash *gCachedPreviews = nullptr; /* Queue of icons for deferred deletion. */ typedef struct DeferredIconDeleteNode { @@ -149,7 +149,7 @@ static void icon_free_data(int icon_id, Icon *icon) } else if (icon->obj_type == ICON_DATA_STUDIOLIGHT) { StudioLight *sl = (StudioLight *)icon->obj; - if (sl != NULL) { + if (sl != nullptr) { BKE_studiolight_unset_icon_id(sl, icon_id); } } @@ -166,7 +166,7 @@ static Icon *icon_ghash_lookup(int icon_id) /* create an id for a new icon and make sure that ids from deleted icons get reused * after the integer number range is used up */ -static int get_next_free_id(void) +static int get_next_free_id() { std::scoped_lock lock(gIconMutex); int startId = gFirstIconId; @@ -214,13 +214,13 @@ void BKE_icons_free(void) BLI_assert(BLI_thread_is_main()); if (gIcons) { - BLI_ghash_free(gIcons, NULL, icon_free); - gIcons = NULL; + BLI_ghash_free(gIcons, nullptr, icon_free); + gIcons = nullptr; } if (gCachedPreviews) { BLI_ghash_free(gCachedPreviews, MEM_freeN, BKE_previewimg_freefunc); - gCachedPreviews = NULL; + gCachedPreviews = nullptr; } BLI_linklist_lockfree_free(&g_icon_delete_queue, MEM_freeN); @@ -232,9 +232,9 @@ void BKE_icons_deferred_free(void) for (DeferredIconDeleteNode *node = (DeferredIconDeleteNode *)BLI_linklist_lockfree_begin(&g_icon_delete_queue); - node != NULL; + node != nullptr; node = node->next) { - BLI_ghash_remove(gIcons, POINTER_FROM_INT(node->icon_id), NULL, icon_free); + BLI_ghash_remove(gIcons, POINTER_FROM_INT(node->icon_id), nullptr, icon_free); } BLI_linklist_lockfree_clear(&g_icon_delete_queue, MEM_freeN); } @@ -296,7 +296,7 @@ void BKE_previewimg_free(PreviewImage **prv) { if (prv && (*prv)) { BKE_previewimg_freefunc(*prv); - *prv = NULL; + *prv = nullptr; } } @@ -321,7 +321,7 @@ void BKE_previewimg_clear(struct PreviewImage *prv) PreviewImage *BKE_previewimg_copy(const PreviewImage *prv) { - PreviewImage *prv_img = NULL; + PreviewImage *prv_img = nullptr; if (prv) { prv_img = (PreviewImage *)MEM_dupallocN(prv); @@ -329,7 +329,7 @@ PreviewImage *BKE_previewimg_copy(const PreviewImage *prv) if (prv->rect[i]) { prv_img->rect[i] = (uint *)MEM_dupallocN(prv->rect[i]); } - prv_img->gputexture[i] = NULL; + prv_img->gputexture[i] = nullptr; } } return prv_img; @@ -345,7 +345,7 @@ void BKE_previewimg_id_copy(ID *new_id, const ID *old_id) PreviewImage **new_prv_p = BKE_previewimg_id_get_p(new_id); if (old_prv_p && *old_prv_p) { - BLI_assert(new_prv_p != NULL && ELEM(*new_prv_p, NULL, *old_prv_p)); + BLI_assert(new_prv_p != nullptr && ELEM(*new_prv_p, nullptr, *old_prv_p)); // const int new_icon_id = get_next_free_id(); // if (new_icon_id == 0) { @@ -379,13 +379,13 @@ PreviewImage **BKE_previewimg_id_get_p(const ID *id) break; } - return NULL; + return nullptr; } PreviewImage *BKE_previewimg_id_get(const ID *id) { PreviewImage **prv_p = BKE_previewimg_id_get_p(id); - return prv_p ? *prv_p : NULL; + return prv_p ? *prv_p : nullptr; } void BKE_previewimg_id_free(ID *id) @@ -401,13 +401,13 @@ PreviewImage *BKE_previewimg_id_ensure(ID *id) PreviewImage **prv_p = BKE_previewimg_id_get_p(id); if (prv_p) { - if (*prv_p == NULL) { + if (*prv_p == nullptr) { *prv_p = BKE_previewimg_create(); } return *prv_p; } - return NULL; + return nullptr; } void BKE_previewimg_id_custom_set(ID *id, const char *path) @@ -464,7 +464,7 @@ PreviewImage *BKE_previewimg_cached_ensure(const char *name) { BLI_assert(BLI_thread_is_main()); - PreviewImage *prv = NULL; + PreviewImage *prv = nullptr; void **key_p, **prv_p; if (!BLI_ghash_ensure_p_ex(gCachedPreviews, name, &key_p, &prv_p)) { @@ -488,7 +488,7 @@ PreviewImage *BKE_previewimg_cached_thumbnail_read(const char *name, { BLI_assert(BLI_thread_is_main()); - PreviewImage *prv = NULL; + PreviewImage *prv = nullptr; void **prv_p; prv_p = BLI_ghash_lookup_p(gCachedPreviews, name); @@ -599,7 +599,7 @@ ImBuf *BKE_previewimg_to_imbuf(PreviewImage *prv, const int size) const unsigned int h = prv->h[size]; const unsigned int *rect = prv->rect[size]; - ImBuf *ima = NULL; + ImBuf *ima = nullptr; if (w > 0 && h > 0 && rect) { /* first allocate imbuf for copying preview into it */ @@ -627,7 +627,7 @@ void BKE_previewimg_blend_write(BlendWriter *writer, const PreviewImage *prv) * but not doing so would causes all previews to be re-rendered after * undo which is too expensive. */ - if (prv == NULL) { + if (prv == nullptr) { return; } @@ -636,7 +636,7 @@ void BKE_previewimg_blend_write(BlendWriter *writer, const PreviewImage *prv) if (!(U.flag & USER_SAVE_PREVIEWS)) { prv_copy.w[1] = 0; prv_copy.h[1] = 0; - prv_copy.rect[1] = NULL; + prv_copy.rect[1] = nullptr; } BLO_write_struct_at_address(writer, PreviewImage, prv, &prv_copy); if (prv_copy.rect[0]) { @@ -649,7 +649,7 @@ void BKE_previewimg_blend_write(BlendWriter *writer, const PreviewImage *prv) void BKE_previewimg_blend_read(BlendDataReader *reader, PreviewImage *prv) { - if (prv == NULL) { + if (prv == nullptr) { return; } @@ -657,7 +657,7 @@ void BKE_previewimg_blend_read(BlendDataReader *reader, PreviewImage *prv) if (prv->rect[i]) { BLO_read_data_address(reader, &prv->rect[i]); } - prv->gputexture[i] = NULL; + prv->gputexture[i] = nullptr; /* For now consider previews read from file as finished to not confuse File Browser preview * loading. That could be smarter and check if there's a preview job running instead. * If the preview is tagged as changed, it needs to be updated anyway, so don't remove the tag. @@ -676,7 +676,7 @@ void BKE_previewimg_blend_read(BlendDataReader *reader, PreviewImage *prv) void BKE_icon_changed(const int icon_id) { - Icon *icon = NULL; + Icon *icon = nullptr; if (!icon_id || G.background) { return; @@ -714,8 +714,8 @@ static Icon *icon_create(int icon_id, int obj_type, void *obj) new_icon->flag = 0; /* next two lines make sure image gets created */ - new_icon->drawinfo = NULL; - new_icon->drawinfo_free = NULL; + new_icon->drawinfo = nullptr; + new_icon->drawinfo_free = nullptr; { std::scoped_lock lock(gIconMutex); @@ -867,11 +867,11 @@ ImBuf *BKE_icon_imbuf_get_buffer(int icon_id) Icon *icon = icon_ghash_lookup(icon_id); if (!icon) { CLOG_ERROR(&LOG, "no icon for icon ID: %d", icon_id); - return NULL; + return nullptr; } if (icon->obj_type != ICON_DATA_IMBUF) { CLOG_ERROR(&LOG, "icon ID does not refer to an imbuf icon: %d", icon_id); - return NULL; + return nullptr; } return (ImBuf *)icon->obj; @@ -881,13 +881,13 @@ Icon *BKE_icon_get(const int icon_id) { BLI_assert(BLI_thread_is_main()); - Icon *icon = NULL; + Icon *icon = nullptr; icon = icon_ghash_lookup(icon_id); if (!icon) { CLOG_ERROR(&LOG, "no icon for icon ID: %d", icon_id); - return NULL; + return nullptr; } return icon; @@ -930,7 +930,7 @@ void BKE_icon_id_delete(struct ID *id) BKE_icons_deferred_free(); std::scoped_lock lock(gIconMutex); - BLI_ghash_remove(gIcons, POINTER_FROM_INT(icon_id), NULL, icon_free); + BLI_ghash_remove(gIcons, POINTER_FROM_INT(icon_id), nullptr, icon_free); } /** @@ -944,7 +944,7 @@ bool BKE_icon_delete(const int icon_id) } std::scoped_lock lock(gIconMutex); - if (Icon *icon = (Icon *)BLI_ghash_popkey(gIcons, POINTER_FROM_INT(icon_id), NULL)) { + if (Icon *icon = (Icon *)BLI_ghash_popkey(gIcons, POINTER_FROM_INT(icon_id), nullptr)) { icon_free_data(icon_id, icon); icon_free(icon); return true; @@ -962,7 +962,7 @@ bool BKE_icon_delete_unmanaged(const int icon_id) std::scoped_lock lock(gIconMutex); - Icon *icon = (Icon *)BLI_ghash_popkey(gIcons, POINTER_FROM_INT(icon_id), NULL); + Icon *icon = (Icon *)BLI_ghash_popkey(gIcons, POINTER_FROM_INT(icon_id), nullptr); if (icon) { if (UNLIKELY(icon->flag & ICON_FLAG_MANAGED)) { BLI_ghash_insert(gIcons, POINTER_FROM_INT(icon_id), icon); @@ -1041,8 +1041,8 @@ struct Icon_Geom *BKE_icon_geom_from_file(const char *filename) BLI_assert(BLI_thread_is_main()); size_t data_len; uchar *data = (uchar *)BLI_file_read_binary_as_mem(filename, 0, &data_len); - if (data == NULL) { - return NULL; + if (data == nullptr) { + return nullptr; } return BKE_icon_geom_from_memory(data, data_len); } diff --git a/source/blender/blenkernel/intern/image_gpu.c b/source/blender/blenkernel/intern/image_gpu.c index 9ed233ab34c..50138b34fa3 100644 --- a/source/blender/blenkernel/intern/image_gpu.c +++ b/source/blender/blenkernel/intern/image_gpu.c @@ -62,7 +62,7 @@ bool BKE_image_has_gpu_texture_premultiplied_alpha(Image *image, ImBuf *ibuf) return ibuf->rect_float != NULL; } } - else if (ibuf) { + if (ibuf) { if (ibuf->rect_float) { return image ? (image->alpha_mode != IMA_ALPHA_STRAIGHT) : false; } diff --git a/source/blender/blenkernel/intern/layer.c b/source/blender/blenkernel/intern/layer.c index 8a699e31f37..fbad0d920ed 100644 --- a/source/blender/blenkernel/intern/layer.c +++ b/source/blender/blenkernel/intern/layer.c @@ -2054,7 +2054,7 @@ static void bke_view_layer_verify_aov_cb(void *userdata, const char *name, int UNUSED(channels), const char *UNUSED(chanid), - int UNUSED(type)) + eNodeSocketDatatype UNUSED(type)) { GHash *name_count = userdata; void **value_p; diff --git a/source/blender/blenkernel/intern/lib_override.c b/source/blender/blenkernel/intern/lib_override.c index d82315a0e7f..cabc80d4024 100644 --- a/source/blender/blenkernel/intern/lib_override.c +++ b/source/blender/blenkernel/intern/lib_override.c @@ -369,6 +369,7 @@ bool BKE_lib_override_library_create_from_tag(Main *bmain) static bool lib_override_hierarchy_recursive_tag(Main *bmain, ID *id, const uint tag, + const uint missing_tag, Library *override_group_lib_reference) { void **entry_vp = BLI_ghash_lookup_p(bmain->relations->id_user_to_used, id); @@ -377,9 +378,16 @@ static bool lib_override_hierarchy_recursive_tag(Main *bmain, return (id->tag & tag) != 0; } + /* Note: in case some reference ID is missing from linked data (and therefore its override uses + * a placeholder as reference), use `missing_tag` instead of `tag` for this override. */ if (override_group_lib_reference != NULL && ID_IS_OVERRIDE_LIBRARY_REAL(id) && id->override_library->reference->lib == override_group_lib_reference) { - id->tag |= tag; + if (id->override_library->reference->tag & LIB_TAG_MISSING) { + id->tag |= missing_tag; + } + else { + id->tag |= tag; + } } /* This way we won't process again that ID, should we encounter it again through another @@ -397,7 +405,7 @@ static bool lib_override_hierarchy_recursive_tag(Main *bmain, /* We only consider IDs from the same library. */ if (entry->id_pointer != NULL && (*entry->id_pointer)->lib == id->lib) { if (lib_override_hierarchy_recursive_tag( - bmain, *entry->id_pointer, tag, override_group_lib_reference) && + bmain, *entry->id_pointer, tag, missing_tag, override_group_lib_reference) && override_group_lib_reference == NULL) { id->tag |= tag; } @@ -430,7 +438,7 @@ void BKE_lib_override_library_dependencies_tag(Main *bmain, /* We tag all intermediary data-blocks in-between two overridden ones (e.g. if a shape-key * has a driver using an armature object's bone, we need to override the shape-key/obdata, * the objects using them, etc.) */ - lib_override_hierarchy_recursive_tag(bmain, id_root, tag, NULL); + lib_override_hierarchy_recursive_tag(bmain, id_root, tag, 0, NULL); BKE_main_relations_free(bmain); } @@ -447,6 +455,7 @@ void BKE_lib_override_library_dependencies_tag(Main *bmain, void BKE_lib_override_library_override_group_tag(Main *bmain, ID *id_root, const uint tag, + const uint missing_tag, const bool do_create_main_relashionships) { if (do_create_main_relashionships) { @@ -456,7 +465,7 @@ void BKE_lib_override_library_override_group_tag(Main *bmain, /* We tag all liboverride data-blocks from the same library as reference one, * being used by the root ID. */ lib_override_hierarchy_recursive_tag( - bmain, id_root, tag, id_root->override_library->reference->lib); + bmain, id_root, tag, missing_tag, id_root->override_library->reference->lib); BKE_main_relations_free(bmain); } @@ -492,8 +501,9 @@ static int lib_override_library_make_tag_ids_cb(LibraryIDLinkCallbackData *cb_da } /* We tag all collections and objects for override. And we also tag all other data-blocks which - * would use one of those. */ - if (ELEM(GS(id->name), ID_OB, ID_GR)) { + * would use one of those. + * Note: missing IDs (aka placeholders) are never overridden. */ + if (ELEM(GS(id->name), ID_OB, ID_GR) && !(id->tag & LIB_TAG_MISSING)) { id->tag |= LIB_TAG_DOIT; } @@ -692,6 +702,12 @@ bool BKE_lib_override_library_proxy_convert(Main *bmain, &ob_proxy->proxy->id; ID *id_reference = is_override_instancing_object ? &ob_proxy_group->id : &ob_proxy->id; + /* In some cases the instance collection of a proxy object may be local (see e.g. T83875). Not + * sure this is a valid state, but for now just abort the overriding process. */ + if (!ID_IS_OVERRIDABLE_LIBRARY(id_root)) { + return false; + } + /* We manually convert the proxy object into a library override, further override handling will * then be handled by `BKE_lib_override_library_create()` just as for a regular override * creation. @@ -725,7 +741,7 @@ bool BKE_lib_override_library_resync(Main *bmain, Scene *scene, ViewLayer *view_ /* Make a mapping 'linked reference IDs' -> 'Local override IDs' of existing overrides, and tag * linked reference ones to be overridden again. */ - BKE_lib_override_library_override_group_tag(bmain, id_root, LIB_TAG_DOIT, true); + BKE_lib_override_library_override_group_tag(bmain, id_root, LIB_TAG_DOIT, LIB_TAG_MISSING, true); GHash *linkedref_to_old_override = BLI_ghash_new( BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp, __func__); @@ -835,6 +851,12 @@ bool BKE_lib_override_library_resync(Main *bmain, Scene *scene, ViewLayer *view_ } id->tag &= ~LIB_TAG_DOIT; } + /* Also cleanup old overrides that went missing in new linked data. */ + else if (id->tag & LIB_TAG_MISSING && !ID_IS_LINKED(id)) { + BLI_assert(ID_IS_OVERRIDE_LIBRARY(id)); + id->tag |= LIB_TAG_DOIT; + id->tag &= ~LIB_TAG_MISSING; + } } FOREACH_MAIN_ID_END; BKE_id_multi_tagged_delete(bmain); @@ -876,7 +898,7 @@ void BKE_lib_override_library_delete(Main *bmain, ID *id_root) id_root->tag |= LIB_TAG_DOIT; /* Tag all library overrides in the chains of dependencies from the given root one. */ - BKE_lib_override_library_override_group_tag(bmain, id_root, LIB_TAG_DOIT, true); + BKE_lib_override_library_override_group_tag(bmain, id_root, LIB_TAG_DOIT, LIB_TAG_DOIT, true); ID *id; FOREACH_MAIN_ID_BEGIN (bmain, id) { diff --git a/source/blender/blenkernel/intern/mesh_fair.cc b/source/blender/blenkernel/intern/mesh_fair.cc new file mode 100644 index 00000000000..527288d06cf --- /dev/null +++ b/source/blender/blenkernel/intern/mesh_fair.cc @@ -0,0 +1,505 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Mesh Fairing algorithm designed by Brett Fedack, used in the addon "Mesh Fairing": + * https://github.com/fedackb/mesh-fairing. + */ + +/** \file + * \ingroup bke + */ + +#include "BLI_map.hh" +#include "BLI_math.h" +#include "BLI_vector.hh" + +#include "DNA_mesh_types.h" +#include "DNA_meshdata_types.h" +#include "DNA_object_types.h" + +#include "BKE_lib_id.h" +#include "BKE_lib_query.h" +#include "BKE_mesh.h" +#include "BKE_mesh_fair.h" +#include "BKE_mesh_mapping.h" + +#include "bmesh.h" +#include "bmesh_tools.h" + +#include "MEM_guardedalloc.h" +#include "eigen_capi.h" + +using blender::Map; +using blender::Vector; +using std::array; + +class VertexWeight { + public: + virtual float weight_at_index(const int index) = 0; + virtual ~VertexWeight() = default; +}; + +class LoopWeight { + public: + virtual float weight_at_index(const int index) = 0; + virtual ~LoopWeight() = default; +}; + +class FairingContext { + public: + /* Get coordinates of vertices which are adjacent to the loop with specified index. */ + virtual void adjacents_coords_from_loop(const int loop, + float r_adj_next[3], + float r_adj_prev[3]) = 0; + + /* Get the other vertex index for a loop. */ + virtual int other_vertex_index_from_loop(const int loop, const unsigned int v) = 0; + + int vertex_count_get() + { + return totvert_; + } + + int loop_count_get() + { + return totvert_; + } + + MeshElemMap *vertex_loop_map_get(const int v) + { + return &vlmap_[v]; + } + + float *vertex_deformation_co_get(const int v) + { + return co_[v]; + } + + virtual ~FairingContext() = default; + + void fair_vertices(bool *affected, + const eMeshFairingDepth depth, + VertexWeight *vertex_weight, + LoopWeight *loop_weight) + { + + fair_vertices_ex(affected, (int)depth, vertex_weight, loop_weight); + } + + protected: + Vector<float *> co_; + + int totvert_; + int totloop_; + + MeshElemMap *vlmap_; + int *vlmap_mem_; + + private: + void fair_setup_fairing(const int v, + const int i, + LinearSolver *solver, + float multiplier, + const int depth, + Map<int, int> &vert_col_map, + VertexWeight *vertex_weight, + LoopWeight *loop_weight) + { + if (depth == 0) { + if (vert_col_map.contains(v)) { + const int j = vert_col_map.lookup(v); + EIG_linear_solver_matrix_add(solver, i, j, -multiplier); + return; + } + for (int j = 0; j < 3; j++) { + EIG_linear_solver_right_hand_side_add(solver, j, i, multiplier * co_[v][j]); + } + return; + } + + float w_ij_sum = 0; + const float w_i = vertex_weight->weight_at_index(v); + MeshElemMap *vlmap_elem = &vlmap_[v]; + for (int l = 0; l < vlmap_elem->count; l++) { + const int l_index = vlmap_elem->indices[l]; + const int other_vert = other_vertex_index_from_loop(l_index, v); + const float w_ij = loop_weight->weight_at_index(l_index); + w_ij_sum += w_ij; + fair_setup_fairing(other_vert, + i, + solver, + w_i * w_ij * multiplier, + depth - 1, + vert_col_map, + vertex_weight, + loop_weight); + } + fair_setup_fairing(v, + i, + solver, + -1 * w_i * w_ij_sum * multiplier, + depth - 1, + vert_col_map, + vertex_weight, + loop_weight); + } + + void fair_vertices_ex(bool *affected, + const int order, + VertexWeight *vertex_weight, + LoopWeight *loop_weight) + { + Map<int, int> vert_col_map; + int num_affected_vertices = 0; + for (int i = 0; i < totvert_; i++) { + if (!affected[i]) { + continue; + } + vert_col_map.add(i, num_affected_vertices); + num_affected_vertices++; + } + + /* Early return, nothing to do. */ + if (num_affected_vertices == 0 || num_affected_vertices == totvert_) { + return; + } + + /* Setup fairing matrices */ + LinearSolver *solver = EIG_linear_solver_new(num_affected_vertices, num_affected_vertices, 3); + for (auto item : vert_col_map.items()) { + const int v = item.key; + const int col = item.value; + fair_setup_fairing(v, col, solver, 1.0f, order, vert_col_map, vertex_weight, loop_weight); + } + + /* Solve linear system */ + EIG_linear_solver_solve(solver); + + /* Copy the result back to the mesh */ + for (auto item : vert_col_map.items()) { + const int v = item.key; + const int col = item.value; + for (int j = 0; j < 3; j++) { + co_[v][j] = EIG_linear_solver_variable_get(solver, j, col); + } + } + + /* Free solver data */ + EIG_linear_solver_delete(solver); + } +}; + +class MeshFairingContext : public FairingContext { + public: + MeshFairingContext(Mesh *mesh, MVert *deform_mverts) + { + totvert_ = mesh->totvert; + totloop_ = mesh->totloop; + + medge_ = mesh->medge; + mpoly_ = mesh->mpoly; + mloop_ = mesh->mloop; + BKE_mesh_vert_loop_map_create(&vlmap_, + &vlmap_mem_, + mesh->mpoly, + mesh->mloop, + mesh->totvert, + mesh->totpoly, + mesh->totloop); + + /* Deformation coords. */ + co_.reserve(mesh->totvert); + if (deform_mverts) { + for (int i = 0; i < mesh->totvert; i++) { + co_[i] = deform_mverts[i].co; + } + } + else { + for (int i = 0; i < mesh->totvert; i++) { + co_[i] = mesh->mvert[i].co; + } + } + + loop_to_poly_map_.reserve(mesh->totloop); + for (int i = 0; i < mesh->totpoly; i++) { + for (int l = 0; l < mesh->mpoly[i].totloop; l++) { + loop_to_poly_map_[l + mesh->mpoly[i].loopstart] = i; + } + } + } + + ~MeshFairingContext() + { + MEM_SAFE_FREE(vlmap_); + MEM_SAFE_FREE(vlmap_mem_); + } + + virtual void adjacents_coords_from_loop(const int loop, + float r_adj_next[3], + float r_adj_prev[3]) override + { + const int vert = mloop_[loop].v; + const MPoly *p = &mpoly_[loop_to_poly_map_[loop]]; + const int corner = poly_find_loop_from_vert(p, &mloop_[p->loopstart], vert); + copy_v3_v3(r_adj_next, co_[ME_POLY_LOOP_NEXT(mloop_, p, corner)->v]); + copy_v3_v3(r_adj_prev, co_[ME_POLY_LOOP_PREV(mloop_, p, corner)->v]); + } + + virtual int other_vertex_index_from_loop(const int loop, const unsigned int v) override + { + MEdge *e = &medge_[mloop_[loop].e]; + if (e->v1 == v) { + return e->v2; + } + return e->v1; + } + + protected: + Mesh *mesh_; + MLoop *mloop_; + MPoly *mpoly_; + MEdge *medge_; + Vector<int> loop_to_poly_map_; +}; + +class BMeshFairingContext : public FairingContext { + public: + BMeshFairingContext(BMesh *bm) + { + this->bm = bm; + totvert_ = bm->totvert; + totloop_ = bm->totloop; + + BM_mesh_elem_table_ensure(bm, BM_VERT); + BM_mesh_elem_index_ensure(bm, BM_LOOP); + + /* Deformation coords. */ + co_.reserve(bm->totvert); + for (int i = 0; i < bm->totvert; i++) { + BMVert *v = BM_vert_at_index(bm, i); + co_[i] = v->co; + } + + bmloop_.reserve(bm->totloop); + vlmap_ = (MeshElemMap *)MEM_calloc_arrayN(sizeof(MeshElemMap), bm->totvert, "bmesh loop map"); + vlmap_mem_ = (int *)MEM_malloc_arrayN(sizeof(int), bm->totloop, "bmesh loop map mempool"); + + BMVert *v; + BMLoop *l; + BMIter iter; + BMIter loop_iter; + int index_iter = 0; + + /* This initializes both the bmloop and the vlmap for bmesh in a single loop. */ + BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) { + int loop_count = 0; + const int vert_index = BM_elem_index_get(v); + vlmap_[vert_index].indices = &vlmap_mem_[index_iter]; + BM_ITER_ELEM (l, &loop_iter, v, BM_LOOPS_OF_VERT) { + const int loop_index = BM_elem_index_get(l); + bmloop_[loop_index] = l; + vlmap_mem_[index_iter] = loop_index; + index_iter++; + loop_count++; + } + vlmap_[vert_index].count = loop_count; + } + } + + ~BMeshFairingContext() + { + MEM_SAFE_FREE(vlmap_); + MEM_SAFE_FREE(vlmap_mem_); + } + + virtual void adjacents_coords_from_loop(const int loop, + float r_adj_next[3], + float r_adj_prev[3]) override + { + copy_v3_v3(r_adj_next, bmloop_[loop]->next->v->co); + copy_v3_v3(r_adj_prev, bmloop_[loop]->prev->v->co); + } + + virtual int other_vertex_index_from_loop(const int loop, const unsigned int v) override + { + BMLoop *l = bmloop_[loop]; + BMVert *bmvert = BM_vert_at_index(bm, v); + BMVert *bm_other_vert = BM_edge_other_vert(l->e, bmvert); + return BM_elem_index_get(bm_other_vert); + } + + protected: + BMesh *bm; + Vector<BMLoop *> bmloop_; +}; + +class UniformVertexWeight : public VertexWeight { + public: + UniformVertexWeight(FairingContext *fairing_context) + { + const int totvert = fairing_context->vertex_count_get(); + vertex_weights_.reserve(totvert); + for (int i = 0; i < totvert; i++) { + const int tot_loop = fairing_context->vertex_loop_map_get(i)->count; + if (tot_loop != 0) { + vertex_weights_[i] = 1.0f / tot_loop; + } + else { + vertex_weights_[i] = FLT_MAX; + } + } + } + ~UniformVertexWeight() = default; + + float weight_at_index(const int index) override + { + return vertex_weights_[index]; + } + + private: + Vector<float> vertex_weights_; +}; + +class VoronoiVertexWeight : public VertexWeight { + + public: + VoronoiVertexWeight(FairingContext *fairing_context) + { + + const int totvert = fairing_context->vertex_count_get(); + vertex_weights_.reserve(totvert); + for (int i = 0; i < totvert; i++) { + + float area = 0.0f; + float a[3]; + copy_v3_v3(a, fairing_context->vertex_deformation_co_get(i)); + const float acute_threshold = M_PI_2; + + MeshElemMap *vlmap_elem = fairing_context->vertex_loop_map_get(i); + for (int l = 0; l < vlmap_elem->count; l++) { + const int l_index = vlmap_elem->indices[l]; + + float b[3], c[3], d[3]; + fairing_context->adjacents_coords_from_loop(l_index, b, c); + + if (angle_v3v3v3(c, fairing_context->vertex_deformation_co_get(i), b) < acute_threshold) { + calc_circumcenter(d, a, b, c); + } + else { + add_v3_v3v3(d, b, c); + mul_v3_fl(d, 0.5f); + } + + float t[3]; + add_v3_v3v3(t, a, b); + mul_v3_fl(t, 0.5f); + area += area_tri_v3(a, t, d); + + add_v3_v3v3(t, a, c); + mul_v3_fl(t, 0.5f); + area += area_tri_v3(a, d, t); + } + + vertex_weights_[i] = area != 0.0f ? 1.0f / area : 1e12; + } + } + ~VoronoiVertexWeight() = default; + + float weight_at_index(const int index) override + { + return vertex_weights_[index]; + } + + private: + Vector<float> vertex_weights_; + + void calc_circumcenter(float r[3], const float a[3], const float b[3], const float c[3]) + { + float ab[3]; + sub_v3_v3v3(ab, b, a); + + float ac[3]; + sub_v3_v3v3(ac, c, a); + + float ab_cross_ac[3]; + cross_v3_v3v3(ab_cross_ac, ab, ac); + + if (len_squared_v3(ab_cross_ac) > 0.0f) { + float d[3]; + cross_v3_v3v3(d, ab_cross_ac, ab); + mul_v3_fl(d, len_squared_v3(ac)); + + float t[3]; + cross_v3_v3v3(t, ac, ab_cross_ac); + mul_v3_fl(t, len_squared_v3(ab)); + + add_v3_v3(d, t); + + mul_v3_fl(d, 1.0f / (2.0f * len_squared_v3(ab_cross_ac))); + + add_v3_v3v3(r, a, d); + return; + } + copy_v3_v3(r, a); + } +}; + +class UniformLoopWeight : public LoopWeight { + public: + float weight_at_index(const int UNUSED(index)) override + { + return 1.0f; + } +}; + +static void prefair_and_fair_vertices(FairingContext *fairing_context, + bool *affected_vertices, + const eMeshFairingDepth depth) +{ + /* Prefair. */ + UniformVertexWeight *uniform_vertex_weights = new UniformVertexWeight(fairing_context); + UniformLoopWeight *uniform_loop_weights = new UniformLoopWeight(); + fairing_context->fair_vertices( + affected_vertices, depth, uniform_vertex_weights, uniform_loop_weights); + delete uniform_vertex_weights; + + /* Fair. */ + VoronoiVertexWeight *voronoi_vertex_weights = new VoronoiVertexWeight(fairing_context); + /* TODO: Implemente cotangent loop weights. */ + fairing_context->fair_vertices( + affected_vertices, depth, voronoi_vertex_weights, uniform_loop_weights); + + delete uniform_loop_weights; + delete voronoi_vertex_weights; +} + +void BKE_mesh_prefair_and_fair_vertices(struct Mesh *mesh, + struct MVert *deform_mverts, + bool *affect_vertices, + const eMeshFairingDepth depth) +{ + MeshFairingContext *fairing_context = new MeshFairingContext(mesh, deform_mverts); + prefair_and_fair_vertices(fairing_context, affect_vertices, depth); + delete fairing_context; +} + +void BKE_bmesh_prefair_and_fair_vertices(struct BMesh *bm, + bool *affect_vertices, + const eMeshFairingDepth depth) +{ + BMeshFairingContext *fairing_context = new BMeshFairingContext(bm); + prefair_and_fair_vertices(fairing_context, affect_vertices, depth); + delete fairing_context; +} diff --git a/source/blender/blenkernel/intern/multires_unsubdivide.h b/source/blender/blenkernel/intern/multires_unsubdivide.h index 39c6da0b6c8..0a03387282f 100644 --- a/source/blender/blenkernel/intern/multires_unsubdivide.h +++ b/source/blender/blenkernel/intern/multires_unsubdivide.h @@ -26,10 +26,8 @@ #include "BLI_sys_types.h" struct BMesh; -struct Depsgraph; struct Mesh; struct MultiresModifierData; -struct Object; typedef struct MultiresUnsubdivideGrid { /* For sanity checks. */ diff --git a/source/blender/blenkernel/intern/node.c b/source/blender/blenkernel/intern/node.c index 87997198334..415eb14be66 100644 --- a/source/blender/blenkernel/intern/node.c +++ b/source/blender/blenkernel/intern/node.c @@ -4737,10 +4737,11 @@ static void registerGeometryNodes(void) register_node_type_geo_point_distribute(); register_node_type_geo_point_instance(); register_node_type_geo_object_info(); - register_node_type_geo_random_attribute(); + register_node_type_geo_attribute_randomize(); register_node_type_geo_attribute_math(); register_node_type_geo_join_geometry(); register_node_type_geo_attribute_mix(); + register_node_type_geo_attribute_color_ramp(); } static void registerFunctionNodes(void) diff --git a/source/blender/blenkernel/intern/scene.c b/source/blender/blenkernel/intern/scene.c index f63d443d29f..cc192c1c3c0 100644 --- a/source/blender/blenkernel/intern/scene.c +++ b/source/blender/blenkernel/intern/scene.c @@ -222,6 +222,7 @@ static void scene_init_data(ID *id) /* Curve Profile */ scene->toolsettings->custom_bevel_profile_preset = BKE_curveprofile_add(PROF_PRESET_LINE); + scene->toolsettings->sequencer_tool_settings = SEQ_tool_settings_init(); for (size_t i = 0; i < ARRAY_SIZE(scene->orientation_slots); i++) { scene->orientation_slots[i].index_custom = -1; @@ -862,6 +863,9 @@ static void scene_blend_write(BlendWriter *writer, ID *id, const void *id_addres if (tos->custom_bevel_profile_preset) { BKE_curveprofile_blend_write(writer, tos->custom_bevel_profile_preset); } + if (tos->sequencer_tool_settings) { + BLO_write_struct(writer, SequencerToolSettings, tos->sequencer_tool_settings); + } BKE_paint_blend_write(writer, &tos->imapaint.paint); @@ -1121,6 +1125,8 @@ static void scene_blend_read_data(BlendDataReader *reader, ID *id) if (sce->toolsettings->custom_bevel_profile_preset) { BKE_curveprofile_blend_read(reader, sce->toolsettings->custom_bevel_profile_preset); } + + BLO_read_data_address(reader, &sce->toolsettings->sequencer_tool_settings); } if (sce->ed) { @@ -1792,6 +1798,8 @@ ToolSettings *BKE_toolsettings_copy(ToolSettings *toolsettings, const int flag) ts->gp_sculpt.cur_primitive = BKE_curvemapping_copy(ts->gp_sculpt.cur_primitive); ts->custom_bevel_profile_preset = BKE_curveprofile_copy(ts->custom_bevel_profile_preset); + + ts->sequencer_tool_settings = SEQ_tool_settings_copy(ts->sequencer_tool_settings); return ts; } @@ -1850,6 +1858,10 @@ void BKE_toolsettings_free(ToolSettings *toolsettings) BKE_curveprofile_free(toolsettings->custom_bevel_profile_preset); } + if (toolsettings->sequencer_tool_settings) { + SEQ_tool_settings_free(toolsettings->sequencer_tool_settings); + } + MEM_freeN(toolsettings); } |