diff options
author | Julian Eisel <julian@blender.org> | 2021-09-15 23:34:20 +0300 |
---|---|---|
committer | Julian Eisel <julian@blender.org> | 2021-09-15 23:34:20 +0300 |
commit | da9be470b546928e3e4320003b333d0aad1c9073 (patch) | |
tree | 3879b762dc226f0b6a55d8e5bdafcfba7dc0c3b9 | |
parent | ad7588600c35423b2908756afd694331f08aeb20 (diff) | |
parent | 28bd74c18650a8362bc791df602097967ff5efdf (diff) |
Merge branch 'master' into temp-cocoa-scroll-acceleration-fixtemp-cocoa-scroll-acceleration-fix
81 files changed, 1056 insertions, 490 deletions
diff --git a/release/scripts/startup/nodeitems_builtins.py b/release/scripts/startup/nodeitems_builtins.py index c0af91b7ad6..569c5291576 100644 --- a/release/scripts/startup/nodeitems_builtins.py +++ b/release/scripts/startup/nodeitems_builtins.py @@ -564,6 +564,8 @@ geometry_node_categories = [ NodeItem("GeometryNodeLegacyMaterialAssign", poll=geometry_nodes_fields_legacy_poll), NodeItem("GeometryNodeLegacySelectByMaterial", poll=geometry_nodes_fields_legacy_poll), + NodeItem("GeometryNodeMaterialAssign", poll=geometry_nodes_fields_poll), + NodeItem("GeometryNodeMaterialSelection", poll=geometry_nodes_fields_poll), NodeItem("GeometryNodeMaterialReplace"), ]), GeometryNodeCategory("GEO_MESH", "Mesh", items=[ diff --git a/source/blender/blenkernel/BKE_node.h b/source/blender/blenkernel/BKE_node.h index d4bc0245a61..a57281e4478 100644 --- a/source/blender/blenkernel/BKE_node.h +++ b/source/blender/blenkernel/BKE_node.h @@ -1491,6 +1491,8 @@ int ntreeTexExecTree(struct bNodeTree *ntree, #define GEO_NODE_INPUT_INDEX 1078 #define GEO_NODE_INPUT_NORMAL 1079 #define GEO_NODE_ATTRIBUTE_CAPTURE 1080 +#define GEO_NODE_MATERIAL_SELECTION 1081 +#define GEO_NODE_MATERIAL_ASSIGN 1082 /** \} */ diff --git a/source/blender/blenkernel/BKE_spline.hh b/source/blender/blenkernel/BKE_spline.hh index fc145f1ddf1..0fbf39a52fa 100644 --- a/source/blender/blenkernel/BKE_spline.hh +++ b/source/blender/blenkernel/BKE_spline.hh @@ -131,6 +131,11 @@ class Spline { virtual void transform(const blender::float4x4 &matrix); /** + * Change the direction of the spline (switch the start and end) without changing its shape. + */ + void reverse(); + + /** * Mark all caches for re-computation. This must be called after any operation that would * change the generated positions, tangents, normals, mapping, etc. of the evaluated points. */ @@ -210,6 +215,7 @@ class Spline { virtual void correct_end_tangents() const = 0; virtual void copy_settings(Spline &dst) const = 0; virtual void copy_data(Spline &dst) const = 0; + virtual void reverse_impl() = 0; }; /** @@ -353,6 +359,9 @@ class BezierSpline final : public Spline { void correct_end_tangents() const final; void copy_settings(Spline &dst) const final; void copy_data(Spline &dst) const final; + + protected: + void reverse_impl() override; }; /** @@ -469,6 +478,7 @@ class NURBSpline final : public Spline { void correct_end_tangents() const final; void copy_settings(Spline &dst) const final; void copy_data(Spline &dst) const final; + void reverse_impl() override; void calculate_knots() const; blender::Span<BasisCache> calculate_basis_cache() const; @@ -519,6 +529,7 @@ class PolySpline final : public Spline { void correct_end_tangents() const final; void copy_settings(Spline &dst) const final; void copy_data(Spline &dst) const final; + void reverse_impl() override; }; /** diff --git a/source/blender/blenkernel/intern/dynamicpaint.c b/source/blender/blenkernel/intern/dynamicpaint.c index 0dc4f64cec1..d75b3259148 100644 --- a/source/blender/blenkernel/intern/dynamicpaint.c +++ b/source/blender/blenkernel/intern/dynamicpaint.c @@ -2064,7 +2064,7 @@ static Mesh *dynamicPaint_Modifier_apply(DynamicPaintModifierData *pmd, Object * } if (update_normals) { - result->runtime.cd_dirty_vert |= CD_MASK_NORMAL; + BKE_mesh_normals_tag_dirty(result); } } /* make a copy of mesh to use as brush data */ diff --git a/source/blender/blenkernel/intern/fluid.c b/source/blender/blenkernel/intern/fluid.c index f13ed1f2bf7..1324b37f39c 100644 --- a/source/blender/blenkernel/intern/fluid.c +++ b/source/blender/blenkernel/intern/fluid.c @@ -3573,7 +3573,7 @@ static Mesh *create_smoke_geometry(FluidDomainSettings *fds, Mesh *orgmesh, Obje } BKE_mesh_calc_edges(result, false, false); - result->runtime.cd_dirty_vert |= CD_MASK_NORMAL; + BKE_mesh_normals_tag_dirty(result); return result; } diff --git a/source/blender/blenkernel/intern/geometry_component_curve.cc b/source/blender/blenkernel/intern/geometry_component_curve.cc index afafd766760..7d0537178ef 100644 --- a/source/blender/blenkernel/intern/geometry_component_curve.cc +++ b/source/blender/blenkernel/intern/geometry_component_curve.cc @@ -222,6 +222,37 @@ static void adapt_curve_domain_point_to_spline_impl(const CurveEval &curve, mixer.finalize(); } +/** + * A spline is selected if all of its control points were selected. + * + * \note Theoretically this interpolation does not need to compute all values at once. + * However, doing that makes the implementation simpler, and this can be optimized in the future if + * only some values are required. + */ +template<> +void adapt_curve_domain_point_to_spline_impl(const CurveEval &curve, + const VArray<bool> &old_values, + MutableSpan<bool> r_values) +{ + const int splines_len = curve.splines().size(); + Array<int> offsets = curve.control_point_offsets(); + BLI_assert(r_values.size() == splines_len); + + r_values.fill(true); + + for (const int i_spline : IndexRange(splines_len)) { + const int spline_offset = offsets[i_spline]; + const int spline_point_len = offsets[i_spline + 1] - spline_offset; + + for (const int i_point : IndexRange(spline_point_len)) { + if (!old_values[spline_offset + i_point]) { + r_values[i_spline] = false; + break; + } + } + } +} + static GVArrayPtr adapt_curve_domain_point_to_spline(const CurveEval &curve, GVArrayPtr varray) { GVArrayPtr new_varray; diff --git a/source/blender/blenkernel/intern/geometry_component_mesh.cc b/source/blender/blenkernel/intern/geometry_component_mesh.cc index 9a4b8f4eb92..0c98aa5551b 100644 --- a/source/blender/blenkernel/intern/geometry_component_mesh.cc +++ b/source/blender/blenkernel/intern/geometry_component_mesh.cc @@ -175,6 +175,34 @@ static void adapt_mesh_domain_corner_to_point_impl(const Mesh &mesh, mixer.finalize(); } +/* A vertex is selected if all connected face corners were selected and it is not loose. */ +template<> +void adapt_mesh_domain_corner_to_point_impl(const Mesh &mesh, + const VArray<bool> &old_values, + MutableSpan<bool> r_values) +{ + BLI_assert(r_values.size() == mesh.totvert); + Array<bool> loose_verts(mesh.totvert, true); + + r_values.fill(true); + for (const int loop_index : IndexRange(mesh.totloop)) { + const MLoop &loop = mesh.mloop[loop_index]; + const int point_index = loop.v; + + loose_verts[point_index] = false; + if (!old_values[loop_index]) { + r_values[point_index] = false; + } + } + + /* Deselect loose vertices without corners that are still selected from the 'true' default. */ + for (const int vert_index : IndexRange(mesh.totvert)) { + if (loose_verts[vert_index]) { + r_values[vert_index] = false; + } + } +} + static GVArrayPtr adapt_mesh_domain_corner_to_point(const Mesh &mesh, GVArrayPtr varray) { GVArrayPtr new_varray; @@ -191,6 +219,13 @@ static GVArrayPtr adapt_mesh_domain_corner_to_point(const Mesh &mesh, GVArrayPtr return new_varray; } +/** + * Each corner's value is simply a copy of the value at its vertex. + * + * \note Theoretically this interpolation does not need to compute all values at once. + * However, doing that makes the implementation simpler, and this can be optimized in the future if + * only some values are required. + */ template<typename T> static void adapt_mesh_domain_point_to_corner_impl(const Mesh &mesh, const VArray<T> &old_values, @@ -209,10 +244,6 @@ static GVArrayPtr adapt_mesh_domain_point_to_corner(const Mesh &mesh, GVArrayPtr GVArrayPtr new_varray; attribute_math::convert_to_static_type(varray->type(), [&](auto dummy) { using T = decltype(dummy); - /* It is not strictly necessary to compute the value for all corners here. Instead one could - * lazily lookup the mesh topology when a specific index accessed. This can be more efficient - * when an algorithm only accesses very few of the corner values. However, for the algorithms - * we currently have, precomputing the array is fine. Also, it is easier to implement. */ Array<T> values(mesh.totloop); adapt_mesh_domain_point_to_corner_impl<T>(mesh, varray->typed<T>(), values); new_varray = std::make_unique<fn::GVArray_For_ArrayContainer<Array<T>>>(std::move(values)); @@ -244,6 +275,26 @@ static void adapt_mesh_domain_corner_to_face_impl(const Mesh &mesh, mixer.finalize(); } +/* A face is selected if all of its corners were selected. */ +template<> +void adapt_mesh_domain_corner_to_face_impl(const Mesh &mesh, + const VArray<bool> &old_values, + MutableSpan<bool> r_values) +{ + BLI_assert(r_values.size() == mesh.totpoly); + + r_values.fill(true); + for (const int poly_index : IndexRange(mesh.totpoly)) { + const MPoly &poly = mesh.mpoly[poly_index]; + for (const int loop_index : IndexRange(poly.loopstart, poly.totloop)) { + if (!old_values[loop_index]) { + r_values[poly_index] = false; + break; + } + } + } +} + static GVArrayPtr adapt_mesh_domain_corner_to_face(const Mesh &mesh, GVArrayPtr varray) { GVArrayPtr new_varray; @@ -282,6 +333,41 @@ static void adapt_mesh_domain_corner_to_edge_impl(const Mesh &mesh, mixer.finalize(); } +/* An edge is selected if all corners on adjacent faces were selected. */ +template<> +void adapt_mesh_domain_corner_to_edge_impl(const Mesh &mesh, + const VArray<bool> &old_values, + MutableSpan<bool> r_values) +{ + BLI_assert(r_values.size() == mesh.totedge); + + /* It may be possible to rely on the #ME_LOOSEEDGE flag, but that seems error-prone. */ + Array<bool> loose_edges(mesh.totedge, true); + + r_values.fill(true); + for (const int poly_index : IndexRange(mesh.totpoly)) { + const MPoly &poly = mesh.mpoly[poly_index]; + + for (const int loop_index : IndexRange(poly.loopstart, poly.totloop)) { + const int loop_index_next = (loop_index == poly.totloop) ? poly.loopstart : (loop_index + 1); + const MLoop &loop = mesh.mloop[loop_index]; + const int edge_index = loop.e; + loose_edges[edge_index] = false; + + if (!old_values[loop_index] || !old_values[loop_index_next]) { + r_values[edge_index] = false; + } + } + } + + /* Deselect loose edges without corners that are still selected from the 'true' default. */ + for (const int edge_index : IndexRange(mesh.totedge)) { + if (loose_edges[edge_index]) { + r_values[edge_index] = false; + } + } +} + static GVArrayPtr adapt_mesh_domain_corner_to_edge(const Mesh &mesh, GVArrayPtr varray) { GVArrayPtr new_varray; @@ -317,6 +403,27 @@ void adapt_mesh_domain_face_to_point_impl(const Mesh &mesh, mixer.finalize(); } +/* A vertex is selected if any of the connected faces were selected. */ +template<> +void adapt_mesh_domain_face_to_point_impl(const Mesh &mesh, + const VArray<bool> &old_values, + MutableSpan<bool> r_values) +{ + BLI_assert(r_values.size() == mesh.totvert); + + r_values.fill(false); + for (const int poly_index : IndexRange(mesh.totpoly)) { + const MPoly &poly = mesh.mpoly[poly_index]; + if (old_values[poly_index]) { + for (const int loop_index : IndexRange(poly.loopstart, poly.totloop)) { + const MLoop &loop = mesh.mloop[loop_index]; + const int vert_index = loop.v; + r_values[vert_index] = true; + } + } + } +} + static GVArrayPtr adapt_mesh_domain_face_to_point(const Mesh &mesh, GVArrayPtr varray) { GVArrayPtr new_varray; @@ -331,6 +438,7 @@ static GVArrayPtr adapt_mesh_domain_face_to_point(const Mesh &mesh, GVArrayPtr v return new_varray; } +/* Each corner's value is simply a copy of the value at its face. */ template<typename T> void adapt_mesh_domain_face_to_corner_impl(const Mesh &mesh, const VArray<T> &old_values, @@ -378,6 +486,27 @@ void adapt_mesh_domain_face_to_edge_impl(const Mesh &mesh, mixer.finalize(); } +/* An edge is selected if any connected face was selected. */ +template<> +void adapt_mesh_domain_face_to_edge_impl(const Mesh &mesh, + const VArray<bool> &old_values, + MutableSpan<bool> r_values) +{ + BLI_assert(r_values.size() == mesh.totedge); + + r_values.fill(false); + for (const int poly_index : IndexRange(mesh.totpoly)) { + const MPoly &poly = mesh.mpoly[poly_index]; + if (old_values[poly_index]) { + for (const int loop_index : IndexRange(poly.loopstart, poly.totloop)) { + const MLoop &loop = mesh.mloop[loop_index]; + const int edge_index = loop.e; + r_values[edge_index] = true; + } + } + } +} + static GVArrayPtr adapt_mesh_domain_face_to_edge(const Mesh &mesh, GVArrayPtr varray) { GVArrayPtr new_varray; @@ -416,6 +545,28 @@ static void adapt_mesh_domain_point_to_face_impl(const Mesh &mesh, mixer.finalize(); } +/* A face is selected if all of its vertices were selected too. */ +template<> +void adapt_mesh_domain_point_to_face_impl(const Mesh &mesh, + const VArray<bool> &old_values, + MutableSpan<bool> r_values) +{ + BLI_assert(r_values.size() == mesh.totpoly); + + r_values.fill(true); + for (const int poly_index : IndexRange(mesh.totpoly)) { + const MPoly &poly = mesh.mpoly[poly_index]; + for (const int loop_index : IndexRange(poly.loopstart, poly.totloop)) { + MLoop &loop = mesh.mloop[loop_index]; + const int vert_index = loop.v; + if (!old_values[vert_index]) { + r_values[poly_index] = false; + break; + } + } + } +} + static GVArrayPtr adapt_mesh_domain_point_to_face(const Mesh &mesh, GVArrayPtr varray) { GVArrayPtr new_varray; @@ -452,6 +603,20 @@ static void adapt_mesh_domain_point_to_edge_impl(const Mesh &mesh, mixer.finalize(); } +/* An edge is selected if both of its vertices were selected. */ +template<> +void adapt_mesh_domain_point_to_edge_impl(const Mesh &mesh, + const VArray<bool> &old_values, + MutableSpan<bool> r_values) +{ + BLI_assert(r_values.size() == mesh.totedge); + + for (const int edge_index : IndexRange(mesh.totedge)) { + const MEdge &edge = mesh.medge[edge_index]; + r_values[edge_index] = old_values[edge.v1] && old_values[edge.v2]; + } +} + static GVArrayPtr adapt_mesh_domain_point_to_edge(const Mesh &mesh, GVArrayPtr varray) { GVArrayPtr new_varray; @@ -490,6 +655,29 @@ void adapt_mesh_domain_edge_to_corner_impl(const Mesh &mesh, mixer.finalize(); } +/* A corner is selected if its two adjacent edges were selected. */ +template<> +void adapt_mesh_domain_edge_to_corner_impl(const Mesh &mesh, + const VArray<bool> &old_values, + MutableSpan<bool> r_values) +{ + BLI_assert(r_values.size() == mesh.totloop); + + r_values.fill(false); + + for (const int poly_index : IndexRange(mesh.totpoly)) { + const MPoly &poly = mesh.mpoly[poly_index]; + for (const int loop_index : IndexRange(poly.loopstart, poly.totloop)) { + const int loop_index_prev = loop_index - 1 + (loop_index == poly.loopstart) * poly.totloop; + const MLoop &loop = mesh.mloop[loop_index]; + const MLoop &loop_prev = mesh.mloop[loop_index_prev]; + if (old_values[loop.e] && old_values[loop_prev.e]) { + r_values[loop_index] = true; + } + } + } +} + static GVArrayPtr adapt_mesh_domain_edge_to_corner(const Mesh &mesh, GVArrayPtr varray) { GVArrayPtr new_varray; @@ -522,6 +710,24 @@ static void adapt_mesh_domain_edge_to_point_impl(const Mesh &mesh, mixer.finalize(); } +/* A vertex is selected if any connected edge was selected. */ +template<> +void adapt_mesh_domain_edge_to_point_impl(const Mesh &mesh, + const VArray<bool> &old_values, + MutableSpan<bool> r_values) +{ + BLI_assert(r_values.size() == mesh.totvert); + + r_values.fill(false); + for (const int edge_index : IndexRange(mesh.totedge)) { + const MEdge &edge = mesh.medge[edge_index]; + if (old_values[edge_index]) { + r_values[edge.v1] = true; + r_values[edge.v2] = true; + } + } +} + static GVArrayPtr adapt_mesh_domain_edge_to_point(const Mesh &mesh, GVArrayPtr varray) { GVArrayPtr new_varray; @@ -560,6 +766,28 @@ static void adapt_mesh_domain_edge_to_face_impl(const Mesh &mesh, mixer.finalize(); } +/* A face is selected if all of its edges are selected. */ +template<> +void adapt_mesh_domain_edge_to_face_impl(const Mesh &mesh, + const VArray<bool> &old_values, + MutableSpan<bool> r_values) +{ + BLI_assert(r_values.size() == mesh.totpoly); + + r_values.fill(true); + for (const int poly_index : IndexRange(mesh.totpoly)) { + const MPoly &poly = mesh.mpoly[poly_index]; + for (const int loop_index : IndexRange(poly.loopstart, poly.totloop)) { + const MLoop &loop = mesh.mloop[loop_index]; + const int edge_index = loop.e; + if (!old_values[edge_index]) { + r_values[poly_index] = false; + break; + } + } + } +} + static GVArrayPtr adapt_mesh_domain_edge_to_face(const Mesh &mesh, GVArrayPtr varray) { GVArrayPtr new_varray; @@ -698,7 +926,7 @@ static void tag_normals_dirty_when_writing_position(GeometryComponent &component { Mesh *mesh = get_mesh_from_component_for_write(component); if (mesh != nullptr) { - mesh->runtime.cd_dirty_vert |= CD_MASK_NORMAL; + BKE_mesh_normals_tag_dirty(mesh); } } diff --git a/source/blender/blenkernel/intern/mesh.c b/source/blender/blenkernel/intern/mesh.c index 2efe0d77d87..b21f8a71174 100644 --- a/source/blender/blenkernel/intern/mesh.c +++ b/source/blender/blenkernel/intern/mesh.c @@ -1859,7 +1859,7 @@ void BKE_mesh_vert_coords_apply(Mesh *mesh, const float (*vert_coords)[3]) for (int i = 0; i < mesh->totvert; i++, mv++) { copy_v3_v3(mv->co, vert_coords[i]); } - mesh->runtime.cd_dirty_vert |= CD_MASK_NORMAL; + BKE_mesh_normals_tag_dirty(mesh); } void BKE_mesh_vert_coords_apply_with_mat4(Mesh *mesh, @@ -1872,7 +1872,7 @@ void BKE_mesh_vert_coords_apply_with_mat4(Mesh *mesh, for (int i = 0; i < mesh->totvert; i++, mv++) { mul_v3_m4v3(mv->co, mat, vert_coords[i]); } - mesh->runtime.cd_dirty_vert |= CD_MASK_NORMAL; + BKE_mesh_normals_tag_dirty(mesh); } void BKE_mesh_vert_normals_apply(Mesh *mesh, const short (*vert_normals)[3]) diff --git a/source/blender/blenkernel/intern/mesh_convert.c b/source/blender/blenkernel/intern/mesh_convert.c index 9fd75be0d35..50c80f8d0a4 100644 --- a/source/blender/blenkernel/intern/mesh_convert.c +++ b/source/blender/blenkernel/intern/mesh_convert.c @@ -525,7 +525,7 @@ Mesh *BKE_mesh_new_nomain_from_curve_displist(const Object *ob, const ListBase * } mesh = BKE_mesh_new_nomain(totvert, totedge, 0, totloop, totpoly); - mesh->runtime.cd_dirty_vert |= CD_MASK_NORMAL; + BKE_mesh_normals_tag_dirty(mesh); if (totvert != 0) { memcpy(mesh->mvert, allvert, totvert * sizeof(MVert)); diff --git a/source/blender/blenkernel/intern/node.cc b/source/blender/blenkernel/intern/node.cc index 61b90b44b03..0d691854c1d 100644 --- a/source/blender/blenkernel/intern/node.cc +++ b/source/blender/blenkernel/intern/node.cc @@ -5153,6 +5153,9 @@ static void registerGeometryNodes() { register_node_type_geo_group(); + register_node_type_geo_legacy_material_assign(); + register_node_type_geo_legacy_select_by_material(); + register_node_type_geo_align_rotation_to_vector(); register_node_type_geo_attribute_clamp(); register_node_type_geo_attribute_color_ramp(); @@ -5225,7 +5228,7 @@ static void registerGeometryNodes() register_node_type_geo_raycast(); register_node_type_geo_sample_texture(); register_node_type_geo_select_by_handle_type(); - register_node_type_geo_select_by_material(); + register_node_type_geo_material_selection(); register_node_type_geo_separate_components(); register_node_type_geo_set_position(); register_node_type_geo_subdivision_surface(); diff --git a/source/blender/blenkernel/intern/screen.c b/source/blender/blenkernel/intern/screen.c index 065240bddbc..60da008a282 100644 --- a/source/blender/blenkernel/intern/screen.c +++ b/source/blender/blenkernel/intern/screen.c @@ -312,7 +312,7 @@ IDTypeInfo IDType_ID_SCR = { .name = "Screen", .name_plural = "screens", .translation_context = BLT_I18NCONTEXT_ID_SCREEN, - .flags = IDTYPE_FLAGS_NO_COPY | IDTYPE_FLAGS_NO_MAKELOCAL | IDTYPE_FLAGS_NO_ANIMDATA, + .flags = IDTYPE_FLAGS_NO_COPY | IDTYPE_FLAGS_NO_ANIMDATA, .init_data = NULL, .copy_data = NULL, diff --git a/source/blender/blenkernel/intern/spline_base.cc b/source/blender/blenkernel/intern/spline_base.cc index 732fabc6582..a8871777420 100644 --- a/source/blender/blenkernel/intern/spline_base.cc +++ b/source/blender/blenkernel/intern/spline_base.cc @@ -19,6 +19,8 @@ #include "BLI_task.hh" #include "BLI_timeit.hh" +#include "BKE_attribute_access.hh" +#include "BKE_attribute_math.hh" #include "BKE_spline.hh" #include "FN_generic_virtual_array.hh" @@ -28,6 +30,8 @@ using blender::float3; using blender::IndexRange; using blender::MutableSpan; using blender::Span; +using blender::attribute_math::convert_to_static_type; +using blender::bke::AttributeIDRef; using blender::fn::GMutableSpan; using blender::fn::GSpan; using blender::fn::GVArray; @@ -110,6 +114,31 @@ void Spline::transform(const blender::float4x4 &matrix) this->mark_cache_invalid(); } +void Spline::reverse() +{ + this->positions().reverse(); + this->radii().reverse(); + this->tilts().reverse(); + + this->attributes.foreach_attribute( + [&](const AttributeIDRef &id, const AttributeMetaData &meta_data) { + std::optional<blender::fn::GMutableSpan> attribute = this->attributes.get_for_write(id); + if (!attribute) { + BLI_assert_unreachable(); + return false; + } + convert_to_static_type(meta_data.data_type, [&](auto dummy) { + using T = decltype(dummy); + attribute->typed<T>().reverse(); + }); + return true; + }, + ATTR_DOMAIN_POINT); + + this->reverse_impl(); + this->mark_cache_invalid(); +} + int Spline::evaluated_edges_size() const { const int eval_size = this->evaluated_points_size(); diff --git a/source/blender/blenkernel/intern/spline_bezier.cc b/source/blender/blenkernel/intern/spline_bezier.cc index b6764f65631..79d2137ee84 100644 --- a/source/blender/blenkernel/intern/spline_bezier.cc +++ b/source/blender/blenkernel/intern/spline_bezier.cc @@ -166,6 +166,17 @@ MutableSpan<float3> BezierSpline::handle_positions_right() return handle_positions_right_; } +void BezierSpline::reverse_impl() +{ + this->handle_positions_left().reverse(); + this->handle_positions_right().reverse(); + std::swap(this->handle_positions_left_, this->handle_positions_right_); + + this->handle_types_left().reverse(); + this->handle_types_right().reverse(); + std::swap(this->handle_types_left_, this->handle_types_right_); +} + static float3 previous_position(Span<float3> positions, const bool cyclic, const int i) { if (i == 0) { diff --git a/source/blender/blenkernel/intern/spline_nurbs.cc b/source/blender/blenkernel/intern/spline_nurbs.cc index ac6f1bd082c..6d30d8ba916 100644 --- a/source/blender/blenkernel/intern/spline_nurbs.cc +++ b/source/blender/blenkernel/intern/spline_nurbs.cc @@ -142,6 +142,11 @@ Span<float> NURBSpline::weights() const return weights_; } +void NURBSpline::reverse_impl() +{ + this->weights().reverse(); +} + void NURBSpline::mark_cache_invalid() { basis_cache_dirty_ = true; diff --git a/source/blender/blenkernel/intern/spline_poly.cc b/source/blender/blenkernel/intern/spline_poly.cc index dfd24b2566e..338b5d0ac9e 100644 --- a/source/blender/blenkernel/intern/spline_poly.cc +++ b/source/blender/blenkernel/intern/spline_poly.cc @@ -91,6 +91,10 @@ Span<float> PolySpline::tilts() const return tilts_; } +void PolySpline::reverse_impl() +{ +} + void PolySpline::mark_cache_invalid() { tangent_cache_dirty_ = true; diff --git a/source/blender/blenkernel/intern/subdiv_mesh.c b/source/blender/blenkernel/intern/subdiv_mesh.c index da6ee8d8779..e9cd0b70019 100644 --- a/source/blender/blenkernel/intern/subdiv_mesh.c +++ b/source/blender/blenkernel/intern/subdiv_mesh.c @@ -1232,7 +1232,7 @@ Mesh *BKE_subdiv_to_mesh(Subdiv *subdiv, // BKE_mesh_validate(result, true, true); BKE_subdiv_stats_end(&subdiv->stats, SUBDIV_STATS_SUBDIV_TO_MESH); if (!subdiv_context.can_evaluate_normals) { - result->runtime.cd_dirty_vert |= CD_MASK_NORMAL; + BKE_mesh_normals_tag_dirty(result); } /* Free used memory. */ subdiv_mesh_context_free(&subdiv_context); diff --git a/source/blender/blenkernel/intern/workspace.c b/source/blender/blenkernel/intern/workspace.c index 329633c6759..d7368e62437 100644 --- a/source/blender/blenkernel/intern/workspace.c +++ b/source/blender/blenkernel/intern/workspace.c @@ -186,7 +186,7 @@ IDTypeInfo IDType_ID_WS = { .name = "WorkSpace", .name_plural = "workspaces", .translation_context = BLT_I18NCONTEXT_ID_WORKSPACE, - .flags = IDTYPE_FLAGS_NO_COPY | IDTYPE_FLAGS_NO_MAKELOCAL | IDTYPE_FLAGS_NO_ANIMDATA, + .flags = IDTYPE_FLAGS_NO_COPY | IDTYPE_FLAGS_NO_ANIMDATA, .init_data = workspace_init_data, .copy_data = NULL, diff --git a/source/blender/blenlib/BLI_span.hh b/source/blender/blenlib/BLI_span.hh index e04295b0e51..5adb47ba0b0 100644 --- a/source/blender/blenlib/BLI_span.hh +++ b/source/blender/blenlib/BLI_span.hh @@ -644,6 +644,16 @@ template<typename T> class MutableSpan { } /** + * Reverse the data in the MutableSpan. + */ + constexpr void reverse() + { + for (const int i : IndexRange(size_ / 2)) { + std::swap(data_[size_ - 1 - i], data_[i]); + } + } + + /** * Returns an (immutable) Span that references the same array. This is usually not needed, * due to implicit conversions. However, sometimes automatic type deduction needs some help. */ diff --git a/source/blender/blenlib/tests/BLI_span_test.cc b/source/blender/blenlib/tests/BLI_span_test.cc index 4d23a53c08a..fb88fb63e53 100644 --- a/source/blender/blenlib/tests/BLI_span_test.cc +++ b/source/blender/blenlib/tests/BLI_span_test.cc @@ -362,6 +362,29 @@ TEST(span, ReverseIterator) EXPECT_EQ_ARRAY(reversed_vec.data(), Span({7, 6, 5, 4}).data(), 4); } +TEST(span, ReverseMutableSpan) +{ + std::array<int, 0> src0 = {}; + MutableSpan<int> span0 = src0; + span0.reverse(); + EXPECT_EQ_ARRAY(span0.data(), Span<int>({}).data(), 0); + + std::array<int, 1> src1 = {4}; + MutableSpan<int> span1 = src1; + span1.reverse(); + EXPECT_EQ_ARRAY(span1.data(), Span<int>({4}).data(), 1); + + std::array<int, 2> src2 = {4, 5}; + MutableSpan<int> span2 = src2; + span2.reverse(); + EXPECT_EQ_ARRAY(span2.data(), Span<int>({5, 4}).data(), 2); + + std::array<int, 5> src5 = {4, 5, 6, 7, 8}; + MutableSpan<int> span5 = src5; + span5.reverse(); + EXPECT_EQ_ARRAY(span5.data(), Span<int>({8, 7, 6, 5, 4}).data(), 5); +} + TEST(span, MutableReverseIterator) { std::array<int, 4> src = {4, 5, 6, 7}; diff --git a/source/blender/editors/mesh/editmesh_bevel.c b/source/blender/editors/mesh/editmesh_bevel.c index cdbbdd820b7..0d74187b50e 100644 --- a/source/blender/editors/mesh/editmesh_bevel.c +++ b/source/blender/editors/mesh/editmesh_bevel.c @@ -97,7 +97,6 @@ typedef struct { int launch_event; float mcenter[2]; void *draw_handle_pixel; - short gizmo_flag; short value_mode; /* Which value does mouse movement and numeric input affect? */ float segments; /* Segments as float so smooth mouse pan works in small increments */ @@ -307,11 +306,6 @@ static bool edbm_bevel_init(bContext *C, wmOperator *op, const bool is_modal) opdata->draw_handle_pixel = ED_region_draw_cb_activate( region->type, ED_region_draw_mouse_line_cb, opdata->mcenter, REGION_DRAW_POST_PIXEL); G.moving = G_TRANSFORM_EDIT; - - if (v3d) { - opdata->gizmo_flag = v3d->gizmo_flag; - v3d->gizmo_flag |= V3D_GIZMO_HIDE_DEFAULT_MODAL; - } } return true; @@ -433,15 +427,11 @@ static void edbm_bevel_exit(bContext *C, wmOperator *op) } if (opdata->is_modal) { - View3D *v3d = CTX_wm_view3d(C); ARegion *region = CTX_wm_region(C); for (uint ob_index = 0; ob_index < opdata->ob_store_len; ob_index++) { EDBM_redo_state_free(&opdata->ob_store[ob_index].mesh_backup); } ED_region_draw_cb_exit(region->type, opdata->draw_handle_pixel); - if (v3d) { - v3d->gizmo_flag = opdata->gizmo_flag; - } G.moving = 0; } MEM_SAFE_FREE(opdata->ob_store); diff --git a/source/blender/editors/mesh/editmesh_bisect.c b/source/blender/editors/mesh/editmesh_bisect.c index f525f2c2e91..5cb57594ec3 100644 --- a/source/blender/editors/mesh/editmesh_bisect.c +++ b/source/blender/editors/mesh/editmesh_bisect.c @@ -72,7 +72,6 @@ typedef struct { bool is_dirty; } * backup; int backup_len; - short gizmo_flag; } BisectData; static void mesh_bisect_interactive_calc(bContext *C, @@ -157,8 +156,6 @@ static int mesh_bisect_invoke(bContext *C, wmOperator *op, const wmEvent *event) } if (ret & OPERATOR_RUNNING_MODAL) { - View3D *v3d = CTX_wm_view3d(C); - wmGesture *gesture = op->customdata; BisectData *opdata; @@ -181,8 +178,6 @@ static int mesh_bisect_invoke(bContext *C, wmOperator *op, const wmEvent *event) /* Misc other vars. */ G.moving = G_TRANSFORM_EDIT; - opdata->gizmo_flag = v3d->gizmo_flag; - v3d->gizmo_flag |= V3D_GIZMO_HIDE_DEFAULT_MODAL; /* Initialize modal callout. */ ED_workspace_status_text(C, TIP_("LMB: Click and drag to draw cut line")); @@ -191,10 +186,8 @@ static int mesh_bisect_invoke(bContext *C, wmOperator *op, const wmEvent *event) return ret; } -static void edbm_bisect_exit(bContext *C, BisectData *opdata) +static void edbm_bisect_exit(BisectData *opdata) { - View3D *v3d = CTX_wm_view3d(C); - v3d->gizmo_flag = opdata->gizmo_flag; G.moving = 0; for (int ob_index = 0; ob_index < opdata->backup_len; ob_index++) { @@ -225,7 +218,7 @@ static int mesh_bisect_modal(bContext *C, wmOperator *op, const wmEvent *event) } if (ret & (OPERATOR_FINISHED | OPERATOR_CANCELLED)) { - edbm_bisect_exit(C, &opdata_back); + edbm_bisect_exit(&opdata_back); #ifdef USE_GIZMO /* Setup gizmos */ diff --git a/source/blender/editors/mesh/editmesh_inset.c b/source/blender/editors/mesh/editmesh_inset.c index 159e84db4ef..7be169f70f4 100644 --- a/source/blender/editors/mesh/editmesh_inset.c +++ b/source/blender/editors/mesh/editmesh_inset.c @@ -76,7 +76,6 @@ typedef struct { int launch_event; float mcenter[2]; void *draw_handle_pixel; - short gizmo_flag; } InsetData; static void edbm_inset_update_header(wmOperator *op, bContext *C) @@ -177,7 +176,6 @@ static bool edbm_inset_init(bContext *C, wmOperator *op, const bool is_modal) opdata->num_input.unit_type[1] = B_UNIT_LENGTH; if (is_modal) { - View3D *v3d = CTX_wm_view3d(C); ARegion *region = CTX_wm_region(C); for (uint ob_index = 0; ob_index < opdata->ob_store_len; ob_index++) { @@ -189,10 +187,6 @@ static bool edbm_inset_init(bContext *C, wmOperator *op, const bool is_modal) opdata->draw_handle_pixel = ED_region_draw_cb_activate( region->type, ED_region_draw_mouse_line_cb, opdata->mcenter, REGION_DRAW_POST_PIXEL); G.moving = G_TRANSFORM_EDIT; - if (v3d) { - opdata->gizmo_flag = v3d->gizmo_flag; - v3d->gizmo_flag |= V3D_GIZMO_HIDE_DEFAULT_MODAL; - } } return true; @@ -206,15 +200,11 @@ static void edbm_inset_exit(bContext *C, wmOperator *op) opdata = op->customdata; if (opdata->is_modal) { - View3D *v3d = CTX_wm_view3d(C); ARegion *region = CTX_wm_region(C); for (uint ob_index = 0; ob_index < opdata->ob_store_len; ob_index++) { EDBM_redo_state_free(&opdata->ob_store[ob_index].mesh_backup); } ED_region_draw_cb_exit(region->type, opdata->draw_handle_pixel); - if (v3d) { - v3d->gizmo_flag = opdata->gizmo_flag; - } G.moving = 0; } diff --git a/source/blender/editors/sculpt_paint/paint_mask.c b/source/blender/editors/sculpt_paint/paint_mask.c index d968b6cc319..4a8dcd7a934 100644 --- a/source/blender/editors/sculpt_paint/paint_mask.c +++ b/source/blender/editors/sculpt_paint/paint_mask.c @@ -1300,7 +1300,7 @@ static void sculpt_gesture_apply_trim(SculptGestureContext *sgcontext) }), sculpt_mesh); BM_mesh_free(bm); - result->runtime.cd_dirty_vert |= CD_MASK_NORMAL; + BKE_mesh_normals_tag_dirty(result); BKE_mesh_nomain_to_mesh( result, sgcontext->vc.obact->data, sgcontext->vc.obact, &CD_MASK_MESH, true); } diff --git a/source/blender/editors/space_image/space_image.c b/source/blender/editors/space_image/space_image.c index 4107fd619aa..de8e4684d45 100644 --- a/source/blender/editors/space_image/space_image.c +++ b/source/blender/editors/space_image/space_image.c @@ -461,7 +461,7 @@ static void IMAGE_GGT_gizmo2d(wmGizmoGroupType *gzgt) gzgt->name = "UV Transform Gizmo"; gzgt->idname = "IMAGE_GGT_gizmo2d"; - gzgt->flag |= (WM_GIZMOGROUPTYPE_TOOL_FALLBACK_KEYMAP | + gzgt->flag |= (WM_GIZMOGROUPTYPE_DRAW_MODAL_EXCLUDE | WM_GIZMOGROUPTYPE_TOOL_FALLBACK_KEYMAP | WM_GIZMOGROUPTYPE_DELAY_REFRESH_FOR_TWEAK); gzgt->gzmap_params.spaceid = SPACE_IMAGE; @@ -475,7 +475,7 @@ static void IMAGE_GGT_gizmo2d_translate(wmGizmoGroupType *gzgt) gzgt->name = "UV Translate Gizmo"; gzgt->idname = "IMAGE_GGT_gizmo2d_translate"; - gzgt->flag |= (WM_GIZMOGROUPTYPE_TOOL_FALLBACK_KEYMAP | + gzgt->flag |= (WM_GIZMOGROUPTYPE_DRAW_MODAL_EXCLUDE | WM_GIZMOGROUPTYPE_TOOL_FALLBACK_KEYMAP | WM_GIZMOGROUPTYPE_DELAY_REFRESH_FOR_TWEAK); gzgt->gzmap_params.spaceid = SPACE_IMAGE; @@ -489,7 +489,7 @@ static void IMAGE_GGT_gizmo2d_resize(wmGizmoGroupType *gzgt) gzgt->name = "UV Transform Gizmo Resize"; gzgt->idname = "IMAGE_GGT_gizmo2d_resize"; - gzgt->flag |= (WM_GIZMOGROUPTYPE_TOOL_FALLBACK_KEYMAP | + gzgt->flag |= (WM_GIZMOGROUPTYPE_DRAW_MODAL_EXCLUDE | WM_GIZMOGROUPTYPE_TOOL_FALLBACK_KEYMAP | WM_GIZMOGROUPTYPE_DELAY_REFRESH_FOR_TWEAK); gzgt->gzmap_params.spaceid = SPACE_IMAGE; @@ -503,7 +503,7 @@ static void IMAGE_GGT_gizmo2d_rotate(wmGizmoGroupType *gzgt) gzgt->name = "UV Transform Gizmo Resize"; gzgt->idname = "IMAGE_GGT_gizmo2d_rotate"; - gzgt->flag |= (WM_GIZMOGROUPTYPE_TOOL_FALLBACK_KEYMAP | + gzgt->flag |= (WM_GIZMOGROUPTYPE_DRAW_MODAL_EXCLUDE | WM_GIZMOGROUPTYPE_TOOL_FALLBACK_KEYMAP | WM_GIZMOGROUPTYPE_DELAY_REFRESH_FOR_TWEAK); gzgt->gzmap_params.spaceid = SPACE_IMAGE; diff --git a/source/blender/editors/transform/transform.h b/source/blender/editors/transform/transform.h index 013c5faa54a..d1a1937cef1 100644 --- a/source/blender/editors/transform/transform.h +++ b/source/blender/editors/transform/transform.h @@ -618,9 +618,6 @@ typedef struct TransInfo { O_SET, } orient_curr; - /** backup from view3d, to restore on end. */ - short gizmo_flag; - short prop_mode; /** Value taken as input, either through mouse coordinates or entered as a parameter. */ diff --git a/source/blender/editors/transform/transform_generics.c b/source/blender/editors/transform/transform_generics.c index b7f579cc12f..c493b9bd102 100644 --- a/source/blender/editors/transform/transform_generics.c +++ b/source/blender/editors/transform/transform_generics.c @@ -249,12 +249,6 @@ void initTransInfo(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *eve t->view = v3d; t->animtimer = (animscreen) ? animscreen->animtimer : NULL; - /* turn gizmo off during transform */ - if (t->flag & T_MODAL) { - t->gizmo_flag = v3d->gizmo_flag; - v3d->gizmo_flag |= V3D_GIZMO_HIDE_DEFAULT_MODAL; - } - if (t->scene->toolsettings->transform_flag & SCE_XFORM_AXIS_ALIGN) { t->flag |= T_V3D_ALIGN; } @@ -742,13 +736,6 @@ void postTrans(bContext *C, TransInfo *t) } } } - else if (t->spacetype == SPACE_VIEW3D) { - View3D *v3d = t->area->spacedata.first; - /* restore gizmo */ - if (t->flag & T_MODAL) { - v3d->gizmo_flag = t->gizmo_flag; - } - } if (t->mouse.data) { MEM_freeN(t->mouse.data); diff --git a/source/blender/editors/transform/transform_gizmo_3d.c b/source/blender/editors/transform/transform_gizmo_3d.c index 8dc4f107837..0fa179c4f74 100644 --- a/source/blender/editors/transform/transform_gizmo_3d.c +++ b/source/blender/editors/transform/transform_gizmo_3d.c @@ -1974,8 +1974,8 @@ void VIEW3D_GGT_xform_gizmo(wmGizmoGroupType *gzgt) gzgt->name = "3D View: Transform Gizmo"; gzgt->idname = "VIEW3D_GGT_xform_gizmo"; - gzgt->flag = WM_GIZMOGROUPTYPE_3D | WM_GIZMOGROUPTYPE_TOOL_FALLBACK_KEYMAP | - WM_GIZMOGROUPTYPE_DELAY_REFRESH_FOR_TWEAK; + gzgt->flag = WM_GIZMOGROUPTYPE_3D | WM_GIZMOGROUPTYPE_DRAW_MODAL_EXCLUDE | + WM_GIZMOGROUPTYPE_TOOL_FALLBACK_KEYMAP | WM_GIZMOGROUPTYPE_DELAY_REFRESH_FOR_TWEAK; gzgt->gzmap_params.spaceid = SPACE_VIEW3D; gzgt->gzmap_params.regionid = RGN_TYPE_WINDOW; @@ -2216,8 +2216,8 @@ void VIEW3D_GGT_xform_cage(wmGizmoGroupType *gzgt) gzgt->name = "Transform Cage"; gzgt->idname = "VIEW3D_GGT_xform_cage"; - gzgt->flag |= WM_GIZMOGROUPTYPE_3D | WM_GIZMOGROUPTYPE_TOOL_FALLBACK_KEYMAP | - WM_GIZMOGROUPTYPE_DELAY_REFRESH_FOR_TWEAK; + gzgt->flag |= WM_GIZMOGROUPTYPE_3D | WM_GIZMOGROUPTYPE_DRAW_MODAL_EXCLUDE | + WM_GIZMOGROUPTYPE_TOOL_FALLBACK_KEYMAP | WM_GIZMOGROUPTYPE_DELAY_REFRESH_FOR_TWEAK; gzgt->gzmap_params.spaceid = SPACE_VIEW3D; gzgt->gzmap_params.regionid = RGN_TYPE_WINDOW; @@ -2459,8 +2459,8 @@ void VIEW3D_GGT_xform_shear(wmGizmoGroupType *gzgt) gzgt->name = "Transform Shear"; gzgt->idname = "VIEW3D_GGT_xform_shear"; - gzgt->flag |= WM_GIZMOGROUPTYPE_3D | WM_GIZMOGROUPTYPE_TOOL_FALLBACK_KEYMAP | - WM_GIZMOGROUPTYPE_DELAY_REFRESH_FOR_TWEAK; + gzgt->flag |= WM_GIZMOGROUPTYPE_3D | WM_GIZMOGROUPTYPE_DRAW_MODAL_EXCLUDE | + WM_GIZMOGROUPTYPE_TOOL_FALLBACK_KEYMAP | WM_GIZMOGROUPTYPE_DELAY_REFRESH_FOR_TWEAK; gzgt->gzmap_params.spaceid = SPACE_VIEW3D; gzgt->gzmap_params.regionid = RGN_TYPE_WINDOW; diff --git a/source/blender/gpencil_modifiers/intern/MOD_gpencillength.c b/source/blender/gpencil_modifiers/intern/MOD_gpencillength.c index 908918b8591..6aa0e6c152e 100644 --- a/source/blender/gpencil_modifiers/intern/MOD_gpencillength.c +++ b/source/blender/gpencil_modifiers/intern/MOD_gpencillength.c @@ -143,7 +143,6 @@ static void bakeModifier(Main *UNUSED(bmain), LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) { LISTBASE_FOREACH (bGPDframe *, gpf, &gpl->frames) { - LengthGpencilModifierData *lmd = (LengthGpencilModifierData *)md; LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) { deformStroke(md, depsgraph, ob, gpl, gpf, gps); } diff --git a/source/blender/makesdna/DNA_view3d_types.h b/source/blender/makesdna/DNA_view3d_types.h index fbf087ca392..4d88f6f0c15 100644 --- a/source/blender/makesdna/DNA_view3d_types.h +++ b/source/blender/makesdna/DNA_view3d_types.h @@ -610,14 +610,6 @@ enum { V3D_GIZMO_HIDE_TOOL = (1 << 3), }; -/** - * Hide these gizmos when modal operators are active, - * the intention is to hide all gizmos except for navigation since from a user-perspective - * these are closer to UI-level interface elements. Hiding them makes the UI flicker, also, - * the 3D view-axis can be useful to see during interactions. - */ -#define V3D_GIZMO_HIDE_DEFAULT_MODAL (V3D_GIZMO_HIDE_CONTEXT | V3D_GIZMO_HIDE_TOOL) - /** #View3d.gizmo_show_object */ enum { V3D_GIZMO_SHOW_OBJECT_TRANSLATE = (1 << 0), diff --git a/source/blender/makesrna/intern/rna_wm_gizmo.c b/source/blender/makesrna/intern/rna_wm_gizmo.c index 43848ce78e2..6a63723d174 100644 --- a/source/blender/makesrna/intern/rna_wm_gizmo.c +++ b/source/blender/makesrna/intern/rna_wm_gizmo.c @@ -1402,6 +1402,11 @@ static void rna_def_gizmogroup(BlenderRNA *brna) 0, "Show Modal All", "Show all while interacting, as well as this group when another is being interacted with"}, + {WM_GIZMOGROUPTYPE_DRAW_MODAL_EXCLUDE, + "EXCLUDE_MODAL", + 0, + "Exclude Modal", + "Show all except this group while interacting"}, {WM_GIZMOGROUPTYPE_TOOL_INIT, "TOOL_INIT", 0, diff --git a/source/blender/modifiers/intern/MOD_array.c b/source/blender/modifiers/intern/MOD_array.c index 6a9c9715994..2f0f11ab56d 100644 --- a/source/blender/modifiers/intern/MOD_array.c +++ b/source/blender/modifiers/intern/MOD_array.c @@ -786,7 +786,7 @@ static Mesh *arrayModifier_doArray(ArrayModifierData *amd, * TODO: we may need to set other dirty flags as well? */ if (use_recalc_normals) { - result->runtime.cd_dirty_vert |= CD_MASK_NORMAL; + BKE_mesh_normals_tag_dirty(result); } if (vgroup_start_cap_remap) { diff --git a/source/blender/modifiers/intern/MOD_bevel.c b/source/blender/modifiers/intern/MOD_bevel.c index 8fdd222402e..add95a0d248 100644 --- a/source/blender/modifiers/intern/MOD_bevel.c +++ b/source/blender/modifiers/intern/MOD_bevel.c @@ -243,7 +243,7 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh * BM_mesh_free(bm); - result->runtime.cd_dirty_vert |= CD_MASK_NORMAL; + BKE_mesh_normals_tag_dirty(result); return result; } diff --git a/source/blender/modifiers/intern/MOD_boolean.cc b/source/blender/modifiers/intern/MOD_boolean.cc index bdb791dc8e7..c5d6902e1bc 100644 --- a/source/blender/modifiers/intern/MOD_boolean.cc +++ b/source/blender/modifiers/intern/MOD_boolean.cc @@ -161,7 +161,7 @@ static Mesh *get_quick_mesh( mul_m4_v3(omat, mv->co); } - result->runtime.cd_dirty_vert |= CD_MASK_NORMAL; + BKE_mesh_normals_tag_dirty(result); } break; @@ -506,7 +506,7 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh * result = BKE_mesh_from_bmesh_for_eval_nomain(bm, nullptr, mesh); BM_mesh_free(bm); - result->runtime.cd_dirty_vert |= CD_MASK_NORMAL; + BKE_mesh_normals_tag_dirty(result); } if (result == nullptr) { @@ -541,7 +541,7 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh * result = BKE_mesh_from_bmesh_for_eval_nomain(bm, nullptr, mesh); BM_mesh_free(bm); - result->runtime.cd_dirty_vert |= CD_MASK_NORMAL; + BKE_mesh_normals_tag_dirty(result); } } } diff --git a/source/blender/modifiers/intern/MOD_build.c b/source/blender/modifiers/intern/MOD_build.c index a344a15b0c1..6cd8d70383d 100644 --- a/source/blender/modifiers/intern/MOD_build.c +++ b/source/blender/modifiers/intern/MOD_build.c @@ -281,7 +281,7 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, struct MEM_freeN(faceMap); if (mesh->runtime.cd_dirty_vert & CD_MASK_NORMAL) { - result->runtime.cd_dirty_vert |= CD_MASK_NORMAL; + BKE_mesh_normals_tag_dirty(result); } /* TODO(sybren): also copy flags & tags? */ diff --git a/source/blender/modifiers/intern/MOD_decimate.c b/source/blender/modifiers/intern/MOD_decimate.c index faad1175f3a..56fcbbd8b7c 100644 --- a/source/blender/modifiers/intern/MOD_decimate.c +++ b/source/blender/modifiers/intern/MOD_decimate.c @@ -222,7 +222,7 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh * TIMEIT_END(decim); #endif - result->runtime.cd_dirty_vert |= CD_MASK_NORMAL; + BKE_mesh_normals_tag_dirty(result); return result; } diff --git a/source/blender/modifiers/intern/MOD_edgesplit.c b/source/blender/modifiers/intern/MOD_edgesplit.c index 82a6e169a7a..b21a536ad8a 100644 --- a/source/blender/modifiers/intern/MOD_edgesplit.c +++ b/source/blender/modifiers/intern/MOD_edgesplit.c @@ -115,7 +115,7 @@ Mesh *doEdgeSplit(const Mesh *mesh, EdgeSplitModifierData *emd) result = BKE_mesh_from_bmesh_for_eval_nomain(bm, NULL, mesh); BM_mesh_free(bm); - result->runtime.cd_dirty_vert |= CD_MASK_NORMAL; + BKE_mesh_normals_tag_dirty(result); return result; } diff --git a/source/blender/modifiers/intern/MOD_mask.cc b/source/blender/modifiers/intern/MOD_mask.cc index 306e79aa647..9a8af35109a 100644 --- a/source/blender/modifiers/intern/MOD_mask.cc +++ b/source/blender/modifiers/intern/MOD_mask.cc @@ -814,8 +814,7 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *UNUSED(ctx) } BKE_mesh_calc_edges_loose(result); - /* Tag to recalculate normals later. */ - result->runtime.cd_dirty_vert |= CD_MASK_NORMAL; + BKE_mesh_normals_tag_dirty(result); return result; } diff --git a/source/blender/modifiers/intern/MOD_mirror.c b/source/blender/modifiers/intern/MOD_mirror.c index 6116cf8146a..7fd90c71c9f 100644 --- a/source/blender/modifiers/intern/MOD_mirror.c +++ b/source/blender/modifiers/intern/MOD_mirror.c @@ -117,7 +117,7 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh * result = mirrorModifier__doMirror(mmd, ctx->object, mesh); if (result != mesh) { - result->runtime.cd_dirty_vert |= CD_MASK_NORMAL; + BKE_mesh_normals_tag_dirty(result); } return result; } diff --git a/source/blender/modifiers/intern/MOD_normal_edit.c b/source/blender/modifiers/intern/MOD_normal_edit.c index 1dbdcf87d63..db2eedf9c02 100644 --- a/source/blender/modifiers/intern/MOD_normal_edit.c +++ b/source/blender/modifiers/intern/MOD_normal_edit.c @@ -450,7 +450,7 @@ static void normalEditModifier_do_directional(NormalEditModifierData *enmd, if (do_polynors_fix && polygons_check_flip(mloop, nos, &mesh->ldata, mpoly, polynors, num_polys)) { - mesh->runtime.cd_dirty_vert |= CD_MASK_NORMAL; + BKE_mesh_normals_tag_dirty(mesh); } BKE_mesh_normals_loop_custom_set(mvert, diff --git a/source/blender/modifiers/intern/MOD_ocean.c b/source/blender/modifiers/intern/MOD_ocean.c index 1c502b94bdb..ff1055eff3b 100644 --- a/source/blender/modifiers/intern/MOD_ocean.c +++ b/source/blender/modifiers/intern/MOD_ocean.c @@ -317,7 +317,7 @@ static Mesh *generate_ocean_geometry(OceanModifierData *omd, Mesh *mesh_orig, co } } - result->runtime.cd_dirty_vert |= CD_MASK_NORMAL; + BKE_mesh_normals_tag_dirty(result); return result; } @@ -510,7 +510,7 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh * result = doOcean(md, ctx, mesh); if (result != mesh) { - result->runtime.cd_dirty_vert |= CD_MASK_NORMAL; + BKE_mesh_normals_tag_dirty(result); } return result; diff --git a/source/blender/modifiers/intern/MOD_particleinstance.c b/source/blender/modifiers/intern/MOD_particleinstance.c index 49b5dabe72d..4fffa7c93f3 100644 --- a/source/blender/modifiers/intern/MOD_particleinstance.c +++ b/source/blender/modifiers/intern/MOD_particleinstance.c @@ -545,7 +545,7 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh * MEM_SAFE_FREE(vert_part_index); MEM_SAFE_FREE(vert_part_value); - result->runtime.cd_dirty_vert |= CD_MASK_NORMAL; + BKE_mesh_normals_tag_dirty(result); return result; } diff --git a/source/blender/modifiers/intern/MOD_remesh.c b/source/blender/modifiers/intern/MOD_remesh.c index df3db894f4e..fef1f76c051 100644 --- a/source/blender/modifiers/intern/MOD_remesh.c +++ b/source/blender/modifiers/intern/MOD_remesh.c @@ -220,7 +220,7 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *UNUSED(ctx) BKE_mesh_copy_parameters_for_eval(result, mesh); BKE_mesh_calc_edges(result, true, false); - result->runtime.cd_dirty_vert |= CD_MASK_NORMAL; + BKE_mesh_normals_tag_dirty(result); return result; } diff --git a/source/blender/modifiers/intern/MOD_screw.c b/source/blender/modifiers/intern/MOD_screw.c index 0819b314e32..f24f6951690 100644 --- a/source/blender/modifiers/intern/MOD_screw.c +++ b/source/blender/modifiers/intern/MOD_screw.c @@ -1135,12 +1135,12 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh * ob_axis != NULL ? mtx_tx[3] : NULL, ltmd->merge_dist); if (result != result_prev) { - result->runtime.cd_dirty_vert |= CD_MASK_NORMAL; + BKE_mesh_normals_tag_dirty(result); } } if ((ltmd->flag & MOD_SCREW_NORMAL_CALC) == 0) { - result->runtime.cd_dirty_vert |= CD_MASK_NORMAL; + BKE_mesh_normals_tag_dirty(result); } return result; diff --git a/source/blender/modifiers/intern/MOD_skin.c b/source/blender/modifiers/intern/MOD_skin.c index 543cee18868..7d90935f678 100644 --- a/source/blender/modifiers/intern/MOD_skin.c +++ b/source/blender/modifiers/intern/MOD_skin.c @@ -1960,7 +1960,7 @@ static Mesh *base_skin(Mesh *origmesh, SkinModifierData *smd, eSkinErrorFlag *r_ result = BKE_mesh_from_bmesh_for_eval_nomain(bm, NULL, origmesh); BM_mesh_free(bm); - result->runtime.cd_dirty_vert |= CD_MASK_NORMAL; + BKE_mesh_normals_tag_dirty(result); skin_set_orig_indices(result); diff --git a/source/blender/modifiers/intern/MOD_solidify_extrude.c b/source/blender/modifiers/intern/MOD_solidify_extrude.c index 00fa6e24a64..8f9aa86e561 100644 --- a/source/blender/modifiers/intern/MOD_solidify_extrude.c +++ b/source/blender/modifiers/intern/MOD_solidify_extrude.c @@ -988,7 +988,7 @@ Mesh *MOD_solidify_extrude_modifyMesh(ModifierData *md, const ModifierEvalContex /* must recalculate normals with vgroups since they can displace unevenly T26888. */ if ((mesh->runtime.cd_dirty_vert & CD_MASK_NORMAL) || do_rim || dvert) { - result->runtime.cd_dirty_vert |= CD_MASK_NORMAL; + BKE_mesh_normals_tag_dirty(result); } else if (do_shell) { uint i; diff --git a/source/blender/modifiers/intern/MOD_solidify_nonmanifold.c b/source/blender/modifiers/intern/MOD_solidify_nonmanifold.c index 5b4716a1a43..f654b69841e 100644 --- a/source/blender/modifiers/intern/MOD_solidify_nonmanifold.c +++ b/source/blender/modifiers/intern/MOD_solidify_nonmanifold.c @@ -1955,7 +1955,7 @@ Mesh *MOD_solidify_nonmanifold_modifyMesh(ModifierData *md, } } - result->runtime.cd_dirty_vert |= CD_MASK_NORMAL; + BKE_mesh_normals_tag_dirty(result); /* Make edges. */ { diff --git a/source/blender/modifiers/intern/MOD_triangulate.c b/source/blender/modifiers/intern/MOD_triangulate.c index ef633494c7b..52d5f3e97ef 100644 --- a/source/blender/modifiers/intern/MOD_triangulate.c +++ b/source/blender/modifiers/intern/MOD_triangulate.c @@ -107,7 +107,7 @@ Mesh *triangulate_mesh(Mesh *mesh, me->flag |= ME_EDGEDRAW | ME_EDGERENDER; } - result->runtime.cd_dirty_vert |= CD_MASK_NORMAL; + BKE_mesh_normals_tag_dirty(result); return result; } diff --git a/source/blender/modifiers/intern/MOD_util.c b/source/blender/modifiers/intern/MOD_util.c index 5b97d0eb259..d57e92b4b35 100644 --- a/source/blender/modifiers/intern/MOD_util.c +++ b/source/blender/modifiers/intern/MOD_util.c @@ -216,7 +216,6 @@ Mesh *MOD_deform_mesh_eval_get(Object *ob, * we really need vertexCos here. */ else if (vertexCos) { BKE_mesh_vert_coords_apply(mesh, vertexCos); - mesh->runtime.cd_dirty_vert |= CD_MASK_NORMAL; } if (use_orco) { diff --git a/source/blender/modifiers/intern/MOD_weld.c b/source/blender/modifiers/intern/MOD_weld.c index b1fa2a7d912..503297d5985 100644 --- a/source/blender/modifiers/intern/MOD_weld.c +++ b/source/blender/modifiers/intern/MOD_weld.c @@ -1979,8 +1979,7 @@ static Mesh *weldModifier_doWeld(WeldModifierData *wmd, BLI_assert(loop_cur == result_nloops); /* is this needed? */ - /* recalculate normals */ - result->runtime.cd_dirty_vert |= CD_MASK_NORMAL; + BKE_mesh_normals_tag_dirty(result); weld_mesh_context_free(&weld_mesh); } diff --git a/source/blender/modifiers/intern/MOD_wireframe.c b/source/blender/modifiers/intern/MOD_wireframe.c index e188a61e975..706960182cf 100644 --- a/source/blender/modifiers/intern/MOD_wireframe.c +++ b/source/blender/modifiers/intern/MOD_wireframe.c @@ -109,7 +109,7 @@ static Mesh *WireframeModifier_do(WireframeModifierData *wmd, Object *ob, Mesh * result = BKE_mesh_from_bmesh_for_eval_nomain(bm, NULL, mesh); BM_mesh_free(bm); - result->runtime.cd_dirty_vert |= CD_MASK_NORMAL; + BKE_mesh_normals_tag_dirty(result); return result; } diff --git a/source/blender/nodes/CMakeLists.txt b/source/blender/nodes/CMakeLists.txt index 614be1d7229..b741461f820 100644 --- a/source/blender/nodes/CMakeLists.txt +++ b/source/blender/nodes/CMakeLists.txt @@ -141,6 +141,9 @@ set(SRC function/nodes/node_fn_random_float.cc function/node_function_util.cc + geometry/nodes/legacy/node_geo_material_assign.cc + geometry/nodes/legacy/node_geo_select_by_material.cc + geometry/nodes/node_geo_align_rotation_to_vector.cc geometry/nodes/node_geo_attribute_capture.cc geometry/nodes/node_geo_attribute_clamp.cc @@ -195,6 +198,7 @@ set(SRC geometry/nodes/node_geo_join_geometry.cc geometry/nodes/node_geo_material_assign.cc geometry/nodes/node_geo_material_replace.cc + geometry/nodes/node_geo_material_selection.cc geometry/nodes/node_geo_mesh_primitive_circle.cc geometry/nodes/node_geo_mesh_primitive_cone.cc geometry/nodes/node_geo_mesh_primitive_cube.cc @@ -214,7 +218,6 @@ set(SRC geometry/nodes/node_geo_point_translate.cc geometry/nodes/node_geo_points_to_volume.cc geometry/nodes/node_geo_raycast.cc - geometry/nodes/node_geo_select_by_material.cc geometry/nodes/node_geo_separate_components.cc geometry/nodes/node_geo_set_position.cc geometry/nodes/node_geo_subdivision_surface.cc diff --git a/source/blender/nodes/NOD_geometry.h b/source/blender/nodes/NOD_geometry.h index e9fb4ad123c..a713da45f0b 100644 --- a/source/blender/nodes/NOD_geometry.h +++ b/source/blender/nodes/NOD_geometry.h @@ -29,6 +29,9 @@ void register_node_tree_type_geo(void); void register_node_type_geo_group(void); void register_node_type_geo_custom_group(bNodeType *ntype); +void register_node_type_geo_legacy_material_assign(void); +void register_node_type_geo_legacy_select_by_material(void); + void register_node_type_geo_align_rotation_to_vector(void); void register_node_type_geo_attribute_clamp(void); void register_node_type_geo_attribute_color_ramp(void); @@ -80,6 +83,7 @@ void register_node_type_geo_is_viewport(void); void register_node_type_geo_join_geometry(void); void register_node_type_geo_material_assign(void); void register_node_type_geo_material_replace(void); +void register_node_type_geo_material_selection(void); void register_node_type_geo_mesh_primitive_circle(void); void register_node_type_geo_mesh_primitive_cone(void); void register_node_type_geo_mesh_primitive_cube(void); @@ -101,7 +105,6 @@ void register_node_type_geo_points_to_volume(void); void register_node_type_geo_raycast(void); void register_node_type_geo_sample_texture(void); void register_node_type_geo_select_by_handle_type(void); -void register_node_type_geo_select_by_material(void); void register_node_type_geo_separate_components(void); void register_node_type_geo_set_position(void); void register_node_type_geo_subdivision_surface(void); diff --git a/source/blender/nodes/NOD_node_declaration.hh b/source/blender/nodes/NOD_node_declaration.hh index 7ba4ac52b86..d64b76ccbb9 100644 --- a/source/blender/nodes/NOD_node_declaration.hh +++ b/source/blender/nodes/NOD_node_declaration.hh @@ -27,12 +27,19 @@ namespace blender::nodes { class NodeDeclarationBuilder; +/** + * Describes a single input or output socket. This is subclassed for different socket types. + */ class SocketDeclaration { protected: std::string name_; std::string identifier_; + bool hide_label_ = false; + bool hide_value_ = false; + bool is_multi_input_ = false; friend NodeDeclarationBuilder; + template<typename SocketDecl> friend class SocketDeclarationBuilder; public: virtual ~SocketDeclaration() = default; @@ -43,6 +50,49 @@ class SocketDeclaration { StringRefNull name() const; StringRefNull identifier() const; + + protected: + void set_common_flags(bNodeSocket &socket) const; + bool matches_common_data(const bNodeSocket &socket) const; +}; + +class BaseSocketDeclarationBuilder { + public: + virtual ~BaseSocketDeclarationBuilder() = default; +}; + +/** + * Wraps a #SocketDeclaration and provides methods to set it up correctly. + * This is separate from #SocketDeclaration, because it allows separating the API used by nodes to + * declare themselves from how the declaration is stored internally. + */ +template<typename SocketDecl> +class SocketDeclarationBuilder : public BaseSocketDeclarationBuilder { + protected: + using Self = typename SocketDecl::Builder; + static_assert(std::is_base_of_v<SocketDeclaration, SocketDecl>); + SocketDecl *decl_; + + friend class NodeDeclarationBuilder; + + public: + Self &hide_label(bool value = true) + { + decl_->hide_label_ = value; + return *(Self *)this; + } + + Self &hide_value(bool value = true) + { + decl_->hide_value_ = value; + return *(Self *)this; + } + + Self &multi_input(bool value = true) + { + decl_->is_multi_input_ = value; + return *(Self *)this; + } }; using SocketDeclarationPtr = std::unique_ptr<SocketDeclaration>; @@ -67,12 +117,21 @@ class NodeDeclaration { class NodeDeclarationBuilder { private: NodeDeclaration &declaration_; + Vector<std::unique_ptr<BaseSocketDeclarationBuilder>> builders_; public: NodeDeclarationBuilder(NodeDeclaration &declaration); - template<typename DeclType> DeclType &add_input(StringRef name, StringRef identifier = ""); - template<typename DeclType> DeclType &add_output(StringRef name, StringRef identifier = ""); + template<typename DeclType> + typename DeclType::Builder &add_input(StringRef name, StringRef identifier = ""); + template<typename DeclType> + typename DeclType::Builder &add_output(StringRef name, StringRef identifier = ""); + + private: + template<typename DeclType> + typename DeclType::Builder &add_socket(StringRef name, + StringRef identifier, + Vector<SocketDeclarationPtr> &r_decls); }; /* -------------------------------------------------------------------- @@ -99,27 +158,34 @@ inline NodeDeclarationBuilder::NodeDeclarationBuilder(NodeDeclaration &declarati } template<typename DeclType> -inline DeclType &NodeDeclarationBuilder::add_input(StringRef name, StringRef identifier) +inline typename DeclType::Builder &NodeDeclarationBuilder::add_input(StringRef name, + StringRef identifier) { - static_assert(std::is_base_of_v<SocketDeclaration, DeclType>); - std::unique_ptr<DeclType> socket_decl = std::make_unique<DeclType>(); - DeclType &ref = *socket_decl; - ref.name_ = name; - ref.identifier_ = identifier.is_empty() ? name : identifier; - declaration_.inputs_.append(std::move(socket_decl)); - return ref; + return this->add_socket<DeclType>(name, identifier, declaration_.inputs_); +} + +template<typename DeclType> +inline typename DeclType::Builder &NodeDeclarationBuilder::add_output(StringRef name, + StringRef identifier) +{ + return this->add_socket<DeclType>(name, identifier, declaration_.outputs_); } template<typename DeclType> -inline DeclType &NodeDeclarationBuilder::add_output(StringRef name, StringRef identifier) +inline typename DeclType::Builder &NodeDeclarationBuilder::add_socket( + StringRef name, StringRef identifier, Vector<SocketDeclarationPtr> &r_decls) { static_assert(std::is_base_of_v<SocketDeclaration, DeclType>); + using Builder = typename DeclType::Builder; std::unique_ptr<DeclType> socket_decl = std::make_unique<DeclType>(); - DeclType &ref = *socket_decl; - ref.name_ = name; - ref.identifier_ = identifier.is_empty() ? name : identifier; - declaration_.outputs_.append(std::move(socket_decl)); - return ref; + std::unique_ptr<Builder> socket_decl_builder = std::make_unique<Builder>(); + socket_decl_builder->decl_ = &*socket_decl; + socket_decl->name_ = name; + socket_decl->identifier_ = identifier.is_empty() ? name : identifier; + r_decls.append(std::move(socket_decl)); + Builder &socket_decl_builder_ref = *socket_decl_builder; + builders_.append(std::move(socket_decl_builder)); + return socket_decl_builder_ref; } /* -------------------------------------------------------------------- diff --git a/source/blender/nodes/NOD_socket_declarations.hh b/source/blender/nodes/NOD_socket_declarations.hh index 11352111356..3d0cfdb5d5d 100644 --- a/source/blender/nodes/NOD_socket_declarations.hh +++ b/source/blender/nodes/NOD_socket_declarations.hh @@ -25,6 +25,8 @@ namespace blender::nodes::decl { +class FloatBuilder; + class Float : public SocketDeclaration { private: float default_value_ = 0.0f; @@ -32,36 +34,45 @@ class Float : public SocketDeclaration { float soft_max_value_ = FLT_MAX; PropertySubType subtype_ = PROP_NONE; + friend FloatBuilder; + public: - Float &min(const float value) + using Builder = FloatBuilder; + + bNodeSocket &build(bNodeTree &ntree, bNode &node, eNodeSocketInOut in_out) const override; + bool matches(const bNodeSocket &socket) const override; + bNodeSocket &update_or_build(bNodeTree &ntree, bNode &node, bNodeSocket &socket) const override; +}; + +class FloatBuilder : public SocketDeclarationBuilder<Float> { + public: + FloatBuilder &min(const float value) { - soft_min_value_ = value; + decl_->soft_min_value_ = value; return *this; } - Float &max(const float value) + FloatBuilder &max(const float value) { - soft_max_value_ = value; + decl_->soft_max_value_ = value; return *this; } - Float &default_value(const float value) + FloatBuilder &default_value(const float value) { - default_value_ = value; + decl_->default_value_ = value; return *this; } - Float &subtype(PropertySubType subtype) + FloatBuilder &subtype(PropertySubType subtype) { - subtype_ = subtype; + decl_->subtype_ = subtype; return *this; } - - bNodeSocket &build(bNodeTree &ntree, bNode &node, eNodeSocketInOut in_out) const override; - bool matches(const bNodeSocket &socket) const override; - bNodeSocket &update_or_build(bNodeTree &ntree, bNode &node, bNodeSocket &socket) const override; }; +class IntBuilder; + class Int : public SocketDeclaration { private: int default_value_ = 0; @@ -69,36 +80,45 @@ class Int : public SocketDeclaration { int soft_max_value_ = INT32_MAX; PropertySubType subtype_ = PROP_NONE; + friend IntBuilder; + public: - Int &min(const int value) + using Builder = IntBuilder; + + bNodeSocket &build(bNodeTree &ntree, bNode &node, eNodeSocketInOut in_out) const override; + bool matches(const bNodeSocket &socket) const override; + bNodeSocket &update_or_build(bNodeTree &ntree, bNode &node, bNodeSocket &socket) const override; +}; + +class IntBuilder : public SocketDeclarationBuilder<Int> { + public: + IntBuilder &min(const int value) { - soft_min_value_ = value; + decl_->soft_min_value_ = value; return *this; } - Int &max(const int value) + IntBuilder &max(const int value) { - soft_max_value_ = value; + decl_->soft_max_value_ = value; return *this; } - Int &default_value(const int value) + IntBuilder &default_value(const int value) { - default_value_ = value; + decl_->default_value_ = value; return *this; } - Int &subtype(PropertySubType subtype) + IntBuilder &subtype(PropertySubType subtype) { - subtype_ = subtype; + decl_->subtype_ = subtype; return *this; } - - bNodeSocket &build(bNodeTree &ntree, bNode &node, eNodeSocketInOut in_out) const override; - bool matches(const bNodeSocket &socket) const override; - bNodeSocket &update_or_build(bNodeTree &ntree, bNode &node, bNodeSocket &socket) const override; }; +class VectorBuilder; + class Vector : public SocketDeclaration { private: float3 default_value_ = {0, 0, 0}; @@ -106,160 +126,152 @@ class Vector : public SocketDeclaration { float soft_max_value_ = FLT_MAX; PropertySubType subtype_ = PROP_NONE; + friend VectorBuilder; + + public: + using Builder = VectorBuilder; + + bNodeSocket &build(bNodeTree &ntree, bNode &node, eNodeSocketInOut in_out) const override; + bool matches(const bNodeSocket &socket) const override; + bNodeSocket &update_or_build(bNodeTree &ntree, bNode &node, bNodeSocket &socket) const override; +}; + +class VectorBuilder : public SocketDeclarationBuilder<Vector> { public: - Vector &default_value(const float3 value) + VectorBuilder &default_value(const float3 value) { - default_value_ = value; + decl_->default_value_ = value; return *this; } - Vector &subtype(PropertySubType subtype) + VectorBuilder &subtype(PropertySubType subtype) { - subtype_ = subtype; + decl_->subtype_ = subtype; return *this; } - Vector &min(const float min) + VectorBuilder &min(const float min) { - soft_min_value_ = min; + decl_->soft_min_value_ = min; return *this; } - Vector &max(const float max) + VectorBuilder &max(const float max) { - soft_max_value_ = max; + decl_->soft_max_value_ = max; return *this; } - - bNodeSocket &build(bNodeTree &ntree, bNode &node, eNodeSocketInOut in_out) const override; - bool matches(const bNodeSocket &socket) const override; - bNodeSocket &update_or_build(bNodeTree &ntree, bNode &node, bNodeSocket &socket) const override; }; +class BoolBuilder; + class Bool : public SocketDeclaration { private: bool default_value_ = false; + friend BoolBuilder; public: - Bool &default_value(const bool value) - { - default_value_ = value; - return *this; - } + using Builder = BoolBuilder; bNodeSocket &build(bNodeTree &ntree, bNode &node, eNodeSocketInOut in_out) const override; bool matches(const bNodeSocket &socket) const override; }; +class BoolBuilder : public SocketDeclarationBuilder<Bool> { + public: + BoolBuilder &default_value(const bool value) + { + decl_->default_value_ = value; + return *this; + } +}; + +class ColorBuilder; + class Color : public SocketDeclaration { private: ColorGeometry4f default_value_; + friend ColorBuilder; + public: - Color &default_value(const ColorGeometry4f value) - { - default_value_ = value; - return *this; - } + using Builder = ColorBuilder; bNodeSocket &build(bNodeTree &ntree, bNode &node, eNodeSocketInOut in_out) const override; bool matches(const bNodeSocket &socket) const override; }; +class ColorBuilder : public SocketDeclarationBuilder<Color> { + public: + ColorBuilder &default_value(const ColorGeometry4f value) + { + decl_->default_value_ = value; + return *this; + } +}; + class String : public SocketDeclaration { public: + using Builder = SocketDeclarationBuilder<String>; + bNodeSocket &build(bNodeTree &ntree, bNode &node, eNodeSocketInOut in_out) const override; bool matches(const bNodeSocket &socket) const override; }; -namespace detail { -struct CommonIDSocketData { - const char *idname; - bool hide_label = false; -}; - -bNodeSocket &build_id_socket(bNodeTree &ntree, - bNode &node, - eNodeSocketInOut in_out, - const CommonIDSocketData &data, - StringRefNull name, - StringRefNull identifier); -bool matches_id_socket(const bNodeSocket &socket, - const CommonIDSocketData &data, - StringRefNull name, - StringRefNull identifier); - -template<typename Subtype> class IDSocketDeclaration : public SocketDeclaration { +class IDSocketDeclaration : public SocketDeclaration { private: - CommonIDSocketData data_; + const char *idname_; public: - IDSocketDeclaration(const char *idname) : data_({idname}) - { - } - - Subtype &hide_label(bool value) - { - data_.hide_label = value; - return *(Subtype *)this; - } - - bNodeSocket &build(bNodeTree &ntree, bNode &node, eNodeSocketInOut in_out) const override - { - return build_id_socket(ntree, node, in_out, data_, name_, identifier_); - } - - bool matches(const bNodeSocket &socket) const override + IDSocketDeclaration(const char *idname) : idname_(idname) { - return matches_id_socket(socket, data_, name_, identifier_); } - bNodeSocket &update_or_build(bNodeTree &ntree, bNode &node, bNodeSocket &socket) const override - { - if (StringRef(socket.idname) != data_.idname) { - return this->build(ntree, node, (eNodeSocketInOut)socket.in_out); - } - if (data_.hide_label) { - socket.flag |= SOCK_HIDE_LABEL; - } - else { - socket.flag &= ~SOCK_HIDE_LABEL; - } - return socket; - } + bNodeSocket &build(bNodeTree &ntree, bNode &node, eNodeSocketInOut in_out) const override; + bool matches(const bNodeSocket &socket) const override; + bNodeSocket &update_or_build(bNodeTree &ntree, bNode &node, bNodeSocket &socket) const override; }; -} // namespace detail -class Object : public detail::IDSocketDeclaration<Object> { +class Object : public IDSocketDeclaration { public: - Object() : detail::IDSocketDeclaration<Object>("NodeSocketObject") + using Builder = SocketDeclarationBuilder<Object>; + + Object() : IDSocketDeclaration("NodeSocketObject") { } }; -class Material : public detail::IDSocketDeclaration<Material> { +class Material : public IDSocketDeclaration { public: - Material() : detail::IDSocketDeclaration<Material>("NodeSocketMaterial") + using Builder = SocketDeclarationBuilder<Material>; + + Material() : IDSocketDeclaration("NodeSocketMaterial") { } }; -class Collection : public detail::IDSocketDeclaration<Collection> { +class Collection : public IDSocketDeclaration { public: - Collection() : detail::IDSocketDeclaration<Collection>("NodeSocketCollection") + using Builder = SocketDeclarationBuilder<Collection>; + + Collection() : IDSocketDeclaration("NodeSocketCollection") { } }; -class Texture : public detail::IDSocketDeclaration<Texture> { +class Texture : public IDSocketDeclaration { public: - Texture() : detail::IDSocketDeclaration<Texture>("NodeSocketTexture") + using Builder = SocketDeclarationBuilder<Texture>; + + Texture() : IDSocketDeclaration("NodeSocketTexture") { } }; class Geometry : public SocketDeclaration { public: + using Builder = SocketDeclarationBuilder<Geometry>; + bNodeSocket &build(bNodeTree &ntree, bNode &node, eNodeSocketInOut in_out) const override; bool matches(const bNodeSocket &socket) const override; }; diff --git a/source/blender/nodes/NOD_static_types.h b/source/blender/nodes/NOD_static_types.h index 215dca63fa3..51d59821d3c 100644 --- a/source/blender/nodes/NOD_static_types.h +++ b/source/blender/nodes/NOD_static_types.h @@ -332,7 +332,9 @@ DefNode(GeometryNode, GEO_NODE_INPUT_NORMAL, 0, "INPUT_NORMAL", InputNormal, "No DefNode(GeometryNode, GEO_NODE_INPUT_POSITION, 0, "POSITION", InputPosition, "Position", "") DefNode(GeometryNode, GEO_NODE_IS_VIEWPORT, 0, "IS_VIEWPORT", IsViewport, "Is Viewport", "") DefNode(GeometryNode, GEO_NODE_JOIN_GEOMETRY, 0, "JOIN_GEOMETRY", JoinGeometry, "Join Geometry", "") +DefNode(GeometryNode, GEO_NODE_MATERIAL_ASSIGN, 0, "MATERIAL_ASSIGN", MaterialAssign, "Material Assign", "") DefNode(GeometryNode, GEO_NODE_MATERIAL_REPLACE, 0, "MATERIAL_REPLACE", MaterialReplace, "Material Replace", "") +DefNode(GeometryNode, GEO_NODE_MATERIAL_SELECTION, 0, "MATERIAL_SELECTION", MaterialSelection, "Material Selection", "") DefNode(GeometryNode, GEO_NODE_MESH_PRIMITIVE_CIRCLE, def_geo_mesh_circle, "MESH_PRIMITIVE_CIRCLE", MeshCircle, "Mesh Circle", "") DefNode(GeometryNode, GEO_NODE_MESH_PRIMITIVE_CONE, def_geo_mesh_cone, "MESH_PRIMITIVE_CONE", MeshCone, "Cone", "") DefNode(GeometryNode, GEO_NODE_MESH_PRIMITIVE_CUBE, 0, "MESH_PRIMITIVE_CUBE", MeshCube, "Cube", "") diff --git a/source/blender/nodes/geometry/nodes/legacy/node_geo_material_assign.cc b/source/blender/nodes/geometry/nodes/legacy/node_geo_material_assign.cc new file mode 100644 index 00000000000..7d3481c1067 --- /dev/null +++ b/source/blender/nodes/geometry/nodes/legacy/node_geo_material_assign.cc @@ -0,0 +1,95 @@ +/* + * 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. + */ + +#include "node_geometry_util.hh" + +#include "UI_interface.h" +#include "UI_resources.h" + +#include "DNA_mesh_types.h" +#include "DNA_meshdata_types.h" + +#include "BKE_material.h" + +namespace blender::nodes { + +static void geo_node_legacy_material_assign_declare(NodeDeclarationBuilder &b) +{ + b.add_input<decl::Geometry>("Geometry"); + b.add_input<decl::Material>("Material").hide_label(true); + b.add_input<decl::String>("Selection"); + b.add_output<decl::Geometry>("Geometry"); +} + +static void assign_material_to_faces(Mesh &mesh, const VArray<bool> &face_mask, Material *material) +{ + int new_material_index = -1; + for (const int i : IndexRange(mesh.totcol)) { + Material *other_material = mesh.mat[i]; + if (other_material == material) { + new_material_index = i; + break; + } + } + if (new_material_index == -1) { + /* Append a new material index. */ + new_material_index = mesh.totcol; + BKE_id_material_eval_assign(&mesh.id, new_material_index + 1, material); + } + + mesh.mpoly = (MPoly *)CustomData_duplicate_referenced_layer(&mesh.pdata, CD_MPOLY, mesh.totpoly); + for (const int i : IndexRange(mesh.totpoly)) { + if (face_mask[i]) { + MPoly &poly = mesh.mpoly[i]; + poly.mat_nr = new_material_index; + } + } +} + +static void geo_node_legacy_material_assign_exec(GeoNodeExecParams params) +{ + Material *material = params.extract_input<Material *>("Material"); + const std::string mask_name = params.extract_input<std::string>("Selection"); + + GeometrySet geometry_set = params.extract_input<GeometrySet>("Geometry"); + + geometry_set = geometry_set_realize_instances(geometry_set); + + if (geometry_set.has<MeshComponent>()) { + MeshComponent &mesh_component = geometry_set.get_component_for_write<MeshComponent>(); + Mesh *mesh = mesh_component.get_for_write(); + if (mesh != nullptr) { + GVArray_Typed<bool> face_mask = mesh_component.attribute_get_for_read<bool>( + mask_name, ATTR_DOMAIN_FACE, true); + assign_material_to_faces(*mesh, face_mask, material); + } + } + + params.set_output("Geometry", std::move(geometry_set)); +} + +} // namespace blender::nodes + +void register_node_type_geo_legacy_material_assign() +{ + static bNodeType ntype; + + geo_node_type_base( + &ntype, GEO_NODE_LEGACY_MATERIAL_ASSIGN, "Material Assign", NODE_CLASS_GEOMETRY, 0); + ntype.declare = blender::nodes::geo_node_legacy_material_assign_declare; + ntype.geometry_node_execute = blender::nodes::geo_node_legacy_material_assign_exec; + nodeRegisterType(&ntype); +} diff --git a/source/blender/nodes/geometry/nodes/node_geo_select_by_material.cc b/source/blender/nodes/geometry/nodes/legacy/node_geo_select_by_material.cc index 40c990346e5..eabdd2bcd5a 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_select_by_material.cc +++ b/source/blender/nodes/geometry/nodes/legacy/node_geo_select_by_material.cc @@ -28,10 +28,10 @@ namespace blender::nodes { -static void geo_node_select_by_material_declare(NodeDeclarationBuilder &b) +static void geo_node_legacy_select_by_material_declare(NodeDeclarationBuilder &b) { b.add_input<decl::Geometry>("Geometry"); - b.add_input<decl::Material>("Material").hide_label(true); + b.add_input<decl::Material>("Material").hide_label(); b.add_input<decl::String>("Selection"); b.add_output<decl::Geometry>("Geometry"); } @@ -54,7 +54,7 @@ static void select_mesh_by_material(const Mesh &mesh, }); } -static void geo_node_select_by_material_exec(GeoNodeExecParams params) +static void geo_node_legacy_select_by_material_exec(GeoNodeExecParams params) { Material *material = params.extract_input<Material *>("Material"); const std::string selection_name = params.extract_input<std::string>("Selection"); @@ -80,13 +80,13 @@ static void geo_node_select_by_material_exec(GeoNodeExecParams params) } // namespace blender::nodes -void register_node_type_geo_select_by_material() +void register_node_type_geo_legacy_select_by_material() { static bNodeType ntype; geo_node_type_base( &ntype, GEO_NODE_LEGACY_SELECT_BY_MATERIAL, "Select by Material", NODE_CLASS_GEOMETRY, 0); - ntype.declare = blender::nodes::geo_node_select_by_material_declare; - ntype.geometry_node_execute = blender::nodes::geo_node_select_by_material_exec; + ntype.declare = blender::nodes::geo_node_legacy_select_by_material_declare; + ntype.geometry_node_execute = blender::nodes::geo_node_legacy_select_by_material_exec; nodeRegisterType(&ntype); } diff --git a/source/blender/nodes/geometry/nodes/node_geo_attribute_remove.cc b/source/blender/nodes/geometry/nodes/node_geo_attribute_remove.cc index e4f3230ebb9..21a9a338857 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_attribute_remove.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_attribute_remove.cc @@ -16,28 +16,15 @@ #include "node_geometry_util.hh" -static bNodeSocketTemplate geo_node_attribute_remove_in[] = { - {SOCK_GEOMETRY, N_("Geometry")}, - {SOCK_STRING, - N_("Attribute"), - 0.0f, - 0.0f, - 0.0f, - 1.0f, - -1.0f, - 1.0f, - PROP_NONE, - SOCK_MULTI_INPUT}, - {-1, ""}, -}; - -static bNodeSocketTemplate geo_node_attribute_remove_out[] = { - {SOCK_GEOMETRY, N_("Geometry")}, - {-1, ""}, -}; - namespace blender::nodes { +static void geo_node_attribute_remove_declare(NodeDeclarationBuilder &b) +{ + b.add_input<decl::Geometry>("Geometry"); + b.add_input<decl::String>("Attribute").multi_input(); + b.add_output<decl::Geometry>("Geometry"); +} + static void remove_attribute(GeometryComponent &component, GeoNodeExecParams ¶ms, Span<std::string> attribute_names) @@ -85,7 +72,7 @@ void register_node_type_geo_attribute_remove() geo_node_type_base( &ntype, GEO_NODE_ATTRIBUTE_REMOVE, "Attribute Remove", NODE_CLASS_ATTRIBUTE, 0); - node_type_socket_templates(&ntype, geo_node_attribute_remove_in, geo_node_attribute_remove_out); ntype.geometry_node_execute = blender::nodes::geo_node_attribute_remove_exec; + ntype.declare = blender::nodes::geo_node_attribute_remove_declare; nodeRegisterType(&ntype); } diff --git a/source/blender/nodes/geometry/nodes/node_geo_attribute_sample_texture.cc b/source/blender/nodes/geometry/nodes/node_geo_attribute_sample_texture.cc index c4fd0ca4008..52f97475941 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_attribute_sample_texture.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_attribute_sample_texture.cc @@ -33,7 +33,7 @@ namespace blender::nodes { static void geo_node_attribute_sample_texture_declare(NodeDeclarationBuilder &b) { b.add_input<decl::Geometry>("Geometry"); - b.add_input<decl::Texture>("Texture").hide_label(true); + b.add_input<decl::Texture>("Texture").hide_label(); b.add_input<decl::String>("Mapping"); b.add_input<decl::String>("Result"); b.add_output<decl::Geometry>("Geometry"); diff --git a/source/blender/nodes/geometry/nodes/node_geo_attribute_vector_rotate.cc b/source/blender/nodes/geometry/nodes/node_geo_attribute_vector_rotate.cc index da753dfc11b..adaa4de3029 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_attribute_vector_rotate.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_attribute_vector_rotate.cc @@ -21,27 +21,26 @@ #include "UI_interface.h" #include "UI_resources.h" -static bNodeSocketTemplate geo_node_attribute_vector_rotate_in[] = { - {SOCK_GEOMETRY, N_("Geometry")}, - {SOCK_STRING, N_("Vector")}, - {SOCK_VECTOR, N_("Vector"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_NONE, SOCK_HIDE_VALUE}, - {SOCK_STRING, N_("Center")}, - {SOCK_VECTOR, N_("Center"), 0.0f, 0.0f, 0.0f, 1.0f, -FLT_MAX, FLT_MAX, PROP_XYZ}, - {SOCK_STRING, N_("Axis")}, - {SOCK_VECTOR, N_("Axis"), 0.0f, 0.0f, 1.0f, 0.0f, -1.0f, 1.0f, PROP_XYZ, PROP_NONE}, - {SOCK_STRING, N_("Angle")}, - {SOCK_FLOAT, N_("Angle"), 0.0f, 0.0f, 0.0f, 1.0f, -FLT_MAX, FLT_MAX, PROP_ANGLE, PROP_NONE}, - {SOCK_STRING, N_("Rotation")}, - {SOCK_VECTOR, N_("Rotation"), 0.0f, 0.0f, 0.0f, 1.0f, -FLT_MAX, FLT_MAX, PROP_EULER}, - {SOCK_BOOLEAN, N_("Invert")}, - {SOCK_STRING, N_("Result")}, - {-1, ""}, -}; - -static bNodeSocketTemplate geo_node_attribute_vector_rotate_out[] = { - {SOCK_GEOMETRY, N_("Geometry")}, - {-1, ""}, -}; +namespace blender::nodes { + +static void geo_node_attribute_vector_rotate_declare(NodeDeclarationBuilder &b) +{ + b.add_input<decl::Geometry>("Geometry"); + b.add_input<decl::String>("Vector"); + b.add_input<decl::Vector>("Vector", "Vector_001").min(0.0f).max(1.0f).hide_value(); + b.add_input<decl::String>("Center"); + b.add_input<decl::Vector>("Center", "Center_001").subtype(PROP_XYZ); + b.add_input<decl::String>("Axis"); + b.add_input<decl::Vector>("Axis", "Axis_001").min(-1.0f).max(1.0f).subtype(PROP_XYZ); + b.add_input<decl::String>("Angle"); + b.add_input<decl::Float>("Angle", "Angle_001").subtype(PROP_ANGLE); + b.add_input<decl::String>("Rotation"); + b.add_input<decl::Vector>("Rotation", "Rotation_001").subtype(PROP_EULER); + b.add_input<decl::Bool>("Invert"); + b.add_input<decl::String>("Result"); + + b.add_output<decl::Geometry>("Geometry"); +} static void geo_node_attribute_vector_rotate_layout(uiLayout *layout, bContext *UNUSED(C), @@ -71,8 +70,6 @@ static void geo_node_attribute_vector_rotate_layout(uiLayout *layout, } } -namespace blender::nodes { - static void geo_node_attribute_vector_rotate_update(bNodeTree *UNUSED(ntree), bNode *node) { const NodeAttributeVectorRotate *node_storage = (NodeAttributeVectorRotate *)node->storage; @@ -339,14 +336,13 @@ void register_node_type_geo_attribute_vector_rotate() "Attribute Vector Rotate", NODE_CLASS_ATTRIBUTE, 0); - node_type_socket_templates( - &ntype, geo_node_attribute_vector_rotate_in, geo_node_attribute_vector_rotate_out); node_type_update(&ntype, blender::nodes::geo_node_attribute_vector_rotate_update); node_type_init(&ntype, blender::nodes::geo_node_attribute_vector_rotate_init); node_type_size(&ntype, 165, 100, 600); node_type_storage( &ntype, "NodeAttributeVectorRotate", node_free_standard_storage, node_copy_standard_storage); ntype.geometry_node_execute = blender::nodes::geo_node_attribute_vector_rotate_exec; - ntype.draw_buttons = geo_node_attribute_vector_rotate_layout; + ntype.draw_buttons = blender::nodes::geo_node_attribute_vector_rotate_layout; + ntype.declare = blender::nodes::geo_node_attribute_vector_rotate_declare; nodeRegisterType(&ntype); } diff --git a/source/blender/nodes/geometry/nodes/node_geo_boolean.cc b/source/blender/nodes/geometry/nodes/node_geo_boolean.cc index d8029ea1eeb..2a1c43a89fe 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_boolean.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_boolean.cc @@ -23,27 +23,16 @@ #include "node_geometry_util.hh" -static bNodeSocketTemplate geo_node_boolean_in[] = { - {SOCK_GEOMETRY, N_("Geometry 1")}, - {SOCK_GEOMETRY, - N_("Geometry 2"), - 0.0f, - 0.0f, - 0.0f, - 0.0f, - 0.0f, - 0.0f, - PROP_NONE, - SOCK_MULTI_INPUT}, - {SOCK_BOOLEAN, N_("Self Intersection")}, - {SOCK_BOOLEAN, N_("Hole Tolerant")}, - {-1, ""}, -}; - -static bNodeSocketTemplate geo_node_boolean_out[] = { - {SOCK_GEOMETRY, N_("Geometry")}, - {-1, ""}, -}; +namespace blender::nodes { + +static void geo_node_boolean_declare(NodeDeclarationBuilder &b) +{ + b.add_input<decl::Geometry>("Geometry 1"); + b.add_input<decl::Geometry>("Geometry 2").multi_input(); + b.add_input<decl::Bool>("Self Intersection"); + b.add_input<decl::Bool>("Hole Tolerant"); + b.add_output<decl::Geometry>("Geometry"); +} static void geo_node_boolean_layout(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) { @@ -77,8 +66,6 @@ static void geo_node_boolean_init(bNodeTree *UNUSED(tree), bNode *node) node->custom1 = GEO_NODE_BOOLEAN_DIFFERENCE; } -namespace blender::nodes { - static void geo_node_boolean_exec(GeoNodeExecParams params) { GeometryNodeBooleanOperation operation = (GeometryNodeBooleanOperation)params.node().custom1; @@ -138,10 +125,10 @@ void register_node_type_geo_boolean() static bNodeType ntype; geo_node_type_base(&ntype, GEO_NODE_BOOLEAN, "Boolean", NODE_CLASS_GEOMETRY, 0); - node_type_socket_templates(&ntype, geo_node_boolean_in, geo_node_boolean_out); - ntype.draw_buttons = geo_node_boolean_layout; - ntype.updatefunc = geo_node_boolean_update; - node_type_init(&ntype, geo_node_boolean_init); + ntype.declare = blender::nodes::geo_node_boolean_declare; + ntype.draw_buttons = blender::nodes::geo_node_boolean_layout; + ntype.updatefunc = blender::nodes::geo_node_boolean_update; + node_type_init(&ntype, blender::nodes::geo_node_boolean_init); ntype.geometry_node_execute = blender::nodes::geo_node_boolean_exec; nodeRegisterType(&ntype); } diff --git a/source/blender/nodes/geometry/nodes/node_geo_collection_info.cc b/source/blender/nodes/geometry/nodes/node_geo_collection_info.cc index e731b4c0cdc..f4c295b06fb 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_collection_info.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_collection_info.cc @@ -27,7 +27,7 @@ namespace blender::nodes { static void geo_node_collection_info_declare(NodeDeclarationBuilder &b) { - b.add_input<decl::Collection>("Collection").hide_label(true); + b.add_input<decl::Collection>("Collection").hide_label(); b.add_output<decl::Geometry>("Geometry"); } diff --git a/source/blender/nodes/geometry/nodes/node_geo_curve_primitive_spiral.cc b/source/blender/nodes/geometry/nodes/node_geo_curve_primitive_spiral.cc index 169a169bb1c..0803d43e5c3 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_curve_primitive_spiral.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_curve_primitive_spiral.cc @@ -41,7 +41,7 @@ static std::unique_ptr<CurveEval> create_spiral_curve(const float rotations, std::unique_ptr<CurveEval> curve = std::make_unique<CurveEval>(); std::unique_ptr<PolySpline> spline = std::make_unique<PolySpline>(); - const int totalpoints = resolution * rotations; + const int totalpoints = std::max(int(resolution * rotations), 1); const float delta_radius = (end_radius - start_radius) / (float)totalpoints; float radius = start_radius; const float delta_height = height / (float)totalpoints; diff --git a/source/blender/nodes/geometry/nodes/node_geo_curve_reverse.cc b/source/blender/nodes/geometry/nodes/node_geo_curve_reverse.cc index 2cb75eda202..32bcbe2c608 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_curve_reverse.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_curve_reverse.cc @@ -29,31 +29,6 @@ static void geo_node_curve_reverse_declare(NodeDeclarationBuilder &b) b.add_output<decl::Geometry>("Curve"); } -/** - * Reverse the data in a MutableSpan object. - */ -template<typename T> static void reverse_data(MutableSpan<T> r_data) -{ - const int size = r_data.size(); - for (const int i : IndexRange(size / 2)) { - std::swap(r_data[size - 1 - i], r_data[i]); - } -} - -/** - * Reverse and Swap the data between 2 MutableSpans. - */ -template<typename T> static void reverse_data(MutableSpan<T> left, MutableSpan<T> right) -{ - BLI_assert(left.size() == right.size()); - const int size = left.size(); - - for (const int i : IndexRange(size / 2 + size % 2)) { - std::swap(left[i], right[size - 1 - i]); - std::swap(right[i], left[size - 1 - i]); - } -} - static void geo_node_curve_reverse_exec(GeoNodeExecParams params) { GeometrySet geometry_set = params.extract_input<GeometrySet>("Curve"); @@ -74,42 +49,9 @@ static void geo_node_curve_reverse_exec(GeoNodeExecParams params) threading::parallel_for(splines.index_range(), 128, [&](IndexRange range) { for (const int i : range) { - if (!selection[i]) { - continue; - } - - reverse_data<float3>(splines[i]->positions()); - reverse_data<float>(splines[i]->radii()); - reverse_data<float>(splines[i]->tilts()); - - splines[i]->attributes.foreach_attribute( - [&](const AttributeIDRef &attribute_id, const AttributeMetaData &meta_data) { - std::optional<blender::fn::GMutableSpan> output_attribute = - splines[i]->attributes.get_for_write(attribute_id); - if (!output_attribute) { - BLI_assert_unreachable(); - return false; - } - attribute_math::convert_to_static_type(meta_data.data_type, [&](auto dummy) { - using T = decltype(dummy); - reverse_data(output_attribute->typed<T>()); - }); - return true; - }, - ATTR_DOMAIN_POINT); - - /* Deal with extra info on derived types. */ - if (BezierSpline *spline = dynamic_cast<BezierSpline *>(splines[i].get())) { - reverse_data<BezierSpline::HandleType>(spline->handle_types_left()); - reverse_data<BezierSpline::HandleType>(spline->handle_types_right()); - reverse_data<float3>(spline->handle_positions_left(), spline->handle_positions_right()); + if (selection[i]) { + splines[i]->reverse(); } - else if (NURBSpline *spline = dynamic_cast<NURBSpline *>(splines[i].get())) { - reverse_data<float>(spline->weights()); - } - /* Nothing to do for poly splines. */ - - splines[i]->mark_cache_invalid(); } }); diff --git a/source/blender/nodes/geometry/nodes/node_geo_curve_to_mesh.cc b/source/blender/nodes/geometry/nodes/node_geo_curve_to_mesh.cc index b0c763c7d06..2eae11d1705 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_curve_to_mesh.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_curve_to_mesh.cc @@ -294,8 +294,7 @@ static Mesh *curve_to_mesh_calculate(const CurveEval &curve, const CurveEval &pr BKE_id_material_eval_ensure_default_slot(&mesh->id); mesh->flag |= ME_AUTOSMOOTH; mesh->smoothresh = DEG2RADF(180.0f); - mesh->runtime.cd_dirty_vert |= CD_MASK_NORMAL; - mesh->runtime.cd_dirty_poly |= CD_MASK_NORMAL; + BKE_mesh_normals_tag_dirty(mesh); threading::parallel_for(curves.index_range(), 128, [&](IndexRange curves_range) { for (const int i_spline : curves_range) { diff --git a/source/blender/nodes/geometry/nodes/node_geo_delete_geometry.cc b/source/blender/nodes/geometry/nodes/node_geo_delete_geometry.cc index 5845eb357e0..1e2f652cd78 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_delete_geometry.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_delete_geometry.cc @@ -559,7 +559,7 @@ static Mesh *delete_mesh_selection(const Mesh &mesh_in, mesh_in, *result, vertex_map, edge_map, selected_poly_indices, new_loop_starts); BKE_mesh_calc_edges_loose(result); /* Tag to recalculate normals later. */ - result->runtime.cd_dirty_vert |= CD_MASK_NORMAL; + BKE_mesh_normals_tag_dirty(result); return result; } diff --git a/source/blender/nodes/geometry/nodes/node_geo_join_geometry.cc b/source/blender/nodes/geometry/nodes/node_geo_join_geometry.cc index 5792ee1485a..93643298f92 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_join_geometry.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_join_geometry.cc @@ -29,27 +29,14 @@ using blender::fn::GVArray_For_GSpan; -static bNodeSocketTemplate geo_node_join_geometry_in[] = { - {SOCK_GEOMETRY, - N_("Geometry"), - 0.0f, - 0.0f, - 0.0f, - 1.0f, - -1.0f, - 1.0f, - PROP_NONE, - SOCK_MULTI_INPUT}, - {-1, ""}, -}; - -static bNodeSocketTemplate geo_node_join_geometry_out[] = { - {SOCK_GEOMETRY, N_("Geometry")}, - {-1, ""}, -}; - namespace blender::nodes { +static void geo_node_join_geometry_declare(NodeDeclarationBuilder &b) +{ + b.add_input<decl::Geometry>("Geometry").multi_input(); + b.add_output<decl::Geometry>("Geometry"); +} + static Mesh *join_mesh_topology_and_builtin_attributes(Span<const MeshComponent *> src_components) { int totverts = 0; @@ -508,7 +495,7 @@ void register_node_type_geo_join_geometry() static bNodeType ntype; geo_node_type_base(&ntype, GEO_NODE_JOIN_GEOMETRY, "Join Geometry", NODE_CLASS_GEOMETRY, 0); - node_type_socket_templates(&ntype, geo_node_join_geometry_in, geo_node_join_geometry_out); ntype.geometry_node_execute = blender::nodes::geo_node_join_geometry_exec; + ntype.declare = blender::nodes::geo_node_join_geometry_declare; nodeRegisterType(&ntype); } diff --git a/source/blender/nodes/geometry/nodes/node_geo_material_assign.cc b/source/blender/nodes/geometry/nodes/node_geo_material_assign.cc index d7d3d0eded8..43818947272 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_material_assign.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_material_assign.cc @@ -29,12 +29,12 @@ namespace blender::nodes { static void geo_node_material_assign_declare(NodeDeclarationBuilder &b) { b.add_input<decl::Geometry>("Geometry"); - b.add_input<decl::Material>("Material").hide_label(true); - b.add_input<decl::String>("Selection"); + b.add_input<decl::Material>("Material").hide_label(); + b.add_input<decl::Bool>("Selection").default_value(true).hide_value(); b.add_output<decl::Geometry>("Geometry"); } -static void assign_material_to_faces(Mesh &mesh, const VArray<bool> &face_mask, Material *material) +static void assign_material_to_faces(Mesh &mesh, const IndexMask selection, Material *material) { int new_material_index = -1; for (const int i : IndexRange(mesh.totcol)) { @@ -51,18 +51,16 @@ static void assign_material_to_faces(Mesh &mesh, const VArray<bool> &face_mask, } mesh.mpoly = (MPoly *)CustomData_duplicate_referenced_layer(&mesh.pdata, CD_MPOLY, mesh.totpoly); - for (const int i : IndexRange(mesh.totpoly)) { - if (face_mask[i]) { - MPoly &poly = mesh.mpoly[i]; - poly.mat_nr = new_material_index; - } + for (const int i : selection) { + MPoly &poly = mesh.mpoly[i]; + poly.mat_nr = new_material_index; } } static void geo_node_material_assign_exec(GeoNodeExecParams params) { Material *material = params.extract_input<Material *>("Material"); - const std::string mask_name = params.extract_input<std::string>("Selection"); + const Field<bool> selection_field = params.extract_input<Field<bool>>("Selection"); GeometrySet geometry_set = params.extract_input<GeometrySet>("Geometry"); @@ -72,9 +70,15 @@ static void geo_node_material_assign_exec(GeoNodeExecParams params) MeshComponent &mesh_component = geometry_set.get_component_for_write<MeshComponent>(); Mesh *mesh = mesh_component.get_for_write(); if (mesh != nullptr) { - GVArray_Typed<bool> face_mask = mesh_component.attribute_get_for_read<bool>( - mask_name, ATTR_DOMAIN_FACE, true); - assign_material_to_faces(*mesh, face_mask, material); + + GeometryComponentFieldContext field_context{mesh_component, ATTR_DOMAIN_FACE}; + + fn::FieldEvaluator selection_evaluator{field_context, mesh->totpoly}; + selection_evaluator.add(selection_field); + selection_evaluator.evaluate(); + const IndexMask selection = selection_evaluator.get_evaluated_as_mask(0); + + assign_material_to_faces(*mesh, selection, material); } } @@ -87,8 +91,7 @@ void register_node_type_geo_material_assign() { static bNodeType ntype; - geo_node_type_base( - &ntype, GEO_NODE_LEGACY_MATERIAL_ASSIGN, "Material Assign", NODE_CLASS_GEOMETRY, 0); + geo_node_type_base(&ntype, GEO_NODE_MATERIAL_ASSIGN, "Material Assign", NODE_CLASS_GEOMETRY, 0); ntype.declare = blender::nodes::geo_node_material_assign_declare; ntype.geometry_node_execute = blender::nodes::geo_node_material_assign_exec; nodeRegisterType(&ntype); diff --git a/source/blender/nodes/geometry/nodes/node_geo_material_selection.cc b/source/blender/nodes/geometry/nodes/node_geo_material_selection.cc new file mode 100644 index 00000000000..22c24e34314 --- /dev/null +++ b/source/blender/nodes/geometry/nodes/node_geo_material_selection.cc @@ -0,0 +1,131 @@ +/* + * 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. + */ + +#include "node_geometry_util.hh" + +#include "UI_interface.h" +#include "UI_resources.h" + +#include "DNA_mesh_types.h" +#include "DNA_meshdata_types.h" + +#include "BLI_task.hh" + +#include "BKE_material.h" + +namespace blender::nodes { + +static void geo_node_material_selection_declare(NodeDeclarationBuilder &b) +{ + b.add_input<decl::Material>("Material").hide_label(true); + b.add_output<decl::Bool>("Selection"); +} + +static void select_mesh_by_material(const Mesh &mesh, + const Material *material, + const IndexMask mask, + const MutableSpan<bool> r_selection) +{ + BLI_assert(mesh.totpoly >= r_selection.size()); + Vector<int> material_indices; + for (const int i : IndexRange(mesh.totcol)) { + if (mesh.mat[i] == material) { + material_indices.append(i); + } + } + threading::parallel_for(mask.index_range(), 1024, [&](IndexRange range) { + for (const int i : range) { + const int face_index = mask[i]; + r_selection[i] = material_indices.contains(mesh.mpoly[face_index].mat_nr); + } + }); +} + +class MaterialSelectionFieldInput final : public fn::FieldInput { + Material *material_; + + public: + MaterialSelectionFieldInput(Material *material) + : fn::FieldInput(CPPType::get<bool>(), "Material Selection"), material_(material) + { + } + + const GVArray *get_varray_for_context(const fn::FieldContext &context, + IndexMask mask, + ResourceScope &scope) const final + { + if (const GeometryComponentFieldContext *geometry_context = + dynamic_cast<const GeometryComponentFieldContext *>(&context)) { + const GeometryComponent &component = geometry_context->geometry_component(); + const AttributeDomain domain = geometry_context->domain(); + if (component.type() != GEO_COMPONENT_TYPE_MESH) { + return nullptr; + } + const MeshComponent &mesh_component = static_cast<const MeshComponent &>(component); + const Mesh *mesh = mesh_component.get_for_read(); + if (mesh == nullptr) { + return nullptr; + } + + if (domain == ATTR_DOMAIN_FACE) { + Array<bool> selection(mask.min_array_size()); + select_mesh_by_material(*mesh, material_, mask, selection); + return &scope.construct<fn::GVArray_For_ArrayContainer<Array<bool>>>(std::move(selection)); + } + + Array<bool> selection(mesh->totpoly); + select_mesh_by_material(*mesh, material_, IndexMask(mesh->totpoly), selection); + GVArrayPtr face_selection = std::make_unique<fn::GVArray_For_ArrayContainer<Array<bool>>>( + std::move(selection)); + GVArrayPtr final_selection = mesh_component.attribute_try_adapt_domain( + std::move(face_selection), ATTR_DOMAIN_FACE, domain); + return scope.add_value(std::move(final_selection)).get(); + } + + return nullptr; + } + + uint64_t hash() const override + { + /* Some random constant hash. */ + return 91619626; + } + + bool is_equal_to(const fn::FieldNode &other) const override + { + return dynamic_cast<const MaterialSelectionFieldInput *>(&other) != nullptr; + } +}; + +static void geo_node_material_selection_exec(GeoNodeExecParams params) +{ + Material *material = params.extract_input<Material *>("Material"); + Field<bool> material_field{std::make_shared<MaterialSelectionFieldInput>(material)}; + params.set_output("Selection", std::move(material_field)); +} + +} // namespace blender::nodes + +void register_node_type_geo_material_selection() +{ + static bNodeType ntype; + + geo_node_type_base( + &ntype, GEO_NODE_MATERIAL_SELECTION, "Material Selection", NODE_CLASS_GEOMETRY, 0); + ntype.declare = blender::nodes::geo_node_material_selection_declare; + ntype.geometry_node_execute = blender::nodes::geo_node_material_selection_exec; + nodeRegisterType(&ntype); +} diff --git a/source/blender/nodes/geometry/nodes/node_geo_object_info.cc b/source/blender/nodes/geometry/nodes/node_geo_object_info.cc index ab99c9bb3f8..389acc40f0f 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_object_info.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_object_info.cc @@ -25,7 +25,7 @@ namespace blender::nodes { static void geo_node_object_info_declare(NodeDeclarationBuilder &b) { - b.add_input<decl::Object>("Object").hide_label(true); + b.add_input<decl::Object>("Object").hide_label(); b.add_output<decl::Vector>("Location"); b.add_output<decl::Vector>("Rotation"); b.add_output<decl::Vector>("Scale"); diff --git a/source/blender/nodes/geometry/nodes/node_geo_point_instance.cc b/source/blender/nodes/geometry/nodes/node_geo_point_instance.cc index 902ccfff179..fb45c22ced4 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_point_instance.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_point_instance.cc @@ -29,8 +29,8 @@ namespace blender::nodes { static void geo_node_point_instance_declare(NodeDeclarationBuilder &b) { b.add_input<decl::Geometry>("Geometry"); - b.add_input<decl::Object>("Object").hide_label(true); - b.add_input<decl::Collection>("Collection").hide_label(true); + b.add_input<decl::Object>("Object").hide_label(); + b.add_input<decl::Collection>("Collection").hide_label(); b.add_input<decl::Geometry>("Instance Geometry"); b.add_input<decl::Int>("Seed").min(-10000).max(10000); b.add_output<decl::Geometry>("Geometry"); diff --git a/source/blender/nodes/geometry/nodes/node_geo_set_position.cc b/source/blender/nodes/geometry/nodes/node_geo_set_position.cc index e8591616f55..4c754ddb643 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_set_position.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_set_position.cc @@ -24,7 +24,7 @@ static void geo_node_set_position_declare(NodeDeclarationBuilder &b) { b.add_input<decl::Geometry>("Geometry"); b.add_input<decl::Vector>("Position"); - b.add_input<decl::Bool>("Selection").default_value(true); + b.add_input<decl::Bool>("Selection").default_value(true).hide_value(); b.add_output<decl::Geometry>("Geometry"); } diff --git a/source/blender/nodes/geometry/nodes/node_geo_subdivision_surface.cc b/source/blender/nodes/geometry/nodes/node_geo_subdivision_surface.cc index d127f7dc0ba..4541bf3569f 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_subdivision_surface.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_subdivision_surface.cc @@ -37,14 +37,13 @@ static void geo_node_subdivision_surface_layout(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) { -#ifndef WITH_OPENSUBDIV - UNUSED_VARS(ptr); - uiItemL(layout, IFACE_("Disabled, built without OpenSubdiv"), ICON_ERROR); -#else +#ifdef WITH_OPENSUBDIV uiLayoutSetPropSep(layout, true); uiLayoutSetPropDecorate(layout, false); uiItemR(layout, ptr, "uv_smooth", 0, nullptr, ICON_NONE); uiItemR(layout, ptr, "boundary_smooth", 0, nullptr, ICON_NONE); +#else + UNUSED_VARS(layout, ptr); #endif } diff --git a/source/blender/nodes/geometry/nodes/node_geo_transform.cc b/source/blender/nodes/geometry/nodes/node_geo_transform.cc index d7423aa6d32..d5eb067cad0 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_transform.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_transform.cc @@ -69,8 +69,7 @@ void transform_mesh(Mesh *mesh, else { const float4x4 matrix = float4x4::from_loc_eul_scale(translation, rotation, scale); BKE_mesh_transform(mesh, matrix.values, false); - mesh->runtime.cd_dirty_vert |= CD_MASK_NORMAL; - mesh->runtime.cd_dirty_poly |= CD_MASK_NORMAL; + BKE_mesh_normals_tag_dirty(mesh); } } diff --git a/source/blender/nodes/intern/node_declaration.cc b/source/blender/nodes/intern/node_declaration.cc index dff92d5884f..f6b6cc49b2e 100644 --- a/source/blender/nodes/intern/node_declaration.cc +++ b/source/blender/nodes/intern/node_declaration.cc @@ -16,6 +16,8 @@ #include "NOD_node_declaration.hh" +#include "BKE_node.h" + namespace blender::nodes { void NodeDeclaration::build(bNodeTree &ntree, bNode &node) const @@ -62,4 +64,31 @@ bNodeSocket &SocketDeclaration::update_or_build(bNodeTree &ntree, return this->build(ntree, node, (eNodeSocketInOut)socket.in_out); } +void SocketDeclaration::set_common_flags(bNodeSocket &socket) const +{ + SET_FLAG_FROM_TEST(socket.flag, hide_value_, SOCK_HIDE_VALUE); + SET_FLAG_FROM_TEST(socket.flag, hide_label_, SOCK_HIDE_LABEL); + SET_FLAG_FROM_TEST(socket.flag, is_multi_input_, SOCK_MULTI_INPUT); +} + +bool SocketDeclaration::matches_common_data(const bNodeSocket &socket) const +{ + if (socket.name != name_) { + return false; + } + if (socket.identifier != identifier_) { + return false; + } + if (((socket.flag & SOCK_HIDE_VALUE) != 0) != hide_value_) { + return false; + } + if (((socket.flag & SOCK_HIDE_LABEL) != 0) != hide_label_) { + return false; + } + if (((socket.flag & SOCK_MULTI_INPUT) != 0) != is_multi_input_) { + return false; + } + return true; +} + } // namespace blender::nodes diff --git a/source/blender/nodes/intern/node_socket_declarations.cc b/source/blender/nodes/intern/node_socket_declarations.cc index e17b0fd5579..4b0dbad3cff 100644 --- a/source/blender/nodes/intern/node_socket_declarations.cc +++ b/source/blender/nodes/intern/node_socket_declarations.cc @@ -38,6 +38,7 @@ bNodeSocket &Float::build(bNodeTree &ntree, bNode &node, eNodeSocketInOut in_out { bNodeSocket &socket = *nodeAddStaticSocket( &ntree, &node, in_out, SOCK_FLOAT, subtype_, identifier_.c_str(), name_.c_str()); + this->set_common_flags(socket); bNodeSocketValueFloat &value = *(bNodeSocketValueFloat *)socket.default_value; value.min = soft_min_value_; value.max = soft_max_value_; @@ -47,16 +48,13 @@ bNodeSocket &Float::build(bNodeTree &ntree, bNode &node, eNodeSocketInOut in_out bool Float::matches(const bNodeSocket &socket) const { - if (socket.type != SOCK_FLOAT) { - return false; - } - if (socket.typeinfo->subtype != subtype_) { + if (!this->matches_common_data(socket)) { return false; } - if (socket.name != name_) { + if (socket.type != SOCK_FLOAT) { return false; } - if (socket.identifier != identifier_) { + if (socket.typeinfo->subtype != subtype_) { return false; } bNodeSocketValueFloat &value = *(bNodeSocketValueFloat *)socket.default_value; @@ -77,6 +75,7 @@ bNodeSocket &Float::update_or_build(bNodeTree &ntree, bNode &node, bNodeSocket & if (socket.typeinfo->subtype != subtype_) { modify_subtype_except_for_storage(socket, subtype_); } + this->set_common_flags(socket); bNodeSocketValueFloat &value = *(bNodeSocketValueFloat *)socket.default_value; value.min = soft_min_value_; value.max = soft_max_value_; @@ -92,6 +91,7 @@ bNodeSocket &Int::build(bNodeTree &ntree, bNode &node, eNodeSocketInOut in_out) { bNodeSocket &socket = *nodeAddStaticSocket( &ntree, &node, in_out, SOCK_INT, subtype_, identifier_.c_str(), name_.c_str()); + this->set_common_flags(socket); bNodeSocketValueInt &value = *(bNodeSocketValueInt *)socket.default_value; value.min = soft_min_value_; value.max = soft_max_value_; @@ -101,16 +101,13 @@ bNodeSocket &Int::build(bNodeTree &ntree, bNode &node, eNodeSocketInOut in_out) bool Int::matches(const bNodeSocket &socket) const { - if (socket.type != SOCK_INT) { - return false; - } - if (socket.typeinfo->subtype != subtype_) { + if (!this->matches_common_data(socket)) { return false; } - if (socket.name != name_) { + if (socket.type != SOCK_INT) { return false; } - if (socket.identifier != identifier_) { + if (socket.typeinfo->subtype != subtype_) { return false; } bNodeSocketValueInt &value = *(bNodeSocketValueInt *)socket.default_value; @@ -131,6 +128,7 @@ bNodeSocket &Int::update_or_build(bNodeTree &ntree, bNode &node, bNodeSocket &so if (socket.typeinfo->subtype != subtype_) { modify_subtype_except_for_storage(socket, subtype_); } + this->set_common_flags(socket); bNodeSocketValueInt &value = *(bNodeSocketValueInt *)socket.default_value; value.min = soft_min_value_; value.max = soft_max_value_; @@ -146,6 +144,7 @@ bNodeSocket &Vector::build(bNodeTree &ntree, bNode &node, eNodeSocketInOut in_ou { bNodeSocket &socket = *nodeAddStaticSocket( &ntree, &node, in_out, SOCK_VECTOR, subtype_, identifier_.c_str(), name_.c_str()); + this->set_common_flags(socket); bNodeSocketValueVector &value = *(bNodeSocketValueVector *)socket.default_value; copy_v3_v3(value.value, default_value_); value.min = soft_min_value_; @@ -155,16 +154,13 @@ bNodeSocket &Vector::build(bNodeTree &ntree, bNode &node, eNodeSocketInOut in_ou bool Vector::matches(const bNodeSocket &socket) const { - if (socket.type != SOCK_VECTOR) { - return false; - } - if (socket.typeinfo->subtype != subtype_) { + if (!this->matches_common_data(socket)) { return false; } - if (socket.name != name_) { + if (socket.type != SOCK_VECTOR) { return false; } - if (socket.identifier != identifier_) { + if (socket.typeinfo->subtype != subtype_) { return false; } return true; @@ -178,6 +174,7 @@ bNodeSocket &Vector::update_or_build(bNodeTree &ntree, bNode &node, bNodeSocket if (socket.typeinfo->subtype != subtype_) { modify_subtype_except_for_storage(socket, subtype_); } + this->set_common_flags(socket); bNodeSocketValueVector &value = *(bNodeSocketValueVector *)socket.default_value; value.subtype = subtype_; STRNCPY(socket.name, name_.c_str()); @@ -192,6 +189,7 @@ bNodeSocket &Bool::build(bNodeTree &ntree, bNode &node, eNodeSocketInOut in_out) { bNodeSocket &socket = *nodeAddStaticSocket( &ntree, &node, in_out, SOCK_BOOLEAN, PROP_NONE, identifier_.c_str(), name_.c_str()); + this->set_common_flags(socket); bNodeSocketValueBoolean &value = *(bNodeSocketValueBoolean *)socket.default_value; value.value = default_value_; return socket; @@ -199,13 +197,10 @@ bNodeSocket &Bool::build(bNodeTree &ntree, bNode &node, eNodeSocketInOut in_out) bool Bool::matches(const bNodeSocket &socket) const { - if (socket.type != SOCK_BOOLEAN) { - return false; - } - if (socket.name != name_) { + if (!this->matches_common_data(socket)) { return false; } - if (socket.identifier != identifier_) { + if (socket.type != SOCK_BOOLEAN) { return false; } return true; @@ -219,6 +214,7 @@ bNodeSocket &Color::build(bNodeTree &ntree, bNode &node, eNodeSocketInOut in_out { bNodeSocket &socket = *nodeAddStaticSocket( &ntree, &node, in_out, SOCK_RGBA, PROP_NONE, identifier_.c_str(), name_.c_str()); + this->set_common_flags(socket); bNodeSocketValueRGBA &value = *(bNodeSocketValueRGBA *)socket.default_value; copy_v4_v4(value.value, default_value_); return socket; @@ -226,13 +222,15 @@ bNodeSocket &Color::build(bNodeTree &ntree, bNode &node, eNodeSocketInOut in_out bool Color::matches(const bNodeSocket &socket) const { - if (socket.type != SOCK_RGBA) { - return false; - } - if (socket.name != name_) { - return false; + if (!this->matches_common_data(socket)) { + if (socket.name != name_) { + return false; + } + if (socket.identifier != identifier_) { + return false; + } } - if (socket.identifier != identifier_) { + if (socket.type != SOCK_RGBA) { return false; } return true; @@ -246,18 +244,16 @@ bNodeSocket &String::build(bNodeTree &ntree, bNode &node, eNodeSocketInOut in_ou { bNodeSocket &socket = *nodeAddStaticSocket( &ntree, &node, in_out, SOCK_STRING, PROP_NONE, identifier_.c_str(), name_.c_str()); + this->set_common_flags(socket); return socket; } bool String::matches(const bNodeSocket &socket) const { - if (socket.type != SOCK_STRING) { - return false; - } - if (socket.name != name_) { + if (!this->matches_common_data(socket)) { return false; } - if (socket.identifier != identifier_) { + if (socket.type != SOCK_STRING) { return false; } return true; @@ -267,42 +263,37 @@ bool String::matches(const bNodeSocket &socket) const * IDSocketDeclaration. */ -namespace detail { -bNodeSocket &build_id_socket(bNodeTree &ntree, - bNode &node, - eNodeSocketInOut in_out, - const CommonIDSocketData &data, - StringRefNull name, - StringRefNull identifier) +bNodeSocket &IDSocketDeclaration::build(bNodeTree &ntree, + bNode &node, + eNodeSocketInOut in_out) const { bNodeSocket &socket = *nodeAddSocket( - &ntree, &node, in_out, data.idname, identifier.c_str(), name.c_str()); - if (data.hide_label) { - socket.flag |= SOCK_HIDE_LABEL; - } + &ntree, &node, in_out, idname_, identifier_.c_str(), name_.c_str()); + this->set_common_flags(socket); return socket; } -bool matches_id_socket(const bNodeSocket &socket, - const CommonIDSocketData &data, - StringRefNull name, - StringRefNull identifier) +bool IDSocketDeclaration::matches(const bNodeSocket &socket) const { - if (!STREQ(socket.idname, data.idname)) { + if (!this->matches_common_data(socket)) { return false; } - if (data.hide_label != ((socket.flag & SOCK_HIDE_LABEL) != 0)) { - return false; - } - if (socket.name != name) { - return false; - } - if (socket.identifier != identifier) { + if (!STREQ(socket.idname, idname_)) { return false; } return true; } -} // namespace detail + +bNodeSocket &IDSocketDeclaration::update_or_build(bNodeTree &ntree, + bNode &node, + bNodeSocket &socket) const +{ + if (StringRef(socket.idname) != idname_) { + return this->build(ntree, node, (eNodeSocketInOut)socket.in_out); + } + this->set_common_flags(socket); + return socket; +} /* -------------------------------------------------------------------- * Geometry. @@ -312,18 +303,16 @@ bNodeSocket &Geometry::build(bNodeTree &ntree, bNode &node, eNodeSocketInOut in_ { bNodeSocket &socket = *nodeAddSocket( &ntree, &node, in_out, "NodeSocketGeometry", identifier_.c_str(), name_.c_str()); + this->set_common_flags(socket); return socket; } bool Geometry::matches(const bNodeSocket &socket) const { - if (socket.type != SOCK_GEOMETRY) { + if (!this->matches_common_data(socket)) { return false; } - if (socket.name != name_) { - return false; - } - if (socket.identifier != identifier_) { + if (socket.type != SOCK_GEOMETRY) { return false; } return true; diff --git a/source/blender/render/intern/render_result.c b/source/blender/render/intern/render_result.c index c29ab342ed7..6cb6aabe885 100644 --- a/source/blender/render/intern/render_result.c +++ b/source/blender/render/intern/render_result.c @@ -250,6 +250,9 @@ RenderPass *render_layer_add_pass(RenderResult *rr, BLI_addtail(&rl->passes, rpass); + /* The result contains non-allocated pass now, so tag it as such. */ + rr->passes_allocated = false; + return rpass; } diff --git a/source/blender/windowmanager/gizmo/WM_gizmo_types.h b/source/blender/windowmanager/gizmo/WM_gizmo_types.h index b0dd7be4572..a1edc4196dc 100644 --- a/source/blender/windowmanager/gizmo/WM_gizmo_types.h +++ b/source/blender/windowmanager/gizmo/WM_gizmo_types.h @@ -120,6 +120,10 @@ typedef enum eWM_GizmoFlagGroupTypeFlag { * Also show this group when another group is being interacted with. */ WM_GIZMOGROUPTYPE_DRAW_MODAL_ALL = (1 << 5), + + /** Don't draw this gizmo group when it is modal. */ + WM_GIZMOGROUPTYPE_DRAW_MODAL_EXCLUDE = (1 << 6), + /** * When used with tool, only run when activating the tool, * instead of linking the gizmo while the tool is active. @@ -130,7 +134,7 @@ typedef enum eWM_GizmoFlagGroupTypeFlag { * when a tool can activate multiple operators based on the key-map. * We could even move the options into the key-map item. * ~ campbell. */ - WM_GIZMOGROUPTYPE_TOOL_INIT = (1 << 6), + WM_GIZMOGROUPTYPE_TOOL_INIT = (1 << 7), /** * This gizmo type supports using the fallback tools keymap. @@ -138,7 +142,7 @@ typedef enum eWM_GizmoFlagGroupTypeFlag { * * Often useful in combination with #WM_GIZMOGROUPTYPE_DELAY_REFRESH_FOR_TWEAK */ - WM_GIZMOGROUPTYPE_TOOL_FALLBACK_KEYMAP = (1 << 7), + WM_GIZMOGROUPTYPE_TOOL_FALLBACK_KEYMAP = (1 << 8), /** * Use this from a gizmos refresh callback so we can postpone the refresh operation @@ -149,14 +153,14 @@ typedef enum eWM_GizmoFlagGroupTypeFlag { * for selection operations. This means gizmos that use this check don't interfere * with click drag events by popping up under the cursor and catching the tweak event. */ - WM_GIZMOGROUPTYPE_DELAY_REFRESH_FOR_TWEAK = (1 << 8), + WM_GIZMOGROUPTYPE_DELAY_REFRESH_FOR_TWEAK = (1 << 9), /** * Cause continuous redraws, i.e. set the region redraw flag on every main loop iteration. This * should really be avoided by using proper region redraw tagging, notifiers and the message-bus, * however for VR it's sometimes needed. */ - WM_GIZMOGROUPTYPE_VR_REDRAWS = (1 << 9), + WM_GIZMOGROUPTYPE_VR_REDRAWS = (1 << 10), } eWM_GizmoFlagGroupTypeFlag; /** diff --git a/source/blender/windowmanager/gizmo/intern/wm_gizmo_map.c b/source/blender/windowmanager/gizmo/intern/wm_gizmo_map.c index 1144cd072e0..295196c701b 100644 --- a/source/blender/windowmanager/gizmo/intern/wm_gizmo_map.c +++ b/source/blender/windowmanager/gizmo/intern/wm_gizmo_map.c @@ -387,14 +387,21 @@ static void gizmomap_prepare_drawing(wmGizmoMap *gzmap, LISTBASE_FOREACH (wmGizmoGroup *, gzgroup, &gzmap->groups) { /* check group visibility - drawstep first to avoid unnecessary call of group poll callback */ - if (!wm_gizmogroup_is_visible_in_drawstep(gzgroup, drawstep) || - !WM_gizmo_group_type_poll(C, gzgroup->type)) { + if (!wm_gizmogroup_is_visible_in_drawstep(gzgroup, drawstep)) { continue; } - /* When modal only show other gizmo groups tagged with #WM_GIZMOGROUPTYPE_DRAW_MODAL_ALL. */ - if (gz_modal && (gzgroup != gz_modal->parent_gzgroup)) { - if ((gzgroup->type->flag & WM_GIZMOGROUPTYPE_DRAW_MODAL_ALL) == 0) { + if (gz_modal && (gzgroup == gz_modal->parent_gzgroup)) { + if (gzgroup->type->flag & WM_GIZMOGROUPTYPE_DRAW_MODAL_EXCLUDE) { + continue; + } + } + else { /* Don't poll modal gizmo since some poll functions unlink. */ + if (!WM_gizmo_group_type_poll(C, gzgroup->type)) { + continue; + } + /* When modal only show other gizmo groups tagged with #WM_GIZMOGROUPTYPE_DRAW_MODAL_ALL. */ + if (gz_modal && ((gzgroup->type->flag & WM_GIZMOGROUPTYPE_DRAW_MODAL_ALL) == 0)) { continue; } } diff --git a/source/blender/windowmanager/intern/wm_files_link.c b/source/blender/windowmanager/intern/wm_files_link.c index 2416f5b50b3..7568c9989a8 100644 --- a/source/blender/windowmanager/intern/wm_files_link.c +++ b/source/blender/windowmanager/intern/wm_files_link.c @@ -383,6 +383,12 @@ static void wm_append_loose_data_instantiate(WMLinkAppendData *lapp_data, ViewLayer *view_layer, const View3D *v3d) { + if (scene == NULL) { + /* In some cases, like the asset drag&drop e.g., the caller code manages instantiation itself. + */ + return; + } + LinkNode *itemlink; Collection *active_collection = NULL; const bool do_obdata = (lapp_data->flag & FILE_OBDATA_INSTANCE) != 0; @@ -1281,6 +1287,10 @@ static ID *wm_file_link_append_datablock_ex(Main *bmain, return id; } +/* + * NOTE: `scene` (and related `view_layer` and `v3d`) pointers may be NULL, in which case no + * instantiation of linked objects, collections etc. will be performed. + */ ID *WM_file_link_datablock(Main *bmain, Scene *scene, ViewLayer *view_layer, @@ -1293,6 +1303,10 @@ ID *WM_file_link_datablock(Main *bmain, bmain, scene, view_layer, v3d, filepath, id_code, id_name, false); } +/* + * NOTE: `scene` (and related `view_layer` and `v3d`) pointers may be NULL, in which case no + * instantiation of appended objects, collections etc. will be performed. + */ ID *WM_file_append_datablock(Main *bmain, Scene *scene, ViewLayer *view_layer, diff --git a/tests/python/CMakeLists.txt b/tests/python/CMakeLists.txt index 79632e49c1f..a1b94abc317 100644 --- a/tests/python/CMakeLists.txt +++ b/tests/python/CMakeLists.txt @@ -766,7 +766,7 @@ foreach(geo_node_test ${geo_node_tests}) ) endforeach() else() - MESSAGE(STATUS "No directory named ${TEST_SRC_DIR}/modeling/geometry_nodes/${geo_node_test}/ found, disabling test.") + MESSAGE(STATUS "Directory named ${TEST_SRC_DIR}/modeling/geometry_nodes/${geo_node_test}/ Not Found, disabling test.") endif() endforeach() |