Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJacques Lucke <jacques@blender.org>2021-06-02 13:17:08 +0300
committerJacques Lucke <jacques@blender.org>2021-06-02 13:17:08 +0300
commita9ba86c0469a400d91486f5a42162fa544b9871a (patch)
tree5c400fa011f17c65d01f901dd09a74912b5dfb50
parent842375e1edacc6638dd7bfc3855cafb3fd5a0804 (diff)
parent46447594de3714ef10725e921008e583008cc97e (diff)
Merge branch 'master' into temp-geometry-nodes-viewer-node
-rw-r--r--release/scripts/startup/nodeitems_builtins.py1
-rw-r--r--source/blender/blenkernel/BKE_callbacks.h59
-rw-r--r--source/blender/blenkernel/BKE_node.h3
-rw-r--r--source/blender/blenkernel/intern/lib_id.c2
-rw-r--r--source/blender/blenkernel/intern/lib_override.c8
-rw-r--r--source/blender/blenkernel/intern/node.cc1
-rw-r--r--source/blender/blenkernel/intern/particle_system.c5
-rw-r--r--source/blender/compositor/intern/COM_NodeOperation.h4
-rw-r--r--source/blender/compositor/nodes/COM_CryptomatteNode.cc6
-rw-r--r--source/blender/draw/engines/overlay/overlay_edit_mesh.c4
-rw-r--r--source/blender/draw/intern/draw_cache_extract_mesh_extractors.c207
-rw-r--r--source/blender/editors/space_sequencer/sequencer_buttons.c2
-rw-r--r--source/blender/modifiers/intern/MOD_mask.cc37
-rw-r--r--source/blender/nodes/CMakeLists.txt1
-rw-r--r--source/blender/nodes/NOD_geometry.h1
-rw-r--r--source/blender/nodes/NOD_static_types.h1
-rw-r--r--source/blender/nodes/geometry/node_geometry_util.hh8
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_delete_geometry.cc526
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_point_separate.cc10
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_transform.cc5
-rw-r--r--source/blender/python/intern/bpy_app_handlers.c3
21 files changed, 762 insertions, 132 deletions
diff --git a/release/scripts/startup/nodeitems_builtins.py b/release/scripts/startup/nodeitems_builtins.py
index 6ef80cf3897..eed8b504c1e 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_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/blenkernel/BKE_node.h b/source/blender/blenkernel/BKE_node.h
index 34665806547..daee52028c8 100644
--- a/source/blender/blenkernel/BKE_node.h
+++ b/source/blender/blenkernel/BKE_node.h
@@ -1430,7 +1430,8 @@ 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_VIEWER 1053
+#define GEO_NODE_DELETE_GEOMETRY 1053
+#define GEO_NODE_VIEWER 1054
/** \} */
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/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(
diff --git a/source/blender/blenkernel/intern/node.cc b/source/blender/blenkernel/intern/node.cc
index b2ea0413005..1ca0c82bbfe 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/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);
}
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/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);
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..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,22 +538,24 @@ 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),
+};
/** \} */
/* ---------------------------------------------------------------------- */
-/** \name Extract Facedots Indices
+/** \name Extract Face-dots Indices
* \{ */
static void *extract_fdots_init(const MeshRenderData *mr,
@@ -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),
+};
/** \} */
@@ -1098,7 +1106,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,
@@ -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),
+};
/** \} */
@@ -4044,7 +4067,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 +4147,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 +4229,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 +4306,7 @@ const MeshExtract extract_fdots_nor_hq = {
/** \} */
/* ---------------------------------------------------------------------- */
-/** \name Extract Facedots UV
+/** \name Extract Face-dots UV
* \{ */
typedef struct MeshExtract_FdotUV_Data {
@@ -4382,7 +4405,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 +4768,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)};
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);
}
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<int> vertex_map);
+void copy_masked_edges_to_new_mesh(const Mesh &src_mesh,
+ Mesh &dst_mesh,
+ Span<int> vertex_map,
+ Span<int> edge_map);
+void copy_masked_polys_to_new_mesh(const Mesh &src_mesh,
+ Mesh &dst_mesh,
+ Span<int> vertex_map,
+ Span<int> edge_map,
+ Span<int> masked_poly_indices,
+ Span<int> 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<int> vertex_map)
+void copy_masked_vertices_to_new_mesh(const Mesh &src_mesh, Mesh &dst_mesh, Span<int> 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<int> vertex_map,
- Span<int> edge_map)
+void copy_masked_edges_to_new_mesh(const Mesh &src_mesh,
+ Mesh &dst_mesh,
+ Span<int> vertex_map,
+ Span<int> 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<int> vertex_map,
- Span<int> edge_map,
- Span<int> masked_poly_indices,
- Span<int> new_loop_starts)
+void copy_masked_polys_to_new_mesh(const Mesh &src_mesh,
+ Mesh &dst_mesh,
+ Span<int> vertex_map,
+ Span<int> edge_map,
+ Span<int> masked_poly_indices,
+ Span<int> 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 c93269fb1a9..601edfdd8aa 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 00bead87c6e..e0701ba0e77 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 be45b22a815..bd7d3dda24b 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<bool> 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..4692cef6616
--- /dev/null
+++ b/source/blender/nodes/geometry/nodes/node_geo_delete_geometry.cc
@@ -0,0 +1,526 @@
+/*
+ * 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 "BKE_spline.hh"
+
+#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<int> vertex_map);
+extern void copy_masked_edges_to_new_mesh(const Mesh &src_mesh,
+ Mesh &dst_mesh,
+ blender::Span<int> vertex_map,
+ blender::Span<int> edge_map);
+extern void copy_masked_polys_to_new_mesh(const Mesh &src_mesh,
+ Mesh &dst_mesh,
+ blender::Span<int> vertex_map,
+ blender::Span<int> edge_map,
+ blender::Span<int> masked_poly_indices,
+ blender::Span<int> 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,
+ PointCloudComponent &out_component,
+ const StringRef selection_name,
+ const bool invert)
+{
+ const GVArray_Typed<bool> selection_attribute = in_component.attribute_get_for_read<bool>(
+ selection_name, ATTR_DOMAIN_POINT, false);
+ VArray_Span<bool> 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<bool> &vertex_selection,
+ const bool invert,
+ MutableSpan<int> 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<bool> &vertex_selection,
+ const bool invert,
+ MutableSpan<int> 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<bool> &vertex_selection,
+ const bool invert,
+ Vector<int> &r_selected_poly_indices,
+ Vector<int> &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<MLoop> 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<bool> &edge_selection,
+ const bool invert,
+ MutableSpan<int> r_vertex_map,
+ MutableSpan<int> 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<bool> &edge_selection,
+ const bool invert,
+ Vector<int> &r_selected_poly_indices,
+ Vector<int> &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<MLoop> 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<bool> &vertex_selection,
+ const bool invert,
+ MutableSpan<int> r_vertex_map,
+ MutableSpan<int> r_edge_map,
+ Vector<int> &r_selected_poly_indices,
+ Vector<int> &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<bool> &edge_selection,
+ const bool invert,
+ MutableSpan<int> r_vertex_map,
+ MutableSpan<int> r_edge_map,
+ Vector<int> &r_selected_poly_indices,
+ Vector<int> &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<bool> &poly_selection,
+ const bool invert,
+ MutableSpan<int> r_vertex_map,
+ MutableSpan<int> r_edge_map,
+ Vector<int> &r_selected_poly_indices,
+ Vector<int> &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<MLoop> 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<bool> &selection,
+ const bool invert,
+ MutableSpan<int> r_vertex_map,
+ MutableSpan<int> r_edge_map,
+ Vector<int> &r_selected_poly_indices,
+ Vector<int> &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<bool> &selection,
+ const bool invert,
+ FillMapsFunction fill_maps_function)
+{
+ Array<int> vertex_map(mesh_in.totvert);
+ uint num_selected_vertices;
+
+ Array<int> edge_map(mesh_in.totedge);
+ uint num_selected_edges;
+
+ Vector<int> selected_poly_indices;
+ Vector<int> 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<AttributeMetaData> 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 Mesh &mesh_in,
+ const StringRef selection_name,
+ const bool invert)
+{
+ /* 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<bool> selection = component.attribute_get_for_read<bool>(
+ 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) {
+ 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, compute_selected_mesh_data_from_vertex_selection);
+ break;
+ case ATTR_DOMAIN_EDGE:
+ mesh_out = delete_mesh_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, 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<GeometrySet>("Geometry");
+ geometry_set = bke::geometry_set_realize_instances(geometry_set);
+
+ const bool invert = params.extract_input<bool>("Invert");
+ const std::string selection_name = params.extract_input<std::string>("Selection");
+ if (selection_name.empty()) {
+ params.set_output("Geometry", std::move(geometry_set));
+ return;
+ }
+
+ GeometrySet out_set(geometry_set);
+ if (geometry_set.has<PointCloudComponent>()) {
+ delete_point_cloud_selection(*geometry_set.get_component_for_read<PointCloudComponent>(),
+ out_set.get_component_for_write<PointCloudComponent>(),
+ selection_name,
+ invert);
+ }
+ if (geometry_set.has<MeshComponent>()) {
+ delete_mesh_selection(out_set.get_component_for_write<MeshComponent>(),
+ *geometry_set.get_mesh_for_read(),
+ selection_name,
+ invert);
+ }
+
+ 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<T> data,
}
}
-static void copy_attributes_based_on_mask(const GeometryComponent &in_component,
- GeometryComponent &result_component,
- Span<bool> masks,
- const bool invert)
+void copy_point_attributes_based_on_mask(const GeometryComponent &in_component,
+ GeometryComponent &result_component,
+ Span<bool> 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,
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);
}
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 "