diff options
author | Hans Goudey <h.goudey@me.com> | 2022-08-30 19:18:40 +0300 |
---|---|---|
committer | Hans Goudey <h.goudey@me.com> | 2022-08-30 19:18:40 +0300 |
commit | abe6c640990962735f6f34d26a401c9e506baee3 (patch) | |
tree | 89fcc951de5a3f6c82a9de9f466241f5b94a0168 /source/blender/blenkernel/intern | |
parent | fa8957e0599cf2be06c4822d9a5c0231320d2077 (diff) | |
parent | 82a46ea6f8829fc40205d0d3cabf4017eb738d9a (diff) |
Merge branch 'master' into refactor-mesh-material-index-generic
Diffstat (limited to 'source/blender/blenkernel/intern')
-rw-r--r-- | source/blender/blenkernel/intern/attribute.cc | 8 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/attribute_access.cc | 120 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/geometry_component_curves.cc | 34 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/geometry_component_mesh.cc | 5 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/geometry_fields.cc | 365 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/geometry_set.cc | 43 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/gpencil_geom.cc | 8 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/lib_override.cc | 329 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/mesh.cc | 4 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/mesh_remesh_voxel.cc | 36 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/node.cc | 6 |
11 files changed, 589 insertions, 369 deletions
diff --git a/source/blender/blenkernel/intern/attribute.cc b/source/blender/blenkernel/intern/attribute.cc index 495a2c82332..ccaa6e56f08 100644 --- a/source/blender/blenkernel/intern/attribute.cc +++ b/source/blender/blenkernel/intern/attribute.cc @@ -187,9 +187,9 @@ static bool unique_name_cb(void *arg, const char *name) continue; } - CustomData *cdata = info[domain].customdata; + const CustomData *cdata = info[domain].customdata; for (int i = 0; i < cdata->totlayer; i++) { - CustomDataLayer *layer = cdata->layers + i; + const CustomDataLayer *layer = cdata->layers + i; if (STREQ(layer->name, name)) { return true; @@ -493,10 +493,10 @@ void BKE_id_attributes_active_set(ID *id, CustomDataLayer *active_layer) int index = 0; for (const int domain : IndexRange(ATTR_DOMAIN_NUM)) { - CustomData *customdata = info[domain].customdata; + const CustomData *customdata = info[domain].customdata; if (customdata) { for (int i = 0; i < customdata->totlayer; i++) { - CustomDataLayer *layer = &customdata->layers[i]; + const CustomDataLayer *layer = &customdata->layers[i]; if (layer == active_layer) { *BKE_id_attributes_active_index_p(id) = index; return; diff --git a/source/blender/blenkernel/intern/attribute_access.cc b/source/blender/blenkernel/intern/attribute_access.cc index b9995796a21..313e6a172ac 100644 --- a/source/blender/blenkernel/intern/attribute_access.cc +++ b/source/blender/blenkernel/intern/attribute_access.cc @@ -5,7 +5,6 @@ #include "BKE_attribute_math.hh" #include "BKE_customdata.h" #include "BKE_deform.h" -#include "BKE_geometry_fields.hh" #include "BKE_geometry_set.hh" #include "BKE_mesh.h" #include "BKE_pointcloud.h" @@ -794,7 +793,7 @@ void CustomDataAttributes::reorder(Span<AttributeIDRef> new_order) } /* -------------------------------------------------------------------- */ -/** \name Geometry Component +/** \name Attribute API * \{ */ static blender::GVArray try_adapt_data_type(blender::GVArray varray, @@ -805,123 +804,6 @@ static blender::GVArray try_adapt_data_type(blender::GVArray varray, return conversions.try_convert(std::move(varray), to_type); } -GVArray GeometryFieldInput::get_varray_for_context(const fn::FieldContext &context, - IndexMask mask, - ResourceScope &UNUSED(scope)) const -{ - if (const GeometryComponentFieldContext *geometry_context = - dynamic_cast<const GeometryComponentFieldContext *>(&context)) { - const GeometryComponent &component = geometry_context->geometry_component(); - const eAttrDomain domain = geometry_context->domain(); - return this->get_varray_for_context(component, domain, mask); - } - return {}; -} - -GVArray AttributeFieldInput::get_varray_for_context(const GeometryComponent &component, - const eAttrDomain domain, - IndexMask UNUSED(mask)) const -{ - const eCustomDataType data_type = cpp_type_to_custom_data_type(*type_); - if (auto attributes = component.attributes()) { - return attributes->lookup(name_, domain, data_type); - } - return {}; -} - -std::string AttributeFieldInput::socket_inspection_name() const -{ - std::stringstream ss; - ss << '"' << name_ << '"' << TIP_(" attribute from geometry"); - return ss.str(); -} - -uint64_t AttributeFieldInput::hash() const -{ - return get_default_hash_2(name_, type_); -} - -bool AttributeFieldInput::is_equal_to(const fn::FieldNode &other) const -{ - if (const AttributeFieldInput *other_typed = dynamic_cast<const AttributeFieldInput *>(&other)) { - return name_ == other_typed->name_ && type_ == other_typed->type_; - } - return false; -} - -static StringRef get_random_id_attribute_name(const eAttrDomain domain) -{ - switch (domain) { - case ATTR_DOMAIN_POINT: - case ATTR_DOMAIN_INSTANCE: - return "id"; - default: - return ""; - } -} - -GVArray IDAttributeFieldInput::get_varray_for_context(const GeometryComponent &component, - const eAttrDomain domain, - IndexMask mask) const -{ - - const StringRef name = get_random_id_attribute_name(domain); - if (auto attributes = component.attributes()) { - if (GVArray attribute = attributes->lookup(name, domain, CD_PROP_INT32)) { - return attribute; - } - } - - /* Use the index as the fallback if no random ID attribute exists. */ - return fn::IndexFieldInput::get_index_varray(mask); -} - -std::string IDAttributeFieldInput::socket_inspection_name() const -{ - return TIP_("ID / Index"); -} - -uint64_t IDAttributeFieldInput::hash() const -{ - /* All random ID attribute inputs are the same within the same evaluation context. */ - return 92386459827; -} - -bool IDAttributeFieldInput::is_equal_to(const fn::FieldNode &other) const -{ - /* All random ID attribute inputs are the same within the same evaluation context. */ - return dynamic_cast<const IDAttributeFieldInput *>(&other) != nullptr; -} - -GVArray AnonymousAttributeFieldInput::get_varray_for_context(const GeometryComponent &component, - const eAttrDomain domain, - IndexMask UNUSED(mask)) const -{ - const eCustomDataType data_type = cpp_type_to_custom_data_type(*type_); - return component.attributes()->lookup(anonymous_id_.get(), domain, data_type); -} - -std::string AnonymousAttributeFieldInput::socket_inspection_name() const -{ - std::stringstream ss; - ss << '"' << debug_name_ << '"' << TIP_(" from ") << producer_name_; - return ss.str(); -} - -uint64_t AnonymousAttributeFieldInput::hash() const -{ - return get_default_hash_2(anonymous_id_.get(), type_); -} - -bool AnonymousAttributeFieldInput::is_equal_to(const fn::FieldNode &other) const -{ - if (const AnonymousAttributeFieldInput *other_typed = - dynamic_cast<const AnonymousAttributeFieldInput *>(&other)) { - return anonymous_id_.get() == other_typed->anonymous_id_.get() && type_ == other_typed->type_; - } - return false; -} - GVArray AttributeAccessor::lookup(const AttributeIDRef &attribute_id, const std::optional<eAttrDomain> domain, const std::optional<eCustomDataType> data_type) const diff --git a/source/blender/blenkernel/intern/geometry_component_curves.cc b/source/blender/blenkernel/intern/geometry_component_curves.cc index 2714c78e381..596c8e0bfc7 100644 --- a/source/blender/blenkernel/intern/geometry_component_curves.cc +++ b/source/blender/blenkernel/intern/geometry_component_curves.cc @@ -206,18 +206,11 @@ static Array<float3> curve_normal_point_domain(const bke::CurvesGeometry &curves return results; } -VArray<float3> curve_normals_varray(const CurveComponent &component, const eAttrDomain domain) +VArray<float3> curve_normals_varray(const CurvesGeometry &curves, const eAttrDomain domain) { - if (!component.has_curves()) { - return {}; - } - - const Curves &curves_id = *component.get_for_read(); - const bke::CurvesGeometry &curves = bke::CurvesGeometry::wrap(curves_id.geometry); - const VArray<int8_t> types = curves.curve_types(); if (curves.is_single_type(CURVE_TYPE_POLY)) { - return component.attributes()->adapt_domain<float3>( + return curves.adapt_domain<float3>( VArray<float3>::ForSpan(curves.evaluated_normals()), ATTR_DOMAIN_POINT, domain); } @@ -228,7 +221,7 @@ VArray<float3> curve_normals_varray(const CurveComponent &component, const eAttr } if (domain == ATTR_DOMAIN_CURVE) { - return component.attributes()->adapt_domain<float3>( + return curves.adapt_domain<float3>( VArray<float3>::ForContainer(std::move(normals)), ATTR_DOMAIN_POINT, ATTR_DOMAIN_CURVE); } @@ -241,15 +234,9 @@ VArray<float3> curve_normals_varray(const CurveComponent &component, const eAttr /** \name Curve Length Field Input * \{ */ -static VArray<float> construct_curve_length_gvarray(const CurveComponent &component, +static VArray<float> construct_curve_length_gvarray(const CurvesGeometry &curves, const eAttrDomain domain) { - if (!component.has_curves()) { - return {}; - } - const Curves &curves_id = *component.get_for_read(); - const bke::CurvesGeometry &curves = bke::CurvesGeometry::wrap(curves_id.geometry); - curves.ensure_evaluated_lengths(); VArray<bool> cyclic = curves.cyclic(); @@ -263,28 +250,23 @@ static VArray<float> construct_curve_length_gvarray(const CurveComponent &compon } if (domain == ATTR_DOMAIN_POINT) { - return component.attributes()->adapt_domain<float>( - std::move(lengths), ATTR_DOMAIN_CURVE, ATTR_DOMAIN_POINT); + return curves.adapt_domain<float>(std::move(lengths), ATTR_DOMAIN_CURVE, ATTR_DOMAIN_POINT); } return {}; } CurveLengthFieldInput::CurveLengthFieldInput() - : GeometryFieldInput(CPPType::get<float>(), "Spline Length node") + : CurvesFieldInput(CPPType::get<float>(), "Spline Length node") { category_ = Category::Generated; } -GVArray CurveLengthFieldInput::get_varray_for_context(const GeometryComponent &component, +GVArray CurveLengthFieldInput::get_varray_for_context(const CurvesGeometry &curves, const eAttrDomain domain, IndexMask UNUSED(mask)) const { - if (component.type() == GEO_COMPONENT_TYPE_CURVE) { - const CurveComponent &curve_component = static_cast<const CurveComponent &>(component); - return construct_curve_length_gvarray(curve_component, domain); - } - return {}; + return construct_curve_length_gvarray(curves, domain); } uint64_t CurveLengthFieldInput::hash() const diff --git a/source/blender/blenkernel/intern/geometry_component_mesh.cc b/source/blender/blenkernel/intern/geometry_component_mesh.cc index 351af04ceba..ff55409d5fc 100644 --- a/source/blender/blenkernel/intern/geometry_component_mesh.cc +++ b/source/blender/blenkernel/intern/geometry_component_mesh.cc @@ -115,8 +115,7 @@ void MeshComponent::ensure_owns_direct_data() namespace blender::bke { -VArray<float3> mesh_normals_varray(const MeshComponent &mesh_component, - const Mesh &mesh, +VArray<float3> mesh_normals_varray(const Mesh &mesh, const IndexMask mask, const eAttrDomain domain) { @@ -150,7 +149,7 @@ VArray<float3> mesh_normals_varray(const MeshComponent &mesh_component, * array and copy the face normal for each of its corners. In this case using the mesh * component's generic domain interpolation is fine, the data will still be normalized, * since the face normal is just copied to every corner. */ - return mesh_component.attributes()->adapt_domain( + return mesh_attributes(mesh).adapt_domain( VArray<float3>::ForSpan({(float3 *)BKE_mesh_poly_normals_ensure(&mesh), mesh.totpoly}), ATTR_DOMAIN_FACE, ATTR_DOMAIN_CORNER); diff --git a/source/blender/blenkernel/intern/geometry_fields.cc b/source/blender/blenkernel/intern/geometry_fields.cc new file mode 100644 index 00000000000..a52ffb6496b --- /dev/null +++ b/source/blender/blenkernel/intern/geometry_fields.cc @@ -0,0 +1,365 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ + +#include "BKE_attribute.hh" +#include "BKE_curves.hh" +#include "BKE_geometry_fields.hh" +#include "BKE_geometry_set.hh" +#include "BKE_mesh.h" +#include "BKE_pointcloud.h" +#include "BKE_type_conversions.hh" + +#include "DNA_mesh_types.h" +#include "DNA_pointcloud_types.h" + +#include "BLT_translation.h" + +namespace blender::bke { + +MeshFieldContext::MeshFieldContext(const Mesh &mesh, const eAttrDomain domain) + : mesh_(mesh), domain_(domain) +{ + BLI_assert(mesh_attributes(mesh).domain_supported(domain_)); +} + +CurvesFieldContext::CurvesFieldContext(const CurvesGeometry &curves, const eAttrDomain domain) + : curves_(curves), domain_(domain) +{ + BLI_assert(curves.attributes().domain_supported(domain)); +} + +GeometryFieldContext::GeometryFieldContext(const void *geometry, + const GeometryComponentType type, + const eAttrDomain domain) + : geometry_(geometry), type_(type), domain_(domain) +{ + BLI_assert(ELEM(type, + GEO_COMPONENT_TYPE_MESH, + GEO_COMPONENT_TYPE_CURVE, + GEO_COMPONENT_TYPE_POINT_CLOUD, + GEO_COMPONENT_TYPE_INSTANCES)); +} + +GeometryFieldContext::GeometryFieldContext(const GeometryComponent &component, + const eAttrDomain domain) + : type_(component.type()), domain_(domain) +{ + switch (component.type()) { + case GEO_COMPONENT_TYPE_MESH: { + const MeshComponent &mesh_component = static_cast<const MeshComponent &>(component); + geometry_ = mesh_component.get_for_read(); + break; + } + case GEO_COMPONENT_TYPE_CURVE: { + const CurveComponent &curve_component = static_cast<const CurveComponent &>(component); + const Curves *curves = curve_component.get_for_read(); + geometry_ = curves ? &CurvesGeometry::wrap(curves->geometry) : nullptr; + break; + } + case GEO_COMPONENT_TYPE_POINT_CLOUD: { + const PointCloudComponent &pointcloud_component = static_cast<const PointCloudComponent &>( + component); + geometry_ = pointcloud_component.get_for_read(); + break; + } + case GEO_COMPONENT_TYPE_INSTANCES: { + const InstancesComponent &instances_component = static_cast<const InstancesComponent &>( + component); + geometry_ = &instances_component; + break; + } + case GEO_COMPONENT_TYPE_VOLUME: + case GEO_COMPONENT_TYPE_EDIT: + BLI_assert_unreachable(); + break; + } +} + +GeometryFieldContext::GeometryFieldContext(const Mesh &mesh, eAttrDomain domain) + : geometry_(&mesh), type_(GEO_COMPONENT_TYPE_MESH), domain_(domain) +{ +} +GeometryFieldContext::GeometryFieldContext(const CurvesGeometry &curves, eAttrDomain domain) + : geometry_(&curves), type_(GEO_COMPONENT_TYPE_CURVE), domain_(domain) +{ +} +GeometryFieldContext::GeometryFieldContext(const PointCloud &points) + : geometry_(&points), type_(GEO_COMPONENT_TYPE_POINT_CLOUD), domain_(ATTR_DOMAIN_POINT) +{ +} +GeometryFieldContext::GeometryFieldContext(const InstancesComponent &instances) + : geometry_(&instances), type_(GEO_COMPONENT_TYPE_INSTANCES), domain_(ATTR_DOMAIN_INSTANCE) +{ +} + +std::optional<AttributeAccessor> GeometryFieldContext::attributes() const +{ + if (const Mesh *mesh = this->mesh()) { + return mesh_attributes(*mesh); + } + if (const CurvesGeometry *curves = this->curves()) { + return curves->attributes(); + } + if (const PointCloud *pointcloud = this->pointcloud()) { + return pointcloud_attributes(*pointcloud); + } + if (const InstancesComponent *instances = this->instances()) { + return instances->attributes(); + } + return {}; +} + +const Mesh *GeometryFieldContext::mesh() const +{ + return this->type() == GEO_COMPONENT_TYPE_MESH ? static_cast<const Mesh *>(geometry_) : nullptr; +} +const CurvesGeometry *GeometryFieldContext::curves() const +{ + return this->type() == GEO_COMPONENT_TYPE_CURVE ? + static_cast<const CurvesGeometry *>(geometry_) : + nullptr; +} +const PointCloud *GeometryFieldContext::pointcloud() const +{ + return this->type() == GEO_COMPONENT_TYPE_POINT_CLOUD ? + static_cast<const PointCloud *>(geometry_) : + nullptr; +} +const InstancesComponent *GeometryFieldContext::instances() const +{ + return this->type() == GEO_COMPONENT_TYPE_INSTANCES ? + static_cast<const InstancesComponent *>(geometry_) : + nullptr; +} + +GVArray GeometryFieldInput::get_varray_for_context(const fn::FieldContext &context, + const IndexMask mask, + ResourceScope & /*scope*/) const +{ + if (const GeometryFieldContext *geometry_context = dynamic_cast<const GeometryFieldContext *>( + &context)) { + return this->get_varray_for_context(*geometry_context, mask); + } + if (const MeshFieldContext *mesh_context = dynamic_cast<const MeshFieldContext *>(&context)) { + return this->get_varray_for_context({mesh_context->mesh(), mesh_context->domain()}, mask); + } + if (const CurvesFieldContext *curve_context = dynamic_cast<const CurvesFieldContext *>( + &context)) { + return this->get_varray_for_context({curve_context->curves(), curve_context->domain()}, mask); + } + if (const PointCloudFieldContext *point_context = dynamic_cast<const PointCloudFieldContext *>( + &context)) { + return this->get_varray_for_context({point_context->pointcloud()}, mask); + } + if (const InstancesFieldContext *instances_context = dynamic_cast<const InstancesFieldContext *>( + &context)) { + return this->get_varray_for_context({instances_context->instances()}, mask); + } + return {}; +} + +GVArray MeshFieldInput::get_varray_for_context(const fn::FieldContext &context, + const IndexMask mask, + ResourceScope & /*scope*/) const +{ + if (const GeometryFieldContext *geometry_context = dynamic_cast<const GeometryFieldContext *>( + &context)) { + if (const Mesh *mesh = geometry_context->mesh()) { + return this->get_varray_for_context(*mesh, geometry_context->domain(), mask); + } + } + if (const MeshFieldContext *mesh_context = dynamic_cast<const MeshFieldContext *>(&context)) { + return this->get_varray_for_context(mesh_context->mesh(), mesh_context->domain(), mask); + } + return {}; +} + +GVArray CurvesFieldInput::get_varray_for_context(const fn::FieldContext &context, + IndexMask mask, + ResourceScope & /*scope*/) const +{ + if (const GeometryFieldContext *geometry_context = dynamic_cast<const GeometryFieldContext *>( + &context)) { + if (const CurvesGeometry *curves = geometry_context->curves()) { + return this->get_varray_for_context(*curves, geometry_context->domain(), mask); + } + } + if (const CurvesFieldContext *curves_context = dynamic_cast<const CurvesFieldContext *>( + &context)) { + return this->get_varray_for_context(curves_context->curves(), curves_context->domain(), mask); + } + return {}; +} + +GVArray PointCloudFieldInput::get_varray_for_context(const fn::FieldContext &context, + IndexMask mask, + ResourceScope & /*scope*/) const +{ + if (const GeometryFieldContext *geometry_context = dynamic_cast<const GeometryFieldContext *>( + &context)) { + if (const PointCloud *pointcloud = geometry_context->pointcloud()) { + return this->get_varray_for_context(*pointcloud, mask); + } + } + if (const PointCloudFieldContext *point_context = dynamic_cast<const PointCloudFieldContext *>( + &context)) { + return this->get_varray_for_context(point_context->pointcloud(), mask); + } + return {}; +} + +GVArray InstancesFieldInput::get_varray_for_context(const fn::FieldContext &context, + IndexMask mask, + ResourceScope & /*scope*/) const +{ + if (const GeometryFieldContext *geometry_context = dynamic_cast<const GeometryFieldContext *>( + &context)) { + if (const InstancesComponent *instances = geometry_context->instances()) { + return this->get_varray_for_context(*instances, mask); + } + } + if (const InstancesFieldContext *instances_context = dynamic_cast<const InstancesFieldContext *>( + &context)) { + return this->get_varray_for_context(instances_context->instances(), mask); + } + return {}; +} + +GVArray AttributeFieldInput::get_varray_for_context(const GeometryFieldContext &context, + IndexMask UNUSED(mask)) const +{ + const eCustomDataType data_type = cpp_type_to_custom_data_type(*type_); + if (auto attributes = context.attributes()) { + return attributes->lookup(name_, context.domain(), data_type); + } + return {}; +} + +std::string AttributeFieldInput::socket_inspection_name() const +{ + std::stringstream ss; + ss << '"' << name_ << '"' << TIP_(" attribute from geometry"); + return ss.str(); +} + +uint64_t AttributeFieldInput::hash() const +{ + return get_default_hash_2(name_, type_); +} + +bool AttributeFieldInput::is_equal_to(const fn::FieldNode &other) const +{ + if (const AttributeFieldInput *other_typed = dynamic_cast<const AttributeFieldInput *>(&other)) { + return name_ == other_typed->name_ && type_ == other_typed->type_; + } + return false; +} + +static StringRef get_random_id_attribute_name(const eAttrDomain domain) +{ + switch (domain) { + case ATTR_DOMAIN_POINT: + case ATTR_DOMAIN_INSTANCE: + return "id"; + default: + return ""; + } +} + +GVArray IDAttributeFieldInput::get_varray_for_context(const GeometryFieldContext &context, + const IndexMask mask) const +{ + + const StringRef name = get_random_id_attribute_name(context.domain()); + if (auto attributes = context.attributes()) { + if (GVArray attribute = attributes->lookup(name, context.domain(), CD_PROP_INT32)) { + return attribute; + } + } + + /* Use the index as the fallback if no random ID attribute exists. */ + return fn::IndexFieldInput::get_index_varray(mask); +} + +std::string IDAttributeFieldInput::socket_inspection_name() const +{ + return TIP_("ID / Index"); +} + +uint64_t IDAttributeFieldInput::hash() const +{ + /* All random ID attribute inputs are the same within the same evaluation context. */ + return 92386459827; +} + +bool IDAttributeFieldInput::is_equal_to(const fn::FieldNode &other) const +{ + /* All random ID attribute inputs are the same within the same evaluation context. */ + return dynamic_cast<const IDAttributeFieldInput *>(&other) != nullptr; +} + +GVArray AnonymousAttributeFieldInput::get_varray_for_context(const GeometryFieldContext &context, + const IndexMask /*mask*/) const +{ + const eCustomDataType data_type = cpp_type_to_custom_data_type(*type_); + return context.attributes()->lookup(anonymous_id_.get(), context.domain(), data_type); +} + +std::string AnonymousAttributeFieldInput::socket_inspection_name() const +{ + std::stringstream ss; + ss << '"' << debug_name_ << '"' << TIP_(" from ") << producer_name_; + return ss.str(); +} + +uint64_t AnonymousAttributeFieldInput::hash() const +{ + return get_default_hash_2(anonymous_id_.get(), type_); +} + +bool AnonymousAttributeFieldInput::is_equal_to(const fn::FieldNode &other) const +{ + if (const AnonymousAttributeFieldInput *other_typed = + dynamic_cast<const AnonymousAttributeFieldInput *>(&other)) { + return anonymous_id_.get() == other_typed->anonymous_id_.get() && type_ == other_typed->type_; + } + return false; +} + +} // namespace blender::bke + +/* -------------------------------------------------------------------- */ +/** \name Mesh and Curve Normals Field Input + * \{ */ + +namespace blender::bke { + +GVArray NormalFieldInput::get_varray_for_context(const GeometryFieldContext &context, + const IndexMask mask) const +{ + if (const Mesh *mesh = context.mesh()) { + return mesh_normals_varray(*mesh, mask, context.domain()); + } + if (const CurvesGeometry *curves = context.curves()) { + return curve_normals_varray(*curves, context.domain()); + } + return {}; +} + +std::string NormalFieldInput::socket_inspection_name() const +{ + return TIP_("Normal"); +} + +uint64_t NormalFieldInput::hash() const +{ + return 213980475983; +} + +bool NormalFieldInput::is_equal_to(const fn::FieldNode &other) const +{ + return dynamic_cast<const NormalFieldInput *>(&other) != nullptr; +} + +} // namespace blender::bke + +/** \} */ diff --git a/source/blender/blenkernel/intern/geometry_set.cc b/source/blender/blenkernel/intern/geometry_set.cc index 1a0ce4f0893..633d9ad8c49 100644 --- a/source/blender/blenkernel/intern/geometry_set.cc +++ b/source/blender/blenkernel/intern/geometry_set.cc @@ -8,7 +8,6 @@ #include "BKE_attribute.h" #include "BKE_curves.hh" -#include "BKE_geometry_fields.hh" #include "BKE_geometry_set.hh" #include "BKE_lib_id.h" #include "BKE_mesh.h" @@ -634,48 +633,6 @@ void GeometrySet::modify_geometry_sets(ForeachSubGeometryCallback callback) /** \} */ /* -------------------------------------------------------------------- */ -/** \name Mesh and Curve Normals Field Input - * \{ */ - -namespace blender::bke { - -GVArray NormalFieldInput::get_varray_for_context(const GeometryComponent &component, - const eAttrDomain domain, - IndexMask mask) const -{ - if (component.type() == GEO_COMPONENT_TYPE_MESH) { - const MeshComponent &mesh_component = static_cast<const MeshComponent &>(component); - if (const Mesh *mesh = mesh_component.get_for_read()) { - return mesh_normals_varray(mesh_component, *mesh, mask, domain); - } - } - else if (component.type() == GEO_COMPONENT_TYPE_CURVE) { - const CurveComponent &curve_component = static_cast<const CurveComponent &>(component); - return curve_normals_varray(curve_component, domain); - } - return {}; -} - -std::string NormalFieldInput::socket_inspection_name() const -{ - return TIP_("Normal"); -} - -uint64_t NormalFieldInput::hash() const -{ - return 213980475983; -} - -bool NormalFieldInput::is_equal_to(const fn::FieldNode &other) const -{ - return dynamic_cast<const NormalFieldInput *>(&other) != nullptr; -} - -} // namespace blender::bke - -/** \} */ - -/* -------------------------------------------------------------------- */ /** \name C API * \{ */ diff --git a/source/blender/blenkernel/intern/gpencil_geom.cc b/source/blender/blenkernel/intern/gpencil_geom.cc index 85ff81ba80e..ce2e106c664 100644 --- a/source/blender/blenkernel/intern/gpencil_geom.cc +++ b/source/blender/blenkernel/intern/gpencil_geom.cc @@ -3966,6 +3966,7 @@ static ListBase *gpencil_stroke_perimeter_ex(const bGPdata *gpd, const bGPDlayer *gpl, const bGPDstroke *gps, int subdivisions, + const float thickness_chg, int *r_num_perimeter_points) { /* sanity check */ @@ -3974,7 +3975,9 @@ static ListBase *gpencil_stroke_perimeter_ex(const bGPdata *gpd, } float defaultpixsize = 1000.0f / gpd->pixfactor; + float ovr_radius = thickness_chg / defaultpixsize / 2.0f; float stroke_radius = ((gps->thickness + gpl->line_change) / defaultpixsize) / 2.0f; + stroke_radius = max_ff(stroke_radius - ovr_radius, 0.0f); ListBase *perimeter_right_side = MEM_cnew<ListBase>(__func__); ListBase *perimeter_left_side = MEM_cnew<ListBase>(__func__); @@ -4208,7 +4211,8 @@ bGPDstroke *BKE_gpencil_stroke_perimeter_from_view(struct RegionView3D *rv3d, const bGPDlayer *gpl, bGPDstroke *gps, const int subdivisions, - const float diff_mat[4][4]) + const float diff_mat[4][4], + const float thickness_chg) { if (gps->totpoints == 0) { return nullptr; @@ -4240,7 +4244,7 @@ bGPDstroke *BKE_gpencil_stroke_perimeter_from_view(struct RegionView3D *rv3d, BKE_gpencil_stroke_to_view_space(rv3d, gps_temp, diff_mat); int num_perimeter_points = 0; ListBase *perimeter_points = gpencil_stroke_perimeter_ex( - gpd, gpl, gps_temp, subdivisions, &num_perimeter_points); + gpd, gpl, gps_temp, subdivisions, thickness_chg, &num_perimeter_points); if (num_perimeter_points == 0) { return nullptr; diff --git a/source/blender/blenkernel/intern/lib_override.cc b/source/blender/blenkernel/intern/lib_override.cc index 03ad4b1cd5f..29f8b26c296 100644 --- a/source/blender/blenkernel/intern/lib_override.cc +++ b/source/blender/blenkernel/intern/lib_override.cc @@ -1802,6 +1802,10 @@ static bool lib_override_library_resync(Main *bmain, lib_override_hierarchy_dependencies_recursive_tag(&data); FOREACH_MAIN_ID_BEGIN (bmain, id) { + if ((id->lib != id_root->lib) || !ID_IS_OVERRIDE_LIBRARY(id)) { + continue; + } + /* IDs that get fully removed from linked data remain as local overrides (using place-holder * linked IDs as reference), but they are often not reachable from any current valid local * override hierarchy anymore. This will ensure they get properly deleted at the end of this @@ -1815,69 +1819,67 @@ static bool lib_override_library_resync(Main *bmain, id->tag |= LIB_TAG_MISSING; } - if ((id->lib == id_root->lib) && ID_IS_OVERRIDE_LIBRARY(id)) { - /* While this should not happen in typical cases (and won't be properly supported here), - * user is free to do all kind of very bad things, including having different local - * overrides of a same linked ID in a same hierarchy. */ - IDOverrideLibrary *id_override_library = BKE_lib_override_library_get( - bmain, id, nullptr, nullptr); + /* While this should not happen in typical cases (and won't be properly supported here), + * user is free to do all kind of very bad things, including having different local + * overrides of a same linked ID in a same hierarchy. */ + IDOverrideLibrary *id_override_library = BKE_lib_override_library_get( + bmain, id, nullptr, nullptr); - if (id_override_library->hierarchy_root != id_root->override_library->hierarchy_root) { - continue; - } + if (id_override_library->hierarchy_root != id_root->override_library->hierarchy_root) { + continue; + } - ID *reference_id = id_override_library->reference; - if (GS(reference_id->name) != GS(id->name)) { - switch (GS(id->name)) { - case ID_KE: - reference_id = reinterpret_cast<ID *>(BKE_key_from_id(reference_id)); - break; - case ID_GR: - BLI_assert(GS(reference_id->name) == ID_SCE); - reference_id = reinterpret_cast<ID *>( - reinterpret_cast<Scene *>(reference_id)->master_collection); - break; - case ID_NT: - reference_id = reinterpret_cast<ID *>(ntreeFromID(id)); - break; - default: - break; - } + ID *reference_id = id_override_library->reference; + if (GS(reference_id->name) != GS(id->name)) { + switch (GS(id->name)) { + case ID_KE: + reference_id = reinterpret_cast<ID *>(BKE_key_from_id(reference_id)); + break; + case ID_GR: + BLI_assert(GS(reference_id->name) == ID_SCE); + reference_id = reinterpret_cast<ID *>( + reinterpret_cast<Scene *>(reference_id)->master_collection); + break; + case ID_NT: + reference_id = reinterpret_cast<ID *>(ntreeFromID(id)); + break; + default: + break; } - if (reference_id == nullptr) { - /* Can happen e.g. when there is a local override of a shapekey, but the matching linked - * obdata (mesh etc.) does not have any shapekey anymore. */ + } + if (reference_id == nullptr) { + /* Can happen e.g. when there is a local override of a shapekey, but the matching linked + * obdata (mesh etc.) does not have any shapekey anymore. */ + continue; + } + BLI_assert(GS(reference_id->name) == GS(id->name)); + + if (!BLI_ghash_haskey(linkedref_to_old_override, reference_id)) { + BLI_ghash_insert(linkedref_to_old_override, reference_id, id); + if (!ID_IS_OVERRIDE_LIBRARY_REAL(id) || (id->tag & LIB_TAG_DOIT) == 0) { continue; } - BLI_assert(GS(reference_id->name) == GS(id->name)); + if ((id->override_library->reference->tag & LIB_TAG_DOIT) == 0) { + /* We have an override, but now it does not seem to be necessary to override that ID + * anymore. Check if there are some actual overrides from the user, otherwise assume + * that we can get rid of this local override. */ + LISTBASE_FOREACH (IDOverrideLibraryProperty *, op, &id->override_library->properties) { + if (!ELEM(op->rna_prop_type, PROP_POINTER, PROP_COLLECTION)) { + id->override_library->reference->tag |= LIB_TAG_DOIT; + break; + } - if (!BLI_ghash_haskey(linkedref_to_old_override, reference_id)) { - BLI_ghash_insert(linkedref_to_old_override, reference_id, id); - if (!ID_IS_OVERRIDE_LIBRARY_REAL(id) || (id->tag & LIB_TAG_DOIT) == 0) { - continue; - } - if ((id->override_library->reference->tag & LIB_TAG_DOIT) == 0) { - /* We have an override, but now it does not seem to be necessary to override that ID - * anymore. Check if there are some actual overrides from the user, otherwise assume - * that we can get rid of this local override. */ - LISTBASE_FOREACH (IDOverrideLibraryProperty *, op, &id->override_library->properties) { - if (!ELEM(op->rna_prop_type, PROP_POINTER, PROP_COLLECTION)) { + bool do_break = false; + LISTBASE_FOREACH (IDOverrideLibraryPropertyOperation *, opop, &op->operations) { + if ((opop->flag & IDOVERRIDE_LIBRARY_FLAG_IDPOINTER_MATCH_REFERENCE) == 0) { id->override_library->reference->tag |= LIB_TAG_DOIT; - break; - } - - bool do_break = false; - LISTBASE_FOREACH (IDOverrideLibraryPropertyOperation *, opop, &op->operations) { - if ((opop->flag & IDOVERRIDE_LIBRARY_FLAG_IDPOINTER_MATCH_REFERENCE) == 0) { - id->override_library->reference->tag |= LIB_TAG_DOIT; - do_break = true; - break; - } - } - if (do_break) { + do_break = true; break; } } + if (do_break) { + break; + } } } } @@ -1919,60 +1921,62 @@ static bool lib_override_library_resync(Main *bmain, ListBase *lb; FOREACH_MAIN_LISTBASE_BEGIN (bmain, lb) { FOREACH_MAIN_LISTBASE_ID_BEGIN (lb, id) { - if (id->tag & LIB_TAG_DOIT && id->newid != nullptr && id->lib == id_root_reference->lib) { - ID *id_override_new = id->newid; - ID *id_override_old = static_cast<ID *>(BLI_ghash_lookup(linkedref_to_old_override, id)); + if ((id->tag & LIB_TAG_DOIT) == 0 || id->newid == nullptr || + id->lib != id_root_reference->lib) { + continue; + } + ID *id_override_new = id->newid; + ID *id_override_old = static_cast<ID *>(BLI_ghash_lookup(linkedref_to_old_override, id)); - BLI_assert((id_override_new->tag & LIB_TAG_LIB_OVERRIDE_NEED_RESYNC) == 0); - - /* We need to 'move back' newly created override into its proper library (since it was - * duplicated from the reference ID with 'no main' option, it should currently be the same - * as the reference ID one). */ - BLI_assert(/*!ID_IS_LINKED(id_override_new) || */ id_override_new->lib == id->lib); - BLI_assert(id_override_old == nullptr || id_override_old->lib == id_root->lib); - id_override_new->lib = id_root->lib; - /* Remap step below will tag directly linked ones properly as needed. */ - if (ID_IS_LINKED(id_override_new)) { - id_override_new->tag |= LIB_TAG_INDIRECT; - } + BLI_assert((id_override_new->tag & LIB_TAG_LIB_OVERRIDE_NEED_RESYNC) == 0); + + /* We need to 'move back' newly created override into its proper library (since it was + * duplicated from the reference ID with 'no main' option, it should currently be the same + * as the reference ID one). */ + BLI_assert(/*!ID_IS_LINKED(id_override_new) || */ id_override_new->lib == id->lib); + BLI_assert(id_override_old == nullptr || id_override_old->lib == id_root->lib); + id_override_new->lib = id_root->lib; + /* Remap step below will tag directly linked ones properly as needed. */ + if (ID_IS_LINKED(id_override_new)) { + id_override_new->tag |= LIB_TAG_INDIRECT; + } - if (id_override_old != nullptr) { - /* Swap the names between old override ID and new one. */ - char id_name_buf[MAX_ID_NAME]; - memcpy(id_name_buf, id_override_old->name, sizeof(id_name_buf)); - memcpy(id_override_old->name, id_override_new->name, sizeof(id_override_old->name)); - memcpy(id_override_new->name, id_name_buf, sizeof(id_override_new->name)); - - BLI_insertlinkreplace(lb, id_override_old, id_override_new); - id_override_old->tag |= LIB_TAG_NO_MAIN; - id_override_new->tag &= ~LIB_TAG_NO_MAIN; - - lib_override_object_posemode_transfer(id_override_new, id_override_old); - - if (ID_IS_OVERRIDE_LIBRARY_REAL(id_override_new)) { - BLI_assert(ID_IS_OVERRIDE_LIBRARY_REAL(id_override_old)); - - id_override_new->override_library->flag = id_override_old->override_library->flag; - - /* Copy over overrides rules from old override ID to new one. */ - BLI_duplicatelist(&id_override_new->override_library->properties, - &id_override_old->override_library->properties); - IDOverrideLibraryProperty *op_new = static_cast<IDOverrideLibraryProperty *>( - id_override_new->override_library->properties.first); - IDOverrideLibraryProperty *op_old = static_cast<IDOverrideLibraryProperty *>( - id_override_old->override_library->properties.first); - for (; op_new; op_new = op_new->next, op_old = op_old->next) { - lib_override_library_property_copy(op_new, op_old); - } + if (id_override_old != nullptr) { + /* Swap the names between old override ID and new one. */ + char id_name_buf[MAX_ID_NAME]; + memcpy(id_name_buf, id_override_old->name, sizeof(id_name_buf)); + memcpy(id_override_old->name, id_override_new->name, sizeof(id_override_old->name)); + memcpy(id_override_new->name, id_name_buf, sizeof(id_override_new->name)); + + BLI_insertlinkreplace(lb, id_override_old, id_override_new); + id_override_old->tag |= LIB_TAG_NO_MAIN; + id_override_new->tag &= ~LIB_TAG_NO_MAIN; + + lib_override_object_posemode_transfer(id_override_new, id_override_old); + + if (ID_IS_OVERRIDE_LIBRARY_REAL(id_override_new)) { + BLI_assert(ID_IS_OVERRIDE_LIBRARY_REAL(id_override_old)); + + id_override_new->override_library->flag = id_override_old->override_library->flag; + + /* Copy over overrides rules from old override ID to new one. */ + BLI_duplicatelist(&id_override_new->override_library->properties, + &id_override_old->override_library->properties); + IDOverrideLibraryProperty *op_new = static_cast<IDOverrideLibraryProperty *>( + id_override_new->override_library->properties.first); + IDOverrideLibraryProperty *op_old = static_cast<IDOverrideLibraryProperty *>( + id_override_old->override_library->properties.first); + for (; op_new; op_new = op_new->next, op_old = op_old->next) { + lib_override_library_property_copy(op_new, op_old); } - - BLI_addtail(no_main_ids_list, id_override_old); - } - else { - /* Add to proper main list, ensure unique name for local ID, sort, and clear relevant - * tags. */ - BKE_libblock_management_main_add(bmain, id_override_new); } + + BLI_addtail(no_main_ids_list, id_override_old); + } + else { + /* Add to proper main list, ensure unique name for local ID, sort, and clear relevant + * tags. */ + BKE_libblock_management_main_add(bmain, id_override_new); } } FOREACH_MAIN_LISTBASE_ID_END; @@ -1991,53 +1995,56 @@ static bool lib_override_library_resync(Main *bmain, * remapped, and all new local override IDs have gotten their proper original names, otherwise * override operations based on those ID names would fail. */ FOREACH_MAIN_ID_BEGIN (bmain, id) { - if (id->tag & LIB_TAG_DOIT && id->newid != nullptr && id->lib == id_root_reference->lib) { - ID *id_override_new = id->newid; - if (!ID_IS_OVERRIDE_LIBRARY_REAL(id_override_new)) { - continue; - } - ID *id_override_old = static_cast<ID *>(BLI_ghash_lookup(linkedref_to_old_override, id)); + if ((id->tag & LIB_TAG_DOIT) == 0 || id->newid == nullptr || + id->lib != id_root_reference->lib) { + continue; + } - if (id_override_old == nullptr) { - continue; - } - if (ID_IS_OVERRIDE_LIBRARY_REAL(id_override_old)) { - /* Apply rules on new override ID using old one as 'source' data. */ - /* Note that since we already remapped ID pointers in old override IDs to new ones, we - * can also apply ID pointer override rules safely here. */ - PointerRNA rnaptr_src, rnaptr_dst; - RNA_id_pointer_create(id_override_old, &rnaptr_src); - RNA_id_pointer_create(id_override_new, &rnaptr_dst); - - /* We remove any operation tagged with `IDOVERRIDE_LIBRARY_FLAG_IDPOINTER_MATCH_REFERENCE`, - * that way the potentially new pointer will be properly kept, when old one is still valid - * too (typical case: assigning new ID to some usage, while old one remains used elsewhere - * in the override hierarchy). */ - LISTBASE_FOREACH_MUTABLE ( - IDOverrideLibraryProperty *, op, &id_override_new->override_library->properties) { - LISTBASE_FOREACH_MUTABLE (IDOverrideLibraryPropertyOperation *, opop, &op->operations) { - if (opop->flag & IDOVERRIDE_LIBRARY_FLAG_IDPOINTER_MATCH_REFERENCE) { - lib_override_library_property_operation_clear(opop); - BLI_freelinkN(&op->operations, opop); - } - } - if (BLI_listbase_is_empty(&op->operations)) { - BKE_lib_override_library_property_delete(id_override_new->override_library, op); + ID *id_override_new = id->newid; + if (!ID_IS_OVERRIDE_LIBRARY_REAL(id_override_new)) { + continue; + } + + ID *id_override_old = static_cast<ID *>(BLI_ghash_lookup(linkedref_to_old_override, id)); + if (id_override_old == nullptr) { + continue; + } + + if (ID_IS_OVERRIDE_LIBRARY_REAL(id_override_old)) { + /* Apply rules on new override ID using old one as 'source' data. */ + /* Note that since we already remapped ID pointers in old override IDs to new ones, we + * can also apply ID pointer override rules safely here. */ + PointerRNA rnaptr_src, rnaptr_dst; + RNA_id_pointer_create(id_override_old, &rnaptr_src); + RNA_id_pointer_create(id_override_new, &rnaptr_dst); + + /* We remove any operation tagged with `IDOVERRIDE_LIBRARY_FLAG_IDPOINTER_MATCH_REFERENCE`, + * that way the potentially new pointer will be properly kept, when old one is still valid + * too (typical case: assigning new ID to some usage, while old one remains used elsewhere + * in the override hierarchy). */ + LISTBASE_FOREACH_MUTABLE ( + IDOverrideLibraryProperty *, op, &id_override_new->override_library->properties) { + LISTBASE_FOREACH_MUTABLE (IDOverrideLibraryPropertyOperation *, opop, &op->operations) { + if (opop->flag & IDOVERRIDE_LIBRARY_FLAG_IDPOINTER_MATCH_REFERENCE) { + lib_override_library_property_operation_clear(opop); + BLI_freelinkN(&op->operations, opop); } } - - RNA_struct_override_apply(bmain, - &rnaptr_dst, - &rnaptr_src, - nullptr, - id_override_new->override_library, - do_hierarchy_enforce ? - RNA_OVERRIDE_APPLY_FLAG_IGNORE_ID_POINTERS : - RNA_OVERRIDE_APPLY_FLAG_NOP); + if (BLI_listbase_is_empty(&op->operations)) { + BKE_lib_override_library_property_delete(id_override_new->override_library, op); + } } - BLI_linklist_prepend(&id_override_old_list, id_override_old); + RNA_struct_override_apply(bmain, + &rnaptr_dst, + &rnaptr_src, + nullptr, + id_override_new->override_library, + do_hierarchy_enforce ? RNA_OVERRIDE_APPLY_FLAG_IGNORE_ID_POINTERS : + RNA_OVERRIDE_APPLY_FLAG_NOP); } + + BLI_linklist_prepend(&id_override_old_list, id_override_old); } FOREACH_MAIN_ID_END; @@ -2081,9 +2088,13 @@ static bool lib_override_library_resync(Main *bmain, } /* Also deal with old overrides that went missing in new linked data - only for real local * overrides for now, not those who are linked. */ - else if (id->tag & LIB_TAG_MISSING && !ID_IS_LINKED(id)) { - BLI_assert(ID_IS_OVERRIDE_LIBRARY(id)); - if (!BKE_lib_override_library_is_user_edited(id)) { + else if (id->tag & LIB_TAG_MISSING && !ID_IS_LINKED(id) && ID_IS_OVERRIDE_LIBRARY(id)) { + if (ID_IS_OVERRIDE_LIBRARY_REAL(id) && + id->override_library->reference->lib->id.tag & LIB_TAG_MISSING) { + /* Do not delete overrides which reference is missing because the library itself is missing + * (ref. T100586). */ + } + else if (!BKE_lib_override_library_is_user_edited(id)) { /* If user never edited them, we can delete them. */ id->tag |= LIB_TAG_DOIT; id->tag &= ~LIB_TAG_MISSING; @@ -2390,11 +2401,21 @@ static void lib_override_library_main_resync_on_library_indirect_level( if (!ID_IS_OVERRIDE_LIBRARY_REAL(id)) { continue; } + + if (!lib_override_resync_id_lib_level_is_valid(id, library_indirect_level, true)) { + continue; + } + if (id->tag & (LIB_TAG_DOIT | LIB_TAG_MISSING)) { /* We already processed that ID as part of another ID's hierarchy. */ continue; } + /* Do not attempt to resync from missing data. */ + if (((id->tag | id->override_library->reference->tag) & LIB_TAG_MISSING) != 0) { + continue; + } + if (id->override_library->flag & IDOVERRIDE_LIBRARY_FLAG_NO_HIERARCHY) { /* This ID is not part of an override hierarchy. */ continue; @@ -2423,6 +2444,11 @@ static void lib_override_library_main_resync_on_library_indirect_level( continue; } + /* Do not attempt to resync from missing data. */ + if (((id->tag | id->override_library->reference->tag) & LIB_TAG_MISSING) != 0) { + continue; + } + if (id->override_library->flag & IDOVERRIDE_LIBRARY_FLAG_NO_HIERARCHY) { /* This ID is not part of an override hierarchy. */ BLI_assert((id->tag & LIB_TAG_LIB_OVERRIDE_NEED_RESYNC) == 0); @@ -2550,6 +2576,15 @@ static void lib_override_library_main_resync_on_library_indirect_level( /* Check there are no left-over IDs needing resync from the current (or higher) level of indirect * library level. */ FOREACH_MAIN_ID_BEGIN (bmain, id) { + if (!ID_IS_OVERRIDE_LIBRARY(id)) { + continue; + } + /* Do not attempt to resync to/from missing data. */ + if (((id->tag | (ID_IS_OVERRIDE_LIBRARY_REAL(id) ? id->override_library->reference->tag : 0)) & + LIB_TAG_MISSING) != 0) { + continue; + } + const bool is_valid_tagged_need_resync = ((id->tag & LIB_TAG_LIB_OVERRIDE_NEED_RESYNC) == 0 || lib_override_resync_id_lib_level_is_valid( id, library_indirect_level - 1, false)); diff --git a/source/blender/blenkernel/intern/mesh.cc b/source/blender/blenkernel/intern/mesh.cc index 6acf15bbb2a..6f91ce2a4e9 100644 --- a/source/blender/blenkernel/intern/mesh.cc +++ b/source/blender/blenkernel/intern/mesh.cc @@ -101,6 +101,10 @@ static void mesh_copy_data(Main *bmain, ID *id_dst, const ID *id_src, const int const Mesh *mesh_src = (const Mesh *)id_src; BKE_mesh_runtime_reset_on_copy(mesh_dst, flag); + /* Copy face dot tags, since meshes may be duplicated after a subsurf modifier + * or node, but we still need to be able to draw face center vertices. */ + mesh_dst->runtime.subsurf_face_dot_tags = static_cast<uint32_t *>( + MEM_dupallocN(mesh_src->runtime.subsurf_face_dot_tags)); if ((mesh_src->id.tag & LIB_TAG_NO_MAIN) == 0) { /* This is a direct copy of a main mesh, so for now it has the same topology. */ mesh_dst->runtime.deformed_only = true; diff --git a/source/blender/blenkernel/intern/mesh_remesh_voxel.cc b/source/blender/blenkernel/intern/mesh_remesh_voxel.cc index 85aed01ce52..423f76407a0 100644 --- a/source/blender/blenkernel/intern/mesh_remesh_voxel.cc +++ b/source/blender/blenkernel/intern/mesh_remesh_voxel.cc @@ -275,11 +275,15 @@ Mesh *BKE_mesh_remesh_voxel(const Mesh *mesh, #endif } -void BKE_mesh_remesh_reproject_paint_mask(Mesh *target, Mesh *source) +void BKE_mesh_remesh_reproject_paint_mask(Mesh *target, const Mesh *source) { BVHTreeFromMesh bvhtree = {nullptr}; BKE_bvhtree_from_mesh_get(&bvhtree, source, BVHTREE_FROM_VERTS, 2); - MVert *target_verts = (MVert *)CustomData_get_layer(&target->vdata, CD_MVERT); + const MVert *target_verts = (const MVert *)CustomData_get_layer(&target->vdata, CD_MVERT); + const float *source_mask = (const float *)CustomData_get_layer(&source->vdata, CD_PAINT_MASK); + if (source_mask == nullptr) { + return; + } float *target_mask; if (CustomData_has_layer(&target->vdata, CD_PAINT_MASK)) { @@ -290,15 +294,6 @@ void BKE_mesh_remesh_reproject_paint_mask(Mesh *target, Mesh *source) &target->vdata, CD_PAINT_MASK, CD_CALLOC, nullptr, target->totvert); } - const float *source_mask; - if (CustomData_has_layer(&source->vdata, CD_PAINT_MASK)) { - source_mask = (float *)CustomData_get_layer(&source->vdata, CD_PAINT_MASK); - } - else { - source_mask = (float *)CustomData_add_layer( - &source->vdata, CD_PAINT_MASK, CD_CALLOC, nullptr, source->totvert); - } - for (int i = 0; i < target->totvert; i++) { float from_co[3]; BVHTreeNearest nearest; @@ -313,13 +308,16 @@ void BKE_mesh_remesh_reproject_paint_mask(Mesh *target, Mesh *source) free_bvhtree_from_mesh(&bvhtree); } -void BKE_remesh_reproject_sculpt_face_sets(Mesh *target, Mesh *source) +void BKE_remesh_reproject_sculpt_face_sets(Mesh *target, const Mesh *source) { - BVHTreeFromMesh bvhtree = {nullptr}; - const MPoly *target_polys = (const MPoly *)CustomData_get_layer(&target->pdata, CD_MPOLY); const MVert *target_verts = (const MVert *)CustomData_get_layer(&target->vdata, CD_MVERT); const MLoop *target_loops = (const MLoop *)CustomData_get_layer(&target->ldata, CD_MLOOP); + const int *source_face_sets = (const int *)CustomData_get_layer(&source->pdata, + CD_SCULPT_FACE_SETS); + if (source_face_sets == nullptr) { + return; + } int *target_face_sets; if (CustomData_has_layer(&target->pdata, CD_SCULPT_FACE_SETS)) { @@ -330,16 +328,8 @@ void BKE_remesh_reproject_sculpt_face_sets(Mesh *target, Mesh *source) &target->pdata, CD_SCULPT_FACE_SETS, CD_CALLOC, nullptr, target->totpoly); } - const int *source_face_sets; - if (CustomData_has_layer(&source->pdata, CD_SCULPT_FACE_SETS)) { - source_face_sets = (const int *)CustomData_get_layer(&source->pdata, CD_SCULPT_FACE_SETS); - } - else { - source_face_sets = (const int *)CustomData_add_layer( - &source->pdata, CD_SCULPT_FACE_SETS, CD_CALLOC, nullptr, source->totpoly); - } - const MLoopTri *looptri = BKE_mesh_runtime_looptri_ensure(source); + BVHTreeFromMesh bvhtree = {nullptr}; BKE_bvhtree_from_mesh_get(&bvhtree, source, BVHTREE_FROM_LOOPTRI, 2); for (int i = 0; i < target->totpoly; i++) { diff --git a/source/blender/blenkernel/intern/node.cc b/source/blender/blenkernel/intern/node.cc index 9b28568aaf7..4ed2885dd90 100644 --- a/source/blender/blenkernel/intern/node.cc +++ b/source/blender/blenkernel/intern/node.cc @@ -3383,8 +3383,10 @@ struct bNodeSocket *ntreeAddSocketInterfaceFromSocket(bNodeTree *ntree, bNode *from_node, bNodeSocket *from_sock) { - bNodeSocket *iosock = ntreeAddSocketInterface( - ntree, static_cast<eNodeSocketInOut>(from_sock->in_out), from_sock->idname, DATA_(from_sock->name)); + bNodeSocket *iosock = ntreeAddSocketInterface(ntree, + static_cast<eNodeSocketInOut>(from_sock->in_out), + from_sock->idname, + DATA_(from_sock->name)); if (iosock) { if (iosock->typeinfo->interface_from_socket) { iosock->typeinfo->interface_from_socket(ntree, iosock, from_node, from_sock); |