diff options
author | Jacques Lucke <jacques@blender.org> | 2021-06-02 13:17:08 +0300 |
---|---|---|
committer | Jacques Lucke <jacques@blender.org> | 2021-06-02 13:17:08 +0300 |
commit | a9ba86c0469a400d91486f5a42162fa544b9871a (patch) | |
tree | 5c400fa011f17c65d01f901dd09a74912b5dfb50 | |
parent | 842375e1edacc6638dd7bfc3855cafb3fd5a0804 (diff) | |
parent | 46447594de3714ef10725e921008e583008cc97e (diff) |
Merge branch 'master' into temp-geometry-nodes-viewer-node
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 " |