From 404b946ac0e4f86e99471c2805570dfe3a8cc67e Mon Sep 17 00:00:00 2001 From: Bastien Montagne Date: Tue, 1 Jun 2021 17:36:33 +0200 Subject: LibOverride: Fix again infinite loop in resync in some complex/degenerated cases. Broken in recent refactor of (recursive)resync, reported by studio, thanks. --- source/blender/blenkernel/intern/lib_override.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/source/blender/blenkernel/intern/lib_override.c b/source/blender/blenkernel/intern/lib_override.c index 4d5085d6ad5..9a2887a1d16 100644 --- a/source/blender/blenkernel/intern/lib_override.c +++ b/source/blender/blenkernel/intern/lib_override.c @@ -1473,16 +1473,16 @@ static void lib_override_library_main_resync_on_library_indirect_level( } int level = 0; - id = lib_override_library_main_resync_find_root_recurse(id, &level); - BLI_assert(ID_IS_OVERRIDE_LIBRARY_REAL(id)); - do_continue = true; - /* In complex non-supported cases, with several different override hierarchies sharing * relations between each-other, we may end up not actually updating/replacing the given * root id (see e.g. pro/shots/110_rextoria/110_0150_A/110_0150_A.anim.blend of sprites * project repository, r2687). * This can lead to infinite loop here, at least avoid this. */ id->tag &= ~LIB_TAG_LIB_OVERRIDE_NEED_RESYNC; + id = lib_override_library_main_resync_find_root_recurse(id, &level); + id->tag &= ~LIB_TAG_LIB_OVERRIDE_NEED_RESYNC; + BLI_assert(ID_IS_OVERRIDE_LIBRARY_REAL(id)); + do_continue = true; CLOG_INFO(&LOG, 2, "Resyncing %s (%p)...", id->name, id->lib); const bool success = BKE_lib_override_library_resync( -- cgit v1.2.3 From 5b6e0bad1bbc33faba2247602349942ce163b7df Mon Sep 17 00:00:00 2001 From: Philipp Oeser Date: Tue, 1 Jun 2021 11:57:30 +0200 Subject: Fix T88715: particle size influence texture not working for 'keyed' or 'none' physics types This was reported for the special case of mapping with "Strand / Particle" coords, but was not working with other coordinates either. Dont see a reason for not supporting Size influence textures for these kinds of particles (and since these types of particles have an "age" like all others as well, even the "Strand / Particle" coords are supported here as well) Maniphest Tasks: T88715 Differential Revision: https://developer.blender.org/D11449 --- source/blender/blenkernel/intern/particle_system.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/source/blender/blenkernel/intern/particle_system.c b/source/blender/blenkernel/intern/particle_system.c index c727a144c87..ce4be411c9a 100644 --- a/source/blender/blenkernel/intern/particle_system.c +++ b/source/blender/blenkernel/intern/particle_system.c @@ -4912,9 +4912,12 @@ void particle_system_update(struct Depsgraph *depsgraph, sim.psmd->flag |= eParticleSystemFlag_Pars; } + ParticleTexture ptex; + LOOP_EXISTING_PARTICLES { - pa->size = part->size; + psys_get_texture(&sim, pa, &ptex, PAMAP_SIZE, cfra); + pa->size = part->size * ptex.size; if (part->randsize > 0.0f) { pa->size *= 1.0f - part->randsize * psys_frand(psys, p + 1); } -- cgit v1.2.3 From 17b09b509c069dad6817e4c123bca50bd0682578 Mon Sep 17 00:00:00 2001 From: Hans Goudey Date: Tue, 1 Jun 2021 12:03:59 -0400 Subject: Geometry Nodes: Skip calculating normals in transform node This commit skips the eager recalculation of mesh normals in the transform node. Often another deformation or topology-altering operation will happen after the transform node, which means the recalculation was redundant anyway. In one of my test cases this made the node more than 14x faster. Though depending on the situation the cost of updating the normals may just be shifted elsewhere. --- source/blender/nodes/geometry/nodes/node_geo_transform.cc | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/source/blender/nodes/geometry/nodes/node_geo_transform.cc b/source/blender/nodes/geometry/nodes/node_geo_transform.cc index 9714a4f8a80..1ad5dbea492 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_transform.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_transform.cc @@ -20,6 +20,7 @@ #include "BLI_float4x4.hh" +#include "DNA_mesh_types.h" #include "DNA_pointcloud_types.h" #include "DNA_volume_types.h" @@ -72,7 +73,8 @@ void transform_mesh(Mesh *mesh, else { const float4x4 matrix = float4x4::from_loc_eul_scale(translation, rotation, scale); BKE_mesh_transform(mesh, matrix.values, false); - BKE_mesh_calc_normals(mesh); + mesh->runtime.cd_dirty_vert |= CD_MASK_NORMAL; + mesh->runtime.cd_dirty_poly |= CD_MASK_NORMAL; } } @@ -158,7 +160,6 @@ static void transform_curve(CurveEval &curve, const float3 rotation, const float3 scale) { - if (use_translate(rotation, scale)) { curve.translate(translation); } -- cgit v1.2.3 From 3400ba329e6b9ce865bcc592889edb7e958b3b37 Mon Sep 17 00:00:00 2001 From: Richard Antalik Date: Tue, 1 Jun 2021 23:06:31 +0200 Subject: VSE: Use own category for metadata panel Metadata panel was visible in each category. In other editors, this panel is usually placed in category with other source media properties. In sequencer, metadata is transfered over while compositing and relation to particular strip is lost, therefore separate category for metadata seems to be best option. Since Metadata panel is alone in this category, it will be open by default. --- source/blender/editors/space_sequencer/sequencer_buttons.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/blender/editors/space_sequencer/sequencer_buttons.c b/source/blender/editors/space_sequencer/sequencer_buttons.c index 11614d94862..1e0ecfd890e 100644 --- a/source/blender/editors/space_sequencer/sequencer_buttons.c +++ b/source/blender/editors/space_sequencer/sequencer_buttons.c @@ -111,10 +111,10 @@ void sequencer_buttons_register(ARegionType *art) pt = MEM_callocN(sizeof(PanelType), "spacetype sequencer panel metadata"); strcpy(pt->idname, "SEQUENCER_PT_metadata"); strcpy(pt->label, N_("Metadata")); + strcpy(pt->category, "Metadata"); strcpy(pt->translation_context, BLT_I18NCONTEXT_DEFAULT_BPYRNA); pt->poll = metadata_panel_context_poll; pt->draw = metadata_panel_context_draw; - pt->flag |= PANEL_TYPE_DEFAULT_CLOSED; pt->order = 10; BLI_addtail(&art->paneltypes, pt); } -- cgit v1.2.3 From 464797078d44a55b45560f561b20a546ce46bcd7 Mon Sep 17 00:00:00 2001 From: Wannes Malfait Date: Tue, 1 Jun 2021 17:32:03 -0400 Subject: Geometry Nodes: Add Delete Geometry Node This node is similar to the mask modifier, but it deletes the elements of the geometry corresponding to the selection, which is retrieved as a boolean attribute. The node currently supports both mesh and point cloud data. For meshes, which elements are deleted depends on the domain of the input selection attribute, just like how behavior depends on the selection mode in mesh edit mode. In the future this node will support curve data, and ideally volume data in some way. Differential Revision: https://developer.blender.org/D10748 --- release/scripts/startup/nodeitems_builtins.py | 1 + source/blender/blenkernel/BKE_node.h | 1 + source/blender/blenkernel/intern/node.cc | 1 + source/blender/modifiers/intern/MOD_mask.cc | 37 +- source/blender/nodes/CMakeLists.txt | 1 + source/blender/nodes/NOD_geometry.h | 1 + source/blender/nodes/NOD_static_types.h | 1 + .../blender/nodes/geometry/node_geometry_util.hh | 8 + .../geometry/nodes/node_geo_delete_geometry.cc | 524 +++++++++++++++++++++ .../geometry/nodes/node_geo_point_separate.cc | 10 +- 10 files changed, 567 insertions(+), 18 deletions(-) create mode 100644 source/blender/nodes/geometry/nodes/node_geo_delete_geometry.cc diff --git a/release/scripts/startup/nodeitems_builtins.py b/release/scripts/startup/nodeitems_builtins.py index 05c7ef756c7..d4c21bf5a23 100644 --- a/release/scripts/startup/nodeitems_builtins.py +++ b/release/scripts/startup/nodeitems_builtins.py @@ -507,6 +507,7 @@ geometry_node_categories = [ ]), GeometryNodeCategory("GEO_GEOMETRY", "Geometry", items=[ NodeItem("GeometryNodeBoundBox"), + NodeItem("GeometryNodeDeleteGeometry"), NodeItem("GeometryNodeTransform"), NodeItem("GeometryNodeJoinGeometry"), ]), diff --git a/source/blender/blenkernel/BKE_node.h b/source/blender/blenkernel/BKE_node.h index fb6647cb68d..00111910d66 100644 --- a/source/blender/blenkernel/BKE_node.h +++ b/source/blender/blenkernel/BKE_node.h @@ -1430,6 +1430,7 @@ int ntreeTexExecTree(struct bNodeTree *ntree, #define GEO_NODE_INPUT_MATERIAL 1050 #define GEO_NODE_MATERIAL_REPLACE 1051 #define GEO_NODE_MESH_TO_CURVE 1052 +#define GEO_NODE_DELETE_GEOMETRY 1053 /** \} */ diff --git a/source/blender/blenkernel/intern/node.cc b/source/blender/blenkernel/intern/node.cc index d0864e85373..0923917aa55 100644 --- a/source/blender/blenkernel/intern/node.cc +++ b/source/blender/blenkernel/intern/node.cc @@ -5052,6 +5052,7 @@ static void registerGeometryNodes() register_node_type_geo_collection_info(); register_node_type_geo_curve_to_mesh(); register_node_type_geo_curve_resample(); + register_node_type_geo_delete_geometry(); register_node_type_geo_edge_split(); register_node_type_geo_input_material(); register_node_type_geo_is_viewport(); diff --git a/source/blender/modifiers/intern/MOD_mask.cc b/source/blender/modifiers/intern/MOD_mask.cc index 812bfe3b375..a77f6cfe8ba 100644 --- a/source/blender/modifiers/intern/MOD_mask.cc +++ b/source/blender/modifiers/intern/MOD_mask.cc @@ -69,6 +69,19 @@ using blender::MutableSpan; using blender::Span; using blender::Vector; +/* For delete geometry node. */ +void copy_masked_vertices_to_new_mesh(const Mesh &src_mesh, Mesh &dst_mesh, Span vertex_map); +void copy_masked_edges_to_new_mesh(const Mesh &src_mesh, + Mesh &dst_mesh, + Span vertex_map, + Span edge_map); +void copy_masked_polys_to_new_mesh(const Mesh &src_mesh, + Mesh &dst_mesh, + Span vertex_map, + Span edge_map, + Span masked_poly_indices, + Span new_loop_starts); + static void initData(ModifierData *md) { MaskModifierData *mmd = (MaskModifierData *)md; @@ -237,9 +250,7 @@ static void computed_masked_polygons(const Mesh *mesh, *r_num_masked_loops = num_masked_loops; } -static void copy_masked_vertices_to_new_mesh(const Mesh &src_mesh, - Mesh &dst_mesh, - Span vertex_map) +void copy_masked_vertices_to_new_mesh(const Mesh &src_mesh, Mesh &dst_mesh, Span vertex_map) { BLI_assert(src_mesh.totvert == vertex_map.size()); for (const int i_src : vertex_map.index_range()) { @@ -256,10 +267,10 @@ static void copy_masked_vertices_to_new_mesh(const Mesh &src_mesh, } } -static void copy_masked_edges_to_new_mesh(const Mesh &src_mesh, - Mesh &dst_mesh, - Span vertex_map, - Span edge_map) +void copy_masked_edges_to_new_mesh(const Mesh &src_mesh, + Mesh &dst_mesh, + Span vertex_map, + Span edge_map) { BLI_assert(src_mesh.totvert == vertex_map.size()); BLI_assert(src_mesh.totedge == edge_map.size()); @@ -279,12 +290,12 @@ static void copy_masked_edges_to_new_mesh(const Mesh &src_mesh, } } -static void copy_masked_polys_to_new_mesh(const Mesh &src_mesh, - Mesh &dst_mesh, - Span vertex_map, - Span edge_map, - Span masked_poly_indices, - Span new_loop_starts) +void copy_masked_polys_to_new_mesh(const Mesh &src_mesh, + Mesh &dst_mesh, + Span vertex_map, + Span edge_map, + Span masked_poly_indices, + Span new_loop_starts) { for (const int i_dst : masked_poly_indices.index_range()) { const int i_src = masked_poly_indices[i_dst]; diff --git a/source/blender/nodes/CMakeLists.txt b/source/blender/nodes/CMakeLists.txt index 24085b31fc3..6ecf46647a0 100644 --- a/source/blender/nodes/CMakeLists.txt +++ b/source/blender/nodes/CMakeLists.txt @@ -164,6 +164,7 @@ set(SRC geometry/nodes/node_geo_common.cc geometry/nodes/node_geo_curve_to_mesh.cc geometry/nodes/node_geo_curve_resample.cc + geometry/nodes/node_geo_delete_geometry.cc geometry/nodes/node_geo_edge_split.cc geometry/nodes/node_geo_input_material.cc geometry/nodes/node_geo_is_viewport.cc diff --git a/source/blender/nodes/NOD_geometry.h b/source/blender/nodes/NOD_geometry.h index eadfed26be1..30b039bca40 100644 --- a/source/blender/nodes/NOD_geometry.h +++ b/source/blender/nodes/NOD_geometry.h @@ -52,6 +52,7 @@ void register_node_type_geo_bounding_box(void); void register_node_type_geo_collection_info(void); void register_node_type_geo_curve_to_mesh(void); void register_node_type_geo_curve_resample(void); +void register_node_type_geo_delete_geometry(void); void register_node_type_geo_edge_split(void); void register_node_type_geo_input_material(void); void register_node_type_geo_is_viewport(void); diff --git a/source/blender/nodes/NOD_static_types.h b/source/blender/nodes/NOD_static_types.h index ef5f25e7b57..081525ffb5b 100644 --- a/source/blender/nodes/NOD_static_types.h +++ b/source/blender/nodes/NOD_static_types.h @@ -291,6 +291,7 @@ DefNode(GeometryNode, GEO_NODE_BOUNDING_BOX, 0, "BOUNDING_BOX", BoundBox, "Bound DefNode(GeometryNode, GEO_NODE_COLLECTION_INFO, def_geo_collection_info, "COLLECTION_INFO", CollectionInfo, "Collection Info", "") DefNode(GeometryNode, GEO_NODE_CURVE_RESAMPLE, def_geo_curve_resample, "CURVE_RESAMPLE", CurveResample, "Resample Curve", "") DefNode(GeometryNode, GEO_NODE_CURVE_TO_MESH, 0, "CURVE_TO_MESH", CurveToMesh, "Curve to Mesh", "") +DefNode(GeometryNode, GEO_NODE_DELETE_GEOMETRY, 0, "DELETE_GEOMETRY", DeleteGeometry, "Delete Geometry", "") DefNode(GeometryNode, GEO_NODE_EDGE_SPLIT, 0, "EDGE_SPLIT", EdgeSplit, "Edge Split", "") DefNode(GeometryNode, GEO_NODE_INPUT_MATERIAL, def_geo_input_material, "INPUT_MATERIAL", InputMaterial, "Material", "") DefNode(GeometryNode, GEO_NODE_IS_VIEWPORT, 0, "IS_VIEWPORT", IsViewport, "Is Viewport", "") diff --git a/source/blender/nodes/geometry/node_geometry_util.hh b/source/blender/nodes/geometry/node_geometry_util.hh index 81092798ca1..79a98c5ebf0 100644 --- a/source/blender/nodes/geometry/node_geometry_util.hh +++ b/source/blender/nodes/geometry/node_geometry_util.hh @@ -62,4 +62,12 @@ Mesh *create_cylinder_or_cone_mesh(const float radius_top, Mesh *create_cube_mesh(const float size); +/** + * Copies the point domain attributes from `in_component` that are in the mask to `out_component`. + */ +void copy_point_attributes_based_on_mask(const GeometryComponent &in_component, + GeometryComponent &result_component, + Span masks, + const bool invert); + } // namespace blender::nodes diff --git a/source/blender/nodes/geometry/nodes/node_geo_delete_geometry.cc b/source/blender/nodes/geometry/nodes/node_geo_delete_geometry.cc new file mode 100644 index 00000000000..9044081de90 --- /dev/null +++ b/source/blender/nodes/geometry/nodes/node_geo_delete_geometry.cc @@ -0,0 +1,524 @@ +/* + * 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 "BLI_array.hh" + +#include "DNA_mesh_types.h" +#include "DNA_meshdata_types.h" + +#include "BKE_customdata.h" +#include "BKE_mesh.h" +#include "BKE_pointcloud.h" + +#include "node_geometry_util.hh" + +/* Code from the mask modifier in MOD_mask.cc. */ +extern void copy_masked_vertices_to_new_mesh(const Mesh &src_mesh, + Mesh &dst_mesh, + blender::Span vertex_map); +extern void copy_masked_edges_to_new_mesh(const Mesh &src_mesh, + Mesh &dst_mesh, + blender::Span vertex_map, + blender::Span edge_map); +extern void copy_masked_polys_to_new_mesh(const Mesh &src_mesh, + Mesh &dst_mesh, + blender::Span vertex_map, + blender::Span edge_map, + blender::Span masked_poly_indices, + blender::Span new_loop_starts); + +static bNodeSocketTemplate geo_node_delete_geometry_in[] = { + {SOCK_GEOMETRY, N_("Geometry")}, + {SOCK_STRING, N_("Selection")}, + {SOCK_BOOLEAN, N_("Invert")}, + {-1, ""}, +}; + +static bNodeSocketTemplate geo_node_delete_geometry_out[] = { + {SOCK_GEOMETRY, N_("Geometry")}, + {-1, ""}, +}; + +namespace blender::nodes { + +static void delete_point_cloud_selection(const PointCloudComponent &in_component, + const GeoNodeExecParams ¶ms, + PointCloudComponent &out_component) +{ + const bool invert = params.get_input("Invert"); + const std::string selection_name = params.get_input("Selection"); + if (selection_name.empty()) { + return; + } + + const GVArray_Typed selection_attribute = in_component.attribute_get_for_read( + selection_name, ATTR_DOMAIN_POINT, false); + VArray_Span selection{selection_attribute}; + + const int total = selection.count(invert); + if (total == 0) { + out_component.clear(); + return; + } + out_component.replace(BKE_pointcloud_new_nomain(total)); + + /* Invert the inversion, because this deletes the selected points instead of keeping them. */ + copy_point_attributes_based_on_mask(in_component, out_component, selection, !invert); +} + +static void compute_selected_vertices_from_vertex_selection(const VArray &vertex_selection, + const bool invert, + MutableSpan r_vertex_map, + uint *r_num_selected_vertices) +{ + BLI_assert(vertex_selection.size() == r_vertex_map.size()); + + uint num_selected_vertices = 0; + for (const int i : r_vertex_map.index_range()) { + if (vertex_selection[i] != invert) { + r_vertex_map[i] = num_selected_vertices; + num_selected_vertices++; + } + else { + r_vertex_map[i] = -1; + } + } + + *r_num_selected_vertices = num_selected_vertices; +} + +static void compute_selected_edges_from_vertex_selection(const Mesh &mesh, + const VArray &vertex_selection, + const bool invert, + MutableSpan r_edge_map, + uint *r_num_selected_edges) +{ + BLI_assert(mesh.totedge == r_edge_map.size()); + + uint num_selected_edges = 0; + for (const int i : IndexRange(mesh.totedge)) { + const MEdge &edge = mesh.medge[i]; + + /* Only add the edge if both vertices will be in the new mesh. */ + if (vertex_selection[edge.v1] != invert && vertex_selection[edge.v2] != invert) { + r_edge_map[i] = num_selected_edges; + num_selected_edges++; + } + else { + r_edge_map[i] = -1; + } + } + + *r_num_selected_edges = num_selected_edges; +} + +static void compute_selected_polygons_from_vertex_selection(const Mesh &mesh, + const VArray &vertex_selection, + const bool invert, + Vector &r_selected_poly_indices, + Vector &r_loop_starts, + uint *r_num_selected_polys, + uint *r_num_selected_loops) +{ + BLI_assert(mesh.totvert == vertex_selection.size()); + + r_selected_poly_indices.reserve(mesh.totpoly); + r_loop_starts.reserve(mesh.totloop); + + uint num_selected_loops = 0; + for (const int i : IndexRange(mesh.totpoly)) { + const MPoly &poly_src = mesh.mpoly[i]; + + bool all_verts_in_selection = true; + Span loops_src(&mesh.mloop[poly_src.loopstart], poly_src.totloop); + for (const MLoop &loop : loops_src) { + if (vertex_selection[loop.v] == invert) { + all_verts_in_selection = false; + break; + } + } + + if (all_verts_in_selection) { + r_selected_poly_indices.append_unchecked(i); + r_loop_starts.append_unchecked(num_selected_loops); + num_selected_loops += poly_src.totloop; + } + } + + *r_num_selected_polys = r_selected_poly_indices.size(); + *r_num_selected_loops = num_selected_loops; +} + +/** + * Checks for every edge if it is in `edge_selection`. If it is, then the two vertices of the edge + * are kept along with the edge. + */ +static void compute_selected_vertices_and_edges_from_edge_selection( + const Mesh &mesh, + const VArray &edge_selection, + const bool invert, + MutableSpan r_vertex_map, + MutableSpan r_edge_map, + uint *r_num_selected_vertices, + uint *r_num_selected_edges) +{ + BLI_assert(mesh.totedge == edge_selection.size()); + + uint num_selected_edges = 0; + uint num_selected_vertices = 0; + for (const int i : IndexRange(mesh.totedge)) { + const MEdge &edge = mesh.medge[i]; + if (edge_selection[i] != invert) { + r_edge_map[i] = num_selected_edges; + num_selected_edges++; + if (r_vertex_map[edge.v1] == -1) { + r_vertex_map[edge.v1] = num_selected_vertices; + num_selected_vertices++; + } + if (r_vertex_map[edge.v2] == -1) { + r_vertex_map[edge.v2] = num_selected_vertices; + num_selected_vertices++; + } + } + else { + r_edge_map[i] = -1; + } + } + + *r_num_selected_vertices = num_selected_vertices; + *r_num_selected_edges = num_selected_edges; +} + +/** + * Checks for every polygon if all the edges are in `edge_selection`. If they are, then that + * polygon is kept. + */ +static void compute_selected_polygons_from_edge_selection(const Mesh &mesh, + const VArray &edge_selection, + const bool invert, + Vector &r_selected_poly_indices, + Vector &r_loop_starts, + uint *r_num_selected_polys, + uint *r_num_selected_loops) +{ + r_selected_poly_indices.reserve(mesh.totpoly); + r_loop_starts.reserve(mesh.totloop); + + uint num_selected_loops = 0; + for (const int i : IndexRange(mesh.totpoly)) { + const MPoly &poly_src = mesh.mpoly[i]; + + bool all_edges_in_selection = true; + Span loops_src(&mesh.mloop[poly_src.loopstart], poly_src.totloop); + for (const MLoop &loop : loops_src) { + if (edge_selection[loop.e] == invert) { + all_edges_in_selection = false; + break; + } + } + + if (all_edges_in_selection) { + r_selected_poly_indices.append_unchecked(i); + r_loop_starts.append_unchecked(num_selected_loops); + num_selected_loops += poly_src.totloop; + } + } + + *r_num_selected_polys = r_selected_poly_indices.size(); + *r_num_selected_loops = num_selected_loops; +} + +/** + * Checks for every vertex if it is in `vertex_selection`. The polygons and edges are kept if all + * vertices of that polygon or edge are in the selection. + */ +static void compute_selected_mesh_data_from_vertex_selection(const Mesh &mesh, + const VArray &vertex_selection, + const bool invert, + MutableSpan r_vertex_map, + MutableSpan r_edge_map, + Vector &r_selected_poly_indices, + Vector &r_loop_starts, + uint *r_num_selected_vertices, + uint *r_num_selected_edges, + uint *r_num_selected_polys, + uint *r_num_selected_loops) +{ + compute_selected_vertices_from_vertex_selection( + vertex_selection, invert, r_vertex_map, r_num_selected_vertices); + + compute_selected_edges_from_vertex_selection( + mesh, vertex_selection, invert, r_edge_map, r_num_selected_edges); + + compute_selected_polygons_from_vertex_selection(mesh, + vertex_selection, + invert, + r_selected_poly_indices, + r_loop_starts, + r_num_selected_polys, + r_num_selected_loops); +} + +/** + * Checks for every edge if it is in `edge_selection`. If it is, the vertices belonging to + * that edge are kept as well. The polygons are kept if all edges are in the selection. + */ +static void compute_selected_mesh_data_from_edge_selection(const Mesh &mesh, + const VArray &edge_selection, + const bool invert, + MutableSpan r_vertex_map, + MutableSpan r_edge_map, + Vector &r_selected_poly_indices, + Vector &r_loop_starts, + uint *r_num_selected_vertices, + uint *r_num_selected_edges, + uint *r_num_selected_polys, + uint *r_num_selected_loops) +{ + r_vertex_map.fill(-1); + compute_selected_vertices_and_edges_from_edge_selection(mesh, + edge_selection, + invert, + r_vertex_map, + r_edge_map, + r_num_selected_vertices, + r_num_selected_edges); + compute_selected_polygons_from_edge_selection(mesh, + edge_selection, + invert, + r_selected_poly_indices, + r_loop_starts, + r_num_selected_polys, + r_num_selected_loops); +} + +/** + * Checks for every polygon if it is in `poly_selection`. If it is, the edges and vertices + * belonging to that polygon are kept as well. + */ +static void compute_selected_mesh_data_from_poly_selection(const Mesh &mesh, + const VArray &poly_selection, + const bool invert, + MutableSpan r_vertex_map, + MutableSpan r_edge_map, + Vector &r_selected_poly_indices, + Vector &r_loop_starts, + uint *r_num_selected_vertices, + uint *r_num_selected_edges, + uint *r_num_selected_polys, + uint *r_num_selected_loops) +{ + BLI_assert(mesh.totpoly == poly_selection.size()); + BLI_assert(mesh.totedge == r_edge_map.size()); + r_vertex_map.fill(-1); + r_edge_map.fill(-1); + + r_selected_poly_indices.reserve(mesh.totpoly); + r_loop_starts.reserve(mesh.totloop); + + uint num_selected_loops = 0; + uint num_selected_vertices = 0; + uint num_selected_edges = 0; + for (const int i : IndexRange(mesh.totpoly)) { + const MPoly &poly_src = mesh.mpoly[i]; + /* We keep this one. */ + if (poly_selection[i] != invert) { + r_selected_poly_indices.append_unchecked(i); + r_loop_starts.append_unchecked(num_selected_loops); + num_selected_loops += poly_src.totloop; + + /* Add the vertices and the edges. */ + Span loops_src(&mesh.mloop[poly_src.loopstart], poly_src.totloop); + for (const MLoop &loop : loops_src) { + /* Check first if it has not yet been added. */ + if (r_vertex_map[loop.v] == -1) { + r_vertex_map[loop.v] = num_selected_vertices; + num_selected_vertices++; + } + if (r_edge_map[loop.e] == -1) { + r_edge_map[loop.e] = num_selected_edges; + num_selected_edges++; + } + } + } + } + *r_num_selected_vertices = num_selected_vertices; + *r_num_selected_edges = num_selected_edges; + *r_num_selected_polys = r_selected_poly_indices.size(); + *r_num_selected_loops = num_selected_loops; +} + +using FillMapsFunction = void (*)(const Mesh &mesh, + const VArray &selection, + const bool invert, + MutableSpan r_vertex_map, + MutableSpan r_edge_map, + Vector &r_selected_poly_indices, + Vector &r_loop_starts, + uint *r_num_selected_vertices, + uint *r_num_selected_edges, + uint *r_num_selected_polys, + uint *r_num_selected_loops); + +/** + * Delete the parts of the mesh that are in the selection. The `fill_maps_function` + * depends on the selection type: vertices, edges or faces. + */ +static Mesh *delete_mesh_selection(const Mesh &mesh_in, + const VArray &selection, + const bool invert, + FillMapsFunction fill_maps_function) +{ + Array vertex_map(mesh_in.totvert); + uint num_selected_vertices; + + Array edge_map(mesh_in.totedge); + uint num_selected_edges; + + Vector selected_poly_indices; + Vector new_loop_starts; + uint num_selected_polys; + uint num_selected_loops; + + /* Fill all the maps based on the selection. We delete everything + * in the selection instead of keeping it, so we need to invert it. */ + fill_maps_function(mesh_in, + selection, + !invert, + vertex_map, + edge_map, + selected_poly_indices, + new_loop_starts, + &num_selected_vertices, + &num_selected_edges, + &num_selected_polys, + &num_selected_loops); + + Mesh *result = BKE_mesh_new_nomain_from_template(&mesh_in, + num_selected_vertices, + num_selected_edges, + 0, + num_selected_loops, + num_selected_polys); + + /* Copy the selected parts of the mesh over to the new mesh. */ + copy_masked_vertices_to_new_mesh(mesh_in, *result, vertex_map); + copy_masked_edges_to_new_mesh(mesh_in, *result, vertex_map, edge_map); + copy_masked_polys_to_new_mesh( + 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; + + return result; +} + +static AttributeDomain get_mesh_selection_domain(MeshComponent &component, const StringRef name) +{ + std::optional selection_attribute = component.attribute_get_meta_data(name); + if (!selection_attribute) { + /* The node will not do anything in this case, but this function must return something. */ + return ATTR_DOMAIN_POINT; + } + + /* Corners can't be deleted separately, so interpolate corner attributes + * to the face domain. Note that this choice is somewhat arbitrary. */ + if (selection_attribute->domain == ATTR_DOMAIN_CORNER) { + return ATTR_DOMAIN_FACE; + } + + return selection_attribute->domain; +} + +static void delete_mesh_selection(MeshComponent &component, + const GeoNodeExecParams ¶ms, + const Mesh &mesh_in) +{ + const bool invert_selection = params.get_input("Invert"); + const std::string selection_name = params.get_input("Selection"); + if (selection_name.empty()) { + return; + } + /* Figure out the best domain to use. */ + const AttributeDomain selection_domain = get_mesh_selection_domain(component, selection_name); + + /* This already checks if the attribute exists, and displays a warning in that case. */ + GVArray_Typed selection = params.get_input_attribute( + "Selection", component, selection_domain, false); + + /* Check if there is anything to delete. */ + bool delete_nothing = true; + for (const int i : selection.index_range()) { + if (selection[i] != invert_selection) { + delete_nothing = false; + break; + } + } + if (delete_nothing) { + return; + } + + Mesh *mesh_out; + switch (selection_domain) { + case ATTR_DOMAIN_POINT: + mesh_out = delete_mesh_selection( + mesh_in, selection, invert_selection, compute_selected_mesh_data_from_vertex_selection); + break; + case ATTR_DOMAIN_EDGE: + mesh_out = delete_mesh_selection( + mesh_in, selection, invert_selection, compute_selected_mesh_data_from_edge_selection); + break; + case ATTR_DOMAIN_FACE: + mesh_out = delete_mesh_selection( + mesh_in, selection, invert_selection, compute_selected_mesh_data_from_poly_selection); + break; + default: + BLI_assert_unreachable(); + break; + } + component.replace_mesh_but_keep_vertex_group_names(mesh_out); +} + +static void geo_node_delete_geometry_exec(GeoNodeExecParams params) +{ + GeometrySet geometry_set = params.extract_input("Geometry"); + geometry_set = bke::geometry_set_realize_instances(geometry_set); + + GeometrySet out_set(geometry_set); + if (geometry_set.has()) { + delete_point_cloud_selection(*geometry_set.get_component_for_read(), + params, + out_set.get_component_for_write()); + } + if (geometry_set.has()) { + delete_mesh_selection(out_set.get_component_for_write(), + params, + *geometry_set.get_mesh_for_read()); + } + params.set_output("Geometry", std::move(out_set)); +} + +} // namespace blender::nodes + +void register_node_type_geo_delete_geometry() +{ + static bNodeType ntype; + + geo_node_type_base(&ntype, GEO_NODE_DELETE_GEOMETRY, "Delete Geometry", NODE_CLASS_GEOMETRY, 0); + node_type_socket_templates(&ntype, geo_node_delete_geometry_in, geo_node_delete_geometry_out); + ntype.geometry_node_execute = blender::nodes::geo_node_delete_geometry_exec; + nodeRegisterType(&ntype); +} diff --git a/source/blender/nodes/geometry/nodes/node_geo_point_separate.cc b/source/blender/nodes/geometry/nodes/node_geo_point_separate.cc index 312ca5b8c33..fc04d1e275f 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_point_separate.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_point_separate.cc @@ -52,10 +52,10 @@ static void copy_data_based_on_mask(Span data, } } -static void copy_attributes_based_on_mask(const GeometryComponent &in_component, - GeometryComponent &result_component, - Span masks, - const bool invert) +void copy_point_attributes_based_on_mask(const GeometryComponent &in_component, + GeometryComponent &result_component, + Span masks, + const bool invert) { for (const std::string &name : in_component.attribute_names()) { ReadAttributeLookup attribute = in_component.attribute_try_get_for_read(name); @@ -118,7 +118,7 @@ static void separate_points_from_component(const GeometryComponent &in_component create_component_points(out_component, total); - copy_attributes_based_on_mask(in_component, out_component, masks, invert); + copy_point_attributes_based_on_mask(in_component, out_component, masks, invert); } static GeometrySet separate_geometry_set(const GeometrySet &set_in, -- cgit v1.2.3 From 6b5bbd22d9f8da025697f9078cf98a07e4e5ac99 Mon Sep 17 00:00:00 2001 From: Hans Goudey Date: Tue, 1 Jun 2021 17:51:21 -0400 Subject: Cleanup: Avoid duplicating node input retrieval Pass the selection name and the invert argument to each component instead of retrieving them every time. --- .../geometry/nodes/node_geo_delete_geometry.cc | 51 +++++++++++----------- 1 file changed, 26 insertions(+), 25 deletions(-) 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 9044081de90..4769126fa3c 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_delete_geometry.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_delete_geometry.cc @@ -22,6 +22,7 @@ #include "BKE_customdata.h" #include "BKE_mesh.h" #include "BKE_pointcloud.h" +#include "BKE_spline.hh" #include "node_geometry_util.hh" @@ -55,15 +56,10 @@ static bNodeSocketTemplate geo_node_delete_geometry_out[] = { namespace blender::nodes { static void delete_point_cloud_selection(const PointCloudComponent &in_component, - const GeoNodeExecParams ¶ms, - PointCloudComponent &out_component) + PointCloudComponent &out_component, + const StringRef selection_name, + const bool invert) { - const bool invert = params.get_input("Invert"); - const std::string selection_name = params.get_input("Selection"); - if (selection_name.empty()) { - return; - } - const GVArray_Typed selection_attribute = in_component.attribute_get_for_read( selection_name, ATTR_DOMAIN_POINT, false); VArray_Span selection{selection_attribute}; @@ -444,25 +440,21 @@ static AttributeDomain get_mesh_selection_domain(MeshComponent &component, const } static void delete_mesh_selection(MeshComponent &component, - const GeoNodeExecParams ¶ms, - const Mesh &mesh_in) + const Mesh &mesh_in, + const StringRef selection_name, + const bool invert) { - const bool invert_selection = params.get_input("Invert"); - const std::string selection_name = params.get_input("Selection"); - if (selection_name.empty()) { - return; - } /* Figure out the best domain to use. */ const AttributeDomain selection_domain = get_mesh_selection_domain(component, selection_name); /* This already checks if the attribute exists, and displays a warning in that case. */ - GVArray_Typed selection = params.get_input_attribute( - "Selection", component, selection_domain, false); + GVArray_Typed selection = component.attribute_get_for_read( + selection_name, selection_domain, false); /* Check if there is anything to delete. */ bool delete_nothing = true; for (const int i : selection.index_range()) { - if (selection[i] != invert_selection) { + if (selection[i] != invert) { delete_nothing = false; break; } @@ -475,15 +467,15 @@ static void delete_mesh_selection(MeshComponent &component, switch (selection_domain) { case ATTR_DOMAIN_POINT: mesh_out = delete_mesh_selection( - mesh_in, selection, invert_selection, compute_selected_mesh_data_from_vertex_selection); + mesh_in, selection, invert, compute_selected_mesh_data_from_vertex_selection); break; case ATTR_DOMAIN_EDGE: mesh_out = delete_mesh_selection( - mesh_in, selection, invert_selection, compute_selected_mesh_data_from_edge_selection); + mesh_in, selection, invert, compute_selected_mesh_data_from_edge_selection); break; case ATTR_DOMAIN_FACE: mesh_out = delete_mesh_selection( - mesh_in, selection, invert_selection, compute_selected_mesh_data_from_poly_selection); + mesh_in, selection, invert, compute_selected_mesh_data_from_poly_selection); break; default: BLI_assert_unreachable(); @@ -497,17 +489,26 @@ static void geo_node_delete_geometry_exec(GeoNodeExecParams params) GeometrySet geometry_set = params.extract_input("Geometry"); geometry_set = bke::geometry_set_realize_instances(geometry_set); + const bool invert = params.extract_input("Invert"); + const std::string selection_name = params.extract_input("Selection"); + if (selection_name.empty()) { + return; + } + GeometrySet out_set(geometry_set); if (geometry_set.has()) { delete_point_cloud_selection(*geometry_set.get_component_for_read(), - params, - out_set.get_component_for_write()); + out_set.get_component_for_write(), + selection_name, + invert); } if (geometry_set.has()) { delete_mesh_selection(out_set.get_component_for_write(), - params, - *geometry_set.get_mesh_for_read()); + *geometry_set.get_mesh_for_read(), + selection_name, + invert); } + params.set_output("Geometry", std::move(out_set)); } -- cgit v1.2.3 From 711ddea60e3d0985d6d7c44024debb72fbae985d Mon Sep 17 00:00:00 2001 From: Hans Goudey Date: Tue, 1 Jun 2021 23:50:23 -0400 Subject: Fix assert with geometry node output The previous commit (my own) returned early without providing a value for the node's output geometry set, which is required. --- source/blender/nodes/geometry/nodes/node_geo_delete_geometry.cc | 1 + 1 file changed, 1 insertion(+) 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 4769126fa3c..4692cef6616 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_delete_geometry.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_delete_geometry.cc @@ -492,6 +492,7 @@ static void geo_node_delete_geometry_exec(GeoNodeExecParams params) const bool invert = params.extract_input("Invert"); const std::string selection_name = params.extract_input("Selection"); if (selection_name.empty()) { + params.set_output("Geometry", std::move(geometry_set)); return; } -- cgit v1.2.3 From b5a883fef980208298fbcaaca04732b58458b3b8 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Wed, 2 Jun 2021 17:04:21 +1000 Subject: Cleanup: spelling in comments --- source/blender/blenkernel/intern/lib_id.c | 2 +- source/blender/compositor/intern/COM_NodeOperation.h | 4 ++-- source/blender/draw/engines/overlay/overlay_edit_mesh.c | 4 ++-- .../draw/intern/draw_cache_extract_mesh_extractors.c | 16 ++++++++-------- 4 files changed, 13 insertions(+), 13 deletions(-) diff --git a/source/blender/blenkernel/intern/lib_id.c b/source/blender/blenkernel/intern/lib_id.c index 490abe05169..f26b85338f0 100644 --- a/source/blender/blenkernel/intern/lib_id.c +++ b/source/blender/blenkernel/intern/lib_id.c @@ -1714,7 +1714,7 @@ bool BKE_id_new_name_validate(ListBase *lb, ID *id, const char *tname, const boo bool result = false; char name[MAX_ID_NAME - 2]; - /* If library, don't rename (unless explicitely required), but do ensure proper sorting. */ + /* If library, don't rename (unless explicitly required), but do ensure proper sorting. */ if (!do_linked_data && ID_IS_LINKED(id)) { id_sort_by_name(lb, id, NULL); diff --git a/source/blender/compositor/intern/COM_NodeOperation.h b/source/blender/compositor/intern/COM_NodeOperation.h index 01068c7f812..11b293a400f 100644 --- a/source/blender/compositor/intern/COM_NodeOperation.h +++ b/source/blender/compositor/intern/COM_NodeOperation.h @@ -192,8 +192,8 @@ struct NodeOperationFlags { bool open_cl : 1; /** - * TODO: Remove this flag and SingleThreadedOperation if tiled implemention is removed. - * Full-frame implemention doesn't need it. + * TODO: Remove this flag and #SingleThreadedOperation if tiled implementation is removed. + * Full-frame implementation doesn't need it. */ bool single_threaded : 1; diff --git a/source/blender/draw/engines/overlay/overlay_edit_mesh.c b/source/blender/draw/engines/overlay/overlay_edit_mesh.c index 40a9dbe01c0..7639911286f 100644 --- a/source/blender/draw/engines/overlay/overlay_edit_mesh.c +++ b/source/blender/draw/engines/overlay/overlay_edit_mesh.c @@ -149,7 +149,7 @@ void OVERLAY_edit_mesh_cache_init(OVERLAY_Data *vedata) DRWState state_common = DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_LESS_EQUAL | DRW_STATE_BLEND_ALPHA; /* Faces */ - /* Cage geom needs to be offsetted to avoid Z-fighting. */ + /* Cage geom needs an offset applied to avoid Z-fighting. */ for (int j = 0; j < 2; j++) { DRWPass **edit_face_ps = (j == 0) ? &psl->edit_mesh_faces_ps[i] : &psl->edit_mesh_faces_cage_ps[i]; @@ -197,7 +197,7 @@ void OVERLAY_edit_mesh_cache_init(OVERLAY_Data *vedata) grp = pd->edit_mesh_skin_roots_grp[i] = DRW_shgroup_create(sh, psl->edit_mesh_verts_ps[i]); DRW_shgroup_uniform_block(grp, "globalsBlock", G_draw.block_ubo); } - /* Facedots */ + /* Face-dots */ if (select_face && show_face_dots) { sh = OVERLAY_shader_edit_mesh_facedot(); grp = pd->edit_mesh_facedots_grp[i] = DRW_shgroup_create(sh, psl->edit_mesh_verts_ps[i]); diff --git a/source/blender/draw/intern/draw_cache_extract_mesh_extractors.c b/source/blender/draw/intern/draw_cache_extract_mesh_extractors.c index 324ebd2ec38..489974a79da 100644 --- a/source/blender/draw/intern/draw_cache_extract_mesh_extractors.c +++ b/source/blender/draw/intern/draw_cache_extract_mesh_extractors.c @@ -549,7 +549,7 @@ const MeshExtract extract_points = {.init = extract_points_init, /** \} */ /* ---------------------------------------------------------------------- */ -/** \name Extract Facedots Indices +/** \name Extract Face-dots Indices * \{ */ static void *extract_fdots_init(const MeshRenderData *mr, @@ -1098,7 +1098,7 @@ const MeshExtract extract_edituv_points = { /** \} */ /* ---------------------------------------------------------------------- */ -/** \name Extract Edit UV Facedots Indices +/** \name Extract Edit UV Face-dots Indices * \{ */ static void *extract_edituv_fdots_init(const MeshRenderData *mr, @@ -4044,7 +4044,7 @@ const MeshExtract extract_mesh_analysis = { /** \} */ /* ---------------------------------------------------------------------- */ -/** \name Extract Facedots positions +/** \name Extract Face-dots positions * \{ */ static void *extract_fdots_pos_init(const MeshRenderData *mr, @@ -4124,7 +4124,7 @@ const MeshExtract extract_fdots_pos = { /** \} */ /* ---------------------------------------------------------------------- */ -/** \name Extract Facedots Normal and edit flag +/** \name Extract Face-dots Normal and edit flag * \{ */ #define NOR_AND_FLAG_DEFAULT 0 #define NOR_AND_FLAG_SELECT 1 @@ -4206,7 +4206,7 @@ const MeshExtract extract_fdots_nor = { /** \} */ /* ---------------------------------------------------------------------- */ -/** \name Extract Facedots High Quality Normal and edit flag +/** \name Extract Face-dots High Quality Normal and edit flag * \{ */ static void *extract_fdots_nor_hq_init(const MeshRenderData *mr, struct MeshBatchCache *UNUSED(cache), @@ -4283,7 +4283,7 @@ const MeshExtract extract_fdots_nor_hq = { /** \} */ /* ---------------------------------------------------------------------- */ -/** \name Extract Facedots UV +/** \name Extract Face-dots UV * \{ */ typedef struct MeshExtract_FdotUV_Data { @@ -4382,7 +4382,7 @@ const MeshExtract extract_fdots_uv = { /** \} */ /* ---------------------------------------------------------------------- */ -/** \name Extract Facedots Edit UV flag +/** \name Extract Face-dots Edit UV flag * \{ */ typedef struct MeshExtract_EditUVFdotData_Data { @@ -4745,4 +4745,4 @@ const MeshExtract extract_fdot_idx = { .iter_poly_mesh = extract_fdot_idx_iter_poly_mesh, .data_type = 0, .use_threading = true, - .mesh_buffer_offset = offsetof(MeshBufferCache, vbo.fdot_idx)}; \ No newline at end of file + .mesh_buffer_offset = offsetof(MeshBufferCache, vbo.fdot_idx)}; -- cgit v1.2.3 From 3b3742c75fb0960997cb28742c0879412004358d Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Wed, 2 Jun 2021 17:06:12 +1000 Subject: Cleanup: trailing commas to avoid right shift This matches most declarations already in this file. --- .../intern/draw_cache_extract_mesh_extractors.c | 191 ++++++++++++--------- 1 file changed, 107 insertions(+), 84 deletions(-) diff --git a/source/blender/draw/intern/draw_cache_extract_mesh_extractors.c b/source/blender/draw/intern/draw_cache_extract_mesh_extractors.c index 489974a79da..a806632c18d 100644 --- a/source/blender/draw/intern/draw_cache_extract_mesh_extractors.c +++ b/source/blender/draw/intern/draw_cache_extract_mesh_extractors.c @@ -242,13 +242,15 @@ static void extract_tris_finish(const MeshRenderData *mr, MEM_freeN(data); } -const MeshExtract extract_tris = {.init = extract_tris_init, - .iter_looptri_bm = extract_tris_iter_looptri_bm, - .iter_looptri_mesh = extract_tris_iter_looptri_mesh, - .finish = extract_tris_finish, - .data_type = 0, - .use_threading = false, - .mesh_buffer_offset = offsetof(MeshBufferCache, ibo.tris)}; +const MeshExtract extract_tris = { + .init = extract_tris_init, + .iter_looptri_bm = extract_tris_iter_looptri_bm, + .iter_looptri_mesh = extract_tris_iter_looptri_mesh, + .finish = extract_tris_finish, + .data_type = 0, + .use_threading = false, + .mesh_buffer_offset = offsetof(MeshBufferCache, ibo.tris), +}; /** \} */ @@ -369,15 +371,17 @@ static void extract_lines_finish(const MeshRenderData *UNUSED(mr), MEM_freeN(elb); } -const MeshExtract extract_lines = {.init = extract_lines_init, - .iter_poly_bm = extract_lines_iter_poly_bm, - .iter_poly_mesh = extract_lines_iter_poly_mesh, - .iter_ledge_bm = extract_lines_iter_ledge_bm, - .iter_ledge_mesh = extract_lines_iter_ledge_mesh, - .finish = extract_lines_finish, - .data_type = 0, - .use_threading = false, - .mesh_buffer_offset = offsetof(MeshBufferCache, ibo.lines)}; +const MeshExtract extract_lines = { + .init = extract_lines_init, + .iter_poly_bm = extract_lines_iter_poly_bm, + .iter_poly_mesh = extract_lines_iter_poly_mesh, + .iter_ledge_bm = extract_lines_iter_ledge_bm, + .iter_ledge_mesh = extract_lines_iter_ledge_mesh, + .finish = extract_lines_finish, + .data_type = 0, + .use_threading = false, + .mesh_buffer_offset = offsetof(MeshBufferCache, ibo.lines), +}; /** \} */ @@ -534,17 +538,19 @@ static void extract_points_finish(const MeshRenderData *UNUSED(mr), MEM_freeN(elb); } -const MeshExtract extract_points = {.init = extract_points_init, - .iter_poly_bm = extract_points_iter_poly_bm, - .iter_poly_mesh = extract_points_iter_poly_mesh, - .iter_ledge_bm = extract_points_iter_ledge_bm, - .iter_ledge_mesh = extract_points_iter_ledge_mesh, - .iter_lvert_bm = extract_points_iter_lvert_bm, - .iter_lvert_mesh = extract_points_iter_lvert_mesh, - .finish = extract_points_finish, - .data_type = 0, - .use_threading = false, - .mesh_buffer_offset = offsetof(MeshBufferCache, ibo.points)}; +const MeshExtract extract_points = { + .init = extract_points_init, + .iter_poly_bm = extract_points_iter_poly_bm, + .iter_poly_mesh = extract_points_iter_poly_mesh, + .iter_ledge_bm = extract_points_iter_ledge_bm, + .iter_ledge_mesh = extract_points_iter_ledge_mesh, + .iter_lvert_bm = extract_points_iter_lvert_bm, + .iter_lvert_mesh = extract_points_iter_lvert_mesh, + .finish = extract_points_finish, + .data_type = 0, + .use_threading = false, + .mesh_buffer_offset = offsetof(MeshBufferCache, ibo.points), +}; /** \} */ @@ -613,13 +619,15 @@ static void extract_fdots_finish(const MeshRenderData *UNUSED(mr), MEM_freeN(elb); } -const MeshExtract extract_fdots = {.init = extract_fdots_init, - .iter_poly_bm = extract_fdots_iter_poly_bm, - .iter_poly_mesh = extract_fdots_iter_poly_mesh, - .finish = extract_fdots_finish, - .data_type = 0, - .use_threading = false, - .mesh_buffer_offset = offsetof(MeshBufferCache, ibo.fdots)}; +const MeshExtract extract_fdots = { + .init = extract_fdots_init, + .iter_poly_bm = extract_fdots_iter_poly_bm, + .iter_poly_mesh = extract_fdots_iter_poly_mesh, + .finish = extract_fdots_finish, + .data_type = 0, + .use_threading = false, + .mesh_buffer_offset = offsetof(MeshBufferCache, ibo.fdots), +}; /** \} */ @@ -1354,17 +1362,19 @@ static void extract_pos_nor_finish(const MeshRenderData *UNUSED(mr), MEM_freeN(data); } -const MeshExtract extract_pos_nor = {.init = extract_pos_nor_init, - .iter_poly_bm = extract_pos_nor_iter_poly_bm, - .iter_poly_mesh = extract_pos_nor_iter_poly_mesh, - .iter_ledge_bm = extract_pos_nor_iter_ledge_bm, - .iter_ledge_mesh = extract_pos_nor_iter_ledge_mesh, - .iter_lvert_bm = extract_pos_nor_iter_lvert_bm, - .iter_lvert_mesh = extract_pos_nor_iter_lvert_mesh, - .finish = extract_pos_nor_finish, - .data_type = 0, - .use_threading = true, - .mesh_buffer_offset = offsetof(MeshBufferCache, vbo.pos_nor)}; +const MeshExtract extract_pos_nor = { + .init = extract_pos_nor_init, + .iter_poly_bm = extract_pos_nor_iter_poly_bm, + .iter_poly_mesh = extract_pos_nor_iter_poly_mesh, + .iter_ledge_bm = extract_pos_nor_iter_ledge_bm, + .iter_ledge_mesh = extract_pos_nor_iter_ledge_mesh, + .iter_lvert_bm = extract_pos_nor_iter_lvert_bm, + .iter_lvert_mesh = extract_pos_nor_iter_lvert_mesh, + .finish = extract_pos_nor_finish, + .data_type = 0, + .use_threading = true, + .mesh_buffer_offset = offsetof(MeshBufferCache, vbo.pos_nor), +}; /** \} */ @@ -1638,12 +1648,14 @@ static void extract_lnor_hq_iter_poly_mesh(const MeshRenderData *mr, } } -const MeshExtract extract_lnor_hq = {.init = extract_lnor_hq_init, - .iter_poly_bm = extract_lnor_hq_iter_poly_bm, - .iter_poly_mesh = extract_lnor_hq_iter_poly_mesh, - .data_type = MR_DATA_LOOP_NOR, - .use_threading = true, - .mesh_buffer_offset = offsetof(MeshBufferCache, vbo.lnor)}; +const MeshExtract extract_lnor_hq = { + .init = extract_lnor_hq_init, + .iter_poly_bm = extract_lnor_hq_iter_poly_bm, + .iter_poly_mesh = extract_lnor_hq_iter_poly_mesh, + .data_type = MR_DATA_LOOP_NOR, + .use_threading = true, + .mesh_buffer_offset = offsetof(MeshBufferCache, vbo.lnor), +}; /** \} */ /* ---------------------------------------------------------------------- */ @@ -1727,12 +1739,14 @@ static void extract_lnor_iter_poly_mesh(const MeshRenderData *mr, } } -const MeshExtract extract_lnor = {.init = extract_lnor_init, - .iter_poly_bm = extract_lnor_iter_poly_bm, - .iter_poly_mesh = extract_lnor_iter_poly_mesh, - .data_type = MR_DATA_LOOP_NOR, - .use_threading = true, - .mesh_buffer_offset = offsetof(MeshBufferCache, vbo.lnor)}; +const MeshExtract extract_lnor = { + .init = extract_lnor_init, + .iter_poly_bm = extract_lnor_iter_poly_bm, + .iter_poly_mesh = extract_lnor_iter_poly_mesh, + .data_type = MR_DATA_LOOP_NOR, + .use_threading = true, + .mesh_buffer_offset = offsetof(MeshBufferCache, vbo.lnor), +}; /** \} */ @@ -1824,10 +1838,12 @@ static void *extract_uv_init(const MeshRenderData *mr, struct MeshBatchCache *ca return NULL; } -const MeshExtract extract_uv = {.init = extract_uv_init, - .data_type = 0, - .use_threading = false, - .mesh_buffer_offset = offsetof(MeshBufferCache, vbo.uv)}; +const MeshExtract extract_uv = { + .init = extract_uv_init, + .data_type = 0, + .use_threading = false, + .mesh_buffer_offset = offsetof(MeshBufferCache, vbo.uv), +}; /** \} */ @@ -2013,11 +2029,12 @@ static void *extract_tan_init(const MeshRenderData *mr, struct MeshBatchCache *c return NULL; } -const MeshExtract extract_tan = {.init = extract_tan_init, - .data_type = MR_DATA_POLY_NOR | MR_DATA_TAN_LOOP_NOR | - MR_DATA_LOOPTRI, - .use_threading = false, - .mesh_buffer_offset = offsetof(MeshBufferCache, vbo.tan)}; +const MeshExtract extract_tan = { + .init = extract_tan_init, + .data_type = MR_DATA_POLY_NOR | MR_DATA_TAN_LOOP_NOR | MR_DATA_LOOPTRI, + .use_threading = false, + .mesh_buffer_offset = offsetof(MeshBufferCache, vbo.tan), +}; /** \} */ @@ -2279,10 +2296,12 @@ static void *extract_vcol_init(const MeshRenderData *mr, struct MeshBatchCache * return NULL; } -const MeshExtract extract_vcol = {.init = extract_vcol_init, - .data_type = 0, - .use_threading = false, - .mesh_buffer_offset = offsetof(MeshBufferCache, vbo.vcol)}; +const MeshExtract extract_vcol = { + .init = extract_vcol_init, + .data_type = 0, + .use_threading = false, + .mesh_buffer_offset = offsetof(MeshBufferCache, vbo.vcol), +}; /** \} */ @@ -2362,13 +2381,15 @@ static void extract_orco_finish(const MeshRenderData *UNUSED(mr), MEM_freeN(data); } -const MeshExtract extract_orco = {.init = extract_orco_init, - .iter_poly_bm = extract_orco_iter_poly_bm, - .iter_poly_mesh = extract_orco_iter_poly_mesh, - .finish = extract_orco_finish, - .data_type = 0, - .use_threading = true, - .mesh_buffer_offset = offsetof(MeshBufferCache, vbo.orco)}; +const MeshExtract extract_orco = { + .init = extract_orco_init, + .iter_poly_bm = extract_orco_iter_poly_bm, + .iter_poly_mesh = extract_orco_iter_poly_mesh, + .finish = extract_orco_finish, + .data_type = 0, + .use_threading = true, + .mesh_buffer_offset = offsetof(MeshBufferCache, vbo.orco), +}; /** \} */ @@ -2717,13 +2738,15 @@ static void extract_weights_finish(const MeshRenderData *UNUSED(mr), MEM_freeN(data); } -const MeshExtract extract_weights = {.init = extract_weights_init, - .iter_poly_bm = extract_weights_iter_poly_bm, - .iter_poly_mesh = extract_weights_iter_poly_mesh, - .finish = extract_weights_finish, - .data_type = 0, - .use_threading = true, - .mesh_buffer_offset = offsetof(MeshBufferCache, vbo.weights)}; +const MeshExtract extract_weights = { + .init = extract_weights_init, + .iter_poly_bm = extract_weights_iter_poly_bm, + .iter_poly_mesh = extract_weights_iter_poly_mesh, + .finish = extract_weights_finish, + .data_type = 0, + .use_threading = true, + .mesh_buffer_offset = offsetof(MeshBufferCache, vbo.weights), +}; /** \} */ -- cgit v1.2.3 From 507c19c0f7a1dc7a46ec8ac19d9e904c9e825a9b Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Wed, 2 Jun 2021 17:15:05 +1000 Subject: Docs: formalize naming for generic callbacks in BKE_callbacks.h Add a doc-string explaining the purpose of each call back and how they should be used. Also add a currently unused callback 'POST_FAIL' that is to be used in cases the action fails - giving script authors, a guarantee that a call to `pre` will always have a matching `post/post_fail` call. - D11422: adds a callback that can use 'post_fail'. - T88696: proposed these conventions. --- source/blender/blenkernel/BKE_callbacks.h | 59 ++++++++++++++++++++++--- source/blender/python/intern/bpy_app_handlers.c | 3 ++ 2 files changed, 57 insertions(+), 5 deletions(-) diff --git a/source/blender/blenkernel/BKE_callbacks.h b/source/blender/blenkernel/BKE_callbacks.h index f04b5e45720..ef2a0ed34a0 100644 --- a/source/blender/blenkernel/BKE_callbacks.h +++ b/source/blender/blenkernel/BKE_callbacks.h @@ -30,11 +30,60 @@ struct Main; struct PointerRNA; /** - * Common suffix uses: - * - ``_PRE/_POST``: - * For handling discrete non-interactive events. - * - ``_INIT/_COMPLETE/_CANCEL``: - * For handling jobs (which may in turn cause other handlers to be called). + Callbacks for One Off Actions + * ============================= + * + * - `{ACTION}` use in cases where only a single callback is required, + * `VERSION_UPDATE` and `RENDER_STATS` for example. + * + * \note avoid single callbacks if there is a chance `PRE/POST` are useful to differentiate + * since renaming callbacks may break Python scripts. + * + * Callbacks for Common Actions + * ============================ + * + * - `{ACTION}_PRE` run before the action. + * - `{ACTION}_POST` run after the action. + * + * Optional Additional Callbacks + * ----------------------------- + * + * - `{ACTION}_INIT` when the handler may manipulate the context used to run the action. + * + * Examples where `INIT` functions may be useful are: + * + * - When rendering, an `INIT` function may change the camera or render settings, + * things which a `PRE` function can't support as this information has already been used. + * - When saving an `INIT` function could temporarily change the preferences. + * + * - `{ACTION}_POST_FAIL` should be included if the action may fail. + * + * Use this so a call to the `PRE` callback always has a matching call to `POST` or `POST_FAIL`. + * + * \note in most cases only `PRE/POST` are required. + * + * Callbacks for Background/Modal Tasks + * ==================================== + * + * - `{ACTION}_INIT` + * - `{ACTION}_COMPLETE` when a background job has finished. + * - `{ACTION}_CANCEL` When a background job is canceled partway through. + * + * While cancellation may be caused by any number of reasons, common causes may include: + * + * - Explicit user cancellation. + * - Exiting Blender. + * - Failure to acquire resources (such as disk-full, out of memory ... etc). + * + * \note `PRE/POST` handlers may be used along side modal task handlers + * as is the case for rendering, where rendering an animation uses modal task handlers, + * rendering a single frame has `PRE/POST` handlers. + * + * Python Access + * ============= + * + * All callbacks here must be exposed via the Python module `bpy.app.handlers`, + * see `bpy_app_handlers.c`. */ typedef enum { BKE_CB_EVT_FRAME_CHANGE_PRE, diff --git a/source/blender/python/intern/bpy_app_handlers.c b/source/blender/python/intern/bpy_app_handlers.c index a0b543097e6..bc05c51414f 100644 --- a/source/blender/python/intern/bpy_app_handlers.c +++ b/source/blender/python/intern/bpy_app_handlers.c @@ -43,6 +43,9 @@ void bpy_app_generic_callback(struct Main *main, static PyTypeObject BlenderAppCbType; +/** + * See `BKE_callbacks.h` #eCbEvent declaration for the policy on naming. + */ static PyStructSequence_Field app_cb_info_fields[] = { {"frame_change_pre", "Called after frame change for playback and rendering, before any data is evaluated for the " -- cgit v1.2.3 From 46447594de3714ef10725e921008e583008cc97e Mon Sep 17 00:00:00 2001 From: Jeroen Bakker Date: Wed, 2 Jun 2021 10:05:39 +0200 Subject: Fix T88567: Cryptomatte only works for the first View Layer. The view layer was always set to 0. This patch increments it. --- source/blender/compositor/nodes/COM_CryptomatteNode.cc | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/source/blender/compositor/nodes/COM_CryptomatteNode.cc b/source/blender/compositor/nodes/COM_CryptomatteNode.cc index 3beb3aa2917..4032a655633 100644 --- a/source/blender/compositor/nodes/COM_CryptomatteNode.cc +++ b/source/blender/compositor/nodes/COM_CryptomatteNode.cc @@ -118,9 +118,9 @@ void CryptomatteNode::input_operations_from_render_source( return; } - const short cryptomatte_layer_id = 0; + short view_layer_id = 0; const std::string prefix = prefix_from_node(context, node); - LISTBASE_FOREACH (ViewLayer *, view_layer, &scene->view_layers) { + LISTBASE_FOREACH_INDEX (ViewLayer *, view_layer, &scene->view_layers, view_layer_id) { RenderLayer *render_layer = RE_GetRenderLayer(render_result, view_layer->name); if (render_layer) { LISTBASE_FOREACH (RenderPass *, render_pass, &render_layer->passes) { @@ -129,7 +129,7 @@ void CryptomatteNode::input_operations_from_render_source( RenderLayersProg *op = new RenderLayersProg( render_pass->name, DataType::Color, render_pass->channels); op->setScene(scene); - op->setLayerId(cryptomatte_layer_id); + op->setLayerId(view_layer_id); op->setRenderData(context.getRenderData()); op->setViewName(context.getViewName()); r_input_operations.append(op); -- cgit v1.2.3