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
path: root/source
diff options
context:
space:
mode:
Diffstat (limited to 'source')
-rw-r--r--source/blender/blenfont/BLF_api.h5
-rw-r--r--source/blender/blenfont/CMakeLists.txt1
-rw-r--r--source/blender/blenfont/intern/blf.c4
-rw-r--r--source/blender/blenfont/intern/blf_default.c16
-rw-r--r--source/blender/blenfont/intern/blf_font.c256
-rw-r--r--source/blender/blenfont/intern/blf_glyph.c493
-rw-r--r--source/blender/blenfont/intern/blf_internal.h14
-rw-r--r--source/blender/blenfont/intern/blf_internal_types.h14
-rw-r--r--source/blender/blenfont/intern/blf_thumbs.c4
-rw-r--r--source/blender/blenkernel/BKE_action.h5
-rw-r--r--source/blender/blenkernel/BKE_asset_catalog.hh4
-rw-r--r--source/blender/blenkernel/BKE_attribute.h13
-rw-r--r--source/blender/blenkernel/BKE_attribute_access.hh63
-rw-r--r--source/blender/blenkernel/BKE_blender_copybuffer.h10
-rw-r--r--source/blender/blenkernel/BKE_blender_version.h6
-rw-r--r--source/blender/blenkernel/BKE_blendfile_link_append.h112
-rw-r--r--source/blender/blenkernel/BKE_brush.h2
-rw-r--r--source/blender/blenkernel/BKE_geometry_set.hh97
-rw-r--r--source/blender/blenkernel/BKE_global.h5
-rw-r--r--source/blender/blenkernel/BKE_gpencil_geom.h5
-rw-r--r--source/blender/blenkernel/BKE_image.h3
-rw-r--r--source/blender/blenkernel/BKE_layer.h2
-rw-r--r--source/blender/blenkernel/BKE_lib_id.h6
-rw-r--r--source/blender/blenkernel/BKE_lib_query.h20
-rw-r--r--source/blender/blenkernel/BKE_lib_remap.h10
-rw-r--r--source/blender/blenkernel/BKE_node.h23
-rw-r--r--source/blender/blenkernel/BKE_spline.hh31
-rw-r--r--source/blender/blenkernel/BKE_volume_to_mesh.hh2
-rw-r--r--source/blender/blenkernel/CMakeLists.txt4
-rw-r--r--source/blender/blenkernel/intern/action.c2
-rw-r--r--source/blender/blenkernel/intern/anim_data.c2
-rw-r--r--source/blender/blenkernel/intern/appdir.c30
-rw-r--r--source/blender/blenkernel/intern/armature.c20
-rw-r--r--source/blender/blenkernel/intern/asset.cc2
-rw-r--r--source/blender/blenkernel/intern/asset_catalog.cc11
-rw-r--r--source/blender/blenkernel/intern/asset_catalog_test.cc23
-rw-r--r--source/blender/blenkernel/intern/asset_library.cc8
-rw-r--r--source/blender/blenkernel/intern/asset_library_service.cc6
-rw-r--r--source/blender/blenkernel/intern/asset_library_service_test.cc2
-rw-r--r--source/blender/blenkernel/intern/attribute_access.cc149
-rw-r--r--source/blender/blenkernel/intern/attribute_access_intern.hh15
-rw-r--r--source/blender/blenkernel/intern/blender.c1
-rw-r--r--source/blender/blenkernel/intern/blender_copybuffer.c40
-rw-r--r--source/blender/blenkernel/intern/blendfile_link_append.c1566
-rw-r--r--source/blender/blenkernel/intern/brush.c7
-rw-r--r--source/blender/blenkernel/intern/collection.c2
-rw-r--r--source/blender/blenkernel/intern/constraint.c2
-rw-r--r--source/blender/blenkernel/intern/curve_eval.cc18
-rw-r--r--source/blender/blenkernel/intern/curve_to_mesh_convert.cc14
-rw-r--r--source/blender/blenkernel/intern/dynamicpaint.c4
-rw-r--r--source/blender/blenkernel/intern/fcurve.c12
-rw-r--r--source/blender/blenkernel/intern/fcurve_driver.c4
-rw-r--r--source/blender/blenkernel/intern/fluid.c2
-rw-r--r--source/blender/blenkernel/intern/geometry_component_curve.cc219
-rw-r--r--source/blender/blenkernel/intern/geometry_component_instances.cc58
-rw-r--r--source/blender/blenkernel/intern/geometry_component_mesh.cc206
-rw-r--r--source/blender/blenkernel/intern/geometry_component_pointcloud.cc9
-rw-r--r--source/blender/blenkernel/intern/geometry_set.cc44
-rw-r--r--source/blender/blenkernel/intern/geometry_set_instances.cc16
-rw-r--r--source/blender/blenkernel/intern/gpencil_geom.cc8
-rw-r--r--source/blender/blenkernel/intern/icons.cc2
-rw-r--r--source/blender/blenkernel/intern/image.c129
-rw-r--r--source/blender/blenkernel/intern/image_gen.c2
-rw-r--r--source/blender/blenkernel/intern/lib_override.c2
-rw-r--r--source/blender/blenkernel/intern/lib_query.c158
-rw-r--r--source/blender/blenkernel/intern/lib_remap.c72
-rw-r--r--source/blender/blenkernel/intern/light.c3
-rw-r--r--source/blender/blenkernel/intern/linestyle.c6
-rw-r--r--source/blender/blenkernel/intern/material.c7
-rw-r--r--source/blender/blenkernel/intern/mesh.cc (renamed from source/blender/blenkernel/intern/mesh.c)361
-rw-r--r--source/blender/blenkernel/intern/mesh_remesh_voxel.cc3
-rw-r--r--source/blender/blenkernel/intern/mesh_runtime.c2
-rw-r--r--source/blender/blenkernel/intern/mesh_sample.cc2
-rw-r--r--source/blender/blenkernel/intern/nla.c4
-rw-r--r--source/blender/blenkernel/intern/node.cc130
-rw-r--r--source/blender/blenkernel/intern/object.cc115
-rw-r--r--source/blender/blenkernel/intern/particle.c3
-rw-r--r--source/blender/blenkernel/intern/pbvh.c2
-rw-r--r--source/blender/blenkernel/intern/scene.c304
-rw-r--r--source/blender/blenkernel/intern/screen.c37
-rw-r--r--source/blender/blenkernel/intern/simulation.cc3
-rw-r--r--source/blender/blenkernel/intern/softbody.c2
-rw-r--r--source/blender/blenkernel/intern/spline_base.cc12
-rw-r--r--source/blender/blenkernel/intern/spline_bezier.cc13
-rw-r--r--source/blender/blenkernel/intern/spline_nurbs.cc16
-rw-r--r--source/blender/blenkernel/intern/spline_poly.cc6
-rw-r--r--source/blender/blenkernel/intern/subsurf_ccg.c2
-rw-r--r--source/blender/blenkernel/intern/text.c2
-rw-r--r--source/blender/blenkernel/intern/texture.c3
-rw-r--r--source/blender/blenkernel/intern/world.c3
-rw-r--r--source/blender/blenlib/BLI_any.hh319
-rw-r--r--source/blender/blenlib/BLI_rect.h4
-rw-r--r--source/blender/blenlib/BLI_serialize.hh19
-rw-r--r--source/blender/blenlib/BLI_virtual_array.hh1078
-rw-r--r--source/blender/blenlib/CMakeLists.txt2
-rw-r--r--source/blender/blenlib/intern/BLI_mempool.c2
-rw-r--r--source/blender/blenlib/intern/string.c8
-rw-r--r--source/blender/blenlib/tests/BLI_any_test.cc108
-rw-r--r--source/blender/blenlib/tests/BLI_virtual_array_test.cc55
-rw-r--r--source/blender/blenloader/BLO_readfile.h4
-rw-r--r--source/blender/blenloader/intern/readblenentry.c1
-rw-r--r--source/blender/blenloader/intern/versioning_300.c78
-rw-r--r--source/blender/blenloader/intern/versioning_common.cc33
-rw-r--r--source/blender/blenloader/intern/versioning_common.h2
-rw-r--r--source/blender/blenloader/intern/versioning_userdef.c17
-rw-r--r--source/blender/blenloader/tests/blendfile_loading_base_test.cc1
-rw-r--r--source/blender/bmesh/operators/bmo_fill_edgeloop.c2
-rw-r--r--source/blender/bmesh/tests/bmesh_core_test.cc6
-rw-r--r--source/blender/compositor/operations/COM_CompositorOperation.cc2
-rw-r--r--source/blender/draw/CMakeLists.txt8
-rw-r--r--source/blender/draw/engines/basic/basic_engine.c119
-rw-r--r--source/blender/draw/engines/basic/basic_private.h (renamed from source/blender/draw/engines/image/image_private.h)44
-rw-r--r--source/blender/draw/engines/basic/basic_shader.c167
-rw-r--r--source/blender/draw/engines/eevee/shaders/ambient_occlusion_lib.glsl4
-rw-r--r--source/blender/draw/engines/eevee/shaders/closure_eval_lib.glsl4
-rw-r--r--source/blender/draw/engines/eevee/shaders/common_utiltex_lib.glsl2
-rw-r--r--source/blender/draw/engines/eevee/shaders/effect_dof_gather_frag.glsl2
-rw-r--r--source/blender/draw/engines/eevee/shaders/effect_dof_reduce_frag.glsl2
-rw-r--r--source/blender/draw/engines/eevee/shaders/effect_reflection_resolve_frag.glsl2
-rw-r--r--source/blender/draw/engines/eevee/shaders/random_lib.glsl2
-rw-r--r--source/blender/draw/engines/eevee/shaders/surface_lib.glsl2
-rw-r--r--source/blender/draw/engines/eevee/shaders/volumetric_lib.glsl2
-rw-r--r--source/blender/draw/engines/gpencil/gpencil_engine.h2
-rw-r--r--source/blender/draw/engines/image/image_drawing_mode.hh153
-rw-r--r--source/blender/draw/engines/image/image_engine.c459
-rw-r--r--source/blender/draw/engines/image/image_engine.cc197
-rw-r--r--source/blender/draw/engines/image/image_engine.h10
-rw-r--r--source/blender/draw/engines/image/image_private.hh196
-rw-r--r--source/blender/draw/engines/image/image_shader.cc (renamed from source/blender/draw/engines/image/image_shader.c)26
-rw-r--r--source/blender/draw/engines/image/image_space_image.hh182
-rw-r--r--source/blender/draw/engines/image/image_space_node.hh138
-rw-r--r--source/blender/draw/engines/workbench/shaders/workbench_effect_dof_frag.glsl2
-rw-r--r--source/blender/draw/intern/draw_manager.c10
-rw-r--r--source/blender/draw/tests/shaders_test.cc18
-rw-r--r--source/blender/editors/animation/anim_channels_defines.c2
-rw-r--r--source/blender/editors/animation/anim_ipo_utils.c16
-rw-r--r--source/blender/editors/animation/anim_motion_paths.c4
-rw-r--r--source/blender/editors/armature/armature_relations.c94
-rw-r--r--source/blender/editors/armature/pose_transform.c6
-rw-r--r--source/blender/editors/asset/ED_asset_list.hh2
-rw-r--r--source/blender/editors/asset/intern/asset_catalog.cc1
-rw-r--r--source/blender/editors/asset/intern/asset_filter.cc1
-rw-r--r--source/blender/editors/asset/intern/asset_handle.cc1
-rw-r--r--source/blender/editors/asset/intern/asset_library_reference_enum.cc1
-rw-r--r--source/blender/editors/asset/intern/asset_list.cc6
-rw-r--r--source/blender/editors/asset/intern/asset_mark_clear.cc5
-rw-r--r--source/blender/editors/asset/intern/asset_ops.cc5
-rw-r--r--source/blender/editors/asset/intern/asset_temp_id_consumer.cc1
-rw-r--r--source/blender/editors/curve/editcurve.c4
-rw-r--r--source/blender/editors/curve/editcurve_paint.c2
-rw-r--r--source/blender/editors/curve/editfont.c4
-rw-r--r--source/blender/editors/gpencil/annotate_paint.c22
-rw-r--r--source/blender/editors/gpencil/gpencil_convert.c2
-rw-r--r--source/blender/editors/gpencil/gpencil_data.c148
-rw-r--r--source/blender/editors/gpencil/gpencil_edit.c12
-rw-r--r--source/blender/editors/gpencil/gpencil_fill.c18
-rw-r--r--source/blender/editors/gpencil/gpencil_intern.h2
-rw-r--r--source/blender/editors/gpencil/gpencil_merge.c3
-rw-r--r--source/blender/editors/gpencil/gpencil_paint.c31
-rw-r--r--source/blender/editors/gpencil/gpencil_primitive.c14
-rw-r--r--source/blender/editors/gpencil/gpencil_utils.c72
-rw-r--r--source/blender/editors/gpencil/gpencil_vertex_ops.c4
-rw-r--r--source/blender/editors/include/ED_clip.h2
-rw-r--r--source/blender/editors/include/ED_gpencil.h5
-rw-r--r--source/blender/editors/include/ED_screen.h6
-rw-r--r--source/blender/editors/include/ED_view3d.h10
-rw-r--r--source/blender/editors/include/UI_interface.h46
-rw-r--r--source/blender/editors/include/UI_tree_view.hh30
-rw-r--r--source/blender/editors/interface/CMakeLists.txt4
-rw-r--r--source/blender/editors/interface/interface.c108
-rw-r--r--source/blender/editors/interface/interface_context_path.cc2
-rw-r--r--source/blender/editors/interface/interface_eyedropper_color.c12
-rw-r--r--source/blender/editors/interface/interface_handlers.c13
-rw-r--r--source/blender/editors/interface/interface_icons_event.c26
-rw-r--r--source/blender/editors/interface/interface_intern.h17
-rw-r--r--source/blender/editors/interface/interface_layout.c18
-rw-r--r--source/blender/editors/interface/interface_panel.c2
-rw-r--r--source/blender/editors/interface/interface_query.c1
-rw-r--r--source/blender/editors/interface/interface_region_menu_pie.c4
-rw-r--r--source/blender/editors/interface/interface_region_menu_popup.c2
-rw-r--r--source/blender/editors/interface/interface_region_popover.c2
-rw-r--r--source/blender/editors/interface/interface_region_popup.c2
-rw-r--r--source/blender/editors/interface/interface_region_search.cc (renamed from source/blender/editors/interface/interface_region_search.c)100
-rw-r--r--source/blender/editors/interface/interface_region_tooltip.c3
-rw-r--r--source/blender/editors/interface/interface_regions_intern.h8
-rw-r--r--source/blender/editors/interface/interface_style.c18
-rw-r--r--source/blender/editors/interface/interface_template_asset_view.cc2
-rw-r--r--source/blender/editors/interface/interface_template_search_menu.cc (renamed from source/blender/editors/interface/interface_template_search_menu.c)286
-rw-r--r--source/blender/editors/interface/interface_templates.c2
-rw-r--r--source/blender/editors/interface/interface_widgets.c17
-rw-r--r--source/blender/editors/interface/tree_view.cc37
-rw-r--r--source/blender/editors/io/io_gpencil_export.c1
-rw-r--r--source/blender/editors/mesh/editmesh_extrude.c4
-rw-r--r--source/blender/editors/mesh/editmesh_extrude_spin.c2
-rw-r--r--source/blender/editors/mesh/editmesh_intersect.c1
-rw-r--r--source/blender/editors/mesh/editmesh_knife.c8
-rw-r--r--source/blender/editors/object/object_add.c11
-rw-r--r--source/blender/editors/object/object_relations.c16
-rw-r--r--source/blender/editors/physics/particle_edit.c12
-rw-r--r--source/blender/editors/screen/area.c8
-rw-r--r--source/blender/editors/screen/screen_edit.c3
-rw-r--r--source/blender/editors/screen/screen_user_menu.c4
-rw-r--r--source/blender/editors/sculpt_paint/CMakeLists.txt1
-rw-r--r--source/blender/editors/sculpt_paint/paint_image_2d.c94
-rw-r--r--source/blender/editors/sculpt_paint/paint_image_2d_curve_mask.cc188
-rw-r--r--source/blender/editors/sculpt_paint/paint_image_proj.c12
-rw-r--r--source/blender/editors/sculpt_paint/paint_intern.h53
-rw-r--r--source/blender/editors/sculpt_paint/paint_vertex_color_ops.c3
-rw-r--r--source/blender/editors/sculpt_paint/sculpt_intern.h10
-rw-r--r--source/blender/editors/space_action/action_data.c3
-rw-r--r--source/blender/editors/space_buttons/space_buttons.c2
-rw-r--r--source/blender/editors/space_clip/clip_editor.c4
-rw-r--r--source/blender/editors/space_file/asset_catalog_tree_view.cc11
-rw-r--r--source/blender/editors/space_file/filelist.c28
-rw-r--r--source/blender/editors/space_graph/graph_buttons.c49
-rw-r--r--source/blender/editors/space_graph/graph_edit.c5
-rw-r--r--source/blender/editors/space_graph/graph_ops.c28
-rw-r--r--source/blender/editors/space_graph/graph_select.c89
-rw-r--r--source/blender/editors/space_graph/graph_slider_ops.c266
-rw-r--r--source/blender/editors/space_graph/graph_utils.c21
-rw-r--r--source/blender/editors/space_graph/graph_view.c47
-rw-r--r--source/blender/editors/space_image/image_draw.c2
-rw-r--r--source/blender/editors/space_image/image_ops.c7
-rw-r--r--source/blender/editors/space_info/CMakeLists.txt2
-rw-r--r--source/blender/editors/space_info/info_stats.cc (renamed from source/blender/editors/space_info/info_stats.c)86
-rw-r--r--source/blender/editors/space_node/CMakeLists.txt8
-rw-r--r--source/blender/editors/space_node/drawnode.cc20
-rw-r--r--source/blender/editors/space_node/node_add.cc2
-rw-r--r--source/blender/editors/space_node/node_context_path.cc2
-rw-r--r--source/blender/editors/space_node/node_draw.cc320
-rw-r--r--source/blender/editors/space_node/node_edit.cc15
-rw-r--r--source/blender/editors/space_node/node_geometry_attribute_search.cc2
-rw-r--r--source/blender/editors/space_node/node_gizmo.cc (renamed from source/blender/editors/space_node/node_gizmo.c)115
-rw-r--r--source/blender/editors/space_node/node_group.cc2
-rw-r--r--source/blender/editors/space_node/node_intern.h355
-rw-r--r--source/blender/editors/space_node/node_intern.hh333
-rw-r--r--source/blender/editors/space_node/node_ops.cc (renamed from source/blender/editors/space_node/node_ops.c)4
-rw-r--r--source/blender/editors/space_node/node_relationships.cc128
-rw-r--r--source/blender/editors/space_node/node_select.cc2
-rw-r--r--source/blender/editors/space_node/node_templates.cc2
-rw-r--r--source/blender/editors/space_node/node_toolbar.cc2
-rw-r--r--source/blender/editors/space_node/node_view.cc2
-rw-r--r--source/blender/editors/space_node/space_node.cc (renamed from source/blender/editors/space_node/space_node.c)147
-rw-r--r--source/blender/editors/space_outliner/outliner_edit.c6
-rw-r--r--source/blender/editors/space_sequencer/space_sequencer.c75
-rw-r--r--source/blender/editors/space_spreadsheet/CMakeLists.txt13
-rw-r--r--source/blender/editors/space_spreadsheet/space_spreadsheet.cc36
-rw-r--r--source/blender/editors/space_spreadsheet/spreadsheet_cell_value.hh1
-rw-r--r--source/blender/editors/space_spreadsheet/spreadsheet_data_source_geometry.cc127
-rw-r--r--source/blender/editors/space_spreadsheet/spreadsheet_data_source_geometry.hh20
-rw-r--r--source/blender/editors/space_spreadsheet/spreadsheet_dataset_draw.cc355
-rw-r--r--source/blender/editors/space_spreadsheet/spreadsheet_dataset_draw.hh42
-rw-r--r--source/blender/editors/space_spreadsheet/spreadsheet_dataset_layout.cc112
-rw-r--r--source/blender/editors/space_spreadsheet/spreadsheet_dataset_layout.hh68
-rw-r--r--source/blender/editors/space_spreadsheet/spreadsheet_intern.hh9
-rw-r--r--source/blender/editors/space_spreadsheet/spreadsheet_layout.cc17
-rw-r--r--source/blender/editors/space_spreadsheet/spreadsheet_panels.cc37
-rw-r--r--source/blender/editors/space_spreadsheet/spreadsheet_row_filter_ui.cc7
-rw-r--r--source/blender/editors/space_text/text_draw.c2
-rw-r--r--source/blender/editors/space_text/text_ops.c42
-rw-r--r--source/blender/editors/space_view3d/drawobject.c52
-rw-r--r--source/blender/editors/space_view3d/space_view3d.c2
-rw-r--r--source/blender/editors/space_view3d/view3d_cursor_snap.c4
-rw-r--r--source/blender/editors/space_view3d/view3d_draw.c18
-rw-r--r--source/blender/editors/space_view3d/view3d_gizmo_ruler.c10
-rw-r--r--source/blender/editors/space_view3d/view3d_ops.c6
-rw-r--r--source/blender/editors/space_view3d/view3d_placement.c8
-rw-r--r--source/blender/editors/space_view3d/view3d_utils.c24
-rw-r--r--source/blender/editors/space_view3d/view3d_view.c6
-rw-r--r--source/blender/editors/transform/transform.h4
-rw-r--r--source/blender/editors/transform/transform_convert_action.c7
-rw-r--r--source/blender/editors/transform/transform_generics.c1
-rw-r--r--source/blender/editors/transform/transform_mode_translate.c2
-rw-r--r--source/blender/editors/transform/transform_snap.c113
-rw-r--r--source/blender/editors/transform/transform_snap_object.c10
-rw-r--r--source/blender/freestyle/intern/view_map/FEdgeXDetector.cpp2
-rw-r--r--source/blender/functions/FN_field.hh129
-rw-r--r--source/blender/functions/FN_field_cpp_type.hh95
-rw-r--r--source/blender/functions/FN_generic_vector_array.hh3
-rw-r--r--source/blender/functions/FN_generic_virtual_array.hh1252
-rw-r--r--source/blender/functions/FN_generic_virtual_vector_array.hh14
-rw-r--r--source/blender/functions/FN_multi_function.hh4
-rw-r--r--source/blender/functions/FN_multi_function_builder.hh34
-rw-r--r--source/blender/functions/FN_multi_function_params.hh26
-rw-r--r--source/blender/functions/FN_multi_function_procedure_executor.hh2
-rw-r--r--source/blender/functions/FN_multi_function_signature.hh47
-rw-r--r--source/blender/functions/intern/field.cc181
-rw-r--r--source/blender/functions/intern/generic_vector_array.cc5
-rw-r--r--source/blender/functions/intern/generic_virtual_array.cc642
-rw-r--r--source/blender/functions/intern/generic_virtual_vector_array.cc10
-rw-r--r--source/blender/functions/intern/multi_function.cc27
-rw-r--r--source/blender/functions/intern/multi_function_builder.cc36
-rw-r--r--source/blender/functions/intern/multi_function_parallel.cc4
-rw-r--r--source/blender/functions/intern/multi_function_procedure.cc2
-rw-r--r--source/blender/functions/intern/multi_function_procedure_executor.cc10
-rw-r--r--source/blender/functions/tests/FN_field_test.cc62
-rw-r--r--source/blender/functions/tests/FN_multi_function_procedure_test.cc49
-rw-r--r--source/blender/functions/tests/FN_multi_function_test.cc2
-rw-r--r--source/blender/geometry/intern/mesh_to_curve_convert.cc16
-rw-r--r--source/blender/gpencil_modifiers/intern/lineart/lineart_cpu.c8
-rw-r--r--source/blender/gpu/CMakeLists.txt1
-rw-r--r--source/blender/gpu/GPU_immediate_util.h1
-rw-r--r--source/blender/gpu/intern/gpu_immediate_util.c52
-rw-r--r--source/blender/gpu/tests/gpu_testing.cc1
-rw-r--r--source/blender/imbuf/intern/anim_movie.c12
-rw-r--r--source/blender/imbuf/intern/indexer.c6
-rw-r--r--source/blender/imbuf/intern/moviecache.c8
-rw-r--r--source/blender/io/alembic/exporter/abc_writer_mesh.cc10
-rw-r--r--source/blender/io/alembic/intern/abc_customdata.cc51
-rw-r--r--source/blender/io/alembic/intern/abc_customdata.h4
-rw-r--r--source/blender/io/avi/intern/avi.c2
-rw-r--r--source/blender/io/collada/AnimationExporter.cpp2
-rw-r--r--source/blender/io/collada/collada_utils.cpp6
-rw-r--r--source/blender/io/gpencil/gpencil_io.h1
-rw-r--r--source/blender/io/gpencil/intern/gpencil_io_capi.cc51
-rw-r--r--source/blender/makesdna/DNA_constraint_types.h2
-rw-r--r--source/blender/makesdna/DNA_fluid_types.h4
-rw-r--r--source/blender/makesdna/DNA_image_types.h8
-rw-r--r--source/blender/makesdna/DNA_lightprobe_types.h2
-rw-r--r--source/blender/makesdna/DNA_node_types.h39
-rw-r--r--source/blender/makesdna/DNA_object_types.h2
-rw-r--r--source/blender/makesdna/DNA_scene_types.h3
-rw-r--r--source/blender/makesdna/DNA_screen_types.h5
-rw-r--r--source/blender/makesdna/DNA_sequence_types.h2
-rw-r--r--source/blender/makesdna/DNA_space_types.h10
-rw-r--r--source/blender/makesdna/DNA_texture_types.h4
-rw-r--r--source/blender/makesdna/DNA_userdef_types.h17
-rw-r--r--source/blender/makesdna/DNA_view3d_types.h10
-rw-r--r--source/blender/makesrna/RNA_enum_items.h2
-rw-r--r--source/blender/makesrna/intern/makesrna.c22
-rw-r--r--source/blender/makesrna/intern/rna_animviz.c2
-rw-r--r--source/blender/makesrna/intern/rna_attribute.c3
-rw-r--r--source/blender/makesrna/intern/rna_brush.c2
-rw-r--r--source/blender/makesrna/intern/rna_gpencil_modifier.c8
-rw-r--r--source/blender/makesrna/intern/rna_nodetree.c5
-rw-r--r--source/blender/makesrna/intern/rna_object_api.c2
-rw-r--r--source/blender/makesrna/intern/rna_object_force.c3
-rw-r--r--source/blender/makesrna/intern/rna_sequencer.c33
-rw-r--r--source/blender/makesrna/intern/rna_space.c8
-rw-r--r--source/blender/makesrna/intern/rna_ui.c7
-rw-r--r--source/blender/makesrna/intern/rna_userdef.c33
-rw-r--r--source/blender/makesrna/intern/rna_volume.c42
-rw-r--r--source/blender/modifiers/intern/MOD_boolean.cc18
-rw-r--r--source/blender/modifiers/intern/MOD_meshdeform.c2
-rw-r--r--source/blender/modifiers/intern/MOD_nodes.cc33
-rw-r--r--source/blender/modifiers/intern/MOD_nodes_evaluator.cc160
-rw-r--r--source/blender/modifiers/intern/MOD_uvproject.c4
-rw-r--r--source/blender/nodes/CMakeLists.txt148
-rw-r--r--source/blender/nodes/NOD_common.h2
-rw-r--r--source/blender/nodes/NOD_geometry_exec.hh70
-rw-r--r--source/blender/nodes/NOD_geometry_nodes_eval_log.hh16
-rw-r--r--source/blender/nodes/NOD_node_declaration.hh1
-rw-r--r--source/blender/nodes/NOD_type_conversions.hh5
-rw-r--r--source/blender/nodes/composite/node_composite_util.cc1
-rw-r--r--source/blender/nodes/composite/nodes/node_composite_common.cc4
-rw-r--r--source/blender/nodes/composite/nodes/node_composite_composite.cc3
-rw-r--r--source/blender/nodes/composite/nodes/node_composite_image.cc5
-rw-r--r--source/blender/nodes/composite/nodes/node_composite_scale.cc9
-rw-r--r--source/blender/nodes/composite/nodes/node_composite_splitViewer.cc3
-rw-r--r--source/blender/nodes/composite/nodes/node_composite_viewer.cc2
-rw-r--r--source/blender/nodes/function/node_function_util.cc1
-rw-r--r--source/blender/nodes/function/nodes/node_fn_boolean_math.cc6
-rw-r--r--source/blender/nodes/function/nodes/node_fn_float_compare.cc6
-rw-r--r--source/blender/nodes/function/nodes/node_fn_random_value.cc26
-rw-r--r--source/blender/nodes/function/nodes/node_fn_rotate_euler.cc14
-rw-r--r--source/blender/nodes/geometry/CMakeLists.txt267
-rw-r--r--source/blender/nodes/geometry/node_geometry_util.cc6
-rw-r--r--source/blender/nodes/geometry/node_geometry_util.hh12
-rw-r--r--source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_align_rotation_to_vector.cc (renamed from source/blender/nodes/geometry/nodes/legacy/node_geo_align_rotation_to_vector.cc)36
-rw-r--r--source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_attribute_clamp.cc (renamed from source/blender/nodes/geometry/nodes/legacy/node_geo_attribute_clamp.cc)56
-rw-r--r--source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_attribute_color_ramp.cc (renamed from source/blender/nodes/geometry/nodes/legacy/node_geo_attribute_color_ramp.cc)26
-rw-r--r--source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_attribute_combine_xyz.cc (renamed from source/blender/nodes/geometry/nodes/legacy/node_geo_attribute_combine_xyz.cc)40
-rw-r--r--source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_attribute_compare.cc (renamed from source/blender/nodes/geometry/nodes/legacy/node_geo_attribute_compare.cc)60
-rw-r--r--source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_attribute_convert.cc (renamed from source/blender/nodes/geometry/nodes/legacy/node_geo_attribute_convert.cc)28
-rw-r--r--source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_attribute_curve_map.cc (renamed from source/blender/nodes/geometry/nodes/legacy/node_geo_attribute_curve_map.cc)57
-rw-r--r--source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_attribute_fill.cc (renamed from source/blender/nodes/geometry/nodes/legacy/node_geo_attribute_fill.cc)36
-rw-r--r--source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_attribute_map_range.cc (renamed from source/blender/nodes/geometry/nodes/legacy/node_geo_attribute_map_range.cc)55
-rw-r--r--source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_attribute_math.cc (renamed from source/blender/nodes/geometry/nodes/legacy/node_geo_attribute_math.cc)38
-rw-r--r--source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_attribute_mix.cc (renamed from source/blender/nodes/geometry/nodes/legacy/node_geo_attribute_mix.cc)53
-rw-r--r--source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_attribute_proximity.cc (renamed from source/blender/nodes/geometry/nodes/legacy/node_geo_attribute_proximity.cc)26
-rw-r--r--source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_attribute_randomize.cc (renamed from source/blender/nodes/geometry/nodes/legacy/node_geo_attribute_randomize.cc)102
-rw-r--r--source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_attribute_sample_texture.cc (renamed from source/blender/nodes/geometry/nodes/legacy/node_geo_attribute_sample_texture.cc)16
-rw-r--r--source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_attribute_separate_xyz.cc (renamed from source/blender/nodes/geometry/nodes/legacy/node_geo_attribute_separate_xyz.cc)34
-rw-r--r--source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_attribute_transfer.cc (renamed from source/blender/nodes/geometry/nodes/legacy/node_geo_attribute_transfer.cc)34
-rw-r--r--source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_attribute_vector_math.cc (renamed from source/blender/nodes/geometry/nodes/legacy/node_geo_attribute_vector_math.cc)92
-rw-r--r--source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_attribute_vector_rotate.cc (renamed from source/blender/nodes/geometry/nodes/legacy/node_geo_attribute_vector_rotate.cc)77
-rw-r--r--source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_curve_endpoints.cc (renamed from source/blender/nodes/geometry/nodes/legacy/node_geo_curve_endpoints.cc)22
-rw-r--r--source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_curve_reverse.cc (renamed from source/blender/nodes/geometry/nodes/legacy/node_geo_curve_reverse.cc)16
-rw-r--r--source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_curve_select_by_handle_type.cc (renamed from source/blender/nodes/geometry/nodes/legacy/node_geo_curve_select_by_handle_type.cc)24
-rw-r--r--source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_curve_set_handles.cc (renamed from source/blender/nodes/geometry/nodes/legacy/node_geo_curve_set_handles.cc)26
-rw-r--r--source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_curve_spline_type.cc (renamed from source/blender/nodes/geometry/nodes/legacy/node_geo_curve_spline_type.cc)26
-rw-r--r--source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_curve_subdivide.cc (renamed from source/blender/nodes/geometry/nodes/legacy/node_geo_curve_subdivide.cc)39
-rw-r--r--source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_curve_to_points.cc (renamed from source/blender/nodes/geometry/nodes/legacy/node_geo_curve_to_points.cc)144
-rw-r--r--source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_delete_geometry.cc (renamed from source/blender/nodes/geometry/nodes/legacy/node_geo_delete_geometry.cc)52
-rw-r--r--source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_edge_split.cc (renamed from source/blender/nodes/geometry/nodes/legacy/node_geo_edge_split.cc)14
-rw-r--r--source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_material_assign.cc (renamed from source/blender/nodes/geometry/nodes/legacy/node_geo_material_assign.cc)16
-rw-r--r--source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_mesh_to_curve.cc (renamed from source/blender/nodes/geometry/nodes/legacy/node_geo_mesh_to_curve.cc)16
-rw-r--r--source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_point_distribute.cc (renamed from source/blender/nodes/geometry/nodes/legacy/node_geo_point_distribute.cc)47
-rw-r--r--source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_point_instance.cc (renamed from source/blender/nodes/geometry/nodes/legacy/node_geo_point_instance.cc)48
-rw-r--r--source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_point_rotate.cc (renamed from source/blender/nodes/geometry/nodes/legacy/node_geo_point_rotate.cc)35
-rw-r--r--source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_point_scale.cc (renamed from source/blender/nodes/geometry/nodes/legacy/node_geo_point_scale.cc)34
-rw-r--r--source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_point_separate.cc (renamed from source/blender/nodes/geometry/nodes/legacy/node_geo_point_separate.cc)36
-rw-r--r--source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_point_translate.cc (renamed from source/blender/nodes/geometry/nodes/legacy/node_geo_point_translate.cc)32
-rw-r--r--source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_points_to_volume.cc (renamed from source/blender/nodes/geometry/nodes/legacy/node_geo_points_to_volume.cc)45
-rw-r--r--source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_raycast.cc (renamed from source/blender/nodes/geometry/nodes/legacy/node_geo_raycast.cc)42
-rw-r--r--source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_select_by_material.cc (renamed from source/blender/nodes/geometry/nodes/legacy/node_geo_select_by_material.cc)14
-rw-r--r--source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_subdivision_surface.cc (renamed from source/blender/nodes/geometry/nodes/legacy/node_geo_subdivision_surface.cc)24
-rw-r--r--source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_volume_to_mesh.cc (renamed from source/blender/nodes/geometry/nodes/legacy/node_geo_volume_to_mesh.cc)32
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_attribute_capture.cc77
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_attribute_remove.cc14
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_attribute_statistic.cc66
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_boolean.cc34
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_bounding_box.cc14
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_collection_info.cc24
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_common.cc4
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_convex_hull.cc34
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_curve_endpoint_selection.cc24
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_curve_fill.cc22
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_curve_fillet.cc44
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_curve_handle_type_selection.cc38
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_curve_length.cc14
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_curve_parameter.cc190
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_curve_primitive_bezier_segment.cc46
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_curve_primitive_circle.cc70
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_curve_primitive_line.cc56
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_curve_primitive_quadratic_bezier.cc28
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_curve_primitive_quadrilateral.cc110
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_curve_primitive_spiral.cc40
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_curve_primitive_star.cc59
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_curve_resample.cc88
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_curve_reverse.cc14
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_curve_sample.cc30
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_curve_set_handles.cc24
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_curve_spline_type.cc24
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_curve_subdivide.cc18
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_curve_to_mesh.cc14
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_curve_to_points.cc64
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_curve_trim.cc60
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_delete_geometry.cc122
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_distribute_points_on_faces.cc42
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_edge_split.cc23
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_image_texture.cc24
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_input_curve_handles.cc14
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_input_curve_tilt.cc14
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_input_id.cc14
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_input_index.cc14
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_input_material.cc18
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_input_material_index.cc14
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_input_normal.cc94
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_input_position.cc14
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_input_radius.cc14
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_input_shade_smooth.cc14
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_input_spline_cyclic.cc14
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_input_spline_length.cc44
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_input_spline_resolution.cc14
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_input_tangent.cc39
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_instance_on_points.cc45
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_instances_to_points.cc19
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_is_viewport.cc14
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_join_geometry.cc31
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_material_replace.cc14
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_material_selection.cc33
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_circle.cc35
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_cone.cc323
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_cube.cc51
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_cylinder.cc95
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_grid.cc48
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_ico_sphere.cc31
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_line.cc123
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_uv_sphere.cc32
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_mesh_subdivide.cc14
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_mesh_to_curve.cc14
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_mesh_to_points.cc28
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_object_info.cc110
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_points_to_vertices.cc22
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_points_to_volume.cc51
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_proximity.cc20
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_raycast.cc48
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_realize_instances.cc14
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_rotate_instances.cc16
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_scale_instances.cc16
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_separate_components.cc14
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_separate_geometry.cc24
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_set_curve_handles.cc49
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_set_curve_radius.cc14
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_set_curve_tilt.cc14
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_set_id.cc14
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_set_material.cc14
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_set_material_index.cc14
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_set_point_radius.cc14
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_set_position.cc23
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_set_shade_smooth.cc14
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_set_spline_cyclic.cc14
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_set_spline_resolution.cc14
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_string_join.cc14
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_string_to_curves.cc32
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_subdivision_surface.cc24
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_switch.cc38
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_transfer_attribute.cc90
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_transform.cc82
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_translate_instances.cc16
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_triangulate.cc20
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_viewer.cc25
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_volume_to_mesh.cc32
-rw-r--r--source/blender/nodes/intern/geometry_nodes_eval_log.cc59
-rw-r--r--source/blender/nodes/intern/node_common.cc21
-rw-r--r--source/blender/nodes/intern/node_declaration.cc10
-rw-r--r--source/blender/nodes/intern/node_geometry_exec.cc34
-rw-r--r--source/blender/nodes/intern/node_socket.cc80
-rw-r--r--source/blender/nodes/intern/node_util.c16
-rw-r--r--source/blender/nodes/intern/node_util.h1
-rw-r--r--source/blender/nodes/intern/type_conversions.cc66
-rw-r--r--source/blender/nodes/shader/node_shader_util.c1
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_bsdf_hair_principled.c49
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_bsdf_principled.c16
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_common.c4
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_map_range.cc4
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_mapping.c4
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_math.cc7
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_output_aov.c3
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_output_light.c3
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_output_linestyle.c3
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_output_material.c3
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_output_world.c3
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_tex_musgrave.cc28
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_tex_noise.cc6
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_tex_sky.c4
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_tex_voronoi.cc52
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_tex_white_noise.cc6
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_vector_math.cc40
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_vector_rotate.cc10
-rw-r--r--source/blender/nodes/texture/node_texture_util.c1
-rw-r--r--source/blender/nodes/texture/nodes/node_texture_common.c1
-rw-r--r--source/blender/nodes/texture/nodes/node_texture_output.c3
-rw-r--r--source/blender/nodes/texture/nodes/node_texture_viewer.c3
-rw-r--r--source/blender/python/generic/blf_py_api.c7
-rw-r--r--source/blender/python/intern/bpy.c58
-rw-r--r--source/blender/python/intern/bpy_operator.c17
-rw-r--r--source/blender/python/intern/bpy_props.c4
-rw-r--r--source/blender/python/intern/bpy_rna.c2
-rw-r--r--source/blender/sequencer/SEQ_edit.h5
-rw-r--r--source/blender/sequencer/intern/effects.c16
-rw-r--r--source/blender/sequencer/intern/render.c65
-rw-r--r--source/blender/sequencer/intern/strip_add.c22
-rw-r--r--source/blender/sequencer/intern/strip_edit.c46
-rw-r--r--source/blender/sequencer/intern/strip_transform.c9
-rw-r--r--source/blender/windowmanager/WM_api.h14
-rw-r--r--source/blender/windowmanager/WM_keymap.h5
-rw-r--r--source/blender/windowmanager/WM_types.h18
-rw-r--r--source/blender/windowmanager/gizmo/WM_gizmo_types.h3
-rw-r--r--source/blender/windowmanager/intern/wm.c9
-rw-r--r--source/blender/windowmanager/intern/wm_dragdrop.c17
-rw-r--r--source/blender/windowmanager/intern/wm_draw.c3
-rw-r--r--source/blender/windowmanager/intern/wm_event_system.c25
-rw-r--r--source/blender/windowmanager/intern/wm_files_link.c1244
-rw-r--r--source/blender/windowmanager/intern/wm_keymap.c10
-rw-r--r--source/blender/windowmanager/intern/wm_operators.c4
-rw-r--r--source/blender/windowmanager/intern/wm_playanim.c3
-rw-r--r--source/blender/windowmanager/wm_event_system.h2
-rw-r--r--source/blender/windowmanager/xr/intern/wm_xr_operators.c16
-rw-r--r--source/creator/creator.c4
-rw-r--r--source/creator/creator_args.c2
562 files changed, 14985 insertions, 10234 deletions
diff --git a/source/blender/blenfont/BLF_api.h b/source/blender/blenfont/BLF_api.h
index 78252bdb08b..fa8e764139d 100644
--- a/source/blender/blenfont/BLF_api.h
+++ b/source/blender/blenfont/BLF_api.h
@@ -43,6 +43,8 @@ void BLF_exit(void);
void BLF_cache_clear(void);
+void BLF_cache_flush_set_fn(void (*cache_flush_fn)(void));
+
/* Loads a font, or returns an already loaded font and increments its reference count. */
int BLF_load(const char *name) ATTR_NONNULL();
int BLF_load_mem(const char *name, const unsigned char *mem, int mem_size) ATTR_NONNULL();
@@ -63,7 +65,7 @@ void BLF_metrics_attach(int fontid, unsigned char *mem, int mem_size);
void BLF_aspect(int fontid, float x, float y, float z);
void BLF_position(int fontid, float x, float y, float z);
-void BLF_size(int fontid, int size, int dpi);
+void BLF_size(int fontid, float size, int dpi);
/* goal: small but useful color API */
void BLF_color4ubv(int fontid, const unsigned char rgba[4]);
@@ -250,6 +252,7 @@ void BLF_thumb_preview(const char *filename,
/* blf_default.c */
void BLF_default_dpi(int dpi);
+void BLF_default_size(int size);
void BLF_default_set(int fontid);
int BLF_default(void); /* get default font ID so we can pass it to other functions */
/* Draw the string using the default font, size and dpi. */
diff --git a/source/blender/blenfont/CMakeLists.txt b/source/blender/blenfont/CMakeLists.txt
index 59a9072de57..cc6e298b322 100644
--- a/source/blender/blenfont/CMakeLists.txt
+++ b/source/blender/blenfont/CMakeLists.txt
@@ -23,7 +23,6 @@ set(INC
../blenkernel
../blenlib
../blentranslation
- ../editors/include
../gpu
../imbuf
../makesdna
diff --git a/source/blender/blenfont/intern/blf.c b/source/blender/blenfont/intern/blf.c
index 34ddb6f22d2..d6773916abd 100644
--- a/source/blender/blenfont/intern/blf.c
+++ b/source/blender/blenfont/intern/blf.c
@@ -363,7 +363,7 @@ void BLF_position(int fontid, float x, float y, float z)
}
}
-void BLF_size(int fontid, int size, int dpi)
+void BLF_size(int fontid, float size, int dpi)
{
FontBLF *font = blf_get(fontid);
@@ -910,7 +910,7 @@ void BLF_state_print(int fontid)
if (font) {
printf("fontid %d %p\n", fontid, (void *)font);
printf(" name: '%s'\n", font->name);
- printf(" size: %u\n", font->size);
+ printf(" size: %f\n", font->size);
printf(" dpi: %u\n", font->dpi);
printf(" pos: %.6f %.6f %.6f\n", UNPACK3(font->pos));
printf(" aspect: (%d) %.6f %.6f %.6f\n",
diff --git a/source/blender/blenfont/intern/blf_default.c b/source/blender/blenfont/intern/blf_default.c
index 2bac0bf8904..57eeaa6768d 100644
--- a/source/blender/blenfont/intern/blf_default.c
+++ b/source/blender/blenfont/intern/blf_default.c
@@ -29,8 +29,6 @@
#include "BLF_api.h"
-#include "UI_interface.h"
-
#include "blf_internal.h"
/* call BLF_default_set first! */
@@ -39,12 +37,19 @@
/* Default size and dpi, for BLF_draw_default. */
static int global_font_default = -1;
static int global_font_dpi = 72;
+/* Keep in sync with `UI_style_get()->widgetlabel.points` */
+static int global_font_size = 11;
void BLF_default_dpi(int dpi)
{
global_font_dpi = dpi;
}
+void BLF_default_size(int size)
+{
+ global_font_size = size;
+}
+
void BLF_default_set(int fontid)
{
if ((fontid == -1) || blf_font_id_is_valid(fontid)) {
@@ -62,8 +67,7 @@ int BLF_set_default(void)
{
ASSERT_DEFAULT_SET;
- const uiStyle *style = UI_style_get();
- BLF_size(global_font_default, style->widgetlabel.points, global_font_dpi);
+ BLF_size(global_font_default, global_font_size, global_font_dpi);
return global_font_default;
}
@@ -71,9 +75,7 @@ int BLF_set_default(void)
void BLF_draw_default(float x, float y, float z, const char *str, const size_t str_len)
{
ASSERT_DEFAULT_SET;
-
- const uiStyle *style = UI_style_get();
- BLF_size(global_font_default, style->widgetlabel.points, global_font_dpi);
+ BLF_size(global_font_default, global_font_size, global_font_dpi);
BLF_position(global_font_default, x, y, z);
BLF_draw(global_font_default, str, str_len);
}
diff --git a/source/blender/blenfont/intern/blf_font.c b/source/blender/blenfont/intern/blf_font.c
index 27478bd7f8e..c81d18ba7de 100644
--- a/source/blender/blenfont/intern/blf_font.c
+++ b/source/blender/blenfont/intern/blf_font.c
@@ -34,6 +34,7 @@
#include FT_FREETYPE_H
#include FT_GLYPH_H
+#include FT_ADVANCES_H /* For FT_Get_Advance */
#include "MEM_guardedalloc.h"
@@ -49,8 +50,6 @@
#include "BLF_api.h"
-#include "UI_interface.h"
-
#include "GPU_batch.h"
#include "GPU_matrix.h"
@@ -71,6 +70,9 @@ static FT_Library ft_lib;
static SpinLock ft_lib_mutex;
static SpinLock blf_glyph_cache_mutex;
+/* May be set to #UI_widgetbase_draw_cache_flush. */
+static void (*blf_draw_cache_flush)(void) = NULL;
+
/* -------------------------------------------------------------------- */
/** \name FreeType Utilities (Internal)
* \{ */
@@ -254,10 +256,10 @@ void blf_batch_draw(void)
GPU_blend(GPU_BLEND_ALPHA);
-#ifndef BLF_STANDALONE
/* We need to flush widget base first to ensure correct ordering. */
- UI_widgetbase_draw_cache_flush();
-#endif
+ if (blf_draw_cache_flush != NULL) {
+ blf_draw_cache_flush();
+ }
GPUTexture *texture = blf_batch_cache_texture_load();
GPU_vertbuf_data_len_set(g_batch.verts, g_batch.glyph_len);
@@ -297,44 +299,27 @@ static void blf_batch_draw_end(void)
* characters.
*/
-BLI_INLINE GlyphBLF *blf_utf8_next_fast(
- FontBLF *font, GlyphCacheBLF *gc, const char *str, size_t str_len, size_t *i_p, uint *r_c)
+BLI_INLINE GlyphBLF *blf_glyph_from_utf8_and_step(
+ FontBLF *font, GlyphCacheBLF *gc, const char *str, size_t str_len, size_t *i_p)
{
- GlyphBLF *g;
- if ((*r_c = str[*i_p]) < GLYPH_ASCII_TABLE_SIZE) {
- g = (gc->glyph_ascii_table)[*r_c];
- if (UNLIKELY(g == NULL)) {
- g = blf_glyph_add(font, gc, FT_Get_Char_Index(font->face, *r_c), *r_c);
- gc->glyph_ascii_table[*r_c] = g;
- }
- (*i_p)++;
- }
- else {
- *r_c = BLI_str_utf8_as_unicode_step(str, str_len, i_p);
- g = blf_glyph_search(gc, *r_c);
- if (UNLIKELY(g == NULL)) {
- g = blf_glyph_add(font, gc, FT_Get_Char_Index(font->face, *r_c), *r_c);
- }
- }
- return g;
+ uint charcode = BLI_str_utf8_as_unicode_step(str, str_len, i_p);
+ /* Invalid unicode sequences return the byte value, stepping forward one.
+ * This allows `latin1` to display (which is sometimes used for file-paths). */
+ BLI_assert(charcode != BLI_UTF8_ERR);
+ return blf_glyph_ensure(font, gc, charcode);
}
-BLI_INLINE void blf_kerning_step_fast(FontBLF *font,
- const GlyphBLF *g_prev,
- const GlyphBLF *g,
- const uint c_prev,
- const uint c,
- int *pen_x_p)
+BLI_INLINE int blf_kerning(FontBLF *font, const GlyphBLF *g_prev, const GlyphBLF *g)
{
if (!FT_HAS_KERNING(font->face) || g_prev == NULL) {
- return;
+ return 0;
}
FT_Vector delta = {KERNING_ENTRY_UNSET};
/* Get unscaled kerning value from our cache if ASCII. */
- if ((c_prev < KERNING_CACHE_TABLE_SIZE) && (c < GLYPH_ASCII_TABLE_SIZE)) {
- delta.x = font->kerning_cache->ascii_table[c][c_prev];
+ if ((g_prev->c < KERNING_CACHE_TABLE_SIZE) && (g->c < GLYPH_ASCII_TABLE_SIZE)) {
+ delta.x = font->kerning_cache->ascii_table[g->c][g_prev->c];
}
/* If not ASCII or not found in cache, ask FreeType for kerning. */
@@ -344,14 +329,16 @@ BLI_INLINE void blf_kerning_step_fast(FontBLF *font,
}
/* If ASCII we save this value to our cache for quicker access next time. */
- if ((c_prev < KERNING_CACHE_TABLE_SIZE) && (c < GLYPH_ASCII_TABLE_SIZE)) {
- font->kerning_cache->ascii_table[c][c_prev] = (int)delta.x;
+ if ((g_prev->c < KERNING_CACHE_TABLE_SIZE) && (g->c < GLYPH_ASCII_TABLE_SIZE)) {
+ font->kerning_cache->ascii_table[g->c][g_prev->c] = (int)delta.x;
}
if (delta.x != 0) {
/* Convert unscaled design units to pixels and move pen. */
- *pen_x_p += blf_unscaled_F26Dot6_to_pixels(font, delta.x);
+ return blf_unscaled_F26Dot6_to_pixels(font, delta.x);
}
+
+ return 0;
}
/** \} */
@@ -367,7 +354,6 @@ static void blf_font_draw_ex(FontBLF *font,
struct ResultBLF *r_info,
int pen_y)
{
- unsigned int c, c_prev = BLI_UTF8_ERR;
GlyphBLF *g, *g_prev = NULL;
int pen_x = 0;
size_t i = 0;
@@ -380,22 +366,18 @@ static void blf_font_draw_ex(FontBLF *font,
blf_batch_draw_begin(font);
while ((i < str_len) && str[i]) {
- g = blf_utf8_next_fast(font, gc, str, str_len, &i, &c);
+ g = blf_glyph_from_utf8_and_step(font, gc, str, str_len, &i);
- if (UNLIKELY(c == BLI_UTF8_ERR)) {
- break;
- }
if (UNLIKELY(g == NULL)) {
continue;
}
- blf_kerning_step_fast(font, g_prev, g, c_prev, c, &pen_x);
+ pen_x += blf_kerning(font, g_prev, g);
/* do not return this loop if clipped, we want every character tested */
- blf_glyph_render(font, gc, g, (float)pen_x, (float)pen_y);
+ blf_glyph_draw(font, gc, g, (float)pen_x, (float)pen_y);
pen_x += g->advance_i;
g_prev = g;
- c_prev = c;
}
blf_batch_draw_end();
@@ -415,7 +397,6 @@ void blf_font_draw(FontBLF *font, const char *str, const size_t str_len, struct
/* use fixed column width, but an utf8 character may occupy multiple columns */
int blf_font_draw_mono(FontBLF *font, const char *str, const size_t str_len, int cwidth)
{
- unsigned int c;
GlyphBLF *g;
int col, columns = 0;
int pen_x = 0, pen_y = 0;
@@ -426,19 +407,15 @@ int blf_font_draw_mono(FontBLF *font, const char *str, const size_t str_len, int
blf_batch_draw_begin(font);
while ((i < str_len) && str[i]) {
- g = blf_utf8_next_fast(font, gc, str, str_len, &i, &c);
+ g = blf_glyph_from_utf8_and_step(font, gc, str, str_len, &i);
- if (UNLIKELY(c == BLI_UTF8_ERR)) {
- break;
- }
if (UNLIKELY(g == NULL)) {
continue;
}
-
/* do not return this loop if clipped, we want every character tested */
- blf_glyph_render(font, gc, g, (float)pen_x, (float)pen_y);
+ blf_glyph_draw(font, gc, g, (float)pen_x, (float)pen_y);
- col = BLI_wcwidth((char32_t)c);
+ col = BLI_wcwidth((char32_t)g->c);
if (col < 0) {
col = 1;
}
@@ -467,7 +444,6 @@ static void blf_font_draw_buffer_ex(FontBLF *font,
struct ResultBLF *r_info,
int pen_y)
{
- unsigned int c, c_prev = BLI_UTF8_ERR;
GlyphBLF *g, *g_prev = NULL;
int pen_x = (int)font->pos[0];
int pen_y_basis = (int)font->pos[1] + pen_y;
@@ -483,15 +459,12 @@ static void blf_font_draw_buffer_ex(FontBLF *font,
/* another buffer specific call for color conversion */
while ((i < str_len) && str[i]) {
- g = blf_utf8_next_fast(font, gc, str, str_len, &i, &c);
+ g = blf_glyph_from_utf8_and_step(font, gc, str, str_len, &i);
- if (UNLIKELY(c == BLI_UTF8_ERR)) {
- break;
- }
if (UNLIKELY(g == NULL)) {
continue;
}
- blf_kerning_step_fast(font, g_prev, g, c_prev, c, &pen_x);
+ pen_x += blf_kerning(font, g_prev, g);
chx = pen_x + ((int)g->pos[0]);
chy = pen_y_basis + g->dims[1];
@@ -588,7 +561,6 @@ static void blf_font_draw_buffer_ex(FontBLF *font,
pen_x += g->advance_i;
g_prev = g;
- c_prev = c;
}
if (r_info) {
@@ -610,38 +582,29 @@ void blf_font_draw_buffer(FontBLF *font,
/** \} */
/* -------------------------------------------------------------------- */
-/** \name Text Evaluation: Width to Sting Length
+/** \name Text Evaluation: Width to String Length
*
* Use to implement exported functions:
* - #BLF_width_to_strlen
* - #BLF_width_to_rstrlen
* \{ */
-static bool blf_font_width_to_strlen_glyph_process(FontBLF *font,
- const uint c_prev,
- const uint c,
- GlyphBLF *g_prev,
- GlyphBLF *g,
- int *pen_x,
- const int width_i)
+static bool blf_font_width_to_strlen_glyph_process(
+ FontBLF *font, GlyphBLF *g_prev, GlyphBLF *g, int *pen_x, const int width_i)
{
- if (UNLIKELY(c == BLI_UTF8_ERR)) {
- return true; /* break the calling loop. */
- }
if (UNLIKELY(g == NULL)) {
return false; /* continue the calling loop. */
}
- blf_kerning_step_fast(font, g_prev, g, c_prev, c, pen_x);
-
+ *pen_x += blf_kerning(font, g_prev, g);
*pen_x += g->advance_i;
+ /* When true, break the calling loop. */
return (*pen_x >= width_i);
}
size_t blf_font_width_to_strlen(
FontBLF *font, const char *str, const size_t str_len, float width, float *r_width)
{
- unsigned int c, c_prev = BLI_UTF8_ERR;
GlyphBLF *g, *g_prev;
int pen_x, width_new;
size_t i, i_prev;
@@ -649,11 +612,11 @@ size_t blf_font_width_to_strlen(
GlyphCacheBLF *gc = blf_glyph_cache_acquire(font);
const int width_i = (int)width;
- for (i_prev = i = 0, width_new = pen_x = 0, g_prev = NULL, c_prev = 0; (i < str_len) && str[i];
- i_prev = i, width_new = pen_x, c_prev = c, g_prev = g) {
- g = blf_utf8_next_fast(font, gc, str, str_len, &i, &c);
+ for (i_prev = i = 0, width_new = pen_x = 0, g_prev = NULL; (i < str_len) && str[i];
+ i_prev = i, width_new = pen_x, g_prev = g) {
+ g = blf_glyph_from_utf8_and_step(font, gc, str, str_len, &i);
- if (blf_font_width_to_strlen_glyph_process(font, c_prev, c, g_prev, g, &pen_x, width_i)) {
+ if (blf_font_width_to_strlen_glyph_process(font, g_prev, g, &pen_x, width_i)) {
break;
}
}
@@ -669,7 +632,6 @@ size_t blf_font_width_to_strlen(
size_t blf_font_width_to_rstrlen(
FontBLF *font, const char *str, const size_t str_len, float width, float *r_width)
{
- unsigned int c, c_prev = BLI_UTF8_ERR;
GlyphBLF *g, *g_prev;
int pen_x, width_new;
size_t i, i_prev, i_tmp;
@@ -685,19 +647,19 @@ size_t blf_font_width_to_rstrlen(
i_prev = (size_t)(s_prev - str);
i_tmp = i;
- g = blf_utf8_next_fast(font, gc, str, str_len, &i_tmp, &c);
+ g = blf_glyph_from_utf8_and_step(font, gc, str, str_len, &i_tmp);
for (width_new = pen_x = 0; (s != NULL);
- i = i_prev, s = s_prev, c = c_prev, g = g_prev, g_prev = NULL, width_new = pen_x) {
+ i = i_prev, s = s_prev, g = g_prev, g_prev = NULL, width_new = pen_x) {
s_prev = BLI_str_find_prev_char_utf8(s, str);
i_prev = (size_t)(s_prev - str);
if (s_prev != NULL) {
i_tmp = i_prev;
- g_prev = blf_utf8_next_fast(font, gc, str, str_len, &i_tmp, &c_prev);
+ g_prev = blf_glyph_from_utf8_and_step(font, gc, str, str_len, &i_tmp);
BLI_assert(i_tmp == i);
}
- if (blf_font_width_to_strlen_glyph_process(font, c_prev, c, g_prev, g, &pen_x, width_i)) {
+ if (blf_font_width_to_strlen_glyph_process(font, g_prev, g, &pen_x, width_i)) {
break;
}
}
@@ -724,7 +686,6 @@ static void blf_font_boundbox_ex(FontBLF *font,
struct ResultBLF *r_info,
int pen_y)
{
- unsigned int c, c_prev = BLI_UTF8_ERR;
GlyphBLF *g, *g_prev = NULL;
int pen_x = 0;
size_t i = 0;
@@ -736,15 +697,12 @@ static void blf_font_boundbox_ex(FontBLF *font,
box->ymax = -32000.0f;
while ((i < str_len) && str[i]) {
- g = blf_utf8_next_fast(font, gc, str, str_len, &i, &c);
+ g = blf_glyph_from_utf8_and_step(font, gc, str, str_len, &i);
- if (UNLIKELY(c == BLI_UTF8_ERR)) {
- break;
- }
if (UNLIKELY(g == NULL)) {
continue;
}
- blf_kerning_step_fast(font, g_prev, g, c_prev, c, &pen_x);
+ pen_x += blf_kerning(font, g_prev, g);
gbox.xmin = (float)pen_x;
gbox.xmax = (float)pen_x + g->advance;
@@ -767,7 +725,6 @@ static void blf_font_boundbox_ex(FontBLF *font,
pen_x += g->advance_i;
g_prev = g;
- c_prev = c;
}
if (box->xmin > box->xmax) {
@@ -869,22 +826,7 @@ float blf_font_height(FontBLF *font,
float blf_font_fixed_width(FontBLF *font)
{
- const unsigned int c = ' ';
-
- GlyphCacheBLF *gc = blf_glyph_cache_acquire(font);
- GlyphBLF *g = blf_glyph_search(gc, c);
- if (!g) {
- g = blf_glyph_add(font, gc, FT_Get_Char_Index(font->face, c), c);
-
- /* if we don't find the glyph. */
- if (!g) {
- blf_glyph_cache_release(font);
- return 0.0f;
- }
- }
-
- blf_glyph_cache_release(font);
- return g->advance;
+ return (float)font->fixed_width;
}
static void blf_font_boundbox_foreach_glyph_ex(FontBLF *font,
@@ -896,7 +838,6 @@ static void blf_font_boundbox_foreach_glyph_ex(FontBLF *font,
struct ResultBLF *r_info,
int pen_y)
{
- unsigned int c, c_prev = BLI_UTF8_ERR;
GlyphBLF *g, *g_prev = NULL;
int pen_x = 0;
size_t i = 0, i_curr;
@@ -909,15 +850,12 @@ static void blf_font_boundbox_foreach_glyph_ex(FontBLF *font,
while ((i < str_len) && str[i]) {
i_curr = i;
- g = blf_utf8_next_fast(font, gc, str, str_len, &i, &c);
+ g = blf_glyph_from_utf8_and_step(font, gc, str, str_len, &i);
- if (UNLIKELY(c == BLI_UTF8_ERR)) {
- break;
- }
if (UNLIKELY(g == NULL)) {
continue;
}
- blf_kerning_step_fast(font, g_prev, g, c_prev, c, &pen_x);
+ pen_x += blf_kerning(font, g_prev, g);
gbox.xmin = pen_x;
gbox.xmax = gbox.xmin + MIN2(g->advance_i, g->dims[0]);
@@ -931,7 +869,6 @@ static void blf_font_boundbox_foreach_glyph_ex(FontBLF *font,
}
g_prev = g;
- c_prev = c;
}
if (r_info) {
@@ -978,7 +915,6 @@ static void blf_font_wrap_apply(FontBLF *font,
void *userdata),
void *userdata)
{
- unsigned int c, c_prev = BLI_UTF8_ERR;
GlyphBLF *g, *g_prev = NULL;
int pen_x = 0, pen_y = 0;
size_t i = 0;
@@ -999,15 +935,12 @@ static void blf_font_wrap_apply(FontBLF *font,
size_t i_curr = i;
bool do_draw = false;
- g = blf_utf8_next_fast(font, gc, str, str_len, &i, &c);
+ g = blf_glyph_from_utf8_and_step(font, gc, str, str_len, &i);
- if (UNLIKELY(c == BLI_UTF8_ERR)) {
- break;
- }
if (UNLIKELY(g == NULL)) {
continue;
}
- blf_kerning_step_fast(font, g_prev, g, c_prev, c, &pen_x);
+ pen_x += blf_kerning(font, g_prev, g);
/**
* Implementation Detail (utf8).
@@ -1045,16 +978,14 @@ static void blf_font_wrap_apply(FontBLF *font,
wrap.start = wrap.last[0];
i = wrap.last[1];
pen_x = 0;
- pen_y -= gc->glyph_height_max;
+ pen_y -= blf_font_height_max(font);
g_prev = NULL;
- c_prev = BLI_UTF8_ERR;
lines += 1;
continue;
}
pen_x = pen_x_next;
g_prev = g;
- c_prev = c;
}
// printf("done! lines: %d, width, %d\n", lines, pen_x_next);
@@ -1170,45 +1101,41 @@ int blf_font_count_missing_chars(FontBLF *font,
int blf_font_height_max(FontBLF *font)
{
int height_max;
-
- GlyphCacheBLF *gc = blf_glyph_cache_acquire(font);
- height_max = gc->glyph_height_max;
-
- blf_glyph_cache_release(font);
- return height_max;
+ if (FT_IS_SCALABLE(font->face)) {
+ height_max = (int)((float)(font->face->ascender - font->face->descender) *
+ (((float)font->face->size->metrics.y_ppem) /
+ ((float)font->face->units_per_EM)));
+ }
+ else {
+ height_max = (int)(((float)font->face->size->metrics.height) / 64.0f);
+ }
+ /* can happen with size 1 fonts */
+ return MAX2(height_max, 1);
}
int blf_font_width_max(FontBLF *font)
{
int width_max;
-
- GlyphCacheBLF *gc = blf_glyph_cache_acquire(font);
- width_max = gc->glyph_width_max;
-
- blf_glyph_cache_release(font);
- return width_max;
+ if (FT_IS_SCALABLE(font->face)) {
+ width_max = (int)((float)(font->face->bbox.xMax - font->face->bbox.xMin) *
+ (((float)font->face->size->metrics.x_ppem) /
+ ((float)font->face->units_per_EM)));
+ }
+ else {
+ width_max = (int)(((float)font->face->size->metrics.max_advance) / 64.0f);
+ }
+ /* can happen with size 1 fonts */
+ return MAX2(width_max, 1);
}
float blf_font_descender(FontBLF *font)
{
- float descender;
-
- GlyphCacheBLF *gc = blf_glyph_cache_acquire(font);
- descender = gc->descender;
-
- blf_glyph_cache_release(font);
- return descender;
+ return ((float)font->face->size->metrics.descender) / 64.0f;
}
float blf_font_ascender(FontBLF *font)
{
- float ascender;
-
- GlyphCacheBLF *gc = blf_glyph_cache_acquire(font);
- ascender = gc->ascender;
-
- blf_glyph_cache_release(font);
- return ascender;
+ return ((float)font->face->size->metrics.ascender) / 64.0f;
}
char *blf_display_name(FontBLF *font)
@@ -1241,6 +1168,14 @@ void blf_font_exit(void)
blf_batch_draw_exit();
}
+/**
+ * Optional cache flushing function, called before #blf_batch_draw.
+ */
+void BLF_cache_flush_set_fn(void (*cache_flush_fn)(void))
+{
+ blf_draw_cache_flush = cache_flush_fn;
+}
+
/** \} */
/* -------------------------------------------------------------------- */
@@ -1415,19 +1350,24 @@ void blf_font_free(FontBLF *font)
/** \name Font Configure
* \{ */
-void blf_font_size(FontBLF *font, unsigned int size, unsigned int dpi)
+void blf_font_size(FontBLF *font, float size, unsigned int dpi)
{
blf_glyph_cache_acquire(font);
+ /* FreeType uses fixed-point integers in 64ths. */
+ FT_F26Dot6 ft_size = lroundf(size * 64.0f);
+ /* Adjust our size to be on even 64ths. */
+ size = (float)ft_size / 64.0f;
+
GlyphCacheBLF *gc = blf_glyph_cache_find(font, size, dpi);
if (gc && (font->size == size && font->dpi == dpi)) {
/* Optimization: do not call FT_Set_Char_Size if size did not change. */
}
else {
- const FT_Error err = FT_Set_Char_Size(font->face, 0, ((FT_F26Dot6)(size)) * 64, dpi, dpi);
+ const FT_Error err = FT_Set_Char_Size(font->face, 0, ft_size, dpi, dpi);
if (err) {
/* FIXME: here we can go through the fixed size and choice a close one */
- printf("The current font don't support the size, %u and dpi, %u\n", size, dpi);
+ printf("The current font don't support the size, %f and dpi, %u\n", size, dpi);
}
else {
font->size = size;
@@ -1439,6 +1379,22 @@ void blf_font_size(FontBLF *font, unsigned int size, unsigned int dpi)
}
blf_glyph_cache_release(font);
+
+ /* Set fixed-width size for monospaced output. */
+ FT_UInt gindex = FT_Get_Char_Index(font->face, U'0');
+ if (gindex) {
+ FT_Fixed advance = 0;
+ FT_Get_Advance(font->face, gindex, FT_LOAD_NO_HINTING, &advance);
+ /* Use CSS 'ch unit' width, advance of zero character. */
+ font->fixed_width = (int)(advance >> 16);
+ }
+ else {
+ /* Font does not contain "0" so use CSS fallback of 1/2 of em. */
+ font->fixed_width = (int)((font->face->size->metrics.height / 2) >> 6);
+ }
+ if (font->fixed_width < 1) {
+ font->fixed_width = 1;
+ }
}
/** \} */
diff --git a/source/blender/blenfont/intern/blf_glyph.c b/source/blender/blenfont/intern/blf_glyph.c
index 6cdf5fc5996..5f14ef433e9 100644
--- a/source/blender/blenfont/intern/blf_glyph.c
+++ b/source/blender/blenfont/intern/blf_glyph.c
@@ -55,27 +55,47 @@
#include "BLI_math_vector.h"
#include "BLI_strict_flags.h"
-GlyphCacheBLF *blf_glyph_cache_find(FontBLF *font, unsigned int size, unsigned int dpi)
+/* -------------------------------------------------------------------- */
+/** \name Internal Utilities
+ * \{ */
+
+/**
+ * Convert a floating point value to a FreeType 16.16 fixed point value.
+ */
+static FT_Fixed to_16dot16(double val)
{
- GlyphCacheBLF *p;
+ return (FT_Fixed)(lround(val * 65536.0));
+}
- p = (GlyphCacheBLF *)font->cache.first;
- while (p) {
- if (p->size == size && p->dpi == dpi && (p->bold == ((font->flags & BLF_BOLD) != 0)) &&
- (p->italic == ((font->flags & BLF_ITALIC) != 0))) {
- return p;
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Glyph Cache
+ * \{ */
+
+/**
+ * Find a glyph cache that matches a size, DPI & styles.
+ */
+GlyphCacheBLF *blf_glyph_cache_find(FontBLF *font, float size, unsigned int dpi)
+{
+ GlyphCacheBLF *gc = (GlyphCacheBLF *)font->cache.first;
+ while (gc) {
+ if (gc->size == size && gc->dpi == dpi && (gc->bold == ((font->flags & BLF_BOLD) != 0)) &&
+ (gc->italic == ((font->flags & BLF_ITALIC) != 0))) {
+ return gc;
}
- p = p->next;
+ gc = gc->next;
}
return NULL;
}
-/* Create a new glyph cache for the current size, dpi, bold, italic. */
+/**
+ * Create a new glyph cache for the current size, DPI & styles.
+ */
GlyphCacheBLF *blf_glyph_cache_new(FontBLF *font)
{
- GlyphCacheBLF *gc;
+ GlyphCacheBLF *gc = (GlyphCacheBLF *)MEM_callocN(sizeof(GlyphCacheBLF), "blf_glyph_cache_new");
- gc = (GlyphCacheBLF *)MEM_callocN(sizeof(GlyphCacheBLF), "blf_glyph_cache_new");
gc->next = NULL;
gc->prev = NULL;
gc->size = font->size;
@@ -86,27 +106,6 @@ GlyphCacheBLF *blf_glyph_cache_new(FontBLF *font)
memset(gc->glyph_ascii_table, 0, sizeof(gc->glyph_ascii_table));
memset(gc->bucket, 0, sizeof(gc->bucket));
- gc->ascender = ((float)font->face->size->metrics.ascender) / 64.0f;
- gc->descender = ((float)font->face->size->metrics.descender) / 64.0f;
-
- if (FT_IS_SCALABLE(font->face)) {
- gc->glyph_width_max = (int)((float)(font->face->bbox.xMax - font->face->bbox.xMin) *
- (((float)font->face->size->metrics.x_ppem) /
- ((float)font->face->units_per_EM)));
-
- gc->glyph_height_max = (int)((float)(font->face->bbox.yMax - font->face->bbox.yMin) *
- (((float)font->face->size->metrics.y_ppem) /
- ((float)font->face->units_per_EM)));
- }
- else {
- gc->glyph_width_max = (int)(((float)font->face->size->metrics.max_advance) / 64.0f);
- gc->glyph_height_max = (int)(((float)font->face->size->metrics.height) / 64.0f);
- }
-
- /* can happen with size 1 fonts */
- CLAMP_MIN(gc->glyph_width_max, 1);
- CLAMP_MIN(gc->glyph_height_max, 1);
-
BLI_addhead(&font->cache, gc);
return gc;
}
@@ -159,59 +158,95 @@ void blf_glyph_cache_free(GlyphCacheBLF *gc)
MEM_freeN(gc);
}
-GlyphBLF *blf_glyph_search(GlyphCacheBLF *gc, unsigned int c)
+/**
+ * Try to find a glyph in cache.
+ *
+ * \return NULL if not found.
+ */
+static GlyphBLF *blf_glyph_cache_find_glyph(GlyphCacheBLF *gc, uint charcode)
{
- GlyphBLF *p;
- unsigned int key;
-
- key = blf_hash(c);
- p = gc->bucket[key].first;
- while (p) {
- if (p->c == c) {
- return p;
+ if (charcode < GLYPH_ASCII_TABLE_SIZE) {
+ return gc->glyph_ascii_table[charcode];
+ }
+
+ GlyphBLF *g = gc->bucket[blf_hash(charcode)].first;
+ while (g) {
+ if (g->c == charcode) {
+ return g;
}
- p = p->next;
+ g = g->next;
}
return NULL;
}
-GlyphBLF *blf_glyph_add(FontBLF *font, GlyphCacheBLF *gc, unsigned int index, unsigned int c)
+/**
+ * Add a rendered glyph to a cache.
+ */
+static GlyphBLF *blf_glyph_cache_add_glyph(
+ FontBLF *font, GlyphCacheBLF *gc, FT_GlyphSlot glyph, uint charcode, FT_UInt glyph_index)
{
- FT_GlyphSlot slot;
- GlyphBLF *g;
- FT_Error err;
- FT_Bitmap bitmap, tempbitmap;
+ GlyphBLF *g = (GlyphBLF *)MEM_callocN(sizeof(GlyphBLF), "blf_glyph_get");
+ g->c = charcode;
+ g->idx = glyph_index;
+ g->advance = ((float)glyph->advance.x) / 64.0f;
+ g->advance_i = (int)g->advance;
+ g->pos[0] = glyph->bitmap_left;
+ g->pos[1] = glyph->bitmap_top;
+ g->dims[0] = (int)glyph->bitmap.width;
+ g->dims[1] = (int)glyph->bitmap.rows;
+ g->pitch = glyph->bitmap.pitch;
+
FT_BBox bbox;
- unsigned int key;
+ FT_Outline_Get_CBox(&(glyph->outline), &bbox);
+ g->box.xmin = ((float)bbox.xMin) / 64.0f;
+ g->box.xmax = ((float)bbox.xMax) / 64.0f;
+ g->box.ymin = ((float)bbox.yMin) / 64.0f;
+ g->box.ymax = ((float)bbox.yMax) / 64.0f;
- g = blf_glyph_search(gc, c);
- if (g) {
- return g;
+ const int buffer_size = (int)(glyph->bitmap.width * glyph->bitmap.rows);
+ if (buffer_size != 0) {
+ if (font->flags & BLF_MONOCHROME) {
+ /* Font buffer uses only 0 or 1 values, Blender expects full 0..255 range. */
+ for (int i = 0; i < buffer_size; i++) {
+ glyph->bitmap.buffer[i] = glyph->bitmap.buffer[i] ? 255 : 0;
+ }
+ }
+ g->bitmap = MEM_mallocN((size_t)buffer_size, "glyph bitmap");
+ memcpy(g->bitmap, glyph->bitmap.buffer, (size_t)buffer_size);
}
- /* glyphs are dynamically created as needed by font rendering. this means that
- * to make font rendering thread safe we have to do locking here. note that this
- * must be a lock for the whole library and not just per font, because the font
- * renderer uses a shared buffer internally */
- BLI_spin_lock(font->ft_lib_mutex);
-
- /* search again after locking */
- g = blf_glyph_search(gc, c);
- if (g) {
- BLI_spin_unlock(font->ft_lib_mutex);
- return g;
+ unsigned int key = blf_hash(g->c);
+ BLI_addhead(&(gc->bucket[key]), g);
+ if (charcode < GLYPH_ASCII_TABLE_SIZE) {
+ gc->glyph_ascii_table[charcode] = g;
}
+ return g;
+}
+
+/**
+ * Return a glyph index from `charcode`. Not found returns zero, which is a valid
+ * printable character (`.notdef` or `tofu`). Font is allowed to change here.
+ */
+static FT_UInt blf_glyph_index_from_charcode(FontBLF **font, const uint charcode)
+{
+ FT_UInt glyph_index = FT_Get_Char_Index((*font)->face, charcode);
+ /* TODO: If not found in this font, check others, update font pointer. */
+ return glyph_index;
+}
+
+/**
+ * Load a glyph into the glyph slot of a font's face object.
+ */
+static FT_GlyphSlot blf_glyph_load(FontBLF *font, FT_UInt glyph_index)
+{
int load_flags;
- int render_mode;
if (font->flags & BLF_MONOCHROME) {
load_flags = FT_LOAD_TARGET_MONO;
- render_mode = FT_RENDER_MODE_MONO;
}
else {
load_flags = FT_LOAD_NO_BITMAP;
- render_mode = FT_RENDER_MODE_NORMAL;
if (font->flags & BLF_HINTING_NONE) {
load_flags |= FT_LOAD_TARGET_NORMAL | FT_LOAD_NO_HINTING;
}
@@ -228,104 +263,222 @@ GlyphBLF *blf_glyph_add(FontBLF *font, GlyphCacheBLF *gc, unsigned int index, un
}
}
- err = FT_Load_Glyph(font->face, (FT_UInt)index, load_flags);
-
- /* Do not oblique a font that is designed to be italic! */
- if (((font->flags & BLF_ITALIC) != 0) && !(font->face->style_flags & FT_STYLE_FLAG_ITALIC) &&
- (font->face->glyph->format == FT_GLYPH_FORMAT_OUTLINE)) {
- /* For (fake) italic: a shear transform with a 6 degree angle. */
- FT_Matrix transform;
- transform.xx = 0x10000L;
- transform.yx = 0x00000L;
- transform.xy = 0x03000L;
- transform.yy = 0x10000L;
- FT_Outline_Transform(&font->face->glyph->outline, &transform);
- }
-
- /* Do not embolden an already bold font! */
- if (((font->flags & BLF_BOLD) != 0) &&
- !(font->face->style_flags & FT_STYLE_FLAG_BOLD) &
- (font->face->glyph->format == FT_GLYPH_FORMAT_OUTLINE)) {
- /* Strengthen the width more than the height. */
- const FT_Pos extra_x = FT_MulFix(font->face->units_per_EM, font->face->size->metrics.x_scale) /
- 14;
- const FT_Pos extra_y = FT_MulFix(font->face->units_per_EM, font->face->size->metrics.y_scale) /
- 28;
- FT_Outline_EmboldenXY(&font->face->glyph->outline, extra_x, extra_y);
- if ((font->face->face_flags & FT_FACE_FLAG_FIXED_WIDTH) == 0) {
- /* Need to increase advance, but not for fixed-width fonts. */
- font->face->glyph->advance.x += (FT_Pos)(((float)extra_x) * 1.05f);
- font->face->glyph->advance.y += extra_y;
- }
- else {
- /* Widened fixed-pitch font gets a nudge left. */
- FT_Outline_Translate(&font->face->glyph->outline, (extra_x / -2), 0);
- }
+ if (FT_Load_Glyph(font->face, glyph_index, load_flags) == 0) {
+ return font->face->glyph;
+ }
+ return NULL;
+}
+
+/**
+ * Convert a glyph from outlines to a bitmap that we can display.
+ */
+static bool blf_glyph_render_bitmap(FontBLF *font, FT_GlyphSlot glyph)
+{
+ int render_mode;
+
+ if (font->flags & BLF_MONOCHROME) {
+ render_mode = FT_RENDER_MODE_MONO;
+ }
+ else {
+ render_mode = FT_RENDER_MODE_NORMAL;
}
- if (err) {
- BLI_spin_unlock(font->ft_lib_mutex);
- return NULL;
+ /* Render the glyph curves to a bitmap. */
+ FT_Error err = FT_Render_Glyph(glyph, render_mode);
+ if (err != 0) {
+ return false;
}
- /* get the glyph. */
- slot = font->face->glyph;
- err = FT_Render_Glyph(slot, render_mode);
+ FT_Bitmap tempbitmap;
if (font->flags & BLF_MONOCHROME) {
/* Convert result from 1 bit per pixel to 8 bit per pixel */
- /* Accum errors for later, fine if not interested beyond "ok vs any error" */
+ /* Accumulate errors for later, fine if not interested beyond "ok vs any error" */
FT_Bitmap_New(&tempbitmap);
/* Does Blender use Pitch 1 always? It works so far */
- err += FT_Bitmap_Convert(font->ft_lib, &slot->bitmap, &tempbitmap, 1);
- err += FT_Bitmap_Copy(font->ft_lib, &tempbitmap, &slot->bitmap);
+ err += FT_Bitmap_Convert(font->ft_lib, &glyph->bitmap, &tempbitmap, 1);
+ err += FT_Bitmap_Copy(font->ft_lib, &tempbitmap, &glyph->bitmap);
err += FT_Bitmap_Done(font->ft_lib, &tempbitmap);
}
- if (err || slot->format != FT_GLYPH_FORMAT_BITMAP) {
- BLI_spin_unlock(font->ft_lib_mutex);
- return NULL;
+ if (err || glyph->format != FT_GLYPH_FORMAT_BITMAP) {
+ return false;
}
- g = (GlyphBLF *)MEM_callocN(sizeof(GlyphBLF), "blf_glyph_add");
- g->c = c;
- g->idx = (FT_UInt)index;
- bitmap = slot->bitmap;
- g->dims[0] = (int)bitmap.width;
- g->dims[1] = (int)bitmap.rows;
+ return true;
+}
- const int buffer_size = g->dims[0] * g->dims[1];
+/** \} */
- if (buffer_size != 0) {
- if (font->flags & BLF_MONOCHROME) {
- /* Font buffer uses only 0 or 1 values, Blender expects full 0..255 range */
- for (int i = 0; i < buffer_size; i++) {
- bitmap.buffer[i] = bitmap.buffer[i] ? 255 : 0;
- }
+/* -------------------------------------------------------------------- */
+/** \name Glyph Transformations
+ * \{ */
+
+/**
+ * Adjust the glyphs weight by a factor.
+ *
+ * \param factor: -1 (min stroke width) <= 0 (normal) => 1 (max boldness).
+ */
+static bool blf_glyph_transform_weight(FT_GlyphSlot glyph, float factor, bool monospaced)
+{
+ if (glyph->format == FT_GLYPH_FORMAT_OUTLINE) {
+ /* Fake bold if the font does not have this variable axis. */
+ const FT_Pos average_width = FT_MulFix(glyph->face->units_per_EM,
+ glyph->face->size->metrics.x_scale);
+ FT_Pos change = (FT_Pos)((float)average_width * factor * 0.1f);
+ FT_Outline_EmboldenXY(&glyph->outline, change, change / 2);
+ if (monospaced) {
+ /* Widened fixed-pitch font needs a nudge left. */
+ FT_Outline_Translate(&glyph->outline, change / -2, 0);
+ }
+ else {
+ /* Need to increase advance. */
+ glyph->advance.x += change;
+ glyph->advance.y += change / 2;
}
+ return true;
+ }
+ return false;
+}
- g->bitmap = MEM_mallocN((size_t)buffer_size, "glyph bitmap");
- memcpy(g->bitmap, bitmap.buffer, (size_t)buffer_size);
+/**
+ * Adjust the glyphs slant by a factor (making it oblique).
+ *
+ * \param factor: -1 (max negative) <= 0 (no slant) => 1 (max positive).
+ *
+ * \note that left-leaning italics are possible in some RTL writing systems.
+ */
+static bool blf_glyph_transform_slant(FT_GlyphSlot glyph, float factor)
+{
+ if (glyph->format == FT_GLYPH_FORMAT_OUTLINE) {
+ FT_Matrix transform = {to_16dot16(1), to_16dot16(factor / 2.0f), 0, to_16dot16(1)};
+ FT_Outline_Transform(&glyph->outline, &transform);
+ return true;
}
+ return false;
+}
- g->advance = ((float)slot->advance.x) / 64.0f;
- g->advance_i = (int)g->advance;
- g->pos[0] = slot->bitmap_left;
- g->pos[1] = slot->bitmap_top;
- g->pitch = slot->bitmap.pitch;
+/**
+ * Adjust the glyph width by factor.
+ *
+ * \param factor: -1 (min width) <= 0 (normal) => 1 (max width).
+ */
+static bool UNUSED_FUNCTION(blf_glyph_transform_width)(FT_GlyphSlot glyph, float factor)
+{
+ if (glyph->format == FT_GLYPH_FORMAT_OUTLINE) {
+ float scale = (factor * 0.4f) + 1.0f; /* 0.6f - 1.4f */
+ FT_Matrix matrix = {to_16dot16(scale), 0, 0, to_16dot16(1)};
+ FT_Outline_Transform(&glyph->outline, &matrix);
+ glyph->advance.x = (FT_Pos)((double)glyph->advance.x * scale);
+ return true;
+ }
+ return false;
+}
- FT_Outline_Get_CBox(&(slot->outline), &bbox);
- g->box.xmin = ((float)bbox.xMin) / 64.0f;
- g->box.xmax = ((float)bbox.xMax) / 64.0f;
- g->box.ymin = ((float)bbox.yMin) / 64.0f;
- g->box.ymax = ((float)bbox.yMax) / 64.0f;
+/**
+ * Transform glyph to fit nicely within a fixed column width.
+ */
+static bool UNUSED_FUNCTION(blf_glyph_transform_monospace)(FT_GlyphSlot glyph, int width)
+{
+ if (glyph->format == FT_GLYPH_FORMAT_OUTLINE) {
+ int gwidth = (int)(glyph->linearHoriAdvance >> 16);
+ if (gwidth > width) {
+ float scale = (float)width / (float)gwidth;
+ FT_Matrix matrix = {to_16dot16(scale), 0, 0, to_16dot16(1)};
+ /* Narrowing all points also thins vertical strokes. */
+ FT_Outline_Transform(&glyph->outline, &matrix);
+ const FT_Pos extra_x = (int)((float)(gwidth - width) * 5.65f);
+ /* Horizontally widen strokes to counteract narrowing. */
+ FT_Outline_EmboldenXY(&glyph->outline, extra_x, 0);
+ }
+ else if (gwidth < width) {
+ /* Narrow glyphs only need to be centered. */
+ int nudge = (width - gwidth) / 2;
+ FT_Outline_Translate(&glyph->outline, (FT_Pos)nudge * 64, 0);
+ }
+ return true;
+ }
+ return false;
+}
- key = blf_hash(g->c);
- BLI_addhead(&(gc->bucket[key]), g);
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Glyph Access (Ensure/Free)
+ * \{ */
+
+/**
+ * Create and return a fully-rendered bitmap glyph.
+ */
+static FT_GlyphSlot blf_glyph_render(FontBLF *settings_font,
+ FontBLF *glyph_font,
+ FT_UInt glyph_index)
+{
+ if (glyph_font != settings_font) {
+ FT_Set_Char_Size(glyph_font->face,
+ 0,
+ ((FT_F26Dot6)(settings_font->size)) * 64,
+ settings_font->dpi,
+ settings_font->dpi);
+ glyph_font->size = settings_font->size;
+ glyph_font->dpi = settings_font->dpi;
+ }
+
+ FT_GlyphSlot glyph = blf_glyph_load(glyph_font, glyph_index);
+ if (!glyph) {
+ return NULL;
+ }
- BLI_spin_unlock(font->ft_lib_mutex);
+ if ((settings_font->flags & BLF_ITALIC) != 0) {
+ /* 37.5% of maximum rightward slant results in 6 degree slope, matching italic
+ * version (`DejaVuSans-Oblique.ttf`) of our current font. But a nice median when
+ * checking others. Worth reevaluating if we change default font. We could also
+ * narrow the glyph slightly as most italics do, but this one does not. */
+ blf_glyph_transform_slant(glyph, 0.375f);
+ }
+ if ((settings_font->flags & BLF_BOLD) != 0) {
+ /* 70% of maximum weight results in the same amount of boldness and horizontal
+ * expansion as the bold version (`DejaVuSans-Bold.ttf`) of our default font.
+ * Worth reevaluating if we change default font. */
+ blf_glyph_transform_weight(glyph, 0.7f, glyph->face->face_flags & FT_FACE_FLAG_FIXED_WIDTH);
+ }
+
+ if (blf_glyph_render_bitmap(glyph_font, glyph)) {
+ return glyph;
+ }
+ return NULL;
+}
+
+/**
+ * Create (or load from cache) a fully-rendered bitmap glyph.
+ */
+GlyphBLF *blf_glyph_ensure(FontBLF *font, GlyphCacheBLF *gc, uint charcode)
+{
+ GlyphBLF *g = blf_glyph_cache_find_glyph(gc, charcode);
+ if (g) {
+ return g;
+ }
+
+ /* Glyph might not come from the initial font. */
+ FontBLF *font_with_glyph = font;
+ FT_UInt glyph_index = blf_glyph_index_from_charcode(&font_with_glyph, charcode);
+
+ /* Glyphs are dynamically created as needed by font rendering. this means that
+ * to make font rendering thread safe we have to do locking here. note that this
+ * must be a lock for the whole library and not just per font, because the font
+ * renderer uses a shared buffer internally. */
+ BLI_spin_lock(font_with_glyph->ft_lib_mutex);
+
+ FT_GlyphSlot glyph = blf_glyph_render(font, font_with_glyph, glyph_index);
+
+ if (glyph) {
+ /* Save this glyph in the initial font's cache. */
+ g = blf_glyph_cache_add_glyph(font, gc, glyph, charcode, glyph_index);
+ }
+
+ BLI_spin_unlock(font_with_glyph->ft_lib_mutex);
return g;
}
@@ -337,6 +490,42 @@ void blf_glyph_free(GlyphBLF *g)
MEM_freeN(g);
}
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Glyph Bounds Calculation
+ * \{ */
+
+static void blf_glyph_calc_rect(rctf *rect, GlyphBLF *g, float x, float y)
+{
+ rect->xmin = floorf(x + (float)g->pos[0]);
+ rect->xmax = rect->xmin + (float)g->dims[0];
+ rect->ymin = floorf(y + (float)g->pos[1]);
+ rect->ymax = rect->ymin - (float)g->dims[1];
+}
+
+static void blf_glyph_calc_rect_test(rctf *rect, GlyphBLF *g, float x, float y)
+{
+ /* Intentionally check with `g->advance`, because this is the
+ * width used by BLF_width. This allows that the text slightly
+ * overlaps the clipping border to achieve better alignment. */
+ rect->xmin = floorf(x);
+ rect->xmax = rect->xmin + MIN2(g->advance, (float)g->dims[0]);
+ rect->ymin = floorf(y);
+ rect->ymax = rect->ymin - (float)g->dims[1];
+}
+
+static void blf_glyph_calc_rect_shadow(rctf *rect, GlyphBLF *g, float x, float y, FontBLF *font)
+{
+ blf_glyph_calc_rect(rect, g, x + (float)font->shadow_x, y + (float)font->shadow_y);
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Glyph Drawing
+ * \{ */
+
static void blf_texture_draw(const unsigned char color[4],
const int glyph_size[2],
const int offset,
@@ -395,31 +584,7 @@ static void blf_texture3_draw(const unsigned char color_in[4],
blf_texture_draw(color_in, glyph_size_flag, offset, x1, y1, x2, y2);
}
-static void blf_glyph_calc_rect(rctf *rect, GlyphBLF *g, float x, float y)
-{
- rect->xmin = floorf(x + (float)g->pos[0]);
- rect->xmax = rect->xmin + (float)g->dims[0];
- rect->ymin = floorf(y + (float)g->pos[1]);
- rect->ymax = rect->ymin - (float)g->dims[1];
-}
-
-static void blf_glyph_calc_rect_test(rctf *rect, GlyphBLF *g, float x, float y)
-{
- /* Intentionally check with g->advance, because this is the
- * width used by BLF_width. This allows that the text slightly
- * overlaps the clipping border to achieve better alignment. */
- rect->xmin = floorf(x);
- rect->xmax = rect->xmin + MIN2(g->advance, (float)g->dims[0]);
- rect->ymin = floorf(y);
- rect->ymax = rect->ymin - (float)g->dims[1];
-}
-
-static void blf_glyph_calc_rect_shadow(rctf *rect, GlyphBLF *g, float x, float y, FontBLF *font)
-{
- blf_glyph_calc_rect(rect, g, x + (float)font->shadow_x, y + (float)font->shadow_y);
-}
-
-void blf_glyph_render(FontBLF *font, GlyphCacheBLF *gc, GlyphBLF *g, float x, float y)
+void blf_glyph_draw(FontBLF *font, GlyphCacheBLF *gc, GlyphBLF *g, float x, float y)
{
if ((!g->dims[0]) || (!g->dims[1])) {
return;
@@ -526,3 +691,5 @@ void blf_glyph_render(FontBLF *font, GlyphCacheBLF *gc, GlyphBLF *g, float x, fl
blf_texture_draw(font->color, g->dims, g->offset, rect.xmin, rect.ymin, rect.xmax, rect.ymax);
#endif
}
+
+/** \} */
diff --git a/source/blender/blenfont/intern/blf_internal.h b/source/blender/blenfont/intern/blf_internal.h
index 6fd5e8b7503..cec20995dc6 100644
--- a/source/blender/blenfont/intern/blf_internal.h
+++ b/source/blender/blenfont/intern/blf_internal.h
@@ -52,7 +52,7 @@ struct FontBLF *blf_font_new(const char *name, const char *filename);
struct FontBLF *blf_font_new_from_mem(const char *name, const unsigned char *mem, int mem_size);
void blf_font_attach_from_mem(struct FontBLF *font, const unsigned char *mem, int mem_size);
-void blf_font_size(struct FontBLF *font, unsigned int size, unsigned int dpi);
+void blf_font_size(struct FontBLF *font, float size, unsigned int dpi);
void blf_font_draw(struct FontBLF *font,
const char *str,
size_t str_len,
@@ -130,23 +130,17 @@ int blf_font_count_missing_chars(struct FontBLF *font,
void blf_font_free(struct FontBLF *font);
-struct GlyphCacheBLF *blf_glyph_cache_find(struct FontBLF *font,
- unsigned int size,
- unsigned int dpi);
+struct GlyphCacheBLF *blf_glyph_cache_find(struct FontBLF *font, float size, unsigned int dpi);
struct GlyphCacheBLF *blf_glyph_cache_new(struct FontBLF *font);
struct GlyphCacheBLF *blf_glyph_cache_acquire(struct FontBLF *font);
void blf_glyph_cache_release(struct FontBLF *font);
void blf_glyph_cache_clear(struct FontBLF *font);
void blf_glyph_cache_free(struct GlyphCacheBLF *gc);
-struct GlyphBLF *blf_glyph_search(struct GlyphCacheBLF *gc, unsigned int c);
-struct GlyphBLF *blf_glyph_add(struct FontBLF *font,
- struct GlyphCacheBLF *gc,
- unsigned int index,
- unsigned int c);
+struct GlyphBLF *blf_glyph_ensure(struct FontBLF *font, struct GlyphCacheBLF *gc, uint charcode);
void blf_glyph_free(struct GlyphBLF *g);
-void blf_glyph_render(
+void blf_glyph_draw(
struct FontBLF *font, struct GlyphCacheBLF *gc, struct GlyphBLF *g, float x, float y);
#ifdef WIN32
diff --git a/source/blender/blenfont/intern/blf_internal_types.h b/source/blender/blenfont/intern/blf_internal_types.h
index e90f82da7f3..46156edbb1f 100644
--- a/source/blender/blenfont/intern/blf_internal_types.h
+++ b/source/blender/blenfont/intern/blf_internal_types.h
@@ -65,7 +65,7 @@ typedef struct GlyphCacheBLF {
struct GlyphCacheBLF *prev;
/* font size. */
- unsigned int size;
+ float size;
/* and dpi. */
unsigned int dpi;
@@ -86,13 +86,6 @@ typedef struct GlyphCacheBLF {
int bitmap_len_landed;
int bitmap_len_alloc;
- /* and the bigger glyph in the font. */
- int glyph_width_max;
- int glyph_height_max;
-
- /* ascender and descender value. */
- float ascender;
- float descender;
} GlyphCacheBLF;
typedef struct GlyphBLF {
@@ -212,7 +205,10 @@ typedef struct FontBLF {
unsigned int dpi;
/* font size. */
- unsigned int size;
+ float size;
+
+ /* Column width when printing monospaced. */
+ int fixed_width;
/* max texture size. */
int tex_size_max;
diff --git a/source/blender/blenfont/intern/blf_thumbs.c b/source/blender/blenfont/intern/blf_thumbs.c
index 3153a55b697..bbdb26a61b6 100644
--- a/source/blender/blenfont/intern/blf_thumbs.c
+++ b/source/blender/blenfont/intern/blf_thumbs.c
@@ -95,7 +95,7 @@ void BLF_thumb_preview(const char *filename,
const size_t draw_str_i18n_len = strlen(draw_str_i18n);
int draw_str_i18n_nbr = 0;
- blf_font_size(font, (unsigned int)MAX2(font_size_min, font_size_curr), dpi);
+ blf_font_size(font, (float)MAX2(font_size_min, font_size_curr), dpi);
gc = blf_glyph_cache_find(font, font->size, font->dpi);
/* There will be no matching glyph cache if blf_font_size() failed to set font size. */
if (!gc) {
@@ -106,7 +106,7 @@ void BLF_thumb_preview(const char *filename,
font_size_curr -= (font_size_curr / font_shrink);
font_shrink += 1;
- font->pos[1] -= gc->ascender * 1.1f;
+ font->pos[1] -= blf_font_ascender(font) * 1.1f;
/* We fallback to default english strings in case not enough chars are available in current
* font for given translated string (useful in non-latin i18n context, like Chinese,
diff --git a/source/blender/blenkernel/BKE_action.h b/source/blender/blenkernel/BKE_action.h
index db55daddba6..763e540fdd9 100644
--- a/source/blender/blenkernel/BKE_action.h
+++ b/source/blender/blenkernel/BKE_action.h
@@ -128,11 +128,12 @@ void action_groups_clear_tempflags(struct bAction *act);
/**
* Return whether the action has one unique point in time keyed.
*
- * This is mostly for the pose library, which will have different behaviour depending on whether an
+ * This is mostly for the pose library, which will have different behavior depending on whether an
* Action corresponds to a "pose" (one keyframe) or "animation snippet" (multiple keyframes).
*
* \return `false` when there is no keyframe at all or keys on different points in time, `true`
- * when exactly one point in time is keyed. */
+ * when exactly one point in time is keyed.
+ */
bool BKE_action_has_single_frame(const struct bAction *act);
/* Pose API ----------------- */
diff --git a/source/blender/blenkernel/BKE_asset_catalog.hh b/source/blender/blenkernel/BKE_asset_catalog.hh
index bdb77571711..d071f782bd6 100644
--- a/source/blender/blenkernel/BKE_asset_catalog.hh
+++ b/source/blender/blenkernel/BKE_asset_catalog.hh
@@ -443,7 +443,9 @@ class AssetCatalog {
* Simple, human-readable name for the asset catalog. This is stored on assets alongside the
* catalog ID; the catalog ID is a UUID that is not human-readable,
* so to avoid complete data-loss when the catalog definition file gets lost,
- * we also store a human-readable simple name for the catalog. */
+ * we also store a human-readable simple name for the catalog.
+ *
+ * It should fit in sizeof(AssetMetaData::catalog_simple_name) bytes. */
std::string simple_name;
struct Flags {
diff --git a/source/blender/blenkernel/BKE_attribute.h b/source/blender/blenkernel/BKE_attribute.h
index 7476474258b..2c83bef7517 100644
--- a/source/blender/blenkernel/BKE_attribute.h
+++ b/source/blender/blenkernel/BKE_attribute.h
@@ -43,12 +43,13 @@ struct ReportList;
* Arrays may be initialized from this (e.g. #DATASET_layout_hierarchy).
*/
typedef enum AttributeDomain {
- ATTR_DOMAIN_AUTO = -1, /* Use for nodes to choose automatically based on other data. */
- ATTR_DOMAIN_POINT = 0, /* Mesh, Hair or PointCloud Point */
- ATTR_DOMAIN_EDGE = 1, /* Mesh Edge */
- ATTR_DOMAIN_FACE = 2, /* Mesh Face */
- ATTR_DOMAIN_CORNER = 3, /* Mesh Corner */
- ATTR_DOMAIN_CURVE = 4, /* Hair Curve */
+ ATTR_DOMAIN_AUTO = -1, /* Use for nodes to choose automatically based on other data. */
+ ATTR_DOMAIN_POINT = 0, /* Mesh, Hair or PointCloud Point */
+ ATTR_DOMAIN_EDGE = 1, /* Mesh Edge */
+ ATTR_DOMAIN_FACE = 2, /* Mesh Face */
+ ATTR_DOMAIN_CORNER = 3, /* Mesh Corner */
+ ATTR_DOMAIN_CURVE = 4, /* Hair Curve */
+ ATTR_DOMAIN_INSTANCE = 5, /* Instance */
ATTR_DOMAIN_NUM
} AttributeDomain;
diff --git a/source/blender/blenkernel/BKE_attribute_access.hh b/source/blender/blenkernel/BKE_attribute_access.hh
index 6a87375e5e2..47f62b52a0f 100644
--- a/source/blender/blenkernel/BKE_attribute_access.hh
+++ b/source/blender/blenkernel/BKE_attribute_access.hh
@@ -115,10 +115,10 @@ struct AttributeInitDefault : public AttributeInit {
* Note that this can be used to fill the new attribute with the default
*/
struct AttributeInitVArray : public AttributeInit {
- const blender::fn::GVArray *varray;
+ blender::fn::GVArray varray;
- AttributeInitVArray(const blender::fn::GVArray *varray)
- : AttributeInit(Type::VArray), varray(varray)
+ AttributeInitVArray(blender::fn::GVArray varray)
+ : AttributeInit(Type::VArray), varray(std::move(varray))
{
}
};
@@ -150,9 +150,7 @@ namespace blender::bke {
using fn::CPPType;
using fn::GVArray;
-using fn::GVArrayPtr;
using fn::GVMutableArray;
-using fn::GVMutableArrayPtr;
const CPPType *custom_data_type_to_cpp_type(const CustomDataType type);
CustomDataType cpp_type_to_custom_data_type(const CPPType &type);
@@ -164,14 +162,14 @@ AttributeDomain attribute_domain_highest_priority(Span<AttributeDomain> domains)
*/
struct ReadAttributeLookup {
/* The virtual array that is used to read from this attribute. */
- GVArrayPtr varray;
+ GVArray varray;
/* Domain the attribute lives on in the geometry. */
AttributeDomain domain;
/* Convenience function to check if the attribute has been found. */
operator bool() const
{
- return this->varray.get() != nullptr;
+ return this->varray;
}
};
@@ -180,7 +178,7 @@ struct ReadAttributeLookup {
*/
struct WriteAttributeLookup {
/* The virtual array that is used to read from and write to the attribute. */
- GVMutableArrayPtr varray;
+ GVMutableArray varray;
/* Domain the attributes lives on in the geometry. */
AttributeDomain domain;
/* Call this after changing the attribute to invalidate caches that depend on this attribute. */
@@ -189,7 +187,7 @@ struct WriteAttributeLookup {
/* Convenience function to check if the attribute has been found. */
operator bool() const
{
- return this->varray.get() != nullptr;
+ return this->varray;
}
};
@@ -209,7 +207,7 @@ class OutputAttribute {
using SaveFn = std::function<void(OutputAttribute &)>;
private:
- GVMutableArrayPtr varray_;
+ GVMutableArray varray_;
AttributeDomain domain_ = ATTR_DOMAIN_AUTO;
SaveFn save_;
std::unique_ptr<fn::GVMutableArray_GSpan> optional_span_varray_;
@@ -219,7 +217,7 @@ class OutputAttribute {
public:
OutputAttribute();
OutputAttribute(OutputAttribute &&other);
- OutputAttribute(GVMutableArrayPtr varray,
+ OutputAttribute(GVMutableArray varray,
AttributeDomain domain,
SaveFn save,
const bool ignore_old_values);
@@ -229,7 +227,7 @@ class OutputAttribute {
operator bool() const;
GVMutableArray &operator*();
- GVMutableArray *operator->();
+ fn::GVMutableArray *operator->();
GVMutableArray &varray();
AttributeDomain domain() const;
const CPPType &cpp_type() const;
@@ -247,16 +245,14 @@ class OutputAttribute {
template<typename T> class OutputAttribute_Typed {
private:
OutputAttribute attribute_;
- std::unique_ptr<fn::GVMutableArray_Typed<T>> optional_varray_;
- VMutableArray<T> *varray_ = nullptr;
+ VMutableArray<T> varray_;
public:
OutputAttribute_Typed();
OutputAttribute_Typed(OutputAttribute attribute) : attribute_(std::move(attribute))
{
if (attribute_) {
- optional_varray_ = std::make_unique<fn::GVMutableArray_Typed<T>>(attribute_.varray());
- varray_ = &**optional_varray_;
+ varray_ = attribute_.varray().template typed<T>();
}
}
@@ -275,22 +271,22 @@ template<typename T> class OutputAttribute_Typed {
operator bool() const
{
- return varray_ != nullptr;
+ return varray_;
}
VMutableArray<T> &operator*()
{
- return *varray_;
+ return varray_;
}
VMutableArray<T> *operator->()
{
- return varray_;
+ return &varray_;
}
VMutableArray<T> &varray()
{
- return *varray_;
+ return varray_;
}
AttributeDomain domain() const
@@ -351,18 +347,17 @@ class CustomDataAttributes {
std::optional<blender::fn::GSpan> get_for_read(const AttributeIDRef &attribute_id) const;
- blender::fn::GVArrayPtr get_for_read(const AttributeIDRef &attribute_id,
- const CustomDataType data_type,
- const void *default_value) const;
+ blender::fn::GVArray get_for_read(const AttributeIDRef &attribute_id,
+ const CustomDataType data_type,
+ const void *default_value) const;
template<typename T>
- blender::fn::GVArray_Typed<T> get_for_read(const AttributeIDRef &attribute_id,
- const T &default_value) const
+ blender::VArray<T> get_for_read(const AttributeIDRef &attribute_id, const T &default_value) const
{
const blender::fn::CPPType &cpp_type = blender::fn::CPPType::get<T>();
const CustomDataType type = blender::bke::cpp_type_to_custom_data_type(cpp_type);
- GVArrayPtr varray = this->get_for_read(attribute_id, type, &default_value);
- return blender::fn::GVArray_Typed<T>(std::move(varray));
+ GVArray varray = this->get_for_read(attribute_id, type, &default_value);
+ return varray.typed<T>();
}
std::optional<blender::fn::GMutableSpan> get_for_write(const AttributeIDRef &attribute_id);
@@ -465,7 +460,7 @@ inline bool AttributeIDRef::should_be_kept() const
inline OutputAttribute::OutputAttribute() = default;
inline OutputAttribute::OutputAttribute(OutputAttribute &&other) = default;
-inline OutputAttribute::OutputAttribute(GVMutableArrayPtr varray,
+inline OutputAttribute::OutputAttribute(GVMutableArray varray,
AttributeDomain domain,
SaveFn save,
const bool ignore_old_values)
@@ -478,22 +473,22 @@ inline OutputAttribute::OutputAttribute(GVMutableArrayPtr varray,
inline OutputAttribute::operator bool() const
{
- return varray_.get() != nullptr;
+ return varray_;
}
inline GVMutableArray &OutputAttribute::operator*()
{
- return *varray_;
+ return varray_;
}
-inline GVMutableArray *OutputAttribute::operator->()
+inline fn::GVMutableArray *OutputAttribute::operator->()
{
- return varray_.get();
+ return &varray_;
}
inline GVMutableArray &OutputAttribute::varray()
{
- return *varray_;
+ return varray_;
}
inline AttributeDomain OutputAttribute::domain() const
@@ -503,7 +498,7 @@ inline AttributeDomain OutputAttribute::domain() const
inline const CPPType &OutputAttribute::cpp_type() const
{
- return varray_->type();
+ return varray_.type();
}
inline CustomDataType OutputAttribute::custom_data_type() const
diff --git a/source/blender/blenkernel/BKE_blender_copybuffer.h b/source/blender/blenkernel/BKE_blender_copybuffer.h
index 1dd6d495276..4dd7145e66d 100644
--- a/source/blender/blenkernel/BKE_blender_copybuffer.h
+++ b/source/blender/blenkernel/BKE_blender_copybuffer.h
@@ -31,16 +31,18 @@ struct ReportList;
struct bContext;
/* copybuffer (wrapper for BKE_blendfile_write_partial) */
-void BKE_copybuffer_begin(struct Main *bmain_src);
-void BKE_copybuffer_tag_ID(struct ID *id);
-bool BKE_copybuffer_save(struct Main *bmain_src, const char *filename, struct ReportList *reports);
+void BKE_copybuffer_copy_begin(struct Main *bmain_src);
+void BKE_copybuffer_copy_tag_ID(struct ID *id);
+bool BKE_copybuffer_copy_end(struct Main *bmain_src,
+ const char *filename,
+ struct ReportList *reports);
bool BKE_copybuffer_read(struct Main *bmain_dst,
const char *libname,
struct ReportList *reports,
const uint64_t id_types_mask);
int BKE_copybuffer_paste(struct bContext *C,
const char *libname,
- const short flag,
+ const int flag,
struct ReportList *reports,
const uint64_t id_types_mask);
diff --git a/source/blender/blenkernel/BKE_blender_version.h b/source/blender/blenkernel/BKE_blender_version.h
index 326ca746292..966d6c95421 100644
--- a/source/blender/blenkernel/BKE_blender_version.h
+++ b/source/blender/blenkernel/BKE_blender_version.h
@@ -31,15 +31,15 @@ extern "C" {
*/
/* Blender major and minor version. */
-#define BLENDER_VERSION 300
+#define BLENDER_VERSION 301
/* Blender patch version for bugfix releases. */
#define BLENDER_VERSION_PATCH 0
/** Blender release cycle stage: alpha/beta/rc/release. */
-#define BLENDER_VERSION_CYCLE beta
+#define BLENDER_VERSION_CYCLE alpha
/* Blender file format version. */
#define BLENDER_FILE_VERSION BLENDER_VERSION
-#define BLENDER_FILE_SUBVERSION 42
+#define BLENDER_FILE_SUBVERSION 3
/* Minimum Blender version that supports reading file written with the current
* version. Older Blender versions will test this and show a warning if the file
diff --git a/source/blender/blenkernel/BKE_blendfile_link_append.h b/source/blender/blenkernel/BKE_blendfile_link_append.h
new file mode 100644
index 00000000000..9e4a498f5e7
--- /dev/null
+++ b/source/blender/blenkernel/BKE_blendfile_link_append.h
@@ -0,0 +1,112 @@
+/*
+ * 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.
+ */
+#pragma once
+
+/** \file
+ * \ingroup bke
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct BlendHandle;
+struct ID;
+struct Library;
+struct LibraryLink_Params;
+struct Main;
+struct ReportList;
+struct Scene;
+struct ViewLayer;
+struct View3D;
+
+typedef struct BlendfileLinkAppendContext BlendfileLinkAppendContext;
+typedef struct BlendfileLinkAppendContextItem BlendfileLinkAppendContextItem;
+
+BlendfileLinkAppendContext *BKE_blendfile_link_append_context_new(
+ struct LibraryLink_Params *params);
+void BKE_blendfile_link_append_context_free(struct BlendfileLinkAppendContext *lapp_context);
+void BKE_blendfile_link_append_context_flag_set(struct BlendfileLinkAppendContext *lapp_context,
+ const int flag,
+ const bool do_set);
+
+void BKE_blendfile_link_append_context_embedded_blendfile_set(
+ struct BlendfileLinkAppendContext *lapp_context,
+ const void *blendfile_mem,
+ int blendfile_memsize);
+void BKE_blendfile_link_append_context_embedded_blendfile_clear(
+ struct BlendfileLinkAppendContext *lapp_context);
+
+void BKE_blendfile_link_append_context_library_add(struct BlendfileLinkAppendContext *lapp_context,
+ const char *libname,
+ struct BlendHandle *blo_handle);
+struct BlendfileLinkAppendContextItem *BKE_blendfile_link_append_context_item_add(
+ struct BlendfileLinkAppendContext *lapp_context,
+ const char *idname,
+ const short idcode,
+ void *userdata);
+void BKE_blendfile_link_append_context_item_library_index_enable(
+ struct BlendfileLinkAppendContext *lapp_context,
+ struct BlendfileLinkAppendContextItem *item,
+ const int library_index);
+bool BKE_blendfile_link_append_context_is_empty(struct BlendfileLinkAppendContext *lapp_context);
+
+void *BKE_blendfile_link_append_context_item_userdata_get(
+ struct BlendfileLinkAppendContext *lapp_context, struct BlendfileLinkAppendContextItem *item);
+struct ID *BKE_blendfile_link_append_context_item_newid_get(
+ struct BlendfileLinkAppendContext *lapp_context, struct BlendfileLinkAppendContextItem *item);
+short BKE_blendfile_link_append_context_item_idcode_get(
+ struct BlendfileLinkAppendContext *lapp_context, struct BlendfileLinkAppendContextItem *item);
+
+typedef enum eBlendfileLinkAppendForeachItemFlag {
+ /** Loop over directly linked items (i.e. those explicitely defined by user code). */
+ BKE_BLENDFILE_LINK_APPEND_FOREACH_ITEM_FLAG_DO_DIRECT = 1 << 0,
+ /** Loop over indirectly linked items (i.e. those defined by internal code, as dependencies of
+ * direct ones).
+ *
+ * IMPORTANT: Those 'indirect' items currently may not cover **all** indrectly linked data. See
+ * comments in #foreach_libblock_link_append_callback. */
+ BKE_BLENDFILE_LINK_APPEND_FOREACH_ITEM_FLAG_DO_INDIRECT = 1 << 0,
+} eBlendfileLinkAppendForeachItemFlag;
+/** Callback called by #BKE_blendfile_link_append_context_item_foreach over each (or a subset of
+ * each) of the items in given #BlendfileLinkAppendContext.
+ *
+ * \param userdata: An opaque void pointer passed to the `callback_function`.
+ *
+ * \return `true` if iteration should continue, `false` otherwise. */
+typedef bool (*BKE_BlendfileLinkAppendContexteItemFunction)(
+ struct BlendfileLinkAppendContext *lapp_context,
+ struct BlendfileLinkAppendContextItem *item,
+ void *userdata);
+void BKE_blendfile_link_append_context_item_foreach(
+ struct BlendfileLinkAppendContext *lapp_context,
+ BKE_BlendfileLinkAppendContexteItemFunction callback_function,
+ const eBlendfileLinkAppendForeachItemFlag flag,
+ void *userdata);
+
+void BKE_blendfile_append(struct BlendfileLinkAppendContext *lapp_context,
+ struct ReportList *reports);
+void BKE_blendfile_link(struct BlendfileLinkAppendContext *lapp_context,
+ struct ReportList *reports);
+
+void BKE_blendfile_library_relocate(struct BlendfileLinkAppendContext *lapp_context,
+ struct ReportList *reports,
+ struct Library *library,
+ const bool do_reload);
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/blenkernel/BKE_brush.h b/source/blender/blenkernel/BKE_brush.h
index 452a08bc9c8..c5f1af4c755 100644
--- a/source/blender/blenkernel/BKE_brush.h
+++ b/source/blender/blenkernel/BKE_brush.h
@@ -78,7 +78,7 @@ void BKE_brush_randomize_texture_coords(struct UnifiedPaintSettings *ups, bool m
/* brush curve */
void BKE_brush_curve_preset(struct Brush *b, enum eCurveMappingPreset preset);
-float BKE_brush_curve_strength_clamped(struct Brush *br, float p, const float len);
+float BKE_brush_curve_strength_clamped(const struct Brush *br, float p, const float len);
float BKE_brush_curve_strength(const struct Brush *br, float p, const float len);
/* sampling */
diff --git a/source/blender/blenkernel/BKE_geometry_set.hh b/source/blender/blenkernel/BKE_geometry_set.hh
index 58a89d0207a..35e66908d54 100644
--- a/source/blender/blenkernel/BKE_geometry_set.hh
+++ b/source/blender/blenkernel/BKE_geometry_set.hh
@@ -119,10 +119,21 @@ class GeometryComponent {
/* Get a read-only attribute for the domain based on the given attribute. This can be used to
* interpolate from one domain to another.
* Returns null if the interpolation is not implemented. */
- virtual std::unique_ptr<blender::fn::GVArray> attribute_try_adapt_domain(
- std::unique_ptr<blender::fn::GVArray> varray,
- const AttributeDomain from_domain,
- const AttributeDomain to_domain) const;
+ blender::fn::GVArray attribute_try_adapt_domain(const blender::fn::GVArray &varray,
+ const AttributeDomain from_domain,
+ const AttributeDomain to_domain) const
+ {
+ return this->attribute_try_adapt_domain_impl(varray, from_domain, to_domain);
+ }
+
+ template<typename T>
+ blender::VArray<T> attribute_try_adapt_domain(const blender::VArray<T> &varray,
+ const AttributeDomain from_domain,
+ const AttributeDomain to_domain) const
+ {
+ return this->attribute_try_adapt_domain_impl(varray, from_domain, to_domain)
+ .template typed<T>();
+ }
/* Returns true when the attribute has been deleted. */
bool attribute_try_delete(const blender::bke::AttributeIDRef &attribute_id);
@@ -146,16 +157,15 @@ class GeometryComponent {
/* Get a virtual array to read the data of an attribute on the given domain and data type.
* Returns null when the attribute does not exist or cannot be converted to the requested domain
* and data type. */
- std::unique_ptr<blender::fn::GVArray> attribute_try_get_for_read(
- const blender::bke::AttributeIDRef &attribute_id,
- const AttributeDomain domain,
- const CustomDataType data_type) const;
+ blender::fn::GVArray attribute_try_get_for_read(const blender::bke::AttributeIDRef &attribute_id,
+ const AttributeDomain domain,
+ const CustomDataType data_type) const;
/* Get a virtual array to read the data of an attribute on the given domain. The data type is
* left unchanged. Returns null when the attribute does not exist or cannot be adapted to the
* requested domain. */
- std::unique_ptr<blender::fn::GVArray> attribute_try_get_for_read(
- const blender::bke::AttributeIDRef &attribute_id, const AttributeDomain domain) const;
+ blender::fn::GVArray attribute_try_get_for_read(const blender::bke::AttributeIDRef &attribute_id,
+ const AttributeDomain domain) const;
/* Get a virtual array to read data of an attribute with the given data type. The domain is
* left unchanged. Returns null when the attribute does not exist or cannot be converted to the
@@ -165,25 +175,22 @@ class GeometryComponent {
/* Get a virtual array to read the data of an attribute. If that is not possible, the returned
* virtual array will contain a default value. This never returns null. */
- std::unique_ptr<blender::fn::GVArray> attribute_get_for_read(
- const blender::bke::AttributeIDRef &attribute_id,
- const AttributeDomain domain,
- const CustomDataType data_type,
- const void *default_value = nullptr) const;
+ blender::fn::GVArray attribute_get_for_read(const blender::bke::AttributeIDRef &attribute_id,
+ const AttributeDomain domain,
+ const CustomDataType data_type,
+ const void *default_value = nullptr) const;
/* Should be used instead of the method above when the requested data type is known at compile
* time for better type safety. */
template<typename T>
- blender::fn::GVArray_Typed<T> attribute_get_for_read(
- const blender::bke::AttributeIDRef &attribute_id,
- const AttributeDomain domain,
- const T &default_value) const
+ blender::VArray<T> attribute_get_for_read(const blender::bke::AttributeIDRef &attribute_id,
+ const AttributeDomain domain,
+ const T &default_value) const
{
const blender::fn::CPPType &cpp_type = blender::fn::CPPType::get<T>();
const CustomDataType type = blender::bke::cpp_type_to_custom_data_type(cpp_type);
- std::unique_ptr varray = this->attribute_get_for_read(
- attribute_id, domain, type, &default_value);
- return blender::fn::GVArray_Typed<T>(std::move(varray));
+ return this->attribute_get_for_read(attribute_id, domain, type, &default_value)
+ .template typed<T>();
}
/**
@@ -234,6 +241,11 @@ class GeometryComponent {
private:
virtual const blender::bke::ComponentAttributeProviders *get_attribute_providers() const;
+
+ virtual blender::fn::GVArray attribute_try_adapt_domain_impl(
+ const blender::fn::GVArray &varray,
+ const AttributeDomain from_domain,
+ const AttributeDomain to_domain) const;
};
template<typename T>
@@ -391,10 +403,6 @@ class MeshComponent : public GeometryComponent {
Mesh *get_for_write();
int attribute_domain_size(const AttributeDomain domain) const final;
- std::unique_ptr<blender::fn::GVArray> attribute_try_adapt_domain(
- std::unique_ptr<blender::fn::GVArray> varray,
- const AttributeDomain from_domain,
- const AttributeDomain to_domain) const final;
bool is_empty() const final;
@@ -405,6 +413,11 @@ class MeshComponent : public GeometryComponent {
private:
const blender::bke::ComponentAttributeProviders *get_attribute_providers() const final;
+
+ blender::fn::GVArray attribute_try_adapt_domain_impl(
+ const blender::fn::GVArray &varray,
+ const AttributeDomain from_domain,
+ const AttributeDomain to_domain) const final;
};
/** A geometry component that stores a point cloud. */
@@ -469,10 +482,6 @@ class CurveComponent : public GeometryComponent {
CurveEval *get_for_write();
int attribute_domain_size(const AttributeDomain domain) const final;
- std::unique_ptr<blender::fn::GVArray> attribute_try_adapt_domain(
- std::unique_ptr<blender::fn::GVArray> varray,
- const AttributeDomain from_domain,
- const AttributeDomain to_domain) const final;
bool is_empty() const final;
@@ -485,6 +494,11 @@ class CurveComponent : public GeometryComponent {
private:
const blender::bke::ComponentAttributeProviders *get_attribute_providers() const final;
+
+ blender::fn::GVArray attribute_try_adapt_domain_impl(
+ const blender::fn::GVArray &varray,
+ const AttributeDomain from_domain,
+ const AttributeDomain to_domain) const final;
};
class InstanceReference {
@@ -637,6 +651,8 @@ class InstancesComponent : public GeometryComponent {
mutable std::mutex almost_unique_ids_mutex_;
mutable blender::Array<int> almost_unique_ids_;
+ blender::bke::CustomDataAttributes attributes_;
+
public:
InstancesComponent();
~InstancesComponent() = default;
@@ -671,6 +687,9 @@ class InstancesComponent : public GeometryComponent {
blender::Span<int> almost_unique_ids() const;
+ blender::bke::CustomDataAttributes &attributes();
+ const blender::bke::CustomDataAttributes &attributes() const;
+
int attribute_domain_size(const AttributeDomain domain) const final;
void foreach_referenced_geometry(
@@ -759,9 +778,9 @@ class AttributeFieldInput : public fn::FieldInput {
return name_;
}
- const GVArray *get_varray_for_context(const fn::FieldContext &context,
- IndexMask mask,
- ResourceScope &scope) const override;
+ GVArray get_varray_for_context(const fn::FieldContext &context,
+ IndexMask mask,
+ ResourceScope &scope) const override;
std::string socket_inspection_name() const override;
@@ -776,9 +795,9 @@ class IDAttributeFieldInput : public fn::FieldInput {
category_ = Category::Generated;
}
- const GVArray *get_varray_for_context(const fn::FieldContext &context,
- IndexMask mask,
- ResourceScope &scope) const override;
+ GVArray get_varray_for_context(const fn::FieldContext &context,
+ IndexMask mask,
+ ResourceScope &scope) const override;
std::string socket_inspection_name() const override;
@@ -815,9 +834,9 @@ class AnonymousAttributeFieldInput : public fn::FieldInput {
return fn::Field<T>{field_input};
}
- const GVArray *get_varray_for_context(const fn::FieldContext &context,
- IndexMask mask,
- ResourceScope &scope) const override;
+ GVArray get_varray_for_context(const fn::FieldContext &context,
+ IndexMask mask,
+ ResourceScope &scope) const override;
std::string socket_inspection_name() const override;
diff --git a/source/blender/blenkernel/BKE_global.h b/source/blender/blenkernel/BKE_global.h
index bacdd4adc76..d6cabbc1236 100644
--- a/source/blender/blenkernel/BKE_global.h
+++ b/source/blender/blenkernel/BKE_global.h
@@ -45,7 +45,6 @@ typedef struct Global {
/** When set: `G_MAIN->name` contains valid relative base path. */
bool relbase_valid;
- bool file_loaded;
bool save_over;
/** Strings of recent opened files. */
@@ -212,9 +211,9 @@ enum {
G_TRANSFORM_FCURVES = (1 << 3),
G_TRANSFORM_WM = (1 << 4),
/**
- * Set when transforming the cursor it's self.
+ * Set when transforming the cursor itself.
* Used as a hint to draw the cursor (even when hidden).
- * Otherwise it's not possible to see whats being transformed.
+ * Otherwise it's not possible to see what's being transformed.
*/
G_TRANSFORM_CURSOR = (1 << 5),
};
diff --git a/source/blender/blenkernel/BKE_gpencil_geom.h b/source/blender/blenkernel/BKE_gpencil_geom.h
index a9cd553a8fe..41b1bba10ba 100644
--- a/source/blender/blenkernel/BKE_gpencil_geom.h
+++ b/source/blender/blenkernel/BKE_gpencil_geom.h
@@ -128,8 +128,9 @@ struct bGPDstroke *BKE_gpencil_stroke_delete_tagged_points(struct bGPdata *gpd,
struct bGPDstroke *gps,
struct bGPDstroke *next_stroke,
int tag_flags,
- bool select,
- int limit);
+ const bool select,
+ const bool flat_cap,
+ const int limit);
void BKE_gpencil_curve_delete_tagged_points(struct bGPdata *gpd,
struct bGPDframe *gpf,
struct bGPDstroke *gps,
diff --git a/source/blender/blenkernel/BKE_image.h b/source/blender/blenkernel/BKE_image.h
index 7a8c55071df..77f1d197844 100644
--- a/source/blender/blenkernel/BKE_image.h
+++ b/source/blender/blenkernel/BKE_image.h
@@ -47,9 +47,6 @@ struct anim;
#define IMA_MAX_SPACE 64
#define IMA_UDIM_MAX 2000
-void BKE_images_init(void);
-void BKE_images_exit(void);
-
void BKE_image_free_packedfiles(struct Image *image);
void BKE_image_free_views(struct Image *image);
void BKE_image_free_buffers(struct Image *image);
diff --git a/source/blender/blenkernel/BKE_layer.h b/source/blender/blenkernel/BKE_layer.h
index c8af1a91725..08b44959096 100644
--- a/source/blender/blenkernel/BKE_layer.h
+++ b/source/blender/blenkernel/BKE_layer.h
@@ -328,7 +328,7 @@ void BKE_view_layer_visible_bases_iterator_end(BLI_Iterator *iter);
{ \
Object *_instance; \
Base *_base; \
- for (_base = (view_layer)->object_bases.first; _base; _base = _base->next) { \
+ for (_base = (Base *)(view_layer)->object_bases.first; _base; _base = _base->next) { \
_instance = _base->object;
#define FOREACH_OBJECT_END \
diff --git a/source/blender/blenkernel/BKE_lib_id.h b/source/blender/blenkernel/BKE_lib_id.h
index 68399959a37..359fb72534a 100644
--- a/source/blender/blenkernel/BKE_lib_id.h
+++ b/source/blender/blenkernel/BKE_lib_id.h
@@ -137,8 +137,10 @@ enum {
LIB_ID_COPY_SHAPEKEY = 1 << 26,
/** EXCEPTION! Specific deep-copy of node trees used e.g. for rendering purposes. */
LIB_ID_COPY_NODETREE_LOCALIZE = 1 << 27,
- /** EXCEPTION! Specific handling of RB objects regarding collections differs depending whether we
- duplicate scene/collections, or objects. */
+ /**
+ * EXCEPTION! Specific handling of RB objects regarding collections differs depending whether we
+ * duplicate scene/collections, or objects.
+ */
LIB_ID_COPY_RIGID_BODY_NO_COLLECTION_HANDLING = 1 << 28,
/* *** Helper 'defines' gathering most common flag sets. *** */
diff --git a/source/blender/blenkernel/BKE_lib_query.h b/source/blender/blenkernel/BKE_lib_query.h
index 957a623577e..30c742e3af6 100644
--- a/source/blender/blenkernel/BKE_lib_query.h
+++ b/source/blender/blenkernel/BKE_lib_query.h
@@ -143,7 +143,8 @@ enum {
typedef struct LibraryForeachIDData LibraryForeachIDData;
-bool BKE_lib_query_foreachid_process(struct LibraryForeachIDData *data,
+bool BKE_lib_query_foreachid_iter_stop(struct LibraryForeachIDData *data);
+void BKE_lib_query_foreachid_process(struct LibraryForeachIDData *data,
struct ID **id_pp,
int cb_flag);
int BKE_lib_query_foreachid_process_flags_get(struct LibraryForeachIDData *data);
@@ -154,7 +155,8 @@ int BKE_lib_query_foreachid_process_callback_flag_override(struct LibraryForeach
#define BKE_LIB_FOREACHID_PROCESS_ID(_data, _id, _cb_flag) \
{ \
CHECK_TYPE_ANY((_id), ID *, void *); \
- if (!BKE_lib_query_foreachid_process((_data), (ID **)&(_id), (_cb_flag))) { \
+ BKE_lib_query_foreachid_process((_data), (ID **)&(_id), (_cb_flag)); \
+ if (BKE_lib_query_foreachid_iter_stop((_data))) { \
return; \
} \
} \
@@ -163,13 +165,23 @@ int BKE_lib_query_foreachid_process_callback_flag_override(struct LibraryForeach
#define BKE_LIB_FOREACHID_PROCESS_IDSUPER(_data, _id_super, _cb_flag) \
{ \
CHECK_TYPE(&((_id_super)->id), ID *); \
- if (!BKE_lib_query_foreachid_process((_data), (ID **)&(_id_super), (_cb_flag))) { \
+ BKE_lib_query_foreachid_process((_data), (ID **)&(_id_super), (_cb_flag)); \
+ if (BKE_lib_query_foreachid_iter_stop((_data))) { \
return; \
} \
} \
((void)0)
-bool BKE_library_foreach_ID_embedded(struct LibraryForeachIDData *data, struct ID **id_pp);
+#define BKE_LIB_FOREACHID_PROCESS_FUNCTION_CALL(_data, _func_call) \
+ { \
+ _func_call; \
+ if (BKE_lib_query_foreachid_iter_stop((_data))) { \
+ return; \
+ } \
+ } \
+ ((void)0)
+
+void BKE_library_foreach_ID_embedded(struct LibraryForeachIDData *data, struct ID **id_pp);
void BKE_lib_query_idpropertiesForeachIDLink_callback(struct IDProperty *id_prop, void *user_data);
/* Loop over all of the ID's this datablock links to. */
diff --git a/source/blender/blenkernel/BKE_lib_remap.h b/source/blender/blenkernel/BKE_lib_remap.h
index c70521f9593..5e154459a6c 100644
--- a/source/blender/blenkernel/BKE_lib_remap.h
+++ b/source/blender/blenkernel/BKE_lib_remap.h
@@ -89,6 +89,12 @@ enum {
* dealing with IDs temporarily out of Main, but which will be put in it ultimately).
*/
ID_REMAP_FORCE_USER_REFCOUNT = 1 << 8,
+ /**
+ * Force obdata pointers to also be processed, even when object (`id_owner`) is in Edit mode.
+ * This is required by some tools creating/deleting IDs while operating in Edit mode, like e.g.
+ * the 'separate' mesh operator.
+ */
+ ID_REMAP_FORCE_OBDATA_IN_EDITMODE = 1 << 9,
};
/* NOTE: Requiring new_id to be non-null, this *may* not be the case ultimately,
@@ -111,8 +117,8 @@ void BKE_libblock_relink_ex(struct Main *bmain,
void *new_idv,
const short remap_flags) ATTR_NONNULL(1, 2);
-void BKE_libblock_relink_to_newid(struct ID *id) ATTR_NONNULL();
-void BKE_libblock_relink_to_newid_new(struct Main *bmain, struct ID *id) ATTR_NONNULL();
+void BKE_libblock_relink_to_newid(struct Main *bmain, struct ID *id, const int remap_flag)
+ ATTR_NONNULL();
typedef void (*BKE_library_free_notifier_reference_cb)(const void *);
typedef void (*BKE_library_remap_editor_id_reference_cb)(struct ID *, struct ID *);
diff --git a/source/blender/blenkernel/BKE_node.h b/source/blender/blenkernel/BKE_node.h
index 58fea6d462c..5ed1b512fd5 100644
--- a/source/blender/blenkernel/BKE_node.h
+++ b/source/blender/blenkernel/BKE_node.h
@@ -121,12 +121,11 @@ class MFDataType;
} // namespace fn
} // namespace blender
+using CPPTypeHandle = blender::fn::CPPType;
using NodeMultiFunctionBuildFunction = void (*)(blender::nodes::NodeMultiFunctionBuilder &builder);
using NodeGeometryExecFunction = void (*)(blender::nodes::GeoNodeExecParams params);
using NodeDeclareFunction = void (*)(blender::nodes::NodeDeclarationBuilder &builder);
-using SocketGetCPPTypeFunction = const blender::fn::CPPType *(*)();
using SocketGetCPPValueFunction = void (*)(const struct bNodeSocket &socket, void *r_value);
-using SocketGetGeometryNodesCPPTypeFunction = const blender::fn::CPPType *(*)();
using SocketGetGeometryNodesCPPValueFunction = void (*)(const struct bNodeSocket &socket,
void *r_value);
@@ -138,6 +137,7 @@ typedef void *SocketGetCPPTypeFunction;
typedef void *SocketGetGeometryNodesCPPTypeFunction;
typedef void *SocketGetGeometryNodesCPPValueFunction;
typedef void *SocketGetCPPValueFunction;
+typedef struct CPPTypeHandle CPPTypeHandle;
#endif
/**
@@ -197,11 +197,11 @@ typedef struct bNodeSocketType {
void (*free_self)(struct bNodeSocketType *stype);
/* Return the CPPType of this socket. */
- SocketGetCPPTypeFunction get_base_cpp_type;
+ const CPPTypeHandle *base_cpp_type;
/* Get the value of this socket in a generic way. */
SocketGetCPPValueFunction get_base_cpp_value;
/* Get geometry nodes cpp type. */
- SocketGetGeometryNodesCPPTypeFunction get_geometry_nodes_cpp_type;
+ const CPPTypeHandle *geometry_nodes_cpp_type;
/* Get geometry nodes cpp value. */
SocketGetGeometryNodesCPPValueFunction get_geometry_nodes_cpp_value;
} bNodeSocketType;
@@ -318,8 +318,6 @@ typedef struct bNodeType {
/* optional handling of link insertion */
void (*insert_link)(struct bNodeTree *ntree, struct bNode *node, struct bNodeLink *link);
- /* Update the internal links list, for muting and disconnect operators. */
- void (*update_internal_links)(struct bNodeTree *, struct bNode *node);
void (*free_self)(struct bNodeType *ntype);
@@ -344,6 +342,9 @@ typedef struct bNodeType {
/* Declaration to be used when it is not dynamic. */
NodeDeclarationHandle *fixed_declaration;
+ /** True when the node cannot be muted. */
+ bool no_muting;
+
/* RNA integration */
ExtensionRNA rna_ext;
} bNodeType;
@@ -731,11 +732,15 @@ void nodeUpdateInternalLinks(struct bNodeTree *ntree, struct bNode *node);
int nodeSocketIsHidden(const struct bNodeSocket *sock);
void ntreeTagUsedSockets(struct bNodeTree *ntree);
-void nodeSetSocketAvailability(struct bNodeSocket *sock, bool is_available);
+void nodeSetSocketAvailability(struct bNodeTree *ntree,
+ struct bNodeSocket *sock,
+ bool is_available);
int nodeSocketLinkLimit(const struct bNodeSocket *sock);
-void nodeDeclarationEnsure(struct bNodeTree *ntree, struct bNode *node);
+bool nodeDeclarationEnsure(struct bNodeTree *ntree, struct bNode *node);
+bool nodeDeclarationEnsureOnOutdatedNode(struct bNodeTree *ntree, struct bNode *node);
+void nodeSocketDeclarationsUpdate(struct bNode *node);
/* Node Clipboard */
void BKE_node_clipboard_init(const struct bNodeTree *ntree);
@@ -887,8 +892,6 @@ void node_type_exec(struct bNodeType *ntype,
NodeFreeExecFunction free_exec_fn,
NodeExecFunction exec_fn);
void node_type_gpu(struct bNodeType *ntype, NodeGPUExecFunction gpu_fn);
-void node_type_internal_links(struct bNodeType *ntype,
- void (*update_internal_links)(struct bNodeTree *, struct bNode *));
/** \} */
diff --git a/source/blender/blenkernel/BKE_spline.hh b/source/blender/blenkernel/BKE_spline.hh
index 55a4f6ffcfd..67eaa7c12c9 100644
--- a/source/blender/blenkernel/BKE_spline.hh
+++ b/source/blender/blenkernel/BKE_spline.hh
@@ -187,14 +187,14 @@ class Spline {
blender::MutableSpan<T> dst) const
{
this->sample_with_index_factors(
- blender::fn::GVArray_For_VArray(src), index_factors, blender::fn::GMutableSpan(dst));
+ blender::fn::GVArray(src), index_factors, blender::fn::GMutableSpan(dst));
}
template<typename T>
void sample_with_index_factors(blender::Span<T> src,
blender::Span<float> index_factors,
blender::MutableSpan<T> dst) const
{
- this->sample_with_index_factors(blender::VArray_For_Span(src), index_factors, dst);
+ this->sample_with_index_factors(blender::VArray<T>::ForSpan(src), index_factors, dst);
}
/**
@@ -202,13 +202,11 @@ class Spline {
* evaluated points. For poly splines, the lifetime of the returned virtual array must not
* exceed the lifetime of the input data.
*/
- virtual blender::fn::GVArrayPtr interpolate_to_evaluated(
- const blender::fn::GVArray &src) const = 0;
- blender::fn::GVArrayPtr interpolate_to_evaluated(blender::fn::GSpan data) const;
- template<typename T>
- blender::fn::GVArray_Typed<T> interpolate_to_evaluated(blender::Span<T> data) const
+ virtual blender::fn::GVArray interpolate_to_evaluated(const blender::fn::GVArray &src) const = 0;
+ blender::fn::GVArray interpolate_to_evaluated(blender::fn::GSpan data) const;
+ template<typename T> blender::VArray<T> interpolate_to_evaluated(blender::Span<T> data) const
{
- return blender::fn::GVArray_Typed<T>(this->interpolate_to_evaluated(blender::fn::GSpan(data)));
+ return this->interpolate_to_evaluated(blender::fn::GSpan(data)).typed<T>();
}
protected:
@@ -307,20 +305,20 @@ class BezierSpline final : public Spline {
blender::MutableSpan<HandleType> handle_types_left();
blender::Span<blender::float3> handle_positions_left() const;
/**
- * Get writable access to the hande position.
+ * Get writable access to the handle position.
*
* \param write_only: pass true for an uninitialized spline, this prevents accessing
- * uninitialized memory while autogenerating handles.
+ * uninitialized memory while auto-generating handles.
*/
blender::MutableSpan<blender::float3> handle_positions_left(bool write_only = false);
blender::Span<HandleType> handle_types_right() const;
blender::MutableSpan<HandleType> handle_types_right();
blender::Span<blender::float3> handle_positions_right() const;
/**
- * Get writable access to the hande position.
+ * Get writable access to the handle position.
*
* \param write_only: pass true for an uninitialized spline, this prevents accessing
- * uninitialized memory while autogenerating handles.
+ * uninitialized memory while auto-generating handles.
*/
blender::MutableSpan<blender::float3> handle_positions_right(bool write_only = false);
void ensure_auto_handles() const;
@@ -350,7 +348,7 @@ class BezierSpline final : public Spline {
};
InterpolationData interpolation_data_from_index_factor(const float index_factor) const;
- virtual blender::fn::GVArrayPtr interpolate_to_evaluated(
+ virtual blender::fn::GVArray interpolate_to_evaluated(
const blender::fn::GVArray &src) const override;
void evaluate_segment(const int index,
@@ -487,7 +485,7 @@ class NURBSpline final : public Spline {
blender::Span<blender::float3> evaluated_positions() const final;
- blender::fn::GVArrayPtr interpolate_to_evaluated(const blender::fn::GVArray &src) const final;
+ blender::fn::GVArray interpolate_to_evaluated(const blender::fn::GVArray &src) const final;
protected:
void correct_end_tangents() const final;
@@ -538,7 +536,7 @@ class PolySpline final : public Spline {
blender::Span<blender::float3> evaluated_positions() const final;
- blender::fn::GVArrayPtr interpolate_to_evaluated(const blender::fn::GVArray &src) const final;
+ blender::fn::GVArray interpolate_to_evaluated(const blender::fn::GVArray &src) const final;
protected:
void correct_end_tangents() const final;
@@ -582,6 +580,9 @@ struct CurveEval {
blender::Array<int> evaluated_point_offsets() const;
blender::Array<float> accumulated_spline_lengths() const;
+ float total_length() const;
+ int total_control_point_size() const;
+
void mark_cache_invalid();
void assert_valid_point_attributes() const;
diff --git a/source/blender/blenkernel/BKE_volume_to_mesh.hh b/source/blender/blenkernel/BKE_volume_to_mesh.hh
index 9532da8c23c..dd8ae7ea554 100644
--- a/source/blender/blenkernel/BKE_volume_to_mesh.hh
+++ b/source/blender/blenkernel/BKE_volume_to_mesh.hh
@@ -14,6 +14,8 @@
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
+#pragma once
+
#include "BLI_span.hh"
#include "DNA_modifier_types.h"
diff --git a/source/blender/blenkernel/CMakeLists.txt b/source/blender/blenkernel/CMakeLists.txt
index d4ec7fd703d..a08f1b81dbe 100644
--- a/source/blender/blenkernel/CMakeLists.txt
+++ b/source/blender/blenkernel/CMakeLists.txt
@@ -100,6 +100,7 @@ set(SRC
intern/blender_undo.c
intern/blender_user_menu.c
intern/blendfile.c
+ intern/blendfile_link_append.c
intern/boids.c
intern/bpath.c
intern/brush.c
@@ -192,7 +193,7 @@ set(SRC
intern/material.c
intern/mball.c
intern/mball_tessellate.c
- intern/mesh.c
+ intern/mesh.cc
intern/mesh_boolean_convert.cc
intern/mesh_convert.cc
intern/mesh_evaluate.cc
@@ -326,6 +327,7 @@ set(SRC
BKE_blender_user_menu.h
BKE_blender_version.h
BKE_blendfile.h
+ BKE_blendfile_link_append.h
BKE_boids.h
BKE_bpath.h
BKE_brush.h
diff --git a/source/blender/blenkernel/intern/action.c b/source/blender/blenkernel/intern/action.c
index 842902b51ed..2cc1cba99cd 100644
--- a/source/blender/blenkernel/intern/action.c
+++ b/source/blender/blenkernel/intern/action.c
@@ -176,7 +176,7 @@ static void action_foreach_id(ID *id, LibraryForeachIDData *data)
bAction *act = (bAction *)id;
LISTBASE_FOREACH (FCurve *, fcu, &act->curves) {
- BKE_fcurve_foreach_id(fcu, data);
+ BKE_LIB_FOREACHID_PROCESS_FUNCTION_CALL(data, BKE_fcurve_foreach_id(fcu, data));
}
LISTBASE_FOREACH (TimeMarker *, marker, &act->markers) {
diff --git a/source/blender/blenkernel/intern/anim_data.c b/source/blender/blenkernel/intern/anim_data.c
index 23d2c4fe55f..21887d514d9 100644
--- a/source/blender/blenkernel/intern/anim_data.c
+++ b/source/blender/blenkernel/intern/anim_data.c
@@ -294,7 +294,7 @@ bool BKE_animdata_id_is_animated(const struct ID *id)
void BKE_animdata_foreach_id(AnimData *adt, LibraryForeachIDData *data)
{
LISTBASE_FOREACH (FCurve *, fcu, &adt->drivers) {
- BKE_fcurve_foreach_id(fcu, data);
+ BKE_LIB_FOREACHID_PROCESS_FUNCTION_CALL(data, BKE_fcurve_foreach_id(fcu, data));
}
BKE_LIB_FOREACHID_PROCESS_IDSUPER(data, adt->action, IDWALK_CB_USER);
diff --git a/source/blender/blenkernel/intern/appdir.c b/source/blender/blenkernel/intern/appdir.c
index 08a3b7d0bbb..d872dc67dcb 100644
--- a/source/blender/blenkernel/intern/appdir.c
+++ b/source/blender/blenkernel/intern/appdir.c
@@ -279,23 +279,31 @@ bool BKE_appdir_folder_caches(char *r_path, const size_t path_len)
/**
* Gets a good default directory for fonts.
*/
-bool BKE_appdir_font_folder_default(
- /* This parameter can only be `const` on non-windows platforms.
- * NOLINTNEXTLINE: readability-non-const-parameter. */
- char *dir)
+bool BKE_appdir_font_folder_default(char *dir)
{
- bool success = false;
+ char test_dir[FILE_MAXDIR];
+ test_dir[0] = '\0';
+
#ifdef WIN32
wchar_t wpath[FILE_MAXDIR];
- success = SHGetSpecialFolderPathW(0, wpath, CSIDL_FONTS, 0);
- if (success) {
+ if (SHGetSpecialFolderPathW(0, wpath, CSIDL_FONTS, 0)) {
wcscat(wpath, L"\\");
- BLI_strncpy_wchar_as_utf8(dir, wpath, FILE_MAXDIR);
+ BLI_strncpy_wchar_as_utf8(test_dir, wpath, sizeof(test_dir));
+ }
+#elif defined(__APPLE__)
+ const char *home = BLI_getenv("HOME");
+ if (home) {
+ BLI_path_join(test_dir, sizeof(test_dir), home, "Library", "Fonts", NULL);
}
+#else
+ STRNCPY(test_dir, "/usr/share/fonts");
#endif
- /* TODO: Values for other platforms. */
- UNUSED_VARS(dir);
- return success;
+
+ if (test_dir[0] && BLI_exists(test_dir)) {
+ BLI_strncpy(dir, test_dir, FILE_MAXDIR);
+ return true;
+ }
+ return false;
}
/** \} */
diff --git a/source/blender/blenkernel/intern/armature.c b/source/blender/blenkernel/intern/armature.c
index b64b050f4e7..b830c9de5f5 100644
--- a/source/blender/blenkernel/intern/armature.c
+++ b/source/blender/blenkernel/intern/armature.c
@@ -161,30 +161,36 @@ static void armature_free_data(struct ID *id)
static void armature_foreach_id_bone(Bone *bone, LibraryForeachIDData *data)
{
- IDP_foreach_property(
- bone->prop, IDP_TYPE_FILTER_ID, BKE_lib_query_idpropertiesForeachIDLink_callback, data);
+ BKE_LIB_FOREACHID_PROCESS_FUNCTION_CALL(
+ data,
+ IDP_foreach_property(
+ bone->prop, IDP_TYPE_FILTER_ID, BKE_lib_query_idpropertiesForeachIDLink_callback, data));
LISTBASE_FOREACH (Bone *, curbone, &bone->childbase) {
- armature_foreach_id_bone(curbone, data);
+ BKE_LIB_FOREACHID_PROCESS_FUNCTION_CALL(data, armature_foreach_id_bone(curbone, data));
}
}
static void armature_foreach_id_editbone(EditBone *edit_bone, LibraryForeachIDData *data)
{
- IDP_foreach_property(
- edit_bone->prop, IDP_TYPE_FILTER_ID, BKE_lib_query_idpropertiesForeachIDLink_callback, data);
+ BKE_LIB_FOREACHID_PROCESS_FUNCTION_CALL(
+ data,
+ IDP_foreach_property(edit_bone->prop,
+ IDP_TYPE_FILTER_ID,
+ BKE_lib_query_idpropertiesForeachIDLink_callback,
+ data));
}
static void armature_foreach_id(ID *id, LibraryForeachIDData *data)
{
bArmature *arm = (bArmature *)id;
LISTBASE_FOREACH (Bone *, bone, &arm->bonebase) {
- armature_foreach_id_bone(bone, data);
+ BKE_LIB_FOREACHID_PROCESS_FUNCTION_CALL(data, armature_foreach_id_bone(bone, data));
}
if (arm->edbo != NULL) {
LISTBASE_FOREACH (EditBone *, edit_bone, arm->edbo) {
- armature_foreach_id_editbone(edit_bone, data);
+ BKE_LIB_FOREACHID_PROCESS_FUNCTION_CALL(data, armature_foreach_id_editbone(edit_bone, data));
}
}
}
diff --git a/source/blender/blenkernel/intern/asset.cc b/source/blender/blenkernel/intern/asset.cc
index 7bea089b9bf..59e402b6680 100644
--- a/source/blender/blenkernel/intern/asset.cc
+++ b/source/blender/blenkernel/intern/asset.cc
@@ -21,14 +21,12 @@
#include <cstring>
#include "DNA_ID.h"
-#include "DNA_asset_types.h"
#include "DNA_defaults.h"
#include "BLI_listbase.h"
#include "BLI_string.h"
#include "BLI_string_ref.hh"
#include "BLI_string_utils.h"
-#include "BLI_utildefines.h"
#include "BLI_uuid.h"
#include "BKE_asset.h"
diff --git a/source/blender/blenkernel/intern/asset_catalog.cc b/source/blender/blenkernel/intern/asset_catalog.cc
index 33405c9aeae..9ef66d23aea 100644
--- a/source/blender/blenkernel/intern/asset_catalog.cc
+++ b/source/blender/blenkernel/intern/asset_catalog.cc
@@ -18,25 +18,20 @@
* \ingroup bke
*/
+#include <fstream>
+#include <set>
+
#include "BKE_asset_catalog.hh"
#include "BKE_asset_library.h"
-#include "BKE_preferences.h"
#include "BLI_fileops.h"
#include "BLI_path_util.h"
-#include "BLI_set.hh"
-#include "BLI_string_ref.hh"
-
-#include "DNA_userdef_types.h"
/* For S_ISREG() and S_ISDIR() on Windows. */
#ifdef WIN32
# include "BLI_winstuff.h"
#endif
-#include <fstream>
-#include <set>
-
namespace blender::bke {
const CatalogFilePath AssetCatalogService::DEFAULT_CATALOG_FILENAME = "blender_assets.cats.txt";
diff --git a/source/blender/blenkernel/intern/asset_catalog_test.cc b/source/blender/blenkernel/intern/asset_catalog_test.cc
index 2cef34966f8..ba8f8716823 100644
--- a/source/blender/blenkernel/intern/asset_catalog_test.cc
+++ b/source/blender/blenkernel/intern/asset_catalog_test.cc
@@ -24,6 +24,7 @@
#include "BLI_fileops.h"
#include "BLI_path_util.h"
+#include "DNA_asset_types.h"
#include "DNA_userdef_types.h"
#include "testing/testing.h"
@@ -930,6 +931,28 @@ TEST_F(AssetCatalogTest, update_catalog_path_simple_name)
<< "Changing the path should update the simplename of children.";
}
+TEST_F(AssetCatalogTest, update_catalog_path_longer_than_simplename)
+{
+ AssetCatalogService service(asset_library_root_);
+ service.load_from_disk(asset_library_root_ + "/" +
+ AssetCatalogService::DEFAULT_CATALOG_FILENAME);
+ const std::string new_path =
+ "this/is/a/very/long/path/that/exceeds/the/simple-name/length/of/assets";
+ ASSERT_GT(new_path.length(), sizeof(AssetMetaData::catalog_simple_name))
+ << "This test case should work with paths longer than AssetMetaData::catalog_simple_name";
+
+ service.update_catalog_path(UUID_POSES_RUZENA, new_path);
+
+ const std::string new_simple_name = service.find_catalog(UUID_POSES_RUZENA)->simple_name;
+ EXPECT_LT(new_simple_name.length(), sizeof(AssetMetaData::catalog_simple_name))
+ << "The new simple name should fit in the asset metadata.";
+ EXPECT_EQ("...very-long-path-that-exceeds-the-simple-name-length-of-assets", new_simple_name)
+ << "Changing the path should update the simplename.";
+ EXPECT_EQ("...long-path-that-exceeds-the-simple-name-length-of-assets-face",
+ service.find_catalog(UUID_POSES_RUZENA_FACE)->simple_name)
+ << "Changing the path should update the simplename of children.";
+}
+
TEST_F(AssetCatalogTest, update_catalog_path_add_slashes)
{
AssetCatalogService service(asset_library_root_);
diff --git a/source/blender/blenkernel/intern/asset_library.cc b/source/blender/blenkernel/intern/asset_library.cc
index aae8a289d32..68e43852a21 100644
--- a/source/blender/blenkernel/intern/asset_library.cc
+++ b/source/blender/blenkernel/intern/asset_library.cc
@@ -18,9 +18,9 @@
* \ingroup bke
*/
-#include "BKE_asset_catalog.hh"
+#include <memory>
+
#include "BKE_asset_library.hh"
-#include "BKE_callbacks.h"
#include "BKE_main.h"
#include "BKE_preferences.h"
@@ -29,12 +29,8 @@
#include "DNA_asset_types.h"
#include "DNA_userdef_types.h"
-#include "MEM_guardedalloc.h"
-
#include "asset_library_service.hh"
-#include <memory>
-
bool blender::bke::AssetLibrary::save_catalogs_when_file_is_saved = true;
/**
diff --git a/source/blender/blenkernel/intern/asset_library_service.cc b/source/blender/blenkernel/intern/asset_library_service.cc
index 7cf95ee4cc1..d202d6462cf 100644
--- a/source/blender/blenkernel/intern/asset_library_service.cc
+++ b/source/blender/blenkernel/intern/asset_library_service.cc
@@ -20,16 +20,12 @@
#include "asset_library_service.hh"
-#include "BKE_asset_library.hh"
#include "BKE_blender.h"
-#include "BKE_callbacks.h"
-#include "BLI_fileops.h"
+#include "BLI_fileops.h" /* For PATH_MAX (at least on Windows). */
#include "BLI_path_util.h"
#include "BLI_string_ref.hh"
-#include "MEM_guardedalloc.h"
-
#include "CLG_log.h"
static CLG_LogRef LOG = {"bke.asset_service"};
diff --git a/source/blender/blenkernel/intern/asset_library_service_test.cc b/source/blender/blenkernel/intern/asset_library_service_test.cc
index e26ae05301e..ee910cab945 100644
--- a/source/blender/blenkernel/intern/asset_library_service_test.cc
+++ b/source/blender/blenkernel/intern/asset_library_service_test.cc
@@ -19,7 +19,7 @@
#include "asset_library_service.hh"
-#include "BLI_fileops.h"
+#include "BLI_fileops.h" /* For PATH_MAX (at least on Windows). */
#include "BLI_path_util.h"
#include "BKE_appdir.h"
diff --git a/source/blender/blenkernel/intern/attribute_access.cc b/source/blender/blenkernel/intern/attribute_access.cc
index cd394a4ca42..3f2c1f13337 100644
--- a/source/blender/blenkernel/intern/attribute_access.cc
+++ b/source/blender/blenkernel/intern/attribute_access.cc
@@ -50,9 +50,7 @@ using blender::bke::AttributeIDRef;
using blender::bke::OutputAttribute;
using blender::fn::GMutableSpan;
using blender::fn::GSpan;
-using blender::fn::GVArray_For_GSpan;
-using blender::fn::GVArray_For_SingleValue;
-using blender::fn::GVMutableArray_For_GMutableSpan;
+using blender::fn::GVMutableArrayImpl_For_GMutableSpan;
namespace blender::bke {
@@ -166,16 +164,18 @@ CustomDataType attribute_data_type_highest_complexity(Span<CustomDataType> data_
static int attribute_domain_priority(const AttributeDomain domain)
{
switch (domain) {
- case ATTR_DOMAIN_CURVE:
+ case ATTR_DOMAIN_INSTANCE:
return 0;
- case ATTR_DOMAIN_FACE:
+ case ATTR_DOMAIN_CURVE:
return 1;
- case ATTR_DOMAIN_EDGE:
+ case ATTR_DOMAIN_FACE:
return 2;
- case ATTR_DOMAIN_POINT:
+ case ATTR_DOMAIN_EDGE:
return 3;
- case ATTR_DOMAIN_CORNER:
+ case ATTR_DOMAIN_POINT:
return 4;
+ case ATTR_DOMAIN_CORNER:
+ return 5;
default:
/* Domain not supported in nodes yet. */
BLI_assert_unreachable();
@@ -207,7 +207,7 @@ fn::GMutableSpan OutputAttribute::as_span()
{
if (!optional_span_varray_) {
const bool materialize_old_values = !ignore_old_values_;
- optional_span_varray_ = std::make_unique<fn::GVMutableArray_GSpan>(*varray_,
+ optional_span_varray_ = std::make_unique<fn::GVMutableArray_GSpan>(varray_,
materialize_old_values);
}
fn::GVMutableArray_GSpan &span_varray = *optional_span_varray_;
@@ -257,8 +257,8 @@ static bool add_builtin_type_custom_data_layer_from_init(CustomData &custom_data
if (data == nullptr) {
return false;
}
- const GVArray *varray = static_cast<const AttributeInitVArray &>(initializer).varray;
- varray->materialize_to_uninitialized(IndexRange(varray->size()), data);
+ const GVArray &varray = static_cast<const AttributeInitVArray &>(initializer).varray;
+ varray.materialize_to_uninitialized(varray.index_range(), data);
return true;
}
case AttributeInit::Type::MoveArray: {
@@ -313,8 +313,8 @@ static bool add_custom_data_layer_from_attribute_init(const AttributeIDRef &attr
if (data == nullptr) {
return false;
}
- const GVArray *varray = static_cast<const AttributeInitVArray &>(initializer).varray;
- varray->materialize_to_uninitialized(IndexRange(varray->size()), data);
+ const GVArray &varray = static_cast<const AttributeInitVArray &>(initializer).varray;
+ varray.materialize_to_uninitialized(varray.index_range(), data);
return true;
}
case AttributeInit::Type::MoveArray: {
@@ -345,8 +345,7 @@ static bool custom_data_layer_matches_attribute_id(const CustomDataLayer &layer,
return layer.name == attribute_id.name();
}
-GVArrayPtr BuiltinCustomDataLayerProvider::try_get_for_read(
- const GeometryComponent &component) const
+GVArray BuiltinCustomDataLayerProvider::try_get_for_read(const GeometryComponent &component) const
{
const CustomData *custom_data = custom_data_access_.get_const_custom_data(component);
if (custom_data == nullptr) {
@@ -511,7 +510,7 @@ ReadAttributeLookup CustomDataAttributeProvider::try_get_for_read(
continue;
}
GSpan data{*type, layer.data, domain_size};
- return {std::make_unique<GVArray_For_GSpan>(data), domain_};
+ return {GVArray::ForSpan(data), domain_};
}
return {};
}
@@ -541,7 +540,7 @@ WriteAttributeLookup CustomDataAttributeProvider::try_get_for_write(
continue;
}
GMutableSpan data{*type, layer.data, domain_size};
- return {std::make_unique<GVMutableArray_For_GMutableSpan>(data), domain_};
+ return {GVMutableArray::ForSpan(data), domain_};
}
return {};
}
@@ -751,25 +750,25 @@ std::optional<GSpan> CustomDataAttributes::get_for_read(const AttributeIDRef &at
* value if the attribute doesn't exist. If no default value is provided, the default value for the
* type will be used.
*/
-GVArrayPtr CustomDataAttributes::get_for_read(const AttributeIDRef &attribute_id,
- const CustomDataType data_type,
- const void *default_value) const
+GVArray CustomDataAttributes::get_for_read(const AttributeIDRef &attribute_id,
+ const CustomDataType data_type,
+ const void *default_value) const
{
const CPPType *type = blender::bke::custom_data_type_to_cpp_type(data_type);
std::optional<GSpan> attribute = this->get_for_read(attribute_id);
if (!attribute) {
const int domain_size = this->size_;
- return std::make_unique<GVArray_For_SingleValue>(
+ return GVArray::ForSingle(
*type, domain_size, (default_value == nullptr) ? type->default_value() : default_value);
}
if (attribute->type() == *type) {
- return std::make_unique<GVArray_For_GSpan>(*attribute);
+ return GVArray::ForSpan(*attribute);
}
const blender::nodes::DataTypeConversions &conversions =
blender::nodes::get_implicit_type_conversions();
- return conversions.try_convert(std::make_unique<GVArray_For_GSpan>(*attribute), *type);
+ return conversions.try_convert(GVArray::ForSpan(*attribute), *type);
}
std::optional<GMutableSpan> CustomDataAttributes::get_for_write(const AttributeIDRef &attribute_id)
@@ -922,8 +921,8 @@ blender::bke::ReadAttributeLookup GeometryComponent::attribute_try_get_for_read(
return {};
}
-std::unique_ptr<blender::fn::GVArray> GeometryComponent::attribute_try_adapt_domain(
- std::unique_ptr<blender::fn::GVArray> varray,
+blender::fn::GVArray GeometryComponent::attribute_try_adapt_domain_impl(
+ const blender::fn::GVArray &varray,
const AttributeDomain from_domain,
const AttributeDomain to_domain) const
{
@@ -1110,15 +1109,15 @@ std::optional<AttributeMetaData> GeometryComponent::attribute_get_meta_data(
return result;
}
-static std::unique_ptr<blender::fn::GVArray> try_adapt_data_type(
- std::unique_ptr<blender::fn::GVArray> varray, const blender::fn::CPPType &to_type)
+static blender::fn::GVArray try_adapt_data_type(blender::fn::GVArray varray,
+ const blender::fn::CPPType &to_type)
{
const blender::nodes::DataTypeConversions &conversions =
blender::nodes::get_implicit_type_conversions();
return conversions.try_convert(std::move(varray), to_type);
}
-std::unique_ptr<blender::fn::GVArray> GeometryComponent::attribute_try_get_for_read(
+blender::fn::GVArray GeometryComponent::attribute_try_get_for_read(
const AttributeIDRef &attribute_id,
const AttributeDomain domain,
const CustomDataType data_type) const
@@ -1128,7 +1127,7 @@ std::unique_ptr<blender::fn::GVArray> GeometryComponent::attribute_try_get_for_r
return {};
}
- std::unique_ptr<blender::fn::GVArray> varray = std::move(attribute.varray);
+ blender::fn::GVArray varray = std::move(attribute.varray);
if (!ELEM(domain, ATTR_DOMAIN_AUTO, attribute.domain)) {
varray = this->attribute_try_adapt_domain(std::move(varray), attribute.domain, domain);
if (!varray) {
@@ -1138,7 +1137,7 @@ std::unique_ptr<blender::fn::GVArray> GeometryComponent::attribute_try_get_for_r
const blender::fn::CPPType *cpp_type = blender::bke::custom_data_type_to_cpp_type(data_type);
BLI_assert(cpp_type != nullptr);
- if (varray->type() != *cpp_type) {
+ if (varray.type() != *cpp_type) {
varray = try_adapt_data_type(std::move(varray), *cpp_type);
if (!varray) {
return {};
@@ -1148,7 +1147,7 @@ std::unique_ptr<blender::fn::GVArray> GeometryComponent::attribute_try_get_for_r
return varray;
}
-std::unique_ptr<blender::bke::GVArray> GeometryComponent::attribute_try_get_for_read(
+blender::fn::GVArray GeometryComponent::attribute_try_get_for_read(
const AttributeIDRef &attribute_id, const AttributeDomain domain) const
{
if (!this->attribute_domain_supported(domain)) {
@@ -1176,7 +1175,7 @@ blender::bke::ReadAttributeLookup GeometryComponent::attribute_try_get_for_read(
}
const blender::fn::CPPType *type = blender::bke::custom_data_type_to_cpp_type(data_type);
BLI_assert(type != nullptr);
- if (attribute.varray->type() == *type) {
+ if (attribute.varray.type() == *type) {
return attribute;
}
const blender::nodes::DataTypeConversions &conversions =
@@ -1184,14 +1183,12 @@ blender::bke::ReadAttributeLookup GeometryComponent::attribute_try_get_for_read(
return {conversions.try_convert(std::move(attribute.varray), *type), attribute.domain};
}
-std::unique_ptr<blender::bke::GVArray> GeometryComponent::attribute_get_for_read(
- const AttributeIDRef &attribute_id,
- const AttributeDomain domain,
- const CustomDataType data_type,
- const void *default_value) const
+blender::fn::GVArray GeometryComponent::attribute_get_for_read(const AttributeIDRef &attribute_id,
+ const AttributeDomain domain,
+ const CustomDataType data_type,
+ const void *default_value) const
{
- std::unique_ptr<blender::bke::GVArray> varray = this->attribute_try_get_for_read(
- attribute_id, domain, data_type);
+ blender::fn::GVArray varray = this->attribute_try_get_for_read(attribute_id, domain, data_type);
if (varray) {
return varray;
}
@@ -1200,11 +1197,11 @@ std::unique_ptr<blender::bke::GVArray> GeometryComponent::attribute_get_for_read
default_value = type->default_value();
}
const int domain_size = this->attribute_domain_size(domain);
- return std::make_unique<blender::fn::GVArray_For_SingleValue>(*type, domain_size, default_value);
+ return blender::fn::GVArray::ForSingle(*type, domain_size, default_value);
}
class GVMutableAttribute_For_OutputAttribute
- : public blender::fn::GVMutableArray_For_GMutableSpan {
+ : public blender::fn::GVMutableArrayImpl_For_GMutableSpan {
public:
GeometryComponent *component;
std::string attribute_name;
@@ -1213,7 +1210,7 @@ class GVMutableAttribute_For_OutputAttribute
GVMutableAttribute_For_OutputAttribute(GMutableSpan data,
GeometryComponent &component,
const AttributeIDRef &attribute_id)
- : blender::fn::GVMutableArray_For_GMutableSpan(data), component(&component)
+ : blender::fn::GVMutableArrayImpl_For_GMutableSpan(data), component(&component)
{
if (attribute_id.is_named()) {
this->attribute_name = attribute_id.name();
@@ -1239,7 +1236,8 @@ static void save_output_attribute(OutputAttribute &output_attribute)
using namespace blender::bke;
GVMutableAttribute_For_OutputAttribute &varray =
- dynamic_cast<GVMutableAttribute_For_OutputAttribute &>(output_attribute.varray());
+ dynamic_cast<GVMutableAttribute_For_OutputAttribute &>(
+ *output_attribute.varray().get_implementation());
GeometryComponent &component = *varray.component;
AttributeIDRef attribute_id;
@@ -1267,7 +1265,7 @@ static void save_output_attribute(OutputAttribute &output_attribute)
BUFFER_FOR_CPP_TYPE_VALUE(varray.type(), buffer);
for (const int i : IndexRange(varray.size())) {
varray.get(i, buffer);
- write_attribute.varray->set_by_relocate(i, buffer);
+ write_attribute.varray.set_by_relocate(i, buffer);
}
if (write_attribute.tag_modified_fn) {
write_attribute.tag_modified_fn();
@@ -1310,9 +1308,9 @@ static OutputAttribute create_output_attribute(GeometryComponent &component,
if (!attribute) {
if (default_value) {
const int64_t domain_size = component.attribute_domain_size(domain);
- const GVArray_For_SingleValueRef default_varray{*cpp_type, domain_size, default_value};
- component.attribute_try_create_builtin(attribute_name,
- AttributeInitVArray(&default_varray));
+ component.attribute_try_create_builtin(
+ attribute_name,
+ AttributeInitVArray(GVArray::ForSingleRef(*cpp_type, domain_size, default_value)));
}
else {
component.attribute_try_create_builtin(attribute_name, AttributeInitDefault());
@@ -1327,9 +1325,8 @@ static OutputAttribute create_output_attribute(GeometryComponent &component,
/* Builtin attribute is on different domain. */
return {};
}
-
- GVMutableArrayPtr varray = std::move(attribute.varray);
- if (varray->type() == *cpp_type) {
+ GVMutableArray varray = std::move(attribute.varray);
+ if (varray.type() == *cpp_type) {
/* Builtin attribute matches exactly. */
return OutputAttribute(std::move(varray),
domain,
@@ -1349,9 +1346,11 @@ static OutputAttribute create_output_attribute(GeometryComponent &component,
WriteAttributeLookup attribute = component.attribute_try_get_for_write(attribute_id);
if (!attribute) {
if (default_value) {
- const GVArray_For_SingleValueRef default_varray{*cpp_type, domain_size, default_value};
component.attribute_try_create(
- attribute_id, domain, data_type, AttributeInitVArray(&default_varray));
+ attribute_id,
+ domain,
+ data_type,
+ AttributeInitVArray(GVArray::ForSingleRef(*cpp_type, domain_size, default_value)));
}
else {
component.attribute_try_create(attribute_id, domain, data_type, AttributeInitDefault());
@@ -1363,7 +1362,7 @@ static OutputAttribute create_output_attribute(GeometryComponent &component,
return {};
}
}
- if (attribute.domain == domain && attribute.varray->type() == *cpp_type) {
+ if (attribute.domain == domain && attribute.varray.type() == *cpp_type) {
/* Existing generic attribute matches exactly. */
return OutputAttribute(std::move(attribute.varray),
@@ -1382,11 +1381,11 @@ static OutputAttribute create_output_attribute(GeometryComponent &component,
}
else {
/* Fill the temporary array with values from the existing attribute. */
- GVArrayPtr old_varray = component.attribute_get_for_read(
+ GVArray old_varray = component.attribute_get_for_read(
attribute_id, domain, data_type, default_value);
- old_varray->materialize_to_uninitialized(IndexRange(domain_size), data);
+ old_varray.materialize_to_uninitialized(IndexRange(domain_size), data);
}
- GVMutableArrayPtr varray = std::make_unique<GVMutableAttribute_For_OutputAttribute>(
+ GVMutableArray varray = GVMutableArray::For<GVMutableAttribute_For_OutputAttribute>(
GMutableSpan{*cpp_type, data, domain_size}, component, attribute_id);
return OutputAttribute(std::move(varray), domain, save_output_attribute, true);
@@ -1410,21 +1409,21 @@ OutputAttribute GeometryComponent::attribute_try_get_for_output_only(
namespace blender::bke {
-const GVArray *AttributeFieldInput::get_varray_for_context(const fn::FieldContext &context,
- IndexMask UNUSED(mask),
- ResourceScope &scope) const
+GVArray AttributeFieldInput::get_varray_for_context(const fn::FieldContext &context,
+ IndexMask UNUSED(mask),
+ ResourceScope &UNUSED(scope)) const
{
if (const GeometryComponentFieldContext *geometry_context =
dynamic_cast<const GeometryComponentFieldContext *>(&context)) {
const GeometryComponent &component = geometry_context->geometry_component();
const AttributeDomain domain = geometry_context->domain();
const CustomDataType data_type = cpp_type_to_custom_data_type(*type_);
- GVArrayPtr attribute = component.attribute_try_get_for_read(name_, domain, data_type);
+ GVArray attribute = component.attribute_try_get_for_read(name_, domain, data_type);
if (attribute) {
- return scope.add(std::move(attribute));
+ return attribute;
}
}
- return nullptr;
+ return {};
}
std::string AttributeFieldInput::socket_inspection_name() const
@@ -1451,31 +1450,32 @@ static StringRef get_random_id_attribute_name(const AttributeDomain domain)
{
switch (domain) {
case ATTR_DOMAIN_POINT:
+ case ATTR_DOMAIN_INSTANCE:
return "id";
default:
return "";
}
}
-const GVArray *IDAttributeFieldInput::get_varray_for_context(const fn::FieldContext &context,
- IndexMask mask,
- ResourceScope &scope) const
+GVArray IDAttributeFieldInput::get_varray_for_context(const fn::FieldContext &context,
+ IndexMask mask,
+ ResourceScope &scope) const
{
if (const GeometryComponentFieldContext *geometry_context =
dynamic_cast<const GeometryComponentFieldContext *>(&context)) {
const GeometryComponent &component = geometry_context->geometry_component();
const AttributeDomain domain = geometry_context->domain();
const StringRef name = get_random_id_attribute_name(domain);
- GVArrayPtr attribute = component.attribute_try_get_for_read(name, domain, CD_PROP_INT32);
+ GVArray attribute = component.attribute_try_get_for_read(name, domain, CD_PROP_INT32);
if (attribute) {
- BLI_assert(attribute->size() == component.attribute_domain_size(domain));
- return scope.add(std::move(attribute));
+ BLI_assert(attribute.size() == component.attribute_domain_size(domain));
+ return attribute;
}
/* Use the index as the fallback if no random ID attribute exists. */
return fn::IndexFieldInput::get_index_varray(mask, scope);
}
- return nullptr;
+ return {};
}
std::string IDAttributeFieldInput::socket_inspection_name() const
@@ -1495,19 +1495,20 @@ bool IDAttributeFieldInput::is_equal_to(const fn::FieldNode &other) const
return dynamic_cast<const IDAttributeFieldInput *>(&other) != nullptr;
}
-const GVArray *AnonymousAttributeFieldInput::get_varray_for_context(
- const fn::FieldContext &context, IndexMask UNUSED(mask), ResourceScope &scope) const
+GVArray AnonymousAttributeFieldInput::get_varray_for_context(const fn::FieldContext &context,
+ IndexMask UNUSED(mask),
+ ResourceScope &UNUSED(scope)) const
{
if (const GeometryComponentFieldContext *geometry_context =
dynamic_cast<const GeometryComponentFieldContext *>(&context)) {
const GeometryComponent &component = geometry_context->geometry_component();
const AttributeDomain domain = geometry_context->domain();
const CustomDataType data_type = cpp_type_to_custom_data_type(*type_);
- GVArrayPtr attribute = component.attribute_try_get_for_read(
+ GVArray attribute = component.attribute_try_get_for_read(
anonymous_id_.get(), domain, data_type);
- return scope.add(std::move(attribute));
+ return attribute;
}
- return nullptr;
+ return {};
}
std::string AnonymousAttributeFieldInput::socket_inspection_name() const
diff --git a/source/blender/blenkernel/intern/attribute_access_intern.hh b/source/blender/blenkernel/intern/attribute_access_intern.hh
index 140498bdb01..b77d7010efa 100644
--- a/source/blender/blenkernel/intern/attribute_access_intern.hh
+++ b/source/blender/blenkernel/intern/attribute_access_intern.hh
@@ -24,9 +24,6 @@
namespace blender::bke {
-using fn::GVArrayPtr;
-using fn::GVMutableArrayPtr;
-
/**
* Utility to group together multiple functions that are used to access custom data on geometry
* components in a generic way.
@@ -86,7 +83,7 @@ class BuiltinAttributeProvider {
{
}
- virtual GVArrayPtr try_get_for_read(const GeometryComponent &component) const = 0;
+ virtual GVArray try_get_for_read(const GeometryComponent &component) const = 0;
virtual WriteAttributeLookup try_get_for_write(GeometryComponent &component) const = 0;
virtual bool try_delete(GeometryComponent &component) const = 0;
virtual bool try_create(GeometryComponent &UNUSED(component),
@@ -188,8 +185,8 @@ class CustomDataAttributeProvider final : public DynamicAttributesProvider {
*/
class NamedLegacyCustomDataProvider final : public DynamicAttributesProvider {
private:
- using AsReadAttribute = GVArrayPtr (*)(const void *data, const int domain_size);
- using AsWriteAttribute = GVMutableArrayPtr (*)(void *data, const int domain_size);
+ using AsReadAttribute = GVArray (*)(const void *data, const int domain_size);
+ using AsWriteAttribute = GVMutableArray (*)(void *data, const int domain_size);
const AttributeDomain domain_;
const CustomDataType attribute_type_;
const CustomDataType stored_type_;
@@ -232,8 +229,8 @@ class NamedLegacyCustomDataProvider final : public DynamicAttributesProvider {
* if the stored type is the same as the attribute type.
*/
class BuiltinCustomDataLayerProvider final : public BuiltinAttributeProvider {
- using AsReadAttribute = GVArrayPtr (*)(const void *data, const int domain_size);
- using AsWriteAttribute = GVMutableArrayPtr (*)(void *data, const int domain_size);
+ using AsReadAttribute = GVArray (*)(const void *data, const int domain_size);
+ using AsWriteAttribute = GVMutableArray (*)(void *data, const int domain_size);
using UpdateOnRead = void (*)(const GeometryComponent &component);
using UpdateOnWrite = void (*)(GeometryComponent &component);
const CustomDataType stored_type_;
@@ -266,7 +263,7 @@ class BuiltinCustomDataLayerProvider final : public BuiltinAttributeProvider {
{
}
- GVArrayPtr try_get_for_read(const GeometryComponent &component) const final;
+ GVArray try_get_for_read(const GeometryComponent &component) const final;
WriteAttributeLookup try_get_for_write(GeometryComponent &component) const final;
bool try_delete(GeometryComponent &component) const final;
bool try_create(GeometryComponent &component, const AttributeInit &initializer) const final;
diff --git a/source/blender/blenkernel/intern/blender.c b/source/blender/blenkernel/intern/blender.c
index 97f8bddc043..fb65a9bec7e 100644
--- a/source/blender/blenkernel/intern/blender.c
+++ b/source/blender/blenkernel/intern/blender.c
@@ -90,7 +90,6 @@ void BKE_blender_free(void)
IMB_exit();
BKE_cachefiles_exit();
- BKE_images_exit();
DEG_free_node_types();
BKE_brush_system_exit();
diff --git a/source/blender/blenkernel/intern/blender_copybuffer.c b/source/blender/blenkernel/intern/blender_copybuffer.c
index 9c9f898afef..f8b943d3479 100644
--- a/source/blender/blenkernel/intern/blender_copybuffer.c
+++ b/source/blender/blenkernel/intern/blender_copybuffer.c
@@ -57,20 +57,26 @@
/** \name Copy/Paste `.blend`, partial saves.
* \{ */
-void BKE_copybuffer_begin(Main *bmain_src)
+/** Initialize a copy operation. */
+void BKE_copybuffer_copy_begin(Main *bmain_src)
{
BKE_blendfile_write_partial_begin(bmain_src);
}
-void BKE_copybuffer_tag_ID(ID *id)
+/** Mark an ID to be copied. Should only be called after a call to #BKE_copybuffer_copy_begin. */
+void BKE_copybuffer_copy_tag_ID(ID *id)
{
BKE_blendfile_write_partial_tag_ID(id, true);
}
/**
- * \return Success.
+ * Finalize a copy operation into given .blend file 'buffer'.
+ *
+ * \param filename: Full path to the .blend file used as copy/paste buffer.
+ *
+ * \return true on success, false otherwise.
*/
-bool BKE_copybuffer_save(Main *bmain_src, const char *filename, ReportList *reports)
+bool BKE_copybuffer_copy_end(Main *bmain_src, const char *filename, ReportList *reports)
{
const int write_flags = 0;
const eBLO_WritePathRemap remap_mode = BLO_WRITE_PATH_REMAP_RELATIVE;
@@ -82,6 +88,16 @@ bool BKE_copybuffer_save(Main *bmain_src, const char *filename, ReportList *repo
return retval;
}
+/**
+ * Paste datablocks from the given .blend file 'buffer' (i.e. append them).
+ *
+ * Unlike #BKE_copybuffer_paste, it does not perform any instantiation of collections/objects/etc.
+ *
+ * \param libname: Full path to the .blend file used as copy/paste buffer.
+ * \param id_types_mask: Only directly link IDs of those types from the given .blend file buffer.
+ *
+ * \return true on success, false otherwise.
+ */
bool BKE_copybuffer_read(Main *bmain_dst,
const char *libname,
ReportList *reports,
@@ -116,12 +132,22 @@ bool BKE_copybuffer_read(Main *bmain_dst,
}
/**
- * \return Number of IDs directly pasted from the buffer
- * (does not includes indirectly pulled out ones).
+ * Paste datablocks from the given .blend file 'buffer' (i.e. append them).
+ *
+ * Similar to #BKE_copybuffer_read, but also handles instantiation of collections/objects/etc.
+ *
+ * \param libname: Full path to the .blend file used as copy/paste buffer.
+ * \param flag: A combination of #eBLOLibLinkFlags and ##eFileSel_Params_Flag to control
+ * link/append behavior.
+ * \note: Ignores #FILE_LINK flag, since it always appends IDs.
+ * \param id_types_mask: Only directly link IDs of those types from the given .blend file buffer.
+ *
+ * \return Number of IDs directly pasted from the buffer (does not includes indirectly linked
+ * ones).
*/
int BKE_copybuffer_paste(bContext *C,
const char *libname,
- const short flag,
+ const int flag,
ReportList *reports,
const uint64_t id_types_mask)
{
diff --git a/source/blender/blenkernel/intern/blendfile_link_append.c b/source/blender/blenkernel/intern/blendfile_link_append.c
new file mode 100644
index 00000000000..36f03990953
--- /dev/null
+++ b/source/blender/blenkernel/intern/blendfile_link_append.c
@@ -0,0 +1,1566 @@
+/*
+ * 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.
+ */
+
+/** \file
+ * \ingroup bke
+ *
+ * High level `.blend` file link/append code,
+ * including linking/appending several IDs from different libraries, handling instanciations of
+ * collections/objects/obdata in current scene.
+ */
+
+#include <stdlib.h>
+#include <string.h>
+
+#include "CLG_log.h"
+
+#include "MEM_guardedalloc.h"
+
+#include "DNA_ID.h"
+#include "DNA_collection_types.h"
+#include "DNA_key_types.h"
+#include "DNA_object_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_screen_types.h"
+#include "DNA_space_types.h"
+
+#include "BLI_bitmap.h"
+#include "BLI_blenlib.h"
+#include "BLI_ghash.h"
+#include "BLI_linklist.h"
+#include "BLI_math.h"
+#include "BLI_memarena.h"
+#include "BLI_utildefines.h"
+
+#include "BLT_translation.h"
+
+#include "BKE_idtype.h"
+#include "BKE_key.h"
+#include "BKE_layer.h"
+#include "BKE_lib_id.h"
+#include "BKE_lib_override.h"
+#include "BKE_lib_query.h"
+#include "BKE_lib_remap.h"
+#include "BKE_main.h"
+#include "BKE_material.h"
+#include "BKE_object.h"
+#include "BKE_report.h"
+#include "BKE_rigidbody.h"
+#include "BKE_scene.h"
+
+#include "BKE_blendfile_link_append.h"
+
+#include "BLO_readfile.h"
+#include "BLO_writefile.h"
+
+static CLG_LogRef LOG = {"bke.blendfile_link_append"};
+
+/* -------------------------------------------------------------------- */
+/** \name Link/append context implementation and public management API.
+ * \{ */
+
+typedef struct BlendfileLinkAppendContextItem {
+ /** Name of the ID (without the heading two-chars IDcode). */
+ char *name;
+ /** All libs (from BlendfileLinkAppendContext.libraries) to try to load this ID from. */
+ BLI_bitmap *libraries;
+ /** ID type. */
+ short idcode;
+
+ /** Type of action to perform on this item, and general status tag information.
+ * NOTE: Mostly used by append post-linking processing. */
+ char action;
+ char tag;
+
+ /** Newly linked ID (NULL until it has been successfully linked). */
+ ID *new_id;
+ /** Library ID from which the #new_id has been linked (NULL until it has been successfully
+ * linked). */
+ Library *source_library;
+ /** Opaque user data pointer. */
+ void *userdata;
+} BlendfileLinkAppendContextItem;
+
+/* A blendfile library entry in the `libraries` list of #BlendfileLinkAppendContext. */
+typedef struct BlendfileLinkAppendContextLibrary {
+ char *path; /* Absolute .blend file path. */
+ BlendHandle *blo_handle; /* Blend file handle, if any. */
+ bool blo_handle_is_owned; /* Whether the blend file handle is owned, or borrowed. */
+ /* The blendfile report associated with the `blo_handle`, if owned. */
+ BlendFileReadReport bf_reports;
+} BlendfileLinkAppendContextLibrary;
+
+typedef struct BlendfileLinkAppendContext {
+ /** List of library paths to search IDs in. */
+ LinkNodePair libraries;
+ /** List of all ID to try to link from #libraries. */
+ LinkNodePair items;
+ int num_libraries;
+ int num_items;
+ /** Linking/appending parameters. Including bmain, scene, viewlayer and view3d. */
+ LibraryLink_Params *params;
+
+ /** Allows to easily find an existing items from an ID pointer. */
+ GHash *new_id_to_item;
+
+ /** Runtime info used by append code to manage re-use of already appended matching IDs. */
+ GHash *library_weak_reference_mapping;
+
+ /** Embedded blendfile and its size, if needed. */
+ const void *blendfile_mem;
+ size_t blendfile_memsize;
+
+ /** Internal 'private' data */
+ MemArena *memarena;
+} BlendfileLinkAppendContext;
+
+typedef struct BlendfileLinkAppendContextCallBack {
+ BlendfileLinkAppendContext *lapp_context;
+ BlendfileLinkAppendContextItem *item;
+ ReportList *reports;
+
+} BlendfileLinkAppendContextCallBack;
+
+/* Actions to apply to an item (i.e. linked ID). */
+enum {
+ LINK_APPEND_ACT_UNSET = 0,
+ LINK_APPEND_ACT_KEEP_LINKED,
+ LINK_APPEND_ACT_REUSE_LOCAL,
+ LINK_APPEND_ACT_MAKE_LOCAL,
+ LINK_APPEND_ACT_COPY_LOCAL,
+};
+
+/* Various status info about an item (i.e. linked ID). */
+enum {
+ /* An indirectly linked ID. */
+ LINK_APPEND_TAG_INDIRECT = 1 << 0,
+};
+
+static BlendHandle *link_append_context_library_blohandle_ensure(
+ BlendfileLinkAppendContext *lapp_context,
+ BlendfileLinkAppendContextLibrary *lib_context,
+ ReportList *reports)
+{
+ if (reports != NULL) {
+ lib_context->bf_reports.reports = reports;
+ }
+
+ char *libname = lib_context->path;
+ BlendHandle *blo_handle = lib_context->blo_handle;
+ if (blo_handle == NULL) {
+ if (STREQ(libname, BLO_EMBEDDED_STARTUP_BLEND)) {
+ blo_handle = BLO_blendhandle_from_memory(lapp_context->blendfile_mem,
+ (int)lapp_context->blendfile_memsize,
+ &lib_context->bf_reports);
+ }
+ else {
+ blo_handle = BLO_blendhandle_from_file(libname, &lib_context->bf_reports);
+ }
+ lib_context->blo_handle = blo_handle;
+ lib_context->blo_handle_is_owned = true;
+ }
+
+ return blo_handle;
+}
+
+static void link_append_context_library_blohandle_release(
+ BlendfileLinkAppendContext *UNUSED(lapp_context),
+ BlendfileLinkAppendContextLibrary *lib_context)
+{
+ if (lib_context->blo_handle_is_owned && lib_context->blo_handle != NULL) {
+ BLO_blendhandle_close(lib_context->blo_handle);
+ lib_context->blo_handle = NULL;
+ }
+}
+
+/** Allocate and initialize a new context to link/append datablocks.
+ *
+ * \param flag a combination of #eFileSel_Params_Flag from DNA_space_types.h & #eBLOLibLinkFlags
+ * from BLO_readfile.h
+ */
+BlendfileLinkAppendContext *BKE_blendfile_link_append_context_new(LibraryLink_Params *params)
+{
+ MemArena *ma = BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE, __func__);
+ BlendfileLinkAppendContext *lapp_context = BLI_memarena_calloc(ma, sizeof(*lapp_context));
+
+ lapp_context->params = params;
+ lapp_context->memarena = ma;
+
+ return lapp_context;
+}
+
+/** Free a link/append context. */
+void BKE_blendfile_link_append_context_free(BlendfileLinkAppendContext *lapp_context)
+{
+ if (lapp_context->new_id_to_item != NULL) {
+ BLI_ghash_free(lapp_context->new_id_to_item, NULL, NULL);
+ }
+
+ for (LinkNode *liblink = lapp_context->libraries.list; liblink != NULL;
+ liblink = liblink->next) {
+ BlendfileLinkAppendContextLibrary *lib_context = liblink->link;
+ link_append_context_library_blohandle_release(lapp_context, lib_context);
+ }
+
+ BLI_assert(lapp_context->library_weak_reference_mapping == NULL);
+
+ BLI_memarena_free(lapp_context->memarena);
+}
+
+/** Set or clear flags in given \a lapp_context.
+ *
+ * \param do_set Set the given \a flag if true, clear it otherwise.
+ */
+void BKE_blendfile_link_append_context_flag_set(BlendfileLinkAppendContext *lapp_context,
+ const int flag,
+ const bool do_set)
+{
+ if (do_set) {
+ lapp_context->params->flag |= flag;
+ }
+ else {
+ lapp_context->params->flag &= ~flag;
+ }
+}
+
+/** Store reference to a Blender's embedded memfile into the context.
+ *
+ * \note This is required since embedded startup blender file is handled in `ED` module, which
+ * cannot be linked in BKE code.
+ */
+void BKE_blendfile_link_append_context_embedded_blendfile_set(
+ BlendfileLinkAppendContext *lapp_context, const void *blendfile_mem, int blendfile_memsize)
+{
+ BLI_assert_msg(lapp_context->blendfile_mem == NULL,
+ "Please explicitely clear reference to an embedded blender memfile before "
+ "setting a new one");
+ lapp_context->blendfile_mem = blendfile_mem;
+ lapp_context->blendfile_memsize = (size_t)blendfile_memsize;
+}
+
+/** Clear reference to Blender's embedded startup file into the context. */
+void BKE_blendfile_link_append_context_embedded_blendfile_clear(
+ BlendfileLinkAppendContext *lapp_context)
+{
+ lapp_context->blendfile_mem = NULL;
+ lapp_context->blendfile_memsize = 0;
+}
+
+/** Add a new source library to search for items to be linked to the given link/append context.
+ *
+ * \param libname: the absolute path to the library blend file.
+ * \param blo_handle: the blend file handle of the library, NULL is not available. Note that this
+ * is only borrowed for linking purpose, no releasing or other management will
+ * be performed by #BKE_blendfile_link_append code on it.
+ *
+ * \note *Never* call BKE_blendfile_link_append_context_library_add() after having added some
+ * items. */
+void BKE_blendfile_link_append_context_library_add(BlendfileLinkAppendContext *lapp_context,
+ const char *libname,
+ BlendHandle *blo_handle)
+{
+ BLI_assert(lapp_context->items.list == NULL);
+
+ BlendfileLinkAppendContextLibrary *lib_context = BLI_memarena_calloc(lapp_context->memarena,
+ sizeof(*lib_context));
+
+ size_t len = strlen(libname) + 1;
+ char *libpath = BLI_memarena_alloc(lapp_context->memarena, len);
+ BLI_strncpy(libpath, libname, len);
+
+ lib_context->path = libpath;
+ lib_context->blo_handle = blo_handle;
+ lib_context->blo_handle_is_owned = (blo_handle == NULL);
+
+ BLI_linklist_append_arena(&lapp_context->libraries, lib_context, lapp_context->memarena);
+ lapp_context->num_libraries++;
+}
+
+/** Add a new item (datablock name and idcode) to be searched and linked/appended from libraries
+ * associated to the given context.
+ *
+ * \param userdata: an opaque user-data pointer stored in generated link/append item. */
+BlendfileLinkAppendContextItem *BKE_blendfile_link_append_context_item_add(
+ BlendfileLinkAppendContext *lapp_context,
+ const char *idname,
+ const short idcode,
+ void *userdata)
+{
+ BlendfileLinkAppendContextItem *item = BLI_memarena_calloc(lapp_context->memarena,
+ sizeof(*item));
+ size_t len = strlen(idname) + 1;
+
+ item->name = BLI_memarena_alloc(lapp_context->memarena, len);
+ BLI_strncpy(item->name, idname, len);
+ item->idcode = idcode;
+ item->libraries = BLI_BITMAP_NEW_MEMARENA(lapp_context->memarena, lapp_context->num_libraries);
+
+ item->new_id = NULL;
+ item->action = LINK_APPEND_ACT_UNSET;
+ item->userdata = userdata;
+
+ BLI_linklist_append_arena(&lapp_context->items, item, lapp_context->memarena);
+ lapp_context->num_items++;
+
+ return item;
+}
+
+/** Enable search of the given \a item into the library stored at given index in the link/append
+ * context. */
+void BKE_blendfile_link_append_context_item_library_index_enable(
+ BlendfileLinkAppendContext *UNUSED(lapp_context),
+ BlendfileLinkAppendContextItem *item,
+ const int library_index)
+{
+ BLI_BITMAP_ENABLE(item->libraries, library_index);
+}
+
+/** Check if given link/append context is empty (has no items to process) or not. */
+bool BKE_blendfile_link_append_context_is_empty(struct BlendfileLinkAppendContext *lapp_context)
+{
+ return lapp_context->num_items == 0;
+}
+
+void *BKE_blendfile_link_append_context_item_userdata_get(
+ BlendfileLinkAppendContext *UNUSED(lapp_context), BlendfileLinkAppendContextItem *item)
+{
+ return item->userdata;
+}
+
+ID *BKE_blendfile_link_append_context_item_newid_get(
+ BlendfileLinkAppendContext *UNUSED(lapp_context), BlendfileLinkAppendContextItem *item)
+{
+ return item->new_id;
+}
+
+short BKE_blendfile_link_append_context_item_idcode_get(
+ struct BlendfileLinkAppendContext *UNUSED(lapp_context),
+ struct BlendfileLinkAppendContextItem *item)
+{
+ return item->idcode;
+}
+
+/** Iterate over all (or a subset) of the items listed in given #BlendfileLinkAppendContext, and
+ * call the `callback_function` on them.
+ *
+ * \param flag: Control which type of items to process (see
+ * #eBlendfileLinkAppendForeachItemFlag enum flags).
+ * \param userdata: An opaque void pointer passed to the `callback_function`.
+ */
+void BKE_blendfile_link_append_context_item_foreach(
+ struct BlendfileLinkAppendContext *lapp_context,
+ BKE_BlendfileLinkAppendContexteItemFunction callback_function,
+ const eBlendfileLinkAppendForeachItemFlag flag,
+ void *userdata)
+{
+ for (LinkNode *itemlink = lapp_context->items.list; itemlink; itemlink = itemlink->next) {
+ BlendfileLinkAppendContextItem *item = itemlink->link;
+
+ if ((flag & BKE_BLENDFILE_LINK_APPEND_FOREACH_ITEM_FLAG_DO_DIRECT) == 0 &&
+ (item->tag & LINK_APPEND_TAG_INDIRECT) == 0) {
+ continue;
+ }
+ if ((flag & BKE_BLENDFILE_LINK_APPEND_FOREACH_ITEM_FLAG_DO_INDIRECT) == 0 &&
+ (item->tag & LINK_APPEND_TAG_INDIRECT) != 0) {
+ continue;
+ }
+
+ if (!callback_function(lapp_context, item, userdata)) {
+ break;
+ }
+ }
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Library link/append helper functions.
+ *
+ * \{ */
+
+/* Struct gathering all required data to handle instantiation of loose data-blocks. */
+typedef struct LooseDataInstantiateContext {
+ BlendfileLinkAppendContext *lapp_context;
+
+ /* The collection in which to add loose collections/objects. */
+ Collection *active_collection;
+} LooseDataInstantiateContext;
+
+static bool object_in_any_scene(Main *bmain, Object *ob)
+{
+ LISTBASE_FOREACH (Scene *, sce, &bmain->scenes) {
+ if (BKE_scene_object_find(sce, ob)) {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+static bool object_in_any_collection(Main *bmain, Object *ob)
+{
+ LISTBASE_FOREACH (Collection *, collection, &bmain->collections) {
+ if (BKE_collection_has_object(collection, ob)) {
+ return true;
+ }
+ }
+
+ LISTBASE_FOREACH (Scene *, scene, &bmain->scenes) {
+ if (scene->master_collection != NULL &&
+ BKE_collection_has_object(scene->master_collection, ob)) {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+static ID *loose_data_instantiate_process_check(LooseDataInstantiateContext *instantiate_context,
+ BlendfileLinkAppendContextItem *item)
+{
+ BlendfileLinkAppendContext *lapp_context = instantiate_context->lapp_context;
+ /* In linking case, we always want to handle instantiation. */
+ if (lapp_context->params->flag & FILE_LINK) {
+ return item->new_id;
+ }
+
+ /* We consider that if we either kept it linked, or re-used already local data, instantiation
+ * status of those should not be modified. */
+ if (!ELEM(item->action, LINK_APPEND_ACT_COPY_LOCAL, LINK_APPEND_ACT_MAKE_LOCAL)) {
+ return NULL;
+ }
+
+ ID *id = item->new_id;
+ if (id == NULL) {
+ return NULL;
+ }
+
+ if (item->action == LINK_APPEND_ACT_COPY_LOCAL) {
+ BLI_assert(ID_IS_LINKED(id));
+ id = id->newid;
+ if (id == NULL) {
+ return NULL;
+ }
+
+ BLI_assert(!ID_IS_LINKED(id));
+ return id;
+ }
+
+ BLI_assert(!ID_IS_LINKED(id));
+ return id;
+}
+
+static void loose_data_instantiate_ensure_active_collection(
+ LooseDataInstantiateContext *instantiate_context)
+{
+
+ BlendfileLinkAppendContext *lapp_context = instantiate_context->lapp_context;
+ Main *bmain = instantiate_context->lapp_context->params->bmain;
+ Scene *scene = instantiate_context->lapp_context->params->context.scene;
+ ViewLayer *view_layer = instantiate_context->lapp_context->params->context.view_layer;
+
+ /* Find or add collection as needed. */
+ if (instantiate_context->active_collection == NULL) {
+ if (lapp_context->params->flag & FILE_ACTIVE_COLLECTION) {
+ LayerCollection *lc = BKE_layer_collection_get_active(view_layer);
+ instantiate_context->active_collection = lc->collection;
+ }
+ else {
+ if (lapp_context->params->flag & FILE_LINK) {
+ instantiate_context->active_collection = BKE_collection_add(
+ bmain, scene->master_collection, DATA_("Linked Data"));
+ }
+ else {
+ instantiate_context->active_collection = BKE_collection_add(
+ bmain, scene->master_collection, DATA_("Appended Data"));
+ }
+ }
+ }
+}
+
+static void loose_data_instantiate_object_base_instance_init(Main *bmain,
+ Collection *collection,
+ Object *ob,
+ ViewLayer *view_layer,
+ const View3D *v3d,
+ const int flag,
+ bool set_active)
+{
+ /* Auto-select and appending. */
+ if ((flag & FILE_AUTOSELECT) && ((flag & FILE_LINK) == 0)) {
+ /* While in general the object should not be manipulated,
+ * when the user requests the object to be selected, ensure it's visible and selectable. */
+ ob->visibility_flag &= ~(OB_HIDE_VIEWPORT | OB_HIDE_SELECT);
+ }
+
+ BKE_collection_object_add(bmain, collection, ob);
+
+ Base *base = BKE_view_layer_base_find(view_layer, ob);
+
+ if (v3d != NULL) {
+ base->local_view_bits |= v3d->local_view_uuid;
+ }
+
+ if (flag & FILE_AUTOSELECT) {
+ /* All objects that use #FILE_AUTOSELECT must be selectable (unless linking data). */
+ BLI_assert((base->flag & BASE_SELECTABLE) || (flag & FILE_LINK));
+ if (base->flag & BASE_SELECTABLE) {
+ base->flag |= BASE_SELECTED;
+ }
+ }
+
+ if (set_active) {
+ view_layer->basact = base;
+ }
+
+ BKE_scene_object_base_flag_sync_from_base(base);
+}
+
+/* Tag obdata that actually need to be instantiated (those referenced by an object do not, since
+ * the object will be instantiated instaed if needed. */
+static void loose_data_instantiate_obdata_preprocess(
+ LooseDataInstantiateContext *instantiate_context)
+{
+ BlendfileLinkAppendContext *lapp_context = instantiate_context->lapp_context;
+ LinkNode *itemlink;
+
+ /* First pass on obdata to enable their instantiation by default, then do a second pass on
+ * objects to clear it for any obdata already in use. */
+ for (itemlink = lapp_context->items.list; itemlink; itemlink = itemlink->next) {
+ BlendfileLinkAppendContextItem *item = itemlink->link;
+ ID *id = loose_data_instantiate_process_check(instantiate_context, item);
+ if (id == NULL) {
+ continue;
+ }
+ const ID_Type idcode = GS(id->name);
+ if (!OB_DATA_SUPPORT_ID(idcode)) {
+ continue;
+ }
+
+ id->tag |= LIB_TAG_DOIT;
+ }
+ for (itemlink = lapp_context->items.list; itemlink; itemlink = itemlink->next) {
+ BlendfileLinkAppendContextItem *item = itemlink->link;
+ ID *id = item->new_id;
+ if (id == NULL || GS(id->name) != ID_OB) {
+ continue;
+ }
+
+ Object *ob = (Object *)id;
+ Object *new_ob = (Object *)id->newid;
+ if (ob->data != NULL) {
+ ((ID *)(ob->data))->tag &= ~LIB_TAG_DOIT;
+ }
+ if (new_ob != NULL && new_ob->data != NULL) {
+ ((ID *)(new_ob->data))->tag &= ~LIB_TAG_DOIT;
+ }
+ }
+}
+
+static void loose_data_instantiate_collection_process(
+ LooseDataInstantiateContext *instantiate_context)
+{
+ BlendfileLinkAppendContext *lapp_context = instantiate_context->lapp_context;
+ Main *bmain = lapp_context->params->bmain;
+ Scene *scene = lapp_context->params->context.scene;
+ ViewLayer *view_layer = lapp_context->params->context.view_layer;
+ const View3D *v3d = lapp_context->params->context.v3d;
+
+ /* NOTE: For collections we only view_layer-instantiate duplicated collections that have
+ * non-instantiated objects in them. */
+ LinkNode *itemlink;
+ for (itemlink = lapp_context->items.list; itemlink; itemlink = itemlink->next) {
+ BlendfileLinkAppendContextItem *item = itemlink->link;
+ ID *id = loose_data_instantiate_process_check(instantiate_context, item);
+ if (id == NULL || GS(id->name) != ID_GR) {
+ continue;
+ }
+
+ /* We do not want to force instantiation of indirectly appended collections. Users can now
+ * easily instantiate collections (and their objects) as needed by themselves. See T67032. */
+ /* We need to check that objects in that collections are already instantiated in a scene.
+ * Otherwise, it's better to add the collection to the scene's active collection, than to
+ * instantiate its objects in active scene's collection directly. See T61141.
+ *
+ * NOTE: We only check object directly into that collection, not recursively into its
+ * children.
+ */
+ Collection *collection = (Collection *)id;
+ /* We always add collections directly selected by the user. */
+ bool do_add_collection = (item->tag & LINK_APPEND_TAG_INDIRECT) == 0;
+ if (!do_add_collection) {
+ LISTBASE_FOREACH (CollectionObject *, coll_ob, &collection->gobject) {
+ Object *ob = coll_ob->ob;
+ if (!object_in_any_scene(bmain, ob)) {
+ do_add_collection = true;
+ break;
+ }
+ }
+ }
+ if (!do_add_collection) {
+ continue;
+ }
+
+ loose_data_instantiate_ensure_active_collection(instantiate_context);
+ Collection *active_collection = instantiate_context->active_collection;
+
+ /* In case user requested instantiation of collections as empties, we do so for the one they
+ * explicitly selected (originally directly linked IDs) only. */
+ if ((lapp_context->params->flag & BLO_LIBLINK_COLLECTION_INSTANCE) != 0 &&
+ (item->tag & LINK_APPEND_TAG_INDIRECT) == 0) {
+ /* BKE_object_add(...) messes with the selection. */
+ Object *ob = BKE_object_add_only_object(bmain, OB_EMPTY, collection->id.name + 2);
+ ob->type = OB_EMPTY;
+ ob->empty_drawsize = U.collection_instance_empty_size;
+
+ const bool set_selected = (lapp_context->params->flag & FILE_AUTOSELECT) != 0;
+ /* TODO: why is it OK to make this active here but not in other situations?
+ * See other callers of #object_base_instance_init */
+ const bool set_active = set_selected;
+ loose_data_instantiate_object_base_instance_init(
+ bmain, active_collection, ob, view_layer, v3d, lapp_context->params->flag, set_active);
+
+ /* Assign the collection. */
+ ob->instance_collection = collection;
+ id_us_plus(&collection->id);
+ ob->transflag |= OB_DUPLICOLLECTION;
+ copy_v3_v3(ob->loc, scene->cursor.location);
+ }
+ else {
+ /* Add collection as child of active collection. */
+ BKE_collection_child_add(bmain, active_collection, collection);
+
+ if ((lapp_context->params->flag & FILE_AUTOSELECT) != 0) {
+ LISTBASE_FOREACH (CollectionObject *, coll_ob, &collection->gobject) {
+ Object *ob = coll_ob->ob;
+ Base *base = BKE_view_layer_base_find(view_layer, ob);
+ if (base) {
+ base->flag |= BASE_SELECTED;
+ BKE_scene_object_base_flag_sync_from_base(base);
+ }
+ }
+ }
+ }
+ }
+}
+
+static void loose_data_instantiate_object_process(LooseDataInstantiateContext *instantiate_context)
+{
+ BlendfileLinkAppendContext *lapp_context = instantiate_context->lapp_context;
+ Main *bmain = lapp_context->params->bmain;
+ ViewLayer *view_layer = lapp_context->params->context.view_layer;
+ const View3D *v3d = lapp_context->params->context.v3d;
+
+ /* Do NOT make base active here! screws up GUI stuff,
+ * if you want it do it at the editor level. */
+ const bool object_set_active = false;
+
+ /* NOTE: For objects we only view_layer-instantiate duplicated objects that are not yet used
+ * anywhere. */
+ LinkNode *itemlink;
+ for (itemlink = lapp_context->items.list; itemlink; itemlink = itemlink->next) {
+ BlendfileLinkAppendContextItem *item = itemlink->link;
+ ID *id = loose_data_instantiate_process_check(instantiate_context, item);
+ if (id == NULL || GS(id->name) != ID_OB) {
+ continue;
+ }
+
+ Object *ob = (Object *)id;
+
+ if (object_in_any_collection(bmain, ob)) {
+ continue;
+ }
+
+ loose_data_instantiate_ensure_active_collection(instantiate_context);
+ Collection *active_collection = instantiate_context->active_collection;
+
+ CLAMP_MIN(ob->id.us, 0);
+ ob->mode = OB_MODE_OBJECT;
+
+ loose_data_instantiate_object_base_instance_init(bmain,
+ active_collection,
+ ob,
+ view_layer,
+ v3d,
+ lapp_context->params->flag,
+ object_set_active);
+ }
+}
+
+static void loose_data_instantiate_obdata_process(LooseDataInstantiateContext *instantiate_context)
+{
+ BlendfileLinkAppendContext *lapp_context = instantiate_context->lapp_context;
+ Main *bmain = lapp_context->params->bmain;
+ Scene *scene = lapp_context->params->context.scene;
+ ViewLayer *view_layer = lapp_context->params->context.view_layer;
+ const View3D *v3d = lapp_context->params->context.v3d;
+
+ /* Do NOT make base active here! screws up GUI stuff,
+ * if you want it do it at the editor level. */
+ const bool object_set_active = false;
+
+ LinkNode *itemlink;
+ for (itemlink = lapp_context->items.list; itemlink; itemlink = itemlink->next) {
+ BlendfileLinkAppendContextItem *item = itemlink->link;
+ ID *id = loose_data_instantiate_process_check(instantiate_context, item);
+ if (id == NULL) {
+ continue;
+ }
+ const ID_Type idcode = GS(id->name);
+ if (!OB_DATA_SUPPORT_ID(idcode)) {
+ continue;
+ }
+ if ((id->tag & LIB_TAG_DOIT) == 0) {
+ continue;
+ }
+
+ loose_data_instantiate_ensure_active_collection(instantiate_context);
+ Collection *active_collection = instantiate_context->active_collection;
+
+ const int type = BKE_object_obdata_to_type(id);
+ BLI_assert(type != -1);
+ Object *ob = BKE_object_add_only_object(bmain, type, id->name + 2);
+ ob->data = id;
+ id_us_plus(id);
+ BKE_object_materials_test(bmain, ob, ob->data);
+
+ loose_data_instantiate_object_base_instance_init(bmain,
+ active_collection,
+ ob,
+ view_layer,
+ v3d,
+ lapp_context->params->flag,
+ object_set_active);
+
+ copy_v3_v3(ob->loc, scene->cursor.location);
+
+ id->tag &= ~LIB_TAG_DOIT;
+ }
+}
+
+static void loose_data_instantiate_object_rigidbody_postprocess(
+ LooseDataInstantiateContext *instantiate_context)
+{
+ BlendfileLinkAppendContext *lapp_context = instantiate_context->lapp_context;
+ Main *bmain = lapp_context->params->bmain;
+
+ LinkNode *itemlink;
+ /* Add rigid body objects and constraints to current RB world(s). */
+ for (itemlink = lapp_context->items.list; itemlink; itemlink = itemlink->next) {
+ BlendfileLinkAppendContextItem *item = itemlink->link;
+ ID *id = loose_data_instantiate_process_check(instantiate_context, item);
+ if (id == NULL || GS(id->name) != ID_OB) {
+ continue;
+ }
+ BKE_rigidbody_ensure_local_object(bmain, (Object *)id);
+ }
+}
+
+static void loose_data_instantiate(LooseDataInstantiateContext *instantiate_context)
+{
+ if (instantiate_context->lapp_context->params->context.scene == NULL) {
+ /* In some cases, like the asset drag&drop e.g., the caller code manages instantiation itself.
+ */
+ return;
+ }
+
+ BlendfileLinkAppendContext *lapp_context = instantiate_context->lapp_context;
+ const bool do_obdata = (lapp_context->params->flag & BLO_LIBLINK_OBDATA_INSTANCE) != 0;
+
+ /* First pass on obdata to enable their instantiation by default, then do a second pass on
+ * objects to clear it for any obdata already in use. */
+ if (do_obdata) {
+ loose_data_instantiate_obdata_preprocess(instantiate_context);
+ }
+
+ /* First do collections, then objects, then obdata. */
+ loose_data_instantiate_collection_process(instantiate_context);
+ loose_data_instantiate_object_process(instantiate_context);
+ if (do_obdata) {
+ loose_data_instantiate_obdata_process(instantiate_context);
+ }
+
+ loose_data_instantiate_object_rigidbody_postprocess(instantiate_context);
+}
+
+static void new_id_to_item_mapping_add(BlendfileLinkAppendContext *lapp_context,
+ ID *id,
+ BlendfileLinkAppendContextItem *item)
+{
+ BLI_ghash_insert(lapp_context->new_id_to_item, id, item);
+
+ /* This ensures that if a liboverride reference is also linked/used by some other appended
+ * data, it gets a local copy instead of being made directly local, so that the liboverride
+ * references remain valid (i.e. linked data). */
+ if (ID_IS_OVERRIDE_LIBRARY_REAL(id)) {
+ id->override_library->reference->tag |= LIB_TAG_PRE_EXISTING;
+ }
+}
+
+/* Generate a mapping between newly linked IDs and their items, and tag linked IDs used as
+ * liboverride references as already existing. */
+static void new_id_to_item_mapping_create(BlendfileLinkAppendContext *lapp_context)
+{
+ lapp_context->new_id_to_item = BLI_ghash_new(
+ BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp, __func__);
+ for (LinkNode *itemlink = lapp_context->items.list; itemlink; itemlink = itemlink->next) {
+ BlendfileLinkAppendContextItem *item = itemlink->link;
+ ID *id = item->new_id;
+ if (id == NULL) {
+ continue;
+ }
+
+ new_id_to_item_mapping_add(lapp_context, id, item);
+ }
+}
+
+static int foreach_libblock_link_append_callback(LibraryIDLinkCallbackData *cb_data)
+{
+ /* NOTE: It is important to also skip liboverride references here, as those should never be made
+ * local. */
+ if (cb_data->cb_flag & (IDWALK_CB_EMBEDDED | IDWALK_CB_INTERNAL | IDWALK_CB_LOOPBACK |
+ IDWALK_CB_OVERRIDE_LIBRARY_REFERENCE)) {
+ return IDWALK_RET_NOP;
+ }
+
+ BlendfileLinkAppendContextCallBack *data = cb_data->user_data;
+ ID *id = *cb_data->id_pointer;
+
+ if (id == NULL) {
+ return IDWALK_RET_NOP;
+ }
+
+ if (!BKE_idtype_idcode_is_linkable(GS(id->name))) {
+ /* While we do not want to add non-linkable ID (shape keys...) to the list of linked items,
+ * unfortunately they can use fully linkable valid IDs too, like actions. Those need to be
+ * processed, so we need to recursively deal with them here. */
+ /* NOTE: Since we are by-passing checks in `BKE_library_foreach_ID_link` by manually calling it
+ * recursively, we need to take care of potential recursion cases ourselves (e.g.animdata of
+ * shapekey referencing the shapekey itself). */
+ if (id != cb_data->id_self) {
+ BKE_library_foreach_ID_link(
+ cb_data->bmain, id, foreach_libblock_link_append_callback, data, IDWALK_NOP);
+ }
+ return IDWALK_RET_NOP;
+ }
+
+ /* In linking case, we always consider all linked IDs, even indirectly ones, for instantiation,
+ * so we need to add them all to the items list.
+ *
+ * In appending case, when `do_recursive` is false, we only make local IDs from same
+ * library(-ies) as the initially directly linked ones.
+ *
+ * NOTE: Since in append case, linked IDs are also fully skipped during instantiation step (see
+ * #append_loose_data_instantiate_process_check), we can avoid adding them to the items list
+ * completely. */
+ const bool do_link = (data->lapp_context->params->flag & FILE_LINK) != 0;
+ const bool do_recursive = (data->lapp_context->params->flag & BLO_LIBLINK_APPEND_RECURSIVE) !=
+ 0 ||
+ do_link;
+ if (!do_recursive && cb_data->id_owner->lib != id->lib) {
+ return IDWALK_RET_NOP;
+ }
+
+ BlendfileLinkAppendContextItem *item = BLI_ghash_lookup(data->lapp_context->new_id_to_item, id);
+ if (item == NULL) {
+ item = BKE_blendfile_link_append_context_item_add(
+ data->lapp_context, id->name, GS(id->name), NULL);
+ item->new_id = id;
+ item->source_library = id->lib;
+ /* Since we did not have an item for that ID yet, we know user did not selected it explicitly,
+ * it was rather linked indirectly. This info is important for instantiation of collections. */
+ item->tag |= LINK_APPEND_TAG_INDIRECT;
+ /* In linking case we already know what we want to do with those items. */
+ if (do_link) {
+ item->action = LINK_APPEND_ACT_KEEP_LINKED;
+ }
+ new_id_to_item_mapping_add(data->lapp_context, id, item);
+ }
+
+ /* NOTE: currently there is no need to do anything else here, but in the future this would be
+ * the place to add specific per-usage decisions on how to append an ID. */
+
+ return IDWALK_RET_NOP;
+}
+
+/** \} */
+
+/** \name Library link/append code.
+ * \{ */
+
+/* Perform append operation, using modern ID usage looper to detect which ID should be kept linked,
+ * made local, duplicated as local, re-used from local etc.
+ *
+ * TODO: Expose somehow this logic to the two other parts of code performing actual append
+ * (i.e. copy/paste and `bpy` link/append API).
+ * Then we can heavily simplify #BKE_library_make_local(). */
+void BKE_blendfile_append(BlendfileLinkAppendContext *lapp_context, ReportList *reports)
+{
+ Main *bmain = lapp_context->params->bmain;
+
+ BLI_assert((lapp_context->params->flag & FILE_LINK) == 0);
+
+ const bool set_fakeuser = (lapp_context->params->flag & BLO_LIBLINK_APPEND_SET_FAKEUSER) != 0;
+ const bool do_reuse_local_id = (lapp_context->params->flag &
+ BLO_LIBLINK_APPEND_LOCAL_ID_REUSE) != 0;
+
+ const int make_local_common_flags = LIB_ID_MAKELOCAL_FULL_LIBRARY |
+ ((lapp_context->params->flag &
+ BLO_LIBLINK_APPEND_ASSET_DATA_CLEAR) != 0 ?
+ LIB_ID_MAKELOCAL_ASSET_DATA_CLEAR :
+ 0);
+
+ LinkNode *itemlink;
+
+ new_id_to_item_mapping_create(lapp_context);
+ lapp_context->library_weak_reference_mapping = BKE_main_library_weak_reference_create(bmain);
+
+ /* NOTE: Since we append items for IDs not already listed (i.e. implicitly linked indirect
+ * dependencies), this list will grow and we will process those IDs later, leading to a flatten
+ * recursive processing of all the linked dependencies. */
+ for (itemlink = lapp_context->items.list; itemlink; itemlink = itemlink->next) {
+ BlendfileLinkAppendContextItem *item = itemlink->link;
+ ID *id = item->new_id;
+ if (id == NULL) {
+ continue;
+ }
+ BLI_assert(item->userdata == NULL);
+
+ /* Linked IDs should never be marked as needing post-processing (instantiation of loose
+ * objects etc.).
+ * NOTE: This is dev test check, can be removed once we get rid of instantiation code in BLO
+ * completely.*/
+ BLI_assert((id->tag & LIB_TAG_DOIT) == 0);
+
+ ID *existing_local_id = BKE_idtype_idcode_append_is_reusable(GS(id->name)) ?
+ BKE_main_library_weak_reference_search_item(
+ lapp_context->library_weak_reference_mapping,
+ id->lib->filepath,
+ id->name) :
+ NULL;
+
+ if (item->action != LINK_APPEND_ACT_UNSET) {
+ /* Already set, pass. */
+ }
+ if (GS(id->name) == ID_OB && ((Object *)id)->proxy_from != NULL) {
+ CLOG_INFO(&LOG, 3, "Appended ID '%s' is proxified, keeping it linked...", id->name);
+ item->action = LINK_APPEND_ACT_KEEP_LINKED;
+ }
+ else if (do_reuse_local_id && existing_local_id != NULL) {
+ CLOG_INFO(&LOG, 3, "Appended ID '%s' as a matching local one, re-using it...", id->name);
+ item->action = LINK_APPEND_ACT_REUSE_LOCAL;
+ item->userdata = existing_local_id;
+ }
+ else if (id->tag & LIB_TAG_PRE_EXISTING) {
+ CLOG_INFO(&LOG, 3, "Appended ID '%s' was already linked, need to copy it...", id->name);
+ item->action = LINK_APPEND_ACT_COPY_LOCAL;
+ }
+ else {
+ CLOG_INFO(&LOG, 3, "Appended ID '%s' will be made local...", id->name);
+ item->action = LINK_APPEND_ACT_MAKE_LOCAL;
+ }
+
+ /* Only check dependencies if we are not keeping linked data, nor re-using existing local data.
+ */
+ if (!ELEM(item->action, LINK_APPEND_ACT_KEEP_LINKED, LINK_APPEND_ACT_REUSE_LOCAL)) {
+ BlendfileLinkAppendContextCallBack cb_data = {
+ .lapp_context = lapp_context, .item = item, .reports = reports};
+ BKE_library_foreach_ID_link(
+ bmain, id, foreach_libblock_link_append_callback, &cb_data, IDWALK_NOP);
+ }
+
+ /* If we found a matching existing local id but are not re-using it, we need to properly clear
+ * its weak reference to linked data. */
+ if (existing_local_id != NULL &&
+ !ELEM(item->action, LINK_APPEND_ACT_KEEP_LINKED, LINK_APPEND_ACT_REUSE_LOCAL)) {
+ BKE_main_library_weak_reference_remove_item(lapp_context->library_weak_reference_mapping,
+ id->lib->filepath,
+ id->name,
+ existing_local_id);
+ }
+ }
+
+ /* Effectively perform required operation on every linked ID. */
+ for (itemlink = lapp_context->items.list; itemlink; itemlink = itemlink->next) {
+ BlendfileLinkAppendContextItem *item = itemlink->link;
+ ID *id = item->new_id;
+ if (id == NULL) {
+ continue;
+ }
+
+ ID *local_appended_new_id = NULL;
+ char lib_filepath[FILE_MAX];
+ BLI_strncpy(lib_filepath, id->lib->filepath, sizeof(lib_filepath));
+ char lib_id_name[MAX_ID_NAME];
+ BLI_strncpy(lib_id_name, id->name, sizeof(lib_id_name));
+
+ switch (item->action) {
+ case LINK_APPEND_ACT_COPY_LOCAL:
+ BKE_lib_id_make_local(bmain, id, make_local_common_flags | LIB_ID_MAKELOCAL_FORCE_COPY);
+ local_appended_new_id = id->newid;
+ break;
+ case LINK_APPEND_ACT_MAKE_LOCAL:
+ BKE_lib_id_make_local(bmain,
+ id,
+ make_local_common_flags | LIB_ID_MAKELOCAL_FORCE_LOCAL |
+ LIB_ID_MAKELOCAL_OBJECT_NO_PROXY_CLEARING);
+ BLI_assert(id->newid == NULL);
+ local_appended_new_id = id;
+ break;
+ case LINK_APPEND_ACT_KEEP_LINKED:
+ /* Nothing to do here. */
+ break;
+ case LINK_APPEND_ACT_REUSE_LOCAL:
+ /* We only need to set `newid` to ID found in previous loop, for proper remapping. */
+ ID_NEW_SET(id, item->userdata);
+ /* This is not a 'new' local appended id, do not set `local_appended_new_id` here. */
+ break;
+ case LINK_APPEND_ACT_UNSET:
+ CLOG_ERROR(
+ &LOG, "Unexpected unset append action for '%s' ID, assuming 'keep link'", id->name);
+ break;
+ default:
+ BLI_assert(0);
+ }
+
+ if (local_appended_new_id != NULL) {
+ if (BKE_idtype_idcode_append_is_reusable(GS(local_appended_new_id->name))) {
+ BKE_main_library_weak_reference_add_item(lapp_context->library_weak_reference_mapping,
+ lib_filepath,
+ lib_id_name,
+ local_appended_new_id);
+ }
+
+ if (set_fakeuser) {
+ if (!ELEM(GS(local_appended_new_id->name), ID_OB, ID_GR)) {
+ /* Do not set fake user on objects nor collections (instancing). */
+ id_fake_user_set(local_appended_new_id);
+ }
+ }
+ }
+ }
+
+ BKE_main_library_weak_reference_destroy(lapp_context->library_weak_reference_mapping);
+ lapp_context->library_weak_reference_mapping = NULL;
+
+ /* Remap IDs as needed. */
+ for (itemlink = lapp_context->items.list; itemlink; itemlink = itemlink->next) {
+ BlendfileLinkAppendContextItem *item = itemlink->link;
+
+ if (item->action == LINK_APPEND_ACT_KEEP_LINKED) {
+ continue;
+ }
+
+ ID *id = item->new_id;
+ if (id == NULL) {
+ continue;
+ }
+ if (ELEM(item->action, LINK_APPEND_ACT_COPY_LOCAL, LINK_APPEND_ACT_REUSE_LOCAL)) {
+ BLI_assert(ID_IS_LINKED(id));
+ id = id->newid;
+ if (id == NULL) {
+ continue;
+ }
+ }
+
+ BLI_assert(!ID_IS_LINKED(id));
+
+ BKE_libblock_relink_to_newid(bmain, id, 0);
+ }
+
+ /* Remove linked IDs when a local existing data has been reused instead. */
+ BKE_main_id_tag_all(bmain, LIB_TAG_DOIT, false);
+ for (itemlink = lapp_context->items.list; itemlink; itemlink = itemlink->next) {
+ BlendfileLinkAppendContextItem *item = itemlink->link;
+
+ if (item->action != LINK_APPEND_ACT_REUSE_LOCAL) {
+ continue;
+ }
+
+ ID *id = item->new_id;
+ if (id == NULL) {
+ continue;
+ }
+ BLI_assert(ID_IS_LINKED(id));
+ BLI_assert(id->newid != NULL);
+
+ id->tag |= LIB_TAG_DOIT;
+ item->new_id = id->newid;
+ }
+ BKE_id_multi_tagged_delete(bmain);
+
+ /* Instantiate newly created (duplicated) IDs as needed. */
+ LooseDataInstantiateContext instantiate_context = {.lapp_context = lapp_context,
+ .active_collection = NULL};
+ loose_data_instantiate(&instantiate_context);
+
+ /* Attempt to deal with object proxies.
+ *
+ * NOTE: Copied from `BKE_library_make_local`, but this is not really working (as in, not
+ * producing any useful result in any known use case), neither here nor in
+ * `BKE_library_make_local` currently.
+ * Proxies are end of life anyway, so not worth spending time on this. */
+ for (itemlink = lapp_context->items.list; itemlink; itemlink = itemlink->next) {
+ BlendfileLinkAppendContextItem *item = itemlink->link;
+
+ if (item->action != LINK_APPEND_ACT_COPY_LOCAL) {
+ continue;
+ }
+
+ ID *id = item->new_id;
+ if (id == NULL) {
+ continue;
+ }
+ BLI_assert(ID_IS_LINKED(id));
+
+ /* Attempt to re-link copied proxy objects. This allows appending of an entire scene
+ * from another blend file into this one, even when that blend file contains proxified
+ * armatures that have local references. Since the proxified object needs to be linked
+ * (not local), this will only work when the "Localize all" checkbox is disabled.
+ * TL;DR: this is a dirty hack on top of an already weak feature (proxies). */
+ if (GS(id->name) == ID_OB && ((Object *)id)->proxy != NULL) {
+ Object *ob = (Object *)id;
+ Object *ob_new = (Object *)id->newid;
+ bool is_local = false, is_lib = false;
+
+ /* Proxies only work when the proxified object is linked-in from a library. */
+ if (!ID_IS_LINKED(ob->proxy)) {
+ CLOG_WARN(&LOG,
+ "Proxy object %s will lose its link to %s, because the "
+ "proxified object is local",
+ id->newid->name,
+ ob->proxy->id.name);
+ continue;
+ }
+
+ BKE_library_ID_test_usages(bmain, id, &is_local, &is_lib);
+
+ /* We can only switch the proxy'ing to a made-local proxy if it is no longer
+ * referred to from a library. Not checking for local use; if new local proxy
+ * was not used locally would be a nasty bug! */
+ if (is_local || is_lib) {
+ CLOG_WARN(&LOG,
+ "Made-local proxy object %s will lose its link to %s, "
+ "because the linked-in proxy is referenced (is_local=%i, is_lib=%i)",
+ id->newid->name,
+ ob->proxy->id.name,
+ is_local,
+ is_lib);
+ }
+ else {
+ /* we can switch the proxy'ing from the linked-in to the made-local proxy.
+ * BKE_object_make_proxy() shouldn't be used here, as it allocates memory that
+ * was already allocated by object_make_local() (which called BKE_object_copy). */
+ ob_new->proxy = ob->proxy;
+ ob_new->proxy_group = ob->proxy_group;
+ ob_new->proxy_from = ob->proxy_from;
+ ob_new->proxy->proxy_from = ob_new;
+ ob->proxy = ob->proxy_from = ob->proxy_group = NULL;
+ }
+ }
+ }
+
+ BKE_main_id_newptr_and_tag_clear(bmain);
+}
+
+void BKE_blendfile_link(BlendfileLinkAppendContext *lapp_context, ReportList *reports)
+{
+ Main *mainl;
+ Library *lib;
+
+ LinkNode *liblink, *itemlink;
+ int lib_idx, item_idx;
+
+ BLI_assert(lapp_context->num_items && lapp_context->num_libraries);
+
+ for (lib_idx = 0, liblink = lapp_context->libraries.list; liblink;
+ lib_idx++, liblink = liblink->next) {
+ BlendfileLinkAppendContextLibrary *lib_context = liblink->link;
+ char *libname = lib_context->path;
+ BlendHandle *blo_handle = link_append_context_library_blohandle_ensure(
+ lapp_context, lib_context, reports);
+
+ if (blo_handle == NULL) {
+ /* Unlikely since we just browsed it, but possible
+ * Error reports will have been made by BLO_blendhandle_from_file() */
+ continue;
+ }
+
+ /* here appending/linking starts */
+
+ /* NOTE: This is temporary hotfix until whole code using link/append features has been moved to
+ * use new BKE code. */
+ /* Do not handle instantiation in linking process anymore, we do it here in
+ * #loose_data_instantiate instead. */
+ lapp_context->params->flag &= ~BLO_LIBLINK_NEEDS_ID_TAG_DOIT;
+
+ mainl = BLO_library_link_begin(&blo_handle, libname, lapp_context->params);
+ lib = mainl->curlib;
+ BLI_assert(lib);
+ UNUSED_VARS_NDEBUG(lib);
+
+ if (mainl->versionfile < 250) {
+ BKE_reportf(reports,
+ RPT_WARNING,
+ "Linking or appending from a very old .blend file format (%d.%d), no animation "
+ "conversion will "
+ "be done! You may want to re-save your lib file with current Blender",
+ mainl->versionfile,
+ mainl->subversionfile);
+ }
+
+ /* For each lib file, we try to link all items belonging to that lib,
+ * and tag those successful to not try to load them again with the other libs. */
+ for (item_idx = 0, itemlink = lapp_context->items.list; itemlink;
+ item_idx++, itemlink = itemlink->next) {
+ BlendfileLinkAppendContextItem *item = itemlink->link;
+ ID *new_id;
+
+ if (!BLI_BITMAP_TEST(item->libraries, lib_idx)) {
+ continue;
+ }
+
+ new_id = BLO_library_link_named_part(
+ mainl, &blo_handle, item->idcode, item->name, lapp_context->params);
+
+ if (new_id) {
+ /* If the link is successful, clear item's libs 'todo' flags.
+ * This avoids trying to link same item with other libraries to come. */
+ BLI_bitmap_set_all(item->libraries, false, lapp_context->num_libraries);
+ item->new_id = new_id;
+ item->source_library = new_id->lib;
+ }
+ }
+
+ BLO_library_link_end(mainl, &blo_handle, lapp_context->params);
+ link_append_context_library_blohandle_release(lapp_context, lib_context);
+ }
+
+ /* Instantiate newly linked IDs as needed, if no append is scheduled. */
+ if ((lapp_context->params->flag & FILE_LINK) != 0 &&
+ lapp_context->params->context.scene != NULL) {
+ new_id_to_item_mapping_create(lapp_context);
+ /* NOTE: Since we append items for IDs not already listed (i.e. implicitly linked indirect
+ * dependencies), this list will grow and we will process those IDs later, leading to a flatten
+ * recursive processing of all the linked dependencies. */
+ for (itemlink = lapp_context->items.list; itemlink; itemlink = itemlink->next) {
+ BlendfileLinkAppendContextItem *item = itemlink->link;
+ ID *id = item->new_id;
+ if (id == NULL) {
+ continue;
+ }
+ BLI_assert(item->userdata == NULL);
+
+ /* Linked IDs should never be marked as needing post-processing (instantiation of loose
+ * objects etc.).
+ * NOTE: This is dev test check, can be removed once we get rid of instantiation code in BLO
+ * completely.*/
+ BLI_assert((id->tag & LIB_TAG_DOIT) == 0);
+
+ BlendfileLinkAppendContextCallBack cb_data = {
+ .lapp_context = lapp_context, .item = item, .reports = reports};
+ BKE_library_foreach_ID_link(lapp_context->params->bmain,
+ id,
+ foreach_libblock_link_append_callback,
+ &cb_data,
+ IDWALK_NOP);
+ }
+
+ LooseDataInstantiateContext instantiate_context = {.lapp_context = lapp_context,
+ .active_collection = NULL};
+ loose_data_instantiate(&instantiate_context);
+ }
+}
+
+/** \} */
+
+/** \name Library relocating code.
+ * \{ */
+
+static void blendfile_library_relocate_remap(Main *bmain,
+ ID *old_id,
+ ID *new_id,
+ ReportList *reports,
+ const bool do_reload,
+ const short remap_flags)
+{
+ BLI_assert(old_id);
+ if (do_reload) {
+ /* Since we asked for placeholders in case of missing IDs,
+ * we expect to always get a valid one. */
+ BLI_assert(new_id);
+ }
+ if (new_id) {
+ CLOG_INFO(&LOG,
+ 4,
+ "Before remap of %s, old_id users: %d, new_id users: %d",
+ old_id->name,
+ old_id->us,
+ new_id->us);
+ BKE_libblock_remap_locked(bmain, old_id, new_id, remap_flags);
+
+ if (old_id->flag & LIB_FAKEUSER) {
+ id_fake_user_clear(old_id);
+ id_fake_user_set(new_id);
+ }
+
+ CLOG_INFO(&LOG,
+ 4,
+ "After remap of %s, old_id users: %d, new_id users: %d",
+ old_id->name,
+ old_id->us,
+ new_id->us);
+
+ /* In some cases, new_id might become direct link, remove parent of library in this case. */
+ if (new_id->lib->parent && (new_id->tag & LIB_TAG_INDIRECT) == 0) {
+ if (do_reload) {
+ BLI_assert_unreachable(); /* Should not happen in 'pure' reload case... */
+ }
+ new_id->lib->parent = NULL;
+ }
+ }
+
+ if (old_id->us > 0 && new_id && old_id->lib == new_id->lib) {
+ /* Note that this *should* not happen - but better be safe than sorry in this area,
+ * at least until we are 100% sure this cannot ever happen.
+ * Also, we can safely assume names were unique so far,
+ * so just replacing '.' by '~' should work,
+ * but this does not totally rules out the possibility of name collision. */
+ size_t len = strlen(old_id->name);
+ size_t dot_pos;
+ bool has_num = false;
+
+ for (dot_pos = len; dot_pos--;) {
+ char c = old_id->name[dot_pos];
+ if (c == '.') {
+ break;
+ }
+ if (c < '0' || c > '9') {
+ has_num = false;
+ break;
+ }
+ has_num = true;
+ }
+
+ if (has_num) {
+ old_id->name[dot_pos] = '~';
+ }
+ else {
+ len = MIN2(len, MAX_ID_NAME - 7);
+ BLI_strncpy(&old_id->name[len], "~000", 7);
+ }
+
+ id_sort_by_name(which_libbase(bmain, GS(old_id->name)), old_id, NULL);
+
+ BKE_reportf(
+ reports,
+ RPT_WARNING,
+ "Lib Reload: Replacing all references to old data-block '%s' by reloaded one failed, "
+ "old one (%d remaining users) had to be kept and was renamed to '%s'",
+ new_id->name,
+ old_id->us,
+ old_id->name);
+ }
+}
+
+void BKE_blendfile_library_relocate(BlendfileLinkAppendContext *lapp_context,
+ ReportList *reports,
+ Library *library,
+ const bool do_reload)
+{
+ ListBase *lbarray[INDEX_ID_MAX];
+ int lba_idx;
+
+ LinkNode *itemlink;
+ int item_idx;
+
+ Main *bmain = lapp_context->params->bmain;
+
+ /* Remove all IDs to be reloaded from Main. */
+ lba_idx = set_listbasepointers(bmain, lbarray);
+ while (lba_idx--) {
+ ID *id = lbarray[lba_idx]->first;
+ const short idcode = id ? GS(id->name) : 0;
+
+ if (!id || !BKE_idtype_idcode_is_linkable(idcode)) {
+ /* No need to reload non-linkable datatypes,
+ * those will get relinked with their 'users ID'. */
+ continue;
+ }
+
+ for (; id; id = id->next) {
+ if (id->lib == library) {
+ BlendfileLinkAppendContextItem *item;
+
+ /* We remove it from current Main, and add it to items to link... */
+ /* Note that non-linkable IDs (like e.g. shapekeys) are also explicitly linked here... */
+ BLI_remlink(lbarray[lba_idx], id);
+ /* Usual special code for ShapeKeys snowflakes... */
+ Key *old_key = BKE_key_from_id(id);
+ if (old_key != NULL) {
+ BLI_remlink(which_libbase(bmain, GS(old_key->id.name)), &old_key->id);
+ }
+
+ item = BKE_blendfile_link_append_context_item_add(lapp_context, id->name + 2, idcode, id);
+ BLI_bitmap_set_all(item->libraries, true, (size_t)lapp_context->num_libraries);
+
+ CLOG_INFO(&LOG, 4, "Datablock to seek for: %s", id->name);
+ }
+ }
+ }
+
+ if (lapp_context->num_items == 0) {
+ /* Early out in case there is nothing to do. */
+ return;
+ }
+
+ BKE_main_id_tag_all(bmain, LIB_TAG_PRE_EXISTING, true);
+
+ /* We do not want any instantiation here! */
+ BKE_blendfile_link(lapp_context, reports);
+
+ BKE_main_lock(bmain);
+
+ /* We add back old id to bmain.
+ * We need to do this in a first, separated loop, otherwise some of those may not be handled by
+ * ID remapping, which means they would still reference old data to be deleted... */
+ for (item_idx = 0, itemlink = lapp_context->items.list; itemlink;
+ item_idx++, itemlink = itemlink->next) {
+ BlendfileLinkAppendContextItem *item = itemlink->link;
+ ID *old_id = item->userdata;
+
+ BLI_assert(old_id);
+ BLI_addtail(which_libbase(bmain, GS(old_id->name)), old_id);
+
+ /* Usual special code for ShapeKeys snowflakes... */
+ Key *old_key = BKE_key_from_id(old_id);
+ if (old_key != NULL) {
+ BLI_addtail(which_libbase(bmain, GS(old_key->id.name)), &old_key->id);
+ }
+ }
+
+ /* Since our (old) reloaded IDs were removed from main, the user count done for them in linking
+ * code is wrong, we need to redo it here after adding them back to main. */
+ BKE_main_id_refcount_recompute(bmain, false);
+
+ /* Note that in reload case, we also want to replace indirect usages. */
+ const short remap_flags = ID_REMAP_SKIP_NEVER_NULL_USAGE |
+ ID_REMAP_NO_INDIRECT_PROXY_DATA_USAGE |
+ (do_reload ? 0 : ID_REMAP_SKIP_INDIRECT_USAGE);
+ for (item_idx = 0, itemlink = lapp_context->items.list; itemlink;
+ item_idx++, itemlink = itemlink->next) {
+ BlendfileLinkAppendContextItem *item = itemlink->link;
+ ID *old_id = item->userdata;
+ ID *new_id = item->new_id;
+
+ blendfile_library_relocate_remap(bmain, old_id, new_id, reports, do_reload, remap_flags);
+ if (new_id == NULL) {
+ continue;
+ }
+ /* Usual special code for ShapeKeys snowflakes... */
+ Key **old_key_p = BKE_key_from_id_p(old_id);
+ if (old_key_p == NULL) {
+ continue;
+ }
+ Key *old_key = *old_key_p;
+ Key *new_key = BKE_key_from_id(new_id);
+ if (old_key != NULL) {
+ *old_key_p = NULL;
+ id_us_min(&old_key->id);
+ blendfile_library_relocate_remap(
+ bmain, &old_key->id, &new_key->id, reports, do_reload, remap_flags);
+ *old_key_p = old_key;
+ id_us_plus_no_lib(&old_key->id);
+ }
+ }
+
+ BKE_main_unlock(bmain);
+
+ for (item_idx = 0, itemlink = lapp_context->items.list; itemlink;
+ item_idx++, itemlink = itemlink->next) {
+ BlendfileLinkAppendContextItem *item = itemlink->link;
+ ID *old_id = item->userdata;
+
+ if (old_id->us == 0) {
+ BKE_id_free(bmain, old_id);
+ }
+ }
+
+ /* Some datablocks can get reloaded/replaced 'silently' because they are not linkable
+ * (shape keys e.g.), so we need another loop here to clear old ones if possible. */
+ lba_idx = set_listbasepointers(bmain, lbarray);
+ while (lba_idx--) {
+ ID *id, *id_next;
+ for (id = lbarray[lba_idx]->first; id; id = id_next) {
+ id_next = id->next;
+ /* XXX That check may be a bit to generic/permissive? */
+ if (id->lib && (id->flag & LIB_TAG_PRE_EXISTING) && id->us == 0) {
+ BKE_id_free(bmain, id);
+ }
+ }
+ }
+
+ /* Get rid of no more used libraries... */
+ BKE_main_id_tag_idcode(bmain, ID_LI, LIB_TAG_DOIT, true);
+ lba_idx = set_listbasepointers(bmain, lbarray);
+ while (lba_idx--) {
+ ID *id;
+ for (id = lbarray[lba_idx]->first; id; id = id->next) {
+ if (id->lib) {
+ id->lib->id.tag &= ~LIB_TAG_DOIT;
+ }
+ }
+ }
+ Library *lib, *lib_next;
+ for (lib = which_libbase(bmain, ID_LI)->first; lib; lib = lib_next) {
+ lib_next = lib->id.next;
+ if (lib->id.tag & LIB_TAG_DOIT) {
+ id_us_clear_real(&lib->id);
+ if (lib->id.us == 0) {
+ BKE_id_free(bmain, (ID *)lib);
+ }
+ }
+ }
+
+ /* Update overrides of reloaded linked data-blocks. */
+ ID *id;
+ FOREACH_MAIN_ID_BEGIN (bmain, id) {
+ if (ID_IS_LINKED(id) || !ID_IS_OVERRIDE_LIBRARY_REAL(id) ||
+ (id->tag & LIB_TAG_PRE_EXISTING) == 0) {
+ continue;
+ }
+ if ((id->override_library->reference->tag & LIB_TAG_PRE_EXISTING) == 0) {
+ BKE_lib_override_library_update(bmain, id);
+ }
+ }
+ FOREACH_MAIN_ID_END;
+
+ /* Resync overrides if needed. */
+ if (!USER_EXPERIMENTAL_TEST(&U, no_override_auto_resync)) {
+ BKE_lib_override_library_main_resync(bmain,
+ lapp_context->params->context.scene,
+ lapp_context->params->context.view_layer,
+ &(struct BlendFileReadReport){
+ .reports = reports,
+ });
+ /* We need to rebuild some of the deleted override rules (for UI feedback purpose). */
+ BKE_lib_override_library_main_operations_create(bmain, true);
+ }
+
+ BKE_main_collection_sync(bmain);
+}
+
+/** \} */
diff --git a/source/blender/blenkernel/intern/brush.c b/source/blender/blenkernel/intern/brush.c
index 7d217d6907d..a682489b7cd 100644
--- a/source/blender/blenkernel/intern/brush.c
+++ b/source/blender/blenkernel/intern/brush.c
@@ -213,8 +213,9 @@ static void brush_foreach_id(ID *id, LibraryForeachIDData *data)
if (brush->gpencil_settings) {
BKE_LIB_FOREACHID_PROCESS_IDSUPER(data, brush->gpencil_settings->material, IDWALK_CB_USER);
}
- BKE_texture_mtex_foreach_id(data, &brush->mtex);
- BKE_texture_mtex_foreach_id(data, &brush->mask_mtex);
+ BKE_LIB_FOREACHID_PROCESS_FUNCTION_CALL(data, BKE_texture_mtex_foreach_id(data, &brush->mtex));
+ BKE_LIB_FOREACHID_PROCESS_FUNCTION_CALL(data,
+ BKE_texture_mtex_foreach_id(data, &brush->mask_mtex));
}
static void brush_blend_write(BlendWriter *writer, ID *id, const void *id_address)
@@ -2474,7 +2475,7 @@ float BKE_brush_curve_strength(const Brush *br, float p, const float len)
}
/* Uses the brush curve control to find a strength value between 0 and 1 */
-float BKE_brush_curve_strength_clamped(Brush *br, float p, const float len)
+float BKE_brush_curve_strength_clamped(const Brush *br, float p, const float len)
{
float strength = BKE_brush_curve_strength(br, p, len);
diff --git a/source/blender/blenkernel/intern/collection.c b/source/blender/blenkernel/intern/collection.c
index 2dca5dcb75d..22b939d3cf9 100644
--- a/source/blender/blenkernel/intern/collection.c
+++ b/source/blender/blenkernel/intern/collection.c
@@ -716,7 +716,7 @@ Collection *BKE_collection_duplicate(Main *bmain,
collection_new->id.tag &= ~LIB_TAG_NEW;
/* This code will follow into all ID links using an ID tagged with LIB_TAG_NEW. */
- BKE_libblock_relink_to_newid(&collection_new->id);
+ BKE_libblock_relink_to_newid(bmain, &collection_new->id, 0);
#ifndef NDEBUG
/* Call to `BKE_libblock_relink_to_newid` above is supposed to have cleared all those flags. */
diff --git a/source/blender/blenkernel/intern/constraint.c b/source/blender/blenkernel/intern/constraint.c
index 7ddbaa0e9ee..3455baa9292 100644
--- a/source/blender/blenkernel/intern/constraint.c
+++ b/source/blender/blenkernel/intern/constraint.c
@@ -2010,7 +2010,7 @@ static void rotlike_evaluate(bConstraint *con, bConstraintOb *cob, ListBase *tar
/* We must get compatible eulers from the beginning because
* some of them can be modified below (see bug T21875).
* Additionally, since this constraint is based on euler rotation math, it doesn't work well
- * with shear. The Y axis is chosen as the main axis when we orthoganalize the matrix because
+ * with shear. The Y axis is chosen as the main axis when we orthogonalize the matrix because
* constraints are used most commonly on bones. */
float mat[4][4];
copy_m4_m4(mat, ct->matrix);
diff --git a/source/blender/blenkernel/intern/curve_eval.cc b/source/blender/blenkernel/intern/curve_eval.cc
index ff0478f2543..163f8b02b85 100644
--- a/source/blender/blenkernel/intern/curve_eval.cc
+++ b/source/blender/blenkernel/intern/curve_eval.cc
@@ -109,6 +109,24 @@ void CurveEval::bounds_min_max(float3 &min, float3 &max, const bool use_evaluate
}
}
+float CurveEval::total_length() const
+{
+ float length = 0.0f;
+ for (const SplinePtr &spline : this->splines()) {
+ length += spline->length();
+ }
+ return length;
+}
+
+int CurveEval::total_control_point_size() const
+{
+ int count = 0;
+ for (const SplinePtr &spline : this->splines()) {
+ count += spline->size();
+ }
+ return count;
+}
+
/**
* Return the start indices for each of the curve spline's control points, if they were part
* of a flattened array. This can be used to facilitate parallelism by avoiding the need to
diff --git a/source/blender/blenkernel/intern/curve_to_mesh_convert.cc b/source/blender/blenkernel/intern/curve_to_mesh_convert.cc
index 1ef205c6903..03525e32a52 100644
--- a/source/blender/blenkernel/intern/curve_to_mesh_convert.cc
+++ b/source/blender/blenkernel/intern/curve_to_mesh_convert.cc
@@ -32,8 +32,6 @@
using blender::fn::GMutableSpan;
using blender::fn::GSpan;
-using blender::fn::GVArray_Typed;
-using blender::fn::GVArrayPtr;
namespace blender::bke {
@@ -76,7 +74,7 @@ static void vert_extrude_to_mesh_data(const Spline &spline,
Span<float3> positions = spline.evaluated_positions();
Span<float3> tangents = spline.evaluated_tangents();
Span<float3> normals = spline.evaluated_normals();
- GVArray_Typed<float> radii = spline.interpolate_to_evaluated(spline.radii());
+ VArray<float> radii = spline.interpolate_to_evaluated(spline.radii());
for (const int i : IndexRange(eval_size)) {
float4x4 point_matrix = float4x4::from_normalized_axis_data(
positions[i], normals[i], tangents[i]);
@@ -227,7 +225,7 @@ static void spline_extrude_to_mesh_data(const ResultInfo &info,
Span<float3> normals = spline.evaluated_normals();
Span<float3> profile_positions = profile.evaluated_positions();
- GVArray_Typed<float> radii = spline.interpolate_to_evaluated(spline.radii());
+ VArray<float> radii = spline.interpolate_to_evaluated(spline.radii());
for (const int i_ring : IndexRange(info.spline_vert_len)) {
float4x4 point_matrix = float4x4::from_normalized_axis_data(
positions[i_ring], normals[i_ring], tangents[i_ring]);
@@ -495,8 +493,8 @@ static void copy_curve_point_attribute_to_mesh(const GSpan src,
const ResultInfo &info,
ResultAttributeData &dst)
{
- GVArrayPtr interpolated_gvarray = info.spline.interpolate_to_evaluated(src);
- GSpan interpolated = interpolated_gvarray->get_internal_span();
+ GVArray interpolated_gvarray = info.spline.interpolate_to_evaluated(src);
+ GSpan interpolated = interpolated_gvarray.get_internal_span();
attribute_math::convert_to_static_type(src.type(), [&](auto dummy) {
using T = decltype(dummy);
@@ -561,8 +559,8 @@ static void copy_profile_point_attribute_to_mesh(const GSpan src,
const ResultInfo &info,
ResultAttributeData &dst)
{
- GVArrayPtr interpolated_gvarray = info.profile.interpolate_to_evaluated(src);
- GSpan interpolated = interpolated_gvarray->get_internal_span();
+ GVArray interpolated_gvarray = info.profile.interpolate_to_evaluated(src);
+ GSpan interpolated = interpolated_gvarray.get_internal_span();
attribute_math::convert_to_static_type(src.type(), [&](auto dummy) {
using T = decltype(dummy);
diff --git a/source/blender/blenkernel/intern/dynamicpaint.c b/source/blender/blenkernel/intern/dynamicpaint.c
index 2ef7ef91160..05f1e9b286f 100644
--- a/source/blender/blenkernel/intern/dynamicpaint.c
+++ b/source/blender/blenkernel/intern/dynamicpaint.c
@@ -763,7 +763,7 @@ static void surfaceGenerateGrid(struct DynamicPaintSurface *surface)
copy_v3_v3(bData->dim, dim);
min_dim = max_fff(td[0], td[1], td[2]) / 1000.0f;
- /* deactivate zero axises */
+ /* deactivate zero axes */
for (i = 0; i < 3; i++) {
if (td[i] < min_dim) {
td[i] = 1.0f;
@@ -784,7 +784,7 @@ static void surfaceGenerateGrid(struct DynamicPaintSurface *surface)
dim_factor = (float)pow((double)volume / ((double)sData->total_points / 10000.0),
1.0 / (double)axis);
- /* define final grid size using dim_factor, use min 3 for active axises */
+ /* define final grid size using dim_factor, use min 3 for active axes */
for (i = 0; i < 3; i++) {
grid->dim[i] = (int)floor(td[i] / dim_factor);
CLAMP(grid->dim[i], (dim[i] >= min_dim) ? 3 : 1, 100);
diff --git a/source/blender/blenkernel/intern/fcurve.c b/source/blender/blenkernel/intern/fcurve.c
index 1564eb3aa7b..bbf61c51bfb 100644
--- a/source/blender/blenkernel/intern/fcurve.c
+++ b/source/blender/blenkernel/intern/fcurve.c
@@ -205,12 +205,16 @@ void BKE_fcurve_foreach_id(FCurve *fcu, LibraryForeachIDData *data)
FMod_Python *fcm_py = (FMod_Python *)fcm->data;
BKE_LIB_FOREACHID_PROCESS_IDSUPER(data, fcm_py->script, IDWALK_CB_NOP);
- IDP_foreach_property(fcm_py->prop,
- IDP_TYPE_FILTER_ID,
- BKE_lib_query_idpropertiesForeachIDLink_callback,
- data);
+ BKE_LIB_FOREACHID_PROCESS_FUNCTION_CALL(
+ data,
+ IDP_foreach_property(fcm_py->prop,
+ IDP_TYPE_FILTER_ID,
+ BKE_lib_query_idpropertiesForeachIDLink_callback,
+ data));
break;
}
+ default:
+ break;
}
}
}
diff --git a/source/blender/blenkernel/intern/fcurve_driver.c b/source/blender/blenkernel/intern/fcurve_driver.c
index d1bf523acef..3ac64dbf84b 100644
--- a/source/blender/blenkernel/intern/fcurve_driver.c
+++ b/source/blender/blenkernel/intern/fcurve_driver.c
@@ -326,7 +326,7 @@ static float dvar_eval_rotDiff(ChannelDriver *driver, DriverVar *dvar)
float(*mat[2])[4];
- /* NOTE: for now, these are all just worldspace */
+ /* NOTE: for now, these are all just world-space. */
for (int i = 0; i < 2; i++) {
/* Get pointer to loc values to store in. */
DriverTarget *dtar = &dvar->targets[i];
@@ -422,7 +422,7 @@ static float dvar_eval_locDiff(ChannelDriver *driver, DriverVar *dvar)
}
}
else {
- /* Convert to worldspace. */
+ /* Convert to world-space. */
copy_v3_v3(tmp_loc, pchan->pose_head);
mul_m4_v3(ob->obmat, tmp_loc);
}
diff --git a/source/blender/blenkernel/intern/fluid.c b/source/blender/blenkernel/intern/fluid.c
index 6b7594dcf36..9d26a1528f3 100644
--- a/source/blender/blenkernel/intern/fluid.c
+++ b/source/blender/blenkernel/intern/fluid.c
@@ -5090,7 +5090,7 @@ void BKE_fluid_modifier_copy(const struct FluidModifierData *fmd,
copy_v4_v4(tfds->gridlines_range_color, fds->gridlines_range_color);
tfds->gridlines_cell_filter = fds->gridlines_cell_filter;
- /* -- Deprecated / unsed options (below)-- */
+ /* -- Deprecated / unused options (below)-- */
/* pointcache options */
BKE_ptcache_free_list(&(tfds->ptcaches[0]));
diff --git a/source/blender/blenkernel/intern/geometry_component_curve.cc b/source/blender/blenkernel/intern/geometry_component_curve.cc
index 961265f3a16..598c61fd877 100644
--- a/source/blender/blenkernel/intern/geometry_component_curve.cc
+++ b/source/blender/blenkernel/intern/geometry_component_curve.cc
@@ -28,10 +28,8 @@
using blender::fn::GMutableSpan;
using blender::fn::GSpan;
-using blender::fn::GVArray_For_GSpan;
+using blender::fn::GVArray;
using blender::fn::GVArray_GSpan;
-using blender::fn::GVArrayPtr;
-using blender::fn::GVMutableArray_For_GMutableSpan;
/* -------------------------------------------------------------------- */
/** \name Geometry Component Implementation
@@ -253,15 +251,15 @@ void adapt_curve_domain_point_to_spline_impl(const CurveEval &curve,
}
}
-static GVArrayPtr adapt_curve_domain_point_to_spline(const CurveEval &curve, GVArrayPtr varray)
+static GVArray adapt_curve_domain_point_to_spline(const CurveEval &curve, GVArray varray)
{
- GVArrayPtr new_varray;
- attribute_math::convert_to_static_type(varray->type(), [&](auto dummy) {
+ GVArray new_varray;
+ attribute_math::convert_to_static_type(varray.type(), [&](auto dummy) {
using T = decltype(dummy);
if constexpr (!std::is_void_v<attribute_math::DefaultMixer<T>>) {
Array<T> values(curve.splines().size());
- adapt_curve_domain_point_to_spline_impl<T>(curve, varray->typed<T>(), values);
- new_varray = std::make_unique<fn::GVArray_For_ArrayContainer<Array<T>>>(std::move(values));
+ adapt_curve_domain_point_to_spline_impl<T>(curve, varray.typed<T>(), values);
+ new_varray = VArray<T>::ForContainer(std::move(values));
}
});
return new_varray;
@@ -272,29 +270,29 @@ static GVArrayPtr adapt_curve_domain_point_to_spline(const CurveEval &curve, GVA
* attributes. The goal is to avoid copying the spline value for every one of its control points
* unless it is necessary (in that case the materialize functions will be called).
*/
-template<typename T> class VArray_For_SplineToPoint final : public VArray<T> {
- GVArrayPtr original_varray_;
+template<typename T> class VArray_For_SplineToPoint final : public VArrayImpl<T> {
+ GVArray original_varray_;
/* Store existing data materialized if it was not already a span. This is expected
* to be worth it because a single spline's value will likely be accessed many times. */
- fn::GVArray_Span<T> original_data_;
+ VArray_Span<T> original_data_;
Array<int> offsets_;
public:
- VArray_For_SplineToPoint(GVArrayPtr original_varray, Array<int> offsets)
- : VArray<T>(offsets.last()),
+ VArray_For_SplineToPoint(GVArray original_varray, Array<int> offsets)
+ : VArrayImpl<T>(offsets.last()),
original_varray_(std::move(original_varray)),
- original_data_(*original_varray_),
+ original_data_(original_varray_.typed<T>()),
offsets_(std::move(offsets))
{
}
- T get_impl(const int64_t index) const final
+ T get(const int64_t index) const final
{
const PointIndices indices = lookup_point_indices(offsets_, index);
return original_data_[indices.spline_index];
}
- void materialize_impl(const IndexMask mask, MutableSpan<T> r_span) const final
+ void materialize(const IndexMask mask, MutableSpan<T> r_span) const final
{
const int total_size = offsets_.last();
if (mask.is_range() && mask.as_range() == IndexRange(total_size)) {
@@ -315,7 +313,7 @@ template<typename T> class VArray_For_SplineToPoint final : public VArray<T> {
}
}
- void materialize_to_uninitialized_impl(const IndexMask mask, MutableSpan<T> r_span) const final
+ void materialize_to_uninitialized(const IndexMask mask, MutableSpan<T> r_span) const final
{
T *dst = r_span.data();
const int total_size = offsets_.last();
@@ -338,29 +336,29 @@ template<typename T> class VArray_For_SplineToPoint final : public VArray<T> {
}
};
-static GVArrayPtr adapt_curve_domain_spline_to_point(const CurveEval &curve, GVArrayPtr varray)
+static GVArray adapt_curve_domain_spline_to_point(const CurveEval &curve, GVArray varray)
{
- GVArrayPtr new_varray;
- attribute_math::convert_to_static_type(varray->type(), [&](auto dummy) {
+ GVArray new_varray;
+ attribute_math::convert_to_static_type(varray.type(), [&](auto dummy) {
using T = decltype(dummy);
Array<int> offsets = curve.control_point_offsets();
- new_varray = std::make_unique<fn::GVArray_For_EmbeddedVArray<T, VArray_For_SplineToPoint<T>>>(
- offsets.last(), std::move(varray), std::move(offsets));
+ new_varray = VArray<T>::template For<VArray_For_SplineToPoint<T>>(std::move(varray),
+ std::move(offsets));
});
return new_varray;
}
} // namespace blender::bke
-GVArrayPtr CurveComponent::attribute_try_adapt_domain(GVArrayPtr varray,
- const AttributeDomain from_domain,
- const AttributeDomain to_domain) const
+GVArray CurveComponent::attribute_try_adapt_domain_impl(const GVArray &varray,
+ const AttributeDomain from_domain,
+ const AttributeDomain to_domain) const
{
if (!varray) {
return {};
}
- if (varray->size() == 0) {
+ if (varray.is_empty()) {
return {};
}
if (from_domain == to_domain) {
@@ -402,8 +400,8 @@ static const CurveEval *get_curve_from_component_for_read(const GeometryComponen
namespace blender::bke {
class BuiltinSplineAttributeProvider final : public BuiltinAttributeProvider {
- using AsReadAttribute = GVArrayPtr (*)(const CurveEval &data);
- using AsWriteAttribute = GVMutableArrayPtr (*)(CurveEval &data);
+ using AsReadAttribute = GVArray (*)(const CurveEval &data);
+ using AsWriteAttribute = GVMutableArray (*)(CurveEval &data);
const AsReadAttribute as_read_attribute_;
const AsWriteAttribute as_write_attribute_;
@@ -424,7 +422,7 @@ class BuiltinSplineAttributeProvider final : public BuiltinAttributeProvider {
{
}
- GVArrayPtr try_get_for_read(const GeometryComponent &component) const final
+ GVArray try_get_for_read(const GeometryComponent &component) const final
{
const CurveEval *curve = get_curve_from_component_for_read(component);
if (curve == nullptr) {
@@ -483,19 +481,15 @@ static void set_spline_resolution(SplinePtr &spline, const int resolution)
}
}
-static GVArrayPtr make_resolution_read_attribute(const CurveEval &curve)
+static GVArray make_resolution_read_attribute(const CurveEval &curve)
{
- return std::make_unique<fn::GVArray_For_DerivedSpan<SplinePtr, int, get_spline_resolution>>(
- curve.splines());
+ return VArray<int>::ForDerivedSpan<SplinePtr, get_spline_resolution>(curve.splines());
}
-static GVMutableArrayPtr make_resolution_write_attribute(CurveEval &curve)
+static GVMutableArray make_resolution_write_attribute(CurveEval &curve)
{
- return std::make_unique<fn::GVMutableArray_For_DerivedSpan<SplinePtr,
- int,
- get_spline_resolution,
- set_spline_resolution>>(
- curve.splines());
+ return VMutableArray<int>::
+ ForDerivedSpan<SplinePtr, get_spline_resolution, set_spline_resolution>(curve.splines());
}
static bool get_cyclic_value(const SplinePtr &spline)
@@ -511,16 +505,14 @@ static void set_cyclic_value(SplinePtr &spline, const bool value)
}
}
-static GVArrayPtr make_cyclic_read_attribute(const CurveEval &curve)
+static GVArray make_cyclic_read_attribute(const CurveEval &curve)
{
- return std::make_unique<fn::GVArray_For_DerivedSpan<SplinePtr, bool, get_cyclic_value>>(
- curve.splines());
+ return VArray<bool>::ForDerivedSpan<SplinePtr, get_cyclic_value>(curve.splines());
}
-static GVMutableArrayPtr make_cyclic_write_attribute(CurveEval &curve)
+static GVMutableArray make_cyclic_write_attribute(CurveEval &curve)
{
- return std::make_unique<
- fn::GVMutableArray_For_DerivedSpan<SplinePtr, bool, get_cyclic_value, set_cyclic_value>>(
+ return VMutableArray<bool>::ForDerivedSpan<SplinePtr, get_cyclic_value, set_cyclic_value>(
curve.splines());
}
@@ -625,9 +617,9 @@ static void point_attribute_materialize_to_uninitialized(Span<Span<T>> data,
}
}
-static GVArrayPtr varray_from_initializer(const AttributeInit &initializer,
- const CustomDataType data_type,
- const Span<SplinePtr> splines)
+static GVArray varray_from_initializer(const AttributeInit &initializer,
+ const CustomDataType data_type,
+ const Span<SplinePtr> splines)
{
switch (initializer.type) {
case AttributeInit::Type::Default:
@@ -636,16 +628,15 @@ static GVArrayPtr varray_from_initializer(const AttributeInit &initializer,
BLI_assert_unreachable();
return {};
case AttributeInit::Type::VArray:
- return static_cast<const AttributeInitVArray &>(initializer).varray->shallow_copy();
+ return static_cast<const AttributeInitVArray &>(initializer).varray;
case AttributeInit::Type::MoveArray:
int total_size = 0;
for (const SplinePtr &spline : splines) {
total_size += spline->size();
}
- return std::make_unique<fn::GVArray_For_GSpan>(
- GSpan(*bke::custom_data_type_to_cpp_type(data_type),
- static_cast<const AttributeInitMove &>(initializer).data,
- total_size));
+ return GVArray::ForSpan(GSpan(*bke::custom_data_type_to_cpp_type(data_type),
+ static_cast<const AttributeInitMove &>(initializer).data,
+ total_size));
}
BLI_assert_unreachable();
return {};
@@ -693,11 +684,11 @@ static bool create_point_attribute(GeometryComponent &component,
/* We just created the attribute, it should exist. */
BLI_assert(write_attribute);
- GVArrayPtr source_varray = varray_from_initializer(initializer, data_type, splines);
+ GVArray source_varray = varray_from_initializer(initializer, data_type, splines);
/* TODO: When we can call a variant of #set_all with a virtual array argument,
* this theoretically unnecessary materialize step could be removed. */
- GVArray_GSpan source_varray_span{*source_varray};
- write_attribute.varray->set_all(source_varray_span.data());
+ GVArray_GSpan source_varray_span{source_varray};
+ write_attribute.varray.set_all(source_varray_span.data());
if (initializer.type == AttributeInit::Type::MoveArray) {
MEM_freeN(static_cast<const AttributeInitMove &>(initializer).data);
@@ -725,29 +716,29 @@ static bool remove_point_attribute(GeometryComponent &component,
/**
* Virtual array for any control point data accessed with spans and an offset array.
*/
-template<typename T> class VArray_For_SplinePoints : public VArray<T> {
+template<typename T> class VArray_For_SplinePoints : public VArrayImpl<T> {
private:
const Array<Span<T>> data_;
Array<int> offsets_;
public:
VArray_For_SplinePoints(Array<Span<T>> data, Array<int> offsets)
- : VArray<T>(offsets.last()), data_(std::move(data)), offsets_(std::move(offsets))
+ : VArrayImpl<T>(offsets.last()), data_(std::move(data)), offsets_(std::move(offsets))
{
}
- T get_impl(const int64_t index) const final
+ T get(const int64_t index) const final
{
const PointIndices indices = lookup_point_indices(offsets_, index);
return data_[indices.spline_index][indices.point_index];
}
- void materialize_impl(const IndexMask mask, MutableSpan<T> r_span) const final
+ void materialize(const IndexMask mask, MutableSpan<T> r_span) const final
{
point_attribute_materialize(data_.as_span(), offsets_, mask, r_span);
}
- void materialize_to_uninitialized_impl(const IndexMask mask, MutableSpan<T> r_span) const final
+ void materialize_to_uninitialized(const IndexMask mask, MutableSpan<T> r_span) const final
{
point_attribute_materialize_to_uninitialized(data_.as_span(), offsets_, mask, r_span);
}
@@ -756,30 +747,30 @@ template<typename T> class VArray_For_SplinePoints : public VArray<T> {
/**
* Mutable virtual array for any control point data accessed with spans and an offset array.
*/
-template<typename T> class VMutableArray_For_SplinePoints final : public VMutableArray<T> {
+template<typename T> class VMutableArray_For_SplinePoints final : public VMutableArrayImpl<T> {
private:
Array<MutableSpan<T>> data_;
Array<int> offsets_;
public:
VMutableArray_For_SplinePoints(Array<MutableSpan<T>> data, Array<int> offsets)
- : VMutableArray<T>(offsets.last()), data_(std::move(data)), offsets_(std::move(offsets))
+ : VMutableArrayImpl<T>(offsets.last()), data_(std::move(data)), offsets_(std::move(offsets))
{
}
- T get_impl(const int64_t index) const final
+ T get(const int64_t index) const final
{
const PointIndices indices = lookup_point_indices(offsets_, index);
return data_[indices.spline_index][indices.point_index];
}
- void set_impl(const int64_t index, T value) final
+ void set(const int64_t index, T value) final
{
const PointIndices indices = lookup_point_indices(offsets_, index);
data_[indices.spline_index][indices.point_index] = value;
}
- void set_all_impl(Span<T> src) final
+ void set_all(Span<T> src) final
{
for (const int spline_index : data_.index_range()) {
const int offset = offsets_[spline_index];
@@ -788,30 +779,28 @@ template<typename T> class VMutableArray_For_SplinePoints final : public VMutabl
}
}
- void materialize_impl(const IndexMask mask, MutableSpan<T> r_span) const final
+ void materialize(const IndexMask mask, MutableSpan<T> r_span) const final
{
point_attribute_materialize({(Span<T> *)data_.data(), data_.size()}, offsets_, mask, r_span);
}
- void materialize_to_uninitialized_impl(const IndexMask mask, MutableSpan<T> r_span) const final
+ void materialize_to_uninitialized(const IndexMask mask, MutableSpan<T> r_span) const final
{
point_attribute_materialize_to_uninitialized(
{(Span<T> *)data_.data(), data_.size()}, offsets_, mask, r_span);
}
};
-template<typename T> GVArrayPtr point_data_gvarray(Array<Span<T>> spans, Array<int> offsets)
+template<typename T> VArray<T> point_data_varray(Array<Span<T>> spans, Array<int> offsets)
{
- return std::make_unique<fn::GVArray_For_EmbeddedVArray<T, VArray_For_SplinePoints<T>>>(
- offsets.last(), std::move(spans), std::move(offsets));
+ return VArray<T>::template For<VArray_For_SplinePoints<T>>(std::move(spans), std::move(offsets));
}
template<typename T>
-GVMutableArrayPtr point_data_gvarray(Array<MutableSpan<T>> spans, Array<int> offsets)
+VMutableArray<T> point_data_varray(Array<MutableSpan<T>> spans, Array<int> offsets)
{
- return std::make_unique<
- fn::GVMutableArray_For_EmbeddedVMutableArray<T, VMutableArray_For_SplinePoints<T>>>(
- offsets.last(), std::move(spans), std::move(offsets));
+ return VMutableArray<T>::template For<VMutableArray_For_SplinePoints<T>>(std::move(spans),
+ std::move(offsets));
}
/**
@@ -822,24 +811,24 @@ GVMutableArrayPtr point_data_gvarray(Array<MutableSpan<T>> spans, Array<int> off
* \note There is no need to check the handle type to avoid changing auto handles, since
* retrieving write access to the position data will mark them for recomputation anyway.
*/
-class VMutableArray_For_SplinePosition final : public VMutableArray<float3> {
+class VMutableArray_For_SplinePosition final : public VMutableArrayImpl<float3> {
private:
MutableSpan<SplinePtr> splines_;
Array<int> offsets_;
public:
VMutableArray_For_SplinePosition(MutableSpan<SplinePtr> splines, Array<int> offsets)
- : VMutableArray<float3>(offsets.last()), splines_(splines), offsets_(std::move(offsets))
+ : VMutableArrayImpl<float3>(offsets.last()), splines_(splines), offsets_(std::move(offsets))
{
}
- float3 get_impl(const int64_t index) const final
+ float3 get(const int64_t index) const final
{
const PointIndices indices = lookup_point_indices(offsets_, index);
return splines_[indices.spline_index]->positions()[indices.point_index];
}
- void set_impl(const int64_t index, float3 value) final
+ void set(const int64_t index, float3 value) final
{
const PointIndices indices = lookup_point_indices(offsets_, index);
Spline &spline = *splines_[indices.spline_index];
@@ -854,7 +843,7 @@ class VMutableArray_For_SplinePosition final : public VMutableArray<float3> {
}
}
- void set_all_impl(Span<float3> src) final
+ void set_all(Span<float3> src) final
{
for (const int spline_index : splines_.index_range()) {
Spline &spline = *splines_[spline_index];
@@ -887,21 +876,20 @@ class VMutableArray_For_SplinePosition final : public VMutableArray<float3> {
return spans;
}
- void materialize_impl(const IndexMask mask, MutableSpan<float3> r_span) const final
+ void materialize(const IndexMask mask, MutableSpan<float3> r_span) const final
{
Array<Span<float3>> spans = this->get_position_spans();
point_attribute_materialize(spans.as_span(), offsets_, mask, r_span);
}
- void materialize_to_uninitialized_impl(const IndexMask mask,
- MutableSpan<float3> r_span) const final
+ void materialize_to_uninitialized(const IndexMask mask, MutableSpan<float3> r_span) const final
{
Array<Span<float3>> spans = this->get_position_spans();
point_attribute_materialize_to_uninitialized(spans.as_span(), offsets_, mask, r_span);
}
};
-class VArray_For_BezierHandle final : public VArray<float3> {
+class VArray_For_BezierHandle final : public VArrayImpl<float3> {
private:
Span<SplinePtr> splines_;
Array<int> offsets_;
@@ -909,7 +897,7 @@ class VArray_For_BezierHandle final : public VArray<float3> {
public:
VArray_For_BezierHandle(Span<SplinePtr> splines, Array<int> offsets, const bool is_right)
- : VArray<float3>(offsets.last()),
+ : VArrayImpl<float3>(offsets.last()),
splines_(std::move(splines)),
offsets_(std::move(offsets)),
is_right_(is_right)
@@ -931,7 +919,7 @@ class VArray_For_BezierHandle final : public VArray<float3> {
return float3(0);
}
- float3 get_impl(const int64_t index) const final
+ float3 get(const int64_t index) const final
{
return get_internal(index, splines_, offsets_, is_right_);
}
@@ -978,19 +966,18 @@ class VArray_For_BezierHandle final : public VArray<float3> {
point_attribute_materialize_to_uninitialized(spans.as_span(), offsets, mask, r_span);
}
- void materialize_impl(const IndexMask mask, MutableSpan<float3> r_span) const final
+ void materialize(const IndexMask mask, MutableSpan<float3> r_span) const final
{
materialize_internal(mask, splines_, offsets_, is_right_, r_span);
}
- void materialize_to_uninitialized_impl(const IndexMask mask,
- MutableSpan<float3> r_span) const final
+ void materialize_to_uninitialized(const IndexMask mask, MutableSpan<float3> r_span) const final
{
materialize_to_uninitialized_internal(mask, splines_, offsets_, is_right_, r_span);
}
};
-class VMutableArray_For_BezierHandles final : public VMutableArray<float3> {
+class VMutableArray_For_BezierHandles final : public VMutableArrayImpl<float3> {
private:
MutableSpan<SplinePtr> splines_;
Array<int> offsets_;
@@ -1000,19 +987,19 @@ class VMutableArray_For_BezierHandles final : public VMutableArray<float3> {
VMutableArray_For_BezierHandles(MutableSpan<SplinePtr> splines,
Array<int> offsets,
const bool is_right)
- : VMutableArray<float3>(offsets.last()),
+ : VMutableArrayImpl<float3>(offsets.last()),
splines_(splines),
offsets_(std::move(offsets)),
is_right_(is_right)
{
}
- float3 get_impl(const int64_t index) const final
+ float3 get(const int64_t index) const final
{
return VArray_For_BezierHandle::get_internal(index, splines_, offsets_, is_right_);
}
- void set_impl(const int64_t index, float3 value) final
+ void set(const int64_t index, float3 value) final
{
const PointIndices indices = lookup_point_indices(offsets_, index);
Spline &spline = *splines_[indices.spline_index];
@@ -1028,7 +1015,7 @@ class VMutableArray_For_BezierHandles final : public VMutableArray<float3> {
}
}
- void set_all_impl(Span<float3> src) final
+ void set_all(Span<float3> src) final
{
for (const int spline_index : splines_.index_range()) {
Spline &spline = *splines_[spline_index];
@@ -1051,13 +1038,12 @@ class VMutableArray_For_BezierHandles final : public VMutableArray<float3> {
}
}
- void materialize_impl(const IndexMask mask, MutableSpan<float3> r_span) const final
+ void materialize(const IndexMask mask, MutableSpan<float3> r_span) const final
{
VArray_For_BezierHandle::materialize_internal(mask, splines_, offsets_, is_right_, r_span);
}
- void materialize_to_uninitialized_impl(const IndexMask mask,
- MutableSpan<float3> r_span) const final
+ void materialize_to_uninitialized(const IndexMask mask, MutableSpan<float3> r_span) const final
{
VArray_For_BezierHandle::materialize_to_uninitialized_internal(
mask, splines_, offsets_, is_right_, r_span);
@@ -1099,7 +1085,7 @@ template<typename T> class BuiltinPointAttributeProvider : public BuiltinAttribu
{
}
- GVArrayPtr try_get_for_read(const GeometryComponent &component) const override
+ GVArray try_get_for_read(const GeometryComponent &component) const override
{
const CurveEval *curve = get_curve_from_component_for_read(component);
if (curve == nullptr) {
@@ -1112,7 +1098,7 @@ template<typename T> class BuiltinPointAttributeProvider : public BuiltinAttribu
Span<SplinePtr> splines = curve->splines();
if (splines.size() == 1) {
- return std::make_unique<fn::GVArray_For_GSpan>(get_span_(*splines.first()));
+ return GVArray::ForSpan(get_span_(*splines.first()));
}
Array<int> offsets = curve->control_point_offsets();
@@ -1121,7 +1107,7 @@ template<typename T> class BuiltinPointAttributeProvider : public BuiltinAttribu
spans[i] = get_span_(*splines[i]);
}
- return point_data_gvarray(spans, offsets);
+ return point_data_varray(spans, offsets);
}
WriteAttributeLookup try_get_for_write(GeometryComponent &component) const override
@@ -1146,8 +1132,7 @@ template<typename T> class BuiltinPointAttributeProvider : public BuiltinAttribu
MutableSpan<SplinePtr> splines = curve->splines();
if (splines.size() == 1) {
- return {std::make_unique<fn::GVMutableArray_For_GMutableSpan>(
- get_mutable_span_(*splines.first())),
+ return {GVMutableArray::ForSpan(get_mutable_span_(*splines.first())),
domain_,
std::move(tag_modified_fn)};
}
@@ -1158,7 +1143,7 @@ template<typename T> class BuiltinPointAttributeProvider : public BuiltinAttribu
spans[i] = get_mutable_span_(*splines[i]);
}
- return {point_data_gvarray(spans, offsets), domain_, tag_modified_fn};
+ return {point_data_varray(spans, offsets), domain_, tag_modified_fn};
}
bool try_delete(GeometryComponent &component) const final
@@ -1250,10 +1235,8 @@ class PositionAttributeProvider final : public BuiltinPointAttributeProvider<flo
};
Array<int> offsets = curve->control_point_offsets();
- return {std::make_unique<
- fn::GVMutableArray_For_EmbeddedVMutableArray<float3,
- VMutableArray_For_SplinePosition>>(
- offsets.last(), curve->splines(), std::move(offsets)),
+ return {VMutableArray<float3>::For<VMutableArray_For_SplinePosition>(curve->splines(),
+ std::move(offsets)),
domain_,
tag_modified_fn};
}
@@ -1275,7 +1258,7 @@ class BezierHandleAttributeProvider : public BuiltinAttributeProvider {
{
}
- GVArrayPtr try_get_for_read(const GeometryComponent &component) const override
+ GVArray try_get_for_read(const GeometryComponent &component) const override
{
const CurveEval *curve = get_curve_from_component_for_read(component);
if (curve == nullptr) {
@@ -1287,8 +1270,8 @@ class BezierHandleAttributeProvider : public BuiltinAttributeProvider {
}
Array<int> offsets = curve->control_point_offsets();
- return std::make_unique<fn::GVArray_For_EmbeddedVArray<float3, VArray_For_BezierHandle>>(
- offsets.last(), curve->splines(), std::move(offsets), is_right_);
+ return VArray<float3>::For<VArray_For_BezierHandle>(
+ curve->splines(), std::move(offsets), is_right_);
}
WriteAttributeLookup try_get_for_write(GeometryComponent &component) const override
@@ -1305,12 +1288,10 @@ class BezierHandleAttributeProvider : public BuiltinAttributeProvider {
auto tag_modified_fn = [curve]() { curve->mark_cache_invalid(); };
Array<int> offsets = curve->control_point_offsets();
- return {
- std::make_unique<
- fn::GVMutableArray_For_EmbeddedVMutableArray<float3, VMutableArray_For_BezierHandles>>(
- offsets.last(), curve->splines(), std::move(offsets), is_right_),
- domain_,
- tag_modified_fn};
+ return {VMutableArray<float3>::For<VMutableArray_For_BezierHandles>(
+ curve->splines(), std::move(offsets), is_right_),
+ domain_,
+ tag_modified_fn};
}
bool try_delete(GeometryComponent &UNUSED(component)) const final
@@ -1389,7 +1370,7 @@ class DynamicPointAttributeProvider final : public DynamicAttributesProvider {
/* First check for the simpler situation when we can return a simpler span virtual array. */
if (spans.size() == 1) {
- return {std::make_unique<GVArray_For_GSpan>(spans.first()), ATTR_DOMAIN_POINT};
+ return {GVArray::ForSpan(spans.first()), ATTR_DOMAIN_POINT};
}
ReadAttributeLookup attribute = {};
@@ -1401,7 +1382,7 @@ class DynamicPointAttributeProvider final : public DynamicAttributesProvider {
data[i] = spans[i].typed<T>();
BLI_assert(data[i].data() != nullptr);
}
- attribute = {point_data_gvarray(data, offsets), ATTR_DOMAIN_POINT};
+ attribute = {point_data_varray(data, offsets), ATTR_DOMAIN_POINT};
});
return attribute;
}
@@ -1442,7 +1423,7 @@ class DynamicPointAttributeProvider final : public DynamicAttributesProvider {
/* First check for the simpler situation when we can return a simpler span virtual array. */
if (spans.size() == 1) {
- return {std::make_unique<GVMutableArray_For_GMutableSpan>(spans.first()), ATTR_DOMAIN_POINT};
+ return {GVMutableArray::ForSpan(spans.first()), ATTR_DOMAIN_POINT};
}
WriteAttributeLookup attribute = {};
@@ -1454,7 +1435,7 @@ class DynamicPointAttributeProvider final : public DynamicAttributesProvider {
data[i] = spans[i].typed<T>();
BLI_assert(data[i].data() != nullptr);
}
- attribute = {point_data_gvarray(data, offsets), ATTR_DOMAIN_POINT};
+ attribute = {point_data_varray(data, offsets), ATTR_DOMAIN_POINT};
});
return attribute;
}
diff --git a/source/blender/blenkernel/intern/geometry_component_instances.cc b/source/blender/blenkernel/intern/geometry_component_instances.cc
index 5fe77000519..9a30c86c1e5 100644
--- a/source/blender/blenkernel/intern/geometry_component_instances.cc
+++ b/source/blender/blenkernel/intern/geometry_component_instances.cc
@@ -363,12 +363,22 @@ blender::Span<int> InstancesComponent::almost_unique_ids() const
int InstancesComponent::attribute_domain_size(const AttributeDomain domain) const
{
- if (domain != ATTR_DOMAIN_POINT) {
+ if (domain != ATTR_DOMAIN_INSTANCE) {
return 0;
}
return this->instances_amount();
}
+blender::bke::CustomDataAttributes &InstancesComponent::attributes()
+{
+ return this->attributes_;
+}
+
+const blender::bke::CustomDataAttributes &InstancesComponent::attributes() const
+{
+ return this->attributes_;
+}
+
namespace blender::bke {
static float3 get_transform_position(const float4x4 &transform)
@@ -385,29 +395,26 @@ class InstancePositionAttributeProvider final : public BuiltinAttributeProvider
public:
InstancePositionAttributeProvider()
: BuiltinAttributeProvider(
- "position", ATTR_DOMAIN_POINT, CD_PROP_FLOAT3, NonCreatable, Writable, NonDeletable)
+ "position", ATTR_DOMAIN_INSTANCE, CD_PROP_FLOAT3, NonCreatable, Writable, NonDeletable)
{
}
- GVArrayPtr try_get_for_read(const GeometryComponent &component) const final
+ GVArray try_get_for_read(const GeometryComponent &component) const final
{
const InstancesComponent &instances_component = static_cast<const InstancesComponent &>(
component);
Span<float4x4> transforms = instances_component.instance_transforms();
- return std::make_unique<fn::GVArray_For_DerivedSpan<float4x4, float3, get_transform_position>>(
- transforms);
+ return VArray<float3>::ForDerivedSpan<float4x4, get_transform_position>(transforms);
}
WriteAttributeLookup try_get_for_write(GeometryComponent &component) const final
{
InstancesComponent &instances_component = static_cast<InstancesComponent &>(component);
MutableSpan<float4x4> transforms = instances_component.instance_transforms();
- return {
- std::make_unique<fn::GVMutableArray_For_DerivedSpan<float4x4,
- float3,
- get_transform_position,
- set_transform_position>>(transforms),
- domain_};
+ return {VMutableArray<float3>::ForDerivedSpan<float4x4,
+ get_transform_position,
+ set_transform_position>(transforms),
+ domain_};
}
bool try_delete(GeometryComponent &UNUSED(component)) const final
@@ -431,17 +438,17 @@ class InstanceIDAttributeProvider final : public BuiltinAttributeProvider {
public:
InstanceIDAttributeProvider()
: BuiltinAttributeProvider(
- "id", ATTR_DOMAIN_POINT, CD_PROP_INT32, Creatable, Writable, Deletable)
+ "id", ATTR_DOMAIN_INSTANCE, CD_PROP_INT32, Creatable, Writable, Deletable)
{
}
- GVArrayPtr try_get_for_read(const GeometryComponent &component) const final
+ GVArray try_get_for_read(const GeometryComponent &component) const final
{
const InstancesComponent &instances = static_cast<const InstancesComponent &>(component);
if (instances.instance_ids().is_empty()) {
return {};
}
- return std::make_unique<fn::GVArray_For_Span<int>>(instances.instance_ids());
+ return VArray<int>::ForSpan(instances.instance_ids());
}
WriteAttributeLookup try_get_for_write(GeometryComponent &component) const final
@@ -450,8 +457,7 @@ class InstanceIDAttributeProvider final : public BuiltinAttributeProvider {
if (instances.instance_ids().is_empty()) {
return {};
}
- return {std::make_unique<fn::GVMutableArray_For_MutableSpan<int>>(instances.instance_ids()),
- domain_};
+ return {VMutableArray<int>::ForSpan(instances.instance_ids()), domain_};
}
bool try_delete(GeometryComponent &component) const final
@@ -477,8 +483,8 @@ class InstanceIDAttributeProvider final : public BuiltinAttributeProvider {
break;
}
case AttributeInit::Type::VArray: {
- const GVArray *varray = static_cast<const AttributeInitVArray &>(initializer).varray;
- varray->materialize_to_uninitialized(IndexRange(varray->size()), ids.data());
+ const GVArray &varray = static_cast<const AttributeInitVArray &>(initializer).varray;
+ varray.materialize_to_uninitialized(varray.index_range(), ids.data());
break;
}
case AttributeInit::Type::MoveArray: {
@@ -503,7 +509,21 @@ static ComponentAttributeProviders create_attribute_providers_for_instances()
static InstancePositionAttributeProvider position;
static InstanceIDAttributeProvider id;
- return ComponentAttributeProviders({&position, &id}, {});
+ static CustomDataAccessInfo instance_custom_data_access = {
+ [](GeometryComponent &component) -> CustomData * {
+ InstancesComponent &inst = static_cast<InstancesComponent &>(component);
+ return &inst.attributes().data;
+ },
+ [](const GeometryComponent &component) -> const CustomData * {
+ const InstancesComponent &inst = static_cast<const InstancesComponent &>(component);
+ return &inst.attributes().data;
+ },
+ nullptr};
+
+ static CustomDataAttributeProvider instance_custom_data(ATTR_DOMAIN_INSTANCE,
+ instance_custom_data_access);
+
+ return ComponentAttributeProviders({&position, &id}, {&instance_custom_data});
}
} // namespace blender::bke
diff --git a/source/blender/blenkernel/intern/geometry_component_mesh.cc b/source/blender/blenkernel/intern/geometry_component_mesh.cc
index 0456316151c..a258a66cdf3 100644
--- a/source/blender/blenkernel/intern/geometry_component_mesh.cc
+++ b/source/blender/blenkernel/intern/geometry_component_mesh.cc
@@ -32,8 +32,6 @@
/* Can't include BKE_object_deform.h right now, due to an enum forward declaration. */
extern "C" MDeformVert *BKE_object_defgroup_data_create(ID *id);
-using blender::fn::GVArray;
-
/* -------------------------------------------------------------------- */
/** \name Geometry Component Implementation
* \{ */
@@ -203,17 +201,17 @@ void adapt_mesh_domain_corner_to_point_impl(const Mesh &mesh,
}
}
-static GVArrayPtr adapt_mesh_domain_corner_to_point(const Mesh &mesh, GVArrayPtr varray)
+static GVArray adapt_mesh_domain_corner_to_point(const Mesh &mesh, const GVArray &varray)
{
- GVArrayPtr new_varray;
- attribute_math::convert_to_static_type(varray->type(), [&](auto dummy) {
+ GVArray new_varray;
+ attribute_math::convert_to_static_type(varray.type(), [&](auto dummy) {
using T = decltype(dummy);
if constexpr (!std::is_void_v<attribute_math::DefaultMixer<T>>) {
/* We compute all interpolated values at once, because for this interpolation, one has to
* iterate over all loops anyway. */
Array<T> values(mesh.totvert);
- adapt_mesh_domain_corner_to_point_impl<T>(mesh, varray->typed<T>(), values);
- new_varray = std::make_unique<fn::GVArray_For_ArrayContainer<Array<T>>>(std::move(values));
+ adapt_mesh_domain_corner_to_point_impl<T>(mesh, varray.typed<T>(), values);
+ new_varray = VArray<T>::ForContainer(std::move(values));
}
});
return new_varray;
@@ -239,14 +237,14 @@ static void adapt_mesh_domain_point_to_corner_impl(const Mesh &mesh,
}
}
-static GVArrayPtr adapt_mesh_domain_point_to_corner(const Mesh &mesh, GVArrayPtr varray)
+static GVArray adapt_mesh_domain_point_to_corner(const Mesh &mesh, const GVArray &varray)
{
- GVArrayPtr new_varray;
- attribute_math::convert_to_static_type(varray->type(), [&](auto dummy) {
+ GVArray new_varray;
+ attribute_math::convert_to_static_type(varray.type(), [&](auto dummy) {
using T = decltype(dummy);
Array<T> values(mesh.totloop);
- adapt_mesh_domain_point_to_corner_impl<T>(mesh, varray->typed<T>(), values);
- new_varray = std::make_unique<fn::GVArray_For_ArrayContainer<Array<T>>>(std::move(values));
+ adapt_mesh_domain_point_to_corner_impl<T>(mesh, varray.typed<T>(), values);
+ new_varray = VArray<T>::ForContainer(std::move(values));
});
return new_varray;
}
@@ -295,15 +293,15 @@ void adapt_mesh_domain_corner_to_face_impl(const Mesh &mesh,
}
}
-static GVArrayPtr adapt_mesh_domain_corner_to_face(const Mesh &mesh, GVArrayPtr varray)
+static GVArray adapt_mesh_domain_corner_to_face(const Mesh &mesh, const GVArray &varray)
{
- GVArrayPtr new_varray;
- attribute_math::convert_to_static_type(varray->type(), [&](auto dummy) {
+ GVArray new_varray;
+ attribute_math::convert_to_static_type(varray.type(), [&](auto dummy) {
using T = decltype(dummy);
if constexpr (!std::is_void_v<attribute_math::DefaultMixer<T>>) {
Array<T> values(mesh.totpoly);
- adapt_mesh_domain_corner_to_face_impl<T>(mesh, varray->typed<T>(), values);
- new_varray = std::make_unique<fn::GVArray_For_ArrayContainer<Array<T>>>(std::move(values));
+ adapt_mesh_domain_corner_to_face_impl<T>(mesh, varray.typed<T>(), values);
+ new_varray = VArray<T>::ForContainer(std::move(values));
}
});
return new_varray;
@@ -368,15 +366,15 @@ void adapt_mesh_domain_corner_to_edge_impl(const Mesh &mesh,
}
}
-static GVArrayPtr adapt_mesh_domain_corner_to_edge(const Mesh &mesh, GVArrayPtr varray)
+static GVArray adapt_mesh_domain_corner_to_edge(const Mesh &mesh, const GVArray &varray)
{
- GVArrayPtr new_varray;
- attribute_math::convert_to_static_type(varray->type(), [&](auto dummy) {
+ GVArray new_varray;
+ attribute_math::convert_to_static_type(varray.type(), [&](auto dummy) {
using T = decltype(dummy);
if constexpr (!std::is_void_v<attribute_math::DefaultMixer<T>>) {
Array<T> values(mesh.totedge);
- adapt_mesh_domain_corner_to_edge_impl<T>(mesh, varray->typed<T>(), values);
- new_varray = std::make_unique<fn::GVArray_For_ArrayContainer<Array<T>>>(std::move(values));
+ adapt_mesh_domain_corner_to_edge_impl<T>(mesh, varray.typed<T>(), values);
+ new_varray = VArray<T>::ForContainer(std::move(values));
}
});
return new_varray;
@@ -424,15 +422,15 @@ void adapt_mesh_domain_face_to_point_impl(const Mesh &mesh,
}
}
-static GVArrayPtr adapt_mesh_domain_face_to_point(const Mesh &mesh, GVArrayPtr varray)
+static GVArray adapt_mesh_domain_face_to_point(const Mesh &mesh, const GVArray &varray)
{
- GVArrayPtr new_varray;
- attribute_math::convert_to_static_type(varray->type(), [&](auto dummy) {
+ GVArray new_varray;
+ attribute_math::convert_to_static_type(varray.type(), [&](auto dummy) {
using T = decltype(dummy);
if constexpr (!std::is_void_v<attribute_math::DefaultMixer<T>>) {
Array<T> values(mesh.totvert);
- adapt_mesh_domain_face_to_point_impl<T>(mesh, varray->typed<T>(), values);
- new_varray = std::make_unique<fn::GVArray_For_ArrayContainer<Array<T>>>(std::move(values));
+ adapt_mesh_domain_face_to_point_impl<T>(mesh, varray.typed<T>(), values);
+ new_varray = VArray<T>::ForContainer(std::move(values));
}
});
return new_varray;
@@ -453,15 +451,15 @@ void adapt_mesh_domain_face_to_corner_impl(const Mesh &mesh,
}
}
-static GVArrayPtr adapt_mesh_domain_face_to_corner(const Mesh &mesh, GVArrayPtr varray)
+static GVArray adapt_mesh_domain_face_to_corner(const Mesh &mesh, const GVArray &varray)
{
- GVArrayPtr new_varray;
- attribute_math::convert_to_static_type(varray->type(), [&](auto dummy) {
+ GVArray new_varray;
+ attribute_math::convert_to_static_type(varray.type(), [&](auto dummy) {
using T = decltype(dummy);
if constexpr (!std::is_void_v<attribute_math::DefaultMixer<T>>) {
Array<T> values(mesh.totloop);
- adapt_mesh_domain_face_to_corner_impl<T>(mesh, varray->typed<T>(), values);
- new_varray = std::make_unique<fn::GVArray_For_ArrayContainer<Array<T>>>(std::move(values));
+ adapt_mesh_domain_face_to_corner_impl<T>(mesh, varray.typed<T>(), values);
+ new_varray = VArray<T>::ForContainer(std::move(values));
}
});
return new_varray;
@@ -507,15 +505,15 @@ void adapt_mesh_domain_face_to_edge_impl(const Mesh &mesh,
}
}
-static GVArrayPtr adapt_mesh_domain_face_to_edge(const Mesh &mesh, GVArrayPtr varray)
+static GVArray adapt_mesh_domain_face_to_edge(const Mesh &mesh, const GVArray &varray)
{
- GVArrayPtr new_varray;
- attribute_math::convert_to_static_type(varray->type(), [&](auto dummy) {
+ GVArray new_varray;
+ attribute_math::convert_to_static_type(varray.type(), [&](auto dummy) {
using T = decltype(dummy);
if constexpr (!std::is_void_v<attribute_math::DefaultMixer<T>>) {
Array<T> values(mesh.totedge);
- adapt_mesh_domain_face_to_edge_impl<T>(mesh, varray->typed<T>(), values);
- new_varray = std::make_unique<fn::GVArray_For_ArrayContainer<Array<T>>>(std::move(values));
+ adapt_mesh_domain_face_to_edge_impl<T>(mesh, varray.typed<T>(), values);
+ new_varray = VArray<T>::ForContainer(std::move(values));
}
});
return new_varray;
@@ -567,15 +565,15 @@ void adapt_mesh_domain_point_to_face_impl(const Mesh &mesh,
}
}
-static GVArrayPtr adapt_mesh_domain_point_to_face(const Mesh &mesh, GVArrayPtr varray)
+static GVArray adapt_mesh_domain_point_to_face(const Mesh &mesh, const GVArray &varray)
{
- GVArrayPtr new_varray;
- attribute_math::convert_to_static_type(varray->type(), [&](auto dummy) {
+ GVArray new_varray;
+ attribute_math::convert_to_static_type(varray.type(), [&](auto dummy) {
using T = decltype(dummy);
if constexpr (!std::is_void_v<attribute_math::DefaultMixer<T>>) {
Array<T> values(mesh.totpoly);
- adapt_mesh_domain_point_to_face_impl<T>(mesh, varray->typed<T>(), values);
- new_varray = std::make_unique<fn::GVArray_For_ArrayContainer<Array<T>>>(std::move(values));
+ adapt_mesh_domain_point_to_face_impl<T>(mesh, varray.typed<T>(), values);
+ new_varray = VArray<T>::ForContainer(std::move(values));
}
});
return new_varray;
@@ -617,15 +615,15 @@ void adapt_mesh_domain_point_to_edge_impl(const Mesh &mesh,
}
}
-static GVArrayPtr adapt_mesh_domain_point_to_edge(const Mesh &mesh, GVArrayPtr varray)
+static GVArray adapt_mesh_domain_point_to_edge(const Mesh &mesh, const GVArray &varray)
{
- GVArrayPtr new_varray;
- attribute_math::convert_to_static_type(varray->type(), [&](auto dummy) {
+ GVArray new_varray;
+ attribute_math::convert_to_static_type(varray.type(), [&](auto dummy) {
using T = decltype(dummy);
if constexpr (!std::is_void_v<attribute_math::DefaultMixer<T>>) {
Array<T> values(mesh.totedge);
- adapt_mesh_domain_point_to_edge_impl<T>(mesh, varray->typed<T>(), values);
- new_varray = std::make_unique<fn::GVArray_For_ArrayContainer<Array<T>>>(std::move(values));
+ adapt_mesh_domain_point_to_edge_impl<T>(mesh, varray.typed<T>(), values);
+ new_varray = VArray<T>::ForContainer(std::move(values));
}
});
return new_varray;
@@ -678,15 +676,15 @@ void adapt_mesh_domain_edge_to_corner_impl(const Mesh &mesh,
}
}
-static GVArrayPtr adapt_mesh_domain_edge_to_corner(const Mesh &mesh, GVArrayPtr varray)
+static GVArray adapt_mesh_domain_edge_to_corner(const Mesh &mesh, const GVArray &varray)
{
- GVArrayPtr new_varray;
- attribute_math::convert_to_static_type(varray->type(), [&](auto dummy) {
+ GVArray new_varray;
+ attribute_math::convert_to_static_type(varray.type(), [&](auto dummy) {
using T = decltype(dummy);
if constexpr (!std::is_void_v<attribute_math::DefaultMixer<T>>) {
Array<T> values(mesh.totloop);
- adapt_mesh_domain_edge_to_corner_impl<T>(mesh, varray->typed<T>(), values);
- new_varray = std::make_unique<fn::GVArray_For_ArrayContainer<Array<T>>>(std::move(values));
+ adapt_mesh_domain_edge_to_corner_impl<T>(mesh, varray.typed<T>(), values);
+ new_varray = VArray<T>::ForContainer(std::move(values));
}
});
return new_varray;
@@ -728,15 +726,15 @@ void adapt_mesh_domain_edge_to_point_impl(const Mesh &mesh,
}
}
-static GVArrayPtr adapt_mesh_domain_edge_to_point(const Mesh &mesh, GVArrayPtr varray)
+static GVArray adapt_mesh_domain_edge_to_point(const Mesh &mesh, const GVArray &varray)
{
- GVArrayPtr new_varray;
- attribute_math::convert_to_static_type(varray->type(), [&](auto dummy) {
+ GVArray new_varray;
+ attribute_math::convert_to_static_type(varray.type(), [&](auto dummy) {
using T = decltype(dummy);
if constexpr (!std::is_void_v<attribute_math::DefaultMixer<T>>) {
Array<T> values(mesh.totvert);
- adapt_mesh_domain_edge_to_point_impl<T>(mesh, varray->typed<T>(), values);
- new_varray = std::make_unique<fn::GVArray_For_ArrayContainer<Array<T>>>(std::move(values));
+ adapt_mesh_domain_edge_to_point_impl<T>(mesh, varray.typed<T>(), values);
+ new_varray = VArray<T>::ForContainer(std::move(values));
}
});
return new_varray;
@@ -788,15 +786,15 @@ void adapt_mesh_domain_edge_to_face_impl(const Mesh &mesh,
}
}
-static GVArrayPtr adapt_mesh_domain_edge_to_face(const Mesh &mesh, GVArrayPtr varray)
+static GVArray adapt_mesh_domain_edge_to_face(const Mesh &mesh, const GVArray &varray)
{
- GVArrayPtr new_varray;
- attribute_math::convert_to_static_type(varray->type(), [&](auto dummy) {
+ GVArray new_varray;
+ attribute_math::convert_to_static_type(varray.type(), [&](auto dummy) {
using T = decltype(dummy);
if constexpr (!std::is_void_v<attribute_math::DefaultMixer<T>>) {
Array<T> values(mesh.totpoly);
- adapt_mesh_domain_edge_to_face_impl<T>(mesh, varray->typed<T>(), values);
- new_varray = std::make_unique<fn::GVArray_For_ArrayContainer<Array<T>>>(std::move(values));
+ adapt_mesh_domain_edge_to_face_impl<T>(mesh, varray.typed<T>(), values);
+ new_varray = VArray<T>::ForContainer(std::move(values));
}
});
return new_varray;
@@ -804,15 +802,15 @@ static GVArrayPtr adapt_mesh_domain_edge_to_face(const Mesh &mesh, GVArrayPtr va
} // namespace blender::bke
-blender::fn::GVArrayPtr MeshComponent::attribute_try_adapt_domain(
- blender::fn::GVArrayPtr varray,
+blender::fn::GVArray MeshComponent::attribute_try_adapt_domain_impl(
+ const blender::fn::GVArray &varray,
const AttributeDomain from_domain,
const AttributeDomain to_domain) const
{
if (!varray) {
return {};
}
- if (varray->size() == 0) {
+ if (varray.size() == 0) {
return {};
}
if (from_domain == to_domain) {
@@ -823,11 +821,11 @@ blender::fn::GVArrayPtr MeshComponent::attribute_try_adapt_domain(
case ATTR_DOMAIN_CORNER: {
switch (to_domain) {
case ATTR_DOMAIN_POINT:
- return blender::bke::adapt_mesh_domain_corner_to_point(*mesh_, std::move(varray));
+ return blender::bke::adapt_mesh_domain_corner_to_point(*mesh_, varray);
case ATTR_DOMAIN_FACE:
- return blender::bke::adapt_mesh_domain_corner_to_face(*mesh_, std::move(varray));
+ return blender::bke::adapt_mesh_domain_corner_to_face(*mesh_, varray);
case ATTR_DOMAIN_EDGE:
- return blender::bke::adapt_mesh_domain_corner_to_edge(*mesh_, std::move(varray));
+ return blender::bke::adapt_mesh_domain_corner_to_edge(*mesh_, varray);
default:
break;
}
@@ -836,11 +834,11 @@ blender::fn::GVArrayPtr MeshComponent::attribute_try_adapt_domain(
case ATTR_DOMAIN_POINT: {
switch (to_domain) {
case ATTR_DOMAIN_CORNER:
- return blender::bke::adapt_mesh_domain_point_to_corner(*mesh_, std::move(varray));
+ return blender::bke::adapt_mesh_domain_point_to_corner(*mesh_, varray);
case ATTR_DOMAIN_FACE:
- return blender::bke::adapt_mesh_domain_point_to_face(*mesh_, std::move(varray));
+ return blender::bke::adapt_mesh_domain_point_to_face(*mesh_, varray);
case ATTR_DOMAIN_EDGE:
- return blender::bke::adapt_mesh_domain_point_to_edge(*mesh_, std::move(varray));
+ return blender::bke::adapt_mesh_domain_point_to_edge(*mesh_, varray);
default:
break;
}
@@ -849,11 +847,11 @@ blender::fn::GVArrayPtr MeshComponent::attribute_try_adapt_domain(
case ATTR_DOMAIN_FACE: {
switch (to_domain) {
case ATTR_DOMAIN_POINT:
- return blender::bke::adapt_mesh_domain_face_to_point(*mesh_, std::move(varray));
+ return blender::bke::adapt_mesh_domain_face_to_point(*mesh_, varray);
case ATTR_DOMAIN_CORNER:
- return blender::bke::adapt_mesh_domain_face_to_corner(*mesh_, std::move(varray));
+ return blender::bke::adapt_mesh_domain_face_to_corner(*mesh_, varray);
case ATTR_DOMAIN_EDGE:
- return blender::bke::adapt_mesh_domain_face_to_edge(*mesh_, std::move(varray));
+ return blender::bke::adapt_mesh_domain_face_to_edge(*mesh_, varray);
default:
break;
}
@@ -862,11 +860,11 @@ blender::fn::GVArrayPtr MeshComponent::attribute_try_adapt_domain(
case ATTR_DOMAIN_EDGE: {
switch (to_domain) {
case ATTR_DOMAIN_CORNER:
- return blender::bke::adapt_mesh_domain_edge_to_corner(*mesh_, std::move(varray));
+ return blender::bke::adapt_mesh_domain_edge_to_corner(*mesh_, varray);
case ATTR_DOMAIN_POINT:
- return blender::bke::adapt_mesh_domain_edge_to_point(*mesh_, std::move(varray));
+ return blender::bke::adapt_mesh_domain_edge_to_point(*mesh_, varray);
case ATTR_DOMAIN_FACE:
- return blender::bke::adapt_mesh_domain_edge_to_face(*mesh_, std::move(varray));
+ return blender::bke::adapt_mesh_domain_edge_to_face(*mesh_, varray);
default:
break;
}
@@ -896,9 +894,9 @@ static const Mesh *get_mesh_from_component_for_read(const GeometryComponent &com
namespace blender::bke {
template<typename StructT, typename ElemT, ElemT (*GetFunc)(const StructT &)>
-static GVArrayPtr make_derived_read_attribute(const void *data, const int domain_size)
+static GVArray make_derived_read_attribute(const void *data, const int domain_size)
{
- return std::make_unique<fn::GVArray_For_DerivedSpan<StructT, ElemT, GetFunc>>(
+ return VArray<ElemT>::template ForDerivedSpan<StructT, GetFunc>(
Span<StructT>((const StructT *)data, domain_size));
}
@@ -906,23 +904,22 @@ template<typename StructT,
typename ElemT,
ElemT (*GetFunc)(const StructT &),
void (*SetFunc)(StructT &, ElemT)>
-static GVMutableArrayPtr make_derived_write_attribute(void *data, const int domain_size)
+static GVMutableArray make_derived_write_attribute(void *data, const int domain_size)
{
- return std::make_unique<fn::GVMutableArray_For_DerivedSpan<StructT, ElemT, GetFunc, SetFunc>>(
+ return VMutableArray<ElemT>::template ForDerivedSpan<StructT, GetFunc, SetFunc>(
MutableSpan<StructT>((StructT *)data, domain_size));
}
template<typename T>
-static GVArrayPtr make_array_read_attribute(const void *data, const int domain_size)
+static GVArray make_array_read_attribute(const void *data, const int domain_size)
{
- return std::make_unique<fn::GVArray_For_Span<T>>(Span<T>((const T *)data, domain_size));
+ return VArray<T>::ForSpan(Span<T>((const T *)data, domain_size));
}
template<typename T>
-static GVMutableArrayPtr make_array_write_attribute(void *data, const int domain_size)
+static GVMutableArray make_array_write_attribute(void *data, const int domain_size)
{
- return std::make_unique<fn::GVMutableArray_For_MutableSpan<T>>(
- MutableSpan<T>((T *)data, domain_size));
+ return VMutableArray<T>::ForSpan(MutableSpan<T>((T *)data, domain_size));
}
static float3 get_vertex_position(const MVert &vert)
@@ -999,23 +996,23 @@ static void set_crease(MEdge &edge, float value)
edge.crease = round_fl_to_uchar_clamp(value * 255.0f);
}
-class VMutableArray_For_VertexWeights final : public VMutableArray<float> {
+class VMutableArray_For_VertexWeights final : public VMutableArrayImpl<float> {
private:
MDeformVert *dverts_;
const int dvert_index_;
public:
VMutableArray_For_VertexWeights(MDeformVert *dverts, const int totvert, const int dvert_index)
- : VMutableArray<float>(totvert), dverts_(dverts), dvert_index_(dvert_index)
+ : VMutableArrayImpl<float>(totvert), dverts_(dverts), dvert_index_(dvert_index)
{
}
- float get_impl(const int64_t index) const override
+ float get(const int64_t index) const override
{
return get_internal(dverts_, dvert_index_, index);
}
- void set_impl(const int64_t index, const float value) override
+ void set(const int64_t index, const float value) override
{
MDeformWeight *weight = BKE_defvert_ensure_index(&dverts_[index], dvert_index_);
weight->weight = value;
@@ -1036,18 +1033,18 @@ class VMutableArray_For_VertexWeights final : public VMutableArray<float> {
}
};
-class VArray_For_VertexWeights final : public VArray<float> {
+class VArray_For_VertexWeights final : public VArrayImpl<float> {
private:
const MDeformVert *dverts_;
const int dvert_index_;
public:
VArray_For_VertexWeights(const MDeformVert *dverts, const int totvert, const int dvert_index)
- : VArray<float>(totvert), dverts_(dverts), dvert_index_(dvert_index)
+ : VArrayImpl<float>(totvert), dverts_(dverts), dvert_index_(dvert_index)
{
}
- float get_impl(const int64_t index) const override
+ float get(const int64_t index) const override
{
return VMutableArray_For_VertexWeights::get_internal(dverts_, dvert_index_, index);
}
@@ -1078,12 +1075,10 @@ class VertexGroupsAttributeProvider final : public DynamicAttributesProvider {
}
if (mesh->dvert == nullptr) {
static const float default_value = 0.0f;
- return {std::make_unique<fn::GVArray_For_SingleValueRef>(
- CPPType::get<float>(), mesh->totvert, &default_value),
- ATTR_DOMAIN_POINT};
+ return {VArray<float>::ForSingle(default_value, mesh->totvert), ATTR_DOMAIN_POINT};
}
- return {std::make_unique<fn::GVArray_For_EmbeddedVArray<float, VArray_For_VertexWeights>>(
- mesh->totvert, mesh->dvert, mesh->totvert, vertex_group_index),
+ return {VArray<float>::For<VArray_For_VertexWeights>(
+ mesh->dvert, mesh->totvert, vertex_group_index),
ATTR_DOMAIN_POINT};
}
@@ -1114,11 +1109,9 @@ class VertexGroupsAttributeProvider final : public DynamicAttributesProvider {
mesh->dvert = (MDeformVert *)CustomData_duplicate_referenced_layer(
&mesh->vdata, CD_MDEFORMVERT, mesh->totvert);
}
- return {
- std::make_unique<
- fn::GVMutableArray_For_EmbeddedVMutableArray<float, VMutableArray_For_VertexWeights>>(
- mesh->totvert, mesh->dvert, mesh->totvert, vertex_group_index),
- ATTR_DOMAIN_POINT};
+ return {VMutableArray<float>::For<VMutableArray_For_VertexWeights>(
+ mesh->dvert, mesh->totvert, vertex_group_index),
+ ATTR_DOMAIN_POINT};
}
bool try_delete(GeometryComponent &component, const AttributeIDRef &attribute_id) const final
@@ -1187,7 +1180,7 @@ class NormalAttributeProvider final : public BuiltinAttributeProvider {
{
}
- GVArrayPtr try_get_for_read(const GeometryComponent &component) const final
+ GVArray try_get_for_read(const GeometryComponent &component) const final
{
const MeshComponent &mesh_component = static_cast<const MeshComponent &>(component);
const Mesh *mesh = mesh_component.get_for_read();
@@ -1200,8 +1193,7 @@ class NormalAttributeProvider final : public BuiltinAttributeProvider {
CustomData_has_layer(&mesh->pdata, CD_NORMAL)) {
const void *data = CustomData_get_layer(&mesh->pdata, CD_NORMAL);
- return std::make_unique<fn::GVArray_For_Span<float3>>(
- Span<float3>((const float3 *)data, mesh->totpoly));
+ return VArray<float3>::ForSpan(Span<float3>((const float3 *)data, mesh->totpoly));
}
Array<float3> normals(mesh->totpoly);
@@ -1210,7 +1202,7 @@ class NormalAttributeProvider final : public BuiltinAttributeProvider {
BKE_mesh_calc_poly_normal(poly, &mesh->mloop[poly->loopstart], mesh->mvert, normals[i]);
}
- return std::make_unique<fn::GVArray_For_ArrayContainer<Array<float3>>>(std::move(normals));
+ return VArray<float3>::ForContainer(std::move(normals));
}
WriteAttributeLookup try_get_for_write(GeometryComponent &UNUSED(component)) const final
diff --git a/source/blender/blenkernel/intern/geometry_component_pointcloud.cc b/source/blender/blenkernel/intern/geometry_component_pointcloud.cc
index dfb65a9078d..c6a1c61a96d 100644
--- a/source/blender/blenkernel/intern/geometry_component_pointcloud.cc
+++ b/source/blender/blenkernel/intern/geometry_component_pointcloud.cc
@@ -141,16 +141,15 @@ int PointCloudComponent::attribute_domain_size(const AttributeDomain domain) con
namespace blender::bke {
template<typename T>
-static GVArrayPtr make_array_read_attribute(const void *data, const int domain_size)
+static GVArray make_array_read_attribute(const void *data, const int domain_size)
{
- return std::make_unique<fn::GVArray_For_Span<T>>(Span<T>((const T *)data, domain_size));
+ return VArray<T>::ForSpan(Span<T>((const T *)data, domain_size));
}
template<typename T>
-static GVMutableArrayPtr make_array_write_attribute(void *data, const int domain_size)
+static GVMutableArray make_array_write_attribute(void *data, const int domain_size)
{
- return std::make_unique<fn::GVMutableArray_For_MutableSpan<T>>(
- MutableSpan<T>((T *)data, domain_size));
+ return VMutableArray<T>::ForSpan(MutableSpan<T>((T *)data, domain_size));
}
/**
diff --git a/source/blender/blenkernel/intern/geometry_set.cc b/source/blender/blenkernel/intern/geometry_set.cc
index cd1bafe445a..c250c14f1d7 100644
--- a/source/blender/blenkernel/intern/geometry_set.cc
+++ b/source/blender/blenkernel/intern/geometry_set.cc
@@ -610,24 +610,32 @@ bool BKE_object_has_geometry_set_instances(const Object *ob)
if (geometry_set == nullptr) {
return false;
}
- if (geometry_set->has_instances()) {
- return true;
- }
- const bool has_mesh = geometry_set->has_mesh();
- const bool has_pointcloud = geometry_set->has_pointcloud();
- const bool has_volume = geometry_set->has_volume();
- const bool has_curve = geometry_set->has_curve();
- if (ob->type == OB_MESH) {
- return has_pointcloud || has_volume || has_curve;
- }
- if (ob->type == OB_POINTCLOUD) {
- return has_mesh || has_volume || has_curve;
- }
- if (ob->type == OB_VOLUME) {
- return has_mesh || has_pointcloud || has_curve;
- }
- if (ELEM(ob->type, OB_CURVE, OB_FONT)) {
- return has_mesh || has_pointcloud || has_volume;
+ for (const GeometryComponent *component : geometry_set->get_components_for_read()) {
+ if (component->is_empty()) {
+ continue;
+ }
+ const GeometryComponentType type = component->type();
+ bool is_instance = false;
+ switch (type) {
+ case GEO_COMPONENT_TYPE_MESH:
+ is_instance = ob->type != OB_MESH;
+ break;
+ case GEO_COMPONENT_TYPE_POINT_CLOUD:
+ is_instance = ob->type != OB_POINTCLOUD;
+ break;
+ case GEO_COMPONENT_TYPE_INSTANCES:
+ is_instance = true;
+ break;
+ case GEO_COMPONENT_TYPE_VOLUME:
+ is_instance = ob->type != OB_VOLUME;
+ break;
+ case GEO_COMPONENT_TYPE_CURVE:
+ is_instance = !ELEM(ob->type, OB_CURVE, OB_FONT);
+ break;
+ }
+ if (is_instance) {
+ return true;
+ }
}
return false;
}
diff --git a/source/blender/blenkernel/intern/geometry_set_instances.cc b/source/blender/blenkernel/intern/geometry_set_instances.cc
index 8a7840acd73..c73da7d9659 100644
--- a/source/blender/blenkernel/intern/geometry_set_instances.cc
+++ b/source/blender/blenkernel/intern/geometry_set_instances.cc
@@ -89,8 +89,7 @@ GeometrySet object_get_evaluated_geometry_set(const Object &object)
static void geometry_set_collect_recursive_collection_instance(
const Collection &collection, const float4x4 &transform, Vector<GeometryInstanceGroup> &r_sets)
{
- float4x4 offset_matrix;
- unit_m4(offset_matrix.values);
+ float4x4 offset_matrix = float4x4::identity();
sub_v3_v3(offset_matrix.values[3], collection.instance_offset);
const float4x4 instance_transform = transform * offset_matrix;
geometry_set_collect_recursive_collection(collection, instance_transform, r_sets);
@@ -183,10 +182,7 @@ static void geometry_set_collect_recursive(const GeometrySet &geometry_set,
void geometry_set_gather_instances(const GeometrySet &geometry_set,
Vector<GeometryInstanceGroup> &r_instance_groups)
{
- float4x4 unit_transform;
- unit_m4(unit_transform.values);
-
- geometry_set_collect_recursive(geometry_set, unit_transform, r_instance_groups);
+ geometry_set_collect_recursive(geometry_set, float4x4::identity(), r_instance_groups);
}
void geometry_set_gather_instances_attribute_info(Span<GeometryInstanceGroup> set_groups,
@@ -364,12 +360,12 @@ static void join_attributes(Span<GeometryInstanceGroup> set_groups,
result.attribute_try_create(
entry.key, domain_output, data_type_output, AttributeInitDefault());
WriteAttributeLookup write_attribute = result.attribute_try_get_for_write(attribute_id);
- if (!write_attribute || &write_attribute.varray->type() != cpp_type ||
+ if (!write_attribute || &write_attribute.varray.type() != cpp_type ||
write_attribute.domain != domain_output) {
continue;
}
- fn::GVMutableArray_GSpan dst_span{*write_attribute.varray};
+ fn::GVMutableArray_GSpan dst_span{write_attribute.varray};
int offset = 0;
for (const GeometryInstanceGroup &set_group : set_groups) {
@@ -381,11 +377,11 @@ static void join_attributes(Span<GeometryInstanceGroup> set_groups,
if (domain_size == 0) {
continue; /* Domain size is 0, so no need to increment the offset. */
}
- GVArrayPtr source_attribute = component.attribute_try_get_for_read(
+ GVArray source_attribute = component.attribute_try_get_for_read(
attribute_id, domain_output, data_type_output);
if (source_attribute) {
- fn::GVArray_GSpan src_span{*source_attribute};
+ fn::GVArray_GSpan src_span{source_attribute};
const void *src_buffer = src_span.data();
for (const int UNUSED(i) : set_group.transforms.index_range()) {
void *dst_buffer = dst_span[offset];
diff --git a/source/blender/blenkernel/intern/gpencil_geom.cc b/source/blender/blenkernel/intern/gpencil_geom.cc
index debdf44b0bb..fffc13c49a8 100644
--- a/source/blender/blenkernel/intern/gpencil_geom.cc
+++ b/source/blender/blenkernel/intern/gpencil_geom.cc
@@ -3122,8 +3122,9 @@ bGPDstroke *BKE_gpencil_stroke_delete_tagged_points(bGPdata *gpd,
bGPDstroke *gps,
bGPDstroke *next_stroke,
int tag_flags,
- bool select,
- int limit)
+ const bool select,
+ const bool flat_cap,
+ const int limit)
{
tGPDeleteIsland *islands = (tGPDeleteIsland *)MEM_callocN(
sizeof(tGPDeleteIsland) * (gps->totpoints + 1) / 2, "gp_point_islands");
@@ -3171,6 +3172,9 @@ bGPDstroke *BKE_gpencil_stroke_delete_tagged_points(bGPdata *gpd,
for (idx = 0; idx < num_islands; idx++) {
tGPDeleteIsland *island = &islands[idx];
new_stroke = BKE_gpencil_stroke_duplicate(gps, false, true);
+ if (flat_cap) {
+ new_stroke->caps[1 - (idx % 2)] = GP_STROKE_CAP_FLAT;
+ }
/* if cyclic and first stroke, save to join later */
if ((is_cyclic) && (gps_first == nullptr)) {
diff --git a/source/blender/blenkernel/intern/icons.cc b/source/blender/blenkernel/intern/icons.cc
index 9cf289935ab..c2250dd04f9 100644
--- a/source/blender/blenkernel/intern/icons.cc
+++ b/source/blender/blenkernel/intern/icons.cc
@@ -35,6 +35,7 @@
#include "DNA_gpencil_types.h"
#include "DNA_light_types.h"
#include "DNA_material_types.h"
+#include "DNA_node_types.h"
#include "DNA_object_types.h"
#include "DNA_scene_types.h"
#include "DNA_screen_types.h"
@@ -375,6 +376,7 @@ PreviewImage **BKE_previewimg_id_get_p(const ID *id)
ID_PRV_CASE(ID_SCE, Scene);
ID_PRV_CASE(ID_SCR, bScreen);
ID_PRV_CASE(ID_AC, bAction);
+ ID_PRV_CASE(ID_NT, bNodeTree);
#undef ID_PRV_CASE
default:
break;
diff --git a/source/blender/blenkernel/intern/image.c b/source/blender/blenkernel/intern/image.c
index 0530d537daf..1ef5659855b 100644
--- a/source/blender/blenkernel/intern/image.c
+++ b/source/blender/blenkernel/intern/image.c
@@ -112,12 +112,26 @@
#include "DNA_view3d_types.h"
static CLG_LogRef LOG = {"bke.image"};
-static ThreadMutex *image_mutex;
static void image_init(Image *ima, short source, short type);
static void image_free_packedfiles(Image *ima);
static void copy_image_packedfiles(ListBase *lb_dst, const ListBase *lb_src);
+/* Reset runtime image fields when datablock is being initialized. */
+static void image_runtime_reset(struct Image *image)
+{
+ memset(&image->runtime, 0, sizeof(image->runtime));
+ image->runtime.cache_mutex = MEM_mallocN(sizeof(ThreadMutex), "image runtime cache_mutex");
+ BLI_mutex_init(image->runtime.cache_mutex);
+}
+
+/* Reset runtime image fields when datablock is being copied. */
+static void image_runtime_reset_on_copy(struct Image *image)
+{
+ image->runtime.cache_mutex = MEM_mallocN(sizeof(ThreadMutex), "image runtime cache_mutex");
+ BLI_mutex_init(image->runtime.cache_mutex);
+}
+
static void image_init_data(ID *id)
{
Image *image = (Image *)id;
@@ -167,6 +181,8 @@ static void image_copy_data(Main *UNUSED(bmain), ID *id_dst, const ID *id_src, c
else {
image_dst->preview = NULL;
}
+
+ image_runtime_reset_on_copy(image_dst);
}
static void image_free_data(ID *id)
@@ -194,6 +210,9 @@ static void image_free_data(ID *id)
BLI_freelistN(&image->tiles);
BLI_freelistN(&image->gpu_refresh_areas);
+
+ BLI_mutex_end(image->runtime.cache_mutex);
+ MEM_freeN(image->runtime.cache_mutex);
}
static void image_foreach_cache(ID *id,
@@ -325,6 +344,8 @@ static void image_blend_read_data(BlendDataReader *reader, ID *id)
ima->lastused = 0;
ima->gpuflag = 0;
BLI_listbase_clear(&ima->gpu_refresh_areas);
+
+ image_runtime_reset(ima);
}
static void image_blend_read_lib(BlendLibReader *UNUSED(reader), ID *id)
@@ -452,16 +473,6 @@ static struct ImBuf *imagecache_get(Image *image, int index, bool *r_is_cached_e
return NULL;
}
-void BKE_images_init(void)
-{
- image_mutex = BLI_mutex_alloc();
-}
-
-void BKE_images_exit(void)
-{
- BLI_mutex_free(image_mutex);
-}
-
/* ***************** ALLOC & FREE, DATA MANAGING *************** */
static void image_free_cached_frames(Image *image)
@@ -514,7 +525,7 @@ static void image_free_anims(Image *ima)
void BKE_image_free_buffers_ex(Image *ima, bool do_lock)
{
if (do_lock) {
- BLI_mutex_lock(image_mutex);
+ BLI_mutex_lock(ima->runtime.cache_mutex);
}
image_free_cached_frames(ima);
@@ -528,7 +539,7 @@ void BKE_image_free_buffers_ex(Image *ima, bool do_lock)
BKE_image_free_gputextures(ima);
if (do_lock) {
- BLI_mutex_unlock(image_mutex);
+ BLI_mutex_unlock(ima->runtime.cache_mutex);
}
}
@@ -567,6 +578,8 @@ static void image_init(Image *ima, short source, short type)
}
}
+ image_runtime_reset(ima);
+
BKE_color_managed_colorspace_settings_init(&ima->colorspace_settings);
ima->stereo3d_format = MEM_callocN(sizeof(Stereo3dFormat), "Image Stereo Format");
}
@@ -640,7 +653,9 @@ void BKE_image_merge(Main *bmain, Image *dest, Image *source)
{
/* sanity check */
if (dest && source && dest != source) {
- BLI_mutex_lock(image_mutex);
+ BLI_mutex_lock(source->runtime.cache_mutex);
+ BLI_mutex_lock(dest->runtime.cache_mutex);
+
if (source->cache != NULL) {
struct MovieCacheIter *iter;
iter = IMB_moviecacheIter_new(source->cache);
@@ -652,7 +667,9 @@ void BKE_image_merge(Main *bmain, Image *dest, Image *source)
}
IMB_moviecacheIter_free(iter);
}
- BLI_mutex_unlock(image_mutex);
+
+ BLI_mutex_unlock(dest->runtime.cache_mutex);
+ BLI_mutex_unlock(source->runtime.cache_mutex);
BKE_id_free(bmain, source);
}
@@ -1243,7 +1260,8 @@ static uintptr_t image_mem_size(Image *image)
return 0;
}
- BLI_mutex_lock(image_mutex);
+ BLI_mutex_lock(image->runtime.cache_mutex);
+
if (image->cache != NULL) {
struct MovieCacheIter *iter = IMB_moviecacheIter_new(image->cache);
@@ -1277,7 +1295,8 @@ static uintptr_t image_mem_size(Image *image)
}
IMB_moviecacheIter_free(iter);
}
- BLI_mutex_unlock(image_mutex);
+
+ BLI_mutex_unlock(image->runtime.cache_mutex);
return size;
}
@@ -1361,11 +1380,11 @@ static bool imagecache_check_free_anim(ImBuf *ibuf, void *UNUSED(userkey), void
/* except_frame is weak, only works for seqs without offset... */
void BKE_image_free_anim_ibufs(Image *ima, int except_frame)
{
- BLI_mutex_lock(image_mutex);
+ BLI_mutex_lock(ima->runtime.cache_mutex);
if (ima->cache != NULL) {
IMB_moviecache_cleanup(ima->cache, imagecache_check_free_anim, &except_frame);
}
- BLI_mutex_unlock(image_mutex);
+ BLI_mutex_unlock(ima->runtime.cache_mutex);
}
void BKE_image_all_free_anim_ibufs(Main *bmain, int cfra)
@@ -3284,7 +3303,7 @@ void BKE_image_ensure_viewer_views(const RenderData *rd, Image *ima, ImageUser *
}
if (do_reset) {
- BLI_mutex_lock(image_mutex);
+ BLI_mutex_lock(ima->runtime.cache_mutex);
image_free_cached_frames(ima);
BKE_image_free_views(ima);
@@ -3292,7 +3311,7 @@ void BKE_image_ensure_viewer_views(const RenderData *rd, Image *ima, ImageUser *
/* add new views */
image_viewer_create_views(rd, ima);
- BLI_mutex_unlock(image_mutex);
+ BLI_mutex_unlock(ima->runtime.cache_mutex);
}
BLI_thread_unlock(LOCK_DRAW_IMAGE);
@@ -3556,7 +3575,7 @@ void BKE_image_signal(Main *bmain, Image *ima, ImageUser *iuser, int signal)
return;
}
- BLI_mutex_lock(image_mutex);
+ BLI_mutex_lock(ima->runtime.cache_mutex);
switch (signal) {
case IMA_SIGNAL_FREE:
@@ -3676,7 +3695,7 @@ void BKE_image_signal(Main *bmain, Image *ima, ImageUser *iuser, int signal)
break;
}
- BLI_mutex_unlock(image_mutex);
+ BLI_mutex_unlock(ima->runtime.cache_mutex);
/* don't use notifiers because they are not 100% sure to succeeded
* this also makes sure all scenes are accounted for. */
@@ -5130,11 +5149,11 @@ ImBuf *BKE_image_acquire_ibuf(Image *ima, ImageUser *iuser, void **r_lock)
{
ImBuf *ibuf;
- BLI_mutex_lock(image_mutex);
+ BLI_mutex_lock(ima->runtime.cache_mutex);
ibuf = image_acquire_ibuf(ima, iuser, r_lock);
- BLI_mutex_unlock(image_mutex);
+ BLI_mutex_unlock(ima->runtime.cache_mutex);
return ibuf;
}
@@ -5153,9 +5172,9 @@ void BKE_image_release_ibuf(Image *ima, ImBuf *ibuf, void *lock)
}
if (ibuf) {
- BLI_mutex_lock(image_mutex);
+ BLI_mutex_lock(ima->runtime.cache_mutex);
IMB_freeImBuf(ibuf);
- BLI_mutex_unlock(image_mutex);
+ BLI_mutex_unlock(ima->runtime.cache_mutex);
}
}
@@ -5169,7 +5188,7 @@ bool BKE_image_has_ibuf(Image *ima, ImageUser *iuser)
return false;
}
- BLI_mutex_lock(image_mutex);
+ BLI_mutex_lock(ima->runtime.cache_mutex);
ibuf = image_get_cached_ibuf(ima, iuser, NULL, NULL, NULL);
@@ -5177,7 +5196,7 @@ bool BKE_image_has_ibuf(Image *ima, ImageUser *iuser)
ibuf = image_acquire_ibuf(ima, iuser, NULL);
}
- BLI_mutex_unlock(image_mutex);
+ BLI_mutex_unlock(ima->runtime.cache_mutex);
IMB_freeImBuf(ibuf);
@@ -5197,6 +5216,7 @@ typedef struct ImagePoolItem {
typedef struct ImagePool {
ListBase image_buffers;
BLI_mempool *memory_pool;
+ ThreadMutex mutex;
} ImagePool;
ImagePool *BKE_image_pool_new(void)
@@ -5204,21 +5224,28 @@ ImagePool *BKE_image_pool_new(void)
ImagePool *pool = MEM_callocN(sizeof(ImagePool), "Image Pool");
pool->memory_pool = BLI_mempool_create(sizeof(ImagePoolItem), 0, 128, BLI_MEMPOOL_NOP);
+ BLI_mutex_init(&pool->mutex);
+
return pool;
}
void BKE_image_pool_free(ImagePool *pool)
{
/* Use single lock to dereference all the image buffers. */
- BLI_mutex_lock(image_mutex);
+ BLI_mutex_lock(&pool->mutex);
for (ImagePoolItem *item = pool->image_buffers.first; item != NULL; item = item->next) {
if (item->ibuf != NULL) {
+ BLI_mutex_lock(item->image->runtime.cache_mutex);
IMB_freeImBuf(item->ibuf);
+ BLI_mutex_unlock(item->image->runtime.cache_mutex);
}
}
- BLI_mutex_unlock(image_mutex);
+ BLI_mutex_unlock(&pool->mutex);
BLI_mempool_destroy(pool->memory_pool);
+
+ BLI_mutex_end(&pool->mutex);
+
MEM_freeN(pool);
}
@@ -5250,28 +5277,34 @@ ImBuf *BKE_image_pool_acquire_ibuf(Image *ima, ImageUser *iuser, ImagePool *pool
}
if (pool == NULL) {
- /* pool could be NULL, in this case use general acquire function */
+ /* Pool could be NULL, in this case use general acquire function. */
return BKE_image_acquire_ibuf(ima, iuser, NULL);
}
image_get_entry_and_index(ima, iuser, &entry, &index);
+ /* Use double-checked locking, to avoid locking when the requested image buffer is already in the
+ * pool. */
+
ibuf = image_pool_find_item(pool, ima, entry, index, &found);
if (found) {
return ibuf;
}
- BLI_mutex_lock(image_mutex);
+ /* Lock the pool, to allow thread-safe modification of the content of the pool. */
+ BLI_mutex_lock(&pool->mutex);
ibuf = image_pool_find_item(pool, ima, entry, index, &found);
- /* will also create item even in cases image buffer failed to load,
- * prevents trying to load the same buggy file multiple times
- */
+ /* Will also create item even in cases image buffer failed to load,
+ * prevents trying to load the same buggy file multiple times. */
if (!found) {
ImagePoolItem *item;
- ibuf = image_acquire_ibuf(ima, iuser, NULL);
+ /* Thread-safe acquisition of an image buffer from the image.
+ * The acquisition does not use image pools, so there is no risk of recursive or out-of-order
+ * mutex locking. */
+ ibuf = BKE_image_acquire_ibuf(ima, iuser, NULL);
item = BLI_mempool_alloc(pool->memory_pool);
item->image = ima;
@@ -5282,7 +5315,7 @@ ImBuf *BKE_image_pool_acquire_ibuf(Image *ima, ImageUser *iuser, ImagePool *pool
BLI_addtail(&pool->image_buffers, item);
}
- BLI_mutex_unlock(image_mutex);
+ BLI_mutex_unlock(&pool->mutex);
return ibuf;
}
@@ -5671,7 +5704,7 @@ bool BKE_image_is_dirty_writable(Image *image, bool *r_is_writable)
bool is_dirty = false;
bool is_writable = false;
- BLI_mutex_lock(image_mutex);
+ BLI_mutex_lock(image->runtime.cache_mutex);
if (image->cache != NULL) {
struct MovieCacheIter *iter = IMB_moviecacheIter_new(image->cache);
@@ -5686,7 +5719,7 @@ bool BKE_image_is_dirty_writable(Image *image, bool *r_is_writable)
}
IMB_moviecacheIter_free(iter);
}
- BLI_mutex_unlock(image_mutex);
+ BLI_mutex_unlock(image->runtime.cache_mutex);
if (r_is_writable) {
*r_is_writable = is_writable;
@@ -5715,7 +5748,7 @@ bool BKE_image_buffer_format_writable(ImBuf *ibuf)
void BKE_image_file_format_set(Image *image, int ftype, const ImbFormatOptions *options)
{
- BLI_mutex_lock(image_mutex);
+ BLI_mutex_lock(image->runtime.cache_mutex);
if (image->cache != NULL) {
struct MovieCacheIter *iter = IMB_moviecacheIter_new(image->cache);
@@ -5729,14 +5762,14 @@ void BKE_image_file_format_set(Image *image, int ftype, const ImbFormatOptions *
}
IMB_moviecacheIter_free(iter);
}
- BLI_mutex_unlock(image_mutex);
+ BLI_mutex_unlock(image->runtime.cache_mutex);
}
bool BKE_image_has_loaded_ibuf(Image *image)
{
bool has_loaded_ibuf = false;
- BLI_mutex_lock(image_mutex);
+ BLI_mutex_lock(image->runtime.cache_mutex);
if (image->cache != NULL) {
struct MovieCacheIter *iter = IMB_moviecacheIter_new(image->cache);
@@ -5746,7 +5779,7 @@ bool BKE_image_has_loaded_ibuf(Image *image)
}
IMB_moviecacheIter_free(iter);
}
- BLI_mutex_unlock(image_mutex);
+ BLI_mutex_unlock(image->runtime.cache_mutex);
return has_loaded_ibuf;
}
@@ -5759,7 +5792,7 @@ ImBuf *BKE_image_get_ibuf_with_name(Image *image, const char *name)
{
ImBuf *ibuf = NULL;
- BLI_mutex_lock(image_mutex);
+ BLI_mutex_lock(image->runtime.cache_mutex);
if (image->cache != NULL) {
struct MovieCacheIter *iter = IMB_moviecacheIter_new(image->cache);
@@ -5774,7 +5807,7 @@ ImBuf *BKE_image_get_ibuf_with_name(Image *image, const char *name)
}
IMB_moviecacheIter_free(iter);
}
- BLI_mutex_unlock(image_mutex);
+ BLI_mutex_unlock(image->runtime.cache_mutex);
return ibuf;
}
@@ -5792,7 +5825,7 @@ ImBuf *BKE_image_get_first_ibuf(Image *image)
{
ImBuf *ibuf = NULL;
- BLI_mutex_lock(image_mutex);
+ BLI_mutex_lock(image->runtime.cache_mutex);
if (image->cache != NULL) {
struct MovieCacheIter *iter = IMB_moviecacheIter_new(image->cache);
@@ -5805,7 +5838,7 @@ ImBuf *BKE_image_get_first_ibuf(Image *image)
}
IMB_moviecacheIter_free(iter);
}
- BLI_mutex_unlock(image_mutex);
+ BLI_mutex_unlock(image->runtime.cache_mutex);
return ibuf;
}
diff --git a/source/blender/blenkernel/intern/image_gen.c b/source/blender/blenkernel/intern/image_gen.c
index 943909cc90f..bef14b6ad70 100644
--- a/source/blender/blenkernel/intern/image_gen.c
+++ b/source/blender/blenkernel/intern/image_gen.c
@@ -369,7 +369,7 @@ static void checker_board_text(
char text[3] = {'A', '1', '\0'};
const int mono = blf_mono_font_render;
- BLF_size(mono, 54, 72); /* hard coded size! */
+ BLF_size(mono, 54.0f, 72); /* hard coded size! */
/* OCIO_TODO: using NULL as display will assume using sRGB display
* this is correct since currently generated images are assumed to be in sRGB space,
diff --git a/source/blender/blenkernel/intern/lib_override.c b/source/blender/blenkernel/intern/lib_override.c
index 9ed7218027f..66a550ec6b0 100644
--- a/source/blender/blenkernel/intern/lib_override.c
+++ b/source/blender/blenkernel/intern/lib_override.c
@@ -1028,7 +1028,7 @@ static void lib_override_library_proxy_convert_do(Main *bmain,
if (success) {
CLOG_INFO(&LOG,
4,
- "Proxy object '%s' successfuly converted to library overrides",
+ "Proxy object '%s' successfully converted to library overrides",
ob_proxy->id.name);
/* Remove the instance empty from this scene, the items now have an overridden collection
* instead. */
diff --git a/source/blender/blenkernel/intern/lib_query.c b/source/blender/blenkernel/intern/lib_query.c
index 4165452801c..74750a9b61a 100644
--- a/source/blender/blenkernel/intern/lib_query.c
+++ b/source/blender/blenkernel/intern/lib_query.c
@@ -76,48 +76,52 @@ typedef struct LibraryForeachIDData {
BLI_LINKSTACK_DECLARE(ids_todo, ID *);
} LibraryForeachIDData;
-bool BKE_lib_query_foreachid_process(LibraryForeachIDData *data, ID **id_pp, int cb_flag)
+/** Check whether current iteration over ID usages should be stopped or not.
+ * \return true if the iteration should be stopped, false otherwise. */
+bool BKE_lib_query_foreachid_iter_stop(LibraryForeachIDData *data)
{
- if (!(data->status & IDWALK_STOP)) {
- const int flag = data->flag;
- ID *old_id = *id_pp;
-
- /* Update the callback flags with the ones defined (or forbidden) in `data` by the generic
- * caller code. */
- cb_flag = ((cb_flag | data->cb_flag) & ~data->cb_flag_clear);
-
- /* Update the callback flags with some extra information regarding overrides: all 'loopback',
- * 'internal', 'embedded' etc. ID pointers are never overridable. */
- if (cb_flag &
- (IDWALK_CB_INTERNAL | IDWALK_CB_LOOPBACK | IDWALK_CB_OVERRIDE_LIBRARY_REFERENCE)) {
- cb_flag |= IDWALK_CB_OVERRIDE_LIBRARY_NOT_OVERRIDABLE;
- }
+ return (data->status & IDWALK_STOP) != 0;
+}
- const int callback_return = data->callback(
- &(struct LibraryIDLinkCallbackData){.user_data = data->user_data,
- .bmain = data->bmain,
- .id_owner = data->owner_id,
- .id_self = data->self_id,
- .id_pointer = id_pp,
- .cb_flag = cb_flag});
- if (flag & IDWALK_READONLY) {
- BLI_assert(*(id_pp) == old_id);
- }
- if (old_id && (flag & IDWALK_RECURSE)) {
- if (BLI_gset_add((data)->ids_handled, old_id)) {
- if (!(callback_return & IDWALK_RET_STOP_RECURSION)) {
- BLI_LINKSTACK_PUSH(data->ids_todo, old_id);
- }
+void BKE_lib_query_foreachid_process(LibraryForeachIDData *data, ID **id_pp, int cb_flag)
+{
+ if (BKE_lib_query_foreachid_iter_stop(data)) {
+ return;
+ }
+
+ const int flag = data->flag;
+ ID *old_id = *id_pp;
+
+ /* Update the callback flags with the ones defined (or forbidden) in `data` by the generic
+ * caller code. */
+ cb_flag = ((cb_flag | data->cb_flag) & ~data->cb_flag_clear);
+
+ /* Update the callback flags with some extra information regarding overrides: all 'loopback',
+ * 'internal', 'embedded' etc. ID pointers are never overridable. */
+ if (cb_flag & (IDWALK_CB_INTERNAL | IDWALK_CB_LOOPBACK | IDWALK_CB_OVERRIDE_LIBRARY_REFERENCE)) {
+ cb_flag |= IDWALK_CB_OVERRIDE_LIBRARY_NOT_OVERRIDABLE;
+ }
+
+ const int callback_return = data->callback(
+ &(struct LibraryIDLinkCallbackData){.user_data = data->user_data,
+ .bmain = data->bmain,
+ .id_owner = data->owner_id,
+ .id_self = data->self_id,
+ .id_pointer = id_pp,
+ .cb_flag = cb_flag});
+ if (flag & IDWALK_READONLY) {
+ BLI_assert(*(id_pp) == old_id);
+ }
+ if (old_id && (flag & IDWALK_RECURSE)) {
+ if (BLI_gset_add((data)->ids_handled, old_id)) {
+ if (!(callback_return & IDWALK_RET_STOP_RECURSION)) {
+ BLI_LINKSTACK_PUSH(data->ids_todo, old_id);
}
}
- if (callback_return & IDWALK_RET_STOP_ITER) {
- data->status |= IDWALK_STOP;
- return false;
- }
- return true;
}
-
- return false;
+ if (callback_return & IDWALK_RET_STOP_ITER) {
+ data->status |= IDWALK_STOP;
+ }
}
int BKE_lib_query_foreachid_process_flags_get(LibraryForeachIDData *data)
@@ -139,7 +143,7 @@ int BKE_lib_query_foreachid_process_callback_flag_override(LibraryForeachIDData
return cb_flag_backup;
}
-static void library_foreach_ID_link(Main *bmain,
+static bool library_foreach_ID_link(Main *bmain,
ID *id_owner,
ID *id,
LibraryIDLinkCallback callback,
@@ -158,19 +162,24 @@ void BKE_lib_query_idpropertiesForeachIDLink_callback(IDProperty *id_prop, void
BKE_LIB_FOREACHID_PROCESS_ID(data, id_prop->data.pointer, cb_flag);
}
-bool BKE_library_foreach_ID_embedded(LibraryForeachIDData *data, ID **id_pp)
+/** Process embedded ID pointers (root nodetrees, master collections, ...).
+ *
+ * Those require specific care, since they are technically sub-data of their owner, yet in some
+ * cases they still behave as regular IDs. */
+void BKE_library_foreach_ID_embedded(LibraryForeachIDData *data, ID **id_pp)
{
/* Needed e.g. for callbacks handling relationships. This call shall be absolutely read-only. */
ID *id = *id_pp;
const int flag = data->flag;
- if (!BKE_lib_query_foreachid_process(data, id_pp, IDWALK_CB_EMBEDDED)) {
- return false;
+ BKE_lib_query_foreachid_process(data, id_pp, IDWALK_CB_EMBEDDED);
+ if (BKE_lib_query_foreachid_iter_stop(data)) {
+ return;
}
BLI_assert(id == *id_pp);
if (id == NULL) {
- return true;
+ return;
}
if (flag & IDWALK_IGNORE_EMBEDDED_ID) {
@@ -186,14 +195,24 @@ bool BKE_library_foreach_ID_embedded(LibraryForeachIDData *data, ID **id_pp)
}
}
else {
- library_foreach_ID_link(
- data->bmain, data->owner_id, id, data->callback, data->user_data, data->flag, data);
+ if (!library_foreach_ID_link(
+ data->bmain, data->owner_id, id, data->callback, data->user_data, data->flag, data)) {
+ data->status |= IDWALK_STOP;
+ return;
+ }
}
+}
- return true;
+static void library_foreach_ID_data_cleanup(LibraryForeachIDData *data)
+{
+ if (data->ids_handled != NULL) {
+ BLI_gset_free(data->ids_handled, NULL);
+ BLI_LINKSTACK_FREE(data->ids_todo);
+ }
}
-static void library_foreach_ID_link(Main *bmain,
+/** \return false in case iteration over ID pointers must be stopped, true otherwise. */
+static bool library_foreach_ID_link(Main *bmain,
ID *id_owner,
ID *id,
LibraryIDLinkCallback callback,
@@ -210,6 +229,10 @@ static void library_foreach_ID_link(Main *bmain,
flag |= IDWALK_READONLY;
flag &= ~IDWALK_DO_INTERNAL_RUNTIME_POINTERS;
+ /* NOTE: This function itself should never be called recursively when IDWALK_RECURSE is set,
+ * see also comments in #BKE_library_foreach_ID_embedded.
+ * This is why we can always create this data here, and do not need to try and re-use it from
+ * `inherit_data`. */
data.ids_handled = BLI_gset_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp, __func__);
BLI_LINKSTACK_INIT(data.ids_todo);
@@ -224,10 +247,26 @@ static void library_foreach_ID_link(Main *bmain,
data.user_data = user_data;
#define CALLBACK_INVOKE_ID(check_id, cb_flag) \
- BKE_LIB_FOREACHID_PROCESS_ID(&data, check_id, cb_flag)
+ { \
+ CHECK_TYPE_ANY((check_id), ID *, void *); \
+ BKE_lib_query_foreachid_process(&data, (ID **)&(check_id), (cb_flag)); \
+ if (BKE_lib_query_foreachid_iter_stop(&data)) { \
+ library_foreach_ID_data_cleanup(&data); \
+ return false; \
+ } \
+ } \
+ ((void)0)
#define CALLBACK_INVOKE(check_id_super, cb_flag) \
- BKE_LIB_FOREACHID_PROCESS_IDSUPER(&data, check_id_super, cb_flag)
+ { \
+ CHECK_TYPE(&((check_id_super)->id), ID *); \
+ BKE_lib_query_foreachid_process(&data, (ID **)&(check_id_super), (cb_flag)); \
+ if (BKE_lib_query_foreachid_iter_stop(&data)) { \
+ library_foreach_ID_data_cleanup(&data); \
+ return false; \
+ } \
+ } \
+ ((void)0)
for (; id != NULL; id = (flag & IDWALK_RECURSE) ? BLI_LINKSTACK_POP(data.ids_todo) : NULL) {
data.self_id = id;
@@ -269,6 +308,10 @@ static void library_foreach_ID_link(Main *bmain,
to_id_entry = to_id_entry->next) {
BKE_lib_query_foreachid_process(
&data, to_id_entry->id_pointer.to, to_id_entry->usage_flag);
+ if (BKE_lib_query_foreachid_iter_stop(&data)) {
+ library_foreach_ID_data_cleanup(&data);
+ return false;
+ }
}
continue;
}
@@ -292,26 +335,33 @@ static void library_foreach_ID_link(Main *bmain,
IDP_TYPE_FILTER_ID,
BKE_lib_query_idpropertiesForeachIDLink_callback,
&data);
+ if (BKE_lib_query_foreachid_iter_stop(&data)) {
+ library_foreach_ID_data_cleanup(&data);
+ return false;
+ }
AnimData *adt = BKE_animdata_from_id(id);
if (adt) {
BKE_animdata_foreach_id(adt, &data);
+ if (BKE_lib_query_foreachid_iter_stop(&data)) {
+ library_foreach_ID_data_cleanup(&data);
+ return false;
+ }
}
const IDTypeInfo *id_type = BKE_idtype_get_info_from_id(id);
if (id_type->foreach_id != NULL) {
id_type->foreach_id(id, &data);
- if (data.status & IDWALK_STOP) {
- break;
+ if (BKE_lib_query_foreachid_iter_stop(&data)) {
+ library_foreach_ID_data_cleanup(&data);
+ return false;
}
}
}
- if (data.ids_handled) {
- BLI_gset_free(data.ids_handled, NULL);
- BLI_LINKSTACK_FREE(data.ids_todo);
- }
+ library_foreach_ID_data_cleanup(&data);
+ return true;
#undef CALLBACK_INVOKE_ID
#undef CALLBACK_INVOKE
diff --git a/source/blender/blenkernel/intern/lib_remap.c b/source/blender/blenkernel/intern/lib_remap.c
index 905ac5af512..014c923f04f 100644
--- a/source/blender/blenkernel/intern/lib_remap.c
+++ b/source/blender/blenkernel/intern/lib_remap.c
@@ -132,7 +132,8 @@ static int foreach_libblock_remap_callback(LibraryIDLinkCallbackData *cb_data)
const bool is_obj = (GS(id_owner->name) == ID_OB);
const bool is_obj_proxy = (is_obj &&
(((Object *)id_owner)->proxy || ((Object *)id_owner)->proxy_group));
- const bool is_obj_editmode = (is_obj && BKE_object_is_in_editmode((Object *)id_owner));
+ const bool is_obj_editmode = (is_obj && BKE_object_is_in_editmode((Object *)id_owner) &&
+ (id_remap_data->flag & ID_REMAP_FORCE_OBDATA_IN_EDITMODE) == 0);
const bool is_never_null = ((cb_flag & IDWALK_CB_NEVER_NULL) && (new_id == NULL) &&
(id_remap_data->flag & ID_REMAP_FORCE_NEVER_NULL_USAGE) == 0);
const bool skip_reference = (id_remap_data->flag & ID_REMAP_SKIP_OVERRIDE_LIBRARY) != 0;
@@ -669,57 +670,10 @@ void BKE_libblock_relink_ex(
DEG_relations_tag_update(bmain);
}
+static void libblock_relink_to_newid(Main *bmain, ID *id, const int remap_flag);
static int id_relink_to_newid_looper(LibraryIDLinkCallbackData *cb_data)
{
const int cb_flag = cb_data->cb_flag;
- if (cb_flag & IDWALK_CB_EMBEDDED) {
- return IDWALK_RET_NOP;
- }
-
- ID **id_pointer = cb_data->id_pointer;
- ID *id = *id_pointer;
- if (id) {
- /* See: NEW_ID macro */
- if (id->newid) {
- BKE_library_update_ID_link_user(id->newid, id, cb_flag);
- id = id->newid;
- *id_pointer = id;
- }
- if (id->tag & LIB_TAG_NEW) {
- id->tag &= ~LIB_TAG_NEW;
- BKE_libblock_relink_to_newid(id);
- }
- }
- return IDWALK_RET_NOP;
-}
-
-/**
- * Similar to #libblock_relink_ex,
- * but is remapping IDs to their newid value if non-NULL, in given \a id.
- *
- * Very specific usage, not sure we'll keep it on the long run,
- * currently only used in Object/Collection duplication code...
- *
- * WARNING: This is a deprecated version of this function, should not be used by new code. See
- * #BKE_libblock_relink_to_newid_new below.
- */
-void BKE_libblock_relink_to_newid(ID *id)
-{
- if (ID_IS_LINKED(id)) {
- return;
- }
-
- BKE_library_foreach_ID_link(NULL, id, id_relink_to_newid_looper, NULL, 0);
-}
-
-/* ************************
- * FIXME: Port all usages of #BKE_libblock_relink_to_newid to this
- * #BKE_libblock_relink_to_newid_new new code and remove old one.
- ************************** */
-static void libblock_relink_to_newid_new(Main *bmain, ID *id);
-static int id_relink_to_newid_looper_new(LibraryIDLinkCallbackData *cb_data)
-{
- const int cb_flag = cb_data->cb_flag;
if (cb_flag & (IDWALK_CB_EMBEDDED | IDWALK_CB_OVERRIDE_LIBRARY_REFERENCE)) {
return IDWALK_RET_NOP;
}
@@ -729,31 +683,31 @@ static int id_relink_to_newid_looper_new(LibraryIDLinkCallbackData *cb_data)
ID **id_pointer = cb_data->id_pointer;
ID *id = *id_pointer;
if (id) {
+ const int remap_flag = POINTER_AS_INT(cb_data->user_data);
/* See: NEW_ID macro */
if (id->newid != NULL) {
- BKE_libblock_relink_ex(bmain,
- id_owner,
- id,
- id->newid,
- ID_REMAP_SKIP_INDIRECT_USAGE | ID_REMAP_SKIP_OVERRIDE_LIBRARY);
+ const int remap_flag_final = remap_flag | ID_REMAP_SKIP_INDIRECT_USAGE |
+ ID_REMAP_SKIP_OVERRIDE_LIBRARY;
+ BKE_libblock_relink_ex(bmain, id_owner, id, id->newid, (short)remap_flag_final);
id = id->newid;
}
if (id->tag & LIB_TAG_NEW) {
id->tag &= ~LIB_TAG_NEW;
- libblock_relink_to_newid_new(bmain, id);
+ libblock_relink_to_newid(bmain, id, remap_flag);
}
}
return IDWALK_RET_NOP;
}
-static void libblock_relink_to_newid_new(Main *bmain, ID *id)
+static void libblock_relink_to_newid(Main *bmain, ID *id, const int remap_flag)
{
if (ID_IS_LINKED(id)) {
return;
}
id->tag &= ~LIB_TAG_NEW;
- BKE_library_foreach_ID_link(bmain, id, id_relink_to_newid_looper_new, NULL, 0);
+ BKE_library_foreach_ID_link(
+ bmain, id, id_relink_to_newid_looper, POINTER_FROM_INT(remap_flag), 0);
}
/**
@@ -765,7 +719,7 @@ static void libblock_relink_to_newid_new(Main *bmain, ID *id)
* Very specific usage, not sure we'll keep it on the long run,
* currently only used in Object/Collection duplication code...
*/
-void BKE_libblock_relink_to_newid_new(Main *bmain, ID *id)
+void BKE_libblock_relink_to_newid(Main *bmain, ID *id, const int remap_flag)
{
if (ID_IS_LINKED(id)) {
return;
@@ -774,7 +728,7 @@ void BKE_libblock_relink_to_newid_new(Main *bmain, ID *id)
BLI_assert(bmain->relations == NULL);
BKE_layer_collection_resync_forbid();
- libblock_relink_to_newid_new(bmain, id);
+ libblock_relink_to_newid(bmain, id, remap_flag);
BKE_layer_collection_resync_allow();
BKE_main_collection_sync_remap(bmain);
}
diff --git a/source/blender/blenkernel/intern/light.c b/source/blender/blenkernel/intern/light.c
index a6150028f46..05e8d4fe978 100644
--- a/source/blender/blenkernel/intern/light.c
+++ b/source/blender/blenkernel/intern/light.c
@@ -129,7 +129,8 @@ static void light_foreach_id(ID *id, LibraryForeachIDData *data)
Light *lamp = (Light *)id;
if (lamp->nodetree) {
/* nodetree **are owned by IDs**, treat them as mere sub-data and not real ID! */
- BKE_library_foreach_ID_embedded(data, (ID **)&lamp->nodetree);
+ BKE_LIB_FOREACHID_PROCESS_FUNCTION_CALL(
+ data, BKE_library_foreach_ID_embedded(data, (ID **)&lamp->nodetree));
}
}
diff --git a/source/blender/blenkernel/intern/linestyle.c b/source/blender/blenkernel/intern/linestyle.c
index a1c93920731..3c305d1fb3f 100644
--- a/source/blender/blenkernel/intern/linestyle.c
+++ b/source/blender/blenkernel/intern/linestyle.c
@@ -155,12 +155,14 @@ static void linestyle_foreach_id(ID *id, LibraryForeachIDData *data)
for (int i = 0; i < MAX_MTEX; i++) {
if (linestyle->mtex[i]) {
- BKE_texture_mtex_foreach_id(data, linestyle->mtex[i]);
+ BKE_LIB_FOREACHID_PROCESS_FUNCTION_CALL(
+ data, BKE_texture_mtex_foreach_id(data, linestyle->mtex[i]));
}
}
if (linestyle->nodetree) {
/* nodetree **are owned by IDs**, treat them as mere sub-data and not real ID! */
- BKE_library_foreach_ID_embedded(data, (ID **)&linestyle->nodetree);
+ BKE_LIB_FOREACHID_PROCESS_FUNCTION_CALL(
+ data, BKE_library_foreach_ID_embedded(data, (ID **)&linestyle->nodetree));
}
LISTBASE_FOREACH (LineStyleModifier *, lsm, &linestyle->color_modifiers) {
diff --git a/source/blender/blenkernel/intern/material.c b/source/blender/blenkernel/intern/material.c
index d82559a27cb..1fac83c5665 100644
--- a/source/blender/blenkernel/intern/material.c
+++ b/source/blender/blenkernel/intern/material.c
@@ -166,9 +166,8 @@ static void material_foreach_id(ID *id, LibraryForeachIDData *data)
{
Material *material = (Material *)id;
/* Nodetrees **are owned by IDs**, treat them as mere sub-data and not real ID! */
- if (!BKE_library_foreach_ID_embedded(data, (ID **)&material->nodetree)) {
- return;
- }
+ BKE_LIB_FOREACHID_PROCESS_FUNCTION_CALL(
+ data, BKE_library_foreach_ID_embedded(data, (ID **)&material->nodetree));
if (material->texpaintslot != NULL) {
BKE_LIB_FOREACHID_PROCESS_IDSUPER(data, material->texpaintslot->ima, IDWALK_CB_NOP);
}
@@ -903,7 +902,7 @@ void BKE_object_materials_test(Main *bmain, Object *ob, ID *id)
if ((ob->id.tag & LIB_TAG_MISSING) == 0 && (id->tag & LIB_TAG_MISSING) != 0) {
/* Exception: In case the object is a valid data, but its obdata is an empty place-holder,
* use object's material slots amount as reference.
- * This avoids loosing materials in a local object when its linked obdata gets missing.
+ * This avoids losing materials in a local object when its linked obdata goes missing.
* See T92780. */
BKE_id_material_resize(bmain, id, (short)ob->totcol, false);
}
diff --git a/source/blender/blenkernel/intern/mesh.c b/source/blender/blenkernel/intern/mesh.cc
index f0ba83b396b..73e0c2cfa74 100644
--- a/source/blender/blenkernel/intern/mesh.c
+++ b/source/blender/blenkernel/intern/mesh.cc
@@ -124,7 +124,7 @@ static void mesh_copy_data(Main *bmain, ID *id_dst, const ID *id_src, const int
CustomData_MeshMasks_update(&mask, &CD_MASK_DERIVEDMESH);
}
- mesh_dst->mat = MEM_dupallocN(mesh_src->mat);
+ mesh_dst->mat = (Material **)MEM_dupallocN(mesh_src->mat);
BKE_defgroup_copy_list(&mesh_dst->vertex_group_names, &mesh_src->vertex_group_names);
@@ -142,9 +142,9 @@ static void mesh_copy_data(Main *bmain, ID *id_dst, const ID *id_src, const int
BKE_mesh_update_customdata_pointers(mesh_dst, do_tessface);
- mesh_dst->edit_mesh = NULL;
+ mesh_dst->edit_mesh = nullptr;
- mesh_dst->mselect = MEM_dupallocN(mesh_dst->mselect);
+ mesh_dst->mselect = (MSelect *)MEM_dupallocN(mesh_dst->mselect);
/* TODO: Do we want to add flag to prevent this? */
if (mesh_src->key && (flag & LIB_ID_COPY_SHAPEKEY)) {
@@ -165,7 +165,7 @@ static void mesh_free_data(ID *id)
BKE_editmesh_free_data(mesh->edit_mesh);
}
MEM_freeN(mesh->edit_mesh);
- mesh->edit_mesh = NULL;
+ mesh->edit_mesh = nullptr;
}
BKE_mesh_runtime_free_data(mesh);
@@ -188,14 +188,14 @@ static void mesh_blend_write(BlendWriter *writer, ID *id, const void *id_address
Mesh *mesh = (Mesh *)id;
const bool is_undo = BLO_write_is_undo(writer);
- CustomDataLayer *vlayers = NULL, vlayers_buff[CD_TEMP_CHUNK_SIZE];
- CustomDataLayer *elayers = NULL, elayers_buff[CD_TEMP_CHUNK_SIZE];
- CustomDataLayer *flayers = NULL, flayers_buff[CD_TEMP_CHUNK_SIZE];
- CustomDataLayer *llayers = NULL, llayers_buff[CD_TEMP_CHUNK_SIZE];
- CustomDataLayer *players = NULL, players_buff[CD_TEMP_CHUNK_SIZE];
+ CustomDataLayer *vlayers = nullptr, vlayers_buff[CD_TEMP_CHUNK_SIZE];
+ CustomDataLayer *elayers = nullptr, elayers_buff[CD_TEMP_CHUNK_SIZE];
+ CustomDataLayer *flayers = nullptr, flayers_buff[CD_TEMP_CHUNK_SIZE];
+ CustomDataLayer *llayers = nullptr, llayers_buff[CD_TEMP_CHUNK_SIZE];
+ CustomDataLayer *players = nullptr, players_buff[CD_TEMP_CHUNK_SIZE];
/* cache only - don't write */
- mesh->mface = NULL;
+ mesh->mface = nullptr;
mesh->totface = 0;
memset(&mesh->fdata, 0, sizeof(mesh->fdata));
memset(&mesh->runtime, 0, sizeof(mesh->runtime));
@@ -203,22 +203,22 @@ static void mesh_blend_write(BlendWriter *writer, ID *id, const void *id_address
/* Do not store actual geometry data in case this is a library override ID. */
if (ID_IS_OVERRIDE_LIBRARY(mesh) && !is_undo) {
- mesh->mvert = NULL;
+ mesh->mvert = nullptr;
mesh->totvert = 0;
memset(&mesh->vdata, 0, sizeof(mesh->vdata));
vlayers = vlayers_buff;
- mesh->medge = NULL;
+ mesh->medge = nullptr;
mesh->totedge = 0;
memset(&mesh->edata, 0, sizeof(mesh->edata));
elayers = elayers_buff;
- mesh->mloop = NULL;
+ mesh->mloop = nullptr;
mesh->totloop = 0;
memset(&mesh->ldata, 0, sizeof(mesh->ldata));
llayers = llayers_buff;
- mesh->mpoly = NULL;
+ mesh->mpoly = nullptr;
mesh->totpoly = 0;
memset(&mesh->pdata, 0, sizeof(mesh->pdata));
players = players_buff;
@@ -307,13 +307,13 @@ static void mesh_blend_read_data(BlendDataReader *reader, ID *id)
CustomData_blend_read(reader, &mesh->pdata, mesh->totpoly);
mesh->texflag &= ~ME_AUTOSPACE_EVALUATED;
- mesh->edit_mesh = NULL;
+ mesh->edit_mesh = nullptr;
memset(&mesh->runtime, 0, sizeof(mesh->runtime));
BKE_mesh_runtime_init_data(mesh);
/* happens with old files */
- if (mesh->mselect == NULL) {
+ if (mesh->mselect == nullptr) {
mesh->totselect = 0;
}
@@ -355,31 +355,28 @@ static void mesh_read_expand(BlendExpander *expander, ID *id)
}
IDTypeInfo IDType_ID_ME = {
- .id_code = ID_ME,
- .id_filter = FILTER_ID_ME,
- .main_listbase_index = INDEX_ID_ME,
- .struct_size = sizeof(Mesh),
- .name = "Mesh",
- .name_plural = "meshes",
- .translation_context = BLT_I18NCONTEXT_ID_MESH,
- .flags = IDTYPE_FLAGS_APPEND_IS_REUSABLE,
-
- .init_data = mesh_init_data,
- .copy_data = mesh_copy_data,
- .free_data = mesh_free_data,
- .make_local = NULL,
- .foreach_id = mesh_foreach_id,
- .foreach_cache = NULL,
- .owner_get = NULL,
-
- .blend_write = mesh_blend_write,
- .blend_read_data = mesh_blend_read_data,
- .blend_read_lib = mesh_blend_read_lib,
- .blend_read_expand = mesh_read_expand,
-
- .blend_read_undo_preserve = NULL,
-
- .lib_override_apply_post = NULL,
+ ID_ME,
+ FILTER_ID_ME,
+ INDEX_ID_ME,
+ sizeof(Mesh),
+ "Mesh",
+ "meshes",
+ BLT_I18NCONTEXT_ID_MESH,
+ IDTYPE_FLAGS_APPEND_IS_REUSABLE,
+
+ mesh_init_data,
+ mesh_copy_data,
+ mesh_free_data,
+ nullptr,
+ mesh_foreach_id,
+ nullptr,
+ nullptr,
+ mesh_blend_write,
+ mesh_blend_read_data,
+ mesh_blend_read_lib,
+ mesh_read_expand,
+ nullptr,
+ nullptr,
};
enum {
@@ -471,8 +468,8 @@ static int customdata_compare(
switch (l1->type) {
case CD_MVERT: {
- MVert *v1 = l1->data;
- MVert *v2 = l2->data;
+ MVert *v1 = (MVert *)l1->data;
+ MVert *v2 = (MVert *)l2->data;
int vtot = m1->totvert;
for (j = 0; j < vtot; j++, v1++, v2++) {
@@ -488,8 +485,8 @@ static int customdata_compare(
/* We're order-agnostic for edges here. */
case CD_MEDGE: {
- MEdge *e1 = l1->data;
- MEdge *e2 = l2->data;
+ MEdge *e1 = (MEdge *)l1->data;
+ MEdge *e2 = (MEdge *)l2->data;
int etot = m1->totedge;
EdgeHash *eh = BLI_edgehash_new_ex(__func__, etot);
@@ -502,12 +499,12 @@ static int customdata_compare(
return MESHCMP_EDGEUNKNOWN;
}
}
- BLI_edgehash_free(eh, NULL);
+ BLI_edgehash_free(eh, nullptr);
break;
}
case CD_MPOLY: {
- MPoly *p1 = l1->data;
- MPoly *p2 = l2->data;
+ MPoly *p1 = (MPoly *)l1->data;
+ MPoly *p2 = (MPoly *)l2->data;
int ptot = m1->totpoly;
for (j = 0; j < ptot; j++, p1++, p2++) {
@@ -530,8 +527,8 @@ static int customdata_compare(
break;
}
case CD_MLOOP: {
- MLoop *lp1 = l1->data;
- MLoop *lp2 = l2->data;
+ MLoop *lp1 = (MLoop *)l1->data;
+ MLoop *lp2 = (MLoop *)l2->data;
int ltot = m1->totloop;
for (j = 0; j < ltot; j++, lp1++, lp2++) {
@@ -542,8 +539,8 @@ static int customdata_compare(
break;
}
case CD_MLOOPUV: {
- MLoopUV *lp1 = l1->data;
- MLoopUV *lp2 = l2->data;
+ MLoopUV *lp1 = (MLoopUV *)l1->data;
+ MLoopUV *lp2 = (MLoopUV *)l2->data;
int ltot = m1->totloop;
for (j = 0; j < ltot; j++, lp1++, lp2++) {
@@ -554,8 +551,8 @@ static int customdata_compare(
break;
}
case CD_MLOOPCOL: {
- MLoopCol *lp1 = l1->data;
- MLoopCol *lp2 = l2->data;
+ MLoopCol *lp1 = (MLoopCol *)l1->data;
+ MLoopCol *lp2 = (MLoopCol *)l2->data;
int ltot = m1->totloop;
for (j = 0; j < ltot; j++, lp1++, lp2++) {
@@ -566,8 +563,8 @@ static int customdata_compare(
break;
}
case CD_MDEFORMVERT: {
- MDeformVert *dv1 = l1->data;
- MDeformVert *dv2 = l2->data;
+ MDeformVert *dv1 = (MDeformVert *)l1->data;
+ MDeformVert *dv2 = (MDeformVert *)l2->data;
int dvtot = m1->totvert;
for (j = 0; j < dvtot; j++, dv1++, dv2++) {
@@ -590,8 +587,8 @@ static int customdata_compare(
break;
}
case CD_PROP_FLOAT: {
- const float *l1_data = l1->data;
- const float *l2_data = l2->data;
+ const float *l1_data = (float *)l1->data;
+ const float *l2_data = (float *)l2->data;
for (int i = 0; i < total_length; i++) {
if (compare_threshold_relative(l1_data[i], l2_data[i], thresh)) {
@@ -601,8 +598,8 @@ static int customdata_compare(
break;
}
case CD_PROP_FLOAT2: {
- const float(*l1_data)[2] = l1->data;
- const float(*l2_data)[2] = l2->data;
+ const float(*l1_data)[2] = (float(*)[2])l1->data;
+ const float(*l2_data)[2] = (float(*)[2])l2->data;
for (int i = 0; i < total_length; i++) {
if (compare_threshold_relative(l1_data[i][0], l2_data[i][0], thresh)) {
@@ -615,8 +612,8 @@ static int customdata_compare(
break;
}
case CD_PROP_FLOAT3: {
- const float(*l1_data)[3] = l1->data;
- const float(*l2_data)[3] = l2->data;
+ const float(*l1_data)[3] = (float(*)[3])l1->data;
+ const float(*l2_data)[3] = (float(*)[3])l2->data;
for (int i = 0; i < total_length; i++) {
if (compare_threshold_relative(l1_data[i][0], l2_data[i][0], thresh)) {
@@ -632,8 +629,8 @@ static int customdata_compare(
break;
}
case CD_PROP_INT32: {
- const int *l1_data = l1->data;
- const int *l2_data = l2->data;
+ const int *l1_data = (int *)l1->data;
+ const int *l2_data = (int *)l2->data;
for (int i = 0; i < total_length; i++) {
if (l1_data[i] != l2_data[i]) {
@@ -643,8 +640,8 @@ static int customdata_compare(
break;
}
case CD_PROP_BOOL: {
- const bool *l1_data = l1->data;
- const bool *l2_data = l2->data;
+ const bool *l1_data = (bool *)l1->data;
+ const bool *l2_data = (bool *)l2->data;
for (int i = 0; i < total_length; i++) {
if (l1_data[i] != l2_data[i]) {
@@ -654,8 +651,8 @@ static int customdata_compare(
break;
}
case CD_PROP_COLOR: {
- const MPropCol *l1_data = l1->data;
- const MPropCol *l2_data = l2->data;
+ const MPropCol *l1_data = (MPropCol *)l1->data;
+ const MPropCol *l2_data = (MPropCol *)l2->data;
for (int i = 0; i < total_length; i++) {
for (j = 0; j < 4; j++) {
@@ -722,7 +719,7 @@ const char *BKE_mesh_cmp(Mesh *me1, Mesh *me2, float thresh)
return cmpcode_to_str(c);
}
- return NULL;
+ return nullptr;
}
static void mesh_ensure_tessellation_customdata(Mesh *me)
@@ -767,7 +764,7 @@ static void mesh_ensure_tessellation_customdata(Mesh *me)
void BKE_mesh_ensure_skin_customdata(Mesh *me)
{
- BMesh *bm = me->edit_mesh ? me->edit_mesh->bm : NULL;
+ BMesh *bm = me->edit_mesh ? me->edit_mesh->bm : nullptr;
MVertSkin *vs;
if (bm) {
@@ -779,7 +776,7 @@ void BKE_mesh_ensure_skin_customdata(Mesh *me)
/* Mark an arbitrary vertex as root */
BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) {
- vs = CustomData_bmesh_get(&bm->vdata, v->head.data, CD_MVERT_SKIN);
+ vs = (MVertSkin *)CustomData_bmesh_get(&bm->vdata, v->head.data, CD_MVERT_SKIN);
vs->flag |= MVERT_SKIN_ROOT;
break;
}
@@ -787,7 +784,8 @@ void BKE_mesh_ensure_skin_customdata(Mesh *me)
}
else {
if (!CustomData_has_layer(&me->vdata, CD_MVERT_SKIN)) {
- vs = CustomData_add_layer(&me->vdata, CD_MVERT_SKIN, CD_DEFAULT, NULL, me->totvert);
+ vs = (MVertSkin *)CustomData_add_layer(
+ &me->vdata, CD_MVERT_SKIN, CD_DEFAULT, nullptr, me->totvert);
/* Mark an arbitrary vertex as root */
if (vs) {
@@ -799,7 +797,7 @@ void BKE_mesh_ensure_skin_customdata(Mesh *me)
bool BKE_mesh_ensure_facemap_customdata(struct Mesh *me)
{
- BMesh *bm = me->edit_mesh ? me->edit_mesh->bm : NULL;
+ BMesh *bm = me->edit_mesh ? me->edit_mesh->bm : nullptr;
bool changed = false;
if (bm) {
if (!CustomData_has_layer(&bm->pdata, CD_FACEMAP)) {
@@ -809,7 +807,7 @@ bool BKE_mesh_ensure_facemap_customdata(struct Mesh *me)
}
else {
if (!CustomData_has_layer(&me->pdata, CD_FACEMAP)) {
- CustomData_add_layer(&me->pdata, CD_FACEMAP, CD_DEFAULT, NULL, me->totpoly);
+ CustomData_add_layer(&me->pdata, CD_FACEMAP, CD_DEFAULT, nullptr, me->totpoly);
changed = true;
}
}
@@ -818,7 +816,7 @@ bool BKE_mesh_ensure_facemap_customdata(struct Mesh *me)
bool BKE_mesh_clear_facemap_customdata(struct Mesh *me)
{
- BMesh *bm = me->edit_mesh ? me->edit_mesh->bm : NULL;
+ BMesh *bm = me->edit_mesh ? me->edit_mesh->bm : nullptr;
bool changed = false;
if (bm) {
if (CustomData_has_layer(&bm->pdata, CD_FACEMAP)) {
@@ -836,12 +834,12 @@ bool BKE_mesh_clear_facemap_customdata(struct Mesh *me)
}
/**
- * This ensures grouped customdata (e.g. mtexpoly and mloopuv and mtface, or
- * mloopcol and mcol) have the same relative active/render/clone/mask indices.
+ * This ensures grouped custom-data (e.g. #CD_MLOOPUV and #CD_MTFACE, or
+ * #CD_MLOOPCOL and #CD_MCOL) have the same relative active/render/clone/mask indices.
*
- * NOTE(campbell): that for undo mesh data we want to skip 'ensure_tess_cd' call since
- * we don't want to store memory for tessface when its only used for older
- * Versions of the mesh.
+ * NOTE(@campbellbarton): that for undo mesh data we want to skip 'ensure_tess_cd' call since
+ * we don't want to store memory for #MFace data when its only used for older
+ * versions of the mesh.
*/
static void mesh_update_linked_customdata(Mesh *me, const bool do_ensure_tess_cd)
{
@@ -856,20 +854,20 @@ void BKE_mesh_update_customdata_pointers(Mesh *me, const bool do_ensure_tess_cd)
{
mesh_update_linked_customdata(me, do_ensure_tess_cd);
- me->mvert = CustomData_get_layer(&me->vdata, CD_MVERT);
- me->dvert = CustomData_get_layer(&me->vdata, CD_MDEFORMVERT);
+ me->mvert = (MVert *)CustomData_get_layer(&me->vdata, CD_MVERT);
+ me->dvert = (MDeformVert *)CustomData_get_layer(&me->vdata, CD_MDEFORMVERT);
- me->medge = CustomData_get_layer(&me->edata, CD_MEDGE);
+ me->medge = (MEdge *)CustomData_get_layer(&me->edata, CD_MEDGE);
- me->mface = CustomData_get_layer(&me->fdata, CD_MFACE);
- me->mcol = CustomData_get_layer(&me->fdata, CD_MCOL);
- me->mtface = CustomData_get_layer(&me->fdata, CD_MTFACE);
+ me->mface = (MFace *)CustomData_get_layer(&me->fdata, CD_MFACE);
+ me->mcol = (MCol *)CustomData_get_layer(&me->fdata, CD_MCOL);
+ me->mtface = (MTFace *)CustomData_get_layer(&me->fdata, CD_MTFACE);
- me->mpoly = CustomData_get_layer(&me->pdata, CD_MPOLY);
- me->mloop = CustomData_get_layer(&me->ldata, CD_MLOOP);
+ me->mpoly = (MPoly *)CustomData_get_layer(&me->pdata, CD_MPOLY);
+ me->mloop = (MLoop *)CustomData_get_layer(&me->ldata, CD_MLOOP);
- me->mloopcol = CustomData_get_layer(&me->ldata, CD_MLOOPCOL);
- me->mloopuv = CustomData_get_layer(&me->ldata, CD_MLOOPUV);
+ me->mloopcol = (MLoopCol *)CustomData_get_layer(&me->ldata, CD_MLOOPCOL);
+ me->mloopuv = (MLoopUV *)CustomData_get_layer(&me->ldata, CD_MLOOPUV);
}
bool BKE_mesh_has_custom_loop_normals(Mesh *me)
@@ -883,7 +881,7 @@ bool BKE_mesh_has_custom_loop_normals(Mesh *me)
/**
* Free (or release) any data used by this mesh (does not free the mesh itself).
- * Only use for undo, in most cases `BKE_id_free(NULL, me)` should be used.
+ * Only use for undo, in most cases `BKE_id_free(nullptr, me)` should be used.
*/
void BKE_mesh_free_data_for_undo(Mesh *me)
{
@@ -939,15 +937,15 @@ static void mesh_tessface_clear_intern(Mesh *mesh, int free_customdata)
CustomData_reset(&mesh->fdata);
}
- mesh->mface = NULL;
- mesh->mtface = NULL;
- mesh->mcol = NULL;
+ mesh->mface = nullptr;
+ mesh->mtface = nullptr;
+ mesh->mcol = nullptr;
mesh->totface = 0;
}
Mesh *BKE_mesh_add(Main *bmain, const char *name)
{
- Mesh *me = BKE_id_new(bmain, ID_ME, name);
+ Mesh *me = (Mesh *)BKE_id_new(bmain, ID_ME, name);
return me;
}
@@ -956,28 +954,28 @@ Mesh *BKE_mesh_add(Main *bmain, const char *name)
static void mesh_ensure_cdlayers_primary(Mesh *mesh, bool do_tessface)
{
if (!CustomData_get_layer(&mesh->vdata, CD_MVERT)) {
- CustomData_add_layer(&mesh->vdata, CD_MVERT, CD_CALLOC, NULL, mesh->totvert);
+ CustomData_add_layer(&mesh->vdata, CD_MVERT, CD_CALLOC, nullptr, mesh->totvert);
}
if (!CustomData_get_layer(&mesh->edata, CD_MEDGE)) {
- CustomData_add_layer(&mesh->edata, CD_MEDGE, CD_CALLOC, NULL, mesh->totedge);
+ CustomData_add_layer(&mesh->edata, CD_MEDGE, CD_CALLOC, nullptr, mesh->totedge);
}
if (!CustomData_get_layer(&mesh->ldata, CD_MLOOP)) {
- CustomData_add_layer(&mesh->ldata, CD_MLOOP, CD_CALLOC, NULL, mesh->totloop);
+ CustomData_add_layer(&mesh->ldata, CD_MLOOP, CD_CALLOC, nullptr, mesh->totloop);
}
if (!CustomData_get_layer(&mesh->pdata, CD_MPOLY)) {
- CustomData_add_layer(&mesh->pdata, CD_MPOLY, CD_CALLOC, NULL, mesh->totpoly);
+ CustomData_add_layer(&mesh->pdata, CD_MPOLY, CD_CALLOC, nullptr, mesh->totpoly);
}
if (do_tessface && !CustomData_get_layer(&mesh->fdata, CD_MFACE)) {
- CustomData_add_layer(&mesh->fdata, CD_MFACE, CD_CALLOC, NULL, mesh->totface);
+ CustomData_add_layer(&mesh->fdata, CD_MFACE, CD_CALLOC, nullptr, mesh->totface);
}
}
Mesh *BKE_mesh_new_nomain(
int verts_len, int edges_len, int tessface_len, int loops_len, int polys_len)
{
- Mesh *mesh = BKE_libblock_alloc(
- NULL, ID_ME, BKE_idtype_idcode_to_name(ID_ME), LIB_ID_CREATE_LOCALIZE);
+ Mesh *mesh = (Mesh *)BKE_libblock_alloc(
+ nullptr, ID_ME, BKE_idtype_idcode_to_name(ID_ME), LIB_ID_CREATE_LOCALIZE);
BKE_libblock_init_empty(&mesh->id);
/* Don't use #CustomData_reset because we don't want to touch custom-data. */
@@ -1043,10 +1041,10 @@ void BKE_mesh_copy_parameters_for_eval(Mesh *me_dst, const Mesh *me_src)
BKE_defgroup_copy_list(&me_dst->vertex_group_names, &me_src->vertex_group_names);
/* Copy materials. */
- if (me_dst->mat != NULL) {
+ if (me_dst->mat != nullptr) {
MEM_freeN(me_dst->mat);
}
- me_dst->mat = MEM_dupallocN(me_src->mat);
+ me_dst->mat = (Material **)MEM_dupallocN(me_src->mat);
me_dst->totcol = me_src->totcol;
}
@@ -1061,9 +1059,9 @@ Mesh *BKE_mesh_new_nomain_from_template_ex(const Mesh *me_src,
/* Only do tessface if we are creating tessfaces or copying from mesh with only tessfaces. */
const bool do_tessface = (tessface_len || ((me_src->totface != 0) && (me_src->totpoly == 0)));
- Mesh *me_dst = BKE_id_new_nomain(ID_ME, NULL);
+ Mesh *me_dst = (Mesh *)BKE_id_new_nomain(ID_ME, nullptr);
- me_dst->mselect = MEM_dupallocN(me_src->mselect);
+ me_dst->mselect = (MSelect *)MEM_dupallocN(me_src->mselect);
me_dst->totvert = verts_len;
me_dst->totedge = edges_len;
@@ -1107,7 +1105,7 @@ Mesh *BKE_mesh_new_nomain_from_template(const Mesh *me_src,
void BKE_mesh_eval_delete(struct Mesh *mesh_eval)
{
/* Evaluated mesh may point to edit mesh, but never owns it. */
- mesh_eval->edit_mesh = NULL;
+ mesh_eval->edit_mesh = nullptr;
mesh_free_data(&mesh_eval->id);
BKE_libblock_free_data(&mesh_eval->id, false);
MEM_freeN(mesh_eval);
@@ -1121,7 +1119,7 @@ Mesh *BKE_mesh_copy_for_eval(const Mesh *source, bool reference)
flags |= LIB_ID_COPY_CD_REFERENCE;
}
- Mesh *result = (Mesh *)BKE_id_copy_ex(NULL, &source->id, NULL, flags);
+ Mesh *result = (Mesh *)BKE_id_copy_ex(nullptr, &source->id, nullptr, flags);
return result;
}
@@ -1142,14 +1140,12 @@ BMesh *BKE_mesh_to_bmesh(Mesh *me,
const bool add_key_index,
const struct BMeshCreateParams *params)
{
- return BKE_mesh_to_bmesh_ex(me,
- params,
- &(struct BMeshFromMeshParams){
- .calc_face_normal = false,
- .add_key_index = add_key_index,
- .use_shapekey = true,
- .active_shapekey = ob->shapenr,
- });
+ BMeshFromMeshParams bmesh_from_mesh_params{};
+ bmesh_from_mesh_params.calc_face_normal = false;
+ bmesh_from_mesh_params.add_key_index = add_key_index;
+ bmesh_from_mesh_params.use_shapekey = true;
+ bmesh_from_mesh_params.active_shapekey = ob->shapenr;
+ return BKE_mesh_to_bmesh_ex(me, params, &bmesh_from_mesh_params);
}
Mesh *BKE_mesh_from_bmesh_nomain(BMesh *bm,
@@ -1157,8 +1153,8 @@ Mesh *BKE_mesh_from_bmesh_nomain(BMesh *bm,
const Mesh *me_settings)
{
BLI_assert(params->calc_object_remap == false);
- Mesh *mesh = BKE_id_new_nomain(ID_ME, NULL);
- BM_mesh_bm_to_me(NULL, bm, mesh, params);
+ Mesh *mesh = (Mesh *)BKE_id_new_nomain(ID_ME, nullptr);
+ BM_mesh_bm_to_me(nullptr, bm, mesh, params);
BKE_mesh_copy_parameters_for_eval(mesh, me_settings);
return mesh;
}
@@ -1167,7 +1163,7 @@ Mesh *BKE_mesh_from_bmesh_for_eval_nomain(BMesh *bm,
const CustomData_MeshMasks *cd_mask_extra,
const Mesh *me_settings)
{
- Mesh *mesh = BKE_id_new_nomain(ID_ME, NULL);
+ Mesh *mesh = (Mesh *)BKE_id_new_nomain(ID_ME, nullptr);
BM_mesh_bm_to_me_for_eval(bm, mesh, cd_mask_extra);
BKE_mesh_copy_parameters_for_eval(mesh, me_settings);
return mesh;
@@ -1177,8 +1173,8 @@ BoundBox *BKE_mesh_boundbox_get(Object *ob)
{
/* This is Object-level data access,
* DO NOT touch to Mesh's bb, would be totally thread-unsafe. */
- if (ob->runtime.bb == NULL || ob->runtime.bb->flag & BOUNDBOX_DIRTY) {
- Mesh *me = ob->data;
+ if (ob->runtime.bb == nullptr || ob->runtime.bb->flag & BOUNDBOX_DIRTY) {
+ Mesh *me = (Mesh *)ob->data;
float min[3], max[3];
INIT_MINMAX(min, max);
@@ -1187,8 +1183,8 @@ BoundBox *BKE_mesh_boundbox_get(Object *ob)
max[0] = max[1] = max[2] = 1.0f;
}
- if (ob->runtime.bb == NULL) {
- ob->runtime.bb = MEM_mallocN(sizeof(*ob->runtime.bb), __func__);
+ if (ob->runtime.bb == nullptr) {
+ ob->runtime.bb = (BoundBox *)MEM_mallocN(sizeof(*ob->runtime.bb), __func__);
}
BKE_boundbox_init_from_minmax(ob->runtime.bb, min, max);
ob->runtime.bb->flag &= ~BOUNDBOX_DIRTY;
@@ -1257,13 +1253,13 @@ void BKE_mesh_texspace_get_reference(Mesh *me, short **r_texflag, float **r_loc,
{
BKE_mesh_texspace_ensure(me);
- if (r_texflag != NULL) {
+ if (r_texflag != nullptr) {
*r_texflag = &me->texflag;
}
- if (r_loc != NULL) {
+ if (r_loc != nullptr) {
*r_loc = me->loc;
}
- if (r_size != NULL) {
+ if (r_size != nullptr) {
*r_size = me->size;
}
}
@@ -1282,11 +1278,11 @@ void BKE_mesh_texspace_copy_from_object(Mesh *me, Object *ob)
float (*BKE_mesh_orco_verts_get(Object *ob))[3]
{
- Mesh *me = ob->data;
+ Mesh *me = (Mesh *)ob->data;
Mesh *tme = me->texcomesh ? me->texcomesh : me;
/* Get appropriate vertex coordinates */
- float(*vcos)[3] = MEM_calloc_arrayN(me->totvert, sizeof(*vcos), "orco mesh");
+ float(*vcos)[3] = (float(*)[3])MEM_calloc_arrayN(me->totvert, sizeof(*vcos), "orco mesh");
MVert *mvert = tme->mvert;
int totvert = min_ii(tme->totvert, me->totvert);
@@ -1393,28 +1389,28 @@ int BKE_mesh_mface_index_validate(MFace *mface, CustomData *fdata, int mfindex,
Mesh *BKE_mesh_from_object(Object *ob)
{
- if (ob == NULL) {
- return NULL;
+ if (ob == nullptr) {
+ return nullptr;
}
if (ob->type == OB_MESH) {
- return ob->data;
+ return (Mesh *)ob->data;
}
- return NULL;
+ return nullptr;
}
void BKE_mesh_assign_object(Main *bmain, Object *ob, Mesh *me)
{
- Mesh *old = NULL;
+ Mesh *old = nullptr;
- if (ob == NULL) {
+ if (ob == nullptr) {
return;
}
multires_force_sculpt_rebuild(ob);
if (ob->type == OB_MESH) {
- old = ob->data;
+ old = (Mesh *)ob->data;
if (old) {
id_us_min(&old->id);
}
@@ -1605,8 +1601,9 @@ bool BKE_mesh_minmax(const Mesh *me, float r_min[3], float r_max[3])
void BKE_mesh_transform(Mesh *me, const float mat[4][4], bool do_keys)
{
int i;
- MVert *mvert = CustomData_duplicate_referenced_layer(&me->vdata, CD_MVERT, me->totvert);
- float(*lnors)[3] = CustomData_duplicate_referenced_layer(&me->ldata, CD_NORMAL, me->totloop);
+ MVert *mvert = (MVert *)CustomData_duplicate_referenced_layer(&me->vdata, CD_MVERT, me->totvert);
+ float(*lnors)[3] = (float(*)[3])CustomData_duplicate_referenced_layer(
+ &me->ldata, CD_NORMAL, me->totloop);
/* If the referenced layer has been re-allocated need to update pointers stored in the mesh. */
BKE_mesh_update_customdata_pointers(me, false);
@@ -1616,9 +1613,8 @@ void BKE_mesh_transform(Mesh *me, const float mat[4][4], bool do_keys)
}
if (do_keys && me->key) {
- KeyBlock *kb;
- for (kb = me->key->block.first; kb; kb = kb->next) {
- float *fp = kb->data;
+ LISTBASE_FOREACH (KeyBlock *, kb, &me->key->block) {
+ float *fp = (float *)kb->data;
for (i = kb->totelem; i--; fp += 3) {
mul_m4_v3(mat, fp);
}
@@ -1651,9 +1647,8 @@ void BKE_mesh_translate(Mesh *me, const float offset[3], const bool do_keys)
}
if (do_keys && me->key) {
- KeyBlock *kb;
- for (kb = me->key->block.first; kb; kb = kb->next) {
- float *fp = kb->data;
+ LISTBASE_FOREACH (KeyBlock *, kb, &me->key->block) {
+ float *fp = (float *)kb->data;
for (i = kb->totelem; i--; fp += 3) {
add_v3_v3(fp, offset);
}
@@ -1725,7 +1720,8 @@ void BKE_mesh_mselect_validate(Mesh *me)
}
mselect_src = me->mselect;
- mselect_dst = MEM_malloc_arrayN((me->totselect), sizeof(MSelect), "Mesh selection history");
+ mselect_dst = (MSelect *)MEM_malloc_arrayN(
+ (me->totselect), sizeof(MSelect), "Mesh selection history");
for (i_src = 0, i_dst = 0; i_src < me->totselect; i_src++) {
int index = mselect_src[i_src].index;
@@ -1762,10 +1758,10 @@ void BKE_mesh_mselect_validate(Mesh *me)
if (i_dst == 0) {
MEM_freeN(mselect_dst);
- mselect_dst = NULL;
+ mselect_dst = nullptr;
}
else if (i_dst != me->totselect) {
- mselect_dst = MEM_reallocN(mselect_dst, sizeof(MSelect) * i_dst);
+ mselect_dst = (MSelect *)MEM_reallocN(mselect_dst, sizeof(MSelect) * i_dst);
}
me->totselect = i_dst;
@@ -1809,7 +1805,7 @@ void BKE_mesh_mselect_active_set(Mesh *me, int index, int type)
if (msel_index == -1) {
/* add to the end */
- me->mselect = MEM_reallocN(me->mselect, sizeof(MSelect) * (me->totselect + 1));
+ me->mselect = (MSelect *)MEM_reallocN(me->mselect, sizeof(MSelect) * (me->totselect + 1));
me->mselect[me->totselect].index = index;
me->mselect[me->totselect].type = type;
me->totselect++;
@@ -1845,7 +1841,7 @@ void BKE_mesh_vert_coords_get(const Mesh *mesh, float (*vert_coords)[3])
float (*BKE_mesh_vert_coords_alloc(const Mesh *mesh, int *r_vert_len))[3]
{
- float(*vert_coords)[3] = MEM_mallocN(sizeof(float[3]) * mesh->totvert, __func__);
+ float(*vert_coords)[3] = (float(*)[3])MEM_mallocN(sizeof(float[3]) * mesh->totvert, __func__);
BKE_mesh_vert_coords_get(mesh, vert_coords);
if (r_vert_len) {
*r_vert_len = mesh->totvert;
@@ -1856,7 +1852,8 @@ float (*BKE_mesh_vert_coords_alloc(const Mesh *mesh, int *r_vert_len))[3]
void BKE_mesh_vert_coords_apply(Mesh *mesh, const float (*vert_coords)[3])
{
/* This will just return the pointer if it wasn't a referenced layer. */
- MVert *mv = CustomData_duplicate_referenced_layer(&mesh->vdata, CD_MVERT, mesh->totvert);
+ MVert *mv = (MVert *)CustomData_duplicate_referenced_layer(
+ &mesh->vdata, CD_MVERT, mesh->totvert);
mesh->mvert = mv;
for (int i = 0; i < mesh->totvert; i++, mv++) {
copy_v3_v3(mv->co, vert_coords[i]);
@@ -1869,7 +1866,8 @@ void BKE_mesh_vert_coords_apply_with_mat4(Mesh *mesh,
const float mat[4][4])
{
/* This will just return the pointer if it wasn't a referenced layer. */
- MVert *mv = CustomData_duplicate_referenced_layer(&mesh->vdata, CD_MVERT, mesh->totvert);
+ MVert *mv = (MVert *)CustomData_duplicate_referenced_layer(
+ &mesh->vdata, CD_MVERT, mesh->totvert);
mesh->mvert = mv;
for (int i = 0; i < mesh->totvert; i++, mv++) {
mul_v3_m4v3(mv->co, mat, vert_coords[i]);
@@ -1880,7 +1878,8 @@ void BKE_mesh_vert_coords_apply_with_mat4(Mesh *mesh,
void BKE_mesh_vert_normals_apply(Mesh *mesh, const short (*vert_normals)[3])
{
/* This will just return the pointer if it wasn't a referenced layer. */
- MVert *mv = CustomData_duplicate_referenced_layer(&mesh->vdata, CD_MVERT, mesh->totvert);
+ MVert *mv = (MVert *)CustomData_duplicate_referenced_layer(
+ &mesh->vdata, CD_MVERT, mesh->totvert);
mesh->mvert = mv;
for (int i = 0; i < mesh->totvert; i++, mv++) {
copy_v3_v3_short(mv->no, vert_normals[i]);
@@ -1899,35 +1898,37 @@ void BKE_mesh_calc_normals_split_ex(Mesh *mesh, MLoopNorSpaceArray *r_lnors_spac
{
float(*r_loopnors)[3];
float(*polynors)[3];
- short(*clnors)[2] = NULL;
+ short(*clnors)[2] = nullptr;
bool free_polynors = false;
/* Note that we enforce computing clnors when the clnor space array is requested by caller here.
- * However, we obviously only use the autosmooth angle threshold
- * only in case autosmooth is enabled. */
- const bool use_split_normals = (r_lnors_spacearr != NULL) || ((mesh->flag & ME_AUTOSMOOTH) != 0);
+ * However, we obviously only use the auto-smooth angle threshold
+ * only in case auto-smooth is enabled. */
+ const bool use_split_normals = (r_lnors_spacearr != nullptr) ||
+ ((mesh->flag & ME_AUTOSMOOTH) != 0);
const float split_angle = (mesh->flag & ME_AUTOSMOOTH) != 0 ? mesh->smoothresh : (float)M_PI;
if (CustomData_has_layer(&mesh->ldata, CD_NORMAL)) {
- r_loopnors = CustomData_get_layer(&mesh->ldata, CD_NORMAL);
+ r_loopnors = (float(*)[3])CustomData_get_layer(&mesh->ldata, CD_NORMAL);
memset(r_loopnors, 0, sizeof(float[3]) * mesh->totloop);
}
else {
- r_loopnors = CustomData_add_layer(&mesh->ldata, CD_NORMAL, CD_CALLOC, NULL, mesh->totloop);
+ r_loopnors = (float(*)[3])CustomData_add_layer(
+ &mesh->ldata, CD_NORMAL, CD_CALLOC, nullptr, mesh->totloop);
CustomData_set_layer_flag(&mesh->ldata, CD_NORMAL, CD_FLAG_TEMPORARY);
}
- /* may be NULL */
- clnors = CustomData_get_layer(&mesh->ldata, CD_CUSTOMLOOPNORMAL);
+ /* may be nullptr */
+ clnors = (short(*)[2])CustomData_get_layer(&mesh->ldata, CD_CUSTOMLOOPNORMAL);
if (CustomData_has_layer(&mesh->pdata, CD_NORMAL)) {
/* This assume that layer is always up to date, not sure this is the case
* (esp. in Edit mode?)... */
- polynors = CustomData_get_layer(&mesh->pdata, CD_NORMAL);
+ polynors = (float(*)[3])CustomData_get_layer(&mesh->pdata, CD_NORMAL);
free_polynors = false;
}
else {
- polynors = MEM_malloc_arrayN(mesh->totpoly, sizeof(float[3]), __func__);
+ polynors = (float(*)[3])MEM_malloc_arrayN(mesh->totpoly, sizeof(float[3]), __func__);
BKE_mesh_calc_normals_poly_and_vertex(mesh->mvert,
mesh->totvert,
mesh->mloop,
@@ -1935,7 +1936,7 @@ void BKE_mesh_calc_normals_split_ex(Mesh *mesh, MLoopNorSpaceArray *r_lnors_spac
mesh->mpoly,
mesh->totpoly,
polynors,
- NULL);
+ nullptr);
free_polynors = true;
}
@@ -1953,7 +1954,7 @@ void BKE_mesh_calc_normals_split_ex(Mesh *mesh, MLoopNorSpaceArray *r_lnors_spac
split_angle,
r_lnors_spacearr,
clnors,
- NULL);
+ nullptr);
if (free_polynors) {
MEM_freeN(polynors);
@@ -1966,25 +1967,25 @@ void BKE_mesh_calc_normals_split_ex(Mesh *mesh, MLoopNorSpaceArray *r_lnors_spac
void BKE_mesh_calc_normals_split(Mesh *mesh)
{
- BKE_mesh_calc_normals_split_ex(mesh, NULL);
+ BKE_mesh_calc_normals_split_ex(mesh, nullptr);
}
/* Split faces helper functions. */
-typedef struct SplitFaceNewVert {
+struct SplitFaceNewVert {
struct SplitFaceNewVert *next;
int new_index;
int orig_index;
float *vnor;
-} SplitFaceNewVert;
+};
-typedef struct SplitFaceNewEdge {
+struct SplitFaceNewEdge {
struct SplitFaceNewEdge *next;
int new_index;
int orig_index;
int v1;
int v2;
-} SplitFaceNewEdge;
+};
/* Detect needed new vertices, and update accordingly loops' vertex indices.
* WARNING! Leaves mesh in invalid state. */
@@ -1996,7 +1997,7 @@ static int split_faces_prepare_new_verts(const Mesh *mesh,
/* This is now mandatory, trying to do the job in simple way without that data is doomed to fail,
* even when only dealing with smooth/flat faces one can find cases that no simple algorithm
* can handle properly. */
- BLI_assert(lnors_spacearr != NULL);
+ BLI_assert(lnors_spacearr != nullptr);
const int loops_len = mesh->totloop;
int verts_len = mesh->totvert;
@@ -2049,7 +2050,8 @@ static int split_faces_prepare_new_verts(const Mesh *mesh,
}
else {
/* Add new vert to list. */
- SplitFaceNewVert *new_vert = BLI_memarena_alloc(memarena, sizeof(*new_vert));
+ SplitFaceNewVert *new_vert = (SplitFaceNewVert *)BLI_memarena_alloc(memarena,
+ sizeof(*new_vert));
new_vert->orig_index = vert_idx;
new_vert->new_index = new_vert_idx;
new_vert->vnor = (*lnor_space)->vec_lnor; /* See note above. */
@@ -2096,7 +2098,8 @@ static int split_faces_prepare_new_edges(const Mesh *mesh,
*eval = POINTER_FROM_INT(new_edge_idx);
ml_prev->e = new_edge_idx;
- SplitFaceNewEdge *new_edge = BLI_memarena_alloc(memarena, sizeof(*new_edge));
+ SplitFaceNewEdge *new_edge = (SplitFaceNewEdge *)BLI_memarena_alloc(memarena,
+ sizeof(*new_edge));
new_edge->orig_index = edge_idx;
new_edge->new_index = new_edge_idx;
new_edge->v1 = ml_prev->v;
@@ -2122,7 +2125,7 @@ static int split_faces_prepare_new_edges(const Mesh *mesh,
}
MEM_freeN(edges_used);
- BLI_edgehash_free(edges_hash, NULL);
+ BLI_edgehash_free(edges_hash, nullptr);
return num_edges - mesh->totedge;
}
@@ -2181,14 +2184,14 @@ void BKE_mesh_split_faces(Mesh *mesh, bool free_loop_normals)
}
BKE_mesh_tessface_clear(mesh);
- MLoopNorSpaceArray lnors_spacearr = {NULL};
+ MLoopNorSpaceArray lnors_spacearr = {nullptr};
/* Compute loop normals and loop normal spaces (a.k.a. smooth fans of faces around vertices). */
BKE_mesh_calc_normals_split_ex(mesh, &lnors_spacearr);
/* Stealing memarena from loop normals space array. */
MemArena *memarena = lnors_spacearr.mem;
- SplitFaceNewVert *new_verts = NULL;
- SplitFaceNewEdge *new_edges = NULL;
+ SplitFaceNewVert *new_verts = nullptr;
+ SplitFaceNewEdge *new_edges = nullptr;
/* Ensure we own the layers, we need to do this before split_faces_prepare_new_verts as it will
* directly assign new indices to existing edges and loops. */
@@ -2252,10 +2255,10 @@ void BKE_mesh_eval_geometry(Depsgraph *depsgraph, Mesh *mesh)
/* We are here because something did change in the mesh. This means we can not trust the existing
* evaluated mesh, and we don't know what parts of the mesh did change. So we simply delete the
* evaluated mesh and let objects to re-create it with updated settings. */
- if (mesh->runtime.mesh_eval != NULL) {
- mesh->runtime.mesh_eval->edit_mesh = NULL;
- BKE_id_free(NULL, mesh->runtime.mesh_eval);
- mesh->runtime.mesh_eval = NULL;
+ if (mesh->runtime.mesh_eval != nullptr) {
+ mesh->runtime.mesh_eval->edit_mesh = nullptr;
+ BKE_id_free(nullptr, mesh->runtime.mesh_eval);
+ mesh->runtime.mesh_eval = nullptr;
}
if (DEG_is_active(depsgraph)) {
Mesh *mesh_orig = (Mesh *)DEG_get_original_id(&mesh->id);
diff --git a/source/blender/blenkernel/intern/mesh_remesh_voxel.cc b/source/blender/blenkernel/intern/mesh_remesh_voxel.cc
index 9f5703a015d..3447185089d 100644
--- a/source/blender/blenkernel/intern/mesh_remesh_voxel.cc
+++ b/source/blender/blenkernel/intern/mesh_remesh_voxel.cc
@@ -410,7 +410,8 @@ struct Mesh *BKE_mesh_remesh_voxel_fix_poles(const Mesh *mesh)
{
const BMAllocTemplate allocsize = BMALLOC_TEMPLATE_FROM_ME(mesh);
- const BMeshCreateParams bmesh_create_params = {true};
+ BMeshCreateParams bmesh_create_params{};
+ bmesh_create_params.use_toolflags = true;
BMesh *bm = BM_mesh_create(&allocsize, &bmesh_create_params);
BMeshFromMeshParams bmesh_from_mesh_params{};
diff --git a/source/blender/blenkernel/intern/mesh_runtime.c b/source/blender/blenkernel/intern/mesh_runtime.c
index ce89c723a61..7b1d5140421 100644
--- a/source/blender/blenkernel/intern/mesh_runtime.c
+++ b/source/blender/blenkernel/intern/mesh_runtime.c
@@ -113,7 +113,7 @@ void BKE_mesh_runtime_reset_on_copy(Mesh *mesh, const int UNUSED(flag))
/**
* \brief This function clears runtime cache of the given mesh.
- *
+ *
* Call this function to recalculate runtime data when used.
*/
void BKE_mesh_runtime_clear_cache(Mesh *mesh)
diff --git a/source/blender/blenkernel/intern/mesh_sample.cc b/source/blender/blenkernel/intern/mesh_sample.cc
index 2274d34f0f1..a046cc68bf2 100644
--- a/source/blender/blenkernel/intern/mesh_sample.cc
+++ b/source/blender/blenkernel/intern/mesh_sample.cc
@@ -269,7 +269,7 @@ void MeshAttributeInterpolator::sample_attribute(const ReadAttributeLookup &src_
eAttributeMapMode mode)
{
if (src_attribute && dst_attribute) {
- this->sample_data(*src_attribute.varray, src_attribute.domain, mode, dst_attribute.as_span());
+ this->sample_data(src_attribute.varray, src_attribute.domain, mode, dst_attribute.as_span());
}
}
diff --git a/source/blender/blenkernel/intern/nla.c b/source/blender/blenkernel/intern/nla.c
index ef84afd8668..124db07298d 100644
--- a/source/blender/blenkernel/intern/nla.c
+++ b/source/blender/blenkernel/intern/nla.c
@@ -491,11 +491,11 @@ void BKE_nla_strip_foreach_id(NlaStrip *strip, LibraryForeachIDData *data)
BKE_LIB_FOREACHID_PROCESS_IDSUPER(data, strip->act, IDWALK_CB_USER);
LISTBASE_FOREACH (FCurve *, fcu, &strip->fcurves) {
- BKE_fcurve_foreach_id(fcu, data);
+ BKE_LIB_FOREACHID_PROCESS_FUNCTION_CALL(data, BKE_fcurve_foreach_id(fcu, data));
}
LISTBASE_FOREACH (NlaStrip *, substrip, &strip->strips) {
- BKE_nla_strip_foreach_id(substrip, data);
+ BKE_LIB_FOREACHID_PROCESS_FUNCTION_CALL(data, BKE_nla_strip_foreach_id(substrip, data));
}
}
diff --git a/source/blender/blenkernel/intern/node.cc b/source/blender/blenkernel/intern/node.cc
index ab3132a5d58..e02ea3f7e37 100644
--- a/source/blender/blenkernel/intern/node.cc
+++ b/source/blender/blenkernel/intern/node.cc
@@ -66,6 +66,7 @@
#include "BKE_colortools.h"
#include "BKE_cryptomatte.h"
#include "BKE_global.h"
+#include "BKE_icons.h"
#include "BKE_idprop.h"
#include "BKE_idtype.h"
#include "BKE_lib_id.h"
@@ -129,10 +130,6 @@ static void node_socket_interface_free(bNodeTree *UNUSED(ntree),
static void nodeMuteRerouteOutputLinks(struct bNodeTree *ntree,
struct bNode *node,
const bool mute);
-static FieldInferencingInterface *node_field_inferencing_interface_copy(
- const FieldInferencingInterface &field_inferencing_interface);
-static void node_field_inferencing_interface_free(
- const FieldInferencingInterface *field_inferencing_interface);
static void ntree_init_data(ID *id)
{
@@ -245,9 +242,16 @@ static void ntree_copy_data(Main *UNUSED(bmain), ID *id_dst, const ID *id_src, c
ntree_dst->interface_type = nullptr;
if (ntree_src->field_inferencing_interface) {
- ntree_dst->field_inferencing_interface = node_field_inferencing_interface_copy(
+ ntree_dst->field_inferencing_interface = new FieldInferencingInterface(
*ntree_src->field_inferencing_interface);
}
+
+ if (flag & LIB_ID_COPY_NO_PREVIEW) {
+ ntree_dst->preview = nullptr;
+ }
+ else {
+ BKE_previewimg_id_copy(&ntree_dst->id, &ntree_src->id);
+ }
}
static void ntree_free_data(ID *id)
@@ -293,7 +297,7 @@ static void ntree_free_data(ID *id)
MEM_freeN(sock);
}
- node_field_inferencing_interface_free(ntree->field_inferencing_interface);
+ delete ntree->field_inferencing_interface;
/* free preview hash */
if (ntree->previews) {
@@ -303,12 +307,16 @@ static void ntree_free_data(ID *id)
if (ntree->id.tag & LIB_TAG_LOCALIZED) {
BKE_libblock_free_data(&ntree->id, true);
}
+
+ BKE_previewimg_free(&ntree->preview);
}
static void library_foreach_node_socket(LibraryForeachIDData *data, bNodeSocket *sock)
{
- IDP_foreach_property(
- sock->prop, IDP_TYPE_FILTER_ID, BKE_lib_query_idpropertiesForeachIDLink_callback, data);
+ BKE_LIB_FOREACHID_PROCESS_FUNCTION_CALL(
+ data,
+ IDP_foreach_property(
+ sock->prop, IDP_TYPE_FILTER_ID, BKE_lib_query_idpropertiesForeachIDLink_callback, data));
switch ((eNodeSocketDatatype)sock->type) {
case SOCK_OBJECT: {
@@ -360,21 +368,25 @@ static void node_foreach_id(ID *id, LibraryForeachIDData *data)
LISTBASE_FOREACH (bNode *, node, &ntree->nodes) {
BKE_LIB_FOREACHID_PROCESS_ID(data, node->id, IDWALK_CB_USER);
- IDP_foreach_property(
- node->prop, IDP_TYPE_FILTER_ID, BKE_lib_query_idpropertiesForeachIDLink_callback, data);
+ BKE_LIB_FOREACHID_PROCESS_FUNCTION_CALL(
+ data,
+ IDP_foreach_property(node->prop,
+ IDP_TYPE_FILTER_ID,
+ BKE_lib_query_idpropertiesForeachIDLink_callback,
+ data));
LISTBASE_FOREACH (bNodeSocket *, sock, &node->inputs) {
- library_foreach_node_socket(data, sock);
+ BKE_LIB_FOREACHID_PROCESS_FUNCTION_CALL(data, library_foreach_node_socket(data, sock));
}
LISTBASE_FOREACH (bNodeSocket *, sock, &node->outputs) {
- library_foreach_node_socket(data, sock);
+ BKE_LIB_FOREACHID_PROCESS_FUNCTION_CALL(data, library_foreach_node_socket(data, sock));
}
}
LISTBASE_FOREACH (bNodeSocket *, sock, &ntree->inputs) {
- library_foreach_node_socket(data, sock);
+ BKE_LIB_FOREACHID_PROCESS_FUNCTION_CALL(data, library_foreach_node_socket(data, sock));
}
LISTBASE_FOREACH (bNodeSocket *, sock, &ntree->outputs) {
- library_foreach_node_socket(data, sock);
+ BKE_LIB_FOREACHID_PROCESS_FUNCTION_CALL(data, library_foreach_node_socket(data, sock));
}
}
@@ -635,6 +647,8 @@ void ntreeBlendWrite(BlendWriter *writer, bNodeTree *ntree)
LISTBASE_FOREACH (bNodeSocket *, sock, &ntree->outputs) {
write_node_socket_interface(writer, sock);
}
+
+ BKE_previewimg_blend_write(writer, ntree->preview);
}
static void ntree_blend_write(BlendWriter *writer, ID *id, const void *id_address)
@@ -665,6 +679,7 @@ static void direct_link_node_socket(BlendDataReader *reader, bNodeSocket *sock)
BLO_read_data_address(reader, &sock->default_value);
sock->total_inputs = 0; /* Clear runtime data set before drawing. */
sock->cache = nullptr;
+ sock->declaration = nullptr;
}
/* ntree itself has been read! */
@@ -828,6 +843,9 @@ void ntreeBlendReadData(BlendDataReader *reader, bNodeTree *ntree)
ntree->update |= NTREE_UPDATE_FIELD_INFERENCING;
}
+ BLO_read_data_address(reader, &ntree->preview);
+ BKE_previewimg_blend_read(reader, ntree->preview);
+
/* type verification is in lib-link */
}
@@ -1051,8 +1069,7 @@ IDTypeInfo IDType_ID_NT = {
static void node_add_sockets_from_type(bNodeTree *ntree, bNode *node, bNodeType *ntype)
{
if (ntype->declare != nullptr) {
- nodeDeclarationEnsure(ntree, node);
- node->declaration->build(*ntree, *node);
+ node_verify_sockets(ntree, node, true);
return;
}
bNodeSocketTemplate *sockdef;
@@ -1141,15 +1158,15 @@ static void ntree_set_typeinfo(bNodeTree *ntree, bNodeTreeType *typeinfo)
{
if (typeinfo) {
ntree->typeinfo = typeinfo;
-
- /* deprecated integer type */
- ntree->type = typeinfo->type;
}
else {
ntree->typeinfo = &NodeTreeTypeUndefined;
ntree->init &= ~NTREE_TYPE_INIT;
}
+
+ /* Deprecated integer type. */
+ ntree->type = ntree->typeinfo->type;
}
static void node_set_typeinfo(const struct bContext *C,
@@ -1523,7 +1540,7 @@ static bNodeSocket *make_socket(bNodeTree *ntree,
}
/* make the identifier unique */
BLI_uniquename_cb(
- unique_identifier_check, lb, "socket", '.', auto_identifier, sizeof(auto_identifier));
+ unique_identifier_check, lb, "socket", '_', auto_identifier, sizeof(auto_identifier));
bNodeSocket *sock = (bNodeSocket *)MEM_callocN(sizeof(bNodeSocket), "sock");
sock->in_out = in_out;
@@ -3975,8 +3992,10 @@ int nodeSocketIsHidden(const bNodeSocket *sock)
return ((sock->flag & (SOCK_HIDDEN | SOCK_UNAVAIL)) != 0);
}
-void nodeSetSocketAvailability(bNodeSocket *sock, bool is_available)
+void nodeSetSocketAvailability(bNodeTree *UNUSED(ntree), bNodeSocket *sock, bool is_available)
{
+ /* #ntree is not needed right now, but it's generally necessary when changing the tree because we
+ * want to tag it as changed in the future. */
if (is_available) {
sock->flag &= ~SOCK_UNAVAIL;
}
@@ -3999,17 +4018,38 @@ int nodeSocketLinkLimit(const bNodeSocket *sock)
return sock->limit;
}
+static void update_socket_declarations(ListBase *sockets,
+ Span<blender::nodes::SocketDeclarationPtr> declarations)
+{
+ int index;
+ LISTBASE_FOREACH_INDEX (bNodeSocket *, socket, sockets, index) {
+ const SocketDeclaration &socket_decl = *declarations[index];
+ socket->declaration = &socket_decl;
+ }
+}
+
/**
- * If the node implements a `declare` function, this function makes sure that `node->declaration`
- * is up to date.
+ * Update `socket->declaration` for all sockets in the node. This assumes that the node declaration
+ * and sockets are up to date already.
*/
-void nodeDeclarationEnsure(bNodeTree *UNUSED(ntree), bNode *node)
+void nodeSocketDeclarationsUpdate(bNode *node)
+{
+ BLI_assert(node->declaration != nullptr);
+ update_socket_declarations(&node->inputs, node->declaration->inputs());
+ update_socket_declarations(&node->outputs, node->declaration->outputs());
+}
+
+/**
+ * Just update `node->declaration` if necessary. This can also be called on nodes that may not be
+ * up to date (e.g. because the need versioning or are dynamic).
+ */
+bool nodeDeclarationEnsureOnOutdatedNode(bNodeTree *UNUSED(ntree), bNode *node)
{
if (node->declaration != nullptr) {
- return;
+ return false;
}
if (node->typeinfo->declare == nullptr) {
- return;
+ return false;
}
if (node->typeinfo->declaration_is_dynamic) {
node->declaration = new blender::nodes::NodeDeclaration();
@@ -4021,6 +4061,20 @@ void nodeDeclarationEnsure(bNodeTree *UNUSED(ntree), bNode *node)
BLI_assert(node->typeinfo->fixed_declaration != nullptr);
node->declaration = node->typeinfo->fixed_declaration;
}
+ return true;
+}
+
+/**
+ * If the node implements a `declare` function, this function makes sure that `node->declaration`
+ * is up to date. It is expected that the sockets of the node are up to date already.
+ */
+bool nodeDeclarationEnsure(bNodeTree *ntree, bNode *node)
+{
+ if (nodeDeclarationEnsureOnOutdatedNode(ntree, node)) {
+ nodeSocketDeclarationsUpdate(node);
+ return true;
+ }
+ return false;
}
/* ************** Node Clipboard *********** */
@@ -4492,18 +4546,6 @@ void ntreeUpdateAllNew(Main *main)
FOREACH_NODETREE_END;
}
-static FieldInferencingInterface *node_field_inferencing_interface_copy(
- const FieldInferencingInterface &field_inferencing_interface)
-{
- return new FieldInferencingInterface(field_inferencing_interface);
-}
-
-static void node_field_inferencing_interface_free(
- const FieldInferencingInterface *field_inferencing_interface)
-{
- delete field_inferencing_interface;
-}
-
namespace blender::bke::node_field_inferencing {
static bool is_field_socket_type(eNodeSocketDatatype type)
@@ -5195,9 +5237,8 @@ bool nodeUpdateID(bNodeTree *ntree, ID *id)
void nodeUpdateInternalLinks(bNodeTree *ntree, bNode *node)
{
BLI_freelistN(&node->internal_links);
-
- if (node->typeinfo && node->typeinfo->update_internal_links) {
- node->typeinfo->update_internal_links(ntree, node);
+ if (!node->typeinfo->no_muting) {
+ node_internal_links_create(ntree, node);
}
}
@@ -5462,12 +5503,6 @@ void node_type_gpu(struct bNodeType *ntype, NodeGPUExecFunction gpu_fn)
ntype->gpu_fn = gpu_fn;
}
-void node_type_internal_links(bNodeType *ntype,
- void (*update_internal_links)(bNodeTree *, bNode *))
-{
- ntype->update_internal_links = update_internal_links;
-}
-
/* callbacks for undefined types */
static bool node_undefined_poll(bNodeType *UNUSED(ntype),
@@ -5485,6 +5520,7 @@ static void register_undefined_types()
* they are just used as placeholders in case the actual types are not registered.
*/
+ NodeTreeTypeUndefined.type = NTREE_UNDEFINED;
strcpy(NodeTreeTypeUndefined.idname, "NodeTreeUndefined");
strcpy(NodeTreeTypeUndefined.ui_name, N_("Undefined"));
strcpy(NodeTreeTypeUndefined.ui_description, N_("Undefined Node Tree Type"));
diff --git a/source/blender/blenkernel/intern/object.cc b/source/blender/blenkernel/intern/object.cc
index 4b01ee29828..b2dd4b40bae 100644
--- a/source/blender/blenkernel/intern/object.cc
+++ b/source/blender/blenkernel/intern/object.cc
@@ -160,11 +160,10 @@
static CLG_LogRef LOG = {"bke.object"};
/**
- * Vertex parent modifies original BMesh which is not safe for threading.
+ * NOTE(@sergey): Vertex parent modifies original #BMesh which is not safe for threading.
* Ideally such a modification should be handled as a separate DAG update
- * callback for mesh datablock, but for until it is actually supported use
+ * callback for mesh data-block, but for until it is actually supported use
* simpler solution with a mutex lock.
- * - sergey -
*/
#define VPARENT_THREADING_HACK
@@ -390,7 +389,8 @@ static void library_foreach_modifiersForeachIDLink(void *user_data,
int cb_flag)
{
LibraryForeachIDData *data = (LibraryForeachIDData *)user_data;
- BKE_lib_query_foreachid_process(data, id_pointer, cb_flag);
+ BKE_LIB_FOREACHID_PROCESS_FUNCTION_CALL(
+ data, BKE_lib_query_foreachid_process(data, id_pointer, cb_flag));
}
static void library_foreach_gpencil_modifiersForeachIDLink(void *user_data,
@@ -399,7 +399,8 @@ static void library_foreach_gpencil_modifiersForeachIDLink(void *user_data,
int cb_flag)
{
LibraryForeachIDData *data = (LibraryForeachIDData *)user_data;
- BKE_lib_query_foreachid_process(data, id_pointer, cb_flag);
+ BKE_LIB_FOREACHID_PROCESS_FUNCTION_CALL(
+ data, BKE_lib_query_foreachid_process(data, id_pointer, cb_flag));
}
static void library_foreach_shaderfxForeachIDLink(void *user_data,
@@ -408,7 +409,8 @@ static void library_foreach_shaderfxForeachIDLink(void *user_data,
int cb_flag)
{
LibraryForeachIDData *data = (LibraryForeachIDData *)user_data;
- BKE_lib_query_foreachid_process(data, id_pointer, cb_flag);
+ BKE_LIB_FOREACHID_PROCESS_FUNCTION_CALL(
+ data, BKE_lib_query_foreachid_process(data, id_pointer, cb_flag));
}
static void library_foreach_constraintObjectLooper(bConstraint *UNUSED(con),
@@ -418,7 +420,8 @@ static void library_foreach_constraintObjectLooper(bConstraint *UNUSED(con),
{
LibraryForeachIDData *data = (LibraryForeachIDData *)user_data;
const int cb_flag = is_reference ? IDWALK_CB_USER : IDWALK_CB_NOP;
- BKE_lib_query_foreachid_process(data, id_pointer, cb_flag);
+ BKE_LIB_FOREACHID_PROCESS_FUNCTION_CALL(
+ data, BKE_lib_query_foreachid_process(data, id_pointer, cb_flag));
}
static void library_foreach_particlesystemsObjectLooper(ParticleSystem *UNUSED(psys),
@@ -427,7 +430,8 @@ static void library_foreach_particlesystemsObjectLooper(ParticleSystem *UNUSED(p
int cb_flag)
{
LibraryForeachIDData *data = (LibraryForeachIDData *)user_data;
- BKE_lib_query_foreachid_process(data, id_pointer, cb_flag);
+ BKE_LIB_FOREACHID_PROCESS_FUNCTION_CALL(
+ data, BKE_lib_query_foreachid_process(data, id_pointer, cb_flag));
}
static void object_foreach_id(ID *id, LibraryForeachIDData *data)
@@ -494,10 +498,18 @@ static void object_foreach_id(ID *id, LibraryForeachIDData *data)
const int cb_flag_orig = BKE_lib_query_foreachid_process_callback_flag_override(
data, proxy_cb_flag, false);
LISTBASE_FOREACH (bPoseChannel *, pchan, &object->pose->chanbase) {
- IDP_foreach_property(
- pchan->prop, IDP_TYPE_FILTER_ID, BKE_lib_query_idpropertiesForeachIDLink_callback, data);
+ BKE_LIB_FOREACHID_PROCESS_FUNCTION_CALL(
+ data,
+ IDP_foreach_property(pchan->prop,
+ IDP_TYPE_FILTER_ID,
+ BKE_lib_query_idpropertiesForeachIDLink_callback,
+ data));
+
BKE_LIB_FOREACHID_PROCESS_IDSUPER(data, pchan->custom, IDWALK_CB_USER);
- BKE_constraints_id_loop(&pchan->constraints, library_foreach_constraintObjectLooper, data);
+ BKE_LIB_FOREACHID_PROCESS_FUNCTION_CALL(
+ data,
+ BKE_constraints_id_loop(
+ &pchan->constraints, library_foreach_constraintObjectLooper, data));
}
BKE_lib_query_foreachid_process_callback_flag_override(data, cb_flag_orig, true);
}
@@ -509,14 +521,21 @@ static void object_foreach_id(ID *id, LibraryForeachIDData *data)
data, object->rigidbody_constraint->ob2, IDWALK_CB_NEVER_SELF);
}
- BKE_modifiers_foreach_ID_link(object, library_foreach_modifiersForeachIDLink, data);
- BKE_gpencil_modifiers_foreach_ID_link(
- object, library_foreach_gpencil_modifiersForeachIDLink, data);
- BKE_constraints_id_loop(&object->constraints, library_foreach_constraintObjectLooper, data);
- BKE_shaderfx_foreach_ID_link(object, library_foreach_shaderfxForeachIDLink, data);
+ BKE_LIB_FOREACHID_PROCESS_FUNCTION_CALL(
+ data, BKE_modifiers_foreach_ID_link(object, library_foreach_modifiersForeachIDLink, data));
+ BKE_LIB_FOREACHID_PROCESS_FUNCTION_CALL(
+ data,
+ BKE_gpencil_modifiers_foreach_ID_link(
+ object, library_foreach_gpencil_modifiersForeachIDLink, data));
+ BKE_LIB_FOREACHID_PROCESS_FUNCTION_CALL(
+ data,
+ BKE_constraints_id_loop(&object->constraints, library_foreach_constraintObjectLooper, data));
+ BKE_LIB_FOREACHID_PROCESS_FUNCTION_CALL(
+ data, BKE_shaderfx_foreach_ID_link(object, library_foreach_shaderfxForeachIDLink, data));
LISTBASE_FOREACH (ParticleSystem *, psys, &object->particlesystem) {
- BKE_particlesystem_id_loop(psys, library_foreach_particlesystemsObjectLooper, data);
+ BKE_LIB_FOREACHID_PROCESS_FUNCTION_CALL(
+ data, BKE_particlesystem_id_loop(psys, library_foreach_particlesystemsObjectLooper, data));
}
if (object->soft) {
@@ -1204,7 +1223,7 @@ static IDProperty *object_asset_dimensions_property(Object *ob)
return nullptr;
}
- IDPropertyTemplate idprop = {0};
+ IDPropertyTemplate idprop{};
idprop.array.len = ARRAY_SIZE(dimensions);
idprop.array.type = IDP_FLOAT;
@@ -1747,24 +1766,24 @@ static void object_update_from_subsurf_ccg(Object *object)
/* NOTE: we need to reshape into an original mesh from main database,
* allowing:
*
- * - Update copies of that mesh at any moment.
- * - Save the file without doing extra reshape.
- * - All the users of the mesh have updated displacement.
+ * - Update copies of that mesh at any moment.
+ * - Save the file without doing extra reshape.
+ * - All the users of the mesh have updated displacement.
*
* However, the tricky part here is that we only know about sculpted
* state of a mesh on an object level, and object is being updated after
- * mesh datablock is updated. This forces us to:
+ * mesh data-block is updated. This forces us to:
*
- * - Update mesh datablock from object evaluation, which is technically
- * forbidden, but there is no other place for this yet.
- * - Reshape to the original mesh from main database, and then copy updated
- * layer to copy of that mesh (since copy of the mesh has decoupled
- * custom data layers).
+ * - Update mesh data-block from object evaluation, which is technically
+ * forbidden, but there is no other place for this yet.
+ * - Reshape to the original mesh from main database, and then copy updated
+ * layer to copy of that mesh (since copy of the mesh has decoupled
+ * custom data layers).
*
* All this is defeating all the designs we need to follow to allow safe
* threaded evaluation, but this is as good as we can make it within the
* current sculpt/evaluated mesh design. This is also how we've survived
- * with old DerivedMesh based solutions. So, while this is all wrong and
+ * with old #DerivedMesh based solutions. So, while this is all wrong and
* needs reconsideration, doesn't seem to be a big stopper for real
* production artists.
*/
@@ -1803,7 +1822,7 @@ void BKE_object_eval_assign_data(Object *object_eval, ID *data_eval, bool is_own
object_eval->runtime.data_eval = data_eval;
object_eval->runtime.is_data_eval_owned = is_owned;
- /* Overwrite data of evaluated object, if the datablock types match. */
+ /* Overwrite data of evaluated object, if the data-block types match. */
ID *data = (ID *)object_eval->data;
if (GS(data->name) == GS(data_eval->name)) {
/* NOTE: we are not supposed to invoke evaluation for original objects,
@@ -1845,8 +1864,8 @@ void BKE_object_free_derived_caches(Object *ob)
ob->runtime.mesh_deform_eval = nullptr;
}
- /* Restore initial pointer for copy-on-write datablocks, object->data
- * might be pointing to an evaluated datablock data was just freed above. */
+ /* Restore initial pointer for copy-on-write data-blocks, object->data
+ * might be pointing to an evaluated data-block data was just freed above. */
if (ob->runtime.data_orig != nullptr) {
ob->data = ob->runtime.data_orig;
}
@@ -2345,13 +2364,13 @@ Object *BKE_object_add_from(
}
/**
- * Add a new object, but assign the given datablock as the ob->data
+ * Add a new object, but assign the given data-block as the `ob->data`
* for the newly created object.
*
- * \param data: The datablock to assign as ob->data for the new object.
- * This is assumed to be of the correct type.
- * \param do_id_user: If true, id_us_plus() will be called on data when
- * assigning it to the object.
+ * \param data: The data-block to assign as `ob->data` for the new object.
+ * This is assumed to be of the correct type.
+ * \param do_id_user: If true, #id_us_plus() will be called on data when
+ * assigning it to the object.
*/
Object *BKE_object_add_for_data(
Main *bmain, ViewLayer *view_layer, int type, const char *name, ID *data, bool do_id_user)
@@ -2616,7 +2635,7 @@ Object **BKE_object_pose_array_get_ex(ViewLayer *view_layer,
Object *ob_pose = BKE_object_pose_armature_get(ob_active);
Object **objects = nullptr;
if (ob_pose == ob_active) {
- ObjectsInModeParams ob_params = {0};
+ ObjectsInModeParams ob_params{};
ob_params.object_mode = OB_MODE_POSE;
ob_params.no_dup_data = unique;
@@ -2663,7 +2682,7 @@ Base **BKE_object_pose_base_array_get_ex(ViewLayer *view_layer,
}
if (base_active && (base_pose == base_active)) {
- ObjectsInModeParams ob_params = {0};
+ ObjectsInModeParams ob_params{};
ob_params.object_mode = OB_MODE_POSE;
ob_params.no_dup_data = unique;
@@ -2851,7 +2870,7 @@ Object *BKE_object_duplicate(Main *bmain, Object *ob, uint dupflag, uint duplica
if (!is_subprocess) {
/* This code will follow into all ID links using an ID tagged with LIB_TAG_NEW. */
- BKE_libblock_relink_to_newid((ID *)&obn->id);
+ BKE_libblock_relink_to_newid(bmain, &obn->id, 0);
#ifndef NDEBUG
/* Call to `BKE_libblock_relink_to_newid` above is supposed to have cleared all those flags. */
@@ -4285,7 +4304,7 @@ void BKE_object_foreach_display_point(Object *ob,
}
}
else if (ob->type == OB_GPENCIL) {
- GPencilStrokePointIterData iter_data = {nullptr};
+ GPencilStrokePointIterData iter_data{};
iter_data.obmat = obmat;
iter_data.point_func_cb = func_cb;
iter_data.user_data = user_data;
@@ -4323,28 +4342,18 @@ void BKE_scene_foreach_display_point(Depsgraph *depsgraph,
}
/**
- * Struct members from DNA_object_types.h
+ * See struct members from #Object in DNA_object_types.h
*/
struct ObTfmBack {
float loc[3], dloc[3];
- /** scale and delta scale. */
float scale[3], dscale[3];
- /** euler rotation. */
float rot[3], drot[3];
- /** quaternion rotation. */
float quat[4], dquat[4];
- /** axis angle rotation - axis part. */
float rotAxis[3], drotAxis[3];
- /** axis angle rotation - angle part. */
float rotAngle, drotAngle;
- /** final worldspace matrix with constraints & animsys applied. */
float obmat[4][4];
- /** inverse result of parent, so that object doesn't 'stick' to parent. */
float parentinv[4][4];
- /** inverse result of constraints. doesn't include effect of parent or object local transform.
- */
float constinv[4][4];
- /** inverse matrix of 'obmat' for during render, temporally: ipokeys of transform. */
float imat[4][4];
};
@@ -5401,7 +5410,7 @@ void BKE_object_groups_clear(Main *bmain, Scene *scene, Object *ob)
}
/**
- * Return a KDTree_3d from the deformed object (in worldspace)
+ * Return a KDTree_3d from the deformed object (in world-space).
*
* \note Only mesh objects currently support deforming, others are TODO.
*
@@ -5427,7 +5436,7 @@ KDTree_3d *BKE_object_as_kdtree(Object *ob, int *r_tot)
MVert *mvert = me_eval->mvert;
uint totvert = me_eval->totvert;
- /* tree over-allocs in case where some verts have ORIGINDEX_NONE */
+ /* Tree over-allocates in case where some verts have #ORIGINDEX_NONE. */
tot = 0;
tree = BLI_kdtree_3d_new(totvert);
diff --git a/source/blender/blenkernel/intern/particle.c b/source/blender/blenkernel/intern/particle.c
index b13fd8a395f..b158633294e 100644
--- a/source/blender/blenkernel/intern/particle.c
+++ b/source/blender/blenkernel/intern/particle.c
@@ -180,7 +180,8 @@ static void particle_settings_foreach_id(ID *id, LibraryForeachIDData *data)
for (int i = 0; i < MAX_MTEX; i++) {
if (psett->mtex[i]) {
- BKE_texture_mtex_foreach_id(data, psett->mtex[i]);
+ BKE_LIB_FOREACHID_PROCESS_FUNCTION_CALL(data,
+ BKE_texture_mtex_foreach_id(data, psett->mtex[i]));
}
}
diff --git a/source/blender/blenkernel/intern/pbvh.c b/source/blender/blenkernel/intern/pbvh.c
index 3358f3e6dea..2318a05e635 100644
--- a/source/blender/blenkernel/intern/pbvh.c
+++ b/source/blender/blenkernel/intern/pbvh.c
@@ -2798,7 +2798,7 @@ float (*BKE_pbvh_vert_coords_alloc(PBVH *pbvh))[3]
void BKE_pbvh_vert_coords_apply(PBVH *pbvh, const float (*vertCos)[3], const int totvert)
{
if (totvert != pbvh->totvert) {
- BLI_assert_msg(0, "PBVH: Given deforming vcos number does not natch PBVH vertex number!");
+ BLI_assert_msg(0, "PBVH: Given deforming vcos number does not match PBVH vertex number!");
return;
}
diff --git a/source/blender/blenkernel/intern/scene.c b/source/blender/blenkernel/intern/scene.c
index 0aeee11ed17..a0bd3abbc1a 100644
--- a/source/blender/blenkernel/intern/scene.c
+++ b/source/blender/blenkernel/intern/scene.c
@@ -471,7 +471,8 @@ static void scene_foreach_rigidbodyworldSceneLooper(struct RigidBodyWorld *UNUSE
int cb_flag)
{
LibraryForeachIDData *data = (LibraryForeachIDData *)user_data;
- BKE_lib_query_foreachid_process(data, id_pointer, cb_flag);
+ BKE_LIB_FOREACHID_PROCESS_FUNCTION_CALL(
+ data, BKE_lib_query_foreachid_process(data, id_pointer, cb_flag));
}
/**
@@ -522,7 +523,10 @@ static void scene_foreach_toolsettings_id_pointer_process(
}
}
-#define BKE_LIB_FOREACHID_UNDO_PRESERVE_PROCESS( \
+/* Special handling is needed here, as `scene_foreach_toolsettings` (and its dependency
+ * `scene_foreach_paint`) are also used by `scene_undo_preserve`, where `LibraryForeachIDData
+ * *data` is NULL. */
+#define BKE_LIB_FOREACHID_UNDO_PRESERVE_PROCESS_IDSUPER( \
__data, __id, __do_undo_restore, __action, __reader, __id_old, __cb_flag) \
{ \
if (__do_undo_restore) { \
@@ -530,24 +534,38 @@ static void scene_foreach_toolsettings_id_pointer_process(
(ID **)&(__id), __action, __reader, (ID **)&(__id_old), __cb_flag); \
} \
else { \
+ BLI_assert((__data) != NULL); \
BKE_LIB_FOREACHID_PROCESS_IDSUPER(__data, __id, __cb_flag); \
} \
} \
(void)0
+#define BKE_LIB_FOREACHID_UNDO_PRESERVE_PROCESS_FUNCTION_CALL( \
+ __data, __do_undo_restore, __func_call) \
+ { \
+ if (__do_undo_restore) { \
+ __func_call; \
+ } \
+ else { \
+ BLI_assert((__data) != NULL); \
+ BKE_LIB_FOREACHID_PROCESS_FUNCTION_CALL(__data, __func_call); \
+ } \
+ } \
+ (void)0
+
static void scene_foreach_paint(LibraryForeachIDData *data,
Paint *paint,
const bool do_undo_restore,
BlendLibReader *reader,
Paint *paint_old)
{
- BKE_LIB_FOREACHID_UNDO_PRESERVE_PROCESS(data,
- paint->brush,
- do_undo_restore,
- SCENE_FOREACH_UNDO_RESTORE,
- reader,
- paint_old->brush,
- IDWALK_CB_USER);
+ BKE_LIB_FOREACHID_UNDO_PRESERVE_PROCESS_IDSUPER(data,
+ paint->brush,
+ do_undo_restore,
+ SCENE_FOREACH_UNDO_RESTORE,
+ reader,
+ paint_old->brush,
+ IDWALK_CB_USER);
for (int i = 0; i < paint_old->tool_slots_len; i++) {
/* This is a bit tricky.
* - In case we do not do `undo_restore`, `paint` and `paint_old` pointers are the same, so
@@ -559,21 +577,21 @@ static void scene_foreach_paint(LibraryForeachIDData *data,
*/
Brush *brush_tmp = NULL;
Brush **brush_p = i < paint->tool_slots_len ? &paint->tool_slots[i].brush : &brush_tmp;
- BKE_LIB_FOREACHID_UNDO_PRESERVE_PROCESS(data,
- *brush_p,
- do_undo_restore,
- SCENE_FOREACH_UNDO_RESTORE,
- reader,
- paint_old->brush,
- IDWALK_CB_USER);
- }
- BKE_LIB_FOREACHID_UNDO_PRESERVE_PROCESS(data,
- paint->palette,
- do_undo_restore,
- SCENE_FOREACH_UNDO_RESTORE,
- reader,
- paint_old->palette,
- IDWALK_CB_USER);
+ BKE_LIB_FOREACHID_UNDO_PRESERVE_PROCESS_IDSUPER(data,
+ *brush_p,
+ do_undo_restore,
+ SCENE_FOREACH_UNDO_RESTORE,
+ reader,
+ paint_old->brush,
+ IDWALK_CB_USER);
+ }
+ BKE_LIB_FOREACHID_UNDO_PRESERVE_PROCESS_IDSUPER(data,
+ paint->palette,
+ do_undo_restore,
+ SCENE_FOREACH_UNDO_RESTORE,
+ reader,
+ paint_old->palette,
+ IDWALK_CB_USER);
}
static void scene_foreach_toolsettings(LibraryForeachIDData *data,
@@ -582,110 +600,152 @@ static void scene_foreach_toolsettings(LibraryForeachIDData *data,
BlendLibReader *reader,
ToolSettings *toolsett_old)
{
- BKE_LIB_FOREACHID_UNDO_PRESERVE_PROCESS(data,
- toolsett->particle.scene,
- do_undo_restore,
- SCENE_FOREACH_UNDO_NO_RESTORE,
- reader,
- toolsett_old->particle.scene,
- IDWALK_CB_NOP);
- BKE_LIB_FOREACHID_UNDO_PRESERVE_PROCESS(data,
- toolsett->particle.object,
- do_undo_restore,
- SCENE_FOREACH_UNDO_NO_RESTORE,
- reader,
- toolsett_old->particle.object,
- IDWALK_CB_NOP);
- BKE_LIB_FOREACHID_UNDO_PRESERVE_PROCESS(data,
- toolsett->particle.shape_object,
- do_undo_restore,
- SCENE_FOREACH_UNDO_NO_RESTORE,
- reader,
- toolsett_old->particle.shape_object,
- IDWALK_CB_NOP);
+ BKE_LIB_FOREACHID_UNDO_PRESERVE_PROCESS_IDSUPER(data,
+ toolsett->particle.scene,
+ do_undo_restore,
+ SCENE_FOREACH_UNDO_NO_RESTORE,
+ reader,
+ toolsett_old->particle.scene,
+ IDWALK_CB_NOP);
+ BKE_LIB_FOREACHID_UNDO_PRESERVE_PROCESS_IDSUPER(data,
+ toolsett->particle.object,
+ do_undo_restore,
+ SCENE_FOREACH_UNDO_NO_RESTORE,
+ reader,
+ toolsett_old->particle.object,
+ IDWALK_CB_NOP);
+ BKE_LIB_FOREACHID_UNDO_PRESERVE_PROCESS_IDSUPER(data,
+ toolsett->particle.shape_object,
+ do_undo_restore,
+ SCENE_FOREACH_UNDO_NO_RESTORE,
+ reader,
+ toolsett_old->particle.shape_object,
+ IDWALK_CB_NOP);
scene_foreach_paint(
data, &toolsett->imapaint.paint, do_undo_restore, reader, &toolsett_old->imapaint.paint);
- BKE_LIB_FOREACHID_UNDO_PRESERVE_PROCESS(data,
- toolsett->imapaint.stencil,
- do_undo_restore,
- SCENE_FOREACH_UNDO_RESTORE,
- reader,
- toolsett_old->imapaint.stencil,
- IDWALK_CB_USER);
- BKE_LIB_FOREACHID_UNDO_PRESERVE_PROCESS(data,
- toolsett->imapaint.clone,
- do_undo_restore,
- SCENE_FOREACH_UNDO_RESTORE,
- reader,
- toolsett_old->imapaint.clone,
- IDWALK_CB_USER);
- BKE_LIB_FOREACHID_UNDO_PRESERVE_PROCESS(data,
- toolsett->imapaint.canvas,
- do_undo_restore,
- SCENE_FOREACH_UNDO_RESTORE,
- reader,
- toolsett_old->imapaint.canvas,
- IDWALK_CB_USER);
+ BKE_LIB_FOREACHID_UNDO_PRESERVE_PROCESS_IDSUPER(data,
+ toolsett->imapaint.stencil,
+ do_undo_restore,
+ SCENE_FOREACH_UNDO_RESTORE,
+ reader,
+ toolsett_old->imapaint.stencil,
+ IDWALK_CB_USER);
+ BKE_LIB_FOREACHID_UNDO_PRESERVE_PROCESS_IDSUPER(data,
+ toolsett->imapaint.clone,
+ do_undo_restore,
+ SCENE_FOREACH_UNDO_RESTORE,
+ reader,
+ toolsett_old->imapaint.clone,
+ IDWALK_CB_USER);
+ BKE_LIB_FOREACHID_UNDO_PRESERVE_PROCESS_IDSUPER(data,
+ toolsett->imapaint.canvas,
+ do_undo_restore,
+ SCENE_FOREACH_UNDO_RESTORE,
+ reader,
+ toolsett_old->imapaint.canvas,
+ IDWALK_CB_USER);
if (toolsett->vpaint) {
- scene_foreach_paint(
- data, &toolsett->vpaint->paint, do_undo_restore, reader, &toolsett_old->vpaint->paint);
+ BKE_LIB_FOREACHID_UNDO_PRESERVE_PROCESS_FUNCTION_CALL(
+ data,
+ do_undo_restore,
+ scene_foreach_paint(data,
+ &toolsett->vpaint->paint,
+ do_undo_restore,
+ reader,
+ &toolsett_old->vpaint->paint));
}
if (toolsett->wpaint) {
- scene_foreach_paint(
- data, &toolsett->wpaint->paint, do_undo_restore, reader, &toolsett_old->wpaint->paint);
+ BKE_LIB_FOREACHID_UNDO_PRESERVE_PROCESS_FUNCTION_CALL(
+ data,
+ do_undo_restore,
+ scene_foreach_paint(data,
+ &toolsett->wpaint->paint,
+ do_undo_restore,
+ reader,
+ &toolsett_old->wpaint->paint));
}
if (toolsett->sculpt) {
- scene_foreach_paint(
- data, &toolsett->sculpt->paint, do_undo_restore, reader, &toolsett_old->sculpt->paint);
- BKE_LIB_FOREACHID_UNDO_PRESERVE_PROCESS(data,
- toolsett->sculpt->gravity_object,
- do_undo_restore,
- SCENE_FOREACH_UNDO_NO_RESTORE,
- reader,
- toolsett_old->sculpt->gravity_object,
- IDWALK_CB_NOP);
+ BKE_LIB_FOREACHID_UNDO_PRESERVE_PROCESS_FUNCTION_CALL(
+ data,
+ do_undo_restore,
+ scene_foreach_paint(data,
+ &toolsett->sculpt->paint,
+ do_undo_restore,
+ reader,
+ &toolsett_old->sculpt->paint));
+ BKE_LIB_FOREACHID_UNDO_PRESERVE_PROCESS_IDSUPER(data,
+ toolsett->sculpt->gravity_object,
+ do_undo_restore,
+ SCENE_FOREACH_UNDO_NO_RESTORE,
+ reader,
+ toolsett_old->sculpt->gravity_object,
+ IDWALK_CB_NOP);
}
if (toolsett->uvsculpt) {
- scene_foreach_paint(
- data, &toolsett->uvsculpt->paint, do_undo_restore, reader, &toolsett_old->uvsculpt->paint);
+ BKE_LIB_FOREACHID_UNDO_PRESERVE_PROCESS_FUNCTION_CALL(
+ data,
+ do_undo_restore,
+ scene_foreach_paint(data,
+ &toolsett->uvsculpt->paint,
+ do_undo_restore,
+ reader,
+ &toolsett_old->uvsculpt->paint));
}
if (toolsett->gp_paint) {
- scene_foreach_paint(
- data, &toolsett->gp_paint->paint, do_undo_restore, reader, &toolsett_old->gp_paint->paint);
+ BKE_LIB_FOREACHID_UNDO_PRESERVE_PROCESS_FUNCTION_CALL(
+ data,
+ do_undo_restore,
+ scene_foreach_paint(data,
+ &toolsett->gp_paint->paint,
+ do_undo_restore,
+ reader,
+ &toolsett_old->gp_paint->paint));
}
if (toolsett->gp_vertexpaint) {
- scene_foreach_paint(data,
- &toolsett->gp_vertexpaint->paint,
- do_undo_restore,
- reader,
- &toolsett_old->gp_vertexpaint->paint);
+ BKE_LIB_FOREACHID_UNDO_PRESERVE_PROCESS_FUNCTION_CALL(
+ data,
+ do_undo_restore,
+ scene_foreach_paint(data,
+ &toolsett->gp_vertexpaint->paint,
+ do_undo_restore,
+ reader,
+ &toolsett_old->gp_vertexpaint->paint));
}
if (toolsett->gp_sculptpaint) {
- scene_foreach_paint(data,
- &toolsett->gp_sculptpaint->paint,
- do_undo_restore,
- reader,
- &toolsett_old->gp_sculptpaint->paint);
+ BKE_LIB_FOREACHID_UNDO_PRESERVE_PROCESS_FUNCTION_CALL(
+ data,
+ do_undo_restore,
+ scene_foreach_paint(data,
+ &toolsett->gp_sculptpaint->paint,
+ do_undo_restore,
+ reader,
+ &toolsett_old->gp_sculptpaint->paint));
}
if (toolsett->gp_weightpaint) {
- scene_foreach_paint(data,
- &toolsett->gp_weightpaint->paint,
- do_undo_restore,
- reader,
- &toolsett_old->gp_weightpaint->paint);
+ BKE_LIB_FOREACHID_UNDO_PRESERVE_PROCESS_FUNCTION_CALL(
+ data,
+ do_undo_restore,
+ scene_foreach_paint(data,
+ &toolsett->gp_weightpaint->paint,
+ do_undo_restore,
+ reader,
+ &toolsett_old->gp_weightpaint->paint));
}
- BKE_LIB_FOREACHID_UNDO_PRESERVE_PROCESS(data,
- toolsett->gp_sculpt.guide.reference_object,
- do_undo_restore,
- SCENE_FOREACH_UNDO_NO_RESTORE,
- reader,
- toolsett_old->gp_sculpt.guide.reference_object,
- IDWALK_CB_NOP);
+ BKE_LIB_FOREACHID_UNDO_PRESERVE_PROCESS_IDSUPER(data,
+ toolsett->gp_sculpt.guide.reference_object,
+ do_undo_restore,
+ SCENE_FOREACH_UNDO_NO_RESTORE,
+ reader,
+ toolsett_old->gp_sculpt.guide.reference_object,
+ IDWALK_CB_NOP);
}
+#undef BKE_LIB_FOREACHID_UNDO_PRESERVE_PROCESS_IDSUPER
+#undef BKE_LIB_FOREACHID_UNDO_PRESERVE_PROCESS_FUNCTION_CALL
+
static void scene_foreach_layer_collection(LibraryForeachIDData *data, ListBase *lb)
{
LISTBASE_FOREACH (LayerCollection *, lc, lb) {
@@ -707,7 +767,8 @@ static bool seq_foreach_member_id_cb(Sequence *seq, void *user_data)
#define FOREACHID_PROCESS_IDSUPER(_data, _id_super, _cb_flag) \
{ \
CHECK_TYPE(&((_id_super)->id), ID *); \
- if (!BKE_lib_query_foreachid_process((_data), (ID **)&(_id_super), (_cb_flag))) { \
+ BKE_lib_query_foreachid_process((_data), (ID **)&(_id_super), (_cb_flag)); \
+ if (BKE_lib_query_foreachid_iter_stop((_data))) { \
return false; \
} \
} \
@@ -746,15 +807,18 @@ static void scene_foreach_id(ID *id, LibraryForeachIDData *data)
BKE_LIB_FOREACHID_PROCESS_IDSUPER(data, scene->r.bake.cage_object, IDWALK_CB_NOP);
if (scene->nodetree) {
/* nodetree **are owned by IDs**, treat them as mere sub-data and not real ID! */
- BKE_library_foreach_ID_embedded(data, (ID **)&scene->nodetree);
+ BKE_LIB_FOREACHID_PROCESS_FUNCTION_CALL(
+ data, BKE_library_foreach_ID_embedded(data, (ID **)&scene->nodetree));
}
if (scene->ed) {
- SEQ_for_each_callback(&scene->ed->seqbase, seq_foreach_member_id_cb, data);
+ BKE_LIB_FOREACHID_PROCESS_FUNCTION_CALL(
+ data, SEQ_for_each_callback(&scene->ed->seqbase, seq_foreach_member_id_cb, data));
}
/* This pointer can be NULL during old files reading, better be safe than sorry. */
if (scene->master_collection != NULL) {
- BKE_library_foreach_ID_embedded(data, (ID **)&scene->master_collection);
+ BKE_LIB_FOREACHID_PROCESS_FUNCTION_CALL(
+ data, BKE_library_foreach_ID_embedded(data, (ID **)&scene->master_collection));
}
LISTBASE_FOREACH (ViewLayer *, view_layer, &scene->view_layers) {
@@ -765,7 +829,8 @@ static void scene_foreach_id(ID *id, LibraryForeachIDData *data)
data, base->object, IDWALK_CB_NOP | IDWALK_CB_OVERRIDE_LIBRARY_NOT_OVERRIDABLE);
}
- scene_foreach_layer_collection(data, &view_layer->layer_collections);
+ BKE_LIB_FOREACHID_PROCESS_FUNCTION_CALL(
+ data, scene_foreach_layer_collection(data, &view_layer->layer_collections));
LISTBASE_FOREACH (FreestyleModuleConfig *, fmc, &view_layer->freestyle_config.modules) {
if (fmc->script) {
@@ -786,18 +851,25 @@ static void scene_foreach_id(ID *id, LibraryForeachIDData *data)
LISTBASE_FOREACH (TimeMarker *, marker, &scene->markers) {
BKE_LIB_FOREACHID_PROCESS_IDSUPER(data, marker->camera, IDWALK_CB_NOP);
- IDP_foreach_property(
- marker->prop, IDP_TYPE_FILTER_ID, BKE_lib_query_idpropertiesForeachIDLink_callback, data);
+ BKE_LIB_FOREACHID_PROCESS_FUNCTION_CALL(
+ data,
+ IDP_foreach_property(marker->prop,
+ IDP_TYPE_FILTER_ID,
+ BKE_lib_query_idpropertiesForeachIDLink_callback,
+ data));
}
ToolSettings *toolsett = scene->toolsettings;
if (toolsett) {
- scene_foreach_toolsettings(data, toolsett, false, NULL, toolsett);
+ BKE_LIB_FOREACHID_PROCESS_FUNCTION_CALL(
+ data, scene_foreach_toolsettings(data, toolsett, false, NULL, toolsett));
}
if (scene->rigidbody_world) {
- BKE_rigidbody_world_id_loop(
- scene->rigidbody_world, scene_foreach_rigidbodyworldSceneLooper, data);
+ BKE_LIB_FOREACHID_PROCESS_FUNCTION_CALL(
+ data,
+ BKE_rigidbody_world_id_loop(
+ scene->rigidbody_world, scene_foreach_rigidbodyworldSceneLooper, data));
}
}
@@ -1853,7 +1925,7 @@ Scene *BKE_scene_duplicate(Main *bmain, Scene *sce, eSceneCopyMethod type)
if (!is_subprocess) {
/* This code will follow into all ID links using an ID tagged with LIB_TAG_NEW. */
- BKE_libblock_relink_to_newid(&sce_copy->id);
+ BKE_libblock_relink_to_newid(bmain, &sce_copy->id, 0);
#ifndef NDEBUG
/* Call to `BKE_libblock_relink_to_newid` above is supposed to have cleared all those
diff --git a/source/blender/blenkernel/intern/screen.c b/source/blender/blenkernel/intern/screen.c
index 233a4f344b5..6352e08ec4b 100644
--- a/source/blender/blenkernel/intern/screen.c
+++ b/source/blender/blenkernel/intern/screen.c
@@ -97,6 +97,10 @@ static void screen_foreach_id_dopesheet(LibraryForeachIDData *data, bDopeSheet *
}
}
+/**
+ * Callback used by lib_query to walk over all ID usages (mimics `foreach_id` callback of
+ * `IDTypeInfo` structure).
+ */
void BKE_screen_foreach_id_screen_area(LibraryForeachIDData *data, ScrArea *area)
{
BKE_LIB_FOREACHID_PROCESS_IDSUPER(data, area->full, IDWALK_CB_NOP);
@@ -107,10 +111,8 @@ void BKE_screen_foreach_id_screen_area(LibraryForeachIDData *data, ScrArea *area
switch (sl->spacetype) {
case SPACE_VIEW3D: {
View3D *v3d = (View3D *)sl;
-
BKE_LIB_FOREACHID_PROCESS_IDSUPER(data, v3d->camera, IDWALK_CB_NOP);
BKE_LIB_FOREACHID_PROCESS_IDSUPER(data, v3d->ob_center, IDWALK_CB_NOP);
-
if (v3d->localvd) {
BKE_LIB_FOREACHID_PROCESS_IDSUPER(data, v3d->localvd->camera, IDWALK_CB_NOP);
}
@@ -118,13 +120,12 @@ void BKE_screen_foreach_id_screen_area(LibraryForeachIDData *data, ScrArea *area
}
case SPACE_GRAPH: {
SpaceGraph *sipo = (SpaceGraph *)sl;
-
- screen_foreach_id_dopesheet(data, sipo->ads);
+ BKE_LIB_FOREACHID_PROCESS_FUNCTION_CALL(data,
+ screen_foreach_id_dopesheet(data, sipo->ads));
break;
}
case SPACE_PROPERTIES: {
SpaceProperties *sbuts = (SpaceProperties *)sl;
-
BKE_LIB_FOREACHID_PROCESS_ID(data, sbuts->pinid, IDWALK_CB_NOP);
break;
}
@@ -132,14 +133,12 @@ void BKE_screen_foreach_id_screen_area(LibraryForeachIDData *data, ScrArea *area
break;
case SPACE_ACTION: {
SpaceAction *saction = (SpaceAction *)sl;
-
screen_foreach_id_dopesheet(data, &saction->ads);
BKE_LIB_FOREACHID_PROCESS_IDSUPER(data, saction->action, IDWALK_CB_NOP);
break;
}
case SPACE_IMAGE: {
SpaceImage *sima = (SpaceImage *)sl;
-
BKE_LIB_FOREACHID_PROCESS_IDSUPER(data, sima->image, IDWALK_CB_USER_ONE);
BKE_LIB_FOREACHID_PROCESS_IDSUPER(data, sima->mask_info.mask, IDWALK_CB_USER_ONE);
BKE_LIB_FOREACHID_PROCESS_IDSUPER(data, sima->gpd, IDWALK_CB_USER);
@@ -147,33 +146,28 @@ void BKE_screen_foreach_id_screen_area(LibraryForeachIDData *data, ScrArea *area
}
case SPACE_SEQ: {
SpaceSeq *sseq = (SpaceSeq *)sl;
-
BKE_LIB_FOREACHID_PROCESS_IDSUPER(data, sseq->gpd, IDWALK_CB_USER);
break;
}
case SPACE_NLA: {
SpaceNla *snla = (SpaceNla *)sl;
-
- screen_foreach_id_dopesheet(data, snla->ads);
+ BKE_LIB_FOREACHID_PROCESS_FUNCTION_CALL(data,
+ screen_foreach_id_dopesheet(data, snla->ads));
break;
}
case SPACE_TEXT: {
SpaceText *st = (SpaceText *)sl;
-
BKE_LIB_FOREACHID_PROCESS_IDSUPER(data, st->text, IDWALK_CB_NOP);
break;
}
case SPACE_SCRIPT: {
SpaceScript *scpt = (SpaceScript *)sl;
-
BKE_LIB_FOREACHID_PROCESS_IDSUPER(data, scpt->script, IDWALK_CB_NOP);
break;
}
case SPACE_OUTLINER: {
SpaceOutliner *space_outliner = (SpaceOutliner *)sl;
-
BKE_LIB_FOREACHID_PROCESS_ID(data, space_outliner->search_tse.id, IDWALK_CB_NOP);
-
if (space_outliner->treestore != NULL) {
TreeStoreElem *tselem;
BLI_mempool_iter iter;
@@ -187,13 +181,11 @@ void BKE_screen_foreach_id_screen_area(LibraryForeachIDData *data, ScrArea *area
}
case SPACE_NODE: {
SpaceNode *snode = (SpaceNode *)sl;
-
const bool is_private_nodetree = snode->id != NULL &&
ntreeFromID(snode->id) == snode->nodetree;
BKE_LIB_FOREACHID_PROCESS_ID(data, snode->id, IDWALK_CB_NOP);
BKE_LIB_FOREACHID_PROCESS_ID(data, snode->from, IDWALK_CB_NOP);
-
BKE_LIB_FOREACHID_PROCESS_IDSUPER(
data, snode->nodetree, is_private_nodetree ? IDWALK_CB_EMBEDDED : IDWALK_CB_USER_ONE);
@@ -219,14 +211,12 @@ void BKE_screen_foreach_id_screen_area(LibraryForeachIDData *data, ScrArea *area
}
case SPACE_CLIP: {
SpaceClip *sclip = (SpaceClip *)sl;
-
BKE_LIB_FOREACHID_PROCESS_IDSUPER(data, sclip->clip, IDWALK_CB_USER_ONE);
BKE_LIB_FOREACHID_PROCESS_IDSUPER(data, sclip->mask_info.mask, IDWALK_CB_USER_ONE);
break;
}
case SPACE_SPREADSHEET: {
SpaceSpreadsheet *sspreadsheet = (SpaceSpreadsheet *)sl;
-
LISTBASE_FOREACH (SpreadsheetContext *, context, &sspreadsheet->context_path) {
if (context->type == SPREADSHEET_CONTEXT_OBJECT) {
BKE_LIB_FOREACHID_PROCESS_IDSUPER(
@@ -243,12 +233,13 @@ void BKE_screen_foreach_id_screen_area(LibraryForeachIDData *data, ScrArea *area
static void screen_foreach_id(ID *id, LibraryForeachIDData *data)
{
- if (BKE_lib_query_foreachid_process_flags_get(data) & IDWALK_INCLUDE_UI) {
- bScreen *screen = (bScreen *)id;
+ if ((BKE_lib_query_foreachid_process_flags_get(data) & IDWALK_INCLUDE_UI) == 0) {
+ return;
+ }
+ bScreen *screen = (bScreen *)id;
- LISTBASE_FOREACH (ScrArea *, area, &screen->areabase) {
- BKE_screen_foreach_id_screen_area(data, area);
- }
+ LISTBASE_FOREACH (ScrArea *, area, &screen->areabase) {
+ BKE_LIB_FOREACHID_PROCESS_FUNCTION_CALL(data, BKE_screen_foreach_id_screen_area(data, area));
}
}
diff --git a/source/blender/blenkernel/intern/simulation.cc b/source/blender/blenkernel/intern/simulation.cc
index 1d297b3ced9..98e7405bde6 100644
--- a/source/blender/blenkernel/intern/simulation.cc
+++ b/source/blender/blenkernel/intern/simulation.cc
@@ -103,7 +103,8 @@ static void simulation_foreach_id(ID *id, LibraryForeachIDData *data)
Simulation *simulation = (Simulation *)id;
if (simulation->nodetree) {
/* nodetree **are owned by IDs**, treat them as mere sub-data and not real ID! */
- BKE_library_foreach_ID_embedded(data, (ID **)&simulation->nodetree);
+ BKE_LIB_FOREACHID_PROCESS_FUNCTION_CALL(
+ data, BKE_library_foreach_ID_embedded(data, (ID **)&simulation->nodetree));
}
}
diff --git a/source/blender/blenkernel/intern/softbody.c b/source/blender/blenkernel/intern/softbody.c
index b7eb9d31b23..a008edd038a 100644
--- a/source/blender/blenkernel/intern/softbody.c
+++ b/source/blender/blenkernel/intern/softbody.c
@@ -2633,7 +2633,7 @@ static void interpolate_exciter(Object *ob, int timescale, int time)
}
}
-/* ************ convertors ********** */
+/* ************ converters ********** */
/* for each object type we need;
* - xxxx_to_softbody(Object *ob) : a full (new) copy, creates SB geometry
diff --git a/source/blender/blenkernel/intern/spline_base.cc b/source/blender/blenkernel/intern/spline_base.cc
index c2c9d178171..52bbd2bec57 100644
--- a/source/blender/blenkernel/intern/spline_base.cc
+++ b/source/blender/blenkernel/intern/spline_base.cc
@@ -30,14 +30,12 @@ using blender::float3;
using blender::IndexRange;
using blender::MutableSpan;
using blender::Span;
+using blender::VArray;
using blender::attribute_math::convert_to_static_type;
using blender::bke::AttributeIDRef;
using blender::fn::GMutableSpan;
using blender::fn::GSpan;
using blender::fn::GVArray;
-using blender::fn::GVArray_For_GSpan;
-using blender::fn::GVArray_Typed;
-using blender::fn::GVArrayPtr;
Spline::Type Spline::type() const
{
@@ -416,7 +414,7 @@ Span<float3> Spline::evaluated_normals() const
}
/* Rotate the generated normals with the interpolated tilt data. */
- GVArray_Typed<float> tilts = this->interpolate_to_evaluated(this->tilts());
+ VArray<float> tilts = this->interpolate_to_evaluated(this->tilts());
for (const int i : normals.index_range()) {
normals[i] = rotate_direction_around_axis(normals[i], tangents[i], tilts[i]);
}
@@ -529,9 +527,9 @@ void Spline::bounds_min_max(float3 &min, float3 &max, const bool use_evaluated)
}
}
-GVArrayPtr Spline::interpolate_to_evaluated(GSpan data) const
+GVArray Spline::interpolate_to_evaluated(GSpan data) const
{
- return this->interpolate_to_evaluated(GVArray_For_GSpan(data));
+ return this->interpolate_to_evaluated(GVArray::ForSpan(data));
}
/**
@@ -547,7 +545,7 @@ void Spline::sample_with_index_factors(const GVArray &src,
blender::attribute_math::convert_to_static_type(src.type(), [&](auto dummy) {
using T = decltype(dummy);
- const GVArray_Typed<T> src_typed = src.typed<T>();
+ const VArray<T> src_typed = src.typed<T>();
MutableSpan<T> dst_typed = dst.typed<T>();
if (src.size() == 1) {
dst_typed.fill(src_typed[0]);
diff --git a/source/blender/blenkernel/intern/spline_bezier.cc b/source/blender/blenkernel/intern/spline_bezier.cc
index 18d195f19da..0cadab998f5 100644
--- a/source/blender/blenkernel/intern/spline_bezier.cc
+++ b/source/blender/blenkernel/intern/spline_bezier.cc
@@ -25,9 +25,8 @@ using blender::float3;
using blender::IndexRange;
using blender::MutableSpan;
using blender::Span;
+using blender::VArray;
using blender::fn::GVArray;
-using blender::fn::GVArray_For_ArrayContainer;
-using blender::fn::GVArrayPtr;
void BezierSpline::copy_settings(Spline &dst) const
{
@@ -708,26 +707,26 @@ static void interpolate_to_evaluated_impl(const BezierSpline &spline,
}
}
-GVArrayPtr BezierSpline::interpolate_to_evaluated(const GVArray &src) const
+GVArray BezierSpline::interpolate_to_evaluated(const GVArray &src) const
{
BLI_assert(src.size() == this->size());
if (src.is_single()) {
- return src.shallow_copy();
+ return src;
}
const int eval_size = this->evaluated_points_size();
if (eval_size == 1) {
- return src.shallow_copy();
+ return src;
}
- GVArrayPtr new_varray;
+ GVArray new_varray;
blender::attribute_math::convert_to_static_type(src.type(), [&](auto dummy) {
using T = decltype(dummy);
if constexpr (!std::is_void_v<blender::attribute_math::DefaultMixer<T>>) {
Array<T> values(eval_size);
interpolate_to_evaluated_impl<T>(*this, src.typed<T>(), values);
- new_varray = std::make_unique<GVArray_For_ArrayContainer<Array<T>>>(std::move(values));
+ new_varray = VArray<T>::ForContainer(std::move(values));
}
});
diff --git a/source/blender/blenkernel/intern/spline_nurbs.cc b/source/blender/blenkernel/intern/spline_nurbs.cc
index 6d30d8ba916..7fa332a0330 100644
--- a/source/blender/blenkernel/intern/spline_nurbs.cc
+++ b/source/blender/blenkernel/intern/spline_nurbs.cc
@@ -26,10 +26,8 @@ using blender::float3;
using blender::IndexRange;
using blender::MutableSpan;
using blender::Span;
+using blender::VArray;
using blender::fn::GVArray;
-using blender::fn::GVArray_For_ArrayContainer;
-using blender::fn::GVArray_Typed;
-using blender::fn::GVArrayPtr;
void NURBSpline::copy_settings(Spline &dst) const
{
@@ -410,23 +408,23 @@ void interpolate_to_evaluated_impl(Span<NURBSpline::BasisCache> weights,
mixer.finalize();
}
-GVArrayPtr NURBSpline::interpolate_to_evaluated(const GVArray &src) const
+GVArray NURBSpline::interpolate_to_evaluated(const GVArray &src) const
{
BLI_assert(src.size() == this->size());
if (src.is_single()) {
- return src.shallow_copy();
+ return src;
}
Span<BasisCache> basis_cache = this->calculate_basis_cache();
- GVArrayPtr new_varray;
+ GVArray new_varray;
blender::attribute_math::convert_to_static_type(src.type(), [&](auto dummy) {
using T = decltype(dummy);
if constexpr (!std::is_void_v<blender::attribute_math::DefaultMixer<T>>) {
Array<T> values(this->evaluated_points_size());
interpolate_to_evaluated_impl<T>(basis_cache, src.typed<T>(), values);
- new_varray = std::make_unique<GVArray_For_ArrayContainer<Array<T>>>(std::move(values));
+ new_varray = VArray<T>::ForContainer(std::move(values));
}
});
@@ -448,8 +446,8 @@ Span<float3> NURBSpline::evaluated_positions() const
evaluated_position_cache_.resize(eval_size);
/* TODO: Avoid copying the evaluated data from the temporary array. */
- GVArray_Typed<float3> evaluated = Spline::interpolate_to_evaluated(positions_.as_span());
- evaluated->materialize(evaluated_position_cache_);
+ VArray<float3> evaluated = Spline::interpolate_to_evaluated(positions_.as_span());
+ evaluated.materialize(evaluated_position_cache_);
position_cache_dirty_ = false;
return evaluated_position_cache_;
diff --git a/source/blender/blenkernel/intern/spline_poly.cc b/source/blender/blenkernel/intern/spline_poly.cc
index 338b5d0ac9e..d495c977285 100644
--- a/source/blender/blenkernel/intern/spline_poly.cc
+++ b/source/blender/blenkernel/intern/spline_poly.cc
@@ -23,7 +23,6 @@ using blender::float3;
using blender::MutableSpan;
using blender::Span;
using blender::fn::GVArray;
-using blender::fn::GVArrayPtr;
void PolySpline::copy_settings(Spline &UNUSED(dst)) const
{
@@ -122,9 +121,8 @@ Span<float3> PolySpline::evaluated_positions() const
* the original data. Therefore the lifetime of the returned virtual array must not be longer than
* the source data.
*/
-GVArrayPtr PolySpline::interpolate_to_evaluated(const GVArray &src) const
+GVArray PolySpline::interpolate_to_evaluated(const GVArray &src) const
{
BLI_assert(src.size() == this->size());
-
- return src.shallow_copy();
+ return src;
}
diff --git a/source/blender/blenkernel/intern/subsurf_ccg.c b/source/blender/blenkernel/intern/subsurf_ccg.c
index 0c58c8e8a5a..6796b1ac397 100644
--- a/source/blender/blenkernel/intern/subsurf_ccg.c
+++ b/source/blender/blenkernel/intern/subsurf_ccg.c
@@ -2020,7 +2020,7 @@ static void set_ccgdm_all_geometry(CCGDerivedMesh *ccgdm,
&dm->loopData, &ccgdm->dm.loopData, loopidx, w2, NULL, numVerts, loopindex2);
loopindex2++;
- /* Copy over poly data, e.g. mtexpoly. */
+ /* Copy over poly data, e.g. #CD_FACEMAP. */
CustomData_copy_data(&dm->polyData, &ccgdm->dm.polyData, origIndex, faceNum, 1);
/* Set original index data. */
diff --git a/source/blender/blenkernel/intern/text.c b/source/blender/blenkernel/intern/text.c
index 0cb2218e7e0..7ac9e20d1a7 100644
--- a/source/blender/blenkernel/intern/text.c
+++ b/source/blender/blenkernel/intern/text.c
@@ -1977,7 +1977,7 @@ static char tab_to_spaces[] = " ";
static void txt_convert_tab_to_spaces(Text *text)
{
/* sb aims to pad adjust the tab-width needed so that the right number of spaces
- * is added so that the indention of the line is the right width (i.e. aligned
+ * is added so that the indentation of the line is the right width (i.e. aligned
* to multiples of TXT_TABSIZE)
*/
const char *sb = &tab_to_spaces[text->curc % TXT_TABSIZE];
diff --git a/source/blender/blenkernel/intern/texture.c b/source/blender/blenkernel/intern/texture.c
index c878abf0dff..a8c8eaa6a1c 100644
--- a/source/blender/blenkernel/intern/texture.c
+++ b/source/blender/blenkernel/intern/texture.c
@@ -142,7 +142,8 @@ static void texture_foreach_id(ID *id, LibraryForeachIDData *data)
Tex *texture = (Tex *)id;
if (texture->nodetree) {
/* nodetree **are owned by IDs**, treat them as mere sub-data and not real ID! */
- BKE_library_foreach_ID_embedded(data, (ID **)&texture->nodetree);
+ BKE_LIB_FOREACHID_PROCESS_FUNCTION_CALL(
+ data, BKE_library_foreach_ID_embedded(data, (ID **)&texture->nodetree));
}
BKE_LIB_FOREACHID_PROCESS_IDSUPER(data, texture->ima, IDWALK_CB_USER);
}
diff --git a/source/blender/blenkernel/intern/world.c b/source/blender/blenkernel/intern/world.c
index fe03c5b817a..2f0a282a298 100644
--- a/source/blender/blenkernel/intern/world.c
+++ b/source/blender/blenkernel/intern/world.c
@@ -131,7 +131,8 @@ static void world_foreach_id(ID *id, LibraryForeachIDData *data)
if (world->nodetree) {
/* nodetree **are owned by IDs**, treat them as mere sub-data and not real ID! */
- BKE_library_foreach_ID_embedded(data, (ID **)&world->nodetree);
+ BKE_LIB_FOREACHID_PROCESS_FUNCTION_CALL(
+ data, BKE_library_foreach_ID_embedded(data, (ID **)&world->nodetree));
}
}
diff --git a/source/blender/blenlib/BLI_any.hh b/source/blender/blenlib/BLI_any.hh
new file mode 100644
index 00000000000..0fc5de5540f
--- /dev/null
+++ b/source/blender/blenlib/BLI_any.hh
@@ -0,0 +1,319 @@
+/*
+ * 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.
+ */
+
+#pragma once
+
+/** \file
+ * \ingroup bli
+ *
+ * A #blender::Any is a type-safe container for single values of any copy constructible type.
+ * It is similar to #std::any but provides the following two additional features:
+ * - Adjustable inline buffer capacity and alignment. #std::any has a small inline buffer in most
+ * implementations as well, but its size is not guaranteed.
+ * - Can store additional user-defined type information without increasing the stack size of #Any.
+ */
+
+#include <algorithm>
+#include <utility>
+
+#include "BLI_memory_utils.hh"
+
+namespace blender {
+
+namespace detail {
+
+/**
+ * Contains function pointers that manage the memory in an #Any.
+ * Additional type specific #ExtraInfo can be embedded here as well.
+ */
+template<typename ExtraInfo> struct AnyTypeInfo {
+ void (*copy_construct)(void *dst, const void *src);
+ void (*move_construct)(void *dst, void *src);
+ void (*destruct)(void *src);
+ const void *(*get)(const void *src);
+ ExtraInfo extra_info;
+
+ /**
+ * Used when #T is stored directly in the inline buffer of the #Any.
+ */
+ template<typename T> static const AnyTypeInfo &get_for_inline()
+ {
+ static AnyTypeInfo funcs = {[](void *dst, const void *src) { new (dst) T(*(const T *)src); },
+ [](void *dst, void *src) { new (dst) T(std::move(*(T *)src)); },
+ [](void *src) { ((T *)src)->~T(); },
+ [](const void *src) { return src; },
+ ExtraInfo::template get<T>()};
+ return funcs;
+ }
+
+ /**
+ * Used when #T can't be stored directly in the inline buffer and is stored in a #std::unique_ptr
+ * instead. In this scenario, the #std::unique_ptr is stored in the inline buffer.
+ */
+ template<typename T> static const AnyTypeInfo &get_for_unique_ptr()
+ {
+ using Ptr = std::unique_ptr<T>;
+ static AnyTypeInfo funcs = {
+ [](void *dst, const void *src) { new (dst) Ptr(new T(**(const Ptr *)src)); },
+ [](void *dst, void *src) { new (dst) Ptr(new T(std::move(**(Ptr *)src))); },
+ [](void *src) { ((Ptr *)src)->~Ptr(); },
+ [](const void *src) -> const void * { return &**(const Ptr *)src; },
+ ExtraInfo::template get<T>()};
+ return funcs;
+ }
+
+ /**
+ * Used when the #Any does not contain any type currently.
+ */
+ static const AnyTypeInfo &get_for_empty()
+ {
+ static AnyTypeInfo funcs = {[](void *UNUSED(dst), const void *UNUSED(src)) {},
+ [](void *UNUSED(dst), void *UNUSED(src)) {},
+ [](void *UNUSED(src)) {},
+ [](const void *UNUSED(src)) -> const void * { return nullptr; },
+ ExtraInfo{}};
+ return funcs;
+ }
+};
+
+/**
+ * Dummy extra info that is used when no additional type information should be stored in the #Any.
+ */
+struct NoExtraInfo {
+ template<typename T> static NoExtraInfo get()
+ {
+ return {};
+ }
+};
+
+} // namespace detail
+
+template<
+ /**
+ * Either void or a struct that contains data members for additional type information.
+ * The struct has to have a static `ExtraInfo get<T>()` method that initializes the struct
+ * based on a type.
+ */
+ typename ExtraInfo = void,
+ /**
+ * Size of the inline buffer. This allows types that are small enough to be stored directly
+ * inside the #Any without an additional allocation.
+ */
+ size_t InlineBufferCapacity = 8,
+ /**
+ * Required minimum alignment of the inline buffer. If this is smaller than the alignment
+ * requirement of a used type, a separate allocation is necessary.
+ */
+ size_t Alignment = 8>
+class Any {
+ private:
+ /* Makes it possible to use void in the template parameters. */
+ using RealExtraInfo =
+ std::conditional_t<std::is_void_v<ExtraInfo>, detail::NoExtraInfo, ExtraInfo>;
+ using Info = detail::AnyTypeInfo<RealExtraInfo>;
+
+ /**
+ * Inline buffer that either contains nothing, the stored value directly, or a #std::unique_ptr
+ * to the value.
+ */
+ AlignedBuffer<std::max(InlineBufferCapacity, sizeof(std::unique_ptr<int>)), Alignment> buffer_{};
+
+ /**
+ * Information about the type that is currently stored.
+ */
+ const Info *info_ = &Info::get_for_empty();
+
+ public:
+ /** Only copy constructible types can be stored in #Any. */
+ template<typename T> static constexpr inline bool is_allowed_v = std::is_copy_constructible_v<T>;
+
+ /**
+ * Checks if the type will be stored in the inline buffer or if it requires a separate
+ * allocation.
+ */
+ template<typename T>
+ static constexpr inline bool is_inline_v = std::is_nothrow_move_constructible_v<T> &&
+ sizeof(T) <= InlineBufferCapacity &&
+ alignof(T) <= Alignment;
+
+ /**
+ * Checks if #T is the same type as this #Any, because in this case the behavior of e.g. the
+ * assignment operator is different.
+ */
+ template<typename T>
+ static constexpr inline bool is_same_any_v = std::is_same_v<std::decay_t<T>, Any>;
+
+ private:
+ template<typename T> const Info &get_info() const
+ {
+ using DecayT = std::decay_t<T>;
+ static_assert(is_allowed_v<DecayT>);
+ if constexpr (is_inline_v<DecayT>) {
+ return Info::template get_for_inline<DecayT>();
+ }
+ else {
+ return Info::template get_for_unique_ptr<DecayT>();
+ }
+ }
+
+ public:
+ Any() = default;
+
+ Any(const Any &other) : info_(other.info_)
+ {
+ info_->copy_construct(&buffer_, &other.buffer_);
+ }
+
+ /**
+ * \note The #other #Any will not be empty afterwards if it was not before. Just its value is in
+ * a moved-from state.
+ */
+ Any(Any &&other) noexcept : info_(other.info_)
+ {
+ info_->move_construct(&buffer_, &other.buffer_);
+ }
+
+ /**
+ * Constructs a new #Any that contains the given type #T from #args. The #std::in_place_type_t is
+ * used to disambiguate this and the copy/move constructors.
+ */
+ template<typename T, typename... Args> explicit Any(std::in_place_type_t<T>, Args &&...args)
+ {
+ using DecayT = std::decay_t<T>;
+ static_assert(is_allowed_v<DecayT>);
+ info_ = &this->template get_info<DecayT>();
+ if constexpr (is_inline_v<DecayT>) {
+ /* Construct the value directly in the inline buffer. */
+ new (&buffer_) DecayT(std::forward<Args>(args)...);
+ }
+ else {
+ /* Construct the value in a new allocation and store a #std::unique_ptr to it in the inline
+ * buffer. */
+ new (&buffer_) std::unique_ptr<DecayT>(new DecayT(std::forward<Args>(args)...));
+ }
+ }
+
+ /**
+ * Constructs a new #Any that contains the given value.
+ */
+ template<typename T, typename X = std::enable_if_t<!is_same_any_v<T>, void>>
+ Any(T &&value) : Any(std::in_place_type<T>, std::forward<T>(value))
+ {
+ }
+
+ ~Any()
+ {
+ info_->destruct(&buffer_);
+ }
+
+ /**
+ * \note: Only needed because the template below does not count as copy assignment operator.
+ */
+ Any &operator=(const Any &other)
+ {
+ if (this == &other) {
+ return *this;
+ }
+ this->~Any();
+ new (this) Any(other);
+ return *this;
+ }
+
+ /** Assign any value to the #Any. */
+ template<typename T> Any &operator=(T &&other)
+ {
+ if constexpr (is_same_any_v<T>) {
+ if (this == &other) {
+ return *this;
+ }
+ }
+ this->~Any();
+ new (this) Any(std::forward<T>(other));
+ return *this;
+ }
+
+ /** Destruct any existing value to make it empty. */
+ void reset()
+ {
+ info_->destruct(&buffer_);
+ info_ = &Info::get_for_empty();
+ }
+
+ operator bool() const
+ {
+ return this->has_value();
+ }
+
+ bool has_value() const
+ {
+ return info_ != &Info::get_for_empty();
+ }
+
+ template<typename T, typename... Args> std::decay_t<T> &emplace(Args &&...args)
+ {
+ this->~Any();
+ new (this) Any(std::in_place_type<T>, std::forward<Args>(args)...);
+ return this->get<T>();
+ }
+
+ /** Return true when the value that is currently stored is a #T. */
+ template<typename T> bool is() const
+ {
+ return info_ == &this->template get_info<T>();
+ }
+
+ /** Get a pointer to the stored value. */
+ void *get()
+ {
+ return const_cast<void *>(info_->get(&buffer_));
+ }
+
+ /** Get a pointer to the stored value. */
+ const void *get() const
+ {
+ return info_->get(&buffer_);
+ }
+
+ /**
+ * Get a reference to the stored value. This invokes undefined behavior when #T does not have the
+ * correct type.
+ */
+ template<typename T> std::decay_t<T> &get()
+ {
+ BLI_assert(this->is<T>());
+ return *static_cast<std::decay_t<T> *>(this->get());
+ }
+
+ /**
+ * Get a reference to the stored value. This invokes undefined behavior when #T does not have the
+ * correct type.
+ */
+ template<typename T> const std::decay_t<T> &get() const
+ {
+ BLI_assert(this->is<T>());
+ return *static_cast<const std::decay_t<T> *>(this->get());
+ }
+
+ /**
+ * Get extra information that has been stored for the contained type.
+ */
+ const RealExtraInfo &extra_info() const
+ {
+ return info_->extra_info;
+ }
+};
+
+} // namespace blender
diff --git a/source/blender/blenlib/BLI_rect.h b/source/blender/blenlib/BLI_rect.h
index fb52436587f..ca06a3e3545 100644
--- a/source/blender/blenlib/BLI_rect.h
+++ b/source/blender/blenlib/BLI_rect.h
@@ -110,8 +110,8 @@ bool BLI_rcti_isect_circle(const struct rcti *rect, const float xy[2], const flo
bool BLI_rctf_isect_circle(const struct rctf *rect, const float xy[2], const float radius);
bool BLI_rcti_inside_rcti(const rcti *rct_a, const rcti *rct_b);
bool BLI_rctf_inside_rctf(const rctf *rct_a, const rctf *rct_b);
-void BLI_rcti_union(struct rcti *rct1, const struct rcti *rct2);
-void BLI_rctf_union(struct rctf *rct1, const struct rctf *rct2);
+void BLI_rcti_union(struct rcti *rct_a, const struct rcti *rct_b);
+void BLI_rctf_union(struct rctf *rct_a, const struct rctf *rct_b);
void BLI_rcti_rctf_copy(struct rcti *dst, const struct rctf *src);
void BLI_rctf_rcti_copy(struct rctf *dst, const struct rcti *src);
void BLI_rcti_rctf_copy_floor(struct rcti *dst, const struct rctf *src);
diff --git a/source/blender/blenlib/BLI_serialize.hh b/source/blender/blenlib/BLI_serialize.hh
index 7b8aa03b807..051731ab801 100644
--- a/source/blender/blenlib/BLI_serialize.hh
+++ b/source/blender/blenlib/BLI_serialize.hh
@@ -103,11 +103,11 @@ using IntValue = PrimitiveValue<int64_t, eValueType::Int>;
using DoubleValue = PrimitiveValue<double, eValueType::Double>;
using BooleanValue = PrimitiveValue<bool, eValueType::Boolean>;
-template<typename Container, typename ContainerItem, eValueType V> class ContainerValue;
+template<typename Container, eValueType V, typename ContainerItem = typename Container::value_type>
+class ContainerValue;
/* ArrayValue stores its items as shared pointer as it shares data with a lookup table that can
* be created by calling `create_lookup`. */
-using ArrayValue =
- ContainerValue<Vector<std::shared_ptr<Value>>, std::shared_ptr<Value>, eValueType::Array>;
+using ArrayValue = ContainerValue<Vector<std::shared_ptr<Value>>, eValueType::Array>;
/**
* Class containing a (de)serializable value.
@@ -138,7 +138,7 @@ class Value {
public:
virtual ~Value() = default;
- const eValueType type() const
+ eValueType type() const
{
return type_;
}
@@ -234,11 +234,11 @@ template<
/** The container type where the elements are stored in. */
typename Container,
- /** Type of the data inside the container. */
- typename ContainerItem,
-
/** ValueType representing the value (object/array). */
- eValueType V>
+ eValueType V,
+
+ /** Type of the data inside the container. */
+ typename ContainerItem>
class ContainerValue : public Value {
public:
using Items = Container;
@@ -275,8 +275,7 @@ using ObjectElementType = std::pair<std::string, std::shared_ptr<Value>>;
* Object is a key-value container where the key must be a std::string.
* Internally it is stored in a blender::Vector to ensure the order of keys.
*/
-class ObjectValue
- : public ContainerValue<Vector<ObjectElementType>, ObjectElementType, eValueType::Object> {
+class ObjectValue : public ContainerValue<Vector<ObjectElementType>, eValueType::Object> {
public:
using LookupValue = std::shared_ptr<Value>;
using Lookup = Map<std::string, LookupValue>;
diff --git a/source/blender/blenlib/BLI_virtual_array.hh b/source/blender/blenlib/BLI_virtual_array.hh
index 1c02bce8411..d9f83d3e1cb 100644
--- a/source/blender/blenlib/BLI_virtual_array.hh
+++ b/source/blender/blenlib/BLI_virtual_array.hh
@@ -37,148 +37,98 @@
* see of the increased compile time and binary size is worth it.
*/
+#include "BLI_any.hh"
#include "BLI_array.hh"
#include "BLI_index_mask.hh"
#include "BLI_span.hh"
namespace blender {
-/* An immutable virtual array. */
-template<typename T> class VArray {
+/* Forward declarations for generic virtual arrays. */
+namespace fn {
+class GVArray;
+class GVMutableArray;
+}; // namespace fn
+
+/**
+ * Implements the specifics of how the elements of a virtual array are accessed. It contains a
+ * bunch of virtual methods that are wrapped by #VArray.
+ */
+template<typename T> class VArrayImpl {
protected:
+ /**
+ * Number of elements in the virtual array. All virtual arrays have a size, but in some cases it
+ * may make sense to set it to the max value.
+ */
int64_t size_;
public:
- VArray(const int64_t size) : size_(size)
+ VArrayImpl(const int64_t size) : size_(size)
{
BLI_assert(size_ >= 0);
}
- virtual ~VArray() = default;
-
- T get(const int64_t index) const
- {
- BLI_assert(index >= 0);
- BLI_assert(index < size_);
- return this->get_impl(index);
- }
+ virtual ~VArrayImpl() = default;
int64_t size() const
{
return size_;
}
- bool is_empty() const
- {
- return size_ == 0;
- }
-
- IndexRange index_range() const
- {
- return IndexRange(size_);
- }
-
- /* Returns true when the virtual array is stored as a span internally. */
- bool is_span() const
- {
- if (size_ == 0) {
- return true;
- }
- return this->is_span_impl();
- }
-
- /* Returns the internally used span of the virtual array. This invokes undefined behavior is the
- * virtual array is not stored as a span internally. */
- Span<T> get_internal_span() const
- {
- BLI_assert(this->is_span());
- if (size_ == 0) {
- return {};
- }
- return this->get_internal_span_impl();
- }
+ /**
+ * Get the element at #index. This does not return a reference, because the value may be computed
+ * on the fly.
+ */
+ virtual T get(const int64_t index) const = 0;
- /* Returns true when the virtual array returns the same value for every index. */
- bool is_single() const
- {
- if (size_ == 1) {
- return true;
- }
- return this->is_single_impl();
- }
-
- /* Returns the value that is returned for every index. This invokes undefined behavior if the
- * virtual array would not return the same value for every index. */
- T get_internal_single() const
- {
- BLI_assert(this->is_single());
- if (size_ == 1) {
- return this->get(0);
- }
- return this->get_internal_single_impl();
- }
-
- /* Get the element at a specific index. Note that this operator cannot be used to assign values
- * to an index, because the return value is not a reference. */
- T operator[](const int64_t index) const
- {
- return this->get(index);
- }
-
- /* Copy the entire virtual array into a span. */
- void materialize(MutableSpan<T> r_span) const
- {
- this->materialize(IndexMask(size_), r_span);
- }
-
- /* Copy some indices of the virtual array into a span. */
- void materialize(IndexMask mask, MutableSpan<T> r_span) const
- {
- BLI_assert(mask.min_array_size() <= size_);
- this->materialize_impl(mask, r_span);
- }
-
- void materialize_to_uninitialized(MutableSpan<T> r_span) const
- {
- this->materialize_to_uninitialized(IndexMask(size_), r_span);
- }
-
- void materialize_to_uninitialized(IndexMask mask, MutableSpan<T> r_span) const
- {
- BLI_assert(mask.min_array_size() <= size_);
- this->materialize_to_uninitialized_impl(mask, r_span);
- }
-
- protected:
- virtual T get_impl(const int64_t index) const = 0;
-
- virtual bool is_span_impl() const
+ /**
+ * Return true when the virtual array is a plain array internally.
+ */
+ virtual bool is_span() const
{
return false;
}
- virtual Span<T> get_internal_span_impl() const
+ /**
+ * Return the span of the virtual array.
+ * This invokes undefined behavior when #is_span returned false.
+ */
+ virtual Span<T> get_internal_span() const
{
+ /* Provide a default implementation, so that subclasses don't have to provide it. This method
+ * should never be called because #is_span returns false by default. */
BLI_assert_unreachable();
return {};
}
- virtual bool is_single_impl() const
+ /**
+ * Return true when the virtual array has the same value at every index.
+ */
+ virtual bool is_single() const
{
return false;
}
- virtual T get_internal_single_impl() const
+ /**
+ * Return the value that is used at every index.
+ * This invokes undefined behavior when #is_single returned false.
+ */
+ virtual T get_internal_single() const
{
/* Provide a default implementation, so that subclasses don't have to provide it. This method
- * should never be called because `is_single_impl` returns false by default. */
+ * should never be called because #is_single returns false by default. */
BLI_assert_unreachable();
return T();
}
- virtual void materialize_impl(IndexMask mask, MutableSpan<T> r_span) const
+ /**
+ * Copy values from the virtual array into the provided span. The index of the value in the
+ * virtual is the same as the index in the span.
+ */
+ virtual void materialize(IndexMask mask, MutableSpan<T> r_span) const
{
T *dst = r_span.data();
+ /* Optimize for a few different common cases. */
if (this->is_span()) {
const T *src = this->get_internal_span().data();
mask.foreach_index([&](const int64_t i) { dst[i] = src[i]; });
@@ -192,9 +142,13 @@ template<typename T> class VArray {
}
}
- virtual void materialize_to_uninitialized_impl(IndexMask mask, MutableSpan<T> r_span) const
+ /**
+ * Same as #materialize but #r_span is expected to be uninitialized.
+ */
+ virtual void materialize_to_uninitialized(IndexMask mask, MutableSpan<T> r_span) const
{
T *dst = r_span.data();
+ /* Optimize for a few different common cases. */
if (this->is_span()) {
const T *src = this->get_internal_span().data();
mask.foreach_index([&](const int64_t i) { new (dst + i) T(src[i]); });
@@ -207,43 +161,48 @@ template<typename T> class VArray {
mask.foreach_index([&](const int64_t i) { new (dst + i) T(this->get(i)); });
}
}
-};
-/* Similar to VArray, but the elements are mutable. */
-template<typename T> class VMutableArray : public VArray<T> {
- public:
- VMutableArray(const int64_t size) : VArray<T>(size)
+ /**
+ * If this virtual wraps another #GVArray, this method should assign the wrapped array to the
+ * provided reference. This allows losslessly converting between generic and typed virtual
+ * arrays in all cases.
+ * Return true when the virtual array was assigned and false when nothing was done.
+ */
+ virtual bool try_assign_GVArray(fn::GVArray &UNUSED(varray)) const
{
+ return false;
}
- void set(const int64_t index, T value)
+ /**
+ * Return true when this virtual array may own any of the memory it references. This can be used
+ * for optimization purposes when converting or copying the virtual array.
+ */
+ virtual bool may_have_ownership() const
{
- BLI_assert(index >= 0);
- BLI_assert(index < this->size_);
- this->set_impl(index, std::move(value));
+ /* Use true by default to be on the safe side. Subclasses that know for sure that they don't
+ * own anything can overwrite this with false. */
+ return true;
}
+};
- /* Copy the values from the source span to all elements in the virtual array. */
- void set_all(Span<T> src)
- {
- BLI_assert(src.size() == this->size_);
- this->set_all_impl(src);
- }
+/* Similar to #VArrayImpl, but adds methods that allow modifying the referenced elements. */
+template<typename T> class VMutableArrayImpl : public VArrayImpl<T> {
+ public:
+ using VArrayImpl<T>::VArrayImpl;
- MutableSpan<T> get_internal_span()
- {
- BLI_assert(this->is_span());
- Span<T> span = static_cast<const VArray<T> *>(this)->get_internal_span();
- return MutableSpan<T>(const_cast<T *>(span.data()), span.size());
- }
+ /**
+ * Assign the provided #value to the #index.
+ */
+ virtual void set(const int64_t index, T value) = 0;
- protected:
- virtual void set_impl(const int64_t index, T value) = 0;
-
- virtual void set_all_impl(Span<T> src)
+ /**
+ * Copy all elements from the provided span into the virtual array.
+ */
+ virtual void set_all(Span<T> src)
{
if (this->is_span()) {
- const MutableSpan<T> span = this->get_internal_span();
+ const Span<T> const_span = this->get_internal_span();
+ const MutableSpan<T> span{(T *)const_span.data(), const_span.size()};
initialized_copy_n(src.data(), this->size_, span.data());
}
else {
@@ -253,95 +212,133 @@ template<typename T> class VMutableArray : public VArray<T> {
}
}
}
-};
-template<typename T> using VArrayPtr = std::unique_ptr<VArray<T>>;
-template<typename T> using VMutableArrayPtr = std::unique_ptr<VMutableArray<T>>;
+ /**
+ * Similar to #VArrayImpl::try_assign_GVArray but for mutable virtual arrays.
+ */
+ virtual bool try_assign_GVMutableArray(fn::GVMutableArray &UNUSED(varray)) const
+ {
+ return false;
+ }
+};
/**
* A virtual array implementation for a span. Methods in this class are final so that it can be
* devirtualized by the compiler in some cases (e.g. when #devirtualize_varray is used).
*/
-template<typename T> class VArray_For_Span : public VArray<T> {
+template<typename T> class VArrayImpl_For_Span : public VArrayImpl<T> {
protected:
const T *data_ = nullptr;
public:
- VArray_For_Span(const Span<T> data) : VArray<T>(data.size()), data_(data.data())
+ VArrayImpl_For_Span(const Span<T> data) : VArrayImpl<T>(data.size()), data_(data.data())
{
}
protected:
- VArray_For_Span(const int64_t size) : VArray<T>(size)
+ VArrayImpl_For_Span(const int64_t size) : VArrayImpl<T>(size)
{
}
- T get_impl(const int64_t index) const final
+ T get(const int64_t index) const final
{
return data_[index];
}
- bool is_span_impl() const final
+ bool is_span() const final
{
return true;
}
- Span<T> get_internal_span_impl() const final
+ Span<T> get_internal_span() const final
{
return Span<T>(data_, this->size_);
}
};
-template<typename T> class VMutableArray_For_MutableSpan : public VMutableArray<T> {
+/**
+ * A version of #VArrayImpl_For_Span that can not be subclassed. This allows safely overwriting the
+ * #may_have_ownership method.
+ */
+template<typename T> class VArrayImpl_For_Span_final final : public VArrayImpl_For_Span<T> {
+ public:
+ using VArrayImpl_For_Span<T>::VArrayImpl_For_Span;
+
+ private:
+ bool may_have_ownership() const override
+ {
+ return false;
+ }
+};
+
+/**
+ * Like #VArrayImpl_For_Span but for mutable data.
+ */
+template<typename T> class VMutableArrayImpl_For_MutableSpan : public VMutableArrayImpl<T> {
protected:
T *data_ = nullptr;
public:
- VMutableArray_For_MutableSpan(const MutableSpan<T> data)
- : VMutableArray<T>(data.size()), data_(data.data())
+ VMutableArrayImpl_For_MutableSpan(const MutableSpan<T> data)
+ : VMutableArrayImpl<T>(data.size()), data_(data.data())
{
}
protected:
- VMutableArray_For_MutableSpan(const int64_t size) : VMutableArray<T>(size)
+ VMutableArrayImpl_For_MutableSpan(const int64_t size) : VMutableArrayImpl<T>(size)
{
}
- T get_impl(const int64_t index) const final
+ T get(const int64_t index) const final
{
return data_[index];
}
- void set_impl(const int64_t index, T value) final
+ void set(const int64_t index, T value) final
{
data_[index] = value;
}
- bool is_span_impl() const override
+ bool is_span() const override
{
return true;
}
- Span<T> get_internal_span_impl() const override
+ Span<T> get_internal_span() const override
{
return Span<T>(data_, this->size_);
}
};
/**
- * A variant of `VArray_For_Span` that owns the underlying data.
+ * Like #VArrayImpl_For_Span_final but for mutable data.
+ */
+template<typename T>
+class VMutableArrayImpl_For_MutableSpan_final final : public VMutableArrayImpl_For_MutableSpan<T> {
+ public:
+ using VMutableArrayImpl_For_MutableSpan<T>::VMutableArrayImpl_For_MutableSpan;
+
+ private:
+ bool may_have_ownership() const override
+ {
+ return false;
+ }
+};
+
+/**
+ * A variant of `VArrayImpl_For_Span` that owns the underlying data.
* The `Container` type has to implement a `size()` and `data()` method.
* The `data()` method has to return a pointer to the first element in the continuous array of
* elements.
*/
template<typename Container, typename T = typename Container::value_type>
-class VArray_For_ArrayContainer : public VArray_For_Span<T> {
+class VArrayImpl_For_ArrayContainer : public VArrayImpl_For_Span<T> {
private:
Container container_;
public:
- VArray_For_ArrayContainer(Container container)
- : VArray_For_Span<T>((int64_t)container.size()), container_(std::move(container))
+ VArrayImpl_For_ArrayContainer(Container container)
+ : VArrayImpl_For_Span<T>((int64_t)container.size()), container_(std::move(container))
{
this->data_ = container_.data();
}
@@ -352,43 +349,671 @@ class VArray_For_ArrayContainer : public VArray_For_Span<T> {
* so that it can be devirtualized by the compiler in some cases (e.g. when #devirtualize_varray is
* used).
*/
-template<typename T> class VArray_For_Single final : public VArray<T> {
+template<typename T> class VArrayImpl_For_Single final : public VArrayImpl<T> {
private:
T value_;
public:
- VArray_For_Single(T value, const int64_t size) : VArray<T>(size), value_(std::move(value))
+ VArrayImpl_For_Single(T value, const int64_t size)
+ : VArrayImpl<T>(size), value_(std::move(value))
{
}
protected:
- T get_impl(const int64_t UNUSED(index)) const override
+ T get(const int64_t UNUSED(index)) const override
{
return value_;
}
- bool is_span_impl() const override
+ bool is_span() const override
{
return this->size_ == 1;
}
- Span<T> get_internal_span_impl() const override
+ Span<T> get_internal_span() const override
{
return Span<T>(&value_, 1);
}
- bool is_single_impl() const override
+ bool is_single() const override
{
return true;
}
- T get_internal_single_impl() const override
+ T get_internal_single() const override
{
return value_;
}
};
/**
+ * This class makes it easy to create a virtual array for an existing function or lambda. The
+ * `GetFunc` should take a single `index` argument and return the value at that index.
+ */
+template<typename T, typename GetFunc> class VArrayImpl_For_Func final : public VArrayImpl<T> {
+ private:
+ GetFunc get_func_;
+
+ public:
+ VArrayImpl_For_Func(const int64_t size, GetFunc get_func)
+ : VArrayImpl<T>(size), get_func_(std::move(get_func))
+ {
+ }
+
+ private:
+ T get(const int64_t index) const override
+ {
+ return get_func_(index);
+ }
+
+ void materialize(IndexMask mask, MutableSpan<T> r_span) const override
+ {
+ T *dst = r_span.data();
+ mask.foreach_index([&](const int64_t i) { dst[i] = get_func_(i); });
+ }
+
+ void materialize_to_uninitialized(IndexMask mask, MutableSpan<T> r_span) const override
+ {
+ T *dst = r_span.data();
+ mask.foreach_index([&](const int64_t i) { new (dst + i) T(get_func_(i)); });
+ }
+};
+
+/**
+ * \note: This is `final` so that #may_have_ownership can be implemented reliably.
+ */
+template<typename StructT, typename ElemT, ElemT (*GetFunc)(const StructT &)>
+class VArrayImpl_For_DerivedSpan final : public VArrayImpl<ElemT> {
+ private:
+ const StructT *data_;
+
+ public:
+ VArrayImpl_For_DerivedSpan(const Span<StructT> data)
+ : VArrayImpl<ElemT>(data.size()), data_(data.data())
+ {
+ }
+
+ private:
+ ElemT get(const int64_t index) const override
+ {
+ return GetFunc(data_[index]);
+ }
+
+ void materialize(IndexMask mask, MutableSpan<ElemT> r_span) const override
+ {
+ ElemT *dst = r_span.data();
+ mask.foreach_index([&](const int64_t i) { dst[i] = GetFunc(data_[i]); });
+ }
+
+ void materialize_to_uninitialized(IndexMask mask, MutableSpan<ElemT> r_span) const override
+ {
+ ElemT *dst = r_span.data();
+ mask.foreach_index([&](const int64_t i) { new (dst + i) ElemT(GetFunc(data_[i])); });
+ }
+
+ bool may_have_ownership() const override
+ {
+ return false;
+ }
+};
+
+/**
+ * \note: This is `final` so that #may_have_ownership can be implemented reliably.
+ */
+template<typename StructT,
+ typename ElemT,
+ ElemT (*GetFunc)(const StructT &),
+ void (*SetFunc)(StructT &, ElemT)>
+class VMutableArrayImpl_For_DerivedSpan final : public VMutableArrayImpl<ElemT> {
+ private:
+ StructT *data_;
+
+ public:
+ VMutableArrayImpl_For_DerivedSpan(const MutableSpan<StructT> data)
+ : VMutableArrayImpl<ElemT>(data.size()), data_(data.data())
+ {
+ }
+
+ private:
+ ElemT get(const int64_t index) const override
+ {
+ return GetFunc(data_[index]);
+ }
+
+ void set(const int64_t index, ElemT value) override
+ {
+ SetFunc(data_[index], std::move(value));
+ }
+
+ void materialize(IndexMask mask, MutableSpan<ElemT> r_span) const override
+ {
+ ElemT *dst = r_span.data();
+ mask.foreach_index([&](const int64_t i) { dst[i] = GetFunc(data_[i]); });
+ }
+
+ void materialize_to_uninitialized(IndexMask mask, MutableSpan<ElemT> r_span) const override
+ {
+ ElemT *dst = r_span.data();
+ mask.foreach_index([&](const int64_t i) { new (dst + i) ElemT(GetFunc(data_[i])); });
+ }
+
+ bool may_have_ownership() const override
+ {
+ return false;
+ }
+};
+
+namespace detail {
+
+/**
+ * Struct that can be passed as `ExtraInfo` into an #Any.
+ * This struct is only intended to be used by #VArrayCommon.
+ */
+template<typename T> struct VArrayAnyExtraInfo {
+ /**
+ * Gets the virtual array that is stored at the given pointer.
+ */
+ const VArrayImpl<T> *(*get_varray)(const void *buffer) =
+ [](const void *UNUSED(buffer)) -> const VArrayImpl<T> * { return nullptr; };
+
+ template<typename StorageT> static VArrayAnyExtraInfo get()
+ {
+ /* These are the only allowed types in the #Any. */
+ static_assert(std::is_base_of_v<VArrayImpl<T>, StorageT> ||
+ std::is_same_v<StorageT, const VArrayImpl<T> *> ||
+ std::is_same_v<StorageT, std::shared_ptr<const VArrayImpl<T>>>);
+
+ /* Depending on how the virtual array implementation is stored in the #Any, a different
+ * #get_varray function is required. */
+ if constexpr (std::is_base_of_v<VArrayImpl<T>, StorageT>) {
+ return {[](const void *buffer) {
+ return static_cast<const VArrayImpl<T> *>((const StorageT *)buffer);
+ }};
+ }
+ else if constexpr (std::is_same_v<StorageT, const VArrayImpl<T> *>) {
+ return {[](const void *buffer) { return *(const StorageT *)buffer; }};
+ }
+ else if constexpr (std::is_same_v<StorageT, std::shared_ptr<const VArrayImpl<T>>>) {
+ return {[](const void *buffer) { return ((const StorageT *)buffer)->get(); }};
+ }
+ else {
+ BLI_assert_unreachable();
+ return {};
+ }
+ }
+};
+
+} // namespace detail
+
+/**
+ * Utility class to reduce code duplication for methods available on #VArray and #VMutableArray.
+ * Deriving #VMutableArray from #VArray would have some issues:
+ * - Static methods on #VArray would also be available on #VMutableArray.
+ * - It would allow assigning a #VArray to a #VMutableArray under some circumstances which is not
+ * allowed and could result in hard to find bugs.
+ */
+template<typename T> class VArrayCommon {
+ protected:
+ /**
+ * Store the virtual array implementation in an #Any. This makes it easy to avoid a memory
+ * allocation if the implementation is small enough and is copyable. This is the case for the
+ * most common virtual arrays.
+ * Other virtual array implementations are typically stored as #std::shared_ptr. That works even
+ * when the implementation itself is not copyable and makes copying #VArrayCommon cheaper.
+ */
+ using Storage = Any<detail::VArrayAnyExtraInfo<T>, 24, 8>;
+
+ /**
+ * Pointer to the currently contained virtual array implementation. This is allowed to be null.
+ */
+ const VArrayImpl<T> *impl_ = nullptr;
+ /**
+ * Does the memory management for the virtual array implementation. It contains one of the
+ * following:
+ * - Inlined subclass of #VArrayImpl.
+ * - Non-owning pointer to a #VArrayImpl.
+ * - Shared pointer to a #VArrayImpl.
+ */
+ Storage storage_;
+
+ protected:
+ VArrayCommon() = default;
+
+ /** Copy constructor. */
+ VArrayCommon(const VArrayCommon &other) : storage_(other.storage_)
+ {
+ impl_ = this->impl_from_storage();
+ }
+
+ /** Move constructor. */
+ VArrayCommon(VArrayCommon &&other) noexcept : storage_(std::move(other.storage_))
+ {
+ impl_ = this->impl_from_storage();
+ other.storage_.reset();
+ other.impl_ = nullptr;
+ }
+
+ /**
+ * Wrap an existing #VArrayImpl and don't take ownership of it. This should rarely be used in
+ * practice.
+ */
+ VArrayCommon(const VArrayImpl<T> *impl) : impl_(impl)
+ {
+ storage_ = impl_;
+ }
+
+ /**
+ * Wrap an existing #VArrayImpl that is contained in a #std::shared_ptr. This takes ownership.
+ */
+ VArrayCommon(std::shared_ptr<const VArrayImpl<T>> impl) : impl_(impl.get())
+ {
+ if (impl) {
+ storage_ = std::move(impl);
+ }
+ }
+
+ /**
+ * Replace the contained #VArrayImpl.
+ */
+ template<typename ImplT, typename... Args> void emplace(Args &&...args)
+ {
+ /* Make sure we are actually constructing a #VArrayImpl. */
+ static_assert(std::is_base_of_v<VArrayImpl<T>, ImplT>);
+ if constexpr (std::is_copy_constructible_v<ImplT> && Storage::template is_inline_v<ImplT>) {
+ /* Only inline the implementatiton when it is copyable and when it fits into the inline
+ * buffer of the storage. */
+ impl_ = &storage_.template emplace<ImplT>(std::forward<Args>(args)...);
+ }
+ else {
+ /* If it can't be inlined, create a new #std::shared_ptr instead and store that in the
+ * storage. */
+ std::shared_ptr<const VArrayImpl<T>> ptr = std::make_shared<ImplT>(
+ std::forward<Args>(args)...);
+ impl_ = &*ptr;
+ storage_ = std::move(ptr);
+ }
+ }
+
+ /** Utility to implement a copy assignment operator in a subclass. */
+ void copy_from(const VArrayCommon &other)
+ {
+ if (this == &other) {
+ return;
+ }
+ storage_ = other.storage_;
+ impl_ = this->impl_from_storage();
+ }
+
+ /** Utility to implement a move assignment operator in a subclass. */
+ void move_from(VArrayCommon &&other) noexcept
+ {
+ if (this == &other) {
+ return;
+ }
+ storage_ = std::move(other.storage_);
+ impl_ = this->impl_from_storage();
+ other.storage_.reset();
+ other.impl_ = nullptr;
+ }
+
+ /** Get a pointer to the virtual array implementation that is currently stored in #storage_, or
+ * null. */
+ const VArrayImpl<T> *impl_from_storage() const
+ {
+ return storage_.extra_info().get_varray(storage_.get());
+ }
+
+ public:
+ /** Return false when there is no virtual array implementation currently. */
+ operator bool() const
+ {
+ return impl_ != nullptr;
+ }
+
+ /**
+ * Get the element at a specific index.
+ * \note: This can't return a reference because the value may be computed on the fly. This also
+ * implies that one can not use this method for assignments.
+ */
+ T operator[](const int64_t index) const
+ {
+ BLI_assert(*this);
+ BLI_assert(index >= 0);
+ BLI_assert(index < this->size());
+ return impl_->get(index);
+ }
+
+ /**
+ * Same as the #operator[] but is sometimes easier to use when one has a pointer to a virtual
+ * array.
+ */
+ T get(const int64_t index) const
+ {
+ return (*this)[index];
+ }
+
+ /**
+ * Return the size of the virtual array. It's allowed to call this method even when there is no
+ * virtual array. In this case 0 is returned.
+ */
+ int64_t size() const
+ {
+ if (impl_ == nullptr) {
+ return 0;
+ }
+ return impl_->size();
+ }
+
+ /** True when the size is zero or when there is no virtual array. */
+ bool is_empty() const
+ {
+ return this->size() == 0;
+ }
+
+ IndexRange index_range() const
+ {
+ return IndexRange(this->size());
+ }
+
+ /** Return true when the virtual array is stored as a span internally. */
+ bool is_span() const
+ {
+ BLI_assert(*this);
+ if (this->is_empty()) {
+ return true;
+ }
+ return impl_->is_span();
+ }
+
+ /**
+ * Returns the internally used span of the virtual array. This invokes undefined behavior is the
+ * virtual array is not stored as a span internally.
+ */
+ Span<T> get_internal_span() const
+ {
+ BLI_assert(this->is_span());
+ if (this->is_empty()) {
+ return {};
+ }
+ return impl_->get_internal_span();
+ }
+
+ /** Return true when the virtual array returns the same value for every index. */
+ bool is_single() const
+ {
+ BLI_assert(*this);
+ if (impl_->size() == 1) {
+ return true;
+ }
+ return impl_->is_single();
+ }
+
+ /**
+ * Return the value that is returned for every index. This invokes undefined behavior if the
+ * virtual array would not return the same value for every index.
+ */
+ T get_internal_single() const
+ {
+ BLI_assert(this->is_single());
+ if (impl_->size() == 1) {
+ return impl_->get(0);
+ }
+ return impl_->get_internal_single();
+ }
+
+ /** Copy the entire virtual array into a span. */
+ void materialize(MutableSpan<T> r_span) const
+ {
+ this->materialize(IndexMask(this->size()), r_span);
+ }
+
+ /** Copy some indices of the virtual array into a span. */
+ void materialize(IndexMask mask, MutableSpan<T> r_span) const
+ {
+ BLI_assert(mask.min_array_size() <= this->size());
+ impl_->materialize(mask, r_span);
+ }
+
+ void materialize_to_uninitialized(MutableSpan<T> r_span) const
+ {
+ this->materialize_to_uninitialized(IndexMask(this->size()), r_span);
+ }
+
+ void materialize_to_uninitialized(IndexMask mask, MutableSpan<T> r_span) const
+ {
+ BLI_assert(mask.min_array_size() <= this->size());
+ impl_->materialize_to_uninitialized(mask, r_span);
+ }
+
+ /** See #GVArrayImpl::try_assign_GVArray. */
+ bool try_assign_GVArray(fn::GVArray &varray) const
+ {
+ return impl_->try_assign_GVArray(varray);
+ }
+
+ /** See #GVArrayImpl::may_have_ownership. */
+ bool may_have_ownership() const
+ {
+ return impl_->may_have_ownership();
+ }
+};
+
+template<typename T> class VMutableArray;
+
+/**
+ * A #VArray wraps a virtual array implementation and provides easy access to its elements. It can
+ * be copied and moved. While it is relatively small, it should still be passed by reference if
+ * possible (other than e.g. #Span).
+ */
+template<typename T> class VArray : public VArrayCommon<T> {
+ friend VMutableArray<T>;
+
+ public:
+ VArray() = default;
+ VArray(const VArray &other) = default;
+ VArray(VArray &&other) noexcept = default;
+
+ VArray(const VArrayImpl<T> *impl) : VArrayCommon<T>(impl)
+ {
+ }
+
+ VArray(std::shared_ptr<const VArrayImpl<T>> impl) : VArrayCommon<T>(std::move(impl))
+ {
+ }
+
+ /**
+ * Construct a new virtual array for a custom #VArrayImpl.
+ */
+ template<typename ImplT, typename... Args> static VArray For(Args &&...args)
+ {
+ static_assert(std::is_base_of_v<VArrayImpl<T>, ImplT>);
+ VArray varray;
+ varray.template emplace<ImplT>(std::forward<Args>(args)...);
+ return varray;
+ }
+
+ /**
+ * Construct a new virtual array that has the same value at every index.
+ */
+ static VArray ForSingle(T value, const int64_t size)
+ {
+ return VArray::For<VArrayImpl_For_Single<T>>(std::move(value), size);
+ }
+
+ /**
+ * Construct a new virtual array for an existing span. This does not take ownership of the
+ * underlying memory.
+ */
+ static VArray ForSpan(Span<T> values)
+ {
+ return VArray::For<VArrayImpl_For_Span_final<T>>(values);
+ }
+
+ /**
+ * Construct a new virtual that will invoke the provided function whenever an element is
+ * accessed.
+ */
+ template<typename GetFunc> static VArray ForFunc(const int64_t size, GetFunc get_func)
+ {
+ return VArray::For<VArrayImpl_For_Func<T, decltype(get_func)>>(size, std::move(get_func));
+ }
+
+ /**
+ * Construct a new virtual array for an existing span with a mapping function. This does not take
+ * ownership of the span.
+ */
+ template<typename StructT, T (*GetFunc)(const StructT &)>
+ static VArray ForDerivedSpan(Span<StructT> values)
+ {
+ return VArray::For<VArrayImpl_For_DerivedSpan<StructT, T, GetFunc>>(values);
+ }
+
+ /**
+ * Construct a new virtual array for an existing container. Every container that lays out the
+ * elements in a plain array works. This takes ownership of the passed in container. If that is
+ * not desired, use #ForSpan instead.
+ */
+ template<typename ContainerT> static VArray ForContainer(ContainerT container)
+ {
+ return VArray::For<VArrayImpl_For_ArrayContainer<ContainerT>>(std::move(container));
+ }
+
+ VArray &operator=(const VArray &other)
+ {
+ this->copy_from(other);
+ return *this;
+ }
+
+ VArray &operator=(VArray &&other) noexcept
+ {
+ this->move_from(std::move(other));
+ return *this;
+ }
+};
+
+/**
+ * Similar to #VArray but references a virtual array that can be modified.
+ */
+template<typename T> class VMutableArray : public VArrayCommon<T> {
+ public:
+ VMutableArray() = default;
+ VMutableArray(const VMutableArray &other) = default;
+ VMutableArray(VMutableArray &&other) noexcept = default;
+
+ VMutableArray(const VMutableArrayImpl<T> *impl) : VArrayCommon<T>(impl)
+ {
+ }
+
+ VMutableArray(std::shared_ptr<const VMutableArrayImpl<T>> impl)
+ : VArrayCommon<T>(std::move(impl))
+ {
+ }
+
+ /**
+ * Construct a new virtual array for a custom #VMutableArrayImpl.
+ */
+ template<typename ImplT, typename... Args> static VMutableArray For(Args &&...args)
+ {
+ static_assert(std::is_base_of_v<VMutableArrayImpl<T>, ImplT>);
+ VMutableArray varray;
+ varray.template emplace<ImplT>(std::forward<Args>(args)...);
+ return varray;
+ }
+
+ /**
+ * Construct a new virtual array for an existing span. This does not take ownership of the span.
+ */
+ static VMutableArray ForSpan(MutableSpan<T> values)
+ {
+ return VMutableArray::For<VMutableArrayImpl_For_MutableSpan_final<T>>(values);
+ }
+
+ /**
+ * Construct a new virtual array for an existing span with a mapping function. This does not take
+ * ownership of the span.
+ */
+ template<typename StructT, T (*GetFunc)(const StructT &), void (*SetFunc)(StructT &, T)>
+ static VMutableArray ForDerivedSpan(MutableSpan<StructT> values)
+ {
+ return VMutableArray::For<VMutableArrayImpl_For_DerivedSpan<StructT, T, GetFunc, SetFunc>>(
+ values);
+ }
+
+ /** Convert to a #VArray by copying. */
+ operator VArray<T>() const &
+ {
+ VArray<T> varray;
+ varray.copy_from(*this);
+ return varray;
+ }
+
+ /** Convert to a #VArray by moving. */
+ operator VArray<T>() &&noexcept
+ {
+ VArray<T> varray;
+ varray.move_from(std::move(*this));
+ return varray;
+ }
+
+ VMutableArray &operator=(const VMutableArray &other)
+ {
+ this->copy_from(other);
+ return *this;
+ }
+
+ VMutableArray &operator=(VMutableArray &&other) noexcept
+ {
+ this->move_from(std::move(other));
+ return *this;
+ }
+
+ /**
+ * Get access to the internal span. This invokes undefined behavior if the #is_span returned
+ * false.
+ */
+ MutableSpan<T> get_internal_span() const
+ {
+ BLI_assert(this->is_span());
+ const Span<T> span = this->impl_->get_internal_span();
+ return MutableSpan<T>(const_cast<T *>(span.data()), span.size());
+ }
+
+ /**
+ * Set the value at the given index.
+ */
+ void set(const int64_t index, T value)
+ {
+ BLI_assert(index >= 0);
+ BLI_assert(index < this->size());
+ this->get_impl()->set(index, std::move(value));
+ }
+
+ /**
+ * Copy the values from the source span to all elements in the virtual array.
+ */
+ void set_all(Span<T> src)
+ {
+ BLI_assert(src.size() == this->size());
+ this->get_impl()->set_all(src);
+ }
+
+ /** See #GVMutableArrayImpl::try_assign_GVMutableArray. */
+ bool try_assign_GVMutableArray(fn::GVMutableArray &varray) const
+ {
+ return this->get_impl()->try_assign_GVMutableArray(varray);
+ }
+
+ private:
+ /** Utility to get the pointer to the wrapped #VMutableArrayImpl. */
+ VMutableArrayImpl<T> *get_impl() const
+ {
+ /* This cast is valid by the invariant that a #VMutableArray->impl_ is always a
+ * #VMutableArrayImpl. */
+ return (VMutableArrayImpl<T> *)this->impl_;
+ }
+};
+
+/**
* In many cases a virtual array is a span internally. In those cases, access to individual could
* be much more efficient than calling a virtual method. When the underlying virtual array is not a
* span, this class allocates a new array and copies the values over.
@@ -401,11 +1026,11 @@ template<typename T> class VArray_For_Single final : public VArray<T> {
*/
template<typename T> class VArray_Span final : public Span<T> {
private:
- const VArray<T> &varray_;
+ VArray<T> varray_;
Array<T> owned_data_;
public:
- VArray_Span(const VArray<T> &varray) : Span<T>(), varray_(varray)
+ VArray_Span(VArray<T> varray) : Span<T>(), varray_(std::move(varray))
{
this->size_ = varray_.size();
if (varray_.is_span()) {
@@ -421,7 +1046,7 @@ template<typename T> class VArray_Span final : public Span<T> {
};
/**
- * Same as VArray_Span, but for a mutable span.
+ * Same as #VArray_Span, but for a mutable span.
* The important thing to note is that when changing this span, the results might not be
* immediately reflected in the underlying virtual array (only when the virtual array is a span
* internally). The #save method can be used to write all changes to the underlying virtual array,
@@ -429,7 +1054,7 @@ template<typename T> class VArray_Span final : public Span<T> {
*/
template<typename T> class VMutableArray_Span final : public MutableSpan<T> {
private:
- VMutableArray<T> &varray_;
+ VMutableArray<T> varray_;
Array<T> owned_data_;
bool save_has_been_called_ = false;
bool show_not_saved_warning_ = true;
@@ -437,8 +1062,8 @@ template<typename T> class VMutableArray_Span final : public MutableSpan<T> {
public:
/* Create a span for any virtual array. This is cheap when the virtual array is a span itself. If
* not, a new array has to be allocated as a wrapper for the underlying virtual array. */
- VMutableArray_Span(VMutableArray<T> &varray, const bool copy_values_to_span = true)
- : MutableSpan<T>(), varray_(varray)
+ VMutableArray_Span(VMutableArray<T> varray, const bool copy_values_to_span = true)
+ : MutableSpan<T>(), varray_(std::move(varray))
{
this->size_ = varray_.size();
if (varray_.is_span()) {
@@ -483,106 +1108,6 @@ template<typename T> class VMutableArray_Span final : public MutableSpan<T> {
};
/**
- * This class makes it easy to create a virtual array for an existing function or lambda. The
- * `GetFunc` should take a single `index` argument and return the value at that index.
- */
-template<typename T, typename GetFunc> class VArray_For_Func final : public VArray<T> {
- private:
- GetFunc get_func_;
-
- public:
- VArray_For_Func(const int64_t size, GetFunc get_func)
- : VArray<T>(size), get_func_(std::move(get_func))
- {
- }
-
- private:
- T get_impl(const int64_t index) const override
- {
- return get_func_(index);
- }
-
- void materialize_impl(IndexMask mask, MutableSpan<T> r_span) const override
- {
- T *dst = r_span.data();
- mask.foreach_index([&](const int64_t i) { dst[i] = get_func_(i); });
- }
-
- void materialize_to_uninitialized_impl(IndexMask mask, MutableSpan<T> r_span) const override
- {
- T *dst = r_span.data();
- mask.foreach_index([&](const int64_t i) { new (dst + i) T(get_func_(i)); });
- }
-};
-
-template<typename StructT, typename ElemT, ElemT (*GetFunc)(const StructT &)>
-class VArray_For_DerivedSpan : public VArray<ElemT> {
- private:
- const StructT *data_;
-
- public:
- VArray_For_DerivedSpan(const Span<StructT> data) : VArray<ElemT>(data.size()), data_(data.data())
- {
- }
-
- private:
- ElemT get_impl(const int64_t index) const override
- {
- return GetFunc(data_[index]);
- }
-
- void materialize_impl(IndexMask mask, MutableSpan<ElemT> r_span) const override
- {
- ElemT *dst = r_span.data();
- mask.foreach_index([&](const int64_t i) { dst[i] = GetFunc(data_[i]); });
- }
-
- void materialize_to_uninitialized_impl(IndexMask mask, MutableSpan<ElemT> r_span) const override
- {
- ElemT *dst = r_span.data();
- mask.foreach_index([&](const int64_t i) { new (dst + i) ElemT(GetFunc(data_[i])); });
- }
-};
-
-template<typename StructT,
- typename ElemT,
- ElemT (*GetFunc)(const StructT &),
- void (*SetFunc)(StructT &, ElemT)>
-class VMutableArray_For_DerivedSpan : public VMutableArray<ElemT> {
- private:
- StructT *data_;
-
- public:
- VMutableArray_For_DerivedSpan(const MutableSpan<StructT> data)
- : VMutableArray<ElemT>(data.size()), data_(data.data())
- {
- }
-
- private:
- ElemT get_impl(const int64_t index) const override
- {
- return GetFunc(data_[index]);
- }
-
- void set_impl(const int64_t index, ElemT value) override
- {
- SetFunc(data_[index], std::move(value));
- }
-
- void materialize_impl(IndexMask mask, MutableSpan<ElemT> r_span) const override
- {
- ElemT *dst = r_span.data();
- mask.foreach_index([&](const int64_t i) { dst[i] = GetFunc(data_[i]); });
- }
-
- void materialize_to_uninitialized_impl(IndexMask mask, MutableSpan<ElemT> r_span) const override
- {
- ElemT *dst = r_span.data();
- mask.foreach_index([&](const int64_t i) { new (dst + i) ElemT(GetFunc(data_[i])); });
- }
-};
-
-/**
* Generate multiple versions of the given function optimized for different virtual arrays.
* One has to be careful with nesting multiple devirtualizations, because that results in an
* exponential number of function instantiations (increasing compile time and binary size).
@@ -596,15 +1121,14 @@ inline void devirtualize_varray(const VArray<T> &varray, const Func &func, bool
/* Support disabling the devirtualization to simplify benchmarking. */
if (enable) {
if (varray.is_single()) {
- /* `VArray_For_Single` can be used for devirtualization, because it is declared `final`. */
- const VArray_For_Single<T> varray_single{varray.get_internal_single(), varray.size()};
- func(varray_single);
+ /* `VArrayImpl_For_Single` can be used for devirtualization, because it is declared `final`.
+ */
+ func(VArray<T>::ForSingle(varray.get_internal_single(), varray.size()));
return;
}
if (varray.is_span()) {
- /* `VArray_For_Span` can be used for devirtualization, because it is declared `final`. */
- const VArray_For_Span<T> varray_span{varray.get_internal_span()};
- func(varray_span);
+ /* `VArrayImpl_For_Span` can be used for devirtualization, because it is declared `final`. */
+ func(VArray<T>::ForSpan(varray.get_internal_span()));
return;
}
}
@@ -629,27 +1153,23 @@ inline void devirtualize_varray2(const VArray<T1> &varray1,
const bool is_single1 = varray1.is_single();
const bool is_single2 = varray2.is_single();
if (is_span1 && is_span2) {
- const VArray_For_Span<T1> varray1_span{varray1.get_internal_span()};
- const VArray_For_Span<T2> varray2_span{varray2.get_internal_span()};
- func(varray1_span, varray2_span);
+ func(VArray<T1>::ForSpan(varray1.get_internal_span()),
+ VArray<T2>::ForSpan(varray2.get_internal_span()));
return;
}
if (is_span1 && is_single2) {
- const VArray_For_Span<T1> varray1_span{varray1.get_internal_span()};
- const VArray_For_Single<T2> varray2_single{varray2.get_internal_single(), varray2.size()};
- func(varray1_span, varray2_single);
+ func(VArray<T1>::ForSpan(varray1.get_internal_span()),
+ VArray<T2>::ForSingle(varray2.get_internal_single(), varray2.size()));
return;
}
if (is_single1 && is_span2) {
- const VArray_For_Single<T1> varray1_single{varray1.get_internal_single(), varray1.size()};
- const VArray_For_Span<T2> varray2_span{varray2.get_internal_span()};
- func(varray1_single, varray2_span);
+ func(VArray<T1>::ForSingle(varray1.get_internal_single(), varray1.size()),
+ VArray<T2>::ForSpan(varray2.get_internal_span()));
return;
}
if (is_single1 && is_single2) {
- const VArray_For_Single<T1> varray1_single{varray1.get_internal_single(), varray1.size()};
- const VArray_For_Single<T2> varray2_single{varray2.get_internal_single(), varray2.size()};
- func(varray1_single, varray2_single);
+ func(VArray<T1>::ForSingle(varray1.get_internal_single(), varray1.size()),
+ VArray<T2>::ForSingle(varray2.get_internal_single(), varray2.size()));
return;
}
}
diff --git a/source/blender/blenlib/CMakeLists.txt b/source/blender/blenlib/CMakeLists.txt
index 7db984aef5c..29493c799b3 100644
--- a/source/blender/blenlib/CMakeLists.txt
+++ b/source/blender/blenlib/CMakeLists.txt
@@ -165,6 +165,7 @@ set(SRC
BLI_alloca.h
BLI_allocator.hh
+ BLI_any.hh
BLI_args.h
BLI_array.h
BLI_array.hh
@@ -411,6 +412,7 @@ blender_add_lib(bf_blenlib "${SRC}" "${INC}" "${INC_SYS}" "${LIB}")
if(WITH_GTESTS)
set(TEST_SRC
+ tests/BLI_any_test.cc
tests/BLI_array_store_test.cc
tests/BLI_array_test.cc
tests/BLI_array_utils_test.cc
diff --git a/source/blender/blenlib/intern/BLI_mempool.c b/source/blender/blenlib/intern/BLI_mempool.c
index f968799326a..bd6a124c7cb 100644
--- a/source/blender/blenlib/intern/BLI_mempool.c
+++ b/source/blender/blenlib/intern/BLI_mempool.c
@@ -126,7 +126,7 @@ struct BLI_mempool {
uint flag;
/* keeps aligned to 16 bits */
- /** Free element list. Interleaved into chunk datas. */
+ /** Free element list. Interleaved into chunk data. */
BLI_freenode *free;
/** Use to know how many chunks to keep for #BLI_mempool_clear. */
uint maxchunks;
diff --git a/source/blender/blenlib/intern/string.c b/source/blender/blenlib/intern/string.c
index e8be674b6c1..62c8625378d 100644
--- a/source/blender/blenlib/intern/string.c
+++ b/source/blender/blenlib/intern/string.c
@@ -1346,9 +1346,8 @@ void BLI_str_format_byte_unit(char dst[15], long long int bytes, const bool base
}
/**
- * Format a attribute domain to a up to 6 places (plus '\0' terminator) string using long number
- * names abbreviations. This function is designed to produce a compact representation of large
- * numbers.
+ * Format a count to up to 6 places (plus '\0' terminator) string using long number
+ * names abbreviations. Used to produce a compact representation of large numbers.
*
* 1 -> 1
* 15 -> 15
@@ -1362,8 +1361,7 @@ void BLI_str_format_byte_unit(char dst[15], long long int bytes, const bool base
* 1000000000 -> 1B
* ...
*
- * Dimension of 7 is the maximum length of the resulting string
- * A combination with 7 places would be -15.5K\0
+ * Length of 7 is the maximum of the resulting string, for example, `-15.5K\0`.
*/
void BLI_str_format_attribute_domain_size(char dst[7], int number_to_format)
{
diff --git a/source/blender/blenlib/tests/BLI_any_test.cc b/source/blender/blenlib/tests/BLI_any_test.cc
new file mode 100644
index 00000000000..226088cf3c7
--- /dev/null
+++ b/source/blender/blenlib/tests/BLI_any_test.cc
@@ -0,0 +1,108 @@
+/* Apache License, Version 2.0 */
+
+#include "BLI_any.hh"
+#include "BLI_map.hh"
+
+#include "testing/testing.h"
+
+namespace blender::tests {
+
+TEST(any, DefaultConstructor)
+{
+ Any a;
+ EXPECT_FALSE(a.has_value());
+}
+
+TEST(any, AssignInt)
+{
+ Any<> a = 5;
+ EXPECT_TRUE(a.has_value());
+ EXPECT_TRUE(a.is<int>());
+ EXPECT_FALSE(a.is<float>());
+ const int &value = a.get<int>();
+ EXPECT_EQ(value, 5);
+ a = 10;
+ EXPECT_EQ(value, 10);
+
+ Any b = a;
+ EXPECT_TRUE(b.has_value());
+ EXPECT_EQ(b.get<int>(), 10);
+
+ Any c = std::move(a);
+ EXPECT_TRUE(c);
+ EXPECT_EQ(c.get<int>(), 10);
+
+ EXPECT_EQ(a.get<int>(), 10); /* NOLINT: bugprone-use-after-move */
+
+ a.reset();
+ EXPECT_FALSE(a);
+}
+
+TEST(any, AssignMap)
+{
+ Any<> a = Map<int, int>();
+ EXPECT_TRUE(a.has_value());
+ EXPECT_TRUE((a.is<Map<int, int>>()));
+ EXPECT_FALSE((a.is<Map<int, float>>()));
+ Map<int, int> &map = a.get<Map<int, int>>();
+ map.add(4, 2);
+ EXPECT_EQ((a.get<Map<int, int>>().lookup(4)), 2);
+
+ Any b = a;
+ EXPECT_TRUE(b);
+ EXPECT_EQ((b.get<Map<int, int>>().lookup(4)), 2);
+
+ Any c = std::move(a);
+ c = c;
+ EXPECT_TRUE(b);
+ EXPECT_EQ((c.get<Map<int, int>>().lookup(4)), 2);
+
+ EXPECT_TRUE((a.get<Map<int, int>>().is_empty())); /* NOLINT: bugprone-use-after-move */
+}
+
+TEST(any, AssignAny)
+{
+ Any<> a = 5;
+ Any<> b = std::string("hello");
+ Any c;
+
+ Any z;
+ EXPECT_FALSE(z.has_value());
+
+ z = a;
+ EXPECT_TRUE(z.has_value());
+ EXPECT_EQ(z.get<int>(), 5);
+
+ z = b;
+ EXPECT_EQ(z.get<std::string>(), "hello");
+
+ z = c;
+ EXPECT_FALSE(z.has_value());
+
+ z = Any(std::in_place_type<Any<>>, a);
+ EXPECT_FALSE(z.is<int>());
+ EXPECT_TRUE(z.is<Any<>>());
+ EXPECT_EQ(z.get<Any<>>().get<int>(), 5);
+}
+
+struct ExtraSizeInfo {
+ size_t size;
+
+ template<typename T> static ExtraSizeInfo get()
+ {
+ return {sizeof(T)};
+ }
+};
+
+TEST(any, ExtraInfo)
+{
+ using MyAny = Any<ExtraSizeInfo>;
+
+ MyAny a = 5;
+ EXPECT_EQ(a.extra_info().size, sizeof(int));
+
+ a = std::string("hello");
+ EXPECT_EQ(a.extra_info().size, sizeof(std::string));
+}
+
+} // namespace blender::tests
diff --git a/source/blender/blenlib/tests/BLI_virtual_array_test.cc b/source/blender/blenlib/tests/BLI_virtual_array_test.cc
index a6d2ca10315..62b7b383831 100644
--- a/source/blender/blenlib/tests/BLI_virtual_array_test.cc
+++ b/source/blender/blenlib/tests/BLI_virtual_array_test.cc
@@ -12,7 +12,7 @@ namespace blender::tests {
TEST(virtual_array, Span)
{
std::array<int, 5> data = {3, 4, 5, 6, 7};
- VArray_For_Span<int> varray{data};
+ VArray<int> varray = VArray<int>::ForSpan(data);
EXPECT_EQ(varray.size(), 5);
EXPECT_EQ(varray.get(0), 3);
EXPECT_EQ(varray.get(4), 7);
@@ -23,7 +23,7 @@ TEST(virtual_array, Span)
TEST(virtual_array, Single)
{
- VArray_For_Single<int> varray{10, 4};
+ VArray<int> varray = VArray<int>::ForSingle(10, 4);
EXPECT_EQ(varray.size(), 4);
EXPECT_EQ(varray.get(0), 10);
EXPECT_EQ(varray.get(3), 10);
@@ -35,7 +35,7 @@ TEST(virtual_array, Array)
{
Array<int> array = {1, 2, 3, 5, 8};
{
- VArray_For_ArrayContainer varray{array};
+ VArray<int> varray = VArray<int>::ForContainer(array);
EXPECT_EQ(varray.size(), 5);
EXPECT_EQ(varray[0], 1);
EXPECT_EQ(varray[2], 3);
@@ -43,7 +43,7 @@ TEST(virtual_array, Array)
EXPECT_TRUE(varray.is_span());
}
{
- VArray_For_ArrayContainer varray{std::move(array)};
+ VArray<int> varray = VArray<int>::ForContainer(std::move(array));
EXPECT_EQ(varray.size(), 5);
EXPECT_EQ(varray[0], 1);
EXPECT_EQ(varray[2], 3);
@@ -51,7 +51,7 @@ TEST(virtual_array, Array)
EXPECT_TRUE(varray.is_span());
}
{
- VArray_For_ArrayContainer varray{array}; /* NOLINT: bugprone-use-after-move */
+ VArray<int> varray = VArray<int>::ForContainer(array); /* NOLINT: bugprone-use-after-move */
EXPECT_TRUE(varray.is_empty());
}
}
@@ -59,7 +59,7 @@ TEST(virtual_array, Array)
TEST(virtual_array, Vector)
{
Vector<int> vector = {9, 8, 7, 6};
- VArray_For_ArrayContainer varray{std::move(vector)};
+ VArray<int> varray = VArray<int>::ForContainer(std::move(vector));
EXPECT_EQ(varray.size(), 4);
EXPECT_EQ(varray[0], 9);
EXPECT_EQ(varray[3], 6);
@@ -68,7 +68,7 @@ TEST(virtual_array, Vector)
TEST(virtual_array, StdVector)
{
std::vector<int> vector = {5, 6, 7, 8};
- VArray_For_ArrayContainer varray{std::move(vector)};
+ VArray<int> varray = VArray<int>::ForContainer(std::move(vector));
EXPECT_EQ(varray.size(), 4);
EXPECT_EQ(varray[0], 5);
EXPECT_EQ(varray[1], 6);
@@ -77,7 +77,7 @@ TEST(virtual_array, StdVector)
TEST(virtual_array, StdArray)
{
std::array<int, 4> array = {2, 3, 4, 5};
- VArray_For_ArrayContainer varray{array};
+ VArray<int> varray = VArray<int>::ForContainer(std::move(array));
EXPECT_EQ(varray.size(), 4);
EXPECT_EQ(varray[0], 2);
EXPECT_EQ(varray[1], 3);
@@ -86,7 +86,7 @@ TEST(virtual_array, StdArray)
TEST(virtual_array, VectorSet)
{
VectorSet<int> vector_set = {5, 3, 7, 3, 3, 5, 1};
- VArray_For_ArrayContainer varray{std::move(vector_set)};
+ VArray<int> varray = VArray<int>::ForContainer(std::move(vector_set));
EXPECT_TRUE(vector_set.is_empty()); /* NOLINT: bugprone-use-after-move. */
EXPECT_EQ(varray.size(), 4);
EXPECT_EQ(varray[0], 5);
@@ -98,7 +98,7 @@ TEST(virtual_array, VectorSet)
TEST(virtual_array, Func)
{
auto func = [](int64_t index) { return (int)(index * index); };
- VArray_For_Func<int, decltype(func)> varray{10, func};
+ VArray<int> varray = VArray<int>::ForFunc(10, func);
EXPECT_EQ(varray.size(), 10);
EXPECT_EQ(varray[0], 0);
EXPECT_EQ(varray[3], 9);
@@ -108,7 +108,7 @@ TEST(virtual_array, Func)
TEST(virtual_array, AsSpan)
{
auto func = [](int64_t index) { return (int)(10 * index); };
- VArray_For_Func<int, decltype(func)> func_varray{10, func};
+ VArray<int> func_varray = VArray<int>::ForFunc(10, func);
VArray_Span span_varray{func_varray};
EXPECT_EQ(span_varray.size(), 10);
Span<int> span = span_varray;
@@ -134,13 +134,14 @@ TEST(virtual_array, DerivedSpan)
vector.append({3, 4, 5});
vector.append({1, 1, 1});
{
- VArray_For_DerivedSpan<std::array<int, 3>, int, get_x> varray{vector};
+ VArray<int> varray = VArray<int>::ForDerivedSpan<std::array<int, 3>, get_x>(vector);
EXPECT_EQ(varray.size(), 2);
EXPECT_EQ(varray[0], 3);
EXPECT_EQ(varray[1], 1);
}
{
- VMutableArray_For_DerivedSpan<std::array<int, 3>, int, get_x, set_x> varray{vector};
+ VMutableArray<int> varray =
+ VMutableArray<int>::ForDerivedSpan<std::array<int, 3>, get_x, set_x>(vector);
EXPECT_EQ(varray.size(), 2);
EXPECT_EQ(varray[0], 3);
EXPECT_EQ(varray[1], 1);
@@ -151,4 +152,32 @@ TEST(virtual_array, DerivedSpan)
}
}
+TEST(virtual_array, MutableToImmutable)
+{
+ std::array<int, 4> array = {4, 2, 6, 4};
+ {
+ VMutableArray<int> mutable_varray = VMutableArray<int>::ForSpan(array);
+ VArray<int> varray = mutable_varray;
+ EXPECT_TRUE(varray.is_span());
+ EXPECT_EQ(varray.size(), 4);
+ EXPECT_EQ(varray[1], 2);
+ EXPECT_EQ(mutable_varray.size(), 4);
+ }
+ {
+ VMutableArray<int> mutable_varray = VMutableArray<int>::ForSpan(array);
+ EXPECT_EQ(mutable_varray.size(), 4);
+ VArray<int> varray = std::move(mutable_varray);
+ EXPECT_TRUE(varray.is_span());
+ EXPECT_EQ(varray.size(), 4);
+ EXPECT_EQ(varray[1], 2);
+ EXPECT_EQ(mutable_varray.size(), 0); /* NOLINT: bugprone-use-after-move */
+ }
+ {
+ VArray<int> varray = VMutableArray<int>::ForSpan(array);
+ EXPECT_TRUE(varray.is_span());
+ EXPECT_EQ(varray.size(), 4);
+ EXPECT_EQ(varray[1], 2);
+ }
+}
+
} // namespace blender::tests
diff --git a/source/blender/blenloader/BLO_readfile.h b/source/blender/blenloader/BLO_readfile.h
index 22182edd070..e3a8fd2bf3f 100644
--- a/source/blender/blenloader/BLO_readfile.h
+++ b/source/blender/blenloader/BLO_readfile.h
@@ -241,7 +241,7 @@ typedef enum eBLOLibLinkFlags {
* #BLO_library_link_begin, #BLO_library_link_named_part & #BLO_library_link_end.
* Wrap these in parameters since it's important both functions receive matching values.
*/
-struct LibraryLink_Params {
+typedef struct LibraryLink_Params {
/** The current main database, e.g. #G_MAIN or `CTX_data_main(C)`. */
struct Main *bmain;
/** Options for linking, used for instantiating. */
@@ -257,7 +257,7 @@ struct LibraryLink_Params {
/** The active 3D viewport (only used to define local-view). */
const struct View3D *v3d;
} context;
-};
+} LibraryLink_Params;
void BLO_library_link_params_init(struct LibraryLink_Params *params,
struct Main *bmain,
diff --git a/source/blender/blenloader/intern/readblenentry.c b/source/blender/blenloader/intern/readblenentry.c
index 3306eb9e454..c0fdfa86907 100644
--- a/source/blender/blenloader/intern/readblenentry.c
+++ b/source/blender/blenloader/intern/readblenentry.c
@@ -347,6 +347,7 @@ LinkNode *BLO_blendhandle_get_previews(BlendHandle *bh, int ofblocktype, int *r_
case ID_GR: /* fall through */
case ID_SCE: /* fall through */
case ID_AC: /* fall through */
+ case ID_NT: /* fall through */
new_prv = MEM_callocN(sizeof(PreviewImage), "newpreview");
BLI_linklist_prepend(&previews, new_prv);
tot++;
diff --git a/source/blender/blenloader/intern/versioning_300.c b/source/blender/blenloader/intern/versioning_300.c
index 940a10a9e91..822ef2cda8d 100644
--- a/source/blender/blenloader/intern/versioning_300.c
+++ b/source/blender/blenloader/intern/versioning_300.c
@@ -1279,6 +1279,18 @@ static void version_geometry_nodes_set_position_node_offset(bNodeTree *ntree)
}
}
+static void version_node_tree_socket_id_delim(bNodeTree *ntree)
+{
+ LISTBASE_FOREACH (bNode *, node, &ntree->nodes) {
+ LISTBASE_FOREACH (bNodeSocket *, socket, &node->inputs) {
+ version_node_socket_id_delim(socket);
+ }
+ LISTBASE_FOREACH (bNodeSocket *, socket, &node->outputs) {
+ version_node_socket_id_delim(socket);
+ }
+ }
+}
+
static bool version_fix_seq_meta_range(Sequence *seq, void *user_data)
{
Scene *scene = (Scene *)user_data;
@@ -2308,35 +2320,11 @@ void blo_do_versions_300(FileData *fd, Library *UNUSED(lib), Main *bmain)
}
if (!MAIN_VERSION_ATLEAST(bmain, 300, 42)) {
- /* Update LibOverride operations regarding insertions in RNA collections (i.e. modifiers,
- * constraints and NLA tracks). */
- ID *id_iter;
- FOREACH_MAIN_ID_BEGIN (bmain, id_iter) {
- if (ID_IS_OVERRIDE_LIBRARY_REAL(id_iter)) {
- version_liboverride_rnacollections_insertion_animdata(id_iter);
- if (GS(id_iter->name) == ID_OB) {
- version_liboverride_rnacollections_insertion_object((Object *)id_iter);
- }
- }
- }
- FOREACH_MAIN_ID_END;
-
/* Use consistent socket identifiers for the math node.
* The code to make unique identifiers from the names was inconsistent. */
FOREACH_NODETREE_BEGIN (bmain, ntree, id) {
- if (ELEM(ntree->type, NTREE_SHADER, NTREE_GEOMETRY)) {
- LISTBASE_FOREACH (bNode *, node, &ntree->nodes) {
- if (node->type == SH_NODE_MATH) {
- bNodeSocket *value1 = ((bNodeSocket *)node->inputs.first)->next;
- bNodeSocket *value2 = value1->next;
- strcpy(value1->identifier, "Value_001");
- if (value2 != NULL) {
- /* This can be null when file is quite old so that the socket did not exist
- * (before 0406eb110332a8). */
- strcpy(value2->identifier, "Value_002");
- }
- }
- }
+ if (ntree->type != NTREE_CUSTOM) {
+ version_node_tree_socket_id_delim(ntree);
}
}
FOREACH_NODETREE_END;
@@ -2357,6 +2345,25 @@ void blo_do_versions_300(FileData *fd, Library *UNUSED(lib), Main *bmain)
}
}
+ /* Change minimum zoom to 0.05f in the node editor. */
+ LISTBASE_FOREACH (bScreen *, screen, &bmain->screens) {
+ LISTBASE_FOREACH (ScrArea *, area, &screen->areabase) {
+ LISTBASE_FOREACH (SpaceLink *, sl, &area->spacedata) {
+ if (sl->spacetype == SPACE_NODE) {
+ ListBase *regionbase = (sl == area->spacedata.first) ? &area->regionbase :
+ &sl->regionbase;
+ LISTBASE_FOREACH (ARegion *, region, regionbase) {
+ if (region->regiontype == RGN_TYPE_WINDOW) {
+ if (region->v2d.minzoom > 0.05f) {
+ region->v2d.minzoom = 0.05f;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
LISTBASE_FOREACH (Scene *, scene, &bmain->scenes) {
Editing *ed = SEQ_editing_get(scene);
/* Make sure range of meta strips is correct.
@@ -2369,6 +2376,24 @@ void blo_do_versions_300(FileData *fd, Library *UNUSED(lib), Main *bmain)
}
}
+ /* Special case to handle older in-dev 3.1 files, before change from 3.0 branch gets merged in
+ * master. */
+ if (!MAIN_VERSION_ATLEAST(bmain, 300, 42) ||
+ (bmain->versionfile == 301 && !MAIN_VERSION_ATLEAST(bmain, 301, 3))) {
+ /* Update LibOverride operations regarding insertions in RNA collections (i.e. modifiers,
+ * constraints and NLA tracks). */
+ ID *id_iter;
+ FOREACH_MAIN_ID_BEGIN (bmain, id_iter) {
+ if (ID_IS_OVERRIDE_LIBRARY_REAL(id_iter)) {
+ version_liboverride_rnacollections_insertion_animdata(id_iter);
+ if (GS(id_iter->name) == ID_OB) {
+ version_liboverride_rnacollections_insertion_object((Object *)id_iter);
+ }
+ }
+ }
+ FOREACH_MAIN_ID_END;
+ }
+
/**
* Versioning code until next subversion bump goes here.
*
@@ -2379,5 +2404,6 @@ void blo_do_versions_300(FileData *fd, Library *UNUSED(lib), Main *bmain)
* \note Keep this message at the bottom of the function.
*/
{
+ /* Keep this block, even when empty. */
}
}
diff --git a/source/blender/blenloader/intern/versioning_common.cc b/source/blender/blenloader/intern/versioning_common.cc
index c7ff496fa20..af765be619f 100644
--- a/source/blender/blenloader/intern/versioning_common.cc
+++ b/source/blender/blenloader/intern/versioning_common.cc
@@ -27,6 +27,7 @@
#include "BLI_listbase.h"
#include "BLI_string.h"
+#include "BLI_string_ref.hh"
#include "BKE_animsys.h"
#include "BKE_lib_id.h"
@@ -37,6 +38,8 @@
#include "versioning_common.h"
+using blender::StringRef;
+
ARegion *do_versions_add_region_if_not_found(ListBase *regionbase,
int region_type,
const char *name,
@@ -101,6 +104,30 @@ static void change_node_socket_name(ListBase *sockets, const char *old_name, con
}
}
+/**
+ * Convert `SocketName.001` unique name format to `SocketName_001`. Previously both were used.
+ */
+void version_node_socket_id_delim(bNodeSocket *socket)
+{
+ StringRef name = socket->name;
+ StringRef id = socket->identifier;
+
+ if (!id.startswith(name)) {
+ /* We only need to affect the case where the identifier starts with the name. */
+ return;
+ }
+
+ StringRef id_number = id.drop_known_prefix(name);
+ if (id_number.is_empty()) {
+ /* The name was already unique, and didn't need numbers at the end for the id. */
+ return;
+ }
+
+ if (id_number.startswith(".")) {
+ socket->identifier[name.size()] = '_';
+ }
+}
+
void version_node_socket_name(bNodeTree *ntree,
const int node_type,
const char *old_name,
@@ -127,9 +154,9 @@ void version_node_input_socket_name(bNodeTree *ntree,
}
void version_node_output_socket_name(bNodeTree *ntree,
- const int node_type,
- const char *old_name,
- const char *new_name)
+ const int node_type,
+ const char *old_name,
+ const char *new_name)
{
LISTBASE_FOREACH (bNode *, node, &ntree->nodes) {
if (node->type == node_type) {
diff --git a/source/blender/blenloader/intern/versioning_common.h b/source/blender/blenloader/intern/versioning_common.h
index ed1cafdca33..7f179800ddd 100644
--- a/source/blender/blenloader/intern/versioning_common.h
+++ b/source/blender/blenloader/intern/versioning_common.h
@@ -62,6 +62,8 @@ void version_node_socket_index_animdata(
void version_node_id(struct bNodeTree *ntree, const int node_type, const char *new_name);
+void version_node_socket_id_delim(bNodeSocket *socket);
+
#ifdef __cplusplus
}
#endif
diff --git a/source/blender/blenloader/intern/versioning_userdef.c b/source/blender/blenloader/intern/versioning_userdef.c
index 809adc493f4..0e5e0b76f43 100644
--- a/source/blender/blenloader/intern/versioning_userdef.c
+++ b/source/blender/blenloader/intern/versioning_userdef.c
@@ -321,14 +321,22 @@ static void do_versions_theme(const UserDef *userdef, bTheme *btheme)
btheme->space_node.grid_levels = 7;
}
- if (!USER_VERSION_ATLEAST(300, 40)) {
+ if (!USER_VERSION_ATLEAST(300, 41)) {
memcpy(btheme, &U_theme_default, sizeof(*btheme));
}
- if (!USER_VERSION_ATLEAST(300, 41)) {
+ /* Again reset the theme, but only if stored with an early 3.1 alpha version. Some changes were
+ * done in the release branch and then merged into the 3.1 branch (master). So the previous reset
+ * wouldn't work for people who saved their preferences with a 3.1 build meanwhile. But we still
+ * don't want to reset theme changes stored in the eventual 3.0 release once opened in a 3.1
+ * build. */
+ if (userdef->versionfile > 300 && !USER_VERSION_ATLEAST(301, 1)) {
memcpy(btheme, &U_theme_default, sizeof(*btheme));
}
+ if (!USER_VERSION_ATLEAST(301, 2)) {
+ FROM_DEFAULT_V4_UCHAR(space_sequencer.mask);
+ }
/**
* Versioning code until next subversion bump goes here.
*
@@ -704,8 +712,6 @@ void blo_do_versions_userdef(UserDef *userdef)
}
if (!USER_VERSION_ATLEAST(280, 38)) {
-
- /* (keep this block even if it becomes empty). */
copy_v4_fl4(userdef->light_param[0].vec, -0.580952, 0.228571, 0.781185, 0.0);
copy_v4_fl4(userdef->light_param[0].col, 0.900000, 0.900000, 0.900000, 1.000000);
copy_v4_fl4(userdef->light_param[0].spec, 0.318547, 0.318547, 0.318547, 1.000000);
@@ -738,8 +744,6 @@ void blo_do_versions_userdef(UserDef *userdef)
}
if (!USER_VERSION_ATLEAST(280, 41)) {
- /* (keep this block even if it becomes empty). */
-
if (userdef->pie_tap_timeout == 0) {
userdef->pie_tap_timeout = 20;
}
@@ -796,7 +800,6 @@ void blo_do_versions_userdef(UserDef *userdef)
}
if (!USER_VERSION_ATLEAST(280, 62)) {
- /* (keep this block even if it becomes empty). */
if (userdef->vbotimeout == 0) {
userdef->vbocollectrate = 60;
userdef->vbotimeout = 120;
diff --git a/source/blender/blenloader/tests/blendfile_loading_base_test.cc b/source/blender/blenloader/tests/blendfile_loading_base_test.cc
index 21156868655..a4a5ced070d 100644
--- a/source/blender/blenloader/tests/blendfile_loading_base_test.cc
+++ b/source/blender/blenloader/tests/blendfile_loading_base_test.cc
@@ -67,7 +67,6 @@ void BlendfileLoadingBaseTest::SetUpTestCase()
BKE_idtype_init();
BKE_appdir_init();
IMB_init();
- BKE_images_init();
BKE_modifier_init();
DEG_register_node_types();
RNA_init();
diff --git a/source/blender/bmesh/operators/bmo_fill_edgeloop.c b/source/blender/bmesh/operators/bmo_fill_edgeloop.c
index da4567d947b..f366aede2ab 100644
--- a/source/blender/bmesh/operators/bmo_fill_edgeloop.c
+++ b/source/blender/bmesh/operators/bmo_fill_edgeloop.c
@@ -85,7 +85,7 @@ void bmo_edgeloop_fill_exec(BMesh *bm, BMOperator *op)
}
if (ok) {
- /* NOTE: in the case of multiple loops, this over-allocs (which is fine). */
+ /* NOTE: in the case of multiple loops, this over-allocates (which is fine). */
BMVert **f_verts = MEM_mallocN(sizeof(*verts) * totv, __func__);
BMIter eiter;
diff --git a/source/blender/bmesh/tests/bmesh_core_test.cc b/source/blender/bmesh/tests/bmesh_core_test.cc
index 202d16b09e3..3d6fabcbc2f 100644
--- a/source/blender/bmesh/tests/bmesh_core_test.cc
+++ b/source/blender/bmesh/tests/bmesh_core_test.cc
@@ -10,9 +10,9 @@ TEST(bmesh_core, BMVertCreate)
BMVert *bv1, *bv2, *bv3;
const float co1[3] = {1.0f, 2.0f, 0.0f};
- BMeshCreateParams bm_params;
- bm_params.use_toolflags = true;
- bm = BM_mesh_create(&bm_mesh_allocsize_default, &bm_params);
+ BMeshCreateParams bmesh_create_params{};
+ bmesh_create_params.use_toolflags = true;
+ bm = BM_mesh_create(&bm_mesh_allocsize_default, &bmesh_create_params);
EXPECT_EQ(bm->totvert, 0);
/* make a custom layer so we can see if it is copied properly */
BM_data_layer_add(bm, &bm->vdata, CD_PROP_FLOAT);
diff --git a/source/blender/compositor/operations/COM_CompositorOperation.cc b/source/blender/compositor/operations/COM_CompositorOperation.cc
index 354997ebd2e..696dbb1807c 100644
--- a/source/blender/compositor/operations/COM_CompositorOperation.cc
+++ b/source/blender/compositor/operations/COM_CompositorOperation.cc
@@ -155,7 +155,7 @@ void CompositorOperation::execute_region(rcti *rect, unsigned int /*tile_number*
if (rd->mode & R_BORDER && rd->mode & R_CROP) {
/**
* When using cropped render result, need to re-position area of interest,
- * so it'll natch bounds of render border within frame. By default, canvas
+ * so it'll match bounds of render border within frame. By default, canvas
* will be centered between full frame and cropped frame, so we use such
* scheme to map cropped coordinates to full-frame coordinates
*
diff --git a/source/blender/draw/CMakeLists.txt b/source/blender/draw/CMakeLists.txt
index 0baf994d978..b8ca22d33d3 100644
--- a/source/blender/draw/CMakeLists.txt
+++ b/source/blender/draw/CMakeLists.txt
@@ -112,8 +112,9 @@ set(SRC
intern/draw_view_data.cc
intern/smaa_textures.c
engines/basic/basic_engine.c
- engines/image/image_engine.c
- engines/image/image_shader.c
+ engines/basic/basic_shader.c
+ engines/image/image_engine.cc
+ engines/image/image_shader.cc
engines/eevee/eevee_bloom.c
engines/eevee/eevee_cryptomatte.c
engines/eevee/eevee_data.c
@@ -214,13 +215,14 @@ set(SRC
intern/mesh_extractors/extract_mesh.h
intern/smaa_textures.h
engines/basic/basic_engine.h
+ engines/basic/basic_private.h
engines/eevee/eevee_engine.h
engines/eevee/eevee_lightcache.h
engines/eevee/eevee_lut.h
engines/eevee/eevee_private.h
engines/external/external_engine.h
engines/image/image_engine.h
- engines/image/image_private.h
+ engines/image/image_private.hh
engines/workbench/workbench_engine.h
engines/workbench/workbench_private.h
engines/select/select_engine.h
diff --git a/source/blender/draw/engines/basic/basic_engine.c b/source/blender/draw/engines/basic/basic_engine.c
index f4fdb9d0912..8a825a7c81f 100644
--- a/source/blender/draw/engines/basic/basic_engine.c
+++ b/source/blender/draw/engines/basic/basic_engine.c
@@ -36,17 +36,10 @@
#include "GPU_shader.h"
#include "basic_engine.h"
-/* Shaders */
+#include "basic_private.h"
#define BASIC_ENGINE "BLENDER_BASIC"
-extern char datatoc_depth_frag_glsl[];
-extern char datatoc_depth_vert_glsl[];
-extern char datatoc_conservative_depth_geom_glsl[];
-
-extern char datatoc_common_view_lib_glsl[];
-extern char datatoc_common_pointcloud_lib_glsl[];
-
/* *********** LISTS *********** */
/* GPUViewport.storage
@@ -69,20 +62,8 @@ typedef struct BASIC_Data {
BASIC_StorageList *stl;
} BASIC_Data;
-typedef struct BASIC_Shaders {
- /* Depth Pre Pass */
- struct GPUShader *depth;
- struct GPUShader *pointcloud_depth;
- struct GPUShader *depth_conservative;
- struct GPUShader *pointcloud_depth_conservative;
-} BASIC_Shaders;
-
/* *********** STATIC *********** */
-static struct {
- BASIC_Shaders sh_data[GPU_SHADER_CFG_LEN];
-} e_data = {{{NULL}}}; /* Engine data */
-
typedef struct BASIC_PrivateData {
DRWShadingGroup *depth_shgrp[2];
DRWShadingGroup *depth_shgrp_cull[2];
@@ -91,74 +72,6 @@ typedef struct BASIC_PrivateData {
bool use_material_slot_selection;
} BASIC_PrivateData; /* Transient data */
-/* Functions */
-
-static void basic_engine_init(void *UNUSED(vedata))
-{
- const DRWContextState *draw_ctx = DRW_context_state_get();
- BASIC_Shaders *sh_data = &e_data.sh_data[draw_ctx->sh_cfg];
-
- /* Depth prepass */
- if (!sh_data->depth) {
- const GPUShaderConfigData *sh_cfg = &GPU_shader_cfg_data[draw_ctx->sh_cfg];
-
- sh_data->depth = GPU_shader_create_from_arrays({
- .vert = (const char *[]){sh_cfg->lib,
- datatoc_common_view_lib_glsl,
- datatoc_depth_vert_glsl,
- NULL},
- .frag = (const char *[]){datatoc_depth_frag_glsl, NULL},
- .defs = (const char *[]){sh_cfg->def, NULL},
- });
-
- sh_data->pointcloud_depth = GPU_shader_create_from_arrays({
- .vert = (const char *[]){sh_cfg->lib,
- datatoc_common_view_lib_glsl,
- datatoc_common_pointcloud_lib_glsl,
- datatoc_depth_vert_glsl,
- NULL},
- .frag = (const char *[]){datatoc_depth_frag_glsl, NULL},
- .defs = (const char *[]){sh_cfg->def,
- "#define POINTCLOUD\n",
- "#define INSTANCED_ATTR\n",
- "#define UNIFORM_RESOURCE_ID\n",
- NULL},
- });
-
- sh_data->depth_conservative = GPU_shader_create_from_arrays({
- .vert = (const char *[]){sh_cfg->lib,
- datatoc_common_view_lib_glsl,
- datatoc_depth_vert_glsl,
- NULL},
- .geom = (const char *[]){sh_cfg->lib,
- datatoc_common_view_lib_glsl,
- datatoc_conservative_depth_geom_glsl,
- NULL},
- .frag = (const char *[]){datatoc_depth_frag_glsl, NULL},
- .defs = (const char *[]){sh_cfg->def, "#define CONSERVATIVE_RASTER\n", NULL},
- });
-
- sh_data->pointcloud_depth_conservative = GPU_shader_create_from_arrays({
- .vert = (const char *[]){sh_cfg->lib,
- datatoc_common_view_lib_glsl,
- datatoc_common_pointcloud_lib_glsl,
- datatoc_depth_vert_glsl,
- NULL},
- .geom = (const char *[]){sh_cfg->lib,
- datatoc_common_view_lib_glsl,
- datatoc_conservative_depth_geom_glsl,
- NULL},
- .frag = (const char *[]){datatoc_depth_frag_glsl, NULL},
- .defs = (const char *[]){sh_cfg->def,
- "#define CONSERVATIVE_RASTER\n",
- "#define POINTCLOUD\n",
- "#define INSTANCED_ATTR\n",
- "#define UNIFORM_RESOURCE_ID\n",
- NULL},
- });
- }
-}
-
static void basic_cache_init(void *vedata)
{
BASIC_PassList *psl = ((BASIC_Data *)vedata)->psl;
@@ -166,7 +79,6 @@ static void basic_cache_init(void *vedata)
DRWShadingGroup *grp;
const DRWContextState *draw_ctx = DRW_context_state_get();
- BASIC_Shaders *sh_data = &e_data.sh_data[draw_ctx->sh_cfg];
if (!stl->g_data) {
/* Alloc transient pointers */
@@ -181,24 +93,29 @@ static void basic_cache_init(void *vedata)
DRWState infront_state = (DRW_state_is_select() && (i == 1)) ? DRW_STATE_IN_FRONT_SELECT : 0;
DRWState state = DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL;
- GPUShader *sh = DRW_state_is_select() ? sh_data->depth_conservative : sh_data->depth;
+ GPUShader *sh = DRW_state_is_select() ?
+ BASIC_shaders_depth_conservative_sh_get(draw_ctx->sh_cfg) :
+ BASIC_shaders_depth_sh_get(draw_ctx->sh_cfg);
DRW_PASS_CREATE(psl->depth_pass[i], state | clip_state | infront_state);
stl->g_data->depth_shgrp[i] = grp = DRW_shgroup_create(sh, psl->depth_pass[i]);
DRW_shgroup_uniform_vec2(grp, "sizeViewport", DRW_viewport_size_get(), 1);
DRW_shgroup_uniform_vec2(grp, "sizeViewportInv", DRW_viewport_invert_size_get(), 1);
- sh = DRW_state_is_select() ? sh_data->pointcloud_depth_conservative : sh_data->pointcloud_depth;
+ sh = DRW_state_is_select() ?
+ BASIC_shaders_pointcloud_depth_conservative_sh_get(draw_ctx->sh_cfg) :
+ BASIC_shaders_pointcloud_depth_sh_get(draw_ctx->sh_cfg);
DRW_PASS_CREATE(psl->depth_pass_pointcloud[i], state | clip_state | infront_state);
- stl->g_data->depth_pointcloud_shgrp[i] = grp = DRW_shgroup_create(sh, psl->depth_pass_pointcloud[i]);
+ stl->g_data->depth_pointcloud_shgrp[i] = grp = DRW_shgroup_create(
+ sh, psl->depth_pass_pointcloud[i]);
DRW_shgroup_uniform_vec2(grp, "sizeViewport", DRW_viewport_size_get(), 1);
DRW_shgroup_uniform_vec2(grp, "sizeViewportInv", DRW_viewport_invert_size_get(), 1);
- stl->g_data->depth_hair_shgrp[i] = grp = DRW_shgroup_create(sh_data->depth,
- psl->depth_pass[i]);
+ stl->g_data->depth_hair_shgrp[i] = grp = DRW_shgroup_create(
+ BASIC_shaders_depth_sh_get(draw_ctx->sh_cfg), psl->depth_pass[i]);
-
- sh = DRW_state_is_select() ? sh_data->depth_conservative : sh_data->depth;
+ sh = DRW_state_is_select() ? BASIC_shaders_depth_conservative_sh_get(draw_ctx->sh_cfg) :
+ BASIC_shaders_depth_sh_get(draw_ctx->sh_cfg);
state |= DRW_STATE_CULL_BACK;
DRW_PASS_CREATE(psl->depth_pass_cull[i], state | clip_state | infront_state);
stl->g_data->depth_shgrp_cull[i] = grp = DRW_shgroup_create(sh, psl->depth_pass_cull[i]);
@@ -336,13 +253,7 @@ static void basic_draw_scene(void *vedata)
static void basic_engine_free(void)
{
- for (int i = 0; i < GPU_SHADER_CFG_LEN; i++) {
- BASIC_Shaders *sh_data = &e_data.sh_data[i];
- DRW_SHADER_FREE_SAFE(sh_data->depth);
- DRW_SHADER_FREE_SAFE(sh_data->depth_conservative);
- DRW_SHADER_FREE_SAFE(sh_data->pointcloud_depth);
- DRW_SHADER_FREE_SAFE(sh_data->pointcloud_depth_conservative);
- }
+ BASIC_shaders_free();
}
static const DrawEngineDataSize basic_data_size = DRW_VIEWPORT_DATA_SIZE(BASIC_Data);
@@ -352,7 +263,7 @@ DrawEngineType draw_engine_basic_type = {
NULL,
N_("Basic"),
&basic_data_size,
- &basic_engine_init,
+ NULL,
&basic_engine_free,
&basic_cache_init,
&basic_cache_populate,
diff --git a/source/blender/draw/engines/image/image_private.h b/source/blender/draw/engines/basic/basic_private.h
index 76a94e68da1..e5f494bf0e7 100644
--- a/source/blender/draw/engines/image/image_private.h
+++ b/source/blender/draw/engines/basic/basic_private.h
@@ -24,45 +24,11 @@
extern "C" {
#endif
-/* Forward declarations */
-struct GPUTexture;
-struct ImBuf;
-struct Image;
-
-/* *********** LISTS *********** */
-
-/* GPUViewport.storage
- * Is freed every time the viewport engine changes. */
-typedef struct IMAGE_PassList {
- DRWPass *image_pass;
-} IMAGE_PassList;
-
-typedef struct IMAGE_PrivateData {
- void *lock;
- struct ImBuf *ibuf;
- struct Image *image;
- struct DRWView *view;
-
- struct GPUTexture *texture;
- bool owns_texture;
-} IMAGE_PrivateData;
-
-typedef struct IMAGE_StorageList {
- IMAGE_PrivateData *pd;
-} IMAGE_StorageList;
-
-typedef struct IMAGE_Data {
- void *engine_type;
- DRWViewportEmptyList *fbl;
- DRWViewportEmptyList *txl;
- IMAGE_PassList *psl;
- IMAGE_StorageList *stl;
-} IMAGE_Data;
-
-/* image_shader.c */
-GPUShader *IMAGE_shader_image_get(bool is_tiled_image);
-void IMAGE_shader_library_ensure(void);
-void IMAGE_shader_free(void);
+GPUShader *BASIC_shaders_depth_sh_get(eGPUShaderConfig config);
+GPUShader *BASIC_shaders_pointcloud_depth_sh_get(eGPUShaderConfig config);
+GPUShader *BASIC_shaders_depth_conservative_sh_get(eGPUShaderConfig config);
+GPUShader *BASIC_shaders_pointcloud_depth_conservative_sh_get(eGPUShaderConfig config);
+void BASIC_shaders_free(void);
#ifdef __cplusplus
}
diff --git a/source/blender/draw/engines/basic/basic_shader.c b/source/blender/draw/engines/basic/basic_shader.c
new file mode 100644
index 00000000000..4b92406d5c0
--- /dev/null
+++ b/source/blender/draw/engines/basic/basic_shader.c
@@ -0,0 +1,167 @@
+/*
+ * 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.
+ *
+ * Copyright 2019, Blender Foundation.
+ */
+
+/** \file
+ * \ingroup draw_engine
+ */
+
+#include "DRW_render.h"
+
+#include "GPU_shader.h"
+
+#include "basic_private.h"
+
+extern char datatoc_depth_frag_glsl[];
+extern char datatoc_depth_vert_glsl[];
+extern char datatoc_conservative_depth_geom_glsl[];
+
+extern char datatoc_common_view_lib_glsl[];
+extern char datatoc_common_pointcloud_lib_glsl[];
+
+/* Shaders */
+
+typedef struct BASIC_Shaders {
+ /* Depth Pre Pass */
+ struct GPUShader *depth;
+ struct GPUShader *pointcloud_depth;
+ struct GPUShader *depth_conservative;
+ struct GPUShader *pointcloud_depth_conservative;
+} BASIC_Shaders;
+
+static struct {
+ BASIC_Shaders sh_data[GPU_SHADER_CFG_LEN];
+} e_data = {{{NULL}}}; /* Engine data */
+
+static GPUShader *BASIC_shader_create_depth_sh(const GPUShaderConfigData *sh_cfg)
+{
+ return GPU_shader_create_from_arrays({
+ .vert = (const char *[]){sh_cfg->lib,
+ datatoc_common_view_lib_glsl,
+ datatoc_depth_vert_glsl,
+ NULL},
+ .frag = (const char *[]){datatoc_depth_frag_glsl, NULL},
+ .defs = (const char *[]){sh_cfg->def, NULL},
+ });
+}
+
+static GPUShader *BASIC_shader_create_pointcloud_depth_sh(const GPUShaderConfigData *sh_cfg)
+{
+ return GPU_shader_create_from_arrays({
+ .vert = (const char *[]){sh_cfg->lib,
+ datatoc_common_view_lib_glsl,
+ datatoc_common_pointcloud_lib_glsl,
+ datatoc_depth_vert_glsl,
+ NULL},
+ .frag = (const char *[]){datatoc_depth_frag_glsl, NULL},
+ .defs = (const char *[]){sh_cfg->def,
+ "#define POINTCLOUD\n",
+ "#define INSTANCED_ATTR\n",
+ "#define UNIFORM_RESOURCE_ID\n",
+ NULL},
+ });
+}
+
+static GPUShader *BASIC_shader_create_depth_conservative_sh(const GPUShaderConfigData *sh_cfg)
+{
+ return GPU_shader_create_from_arrays({
+ .vert = (const char *[]){sh_cfg->lib,
+ datatoc_common_view_lib_glsl,
+ datatoc_depth_vert_glsl,
+ NULL},
+ .geom = (const char *[]){sh_cfg->lib,
+ datatoc_common_view_lib_glsl,
+ datatoc_conservative_depth_geom_glsl,
+ NULL},
+ .frag = (const char *[]){datatoc_depth_frag_glsl, NULL},
+ .defs = (const char *[]){sh_cfg->def, "#define CONSERVATIVE_RASTER\n", NULL},
+ });
+}
+
+static GPUShader *BASIC_shader_create_pointcloud_depth_conservative_sh(
+ const GPUShaderConfigData *sh_cfg)
+{
+ return GPU_shader_create_from_arrays({
+ .vert = (const char *[]){sh_cfg->lib,
+ datatoc_common_view_lib_glsl,
+ datatoc_common_pointcloud_lib_glsl,
+ datatoc_depth_vert_glsl,
+ NULL},
+ .geom = (const char *[]){sh_cfg->lib,
+ datatoc_common_view_lib_glsl,
+ datatoc_conservative_depth_geom_glsl,
+ NULL},
+ .frag = (const char *[]){datatoc_depth_frag_glsl, NULL},
+ .defs = (const char *[]){sh_cfg->def,
+ "#define CONSERVATIVE_RASTER\n",
+ "#define POINTCLOUD\n",
+ "#define INSTANCED_ATTR\n",
+ "#define UNIFORM_RESOURCE_ID\n",
+ NULL},
+ });
+}
+
+GPUShader *BASIC_shaders_depth_sh_get(eGPUShaderConfig config)
+{
+ BASIC_Shaders *sh_data = &e_data.sh_data[config];
+ const GPUShaderConfigData *sh_cfg = &GPU_shader_cfg_data[config];
+ if (sh_data->depth == NULL) {
+ sh_data->depth = BASIC_shader_create_depth_sh(sh_cfg);
+ }
+ return sh_data->depth;
+}
+
+GPUShader *BASIC_shaders_pointcloud_depth_sh_get(eGPUShaderConfig config)
+{
+ BASIC_Shaders *sh_data = &e_data.sh_data[config];
+ const GPUShaderConfigData *sh_cfg = &GPU_shader_cfg_data[config];
+ if (sh_data->pointcloud_depth == NULL) {
+ sh_data->pointcloud_depth = BASIC_shader_create_pointcloud_depth_sh(sh_cfg);
+ }
+ return sh_data->pointcloud_depth;
+}
+
+GPUShader *BASIC_shaders_depth_conservative_sh_get(eGPUShaderConfig config)
+{
+ BASIC_Shaders *sh_data = &e_data.sh_data[config];
+ const GPUShaderConfigData *sh_cfg = &GPU_shader_cfg_data[config];
+ if (sh_data->depth_conservative == NULL) {
+ sh_data->depth_conservative = BASIC_shader_create_depth_conservative_sh(sh_cfg);
+ }
+ return sh_data->depth_conservative;
+}
+
+GPUShader *BASIC_shaders_pointcloud_depth_conservative_sh_get(eGPUShaderConfig config)
+{
+ BASIC_Shaders *sh_data = &e_data.sh_data[config];
+ const GPUShaderConfigData *sh_cfg = &GPU_shader_cfg_data[config];
+ if (sh_data->pointcloud_depth_conservative == NULL) {
+ sh_data->pointcloud_depth_conservative = BASIC_shader_create_pointcloud_depth_conservative_sh(
+ sh_cfg);
+ }
+ return sh_data->pointcloud_depth_conservative;
+}
+
+void BASIC_shaders_free(void)
+{
+ for (int i = 0; i < GPU_SHADER_CFG_LEN; i++) {
+ GPUShader **sh_data_as_array = (GPUShader **)&e_data.sh_data[i];
+ for (int j = 0; j < (sizeof(BASIC_Shaders) / sizeof(GPUShader *)); j++) {
+ DRW_SHADER_FREE_SAFE(sh_data_as_array[j]);
+ }
+ }
+}
diff --git a/source/blender/draw/engines/eevee/shaders/ambient_occlusion_lib.glsl b/source/blender/draw/engines/eevee/shaders/ambient_occlusion_lib.glsl
index 93641443cac..41d6db7f726 100644
--- a/source/blender/draw/engines/eevee/shaders/ambient_occlusion_lib.glsl
+++ b/source/blender/draw/engines/eevee/shaders/ambient_occlusion_lib.glsl
@@ -56,7 +56,7 @@ vec2 get_ao_noise(void)
{
vec2 noise = texelfetch_noise_tex(gl_FragCoord.xy).xy;
/* Decorrelate noise from AA. */
- /* TODO(fclem) we should use a more general approach for more random number dimentions. */
+ /* TODO(fclem) we should use a more general approach for more random number dimensions. */
noise = fract(noise * 6.1803402007);
return noise;
}
@@ -399,7 +399,7 @@ float specular_occlusion(
/* Use the right occlusion. */
OcclusionData occlusion_load(vec3 vP, float custom_occlusion)
{
- /* Default to fully openned cone. */
+ /* Default to fully opened cone. */
OcclusionData data = NO_OCCLUSION_DATA;
#ifdef ENABLE_DEFERED_AO
diff --git a/source/blender/draw/engines/eevee/shaders/closure_eval_lib.glsl b/source/blender/draw/engines/eevee/shaders/closure_eval_lib.glsl
index e5cbc487e93..311887cf2f5 100644
--- a/source/blender/draw/engines/eevee/shaders/closure_eval_lib.glsl
+++ b/source/blender/draw/engines/eevee/shaders/closure_eval_lib.glsl
@@ -172,7 +172,7 @@
/* -------------------------------------------------------------------- */
/** \name Common cl_eval data
*
- * Eval data not dependant on input parameters. All might not be used but unused ones
+ * Eval data not dependent on input parameters. All might not be used but unused ones
* will be optimized out.
* \{ */
@@ -240,7 +240,7 @@ ClosureEvalCommon closure_Common_eval_init(ClosureInputCommon cl_in)
/* -------------------------------------------------------------------- */
/** \name Loop data
*
- * Loop datas are conveniently packed into struct to make it future proof.
+ * Loop data is conveniently packed into struct to make it future proof.
* \{ */
struct ClosureLightData {
diff --git a/source/blender/draw/engines/eevee/shaders/common_utiltex_lib.glsl b/source/blender/draw/engines/eevee/shaders/common_utiltex_lib.glsl
index c3325ec4286..77a1560f3a7 100644
--- a/source/blender/draw/engines/eevee/shaders/common_utiltex_lib.glsl
+++ b/source/blender/draw/engines/eevee/shaders/common_utiltex_lib.glsl
@@ -79,7 +79,7 @@ vec2 btdf_lut(float cos_theta, float roughness, float ior)
/* Baked IOR for GGX BRDF. */
const float specular = 1.0;
const float eta_brdf = (2.0 / (1.0 - sqrt(0.08 * specular))) - 1.0;
- /* Avoid harsh transition comming from ior == 1. */
+ /* Avoid harsh transition coming from ior == 1. */
float f90 = fast_sqrt(saturate(f0 / (f0_from_ior(eta_brdf) * 0.25)));
float fresnel = F_brdf_single_scatter(vec3(f0), vec3(f90), split_sum).r;
/* Setting the BTDF to one is not really important since it is only used for multiscatter
diff --git a/source/blender/draw/engines/eevee/shaders/effect_dof_gather_frag.glsl b/source/blender/draw/engines/eevee/shaders/effect_dof_gather_frag.glsl
index 39a7e8fb931..c09365cdcb4 100644
--- a/source/blender/draw/engines/eevee/shaders/effect_dof_gather_frag.glsl
+++ b/source/blender/draw/engines/eevee/shaders/effect_dof_gather_frag.glsl
@@ -2,7 +2,7 @@
/**
* Gather pass: Convolve foreground and background parts in separate passes.
*
- * Using the min&max CoC tile buffer, we select the best apropriate method to blur the scene color.
+ * Using the min&max CoC tile buffer, we select the best appropriate method to blur the scene color.
* A fast gather path is taken if there is not many CoC variation inside the tile.
*
* We sample using an octaweb sampling pattern. We randomize the kernel center and each ring
diff --git a/source/blender/draw/engines/eevee/shaders/effect_dof_reduce_frag.glsl b/source/blender/draw/engines/eevee/shaders/effect_dof_reduce_frag.glsl
index 1b5b305dfc1..d21254003f9 100644
--- a/source/blender/draw/engines/eevee/shaders/effect_dof_reduce_frag.glsl
+++ b/source/blender/draw/engines/eevee/shaders/effect_dof_reduce_frag.glsl
@@ -140,7 +140,7 @@ void main()
do_scatter *= dof_scatter_screen_border_rejection(outCoc, uv, halfres);
/* Only scatter if neighborhood is different enough. */
do_scatter *= dof_scatter_neighborhood_rejection(outColor.rgb);
- /* For debuging. */
+ /* For debugging. */
do_scatter *= float(!no_scatter_pass);
outScatterColor = mix(vec3(0.0), outColor.rgb, do_scatter);
diff --git a/source/blender/draw/engines/eevee/shaders/effect_reflection_resolve_frag.glsl b/source/blender/draw/engines/eevee/shaders/effect_reflection_resolve_frag.glsl
index 7689e730bf3..7568d70bd14 100644
--- a/source/blender/draw/engines/eevee/shaders/effect_reflection_resolve_frag.glsl
+++ b/source/blender/draw/engines/eevee/shaders/effect_reflection_resolve_frag.glsl
@@ -134,7 +134,7 @@ void raytrace_resolve(ClosureInputGlossy cl_in,
vec3 V, P, N;
if (planar_index != -1) {
PlanarData pd = planars_data[planar_index];
- /* Evaluate everything in refected space. */
+ /* Evaluate everything in reflected space. */
P = line_plane_intersect(cl_common.P, cl_common.V, pd.pl_plane_eq);
V = reflect(cl_common.V, pd.pl_normal);
N = reflect(cl_in.N, pd.pl_normal);
diff --git a/source/blender/draw/engines/eevee/shaders/random_lib.glsl b/source/blender/draw/engines/eevee/shaders/random_lib.glsl
index 3a4ae257bbe..c2388f61346 100644
--- a/source/blender/draw/engines/eevee/shaders/random_lib.glsl
+++ b/source/blender/draw/engines/eevee/shaders/random_lib.glsl
@@ -1,6 +1,6 @@
/**
- * Random numbers and low discrepency sequences utilities.
+ * Random numbers and low discrepancy sequences utilities.
*/
#pragma BLENDER_REQUIRE(common_math_lib.glsl)
diff --git a/source/blender/draw/engines/eevee/shaders/surface_lib.glsl b/source/blender/draw/engines/eevee/shaders/surface_lib.glsl
index 0efa7b80b0b..7d016d57c46 100644
--- a/source/blender/draw/engines/eevee/shaders/surface_lib.glsl
+++ b/source/blender/draw/engines/eevee/shaders/surface_lib.glsl
@@ -8,7 +8,7 @@
#if defined(STEP_RESOLVE) || defined(STEP_RAYTRACE)
/* SSR will set these global variables itself.
- * Also make false positive compiler warnings disapear by setting values. */
+ * Also make false positive compiler warnings disappear by setting values. */
vec3 worldPosition = vec3(0);
vec3 viewPosition = vec3(0);
vec3 worldNormal = vec3(0);
diff --git a/source/blender/draw/engines/eevee/shaders/volumetric_lib.glsl b/source/blender/draw/engines/eevee/shaders/volumetric_lib.glsl
index c48c3bffaef..777e48fde34 100644
--- a/source/blender/draw/engines/eevee/shaders/volumetric_lib.glsl
+++ b/source/blender/draw/engines/eevee/shaders/volumetric_lib.glsl
@@ -74,7 +74,7 @@ vec3 light_volume(LightData ld, vec4 l_vector)
float d = l_vector.w;
float d_sqr = sqr(d);
float r_sqr = ld.l_volume_radius;
- /* Using reformulation that has better numerical percision. */
+ /* Using reformulation that has better numerical precision. */
power = 2.0 / (d_sqr + r_sqr + d * sqrt(d_sqr + r_sqr));
if (ld.l_type == AREA_RECT || ld.l_type == AREA_ELLIPSE) {
diff --git a/source/blender/draw/engines/gpencil/gpencil_engine.h b/source/blender/draw/engines/gpencil/gpencil_engine.h
index 674aca29662..328e60cf60b 100644
--- a/source/blender/draw/engines/gpencil/gpencil_engine.h
+++ b/source/blender/draw/engines/gpencil/gpencil_engine.h
@@ -106,7 +106,7 @@ typedef struct gpLight {
BLI_STATIC_ASSERT_ALIGN(gpMaterial, 16)
BLI_STATIC_ASSERT_ALIGN(gpLight, 16)
-/* *********** Draw Datas *********** */
+/* *********** Draw Data *********** */
typedef struct GPENCIL_MaterialPool {
/* Linklist. */
struct GPENCIL_MaterialPool *next;
diff --git a/source/blender/draw/engines/image/image_drawing_mode.hh b/source/blender/draw/engines/image/image_drawing_mode.hh
new file mode 100644
index 00000000000..d81b0971982
--- /dev/null
+++ b/source/blender/draw/engines/image/image_drawing_mode.hh
@@ -0,0 +1,153 @@
+/*
+ * 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.
+ *
+ * Copyright 2021, Blender Foundation.
+ */
+
+/** \file
+ * \ingroup draw_engine
+ */
+
+#pragma once
+
+#include "image_private.hh"
+
+namespace blender::draw::image_engine {
+
+class DefaultDrawingMode : public AbstractDrawingMode {
+ private:
+ DRWPass *create_image_pass() const
+ {
+ /* Write depth is needed for background overlay rendering. Near depth is used for
+ * transparency checker and Far depth is used for indicating the image size. */
+ DRWState state = static_cast<DRWState>(DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH |
+ DRW_STATE_DEPTH_ALWAYS | DRW_STATE_BLEND_ALPHA_PREMUL);
+ return DRW_pass_create("Image", state);
+ }
+
+ void add_to_shgroup(AbstractSpaceAccessor *space,
+ DRWShadingGroup *grp,
+ const Image *image,
+ const ImBuf *image_buffer) const
+ {
+ float image_mat[4][4];
+
+ const DRWContextState *draw_ctx = DRW_context_state_get();
+ const ARegion *region = draw_ctx->region;
+ space->get_image_mat(image_buffer, region, image_mat);
+
+ GPUBatch *geom = DRW_cache_quad_get();
+
+ const bool is_tiled_texture = image && image->source == IMA_SRC_TILED;
+ if (is_tiled_texture) {
+ const float translate_x = image_mat[3][0];
+ const float translate_y = image_mat[3][1];
+ LISTBASE_FOREACH (ImageTile *, tile, &image->tiles) {
+ const int tile_x = ((tile->tile_number - 1001) % 10);
+ const int tile_y = ((tile->tile_number - 1001) / 10);
+ image_mat[3][0] = (float)tile_x + translate_x;
+ image_mat[3][1] = (float)tile_y + translate_y;
+ DRW_shgroup_call_obmat(grp, geom, image_mat);
+ }
+ }
+ else {
+ DRW_shgroup_call_obmat(grp, geom, image_mat);
+ }
+ }
+
+ public:
+ void cache_init(IMAGE_Data *vedata) const override
+ {
+ IMAGE_PassList *psl = vedata->psl;
+
+ psl->image_pass = create_image_pass();
+ }
+
+ void cache_image(AbstractSpaceAccessor *space,
+ IMAGE_Data *vedata,
+ Image *image,
+ ImageUser *iuser,
+ ImBuf *image_buffer) const override
+ {
+ IMAGE_PassList *psl = vedata->psl;
+ IMAGE_StorageList *stl = vedata->stl;
+ IMAGE_PrivateData *pd = stl->pd;
+
+ GPUTexture *tex_tile_data = nullptr;
+ space->get_gpu_textures(
+ image, iuser, image_buffer, &pd->texture, &pd->owns_texture, &tex_tile_data);
+ if (pd->texture == nullptr) {
+ return;
+ }
+ const bool is_tiled_texture = tex_tile_data != nullptr;
+
+ ShaderParameters sh_params;
+ sh_params.use_premul_alpha = BKE_image_has_gpu_texture_premultiplied_alpha(image,
+ image_buffer);
+ const DRWContextState *draw_ctx = DRW_context_state_get();
+ const Scene *scene = draw_ctx->scene;
+ if (scene->camera && scene->camera->type == OB_CAMERA) {
+ Camera *camera = static_cast<Camera *>(scene->camera->data);
+ copy_v2_fl2(sh_params.far_near, camera->clip_end, camera->clip_start);
+ }
+ space->get_shader_parameters(sh_params, image_buffer, is_tiled_texture);
+
+ GPUShader *shader = IMAGE_shader_image_get(is_tiled_texture);
+ DRWShadingGroup *shgrp = DRW_shgroup_create(shader, psl->image_pass);
+ if (is_tiled_texture) {
+ DRW_shgroup_uniform_texture_ex(shgrp, "imageTileArray", pd->texture, GPU_SAMPLER_DEFAULT);
+ DRW_shgroup_uniform_texture(shgrp, "imageTileData", tex_tile_data);
+ }
+ else {
+ DRW_shgroup_uniform_texture_ex(shgrp, "imageTexture", pd->texture, GPU_SAMPLER_DEFAULT);
+ }
+ DRW_shgroup_uniform_vec2_copy(shgrp, "farNearDistances", sh_params.far_near);
+ DRW_shgroup_uniform_vec4_copy(shgrp, "color", ShaderParameters::color);
+ DRW_shgroup_uniform_vec4_copy(shgrp, "shuffle", sh_params.shuffle);
+ DRW_shgroup_uniform_int_copy(shgrp, "drawFlags", sh_params.flags);
+ DRW_shgroup_uniform_bool_copy(shgrp, "imgPremultiplied", sh_params.use_premul_alpha);
+
+ add_to_shgroup(space, shgrp, image, image_buffer);
+ }
+
+ void draw_finish(IMAGE_Data *vedata) const override
+ {
+ IMAGE_StorageList *stl = vedata->stl;
+ IMAGE_PrivateData *pd = stl->pd;
+
+ if (pd->texture && pd->owns_texture) {
+ GPU_texture_free(pd->texture);
+ pd->owns_texture = false;
+ }
+ pd->texture = nullptr;
+ }
+
+ void draw_scene(IMAGE_Data *vedata) const override
+ {
+ IMAGE_PassList *psl = vedata->psl;
+ IMAGE_PrivateData *pd = vedata->stl->pd;
+
+ DefaultFramebufferList *dfbl = DRW_viewport_framebuffer_list_get();
+ GPU_framebuffer_bind(dfbl->default_fb);
+ static float clear_col[4] = {0.0f, 0.0f, 0.0f, 0.0f};
+ GPU_framebuffer_clear_color_depth(dfbl->default_fb, clear_col, 1.0);
+
+ DRW_view_set_active(pd->view);
+ DRW_draw_pass(psl->image_pass);
+ DRW_view_set_active(nullptr);
+ }
+};
+
+} // namespace blender::draw::image_engine
diff --git a/source/blender/draw/engines/image/image_engine.c b/source/blender/draw/engines/image/image_engine.c
deleted file mode 100644
index 8b4acfbd5e3..00000000000
--- a/source/blender/draw/engines/image/image_engine.c
+++ /dev/null
@@ -1,459 +0,0 @@
-/*
- * 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.
- *
- * Copyright 2020, Blender Foundation.
- */
-
-/** \file
- * \ingroup draw_editors
- *
- * Draw engine to draw the Image/UV editor
- */
-
-#include "DRW_render.h"
-
-#include "BKE_image.h"
-#include "BKE_main.h"
-#include "BKE_object.h"
-
-#include "DNA_camera_types.h"
-#include "DNA_screen_types.h"
-
-#include "IMB_imbuf.h"
-#include "IMB_imbuf_types.h"
-
-#include "ED_image.h"
-
-#include "GPU_batch.h"
-
-#include "image_engine.h"
-#include "image_private.h"
-
-#define IMAGE_DRAW_FLAG_SHOW_ALPHA (1 << 0)
-#define IMAGE_DRAW_FLAG_APPLY_ALPHA (1 << 1)
-#define IMAGE_DRAW_FLAG_SHUFFLING (1 << 2)
-#define IMAGE_DRAW_FLAG_DEPTH (1 << 3)
-#define IMAGE_DRAW_FLAG_DO_REPEAT (1 << 4)
-#define IMAGE_DRAW_FLAG_USE_WORLD_POS (1 << 5)
-
-static void image_cache_image_add(DRWShadingGroup *grp, Image *image, ImBuf *ibuf)
-{
- const DRWContextState *draw_ctx = DRW_context_state_get();
- const ARegion *region = draw_ctx->region;
- const char space_type = draw_ctx->space_data->spacetype;
-
- float zoom_x = 1.0f;
- float zoom_y = 1.0f;
- float translate_x = 0.0f;
- float translate_y = 0.0f;
-
- /* User can freely move the backdrop in the space of the node editor */
- if (space_type == SPACE_NODE) {
- SpaceNode *snode = (SpaceNode *)draw_ctx->space_data;
- const float ibuf_width = ibuf->x;
- const float ibuf_height = ibuf->y;
- const float x = (region->winx - snode->zoom * ibuf_width) / 2 + snode->xof;
- const float y = (region->winy - snode->zoom * ibuf_height) / 2 + snode->yof;
-
- zoom_x = ibuf_width * snode->zoom;
- zoom_y = ibuf_height * snode->zoom;
- translate_x = x;
- translate_y = y;
- }
-
- const bool is_tiled_texture = image && image->source == IMA_SRC_TILED;
- float obmat[4][4];
- unit_m4(obmat);
-
- GPUBatch *geom = DRW_cache_quad_get();
-
- obmat[0][0] = zoom_x;
- obmat[1][1] = zoom_y;
- obmat[3][1] = translate_y;
- obmat[3][0] = translate_x;
-
- if (is_tiled_texture) {
- LISTBASE_FOREACH (ImageTile *, tile, &image->tiles) {
- const int tile_x = ((tile->tile_number - 1001) % 10);
- const int tile_y = ((tile->tile_number - 1001) / 10);
- obmat[3][1] = (float)tile_y + translate_y;
- obmat[3][0] = (float)tile_x + translate_x;
- DRW_shgroup_call_obmat(grp, geom, obmat);
- }
- }
- else {
- DRW_shgroup_call_obmat(grp, geom, obmat);
- }
-}
-
-static void space_image_gpu_texture_get(Image *image,
- ImageUser *iuser,
- ImBuf *ibuf,
- GPUTexture **r_gpu_texture,
- bool *r_owns_texture,
- GPUTexture **r_tex_tile_data)
-{
- const DRWContextState *draw_ctx = DRW_context_state_get();
- SpaceImage *sima = (SpaceImage *)draw_ctx->space_data;
- if (image->rr != NULL) {
- /* Update multi-index and pass for the current eye. */
- BKE_image_multilayer_index(image->rr, &sima->iuser);
- }
- else {
- BKE_image_multiview_index(image, &sima->iuser);
- }
-
- if (ibuf == NULL) {
- return;
- }
-
- if (ibuf->rect == NULL && ibuf->rect_float == NULL) {
- /* This code-path is only supposed to happen when drawing a lazily-allocatable render result.
- * In all the other cases the `ED_space_image_acquire_buffer()` is expected to return NULL as
- * an image buffer when it has no pixels. */
-
- BLI_assert(image->type == IMA_TYPE_R_RESULT);
-
- float zero[4] = {0, 0, 0, 0};
- *r_gpu_texture = GPU_texture_create_2d(__func__, 1, 1, 0, GPU_RGBA16F, zero);
- *r_owns_texture = true;
- return;
- }
-
- const int sima_flag = sima->flag & ED_space_image_get_display_channel_mask(ibuf);
- if (sima_flag & SI_SHOW_ZBUF && (ibuf->zbuf || ibuf->zbuf_float || (ibuf->channels == 1))) {
- if (ibuf->zbuf) {
- BLI_assert_msg(0, "Integer based depth buffers not supported");
- }
- else if (ibuf->zbuf_float) {
- *r_gpu_texture = GPU_texture_create_2d(
- __func__, ibuf->x, ibuf->y, 0, GPU_R16F, ibuf->zbuf_float);
- *r_owns_texture = true;
- }
- else if (ibuf->rect_float && ibuf->channels == 1) {
- *r_gpu_texture = GPU_texture_create_2d(
- __func__, ibuf->x, ibuf->y, 0, GPU_R16F, ibuf->rect_float);
- *r_owns_texture = true;
- }
- }
- else if (image->source == IMA_SRC_TILED) {
- *r_gpu_texture = BKE_image_get_gpu_tiles(image, iuser, ibuf);
- *r_tex_tile_data = BKE_image_get_gpu_tilemap(image, iuser, NULL);
- *r_owns_texture = false;
- }
- else {
- *r_gpu_texture = BKE_image_get_gpu_texture(image, iuser, ibuf);
- *r_owns_texture = false;
- }
-}
-
-static void space_node_gpu_texture_get(Image *image,
- ImageUser *iuser,
- ImBuf *ibuf,
- GPUTexture **r_gpu_texture,
- bool *r_owns_texture,
- GPUTexture **r_tex_tile_data)
-{
- *r_gpu_texture = BKE_image_get_gpu_texture(image, iuser, ibuf);
- *r_owns_texture = false;
- *r_tex_tile_data = NULL;
-}
-
-static void image_gpu_texture_get(Image *image,
- ImageUser *iuser,
- ImBuf *ibuf,
- GPUTexture **r_gpu_texture,
- bool *r_owns_texture,
- GPUTexture **r_tex_tile_data)
-{
- if (!image) {
- return;
- }
-
- const DRWContextState *draw_ctx = DRW_context_state_get();
- const char space_type = draw_ctx->space_data->spacetype;
-
- if (space_type == SPACE_IMAGE) {
- space_image_gpu_texture_get(
- image, iuser, ibuf, r_gpu_texture, r_owns_texture, r_tex_tile_data);
- }
- else if (space_type == SPACE_NODE) {
- space_node_gpu_texture_get(image, iuser, ibuf, r_gpu_texture, r_owns_texture, r_tex_tile_data);
- }
-}
-
-static void image_cache_image(IMAGE_Data *vedata, Image *image, ImageUser *iuser, ImBuf *ibuf)
-{
- IMAGE_PassList *psl = vedata->psl;
- IMAGE_StorageList *stl = vedata->stl;
- IMAGE_PrivateData *pd = stl->pd;
-
- const DRWContextState *draw_ctx = DRW_context_state_get();
- const char space_type = draw_ctx->space_data->spacetype;
- const Scene *scene = draw_ctx->scene;
-
- GPUTexture *tex_tile_data = NULL;
- image_gpu_texture_get(image, iuser, ibuf, &pd->texture, &pd->owns_texture, &tex_tile_data);
-
- if (pd->texture) {
- static float color[4] = {1.0f, 1.0f, 1.0f, 1.0f};
- static float shuffle[4] = {1.0f, 1.0f, 1.0f, 1.0f};
- static float far_near[2] = {100.0f, 0.0f};
-
- if (scene->camera && scene->camera->type == OB_CAMERA) {
- far_near[1] = ((Camera *)scene->camera->data)->clip_start;
- far_near[0] = ((Camera *)scene->camera->data)->clip_end;
- }
-
- const bool use_premul_alpha = BKE_image_has_gpu_texture_premultiplied_alpha(image, ibuf);
- const bool is_tiled_texture = tex_tile_data != NULL;
-
- int draw_flags = 0;
- if (space_type == SPACE_IMAGE) {
- SpaceImage *sima = (SpaceImage *)draw_ctx->space_data;
- const int sima_flag = sima->flag & ED_space_image_get_display_channel_mask(ibuf);
- const bool do_repeat = (!is_tiled_texture) && ((sima->flag & SI_DRAW_TILE) != 0);
- SET_FLAG_FROM_TEST(draw_flags, do_repeat, IMAGE_DRAW_FLAG_DO_REPEAT);
- SET_FLAG_FROM_TEST(draw_flags, is_tiled_texture, IMAGE_DRAW_FLAG_USE_WORLD_POS);
- if ((sima_flag & SI_USE_ALPHA) != 0) {
- /* Show RGBA */
- draw_flags |= IMAGE_DRAW_FLAG_SHOW_ALPHA | IMAGE_DRAW_FLAG_APPLY_ALPHA;
- }
- else if ((sima_flag & SI_SHOW_ALPHA) != 0) {
- draw_flags |= IMAGE_DRAW_FLAG_SHUFFLING;
- copy_v4_fl4(shuffle, 0.0f, 0.0f, 0.0f, 1.0f);
- }
- else if ((sima_flag & SI_SHOW_ZBUF) != 0) {
- draw_flags |= IMAGE_DRAW_FLAG_DEPTH | IMAGE_DRAW_FLAG_SHUFFLING;
- copy_v4_fl4(shuffle, 1.0f, 0.0f, 0.0f, 0.0f);
- }
- else if ((sima_flag & SI_SHOW_R) != 0) {
- draw_flags |= IMAGE_DRAW_FLAG_SHUFFLING;
- if (IMB_alpha_affects_rgb(ibuf)) {
- draw_flags |= IMAGE_DRAW_FLAG_APPLY_ALPHA;
- }
- copy_v4_fl4(shuffle, 1.0f, 0.0f, 0.0f, 0.0f);
- }
- else if ((sima_flag & SI_SHOW_G) != 0) {
- draw_flags |= IMAGE_DRAW_FLAG_SHUFFLING;
- if (IMB_alpha_affects_rgb(ibuf)) {
- draw_flags |= IMAGE_DRAW_FLAG_APPLY_ALPHA;
- }
- copy_v4_fl4(shuffle, 0.0f, 1.0f, 0.0f, 0.0f);
- }
- else if ((sima_flag & SI_SHOW_B) != 0) {
- draw_flags |= IMAGE_DRAW_FLAG_SHUFFLING;
- if (IMB_alpha_affects_rgb(ibuf)) {
- draw_flags |= IMAGE_DRAW_FLAG_APPLY_ALPHA;
- }
- copy_v4_fl4(shuffle, 0.0f, 0.0f, 1.0f, 0.0f);
- }
- else /* RGB */ {
- if (IMB_alpha_affects_rgb(ibuf)) {
- draw_flags |= IMAGE_DRAW_FLAG_APPLY_ALPHA;
- }
- }
- }
- if (space_type == SPACE_NODE) {
- SpaceNode *snode = (SpaceNode *)draw_ctx->space_data;
- if ((snode->flag & SNODE_USE_ALPHA) != 0) {
- /* Show RGBA */
- draw_flags |= IMAGE_DRAW_FLAG_SHOW_ALPHA | IMAGE_DRAW_FLAG_APPLY_ALPHA;
- }
- else if ((snode->flag & SNODE_SHOW_ALPHA) != 0) {
- draw_flags |= IMAGE_DRAW_FLAG_SHUFFLING;
- copy_v4_fl4(shuffle, 0.0f, 0.0f, 0.0f, 1.0f);
- }
- else if ((snode->flag & SNODE_SHOW_R) != 0) {
- draw_flags |= IMAGE_DRAW_FLAG_SHUFFLING;
- if (IMB_alpha_affects_rgb(ibuf)) {
- draw_flags |= IMAGE_DRAW_FLAG_APPLY_ALPHA;
- }
- copy_v4_fl4(shuffle, 1.0f, 0.0f, 0.0f, 0.0f);
- }
- else if ((snode->flag & SNODE_SHOW_G) != 0) {
- draw_flags |= IMAGE_DRAW_FLAG_SHUFFLING;
- if (IMB_alpha_affects_rgb(ibuf)) {
- draw_flags |= IMAGE_DRAW_FLAG_APPLY_ALPHA;
- }
- copy_v4_fl4(shuffle, 0.0f, 1.0f, 0.0f, 0.0f);
- }
- else if ((snode->flag & SNODE_SHOW_B) != 0) {
- draw_flags |= IMAGE_DRAW_FLAG_SHUFFLING;
- if (IMB_alpha_affects_rgb(ibuf)) {
- draw_flags |= IMAGE_DRAW_FLAG_APPLY_ALPHA;
- }
- copy_v4_fl4(shuffle, 0.0f, 0.0f, 1.0f, 0.0f);
- }
- else /* RGB */ {
- if (IMB_alpha_affects_rgb(ibuf)) {
- draw_flags |= IMAGE_DRAW_FLAG_APPLY_ALPHA;
- }
- }
- }
-
- GPUShader *shader = IMAGE_shader_image_get(is_tiled_texture);
- DRWShadingGroup *shgrp = DRW_shgroup_create(shader, psl->image_pass);
- if (is_tiled_texture) {
- DRW_shgroup_uniform_texture_ex(shgrp, "imageTileArray", pd->texture, 0);
- DRW_shgroup_uniform_texture(shgrp, "imageTileData", tex_tile_data);
- }
- else {
- DRW_shgroup_uniform_texture_ex(shgrp, "imageTexture", pd->texture, 0);
- }
- DRW_shgroup_uniform_vec2_copy(shgrp, "farNearDistances", far_near);
- DRW_shgroup_uniform_vec4_copy(shgrp, "color", color);
- DRW_shgroup_uniform_vec4_copy(shgrp, "shuffle", shuffle);
- DRW_shgroup_uniform_int_copy(shgrp, "drawFlags", draw_flags);
- DRW_shgroup_uniform_bool_copy(shgrp, "imgPremultiplied", use_premul_alpha);
- image_cache_image_add(shgrp, image, ibuf);
- }
-}
-
-/* -------------------------------------------------------------------- */
-/** \name Engine Callbacks
- * \{ */
-
-static void IMAGE_engine_init(void *ved)
-{
- IMAGE_shader_library_ensure();
- IMAGE_Data *vedata = (IMAGE_Data *)ved;
- IMAGE_StorageList *stl = vedata->stl;
- if (!stl->pd) {
- stl->pd = MEM_callocN(sizeof(IMAGE_PrivateData), __func__);
- }
- IMAGE_PrivateData *pd = stl->pd;
-
- pd->ibuf = NULL;
- pd->lock = NULL;
- pd->texture = NULL;
-}
-
-static void IMAGE_cache_init(void *ved)
-{
- IMAGE_Data *vedata = (IMAGE_Data *)ved;
- IMAGE_StorageList *stl = vedata->stl;
- IMAGE_PrivateData *pd = stl->pd;
- IMAGE_PassList *psl = vedata->psl;
- const DRWContextState *draw_ctx = DRW_context_state_get();
-
- {
- /* Write depth is needed for background overlay rendering. Near depth is used for
- * transparency checker and Far depth is used for indicating the image size. */
- DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_ALWAYS |
- DRW_STATE_BLEND_ALPHA_PREMUL;
- psl->image_pass = DRW_pass_create("Image", state);
- }
-
- const SpaceLink *space_link = draw_ctx->space_data;
- const char space_type = space_link->spacetype;
- pd->view = NULL;
- if (space_type == SPACE_IMAGE) {
- SpaceImage *sima = (SpaceImage *)draw_ctx->space_data;
- Image *image = ED_space_image(sima);
- ImBuf *ibuf = ED_space_image_acquire_buffer(sima, &pd->lock, 0);
- image_cache_image(vedata, image, &sima->iuser, ibuf);
- pd->image = image;
- pd->ibuf = ibuf;
- }
- else if (space_type == SPACE_NODE) {
- ARegion *region = draw_ctx->region;
- Main *bmain = CTX_data_main(draw_ctx->evil_C);
- Image *image = BKE_image_ensure_viewer(bmain, IMA_TYPE_COMPOSITE, "Viewer Node");
- ImBuf *ibuf = BKE_image_acquire_ibuf(image, NULL, &pd->lock);
- {
- /* Setup a screen pixel view. The backdrop of the node editor doesn't follow the region. */
- float winmat[4][4], viewmat[4][4];
- orthographic_m4(viewmat, 0.0, region->winx, 0.0, region->winy, 0.0, 1.0);
- unit_m4(winmat);
- pd->view = DRW_view_create(viewmat, winmat, NULL, NULL, NULL);
- }
- image_cache_image(vedata, image, NULL, ibuf);
- pd->image = image;
- pd->ibuf = ibuf;
- }
-}
-
-static void IMAGE_cache_populate(void *UNUSED(vedata), Object *UNUSED(ob))
-{
- /* Function intentional left empty. `cache_populate` is required to be implemented. */
-}
-
-static void image_draw_finish(IMAGE_Data *ved)
-{
- IMAGE_Data *vedata = (IMAGE_Data *)ved;
- IMAGE_StorageList *stl = vedata->stl;
- IMAGE_PrivateData *pd = stl->pd;
- const DRWContextState *draw_ctx = DRW_context_state_get();
- const char space_type = draw_ctx->space_data->spacetype;
- if (space_type == SPACE_IMAGE) {
- SpaceImage *sima = (SpaceImage *)draw_ctx->space_data;
- ED_space_image_release_buffer(sima, pd->ibuf, pd->lock);
- }
- else if (space_type == SPACE_NODE) {
- BKE_image_release_ibuf(pd->image, pd->ibuf, pd->lock);
- }
- pd->image = NULL;
- pd->ibuf = NULL;
-
- if (pd->texture && pd->owns_texture) {
- GPU_texture_free(pd->texture);
- pd->owns_texture = false;
- }
- pd->texture = NULL;
-}
-
-static void IMAGE_draw_scene(void *ved)
-{
- IMAGE_Data *vedata = (IMAGE_Data *)ved;
- IMAGE_PassList *psl = vedata->psl;
- IMAGE_PrivateData *pd = vedata->stl->pd;
-
- DefaultFramebufferList *dfbl = DRW_viewport_framebuffer_list_get();
- GPU_framebuffer_bind(dfbl->default_fb);
- static float clear_col[4] = {0.0f, 0.0f, 0.0f, 0.0f};
- GPU_framebuffer_clear_color_depth(dfbl->default_fb, clear_col, 1.0);
-
- DRW_view_set_active(pd->view);
- DRW_draw_pass(psl->image_pass);
- DRW_view_set_active(NULL);
- image_draw_finish(vedata);
-}
-
-static void IMAGE_engine_free(void)
-{
- IMAGE_shader_free();
-}
-
-/** \} */
-
-static const DrawEngineDataSize IMAGE_data_size = DRW_VIEWPORT_DATA_SIZE(IMAGE_Data);
-
-DrawEngineType draw_engine_image_type = {
- NULL, /* next */
- NULL, /* prev */
- N_("UV/Image"), /* idname */
- &IMAGE_data_size, /* vedata_size */
- &IMAGE_engine_init, /* engine_init */
- &IMAGE_engine_free, /* engine_free */
- &IMAGE_cache_init, /* cache_init */
- &IMAGE_cache_populate, /* cache_populate */
- NULL, /* cache_finish */
- &IMAGE_draw_scene, /* draw_scene */
- NULL, /* view_update */
- NULL, /* id_update */
- NULL, /* render_to_image */
- NULL, /* store_metadata */
-};
diff --git a/source/blender/draw/engines/image/image_engine.cc b/source/blender/draw/engines/image/image_engine.cc
new file mode 100644
index 00000000000..491fbec978b
--- /dev/null
+++ b/source/blender/draw/engines/image/image_engine.cc
@@ -0,0 +1,197 @@
+/*
+ * 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.
+ *
+ * Copyright 2020, Blender Foundation.
+ */
+
+/** \file
+ * \ingroup draw_engine
+ *
+ * Draw engine to draw the Image/UV editor
+ */
+
+#include "DRW_render.h"
+
+#include <memory>
+#include <optional>
+
+#include "BKE_image.h"
+#include "BKE_main.h"
+#include "BKE_object.h"
+
+#include "DNA_camera_types.h"
+#include "DNA_screen_types.h"
+
+#include "IMB_imbuf.h"
+#include "IMB_imbuf_types.h"
+
+#include "ED_image.h"
+
+#include "GPU_batch.h"
+
+#include "image_drawing_mode.hh"
+#include "image_engine.h"
+#include "image_private.hh"
+#include "image_space_image.hh"
+#include "image_space_node.hh"
+
+namespace blender::draw::image_engine {
+
+static std::unique_ptr<AbstractSpaceAccessor> space_accessor_from_context(
+ const DRWContextState *draw_ctx)
+{
+ const char space_type = draw_ctx->space_data->spacetype;
+ if (space_type == SPACE_IMAGE) {
+ return std::make_unique<SpaceImageAccessor>((SpaceImage *)draw_ctx->space_data);
+ }
+ if (space_type == SPACE_NODE) {
+ return std::make_unique<SpaceNodeAccessor>((SpaceNode *)draw_ctx->space_data);
+ }
+ BLI_assert_unreachable();
+ return nullptr;
+}
+
+class ImageEngine {
+ private:
+ const DRWContextState *draw_ctx;
+ IMAGE_Data *vedata;
+ std::unique_ptr<AbstractSpaceAccessor> space;
+ DefaultDrawingMode drawing_mode;
+
+ public:
+ ImageEngine(const DRWContextState *draw_ctx, IMAGE_Data *vedata)
+ : draw_ctx(draw_ctx), vedata(vedata), space(space_accessor_from_context(draw_ctx))
+ {
+ }
+
+ virtual ~ImageEngine() = default;
+
+ void cache_init()
+ {
+ IMAGE_StorageList *stl = vedata->stl;
+ IMAGE_PrivateData *pd = stl->pd;
+
+ drawing_mode.cache_init(vedata);
+ pd->view = nullptr;
+ if (space->has_view_override()) {
+ const ARegion *region = draw_ctx->region;
+ pd->view = space->create_view_override(region);
+ }
+ }
+
+ void cache_populate()
+ {
+ IMAGE_StorageList *stl = vedata->stl;
+ IMAGE_PrivateData *pd = stl->pd;
+ Main *bmain = CTX_data_main(draw_ctx->evil_C);
+ pd->image = space->get_image(bmain);
+ if (pd->image == nullptr) {
+ /* Early exit, nothing to draw. */
+ return;
+ }
+ pd->ibuf = space->acquire_image_buffer(pd->image, &pd->lock);
+ ImageUser *iuser = space->get_image_user();
+ drawing_mode.cache_image(space.get(), vedata, pd->image, iuser, pd->ibuf);
+ }
+
+ void draw_finish()
+ {
+ drawing_mode.draw_finish(vedata);
+
+ IMAGE_StorageList *stl = vedata->stl;
+ IMAGE_PrivateData *pd = stl->pd;
+ space->release_buffer(pd->image, pd->ibuf, pd->lock);
+ pd->image = nullptr;
+ pd->ibuf = nullptr;
+ }
+
+ void draw_scene()
+ {
+ drawing_mode.draw_scene(vedata);
+ }
+};
+
+/* -------------------------------------------------------------------- */
+/** \name Engine Callbacks
+ * \{ */
+
+static void IMAGE_engine_init(void *ved)
+{
+ IMAGE_shader_library_ensure();
+ IMAGE_Data *vedata = (IMAGE_Data *)ved;
+ IMAGE_StorageList *stl = vedata->stl;
+ if (!stl->pd) {
+ stl->pd = static_cast<IMAGE_PrivateData *>(MEM_callocN(sizeof(IMAGE_PrivateData), __func__));
+ }
+ IMAGE_PrivateData *pd = stl->pd;
+
+ pd->ibuf = nullptr;
+ pd->lock = nullptr;
+ pd->texture = nullptr;
+}
+
+static void IMAGE_cache_init(void *vedata)
+{
+ const DRWContextState *draw_ctx = DRW_context_state_get();
+ ImageEngine image_engine(draw_ctx, static_cast<IMAGE_Data *>(vedata));
+ image_engine.cache_init();
+ image_engine.cache_populate();
+}
+
+static void IMAGE_cache_populate(void *UNUSED(vedata), Object *UNUSED(ob))
+{
+ /* Function intentional left empty. `cache_populate` is required to be implemented. */
+}
+
+static void IMAGE_draw_scene(void *vedata)
+{
+ const DRWContextState *draw_ctx = DRW_context_state_get();
+ ImageEngine image_engine(draw_ctx, static_cast<IMAGE_Data *>(vedata));
+ image_engine.draw_scene();
+ image_engine.draw_finish();
+}
+
+static void IMAGE_engine_free()
+{
+ IMAGE_shader_free();
+}
+
+/** \} */
+
+static const DrawEngineDataSize IMAGE_data_size = DRW_VIEWPORT_DATA_SIZE(IMAGE_Data);
+
+} // namespace blender::draw::image_engine
+
+extern "C" {
+
+using namespace blender::draw::image_engine;
+
+DrawEngineType draw_engine_image_type = {
+ nullptr, /* next */
+ nullptr, /* prev */
+ N_("UV/Image"), /* idname */
+ &IMAGE_data_size, /* vedata_size */
+ &IMAGE_engine_init, /* engine_init */
+ &IMAGE_engine_free, /* engine_free */
+ &IMAGE_cache_init, /* cache_init */
+ &IMAGE_cache_populate, /* cache_populate */
+ nullptr, /* cache_finish */
+ &IMAGE_draw_scene, /* draw_scene */
+ nullptr, /* view_update */
+ nullptr, /* id_update */
+ nullptr, /* render_to_image */
+ nullptr, /* store_metadata */
+};
+}
diff --git a/source/blender/draw/engines/image/image_engine.h b/source/blender/draw/engines/image/image_engine.h
index 0098d863ef9..f7e2f53d41b 100644
--- a/source/blender/draw/engines/image/image_engine.h
+++ b/source/blender/draw/engines/image/image_engine.h
@@ -17,9 +17,17 @@
*/
/** \file
- * \ingroup draw_editors
+ * \ingroup draw_engine
*/
#pragma once
+#ifdef __cplusplus
+extern "C" {
+#endif
+
extern DrawEngineType draw_engine_image_type;
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/draw/engines/image/image_private.hh b/source/blender/draw/engines/image/image_private.hh
new file mode 100644
index 00000000000..a62cd882e40
--- /dev/null
+++ b/source/blender/draw/engines/image/image_private.hh
@@ -0,0 +1,196 @@
+/*
+ * 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.
+ *
+ * Copyright 2020, Blender Foundation.
+ */
+
+/** \file
+ * \ingroup draw_engine
+ */
+
+#pragma once
+
+#include <optional>
+
+/* Forward declarations */
+extern "C" {
+struct GPUTexture;
+struct ImBuf;
+struct Image;
+}
+
+/* *********** LISTS *********** */
+
+namespace blender::draw::image_engine {
+
+/* GPUViewport.storage
+ * Is freed every time the viewport engine changes. */
+struct IMAGE_PassList {
+ DRWPass *image_pass;
+};
+
+struct IMAGE_PrivateData {
+ void *lock;
+ struct ImBuf *ibuf;
+ struct Image *image;
+ struct DRWView *view;
+
+ struct GPUTexture *texture;
+ bool owns_texture;
+};
+
+struct IMAGE_StorageList {
+ IMAGE_PrivateData *pd;
+};
+
+struct IMAGE_Data {
+ void *engine_type;
+ DRWViewportEmptyList *fbl;
+ DRWViewportEmptyList *txl;
+ IMAGE_PassList *psl;
+ IMAGE_StorageList *stl;
+};
+
+/* Shader parameters. */
+#define IMAGE_DRAW_FLAG_SHOW_ALPHA (1 << 0)
+#define IMAGE_DRAW_FLAG_APPLY_ALPHA (1 << 1)
+#define IMAGE_DRAW_FLAG_SHUFFLING (1 << 2)
+#define IMAGE_DRAW_FLAG_DEPTH (1 << 3)
+#define IMAGE_DRAW_FLAG_DO_REPEAT (1 << 4)
+#define IMAGE_DRAW_FLAG_USE_WORLD_POS (1 << 5)
+
+struct ShaderParameters {
+ constexpr static float color[4] = {1.0f, 1.0f, 1.0f, 1.0f};
+
+ int flags = 0;
+ float shuffle[4];
+ float far_near[2];
+ bool use_premul_alpha = false;
+
+ ShaderParameters()
+ {
+ copy_v4_fl(shuffle, 1.0f);
+ copy_v2_fl2(far_near, 100.0f, 0.0f);
+ }
+};
+
+/**
+ * Space accessor.
+ *
+ * Image engine is used to draw the images inside multiple spaces \see SpaceLink.
+ * The AbstractSpaceAccessor is an interface to communicate with a space.
+ */
+class AbstractSpaceAccessor {
+ public:
+ virtual ~AbstractSpaceAccessor() = default;
+
+ /**
+ * Return the active image of the space.
+ *
+ * The returned image will be drawn in the space.
+ *
+ * The return value is optional.
+ */
+ virtual Image *get_image(Main *bmain) = 0;
+
+ /**
+ * Return the #ImageUser of the space.
+ *
+ * The return value is optional.
+ */
+ virtual ImageUser *get_image_user() = 0;
+
+ /**
+ * Acquire the image buffer of the image.
+ *
+ * \param image: Image to get the buffer from. Image is the same as returned from the #get_image
+ * member.
+ * \param lock: pointer to a lock object.
+ * \return Image buffer of the given image.
+ */
+ virtual ImBuf *acquire_image_buffer(Image *image, void **lock) = 0;
+
+ /**
+ * Release a previous locked image from #acquire_image_buffer.
+ */
+ virtual void release_buffer(Image *image, ImBuf *image_buffer, void *lock) = 0;
+
+ /**
+ * Update the r_shader_parameters with space specific settings.
+ *
+ * Only update the #ShaderParameters.flags and #ShaderParameters.shuffle. Other parameters
+ * are updated inside the image engine.
+ */
+ virtual void get_shader_parameters(ShaderParameters &r_shader_parameters,
+ ImBuf *image_buffer,
+ bool is_tiled) = 0;
+
+ /**
+ * Retrieve the gpu textures to draw.
+ */
+ virtual void get_gpu_textures(Image *image,
+ ImageUser *iuser,
+ ImBuf *image_buffer,
+ GPUTexture **r_gpu_texture,
+ bool *r_owns_texture,
+ GPUTexture **r_tex_tile_data) = 0;
+
+ /**
+ * Does this space override the view.
+ * When so this member should return true and the create_view_override must return the view to
+ * use during drawing.
+ */
+ virtual bool has_view_override() const = 0;
+
+ /**
+ * Override the view for drawing.
+ * Should match #has_view_override.
+ */
+ virtual DRWView *create_view_override(const ARegion *UNUSED(region)) = 0;
+
+ /**
+ * Initialize the matrix that will be used to draw the image. The matrix will be send as object
+ * matrix to the drawing pipeline.
+ */
+ virtual void get_image_mat(const ImBuf *image_buffer,
+ const ARegion *region,
+ float r_mat[4][4]) const = 0;
+}; // namespace blender::draw::image_engine
+
+/**
+ * Abstract class for a drawing mode of the image engine.
+ *
+ * The drawing mode decides how to draw the image on the screen. Each way how to draw would have
+ * its own subclass. For now there is only a single drawing mode. #DefaultDrawingMode.
+ **/
+class AbstractDrawingMode {
+ public:
+ virtual ~AbstractDrawingMode() = default;
+ virtual void cache_init(IMAGE_Data *vedata) const = 0;
+ virtual void cache_image(AbstractSpaceAccessor *space,
+ IMAGE_Data *vedata,
+ Image *image,
+ ImageUser *iuser,
+ ImBuf *image_buffer) const = 0;
+ virtual void draw_scene(IMAGE_Data *vedata) const = 0;
+ virtual void draw_finish(IMAGE_Data *vedata) const = 0;
+};
+
+/* image_shader.c */
+GPUShader *IMAGE_shader_image_get(bool is_tiled_image);
+void IMAGE_shader_library_ensure(void);
+void IMAGE_shader_free(void);
+
+} // namespace blender::draw::image_engine
diff --git a/source/blender/draw/engines/image/image_shader.c b/source/blender/draw/engines/image/image_shader.cc
index 691c0d7029a..1c6abf36505 100644
--- a/source/blender/draw/engines/image/image_shader.c
+++ b/source/blender/draw/engines/image/image_shader.cc
@@ -27,27 +27,31 @@
#include "GPU_batch.h"
#include "image_engine.h"
-#include "image_private.h"
+#include "image_private.hh"
+extern "C" {
extern char datatoc_common_colormanagement_lib_glsl[];
extern char datatoc_common_globals_lib_glsl[];
extern char datatoc_common_view_lib_glsl[];
extern char datatoc_engine_image_frag_glsl[];
extern char datatoc_engine_image_vert_glsl[];
+}
+
+namespace blender::draw::image_engine {
-typedef struct IMAGE_Shaders {
+struct IMAGE_Shaders {
GPUShader *image_sh[2];
-} IMAGE_Shaders;
+};
static struct {
IMAGE_Shaders shaders;
DRWShaderLibrary *lib;
-} e_data = {{{0}}}; /* Engine data */
+} e_data = {{{nullptr}}}; /* Engine data */
-void IMAGE_shader_library_ensure(void)
+void IMAGE_shader_library_ensure()
{
- if (e_data.lib == NULL) {
+ if (e_data.lib == nullptr) {
e_data.lib = DRW_shader_library_create();
/* NOTE: These need to be ordered by dependencies. */
DRW_SHADER_LIB_ADD(e_data.lib, common_colormanagement_lib);
@@ -60,18 +64,18 @@ GPUShader *IMAGE_shader_image_get(bool is_tiled_image)
{
const int index = is_tiled_image ? 1 : 0;
IMAGE_Shaders *sh_data = &e_data.shaders;
- if (!sh_data->image_sh[index]) {
+ if (sh_data->image_sh[index] == nullptr) {
sh_data->image_sh[index] = DRW_shader_create_with_shaderlib(
datatoc_engine_image_vert_glsl,
- NULL,
+ nullptr,
datatoc_engine_image_frag_glsl,
e_data.lib,
- is_tiled_image ? "#define TILED_IMAGE\n" : NULL);
+ is_tiled_image ? "#define TILED_IMAGE\n" : nullptr);
}
return sh_data->image_sh[index];
}
-void IMAGE_shader_free(void)
+void IMAGE_shader_free()
{
GPUShader **sh_data_as_array = (GPUShader **)&e_data.shaders;
for (int i = 0; i < (sizeof(IMAGE_Shaders) / sizeof(GPUShader *)); i++) {
@@ -80,3 +84,5 @@ void IMAGE_shader_free(void)
DRW_SHADER_LIB_FREE_SAFE(e_data.lib);
}
+
+} // namespace blender::draw::image_engine
diff --git a/source/blender/draw/engines/image/image_space_image.hh b/source/blender/draw/engines/image/image_space_image.hh
new file mode 100644
index 00000000000..7728a963254
--- /dev/null
+++ b/source/blender/draw/engines/image/image_space_image.hh
@@ -0,0 +1,182 @@
+/*
+ * 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.
+ *
+ * Copyright 2021, Blender Foundation.
+ */
+
+/** \file
+ * \ingroup draw_engine
+ */
+
+#pragma once
+
+#include "image_private.hh"
+
+namespace blender::draw::image_engine {
+
+class SpaceImageAccessor : public AbstractSpaceAccessor {
+ SpaceImage *sima;
+
+ public:
+ SpaceImageAccessor(SpaceImage *sima) : sima(sima)
+ {
+ }
+
+ Image *get_image(Main *UNUSED(bmain)) override
+ {
+ return ED_space_image(sima);
+ }
+
+ ImageUser *get_image_user() override
+ {
+ return &sima->iuser;
+ }
+
+ ImBuf *acquire_image_buffer(Image *UNUSED(image), void **lock) override
+ {
+ return ED_space_image_acquire_buffer(sima, lock, 0);
+ }
+
+ void release_buffer(Image *UNUSED(image), ImBuf *image_buffer, void *lock) override
+ {
+ ED_space_image_release_buffer(sima, image_buffer, lock);
+ }
+
+ void get_shader_parameters(ShaderParameters &r_shader_parameters,
+ ImBuf *image_buffer,
+ bool is_tiled) override
+ {
+ const int sima_flag = sima->flag & ED_space_image_get_display_channel_mask(image_buffer);
+ const bool do_repeat = (!is_tiled) && ((sima->flag & SI_DRAW_TILE) != 0);
+ SET_FLAG_FROM_TEST(r_shader_parameters.flags, do_repeat, IMAGE_DRAW_FLAG_DO_REPEAT);
+ SET_FLAG_FROM_TEST(r_shader_parameters.flags, is_tiled, IMAGE_DRAW_FLAG_USE_WORLD_POS);
+ if ((sima_flag & SI_USE_ALPHA) != 0) {
+ /* Show RGBA */
+ r_shader_parameters.flags |= IMAGE_DRAW_FLAG_SHOW_ALPHA | IMAGE_DRAW_FLAG_APPLY_ALPHA;
+ }
+ else if ((sima_flag & SI_SHOW_ALPHA) != 0) {
+ r_shader_parameters.flags |= IMAGE_DRAW_FLAG_SHUFFLING;
+ copy_v4_fl4(r_shader_parameters.shuffle, 0.0f, 0.0f, 0.0f, 1.0f);
+ }
+ else if ((sima_flag & SI_SHOW_ZBUF) != 0) {
+ r_shader_parameters.flags |= IMAGE_DRAW_FLAG_DEPTH | IMAGE_DRAW_FLAG_SHUFFLING;
+ copy_v4_fl4(r_shader_parameters.shuffle, 1.0f, 0.0f, 0.0f, 0.0f);
+ }
+ else if ((sima_flag & SI_SHOW_R) != 0) {
+ r_shader_parameters.flags |= IMAGE_DRAW_FLAG_SHUFFLING;
+ if (IMB_alpha_affects_rgb(image_buffer)) {
+ r_shader_parameters.flags |= IMAGE_DRAW_FLAG_APPLY_ALPHA;
+ }
+ copy_v4_fl4(r_shader_parameters.shuffle, 1.0f, 0.0f, 0.0f, 0.0f);
+ }
+ else if ((sima_flag & SI_SHOW_G) != 0) {
+ r_shader_parameters.flags |= IMAGE_DRAW_FLAG_SHUFFLING;
+ if (IMB_alpha_affects_rgb(image_buffer)) {
+ r_shader_parameters.flags |= IMAGE_DRAW_FLAG_APPLY_ALPHA;
+ }
+ copy_v4_fl4(r_shader_parameters.shuffle, 0.0f, 1.0f, 0.0f, 0.0f);
+ }
+ else if ((sima_flag & SI_SHOW_B) != 0) {
+ r_shader_parameters.flags |= IMAGE_DRAW_FLAG_SHUFFLING;
+ if (IMB_alpha_affects_rgb(image_buffer)) {
+ r_shader_parameters.flags |= IMAGE_DRAW_FLAG_APPLY_ALPHA;
+ }
+ copy_v4_fl4(r_shader_parameters.shuffle, 0.0f, 0.0f, 1.0f, 0.0f);
+ }
+ else /* RGB */ {
+ if (IMB_alpha_affects_rgb(image_buffer)) {
+ r_shader_parameters.flags |= IMAGE_DRAW_FLAG_APPLY_ALPHA;
+ }
+ }
+ }
+
+ bool has_view_override() const override
+ {
+ return false;
+ }
+ DRWView *create_view_override(const ARegion *UNUSED(region)) override
+ {
+ return nullptr;
+ }
+
+ void get_gpu_textures(Image *image,
+ ImageUser *iuser,
+ ImBuf *image_buffer,
+ GPUTexture **r_gpu_texture,
+ bool *r_owns_texture,
+ GPUTexture **r_tex_tile_data) override
+ {
+ if (image->rr != nullptr) {
+ /* Update multi-index and pass for the current eye. */
+ BKE_image_multilayer_index(image->rr, iuser);
+ }
+ else {
+ BKE_image_multiview_index(image, iuser);
+ }
+
+ if (image_buffer == nullptr) {
+ return;
+ }
+
+ if (image_buffer->rect == nullptr && image_buffer->rect_float == nullptr) {
+ /* This code-path is only supposed to happen when drawing a lazily-allocatable render result.
+ * In all the other cases the `ED_space_image_acquire_buffer()` is expected to return nullptr
+ * as an image buffer when it has no pixels. */
+
+ BLI_assert(image->type == IMA_TYPE_R_RESULT);
+
+ float zero[4] = {0, 0, 0, 0};
+ *r_gpu_texture = GPU_texture_create_2d(__func__, 1, 1, 0, GPU_RGBA16F, zero);
+ *r_owns_texture = true;
+ return;
+ }
+
+ const int sima_flag = sima->flag & ED_space_image_get_display_channel_mask(image_buffer);
+ if (sima_flag & SI_SHOW_ZBUF &&
+ (image_buffer->zbuf || image_buffer->zbuf_float || (image_buffer->channels == 1))) {
+ if (image_buffer->zbuf) {
+ BLI_assert_msg(0, "Integer based depth buffers not supported");
+ }
+ else if (image_buffer->zbuf_float) {
+ *r_gpu_texture = GPU_texture_create_2d(
+ __func__, image_buffer->x, image_buffer->y, 0, GPU_R16F, image_buffer->zbuf_float);
+ *r_owns_texture = true;
+ }
+ else if (image_buffer->rect_float && image_buffer->channels == 1) {
+ *r_gpu_texture = GPU_texture_create_2d(
+ __func__, image_buffer->x, image_buffer->y, 0, GPU_R16F, image_buffer->rect_float);
+ *r_owns_texture = true;
+ }
+ }
+ else if (image->source == IMA_SRC_TILED) {
+ *r_gpu_texture = BKE_image_get_gpu_tiles(image, iuser, image_buffer);
+ *r_tex_tile_data = BKE_image_get_gpu_tilemap(image, iuser, nullptr);
+ *r_owns_texture = false;
+ }
+ else {
+ *r_gpu_texture = BKE_image_get_gpu_texture(image, iuser, image_buffer);
+ *r_owns_texture = false;
+ }
+ }
+
+ void get_image_mat(const ImBuf *UNUSED(image_buffer),
+ const ARegion *UNUSED(region),
+ float r_mat[4][4]) const override
+ {
+ unit_m4(r_mat);
+ }
+};
+
+} // namespace blender::draw::image_engine
diff --git a/source/blender/draw/engines/image/image_space_node.hh b/source/blender/draw/engines/image/image_space_node.hh
new file mode 100644
index 00000000000..3ca18eec742
--- /dev/null
+++ b/source/blender/draw/engines/image/image_space_node.hh
@@ -0,0 +1,138 @@
+/*
+ * 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.
+ *
+ * Copyright 2021, Blender Foundation.
+ */
+
+/** \file
+ * \ingroup draw_engine
+ */
+
+#pragma once
+
+#include "image_private.hh"
+
+namespace blender::draw::image_engine {
+
+class SpaceNodeAccessor : public AbstractSpaceAccessor {
+ SpaceNode *snode;
+
+ public:
+ SpaceNodeAccessor(SpaceNode *snode) : snode(snode)
+ {
+ }
+
+ Image *get_image(Main *bmain) override
+ {
+ return BKE_image_ensure_viewer(bmain, IMA_TYPE_COMPOSITE, "Viewer Node");
+ }
+
+ ImageUser *get_image_user() override
+ {
+ return nullptr;
+ }
+
+ ImBuf *acquire_image_buffer(Image *image, void **lock) override
+ {
+ return BKE_image_acquire_ibuf(image, nullptr, lock);
+ }
+
+ void release_buffer(Image *image, ImBuf *ibuf, void *lock) override
+ {
+ BKE_image_release_ibuf(image, ibuf, lock);
+ }
+
+ bool has_view_override() const override
+ {
+ return true;
+ }
+
+ DRWView *create_view_override(const ARegion *region) override
+ {
+ /* Setup a screen pixel view. The backdrop of the node editor doesn't follow the region. */
+ float winmat[4][4], viewmat[4][4];
+ orthographic_m4(viewmat, 0.0, region->winx, 0.0, region->winy, 0.0, 1.0);
+ unit_m4(winmat);
+ return DRW_view_create(viewmat, winmat, nullptr, nullptr, nullptr);
+ }
+
+ void get_shader_parameters(ShaderParameters &r_shader_parameters,
+ ImBuf *ibuf,
+ bool UNUSED(is_tiled)) override
+ {
+ if ((snode->flag & SNODE_USE_ALPHA) != 0) {
+ /* Show RGBA */
+ r_shader_parameters.flags |= IMAGE_DRAW_FLAG_SHOW_ALPHA | IMAGE_DRAW_FLAG_APPLY_ALPHA;
+ }
+ else if ((snode->flag & SNODE_SHOW_ALPHA) != 0) {
+ r_shader_parameters.flags |= IMAGE_DRAW_FLAG_SHUFFLING;
+ copy_v4_fl4(r_shader_parameters.shuffle, 0.0f, 0.0f, 0.0f, 1.0f);
+ }
+ else if ((snode->flag & SNODE_SHOW_R) != 0) {
+ r_shader_parameters.flags |= IMAGE_DRAW_FLAG_SHUFFLING;
+ if (IMB_alpha_affects_rgb(ibuf)) {
+ r_shader_parameters.flags |= IMAGE_DRAW_FLAG_APPLY_ALPHA;
+ }
+ copy_v4_fl4(r_shader_parameters.shuffle, 1.0f, 0.0f, 0.0f, 0.0f);
+ }
+ else if ((snode->flag & SNODE_SHOW_G) != 0) {
+ r_shader_parameters.flags |= IMAGE_DRAW_FLAG_SHUFFLING;
+ if (IMB_alpha_affects_rgb(ibuf)) {
+ r_shader_parameters.flags |= IMAGE_DRAW_FLAG_APPLY_ALPHA;
+ }
+ copy_v4_fl4(r_shader_parameters.shuffle, 0.0f, 1.0f, 0.0f, 0.0f);
+ }
+ else if ((snode->flag & SNODE_SHOW_B) != 0) {
+ r_shader_parameters.flags |= IMAGE_DRAW_FLAG_SHUFFLING;
+ if (IMB_alpha_affects_rgb(ibuf)) {
+ r_shader_parameters.flags |= IMAGE_DRAW_FLAG_APPLY_ALPHA;
+ }
+ copy_v4_fl4(r_shader_parameters.shuffle, 0.0f, 0.0f, 1.0f, 0.0f);
+ }
+ else /* RGB */ {
+ if (IMB_alpha_affects_rgb(ibuf)) {
+ r_shader_parameters.flags |= IMAGE_DRAW_FLAG_APPLY_ALPHA;
+ }
+ }
+ }
+
+ void get_gpu_textures(Image *image,
+ ImageUser *iuser,
+ ImBuf *ibuf,
+ GPUTexture **r_gpu_texture,
+ bool *r_owns_texture,
+ GPUTexture **r_tex_tile_data) override
+ {
+ *r_gpu_texture = BKE_image_get_gpu_texture(image, iuser, ibuf);
+ *r_owns_texture = false;
+ *r_tex_tile_data = nullptr;
+ }
+
+ void get_image_mat(const ImBuf *image_buffer,
+ const ARegion *region,
+ float r_mat[4][4]) const override
+ {
+ unit_m4(r_mat);
+ const float ibuf_width = image_buffer->x;
+ const float ibuf_height = image_buffer->y;
+
+ r_mat[0][0] = ibuf_width * snode->zoom;
+ r_mat[1][1] = ibuf_height * snode->zoom;
+ r_mat[3][0] = (region->winx - snode->zoom * ibuf_width) / 2 + snode->xof;
+ r_mat[3][1] = (region->winy - snode->zoom * ibuf_height) / 2 + snode->yof;
+ }
+};
+
+} // namespace blender::draw::image_engine
diff --git a/source/blender/draw/engines/workbench/shaders/workbench_effect_dof_frag.glsl b/source/blender/draw/engines/workbench/shaders/workbench_effect_dof_frag.glsl
index 92d5df1a13a..c4580e6ffc3 100644
--- a/source/blender/draw/engines/workbench/shaders/workbench_effect_dof_frag.glsl
+++ b/source/blender/draw/engines/workbench/shaders/workbench_effect_dof_frag.glsl
@@ -95,7 +95,7 @@ void main()
/**
* ----------------- STEP 0.5 ------------------
- * Custom Coc aware downsampling. Quater res pass.
+ * Custom Coc aware downsampling. Quarter res pass.
*/
#ifdef DOWNSAMPLE
diff --git a/source/blender/draw/intern/draw_manager.c b/source/blender/draw/intern/draw_manager.c
index 59ed5316c02..1c7e8bd8ad6 100644
--- a/source/blender/draw/intern/draw_manager.c
+++ b/source/blender/draw/intern/draw_manager.c
@@ -1368,11 +1368,11 @@ void DRW_notify_view_update(const DRWUpdateContext *update_ctx)
}
/* update a viewport which belongs to a GPUOffscreen */
-void DRW_notify_view_update_offscreen(struct Depsgraph *depsgraph,
- RenderEngineType *engine_type,
- ARegion *region,
- View3D *v3d,
- GPUViewport *viewport)
+static void DRW_notify_view_update_offscreen(struct Depsgraph *depsgraph,
+ RenderEngineType *engine_type,
+ ARegion *region,
+ View3D *v3d,
+ GPUViewport *viewport)
{
if (viewport && GPU_viewport_do_update(viewport)) {
diff --git a/source/blender/draw/tests/shaders_test.cc b/source/blender/draw/tests/shaders_test.cc
index a9810b4cc77..ef702821a59 100644
--- a/source/blender/draw/tests/shaders_test.cc
+++ b/source/blender/draw/tests/shaders_test.cc
@@ -13,15 +13,18 @@
#include "intern/draw_manager_testing.h"
+#include "engines/basic/basic_private.h"
#include "engines/eevee/eevee_private.h"
#include "engines/gpencil/gpencil_engine.h"
-#include "engines/image/image_private.h"
+#include "engines/image/image_private.hh"
#include "engines/overlay/overlay_private.h"
#include "engines/workbench/workbench_private.h"
#include "intern/draw_shader.h"
namespace blender::draw {
+using namespace blender::draw::image_engine;
+
static void test_workbench_glsl_shaders()
{
workbench_shader_library_ensure();
@@ -394,4 +397,17 @@ static void test_draw_glsl_shaders()
}
DRAW_TEST(draw_glsl_shaders)
+static void test_basic_glsl_shaders()
+{
+ for (int i = 0; i < GPU_SHADER_CFG_LEN; i++) {
+ eGPUShaderConfig sh_cfg = static_cast<eGPUShaderConfig>(i);
+ BASIC_shaders_depth_sh_get(sh_cfg);
+ BASIC_shaders_pointcloud_depth_sh_get(sh_cfg);
+ BASIC_shaders_depth_conservative_sh_get(sh_cfg);
+ BASIC_shaders_pointcloud_depth_conservative_sh_get(sh_cfg);
+ }
+ BASIC_shaders_free();
+}
+DRAW_TEST(basic_glsl_shaders)
+
} // namespace blender::draw
diff --git a/source/blender/editors/animation/anim_channels_defines.c b/source/blender/editors/animation/anim_channels_defines.c
index e5dc9a83ebb..9f2681fbf7a 100644
--- a/source/blender/editors/animation/anim_channels_defines.c
+++ b/source/blender/editors/animation/anim_channels_defines.c
@@ -199,7 +199,7 @@ static void acf_generic_channel_color(bAnimContext *ac, bAnimListElem *ale, floa
}
/* set color for normal channels
- * - use 3 shades of color group/standard color for 3 indention level
+ * - use 3 shades of color group/standard color for 3 indentation level
* - only use group colors if allowed to, and if actually feasible
*/
if (showGroupColors && (grp) && (grp->customCol)) {
diff --git a/source/blender/editors/animation/anim_ipo_utils.c b/source/blender/editors/animation/anim_ipo_utils.c
index 6fe32699907..05837ed17b9 100644
--- a/source/blender/editors/animation/anim_ipo_utils.c
+++ b/source/blender/editors/animation/anim_ipo_utils.c
@@ -145,6 +145,22 @@ int getname_anim_fcurve(char *name, ID *id, FCurve *fcu)
}
}
}
+ /* For node sockets, it is useful to include the node name as well (multiple similar nodes
+ * are not distinguishable otherwise). Unfortunately, the node label cannot be retrieved
+ * from the rna path, for this to work access to the underlying node is needed (but finding
+ * the node iterates all nodes & sockets which would result in bad performance in some
+ * circumstances). */
+ if (RNA_struct_is_a(ptr.type, &RNA_NodeSocket)) {
+ char nodename[256];
+ if (BLI_str_quoted_substr(fcu->rna_path, "nodes[", nodename, sizeof(nodename))) {
+ const char *structname_all = BLI_sprintfN("%s : %s", nodename, structname);
+ if (free_structname) {
+ MEM_freeN((void *)structname);
+ }
+ structname = structname_all;
+ free_structname = 1;
+ }
+ }
}
/* Property Name is straightforward */
diff --git a/source/blender/editors/animation/anim_motion_paths.c b/source/blender/editors/animation/anim_motion_paths.c
index 0d812198d04..335034fef6e 100644
--- a/source/blender/editors/animation/anim_motion_paths.c
+++ b/source/blender/editors/animation/anim_motion_paths.c
@@ -176,11 +176,11 @@ static void motionpaths_calc_bake_targets(ListBase *targets, int cframe)
copy_v3_v3(mpv->co, pchan_eval->pose_tail);
}
- /* result must be in worldspace */
+ /* Result must be in world-space. */
mul_m4_v3(ob_eval->obmat, mpv->co);
}
else {
- /* worldspace object location */
+ /* World-space object location. */
copy_v3_v3(mpv->co, ob_eval->obmat[3]);
}
diff --git a/source/blender/editors/armature/armature_relations.c b/source/blender/editors/armature/armature_relations.c
index 32fd1c9ad41..b06e4b6a9e7 100644
--- a/source/blender/editors/armature/armature_relations.c
+++ b/source/blender/editors/armature/armature_relations.c
@@ -745,6 +745,10 @@ void ARMATURE_OT_separate(wmOperatorType *ot)
#define ARM_PAR_CONNECT 1
#define ARM_PAR_OFFSET 2
+/* armature un-parenting options */
+#define ARM_PAR_CLEAR 1
+#define ARM_PAR_CLEAR_DISCONNECT 2
+
/* check for null, before calling! */
static void bone_connect_to_existing_parent(EditBone *bone)
{
@@ -904,19 +908,29 @@ static int armature_parent_set_invoke(bContext *C,
wmOperator *UNUSED(op),
const wmEvent *UNUSED(event))
{
- bool all_childbones = false;
+ /* False when all selected bones are parented to the active bone. */
+ bool enable_offset = false;
+ /* False when all selected bones are connected to the active bone. */
+ bool enable_connect = false;
{
Object *ob = CTX_data_edit_object(C);
bArmature *arm = ob->data;
EditBone *actbone = arm->act_edbone;
LISTBASE_FOREACH (EditBone *, ebone, arm->edbo) {
- if (EBONE_EDITABLE(ebone) && (ebone->flag & BONE_SELECTED)) {
- if (ebone != actbone) {
- if (ebone->parent != actbone) {
- all_childbones = true;
- break;
- }
- }
+ if (!EBONE_EDITABLE(ebone) || !(ebone->flag & BONE_SELECTED)) {
+ continue;
+ }
+ if (ebone == actbone) {
+ continue;
+ }
+
+ if (ebone->parent != actbone) {
+ enable_offset = true;
+ enable_connect = true;
+ break;
+ }
+ if (!(ebone->flag & BONE_CONNECTED)) {
+ enable_connect = true;
}
}
}
@@ -924,11 +938,14 @@ static int armature_parent_set_invoke(bContext *C,
uiPopupMenu *pup = UI_popup_menu_begin(
C, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Make Parent"), ICON_NONE);
uiLayout *layout = UI_popup_menu_layout(pup);
- uiItemEnumO(layout, "ARMATURE_OT_parent_set", NULL, 0, "type", ARM_PAR_CONNECT);
- if (all_childbones) {
- /* Object becomes parent, make the associated menus. */
- uiItemEnumO(layout, "ARMATURE_OT_parent_set", NULL, 0, "type", ARM_PAR_OFFSET);
- }
+
+ uiLayout *row_offset = uiLayoutRow(layout, false);
+ uiLayoutSetEnabled(row_offset, enable_offset);
+ uiItemEnumO(row_offset, "ARMATURE_OT_parent_set", NULL, 0, "type", ARM_PAR_OFFSET);
+
+ uiLayout *row_connect = uiLayoutRow(layout, false);
+ uiLayoutSetEnabled(row_connect, enable_connect);
+ uiItemEnumO(row_connect, "ARMATURE_OT_parent_set", NULL, 0, "type", ARM_PAR_CONNECT);
UI_popup_menu_end(C, pup);
@@ -955,8 +972,8 @@ void ARMATURE_OT_parent_set(wmOperatorType *ot)
}
static const EnumPropertyItem prop_editarm_clear_parent_types[] = {
- {1, "CLEAR", 0, "Clear Parent", ""},
- {2, "DISCONNECT", 0, "Disconnect Bone", ""},
+ {ARM_PAR_CLEAR, "CLEAR", 0, "Clear Parent", ""},
+ {ARM_PAR_CLEAR_DISCONNECT, "DISCONNECT", 0, "Disconnect Bone", ""},
{0, NULL, 0, NULL, NULL},
};
@@ -1012,6 +1029,51 @@ static int armature_parent_clear_exec(bContext *C, wmOperator *op)
return OPERATOR_FINISHED;
}
+static int armature_parent_clear_invoke(bContext *C,
+ wmOperator *UNUSED(op),
+ const wmEvent *UNUSED(event))
+{
+ /* False when no selected bones are connected to the active bone. */
+ bool enable_disconnect = false;
+ /* False when no selected bones are parented to the active bone. */
+ bool enable_clear = false;
+ {
+ Object *ob = CTX_data_edit_object(C);
+ bArmature *arm = ob->data;
+ LISTBASE_FOREACH (EditBone *, ebone, arm->edbo) {
+ if (!EBONE_EDITABLE(ebone) || !(ebone->flag & BONE_SELECTED)) {
+ continue;
+ }
+ if (ebone->parent == NULL) {
+ continue;
+ }
+ enable_clear = true;
+
+ if (ebone->flag & BONE_CONNECTED) {
+ enable_disconnect = true;
+ break;
+ }
+ }
+ }
+
+ uiPopupMenu *pup = UI_popup_menu_begin(
+ C, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Clear Parent"), ICON_NONE);
+ uiLayout *layout = UI_popup_menu_layout(pup);
+
+ uiLayout *row_clear = uiLayoutRow(layout, false);
+ uiLayoutSetEnabled(row_clear, enable_clear);
+ uiItemEnumO(row_clear, "ARMATURE_OT_parent_clear", NULL, 0, "type", ARM_PAR_CLEAR);
+
+ uiLayout *row_disconnect = uiLayoutRow(layout, false);
+ uiLayoutSetEnabled(row_disconnect, enable_disconnect);
+ uiItemEnumO(
+ row_disconnect, "ARMATURE_OT_parent_clear", NULL, 0, "type", ARM_PAR_CLEAR_DISCONNECT);
+
+ UI_popup_menu_end(C, pup);
+
+ return OPERATOR_INTERFACE;
+}
+
void ARMATURE_OT_parent_clear(wmOperatorType *ot)
{
/* identifiers */
@@ -1021,7 +1083,7 @@ void ARMATURE_OT_parent_clear(wmOperatorType *ot)
"Remove the parent-child relationship between selected bones and their parents";
/* api callbacks */
- ot->invoke = WM_menu_invoke;
+ ot->invoke = armature_parent_clear_invoke;
ot->exec = armature_parent_clear_exec;
ot->poll = ED_operator_editarmature;
diff --git a/source/blender/editors/armature/pose_transform.c b/source/blender/editors/armature/pose_transform.c
index 279f79ac44b..70d6fa93104 100644
--- a/source/blender/editors/armature/pose_transform.c
+++ b/source/blender/editors/armature/pose_transform.c
@@ -797,13 +797,13 @@ static int pose_copy_exec(bContext *C, wmOperator *op)
BLI_addtail(&temp_bmain->objects, &ob_copy);
BLI_addtail(&temp_bmain->armatures, &arm_copy);
/* begin copy buffer on a temp bmain. */
- BKE_copybuffer_begin(temp_bmain);
+ BKE_copybuffer_copy_begin(temp_bmain);
/* Store the whole object to the copy buffer because pose can't be
* existing on its own.
*/
- BKE_copybuffer_tag_ID(&ob_copy.id);
+ BKE_copybuffer_copy_tag_ID(&ob_copy.id);
BLI_join_dirfile(str, sizeof(str), BKE_tempdir_base(), "copybuffer_pose.blend");
- BKE_copybuffer_save(temp_bmain, str, op->reports);
+ BKE_copybuffer_copy_end(temp_bmain, str, op->reports);
/* We clear the lists so no datablocks gets freed,
* This is required because objects in temp bmain shares same pointers
* as the real ones.
diff --git a/source/blender/editors/asset/ED_asset_list.hh b/source/blender/editors/asset/ED_asset_list.hh
index dcc07f54e75..24def2fb4ab 100644
--- a/source/blender/editors/asset/ED_asset_list.hh
+++ b/source/blender/editors/asset/ED_asset_list.hh
@@ -35,4 +35,4 @@ std::string ED_assetlist_asset_filepath_get(const bContext *C,
/* Can return false to stop iterating. */
using AssetListIterFn = blender::FunctionRef<bool(AssetHandle)>;
-void ED_assetlist_iterate(const AssetLibraryReference *library_reference, AssetListIterFn fn);
+void ED_assetlist_iterate(const AssetLibraryReference &library_reference, AssetListIterFn fn);
diff --git a/source/blender/editors/asset/intern/asset_catalog.cc b/source/blender/editors/asset/intern/asset_catalog.cc
index 8e1e5be2e47..9634665be7b 100644
--- a/source/blender/editors/asset/intern/asset_catalog.cc
+++ b/source/blender/editors/asset/intern/asset_catalog.cc
@@ -19,7 +19,6 @@
*/
#include "BKE_asset_catalog.hh"
-#include "BKE_asset_catalog_path.hh"
#include "BKE_asset_library.hh"
#include "BKE_main.h"
diff --git a/source/blender/editors/asset/intern/asset_filter.cc b/source/blender/editors/asset/intern/asset_filter.cc
index 329342a30cd..c22bbc923eb 100644
--- a/source/blender/editors/asset/intern/asset_filter.cc
+++ b/source/blender/editors/asset/intern/asset_filter.cc
@@ -22,7 +22,6 @@
#include "BLI_listbase.h"
-#include "DNA_ID.h"
#include "DNA_asset_types.h"
#include "ED_asset_filter.h"
diff --git a/source/blender/editors/asset/intern/asset_handle.cc b/source/blender/editors/asset/intern/asset_handle.cc
index 5c8d0b1349c..363bd9226da 100644
--- a/source/blender/editors/asset/intern/asset_handle.cc
+++ b/source/blender/editors/asset/intern/asset_handle.cc
@@ -26,7 +26,6 @@
#include <string>
-#include "DNA_asset_types.h"
#include "DNA_space_types.h"
#include "BLO_readfile.h"
diff --git a/source/blender/editors/asset/intern/asset_library_reference_enum.cc b/source/blender/editors/asset/intern/asset_library_reference_enum.cc
index 5a83893f8e1..102b2a97859 100644
--- a/source/blender/editors/asset/intern/asset_library_reference_enum.cc
+++ b/source/blender/editors/asset/intern/asset_library_reference_enum.cc
@@ -27,7 +27,6 @@
#include "BKE_preferences.h"
-#include "DNA_asset_types.h"
#include "DNA_userdef_types.h"
#include "UI_resources.h"
diff --git a/source/blender/editors/asset/intern/asset_list.cc b/source/blender/editors/asset/intern/asset_list.cc
index 4bc15e842fc..c1b1e33d428 100644
--- a/source/blender/editors/asset/intern/asset_list.cc
+++ b/source/blender/editors/asset/intern/asset_list.cc
@@ -32,7 +32,6 @@
#include "BLI_path_util.h"
#include "BLI_utility_mixins.hh"
-#include "DNA_asset_types.h"
#include "DNA_space_types.h"
#include "BKE_preferences.h"
@@ -40,7 +39,6 @@
#include "ED_fileselect.h"
#include "WM_api.h"
-#include "WM_types.h"
/* XXX uses private header of file-space. */
#include "../space_file/filelist.h"
@@ -458,9 +456,9 @@ bool ED_assetlist_storage_has_list_for_library(const AssetLibraryReference *libr
return AssetListStorage::lookup_list(*library_reference) != nullptr;
}
-void ED_assetlist_iterate(const AssetLibraryReference *library_reference, AssetListIterFn fn)
+void ED_assetlist_iterate(const AssetLibraryReference &library_reference, AssetListIterFn fn)
{
- AssetList *list = AssetListStorage::lookup_list(*library_reference);
+ AssetList *list = AssetListStorage::lookup_list(library_reference);
if (list) {
list->iterate(fn);
}
diff --git a/source/blender/editors/asset/intern/asset_mark_clear.cc b/source/blender/editors/asset/intern/asset_mark_clear.cc
index a0a2c63b407..2e5bdb63359 100644
--- a/source/blender/editors/asset/intern/asset_mark_clear.cc
+++ b/source/blender/editors/asset/intern/asset_mark_clear.cc
@@ -20,9 +20,6 @@
* Functions for marking and clearing assets.
*/
-#include <memory>
-#include <string>
-
#include "DNA_ID.h"
#include "BKE_asset.h"
@@ -32,8 +29,6 @@
#include "BKE_lib_id.h"
#include "BKE_main.h"
-#include "BLO_readfile.h"
-
#include "UI_interface_icons.h"
#include "RNA_access.h"
diff --git a/source/blender/editors/asset/intern/asset_ops.cc b/source/blender/editors/asset/intern/asset_ops.cc
index 1f5d3f5c101..3c4f6b8755f 100644
--- a/source/blender/editors/asset/intern/asset_ops.cc
+++ b/source/blender/editors/asset/intern/asset_ops.cc
@@ -18,8 +18,6 @@
* \ingroup edasset
*/
-#include "BKE_asset.h"
-#include "BKE_asset_catalog.hh"
#include "BKE_asset_library.hh"
#include "BKE_bpath.h"
#include "BKE_context.h"
@@ -32,8 +30,6 @@
#include "BLI_fileops.h"
#include "BLI_fnmatch.h"
#include "BLI_path_util.h"
-#include "BLI_string_ref.hh"
-#include "BLI_vector.hh"
#include "ED_asset.h"
#include "ED_asset_catalog.hh"
@@ -46,7 +42,6 @@
#include "RNA_define.h"
#include "WM_api.h"
-#include "WM_types.h"
#include "DNA_space_types.h"
diff --git a/source/blender/editors/asset/intern/asset_temp_id_consumer.cc b/source/blender/editors/asset/intern/asset_temp_id_consumer.cc
index f664eab5cbb..f136c08f129 100644
--- a/source/blender/editors/asset/intern/asset_temp_id_consumer.cc
+++ b/source/blender/editors/asset/intern/asset_temp_id_consumer.cc
@@ -23,7 +23,6 @@
#include <new>
-#include "DNA_asset_types.h"
#include "DNA_space_types.h"
#include "BKE_report.h"
diff --git a/source/blender/editors/curve/editcurve.c b/source/blender/editors/curve/editcurve.c
index 46bf1f6c9b5..3b05975d22d 100644
--- a/source/blender/editors/curve/editcurve.c
+++ b/source/blender/editors/curve/editcurve.c
@@ -4909,7 +4909,9 @@ bool ED_curve_editnurb_select_pick(
/** \name Spin Operator
* \{ */
-/* 'cent' is in object space and 'dvec' in worldspace.
+/**
+ * \param axis: is in world-space.
+ * \param cent: is in object-space.
*/
bool ed_editnurb_spin(
float viewmat[4][4], View3D *v3d, Object *obedit, const float axis[3], const float cent[3])
diff --git a/source/blender/editors/curve/editcurve_paint.c b/source/blender/editors/curve/editcurve_paint.c
index 26906b0ddcd..784f67ac4f1 100644
--- a/source/blender/editors/curve/editcurve_paint.c
+++ b/source/blender/editors/curve/editcurve_paint.c
@@ -102,7 +102,7 @@ struct CurveDrawData {
/* offset projection by this value */
bool use_offset;
- float offset[3]; /* worldspace */
+ float offset[3]; /* world-space */
float surface_offset;
bool use_surface_offset_absolute;
} project;
diff --git a/source/blender/editors/curve/editfont.c b/source/blender/editors/curve/editfont.c
index 1b44cf88db1..6f18798bd2a 100644
--- a/source/blender/editors/curve/editfont.c
+++ b/source/blender/editors/curve/editfont.c
@@ -2155,8 +2155,8 @@ void FONT_OT_open(wmOperatorType *ot)
FILE_SPECIAL,
FILE_OPENFILE,
WM_FILESEL_FILEPATH | WM_FILESEL_RELPATH,
- FILE_DEFAULTDISPLAY,
- FILE_SORT_DEFAULT);
+ FILE_IMGDISPLAY,
+ FILE_SORT_ALPHA);
}
/** \} */
diff --git a/source/blender/editors/gpencil/annotate_paint.c b/source/blender/editors/gpencil/annotate_paint.c
index ba603cdd6ec..bf53241a947 100644
--- a/source/blender/editors/gpencil/annotate_paint.c
+++ b/source/blender/editors/gpencil/annotate_paint.c
@@ -123,6 +123,8 @@ typedef struct tGPsdata {
ARegion *region;
/** needed for GP_STROKE_2DSPACE. */
View2D *v2d;
+ /** For operations that require occlusion testing. */
+ ViewDepths *depths;
/** for using the camera rect within the 3d view. */
rctf *subrect;
rctf subrect_data;
@@ -972,12 +974,13 @@ static void annotation_stroke_newfrombuffer(tGPsdata *p)
depth_arr = MEM_mallocN(sizeof(float) * gpd->runtime.sbuffer_used, "depth_points");
+ const ViewDepths *depths = p->depths;
for (i = 0, ptc = gpd->runtime.sbuffer; i < gpd->runtime.sbuffer_used; i++, ptc++, pt++) {
round_v2i_v2fl(mval_i, &ptc->x);
- if ((ED_view3d_autodist_depth(p->region, mval_i, depth_margin, depth_arr + i) == 0) &&
- (i && (ED_view3d_autodist_depth_seg(
- p->region, mval_i, mval_prev, depth_margin + 1, depth_arr + i) == 0))) {
+ if ((ED_view3d_depth_read_cached(depths, mval_i, depth_margin, depth_arr + i) == 0) &&
+ (i && (ED_view3d_depth_read_cached_seg(
+ depths, mval_i, mval_prev, depth_margin + 1, depth_arr + i) == 0))) {
interp_depth = true;
}
else {
@@ -1086,7 +1089,10 @@ static bool annotation_stroke_eraser_is_occluded(tGPsdata *p,
const int mval_i[2] = {x, y};
float mval_3d[3];
- if (ED_view3d_autodist_simple(p->region, mval_i, mval_3d, 0, NULL)) {
+ float p_depth;
+ if (ED_view3d_depth_read_cached(p->depths, mval_i, 0, &p_depth)) {
+ ED_view3d_depth_unproject_v3(p->region, mval_i, (double)p_depth, mval_3d);
+
const float depth_mval = ED_view3d_calc_depth_for_comparison(rv3d, mval_3d);
const float depth_pt = ED_view3d_calc_depth_for_comparison(rv3d, &pt->x);
@@ -1189,7 +1195,7 @@ static void annotation_stroke_eraser_dostroke(tGPsdata *p,
/* Second Pass: Remove any points that are tagged */
if (do_cull) {
BKE_gpencil_stroke_delete_tagged_points(
- p->gpd, gpf, gps, gps->next, GP_SPOINT_TAG, false, 0);
+ p->gpd, gpf, gps, gps->next, GP_SPOINT_TAG, false, false, 0);
}
}
}
@@ -1211,7 +1217,8 @@ static void annotation_stroke_doeraser(tGPsdata *p)
if (p->flags & GP_PAINTFLAG_V3D_ERASER_DEPTH) {
View3D *v3d = p->area->spacedata.first;
view3d_region_operator_needs_opengl(p->win, p->region);
- ED_view3d_depth_override(p->depsgraph, p->region, v3d, NULL, V3D_DEPTH_NO_GPENCIL, NULL);
+ ED_view3d_depth_override(
+ p->depsgraph, p->region, v3d, NULL, V3D_DEPTH_NO_GPENCIL, &p->depths);
}
}
@@ -1499,6 +1506,9 @@ static void annotation_session_cleanup(tGPsdata *p)
static void annotation_session_free(tGPsdata *p)
{
+ if (p->depths) {
+ ED_view3d_depths_free(p->depths);
+ }
MEM_freeN(p);
}
diff --git a/source/blender/editors/gpencil/gpencil_convert.c b/source/blender/editors/gpencil/gpencil_convert.c
index 406a7ac77fc..656fec565df 100644
--- a/source/blender/editors/gpencil/gpencil_convert.c
+++ b/source/blender/editors/gpencil/gpencil_convert.c
@@ -1834,7 +1834,7 @@ static int image_to_gpencil_exec(bContext *C, wmOperator *op)
/* Delete any selected point. */
LISTBASE_FOREACH_MUTABLE (bGPDstroke *, gps, &gpf->strokes) {
BKE_gpencil_stroke_delete_tagged_points(
- gpd, gpf, gps, gps->next, GP_SPOINT_SELECT, false, 0);
+ gpd, gpf, gps, gps->next, GP_SPOINT_SELECT, false, false, 0);
}
BKE_reportf(op->reports, RPT_INFO, "Object created");
diff --git a/source/blender/editors/gpencil/gpencil_data.c b/source/blender/editors/gpencil/gpencil_data.c
index a77d3bee025..db2104dfdf9 100644
--- a/source/blender/editors/gpencil/gpencil_data.c
+++ b/source/blender/editors/gpencil/gpencil_data.c
@@ -1321,78 +1321,102 @@ void GPENCIL_OT_layer_isolate(wmOperatorType *ot)
}
/* ********************** Merge Layer with the next layer **************************** */
+enum {
+ GP_LAYER_MERGE_ACTIVE = 0,
+ GP_LAYER_MERGE_ALL = 1,
+};
-static int gpencil_merge_layer_exec(bContext *C, wmOperator *op)
+static void apply_layer_settings(bGPDlayer *gpl)
{
- bGPdata *gpd = ED_gpencil_data_get_active(C);
- bGPDlayer *gpl_src = BKE_gpencil_layer_active_get(gpd);
- bGPDlayer *gpl_dst = gpl_src->prev;
+ /* Apply layer attributes. */
+ LISTBASE_FOREACH (bGPDframe *, gpf, &gpl->frames) {
+ LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) {
+ gps->fill_opacity_fac *= gpl->opacity;
+ gps->vert_color_fill[3] *= gpl->opacity;
+ for (int p = 0; p < gps->totpoints; p++) {
+ bGPDspoint *pt = &gps->points[p];
+ float factor = (((float)gps->thickness * pt->pressure) + (float)gpl->line_change) /
+ ((float)gps->thickness * pt->pressure);
+ pt->pressure *= factor;
+ pt->strength *= gpl->opacity;
- if (ELEM(NULL, gpd, gpl_dst, gpl_src)) {
- BKE_report(op->reports, RPT_ERROR, "No layers to merge");
- return OPERATOR_CANCELLED;
+ /* Layer transformation. */
+ mul_v3_m4v3(&pt->x, gpl->layer_mat, &pt->x);
+ zero_v3(gpl->location);
+ zero_v3(gpl->rotation);
+ copy_v3_fl(gpl->scale, 1.0f);
+ }
+ }
}
- /* Collect frames of gpl_dst in hash table to avoid O(n^2) lookups. */
- GHash *gh_frames_dst = BLI_ghash_int_new_ex(__func__, 64);
- LISTBASE_FOREACH (bGPDframe *, gpf_dst, &gpl_dst->frames) {
- BLI_ghash_insert(gh_frames_dst, POINTER_FROM_INT(gpf_dst->framenum), gpf_dst);
- }
+ gpl->line_change = 0;
+ gpl->opacity = 1.0f;
+ unit_m4(gpl->layer_mat);
+ invert_m4_m4(gpl->layer_invmat, gpl->layer_mat);
+}
- /* Read all frames from merge layer and add any missing in destination layer,
- * copying all previous strokes to keep the image equals.
- * Need to do it in a separated loop to avoid strokes accumulation. */
- LISTBASE_FOREACH (bGPDframe *, gpf_src, &gpl_src->frames) {
- /* Try to find frame in destination layer hash table. */
- bGPDframe *gpf_dst = BLI_ghash_lookup(gh_frames_dst, POINTER_FROM_INT(gpf_src->framenum));
- if (!gpf_dst) {
- gpf_dst = BKE_gpencil_layer_frame_get(gpl_dst, gpf_src->framenum, GP_GETFRAME_ADD_COPY);
- /* Use same frame type. */
- gpf_dst->key_type = gpf_src->key_type;
- BLI_ghash_insert(gh_frames_dst, POINTER_FROM_INT(gpf_src->framenum), gpf_dst);
- }
- }
+static int gpencil_merge_layer_exec(bContext *C, wmOperator *op)
+{
+ bGPdata *gpd = ED_gpencil_data_get_active(C);
+ bGPDlayer *gpl_active = BKE_gpencil_layer_active_get(gpd);
+ bGPDlayer *gpl_dst = gpl_active->prev;
+ const int mode = RNA_enum_get(op->ptr, "mode");
- /* Read all frames from merge layer and add strokes. */
- LISTBASE_FOREACH (bGPDframe *, gpf_src, &gpl_src->frames) {
- /* Try to find frame in destination layer hash table. */
- bGPDframe *gpf_dst = BLI_ghash_lookup(gh_frames_dst, POINTER_FROM_INT(gpf_src->framenum));
- /* Apply layer transformation. */
- LISTBASE_FOREACH (bGPDstroke *, gps_src, &gpf_src->strokes) {
- for (int p = 0; p < gps_src->totpoints; p++) {
- bGPDspoint *pt = &gps_src->points[p];
- mul_v3_m4v3(&pt->x, gpl_src->layer_mat, &pt->x);
- }
+ if (mode == GP_LAYER_MERGE_ACTIVE) {
+ if (ELEM(NULL, gpd, gpl_dst, gpl_active)) {
+ BKE_report(op->reports, RPT_ERROR, "No layers to merge");
+ return OPERATOR_CANCELLED;
}
-
- /* Add to tail all strokes. */
- if (gpf_dst) {
- BLI_movelisttolist(&gpf_dst->strokes, &gpf_src->strokes);
+ }
+ else {
+ if (ELEM(NULL, gpd, gpl_active)) {
+ BKE_report(op->reports, RPT_ERROR, "No layers to flatten");
+ return OPERATOR_CANCELLED;
}
}
- /* Add Masks to destination layer. */
- LISTBASE_FOREACH (bGPDlayer_Mask *, mask, &gpl_src->mask_layers) {
- /* Don't add merged layers or missing layer names. */
- if (!BKE_gpencil_layer_named_get(gpd, mask->name) || STREQ(mask->name, gpl_src->info) ||
- STREQ(mask->name, gpl_dst->info)) {
- continue;
+ if (mode == GP_LAYER_MERGE_ACTIVE) {
+ /* Apply destination layer attributes. */
+ apply_layer_settings(gpl_active);
+ ED_gpencil_layer_merge(gpd, gpl_active, gpl_dst, false);
+ }
+ else if (mode == GP_LAYER_MERGE_ALL) {
+ /* Apply layer attributes to all layers. */
+ LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
+ apply_layer_settings(gpl);
}
- if (!BKE_gpencil_layer_mask_named_get(gpl_dst, mask->name)) {
- bGPDlayer_Mask *mask_new = MEM_dupallocN(mask);
- BLI_addtail(&gpl_dst->mask_layers, mask_new);
- gpl_dst->act_mask++;
+ gpl_dst = gpl_active;
+ /* Merge layers on top of active layer. */
+ if (gpd->layers.last != gpl_dst) {
+ LISTBASE_FOREACH_BACKWARD_MUTABLE (bGPDlayer *, gpl, &gpd->layers) {
+ if (gpl == gpl_dst) {
+ break;
+ }
+ ED_gpencil_layer_merge(gpd, gpl, gpl->prev, false);
+ }
}
+ /* Merge layers below active layer. */
+ LISTBASE_FOREACH_BACKWARD_MUTABLE (bGPDlayer *, gpl, &gpd->layers) {
+ if (gpl == gpl_dst) {
+ continue;
+ }
+ ED_gpencil_layer_merge(gpd, gpl, gpl_dst, true);
+ }
+ /* Set general layers settings to default values. */
+ gpl_active->blend_mode = eGplBlendMode_Regular;
+ gpl_active->flag &= ~GP_LAYER_LOCKED;
+ gpl_active->flag &= ~GP_LAYER_HIDE;
+ gpl_active->flag |= GP_LAYER_USE_LIGHTS;
+ gpl_active->onion_flag |= GP_LAYER_ONIONSKIN;
+ }
+ else {
+ return OPERATOR_CANCELLED;
}
- /* Set destination layer as active. */
- BKE_gpencil_layer_active_set(gpd, gpl_dst);
-
- /* Now delete next layer */
- BKE_gpencil_layer_delete(gpd, gpl_src);
- BLI_ghash_free(gh_frames_dst, NULL, NULL);
- /* Reorder masking. */
- BKE_gpencil_layer_mask_sort(gpd, gpl_dst);
+ /* Clear any invalid mask. Some other layer could be using the merged layer. */
+ LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
+ BKE_gpencil_layer_mask_cleanup(gpd, gpl);
+ }
/* notifiers */
DEG_id_tag_update(&gpd->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
@@ -1404,10 +1428,16 @@ static int gpencil_merge_layer_exec(bContext *C, wmOperator *op)
void GPENCIL_OT_layer_merge(wmOperatorType *ot)
{
+ static const EnumPropertyItem merge_modes[] = {
+ {GP_LAYER_MERGE_ACTIVE, "ACTIVE", 0, "Active", "Combine active layer into the layer below"},
+ {GP_LAYER_MERGE_ALL, "ALL", 0, "All", "Combine all layers into the active layer"},
+ {0, NULL, 0, NULL, NULL},
+ };
+
/* identifiers */
ot->name = "Merge Down";
ot->idname = "GPENCIL_OT_layer_merge";
- ot->description = "Merge the current layer with the layer below";
+ ot->description = "Combine Layers";
/* callbacks */
ot->exec = gpencil_merge_layer_exec;
@@ -1415,6 +1445,8 @@ void GPENCIL_OT_layer_merge(wmOperatorType *ot)
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ ot->prop = RNA_def_enum(ot->srna, "mode", merge_modes, GP_LAYER_MERGE_ACTIVE, "Mode", "");
}
/* ********************** Change Layer ***************************** */
diff --git a/source/blender/editors/gpencil/gpencil_edit.c b/source/blender/editors/gpencil/gpencil_edit.c
index f6012883e1f..3fc08096ab5 100644
--- a/source/blender/editors/gpencil/gpencil_edit.c
+++ b/source/blender/editors/gpencil/gpencil_edit.c
@@ -2635,7 +2635,7 @@ static int gpencil_delete_selected_points(bContext *C)
else {
/* delete unwanted points by splitting stroke into several smaller ones */
BKE_gpencil_stroke_delete_tagged_points(
- gpd, gpf, gps, gps->next, GP_SPOINT_SELECT, false, 0);
+ gpd, gpf, gps, gps->next, GP_SPOINT_SELECT, false, false, 0);
}
changed = true;
@@ -4656,11 +4656,11 @@ static int gpencil_stroke_separate_exec(bContext *C, wmOperator *op)
/* delete selected points from destination stroke */
BKE_gpencil_stroke_delete_tagged_points(
- gpd_dst, gpf_dst, gps_dst, NULL, GP_SPOINT_SELECT, false, 0);
+ gpd_dst, gpf_dst, gps_dst, NULL, GP_SPOINT_SELECT, false, false, 0);
/* delete selected points from origin stroke */
BKE_gpencil_stroke_delete_tagged_points(
- gpd_src, gpf, gps, gps->next, GP_SPOINT_SELECT, false, 0);
+ gpd_src, gpf, gps, gps->next, GP_SPOINT_SELECT, false, false, 0);
}
}
/* selected strokes mode */
@@ -4839,11 +4839,11 @@ static int gpencil_stroke_split_exec(bContext *C, wmOperator *op)
/* delete selected points from destination stroke */
BKE_gpencil_stroke_delete_tagged_points(
- gpd, gpf, gps_dst, NULL, GP_SPOINT_SELECT, true, 0);
+ gpd, gpf, gps_dst, NULL, GP_SPOINT_SELECT, true, false, 0);
/* delete selected points from origin stroke */
BKE_gpencil_stroke_delete_tagged_points(
- gpd, gpf, gps, gps->next, GP_SPOINT_SELECT, false, 0);
+ gpd, gpf, gps, gps->next, GP_SPOINT_SELECT, false, false, 0);
}
}
}
@@ -5039,7 +5039,7 @@ static void gpencil_cutter_dissolve(bGPdata *gpd,
}
BKE_gpencil_stroke_delete_tagged_points(
- gpd, hit_layer->actframe, hit_stroke, gpsn, GP_SPOINT_TAG, false, 1);
+ gpd, hit_layer->actframe, hit_stroke, gpsn, GP_SPOINT_TAG, false, flat_caps, 1);
}
}
diff --git a/source/blender/editors/gpencil/gpencil_fill.c b/source/blender/editors/gpencil/gpencil_fill.c
index 1b69947b294..9860c75f290 100644
--- a/source/blender/editors/gpencil/gpencil_fill.c
+++ b/source/blender/editors/gpencil/gpencil_fill.c
@@ -127,6 +127,8 @@ typedef struct tGPDfill {
struct bGPDstroke *gps_mouse;
/** Pointer to report messages. */
struct ReportList *reports;
+ /** For operations that require occlusion testing. */
+ struct ViewDepths *depths;
/** flags */
short flag;
/** avoid too fast events */
@@ -1374,7 +1376,7 @@ static void gpencil_get_depth_array(tGPDfill *tgpf)
/* need to restore the original projection settings before packing up */
view3d_region_operator_needs_opengl(tgpf->win, tgpf->region);
ED_view3d_depth_override(
- tgpf->depsgraph, tgpf->region, tgpf->v3d, NULL, V3D_DEPTH_NO_GPENCIL, NULL);
+ tgpf->depsgraph, tgpf->region, tgpf->v3d, NULL, V3D_DEPTH_NO_GPENCIL, &tgpf->depths);
/* Since strokes are so fine, when using their depth we need a margin
* otherwise they might get missed. */
@@ -1385,6 +1387,7 @@ static void gpencil_get_depth_array(tGPDfill *tgpf)
int interp_depth = 0;
int found_depth = 0;
+ const ViewDepths *depths = tgpf->depths;
tgpf->depth_arr = MEM_mallocN(sizeof(float) * totpoints, "depth_points");
for (i = 0, ptc = tgpf->sbuffer; i < totpoints; i++, ptc++) {
@@ -1392,11 +1395,9 @@ static void gpencil_get_depth_array(tGPDfill *tgpf)
int mval_i[2];
round_v2i_v2fl(mval_i, &ptc->x);
- if ((ED_view3d_autodist_depth(tgpf->region, mval_i, depth_margin, tgpf->depth_arr + i) ==
- 0) &&
- (i &&
- (ED_view3d_autodist_depth_seg(
- tgpf->region, mval_i, mval_prev, depth_margin + 1, tgpf->depth_arr + i) == 0))) {
+ if ((ED_view3d_depth_read_cached(depths, mval_i, depth_margin, tgpf->depth_arr + i) == 0) &&
+ (i && (ED_view3d_depth_read_cached_seg(
+ depths, mval_i, mval_prev, depth_margin + 1, tgpf->depth_arr + i) == 0))) {
interp_depth = true;
}
else {
@@ -1771,6 +1772,11 @@ static void gpencil_fill_exit(bContext *C, wmOperator *op)
ED_region_draw_cb_exit(tgpf->region->type, tgpf->draw_handle_3d);
}
+ /* Remove depth buffer in cache. */
+ if (tgpf->depths) {
+ ED_view3d_depths_free(tgpf->depths);
+ }
+
/* finally, free memory used by temp data */
MEM_freeN(tgpf);
}
diff --git a/source/blender/editors/gpencil/gpencil_intern.h b/source/blender/editors/gpencil/gpencil_intern.h
index b6730cb123b..3f3fd4fff39 100644
--- a/source/blender/editors/gpencil/gpencil_intern.h
+++ b/source/blender/editors/gpencil/gpencil_intern.h
@@ -155,6 +155,8 @@ typedef struct tGPDprimitive {
struct Material *material;
/** current brush */
struct Brush *brush;
+ /** For operations that require occlusion testing. */
+ struct ViewDepths *depths;
/** Settings to pass to gp_points_to_xy(). */
GP_SpaceConversion gsc;
diff --git a/source/blender/editors/gpencil/gpencil_merge.c b/source/blender/editors/gpencil/gpencil_merge.c
index 259b2882589..925c2e1cd7f 100644
--- a/source/blender/editors/gpencil/gpencil_merge.c
+++ b/source/blender/editors/gpencil/gpencil_merge.c
@@ -182,7 +182,8 @@ static void gpencil_dissolve_points(bContext *C)
}
LISTBASE_FOREACH_MUTABLE (bGPDstroke *, gps, &gpf->strokes) {
- BKE_gpencil_stroke_delete_tagged_points(gpd, gpf, gps, gps->next, GP_SPOINT_TAG, false, 0);
+ BKE_gpencil_stroke_delete_tagged_points(
+ gpd, gpf, gps, gps->next, GP_SPOINT_TAG, false, false, 0);
}
}
CTX_DATA_END;
diff --git a/source/blender/editors/gpencil/gpencil_paint.c b/source/blender/editors/gpencil/gpencil_paint.c
index 3e9f22f25d3..f0118988559 100644
--- a/source/blender/editors/gpencil/gpencil_paint.c
+++ b/source/blender/editors/gpencil/gpencil_paint.c
@@ -161,6 +161,8 @@ typedef struct tGPsdata {
ARegion *region;
/** needed for GP_STROKE_2DSPACE. */
View2D *v2d;
+ /** For operations that require occlusion testing. */
+ ViewDepths *depths;
/** for using the camera rect within the 3d view. */
rctf *subrect;
rctf subrect_data;
@@ -1090,14 +1092,16 @@ static void gpencil_stroke_newfrombuffer(tGPsdata *p)
int found_depth = 0;
depth_arr = MEM_mallocN(sizeof(float) * gpd->runtime.sbuffer_used, "depth_points");
+
+ const ViewDepths *depths = p->depths;
int i;
for (i = 0, ptc = gpd->runtime.sbuffer; i < gpd->runtime.sbuffer_used; i++, ptc++, pt++) {
round_v2i_v2fl(mval_i, &ptc->x);
- if ((ED_view3d_autodist_depth(p->region, mval_i, depth_margin, depth_arr + i) == 0) &&
- (i && (ED_view3d_autodist_depth_seg(
- p->region, mval_i, mval_prev, depth_margin + 1, depth_arr + i) == 0))) {
+ if ((ED_view3d_depth_read_cached(depths, mval_i, depth_margin, depth_arr + i) == 0) &&
+ (i && (ED_view3d_depth_read_cached_seg(
+ depths, mval_i, mval_prev, depth_margin + 1, depth_arr + i) == 0))) {
interp_depth = true;
}
else {
@@ -1346,7 +1350,10 @@ static bool gpencil_stroke_eraser_is_occluded(
/* calculate difference matrix if parent object */
BKE_gpencil_layer_transform_matrix_get(p->depsgraph, obact, gpl, diff_mat);
- if (ED_view3d_autodist_simple(p->region, mval_i, mval_3d, 0, NULL)) {
+ float p_depth;
+ if (ED_view3d_depth_read_cached(p->depths, mval_i, 0, &p_depth)) {
+ ED_view3d_depth_unproject_v3(p->region, mval_i, (double)p_depth, mval_3d);
+
const float depth_mval = ED_view3d_calc_depth_for_comparison(rv3d, mval_3d);
mul_v3_m4v3(fpt, diff_mat, &pt->x);
@@ -1692,7 +1699,7 @@ static void gpencil_stroke_eraser_dostroke(tGPsdata *p,
}
BKE_gpencil_stroke_delete_tagged_points(
- p->gpd, gpf, gps, gps->next, GP_SPOINT_TAG, false, 0);
+ p->gpd, gpf, gps, gps->next, GP_SPOINT_TAG, false, false, 0);
}
gpencil_update_cache(p->gpd);
}
@@ -1733,7 +1740,7 @@ static void gpencil_stroke_doeraser(tGPsdata *p)
if ((gp_settings != NULL) && (gp_settings->flag & GP_BRUSH_OCCLUDE_ERASER)) {
View3D *v3d = p->area->spacedata.first;
view3d_region_operator_needs_opengl(p->win, p->region);
- ED_view3d_depth_override(p->depsgraph, p->region, v3d, NULL, V3D_DEPTH_NO_GPENCIL, NULL);
+ ED_view3d_depth_override(p->depsgraph, p->region, v3d, NULL, V3D_DEPTH_NO_GPENCIL, &p->depths);
}
/* loop over all layers too, since while it's easy to restrict editing to
@@ -2087,6 +2094,9 @@ static void gpencil_session_free(tGPsdata *p)
if (p->rng != NULL) {
BLI_rng_free(p->rng);
}
+ if (p->depths != NULL) {
+ ED_view3d_depths_free(p->depths);
+ }
MEM_freeN(p);
}
@@ -2267,8 +2277,9 @@ static void gpencil_paint_initstroke(tGPsdata *p,
static void gpencil_paint_strokeend(tGPsdata *p)
{
ToolSettings *ts = p->scene->toolsettings;
- /* for surface sketching, need to set the right OpenGL context stuff so that
- * the conversions will project the values correctly...
+ const bool is_eraser = (p->gpd->runtime.sbuffer_sflag & GP_STROKE_ERASER) != 0;
+ /* for surface sketching, need to set the right OpenGL context stuff so
+ * that the conversions will project the values correctly...
*/
if (gpencil_project_check(p)) {
View3D *v3d = p->area->spacedata.first;
@@ -2282,11 +2293,11 @@ static void gpencil_paint_strokeend(tGPsdata *p)
(ts->gpencil_v3d_align & GP_PROJECT_DEPTH_STROKE) ?
V3D_DEPTH_GPENCIL_ONLY :
V3D_DEPTH_NO_GPENCIL,
- NULL);
+ is_eraser ? NULL : &p->depths);
}
/* check if doing eraser or not */
- if ((p->gpd->runtime.sbuffer_sflag & GP_STROKE_ERASER) == 0) {
+ if (!is_eraser) {
/* transfer stroke to frame */
gpencil_stroke_newfrombuffer(p);
}
diff --git a/source/blender/editors/gpencil/gpencil_primitive.c b/source/blender/editors/gpencil/gpencil_primitive.c
index f8cfc130e35..7382aca9a87 100644
--- a/source/blender/editors/gpencil/gpencil_primitive.c
+++ b/source/blender/editors/gpencil/gpencil_primitive.c
@@ -795,15 +795,16 @@ static void gpencil_primitive_update_strokes(bContext *C, tGPDprimitive *tgpi)
(ts->gpencil_v3d_align & GP_PROJECT_DEPTH_STROKE) ?
V3D_DEPTH_GPENCIL_ONLY :
V3D_DEPTH_NO_GPENCIL,
- NULL);
+ &tgpi->depths);
depth_arr = MEM_mallocN(sizeof(float) * gps->totpoints, "depth_points");
+ const ViewDepths *depths = tgpi->depths;
tGPspoint *ptc = &points2D[0];
for (int i = 0; i < gps->totpoints; i++, ptc++) {
round_v2i_v2fl(mval_i, &ptc->x);
- if ((ED_view3d_autodist_depth(tgpi->region, mval_i, depth_margin, depth_arr + i) == 0) &&
- (i && (ED_view3d_autodist_depth_seg(
- tgpi->region, mval_i, mval_prev, depth_margin + 1, depth_arr + i) == 0))) {
+ if ((ED_view3d_depth_read_cached(depths, mval_i, depth_margin, depth_arr + i) == 0) &&
+ (i && (ED_view3d_depth_read_cached_seg(
+ depths, mval_i, mval_prev, depth_margin + 1, depth_arr + i) == 0))) {
interp_depth = true;
}
else {
@@ -1154,6 +1155,11 @@ static void gpencil_primitive_exit(bContext *C, wmOperator *op)
BLI_rng_free(tgpi->rng);
}
+ /* Remove depth buffer in cache. */
+ if (tgpi->depths) {
+ ED_view3d_depths_free(tgpi->depths);
+ }
+
MEM_freeN(tgpi);
}
diff --git a/source/blender/editors/gpencil/gpencil_utils.c b/source/blender/editors/gpencil/gpencil_utils.c
index d3640c6eebd..86df452f49a 100644
--- a/source/blender/editors/gpencil/gpencil_utils.c
+++ b/source/blender/editors/gpencil/gpencil_utils.c
@@ -979,7 +979,7 @@ bool gpencil_point_xy_to_3d(const GP_SpaceConversion *gsc,
* to 3D coordinates.
*
* \param point2D: The screen-space 2D point data to convert.
- * \param depth: Depth array (via #ED_view3d_autodist_depth()).
+ * \param depth: Depth array (via #ED_view3d_depth_read_cached()).
* \param r_out: The resulting 2D point data.
*/
void gpencil_stroke_convertcoords_tpoint(Scene *scene,
@@ -3372,7 +3372,7 @@ bGPDstroke *ED_gpencil_stroke_join_and_trim(
}
/* Remove tagged points to trim stroke. */
gps_final = BKE_gpencil_stroke_delete_tagged_points(
- gpd, gpf, gps_dst, gps_dst->next, GP_SPOINT_TAG, false, 0);
+ gpd, gpf, gps_dst, gps_dst->next, GP_SPOINT_TAG, false, false, 0);
}
/* Join both strokes. */
@@ -3415,3 +3415,71 @@ void ED_gpencil_stroke_close_by_distance(bGPDstroke *gps, const float threshold)
BKE_gpencil_stroke_close(gps);
}
}
+
+/* Merge two layers. */
+void ED_gpencil_layer_merge(bGPdata *gpd,
+ bGPDlayer *gpl_src,
+ bGPDlayer *gpl_dst,
+ const bool reverse)
+{
+ /* Collect frames of gpl_dst in hash table to avoid O(n^2) lookups. */
+ GHash *gh_frames_dst = BLI_ghash_int_new_ex(__func__, 64);
+ LISTBASE_FOREACH (bGPDframe *, gpf_dst, &gpl_dst->frames) {
+ BLI_ghash_insert(gh_frames_dst, POINTER_FROM_INT(gpf_dst->framenum), gpf_dst);
+ }
+
+ /* Read all frames from merge layer and add any missing in destination layer,
+ * copying all previous strokes to keep the image equals.
+ * Need to do it in a separated loop to avoid strokes accumulation. */
+ LISTBASE_FOREACH (bGPDframe *, gpf_src, &gpl_src->frames) {
+ /* Try to find frame in destination layer hash table. */
+ bGPDframe *gpf_dst = BLI_ghash_lookup(gh_frames_dst, POINTER_FROM_INT(gpf_src->framenum));
+ if (!gpf_dst) {
+ gpf_dst = BKE_gpencil_layer_frame_get(gpl_dst, gpf_src->framenum, GP_GETFRAME_ADD_COPY);
+ /* Use same frame type. */
+ gpf_dst->key_type = gpf_src->key_type;
+ BLI_ghash_insert(gh_frames_dst, POINTER_FROM_INT(gpf_src->framenum), gpf_dst);
+ }
+ }
+
+ /* Read all frames from merge layer and add strokes. */
+ LISTBASE_FOREACH (bGPDframe *, gpf_src, &gpl_src->frames) {
+ /* Try to find frame in destination layer hash table. */
+ bGPDframe *gpf_dst = BLI_ghash_lookup(gh_frames_dst, POINTER_FROM_INT(gpf_src->framenum));
+ /* Add to tail all strokes. */
+ if (gpf_dst) {
+ if (reverse) {
+ BLI_movelisttolist_reverse(&gpf_dst->strokes, &gpf_src->strokes);
+ }
+ else {
+ BLI_movelisttolist(&gpf_dst->strokes, &gpf_src->strokes);
+ }
+ }
+ }
+
+ /* Add Masks to destination layer. */
+ LISTBASE_FOREACH (bGPDlayer_Mask *, mask, &gpl_src->mask_layers) {
+ /* Don't add merged layers or missing layer names. */
+ if (!BKE_gpencil_layer_named_get(gpd, mask->name) || STREQ(mask->name, gpl_src->info) ||
+ STREQ(mask->name, gpl_dst->info)) {
+ continue;
+ }
+ if (!BKE_gpencil_layer_mask_named_get(gpl_dst, mask->name)) {
+ bGPDlayer_Mask *mask_new = MEM_dupallocN(mask);
+ BLI_addtail(&gpl_dst->mask_layers, mask_new);
+ gpl_dst->act_mask++;
+ }
+ }
+
+ /* Set destination layer as active. */
+ BKE_gpencil_layer_active_set(gpd, gpl_dst);
+
+ /* Now delete merged layer. */
+ BKE_gpencil_layer_delete(gpd, gpl_src);
+ BLI_ghash_free(gh_frames_dst, NULL, NULL);
+
+ /* Reorder masking. */
+ if (gpl_dst->mask_layers.first) {
+ BKE_gpencil_layer_mask_sort(gpd, gpl_dst);
+ }
+}
diff --git a/source/blender/editors/gpencil/gpencil_vertex_ops.c b/source/blender/editors/gpencil/gpencil_vertex_ops.c
index 5c3a7cf9e6f..891bd3ca5ec 100644
--- a/source/blender/editors/gpencil/gpencil_vertex_ops.c
+++ b/source/blender/editors/gpencil/gpencil_vertex_ops.c
@@ -54,7 +54,7 @@
static const EnumPropertyItem gpencil_modesEnumPropertyItem_mode[] = {
{GPPAINT_MODE_STROKE, "STROKE", 0, "Stroke", ""},
{GPPAINT_MODE_FILL, "FILL", 0, "Fill", ""},
- {GPPAINT_MODE_BOTH, "BOTH", 0, "Stroke and Fill", ""},
+ {GPPAINT_MODE_BOTH, "BOTH", 0, "Stroke & Fill", ""},
{0, NULL, 0, NULL, NULL},
};
@@ -1142,7 +1142,7 @@ void GPENCIL_OT_stroke_reset_vertex_color(wmOperatorType *ot)
static EnumPropertyItem mode_types_items[] = {
{GPPAINT_MODE_STROKE, "STROKE", 0, "Stroke", "Reset Vertex Color to Stroke only"},
{GPPAINT_MODE_FILL, "FILL", 0, "Fill", "Reset Vertex Color to Fill only"},
- {GPPAINT_MODE_BOTH, "BOTH", 0, "Stroke and Fill", "Reset Vertex Color to Stroke and Fill"},
+ {GPPAINT_MODE_BOTH, "BOTH", 0, "Stroke & Fill", "Reset Vertex Color to Stroke and Fill"},
{0, NULL, 0, NULL, NULL},
};
diff --git a/source/blender/editors/include/ED_clip.h b/source/blender/editors/include/ED_clip.h
index 21d8a28e2c9..4fa78eddec4 100644
--- a/source/blender/editors/include/ED_clip.h
+++ b/source/blender/editors/include/ED_clip.h
@@ -65,7 +65,7 @@ struct ImBuf *ED_space_clip_get_stable_buffer(struct SpaceClip *sc,
float *angle);
bool ED_space_clip_get_position(struct SpaceClip *sc,
- struct ARegion *ar,
+ struct ARegion *region,
int mval[2],
float fpos[2]);
bool ED_space_clip_color_sample(struct SpaceClip *sc,
diff --git a/source/blender/editors/include/ED_gpencil.h b/source/blender/editors/include/ED_gpencil.h
index c760b661373..1cf15ce3a48 100644
--- a/source/blender/editors/include/ED_gpencil.h
+++ b/source/blender/editors/include/ED_gpencil.h
@@ -205,6 +205,11 @@ void ED_gpencil_select_frame(struct bGPDlayer *gpl, int selx, short select_mode)
bool ED_gpencil_layer_frames_delete(struct bGPDlayer *gpl);
void ED_gpencil_layer_frames_duplicate(struct bGPDlayer *gpl);
+void ED_gpencil_layer_merge(struct bGPdata *gpd,
+ struct bGPDlayer *gpl_src,
+ struct bGPDlayer *gpl_dst,
+ const bool reverse);
+
void ED_gpencil_layer_frames_keytype_set(struct bGPDlayer *gpl, short type);
void ED_gpencil_layer_snap_frames(struct bGPDlayer *gpl, struct Scene *scene, short mode);
diff --git a/source/blender/editors/include/ED_screen.h b/source/blender/editors/include/ED_screen.h
index ef3ff7874df..eee119c0712 100644
--- a/source/blender/editors/include/ED_screen.h
+++ b/source/blender/editors/include/ED_screen.h
@@ -31,6 +31,8 @@
#include "DNA_object_enums.h"
+#include "WM_types.h"
+
#include "BLI_compiler_attrs.h"
#ifdef __cplusplus
@@ -380,7 +382,7 @@ struct bUserMenu *ED_screen_user_menu_ensure(struct bContext *C);
struct bUserMenuItem_Op *ED_screen_user_menu_item_find_operator(struct ListBase *lb,
const struct wmOperatorType *ot,
struct IDProperty *prop,
- short opcontext);
+ wmOperatorCallContext opcontext);
struct bUserMenuItem_Menu *ED_screen_user_menu_item_find_menu(struct ListBase *lb,
const struct MenuType *mt);
struct bUserMenuItem_Prop *ED_screen_user_menu_item_find_prop(struct ListBase *lb,
@@ -392,7 +394,7 @@ void ED_screen_user_menu_item_add_operator(struct ListBase *lb,
const char *ui_name,
const struct wmOperatorType *ot,
const struct IDProperty *prop,
- short opcontext);
+ wmOperatorCallContext opcontext);
void ED_screen_user_menu_item_add_menu(struct ListBase *lb,
const char *ui_name,
const struct MenuType *mt);
diff --git a/source/blender/editors/include/ED_view3d.h b/source/blender/editors/include/ED_view3d.h
index 8e19628ec87..008ad5b3203 100644
--- a/source/blender/editors/include/ED_view3d.h
+++ b/source/blender/editors/include/ED_view3d.h
@@ -588,8 +588,6 @@ float ED_view3d_radius_to_dist(const struct View3D *v3d,
const bool use_aspect,
const float radius);
-void imm_drawcircball(const float cent[3], float rad, const float tmat[4][4], unsigned int pos);
-
/* Back-buffer select and draw support. */
void ED_view3d_backbuf_depth_validate(struct ViewContext *vc);
int ED_view3d_backbuf_sample_size_clamp(struct ARegion *region, const float dist);
@@ -609,12 +607,8 @@ bool ED_view3d_autodist_simple(struct ARegion *region,
float mouse_worldloc[3],
int margin,
const float *force_depth);
-bool ED_view3d_autodist_depth(struct ARegion *region, const int mval[2], int margin, float *depth);
-bool ED_view3d_autodist_depth_seg(struct ARegion *region,
- const int mval_sta[2],
- const int mval_end[2],
- int margin,
- float *depth);
+bool ED_view3d_depth_read_cached_seg(
+ const ViewDepths *vd, const int mval_sta[2], const int mval_end[2], int margin, float *depth);
/* select */
#define MAXPICKELEMS 2500
diff --git a/source/blender/editors/include/UI_interface.h b/source/blender/editors/include/UI_interface.h
index 1ed10f37de3..d5d45068828 100644
--- a/source/blender/editors/include/UI_interface.h
+++ b/source/blender/editors/include/UI_interface.h
@@ -27,6 +27,7 @@
#include "BLI_sys_types.h" /* size_t */
#include "BLI_utildefines.h"
#include "UI_interface_icons.h"
+#include "WM_types.h"
#ifdef __cplusplus
extern "C" {
@@ -244,10 +245,10 @@ enum {
};
/* Default font size for normal text. */
-#define UI_DEFAULT_TEXT_POINTS 11
+#define UI_DEFAULT_TEXT_POINTS 11.0f
/* Larger size used for title text. */
-#define UI_DEFAULT_TITLE_POINTS 11
+#define UI_DEFAULT_TITLE_POINTS 11.0f
#define UI_PANEL_WIDTH 340
#define UI_COMPACT_PANEL_WIDTH 160
@@ -399,9 +400,8 @@ typedef enum {
/** Resize handle (resize uilist). */
UI_BTYPE_GRIP = 57 << 9,
UI_BTYPE_DECORATOR = 58 << 9,
- UI_BTYPE_DATASETROW = 59 << 9,
/* An item in a tree view. Parent items may be collapsible. */
- UI_BTYPE_TREEROW = 60 << 9,
+ UI_BTYPE_TREEROW = 59 << 9,
} eButType;
#define BUTTYPE (63 << 9)
@@ -691,7 +691,7 @@ void UI_popup_block_ex(struct bContext *C,
void uiPupBlockOperator(struct bContext *C,
uiBlockCreateFunc func,
struct wmOperator *op,
- int opcontext);
+ wmOperatorCallContext opcontext);
#endif
void UI_popup_block_close(struct bContext *C, struct wmWindow *win, uiBlock *block);
@@ -731,8 +731,8 @@ bool UI_block_is_search_only(const uiBlock *block);
void UI_block_set_search_only(uiBlock *block, bool search_only);
void UI_block_free(const struct bContext *C, uiBlock *block);
-void UI_blocklist_free(const struct bContext *C, struct ListBase *lb);
-void UI_blocklist_free_inactive(const struct bContext *C, struct ListBase *lb);
+void UI_blocklist_free(const struct bContext *C, struct ARegion *region);
+void UI_blocklist_free_inactive(const struct bContext *C, struct ARegion *region);
void UI_screen_free_active_but(const struct bContext *C, struct bScreen *screen);
void UI_block_region_set(uiBlock *block, struct ARegion *region);
@@ -1003,7 +1003,7 @@ uiBut *uiDefButR_prop(uiBlock *block,
uiBut *uiDefButO(uiBlock *block,
int type,
const char *opname,
- int opcontext,
+ wmOperatorCallContext opcontext,
const char *str,
int x,
int y,
@@ -1013,7 +1013,7 @@ uiBut *uiDefButO(uiBlock *block,
uiBut *uiDefButO_ptr(uiBlock *block,
int type,
struct wmOperatorType *ot,
- int opcontext,
+ wmOperatorCallContext opcontext,
const char *str,
int x,
int y,
@@ -1186,7 +1186,7 @@ uiBut *uiDefIconButR_prop(uiBlock *block,
uiBut *uiDefIconButO(uiBlock *block,
int type,
const char *opname,
- int opcontext,
+ wmOperatorCallContext opcontext,
int icon,
int x,
int y,
@@ -1196,7 +1196,7 @@ uiBut *uiDefIconButO(uiBlock *block,
uiBut *uiDefIconButO_ptr(uiBlock *block,
int type,
struct wmOperatorType *ot,
- int opcontext,
+ wmOperatorCallContext opcontext,
int icon,
int x,
int y,
@@ -1382,7 +1382,7 @@ uiBut *uiDefIconTextButR_prop(uiBlock *block,
uiBut *uiDefIconTextButO(uiBlock *block,
int type,
const char *opname,
- int opcontext,
+ wmOperatorCallContext opcontext,
int icon,
const char *str,
int x,
@@ -1393,7 +1393,7 @@ uiBut *uiDefIconTextButO(uiBlock *block,
uiBut *uiDefIconTextButO_ptr(uiBlock *block,
int type,
struct wmOperatorType *ot,
- int opcontext,
+ wmOperatorCallContext opcontext,
int icon,
const char *str,
int x,
@@ -1675,11 +1675,7 @@ int UI_searchbox_size_x(void);
int UI_search_items_find_index(uiSearchItems *items, const char *name);
void UI_but_hint_drawstr_set(uiBut *but, const char *string);
-void UI_but_datasetrow_indentation_set(uiBut *but, int indentation);
-void UI_but_datasetrow_component_set(uiBut *but, uint8_t geometry_component_type);
-void UI_but_datasetrow_domain_set(uiBut *but, uint8_t attribute_domain);
-uint8_t UI_but_datasetrow_component_get(uiBut *but);
-uint8_t UI_but_datasetrow_domain_get(uiBut *but);
+
void UI_but_treerow_indentation_set(uiBut *but, int indentation);
void UI_but_node_link_set(uiBut *but, struct bNodeSocket *socket, const float draw_color[4]);
@@ -1724,7 +1720,7 @@ void UI_but_func_pushed_state_set(uiBut *but, uiButPushedStateFunc func, const v
struct PointerRNA *UI_but_extra_operator_icon_add(uiBut *but,
const char *opname,
- short opcontext,
+ wmOperatorCallContext opcontext,
int icon);
struct wmOperatorType *UI_but_extra_operator_icon_optype_get(struct uiButExtraOpIcon *extra_icon);
struct PointerRNA *UI_but_extra_operator_icon_opptr_get(struct uiButExtraOpIcon *extra_icon);
@@ -1966,7 +1962,7 @@ void UI_paneltype_draw(struct bContext *C, struct PanelType *pt, struct uiLayout
/* Only for convenience. */
void uiLayoutSetContextFromBut(uiLayout *layout, uiBut *but);
-void uiLayoutSetOperatorContext(uiLayout *layout, int opcontext);
+void uiLayoutSetOperatorContext(uiLayout *layout, wmOperatorCallContext opcontext);
void uiLayoutSetActive(uiLayout *layout, bool active);
void uiLayoutSetActiveDefault(uiLayout *layout, bool active_default);
void uiLayoutSetActivateInit(uiLayout *layout, bool activate_init);
@@ -2394,7 +2390,7 @@ void uiItemFullO_ptr(uiLayout *layout,
const char *name,
int icon,
struct IDProperty *properties,
- int context,
+ wmOperatorCallContext context,
int flag,
struct PointerRNA *r_opptr);
void uiItemFullO(uiLayout *layout,
@@ -2402,7 +2398,7 @@ void uiItemFullO(uiLayout *layout,
const char *name,
int icon,
struct IDProperty *properties,
- int context,
+ wmOperatorCallContext context,
int flag,
struct PointerRNA *r_opptr);
void uiItemFullOMenuHold_ptr(uiLayout *layout,
@@ -2410,7 +2406,7 @@ void uiItemFullOMenuHold_ptr(uiLayout *layout,
const char *name,
int icon,
struct IDProperty *properties,
- int context,
+ wmOperatorCallContext context,
int flag,
const char *menu_id, /* extra menu arg. */
struct PointerRNA *r_opptr);
@@ -2490,14 +2486,14 @@ void uiItemsFullEnumO(uiLayout *layout,
const char *opname,
const char *propname,
struct IDProperty *properties,
- int context,
+ wmOperatorCallContext context,
int flag);
void uiItemsFullEnumO_items(uiLayout *layout,
struct wmOperatorType *ot,
struct PointerRNA ptr,
struct PropertyRNA *prop,
struct IDProperty *properties,
- int context,
+ wmOperatorCallContext context,
int flag,
const struct EnumPropertyItem *item_array,
int totitem);
diff --git a/source/blender/editors/include/UI_tree_view.hh b/source/blender/editors/include/UI_tree_view.hh
index 0d18eedeac9..8caf17741a7 100644
--- a/source/blender/editors/include/UI_tree_view.hh
+++ b/source/blender/editors/include/UI_tree_view.hh
@@ -217,15 +217,11 @@ class AbstractTreeViewItem : public TreeViewItemContainer {
friend class TreeViewLayoutBuilder;
public:
- using IsActiveFn = std::function<bool()>;
-
private:
bool is_open_ = false;
bool is_active_ = false;
bool is_renaming_ = false;
- IsActiveFn is_active_fn_;
-
protected:
/** This label is used for identifying an item (together with its parent's labels). */
std::string label_{};
@@ -239,11 +235,6 @@ class AbstractTreeViewItem : public TreeViewItemContainer {
virtual void build_context_menu(bContext &C, uiLayout &column) const;
virtual void on_activate();
- /**
- * Set a custom callback to check if this item should be active. There's a version without
- * arguments for checking if the item is currently in an active state.
- */
- virtual void is_active(IsActiveFn is_active_fn);
/**
* Queries if the tree-view item supports renaming in principle. Renaming may still fail, e.g. if
@@ -329,6 +320,17 @@ class AbstractTreeViewItem : public TreeViewItemContainer {
*/
void activate();
+ /**
+ * If the result is not empty, it controls whether the item should be active or not,
+ * usually depending on the data that the view represents.
+ */
+ virtual std::optional<bool> should_be_active() const;
+
+ /**
+ * Return whether the item can be collapsed. Used to disable collapsing for items with children.
+ */
+ virtual bool supports_collapsing() const;
+
private:
static void rename_button_fn(bContext *, void *, char *);
static AbstractTreeViewItem *find_tree_item_from_rename_button(const uiBut &but);
@@ -416,6 +418,7 @@ class AbstractTreeViewItemDropController {
*/
class BasicTreeViewItem : public AbstractTreeViewItem {
public:
+ using IsActiveFn = std::function<bool()>;
using ActivateFn = std::function<void(BasicTreeViewItem &new_active)>;
BIFIconID icon;
@@ -423,7 +426,11 @@ class BasicTreeViewItem : public AbstractTreeViewItem {
void build_row(uiLayout &row) override;
void add_label(uiLayout &layout, StringRefNull label_override = "");
- void on_activate(ActivateFn fn);
+ void set_on_activate_fn(ActivateFn fn);
+ /**
+ * Set a custom callback to check if this item should be active.
+ */
+ void set_is_active_fn(IsActiveFn fn);
protected:
/**
@@ -433,9 +440,12 @@ class BasicTreeViewItem : public AbstractTreeViewItem {
*/
ActivateFn activate_fn_;
+ IsActiveFn is_active_fn_;
+
private:
static void tree_row_click_fn(struct bContext *C, void *arg1, void *arg2);
+ std::optional<bool> should_be_active() const override;
void on_activate() override;
};
diff --git a/source/blender/editors/interface/CMakeLists.txt b/source/blender/editors/interface/CMakeLists.txt
index 84172c7efce..bc3075f9de8 100644
--- a/source/blender/editors/interface/CMakeLists.txt
+++ b/source/blender/editors/interface/CMakeLists.txt
@@ -66,14 +66,14 @@ set(SRC
interface_region_menu_popup.c
interface_region_popover.c
interface_region_popup.c
- interface_region_search.c
+ interface_region_search.cc
interface_region_tooltip.c
interface_regions.c
interface_style.c
interface_template_asset_view.cc
interface_template_list.cc
interface_template_attribute_search.cc
- interface_template_search_menu.c
+ interface_template_search_menu.cc
interface_template_search_operator.c
interface_templates.c
interface_undo.c
diff --git a/source/blender/editors/interface/interface.c b/source/blender/editors/interface/interface.c
index 6ad0ef9de18..55fab04e9a4 100644
--- a/source/blender/editors/interface/interface.c
+++ b/source/blender/editors/interface/interface.c
@@ -37,6 +37,7 @@
#include "DNA_workspace_types.h"
#include "BLI_alloca.h"
+#include "BLI_ghash.h"
#include "BLI_listbase.h"
#include "BLI_math.h"
#include "BLI_rect.h"
@@ -1638,7 +1639,7 @@ typedef enum PredefinedExtraOpIconType {
static PointerRNA *ui_but_extra_operator_icon_add_ptr(uiBut *but,
wmOperatorType *optype,
- short opcontext,
+ wmOperatorCallContext opcontext,
int icon)
{
uiButExtraOpIcon *extra_op_icon = MEM_mallocN(sizeof(*extra_op_icon), __func__);
@@ -1678,7 +1679,7 @@ void ui_but_extra_operator_icons_free(uiBut *but)
PointerRNA *UI_but_extra_operator_icon_add(uiBut *but,
const char *opname,
- short opcontext,
+ wmOperatorCallContext opcontext,
int icon)
{
wmOperatorType *optype = WM_operatortype_find(opname, false);
@@ -1881,7 +1882,7 @@ bool ui_but_context_poll_operator_ex(bContext *C,
bool ui_but_context_poll_operator(bContext *C, wmOperatorType *ot, const uiBut *but)
{
- const int opcontext = but ? but->opcontext : WM_OP_INVOKE_DEFAULT;
+ const wmOperatorCallContext opcontext = but ? but->opcontext : WM_OP_INVOKE_DEFAULT;
return ui_but_context_poll_operator_ex(
C, but, &(wmOperatorCallParams){.optype = ot, .opcontext = opcontext});
}
@@ -1993,23 +1994,9 @@ void UI_block_end(const bContext *C, uiBlock *block)
/* ************** BLOCK DRAWING FUNCTION ************* */
-void ui_fontscale(short *points, float aspect)
+void ui_fontscale(float *points, float aspect)
{
- if (aspect < 0.9f || aspect > 1.1f) {
- float pointsf = *points;
-
- /* For some reason scaling fonts goes too fast compared to widget size. */
- /* XXX(ton): not true anymore? */
- // aspect = sqrt(aspect);
- pointsf /= aspect;
-
- if (aspect > 1.0f) {
- *points = ceilf(pointsf);
- }
- else {
- *points = floorf(pointsf);
- }
- }
+ *points /= aspect;
}
/* Project button or block (but==NULL) to pixels in region-space. */
@@ -3535,22 +3522,35 @@ void UI_blocklist_draw(const bContext *C, const ListBase *lb)
}
/* can be called with C==NULL */
-void UI_blocklist_free(const bContext *C, ListBase *lb)
+void UI_blocklist_free(const bContext *C, ARegion *region)
{
+ ListBase *lb = &region->uiblocks;
uiBlock *block;
while ((block = BLI_pophead(lb))) {
UI_block_free(C, block);
}
+ if (region->runtime.block_name_map != NULL) {
+ BLI_ghash_free(region->runtime.block_name_map, NULL, NULL);
+ region->runtime.block_name_map = NULL;
+ }
}
-void UI_blocklist_free_inactive(const bContext *C, ListBase *lb)
+void UI_blocklist_free_inactive(const bContext *C, ARegion *region)
{
+ ListBase *lb = &region->uiblocks;
+
LISTBASE_FOREACH_MUTABLE (uiBlock *, block, lb) {
if (!block->handle) {
if (block->active) {
block->active = false;
}
else {
+ if (region->runtime.block_name_map != NULL) {
+ uiBlock *b = BLI_ghash_lookup(region->runtime.block_name_map, block->name);
+ if (b == block) {
+ BLI_ghash_remove(region->runtime.block_name_map, b->name, NULL, NULL);
+ }
+ }
BLI_remlink(lb, block);
UI_block_free(C, block);
}
@@ -3566,7 +3566,10 @@ void UI_block_region_set(uiBlock *block, ARegion *region)
/* each listbase only has one block with this name, free block
* if is already there so it can be rebuilt from scratch */
if (lb) {
- oldblock = BLI_findstring(lb, block->name, offsetof(uiBlock, name));
+ if (region->runtime.block_name_map == NULL) {
+ region->runtime.block_name_map = BLI_ghash_str_new(__func__);
+ }
+ oldblock = (uiBlock *)BLI_ghash_lookup(region->runtime.block_name_map, block->name);
if (oldblock) {
oldblock->active = false;
@@ -3576,6 +3579,7 @@ void UI_block_region_set(uiBlock *block, ARegion *region)
/* at the beginning of the list! for dynamical menus/blocks */
BLI_addhead(lb, block);
+ BLI_ghash_reinsert(region->runtime.block_name_map, block->name, block, NULL, NULL);
}
block->oldblock = oldblock;
@@ -3991,10 +3995,6 @@ static void ui_but_alloc_info(const eButType type,
alloc_size = sizeof(uiButCurveProfile);
alloc_str = "uiButCurveProfile";
break;
- case UI_BTYPE_DATASETROW:
- alloc_size = sizeof(uiButDatasetRow);
- alloc_str = "uiButDatasetRow";
- break;
case UI_BTYPE_TREEROW:
alloc_size = sizeof(uiButTreeRow);
alloc_str = "uiButTreeRow";
@@ -4197,7 +4197,6 @@ static uiBut *ui_def_but(uiBlock *block,
UI_BTYPE_BLOCK,
UI_BTYPE_BUT_MENU,
UI_BTYPE_SEARCH_MENU,
- UI_BTYPE_DATASETROW,
UI_BTYPE_TREEROW,
UI_BTYPE_POPOVER)) {
but->drawflag |= (UI_BUT_TEXT_LEFT | UI_BUT_ICON_LEFT);
@@ -4755,7 +4754,7 @@ static uiBut *ui_def_but_rna_propname(uiBlock *block,
static uiBut *ui_def_but_operator_ptr(uiBlock *block,
int type,
wmOperatorType *ot,
- int opcontext,
+ wmOperatorCallContext opcontext,
const char *str,
int x,
int y,
@@ -5293,7 +5292,7 @@ uiBut *uiDefButR_prop(uiBlock *block,
uiBut *uiDefButO_ptr(uiBlock *block,
int type,
wmOperatorType *ot,
- int opcontext,
+ wmOperatorCallContext opcontext,
const char *str,
int x,
int y,
@@ -5308,7 +5307,7 @@ uiBut *uiDefButO_ptr(uiBlock *block,
uiBut *uiDefButO(uiBlock *block,
int type,
const char *opname,
- int opcontext,
+ wmOperatorCallContext opcontext,
const char *str,
int x,
int y,
@@ -5676,7 +5675,7 @@ uiBut *uiDefIconButR_prop(uiBlock *block,
uiBut *uiDefIconButO_ptr(uiBlock *block,
int type,
wmOperatorType *ot,
- int opcontext,
+ wmOperatorCallContext opcontext,
int icon,
int x,
int y,
@@ -5691,7 +5690,7 @@ uiBut *uiDefIconButO_ptr(uiBlock *block,
uiBut *uiDefIconButO(uiBlock *block,
int type,
const char *opname,
- int opcontext,
+ wmOperatorCallContext opcontext,
int icon,
int x,
int y,
@@ -6079,7 +6078,7 @@ uiBut *uiDefIconTextButR_prop(uiBlock *block,
uiBut *uiDefIconTextButO_ptr(uiBlock *block,
int type,
wmOperatorType *ot,
- int opcontext,
+ wmOperatorCallContext opcontext,
int icon,
const char *str,
int x,
@@ -6096,7 +6095,7 @@ uiBut *uiDefIconTextButO_ptr(uiBlock *block,
uiBut *uiDefIconTextButO(uiBlock *block,
int type,
const char *opname,
- int opcontext,
+ wmOperatorCallContext opcontext,
int icon,
const char *str,
int x,
@@ -6938,15 +6937,6 @@ uiBut *uiDefSearchButO_ptr(uiBlock *block,
return but;
}
-void UI_but_datasetrow_indentation_set(uiBut *but, int indentation)
-{
- uiButDatasetRow *but_dataset = (uiButDatasetRow *)but;
- BLI_assert(but->type == UI_BTYPE_DATASETROW);
-
- but_dataset->indentation = indentation;
- BLI_assert(indentation >= 0);
-}
-
void UI_but_treerow_indentation_set(uiBut *but, int indentation)
{
uiButTreeRow *but_row = (uiButTreeRow *)but;
@@ -6964,38 +6954,6 @@ void UI_but_hint_drawstr_set(uiBut *but, const char *string)
ui_but_add_shortcut(but, string, false);
}
-void UI_but_datasetrow_component_set(uiBut *but, uint8_t geometry_component_type)
-{
- uiButDatasetRow *but_dataset_row = (uiButDatasetRow *)but;
- BLI_assert(but->type == UI_BTYPE_DATASETROW);
-
- but_dataset_row->geometry_component_type = geometry_component_type;
-}
-
-void UI_but_datasetrow_domain_set(uiBut *but, uint8_t attribute_domain)
-{
- uiButDatasetRow *but_dataset_row = (uiButDatasetRow *)but;
- BLI_assert(but->type == UI_BTYPE_DATASETROW);
-
- but_dataset_row->attribute_domain = attribute_domain;
-}
-
-uint8_t UI_but_datasetrow_component_get(uiBut *but)
-{
- uiButDatasetRow *but_dataset_row = (uiButDatasetRow *)but;
- BLI_assert(but->type == UI_BTYPE_DATASETROW);
-
- return but_dataset_row->geometry_component_type;
-}
-
-uint8_t UI_but_datasetrow_domain_get(uiBut *but)
-{
- uiButDatasetRow *but_dataset_row = (uiButDatasetRow *)but;
- BLI_assert(but->type == UI_BTYPE_DATASETROW);
-
- return but_dataset_row->attribute_domain;
-}
-
void UI_but_node_link_set(uiBut *but, bNodeSocket *socket, const float draw_color[4])
{
but->flag |= UI_BUT_NODE_LINK;
diff --git a/source/blender/editors/interface/interface_context_path.cc b/source/blender/editors/interface/interface_context_path.cc
index b0f8d186afa..3f5efd187d8 100644
--- a/source/blender/editors/interface/interface_context_path.cc
+++ b/source/blender/editors/interface/interface_context_path.cc
@@ -82,4 +82,4 @@ void template_breadcrumbs(uiLayout &layout, Span<ContextPathItem> context_path)
} // namespace blender::ui
-/** \} */ \ No newline at end of file
+/** \} */
diff --git a/source/blender/editors/interface/interface_eyedropper_color.c b/source/blender/editors/interface/interface_eyedropper_color.c
index c3633e11f83..e45619d89e8 100644
--- a/source/blender/editors/interface/interface_eyedropper_color.c
+++ b/source/blender/editors/interface/interface_eyedropper_color.c
@@ -268,28 +268,28 @@ static bool eyedropper_cryptomatte_sample_fl(
return false;
}
- ARegion *ar = BKE_area_find_region_xy(sa, RGN_TYPE_WINDOW, mx, my);
- if (!ar) {
+ ARegion *region = BKE_area_find_region_xy(sa, RGN_TYPE_WINDOW, mx, my);
+ if (!region) {
return false;
}
- int mval[2] = {mx - ar->winrct.xmin, my - ar->winrct.ymin};
+ int mval[2] = {mx - region->winrct.xmin, my - region->winrct.ymin};
float fpos[2] = {-1.0f, -1.0};
switch (sa->spacetype) {
case SPACE_IMAGE: {
SpaceImage *sima = sa->spacedata.first;
- ED_space_image_get_position(sima, ar, mval, fpos);
+ ED_space_image_get_position(sima, region, mval, fpos);
break;
}
case SPACE_NODE: {
Main *bmain = CTX_data_main(C);
SpaceNode *snode = sa->spacedata.first;
- ED_space_node_get_position(bmain, snode, ar, mval, fpos);
+ ED_space_node_get_position(bmain, snode, region, mval, fpos);
break;
}
case SPACE_CLIP: {
SpaceClip *sc = sa->spacedata.first;
- ED_space_clip_get_position(sc, ar, mval, fpos);
+ ED_space_clip_get_position(sc, region, mval, fpos);
break;
}
default: {
diff --git a/source/blender/editors/interface/interface_handlers.c b/source/blender/editors/interface/interface_handlers.c
index 6d69724efef..d18b3fdf505 100644
--- a/source/blender/editors/interface/interface_handlers.c
+++ b/source/blender/editors/interface/interface_handlers.c
@@ -492,7 +492,7 @@ typedef struct uiAfterFunc {
wmOperator *popup_op;
wmOperatorType *optype;
- int opcontext;
+ wmOperatorCallContext opcontext;
PointerRNA *opptr;
PointerRNA rnapoin;
@@ -775,7 +775,7 @@ static uiAfterFunc *ui_afterfunc_new(void)
*/
static void ui_handle_afterfunc_add_operator_ex(wmOperatorType *ot,
PointerRNA **properties,
- int opcontext,
+ wmOperatorCallContext opcontext,
const uiBut *context_but)
{
uiAfterFunc *after = ui_afterfunc_new();
@@ -796,7 +796,7 @@ static void ui_handle_afterfunc_add_operator_ex(wmOperatorType *ot,
}
}
-void ui_handle_afterfunc_add_operator(wmOperatorType *ot, int opcontext)
+void ui_handle_afterfunc_add_operator(wmOperatorType *ot, wmOperatorCallContext opcontext)
{
ui_handle_afterfunc_add_operator_ex(ot, NULL, opcontext, NULL);
}
@@ -2334,9 +2334,6 @@ static void ui_apply_but(
case UI_BTYPE_LISTROW:
ui_apply_but_LISTROW(C, block, but, data);
break;
- case UI_BTYPE_DATASETROW:
- ui_apply_but_ROW(C, block, but, data);
- break;
case UI_BTYPE_TAB:
ui_apply_but_TAB(C, but, data);
break;
@@ -8012,7 +8009,6 @@ static int ui_do_button(bContext *C, uiBlock *block, uiBut *but, const wmEvent *
case UI_BTYPE_CHECKBOX:
case UI_BTYPE_CHECKBOX_N:
case UI_BTYPE_ROW:
- case UI_BTYPE_DATASETROW:
retval = ui_do_but_TOG(C, but, data, event);
break;
case UI_BTYPE_TREEROW:
@@ -11344,8 +11340,7 @@ static void ui_region_handler_remove(bContext *C, void *UNUSED(userdata))
return;
}
- UI_blocklist_free(C, &region->uiblocks);
-
+ UI_blocklist_free(C, region);
bScreen *screen = CTX_wm_screen(C);
if (screen == NULL) {
return;
diff --git a/source/blender/editors/interface/interface_icons_event.c b/source/blender/editors/interface/interface_icons_event.c
index 3962ff6a702..577db6a0338 100644
--- a/source/blender/editors/interface/interface_icons_event.c
+++ b/source/blender/editors/interface/interface_icons_event.c
@@ -77,7 +77,7 @@
static void icon_draw_rect_input_text(const rctf *rect,
const float color[4],
const char *str,
- int font_size)
+ float font_size)
{
BLF_batch_draw_flush();
const int font_id = BLF_default();
@@ -97,7 +97,7 @@ static void icon_draw_rect_input_symbol(const rctf *rect, const float color[4],
BLF_batch_draw_flush();
const int font_id = blf_mono_font;
BLF_color4fv(font_id, color);
- BLF_size(font_id, 19 * U.pixelsize, U.dpi);
+ BLF_size(font_id, 19.0f * U.pixelsize, U.dpi);
const float x = rect->xmin + (2.0f * U.pixelsize);
const float y = rect->ymin + (1.0f * U.pixelsize);
BLF_position(font_id, x, y, 0.0f);
@@ -152,12 +152,12 @@ void icon_draw_rect_input(float x,
if ((event_type >= EVT_AKEY) && (event_type <= EVT_ZKEY)) {
const char str[2] = {'A' + (event_type - EVT_AKEY), '\0'};
- icon_draw_rect_input_text(&rect, color, str, 13);
+ icon_draw_rect_input_text(&rect, color, str, 13.0f);
}
else if ((event_type >= EVT_F1KEY) && (event_type <= EVT_F12KEY)) {
char str[4];
SNPRINTF(str, "F%d", 1 + (event_type - EVT_F1KEY));
- icon_draw_rect_input_text(&rect, color, str, event_type > EVT_F9KEY ? 8 : 10);
+ icon_draw_rect_input_text(&rect, color, str, event_type > EVT_F9KEY ? 8.0f : 10.0f);
}
else if (event_type == EVT_LEFTSHIFTKEY) {
icon_draw_rect_input_symbol(&rect, color, (const char[]){0xe2, 0x87, 0xa7, 0x0});
@@ -167,7 +167,7 @@ void icon_draw_rect_input(float x,
icon_draw_rect_input_symbol(&rect, color, (const char[]){0xe2, 0x8c, 0x83, 0x0});
}
else {
- icon_draw_rect_input_text(&rect, color, "Ctrl", 9);
+ icon_draw_rect_input_text(&rect, color, "Ctrl", 9.0f);
}
}
else if (event_type == EVT_LEFTALTKEY) {
@@ -175,7 +175,7 @@ void icon_draw_rect_input(float x,
icon_draw_rect_input_symbol(&rect, color, (const char[]){0xe2, 0x8c, 0xa5, 0x0});
}
else {
- icon_draw_rect_input_text(&rect, color, "Alt", 10);
+ icon_draw_rect_input_text(&rect, color, "Alt", 10.0f);
}
}
else if (event_type == EVT_OSKEY) {
@@ -186,20 +186,20 @@ void icon_draw_rect_input(float x,
icon_draw_rect_input_symbol(&rect, color, (const char[]){0xe2, 0x9d, 0x96, 0x0});
}
else {
- icon_draw_rect_input_text(&rect, color, "OS", 10);
+ icon_draw_rect_input_text(&rect, color, "OS", 10.0f);
}
}
else if (event_type == EVT_DELKEY) {
- icon_draw_rect_input_text(&rect, color, "Del", 9);
+ icon_draw_rect_input_text(&rect, color, "Del", 9.0f);
}
else if (event_type == EVT_TABKEY) {
icon_draw_rect_input_symbol(&rect, color, (const char[]){0xe2, 0xad, 0xbe, 0x0});
}
else if (event_type == EVT_HOMEKEY) {
- icon_draw_rect_input_text(&rect, color, "Home", 6);
+ icon_draw_rect_input_text(&rect, color, "Home", 6.0f);
}
else if (event_type == EVT_ENDKEY) {
- icon_draw_rect_input_text(&rect, color, "End", 8);
+ icon_draw_rect_input_text(&rect, color, "End", 8.0f);
}
else if (event_type == EVT_RETKEY) {
icon_draw_rect_input_symbol(&rect, color, (const char[]){0xe2, 0x8f, 0x8e, 0x0});
@@ -209,14 +209,14 @@ void icon_draw_rect_input(float x,
icon_draw_rect_input_symbol(&rect, color, (const char[]){0xe2, 0x8e, 0x8b, 0x0});
}
else {
- icon_draw_rect_input_text(&rect, color, "Esc", 8);
+ icon_draw_rect_input_text(&rect, color, "Esc", 8.0f);
}
}
else if (event_type == EVT_PAGEUPKEY) {
- icon_draw_rect_input_text(&rect, color, (const char[]){'P', 0xe2, 0x86, 0x91, 0x0}, 8);
+ icon_draw_rect_input_text(&rect, color, (const char[]){'P', 0xe2, 0x86, 0x91, 0x0}, 8.0f);
}
else if (event_type == EVT_PAGEDOWNKEY) {
- icon_draw_rect_input_text(&rect, color, (const char[]){'P', 0xe2, 0x86, 0x93, 0x0}, 8);
+ icon_draw_rect_input_text(&rect, color, (const char[]){'P', 0xe2, 0x86, 0x93, 0x0}, 8.0f);
}
else if (event_type == EVT_LEFTARROWKEY) {
icon_draw_rect_input_symbol(&rect, color, (const char[]){0xe2, 0x86, 0x90, 0x0});
diff --git a/source/blender/editors/interface/interface_intern.h b/source/blender/editors/interface/interface_intern.h
index f766bb1465f..e0686c1ff7a 100644
--- a/source/blender/editors/interface/interface_intern.h
+++ b/source/blender/editors/interface/interface_intern.h
@@ -255,7 +255,7 @@ struct uiBut {
/* Operator data */
struct wmOperatorType *optype;
struct PointerRNA *opptr;
- short opcontext;
+ wmOperatorCallContext opcontext;
/** When non-zero, this is the key used to activate a menu items (`a-z` always lower case). */
uchar menu_key;
@@ -351,14 +351,6 @@ typedef struct uiButProgressbar {
float progress;
} uiButProgressbar;
-/** Derived struct for #UI_BTYPE_DATASETROW. */
-typedef struct uiButDatasetRow {
- uiBut but;
-
- uint8_t geometry_component_type;
- uint8_t attribute_domain;
- int indentation;
-} uiButDatasetRow;
/** Derived struct for #UI_BTYPE_TREEROW. */
typedef struct uiButTreeRow {
@@ -609,7 +601,7 @@ typedef struct uiSafetyRct {
/* interface.c */
-void ui_fontscale(short *points, float aspect);
+void ui_fontscale(float *points, float aspect);
extern void ui_block_to_region_fl(const struct ARegion *region,
uiBlock *block,
@@ -882,7 +874,7 @@ void ui_pie_menu_level_create(uiBlock *block,
struct IDProperty *properties,
const EnumPropertyItem *items,
int totitem,
- int context,
+ wmOperatorCallContext context,
int flag);
/* interface_region_popup.c */
@@ -960,7 +952,8 @@ const char *ui_textedit_undo(struct uiUndoStack_Text *undo_stack,
int *r_cursor_index);
/* interface_handlers.c */
-extern void ui_handle_afterfunc_add_operator(struct wmOperatorType *ot, int opcontext);
+extern void ui_handle_afterfunc_add_operator(struct wmOperatorType *ot,
+ wmOperatorCallContext opcontext);
extern void ui_pan_to_scroll(const struct wmEvent *event, int *type, int *val);
extern void ui_but_activate_event(struct bContext *C, struct ARegion *region, uiBut *but);
extern void ui_but_activate_over(struct bContext *C, struct ARegion *region, uiBut *but);
diff --git a/source/blender/editors/interface/interface_layout.c b/source/blender/editors/interface/interface_layout.c
index 20e95ef4e9c..b792c59481c 100644
--- a/source/blender/editors/interface/interface_layout.c
+++ b/source/blender/editors/interface/interface_layout.c
@@ -82,7 +82,7 @@ typedef struct uiLayoutRoot {
struct uiLayoutRoot *next, *prev;
int type;
- int opcontext;
+ wmOperatorCallContext opcontext;
int emw, emh;
int padding;
@@ -1218,7 +1218,7 @@ static uiBut *uiItemFullO_ptr_ex(uiLayout *layout,
const char *name,
int icon,
IDProperty *properties,
- int context,
+ wmOperatorCallContext context,
int flag,
PointerRNA *r_opptr)
{
@@ -1350,7 +1350,7 @@ void uiItemFullO_ptr(uiLayout *layout,
const char *name,
int icon,
IDProperty *properties,
- int context,
+ wmOperatorCallContext context,
int flag,
PointerRNA *r_opptr)
{
@@ -1362,7 +1362,7 @@ void uiItemFullOMenuHold_ptr(uiLayout *layout,
const char *name,
int icon,
IDProperty *properties,
- int context,
+ wmOperatorCallContext context,
int flag,
const char *menu_id,
PointerRNA *r_opptr)
@@ -1376,7 +1376,7 @@ void uiItemFullO(uiLayout *layout,
const char *name,
int icon,
IDProperty *properties,
- int context,
+ wmOperatorCallContext context,
int flag,
PointerRNA *r_opptr)
{
@@ -1474,7 +1474,7 @@ void uiItemsFullEnumO_items(uiLayout *layout,
PointerRNA ptr,
PropertyRNA *prop,
IDProperty *properties,
- int context,
+ wmOperatorCallContext context,
int flag,
const EnumPropertyItem *item_array,
int totitem)
@@ -1623,7 +1623,7 @@ void uiItemsFullEnumO(uiLayout *layout,
const char *opname,
const char *propname,
IDProperty *properties,
- int context,
+ wmOperatorCallContext context,
int flag)
{
wmOperatorType *ot = WM_operatortype_find(opname, 0); /* print error next */
@@ -3433,7 +3433,7 @@ void uiItemMenuFN(uiLayout *layout, const char *name, int icon, uiMenuCreateFunc
}
typedef struct MenuItemLevel {
- int opcontext;
+ wmOperatorCallContext opcontext;
/* don't use pointers to the strings because python can dynamically
* allocate strings and free before the menu draws, see T27304. */
char opname[OP_MAX_TYPENAME];
@@ -5672,7 +5672,7 @@ bool uiLayoutGetFixedSize(uiLayout *layout)
return (layout->item.flag & UI_ITEM_FIXED_SIZE) != 0;
}
-void uiLayoutSetOperatorContext(uiLayout *layout, int opcontext)
+void uiLayoutSetOperatorContext(uiLayout *layout, wmOperatorCallContext opcontext)
{
layout->root->opcontext = opcontext;
}
diff --git a/source/blender/editors/interface/interface_panel.c b/source/blender/editors/interface/interface_panel.c
index 3a8e06a3e49..8d47b8a1011 100644
--- a/source/blender/editors/interface/interface_panel.c
+++ b/source/blender/editors/interface/interface_panel.c
@@ -1352,7 +1352,7 @@ void UI_panel_category_draw_all(ARegion *region, const char *category_id_active)
const uiStyle *style = UI_style_get();
const uiFontStyle *fstyle = &style->widget;
const int fontid = fstyle->uifont_id;
- short fstyle_points = fstyle->points;
+ float fstyle_points = fstyle->points;
const float aspect = ((uiBlock *)region->uiblocks.first)->aspect;
const float zoom = 1.0f / aspect;
const int px = U.pixelsize;
diff --git a/source/blender/editors/interface/interface_query.c b/source/blender/editors/interface/interface_query.c
index bdf93d7c82e..a07222854d2 100644
--- a/source/blender/editors/interface/interface_query.c
+++ b/source/blender/editors/interface/interface_query.c
@@ -69,7 +69,6 @@ bool ui_but_is_toggle(const uiBut *but)
UI_BTYPE_CHECKBOX,
UI_BTYPE_CHECKBOX_N,
UI_BTYPE_ROW,
- UI_BTYPE_DATASETROW,
UI_BTYPE_TREEROW);
}
diff --git a/source/blender/editors/interface/interface_region_menu_pie.c b/source/blender/editors/interface/interface_region_menu_pie.c
index 01562b25da1..0ffbdd6911c 100644
--- a/source/blender/editors/interface/interface_region_menu_pie.c
+++ b/source/blender/editors/interface/interface_region_menu_pie.c
@@ -330,7 +330,7 @@ typedef struct PieMenuLevelData {
wmOperatorType *ot;
const char *propname;
IDProperty *properties;
- int context, flag;
+ wmOperatorCallContext context, flag;
} PieMenuLevelData;
/**
@@ -381,7 +381,7 @@ void ui_pie_menu_level_create(uiBlock *block,
IDProperty *properties,
const EnumPropertyItem *items,
int totitem,
- int context,
+ wmOperatorCallContext context,
int flag)
{
const int totitem_parent = PIE_MAX_ITEMS - 1;
diff --git a/source/blender/editors/interface/interface_region_menu_popup.c b/source/blender/editors/interface/interface_region_menu_popup.c
index 4e20466326e..408953f8d0e 100644
--- a/source/blender/editors/interface/interface_region_menu_popup.c
+++ b/source/blender/editors/interface/interface_region_menu_popup.c
@@ -640,7 +640,7 @@ void UI_popup_block_ex(bContext *C,
}
#if 0 /* UNUSED */
-void uiPupBlockOperator(bContext *C, uiBlockCreateFunc func, wmOperator *op, int opcontext)
+void uiPupBlockOperator(bContext *C, uiBlockCreateFunc func, wmOperator *op, wmOperatorCallContext opcontext)
{
wmWindow *window = CTX_wm_window(C);
uiPopupBlockHandle *handle;
diff --git a/source/blender/editors/interface/interface_region_popover.c b/source/blender/editors/interface/interface_region_popover.c
index f8f19c2e43d..5e7e0bfe9b5 100644
--- a/source/blender/editors/interface/interface_region_popover.c
+++ b/source/blender/editors/interface/interface_region_popover.c
@@ -90,7 +90,7 @@ struct uiPopover {
#endif
};
-static void ui_popover_create_block(bContext *C, uiPopover *pup, int opcontext)
+static void ui_popover_create_block(bContext *C, uiPopover *pup, wmOperatorCallContext opcontext)
{
BLI_assert(pup->ui_size_x != 0);
diff --git a/source/blender/editors/interface/interface_region_popup.c b/source/blender/editors/interface/interface_region_popup.c
index 0e53100f91b..0f903bd4af9 100644
--- a/source/blender/editors/interface/interface_region_popup.c
+++ b/source/blender/editors/interface/interface_region_popup.c
@@ -743,7 +743,7 @@ uiBlock *ui_popup_block_refresh(bContext *C,
if (block_old) {
block->oldblock = block_old;
UI_block_update_from_old(C, block);
- UI_blocklist_free_inactive(C, &region->uiblocks);
+ UI_blocklist_free_inactive(C, region);
}
/* checks which buttons are visible, sets flags to prevent draw (do after region init) */
diff --git a/source/blender/editors/interface/interface_region_search.c b/source/blender/editors/interface/interface_region_search.cc
index b8a19d06be1..eaf1ed3693b 100644
--- a/source/blender/editors/interface/interface_region_search.c
+++ b/source/blender/editors/interface/interface_region_search.cc
@@ -23,9 +23,9 @@
* Search Box Region & Interaction
*/
-#include <stdarg.h>
-#include <stdlib.h>
-#include <string.h>
+#include <cstdarg>
+#include <cstdlib>
+#include <cstring>
#include "DNA_ID.h"
#include "MEM_guardedalloc.h"
@@ -84,7 +84,7 @@ struct uiSearchItems {
void *active;
};
-typedef struct uiSearchboxData {
+struct uiSearchboxData {
rcti bbox;
uiFontStyle fstyle;
uiSearchItems items;
@@ -102,7 +102,7 @@ typedef struct uiSearchboxData {
* Used so we can show leading text to menu items less prominently (not related to 'use_sep').
*/
const char *sep_string;
-} uiSearchboxData;
+};
#define SEARCH_ITEMS 10
@@ -166,9 +166,9 @@ bool UI_search_item_add(uiSearchItems *items,
if (name_prefix_offset != 0) {
/* Lazy initialize, as this isn't used often. */
- if (items->name_prefix_offsets == NULL) {
- items->name_prefix_offsets = MEM_callocN(
- items->maxitem * sizeof(*items->name_prefix_offsets), "search name prefix offsets");
+ if (items->name_prefix_offsets == nullptr) {
+ items->name_prefix_offsets = (uint8_t *)MEM_callocN(
+ items->maxitem * sizeof(*items->name_prefix_offsets), __func__);
}
items->name_prefix_offsets[items->totitem] = name_prefix_offset;
}
@@ -198,7 +198,7 @@ int UI_searchbox_size_x(void)
int UI_search_items_find_index(uiSearchItems *items, const char *name)
{
- if (items->name_prefix_offsets != NULL) {
+ if (items->name_prefix_offsets != nullptr) {
for (int i = 0; i < items->totitem; i++) {
if (STREQ(name, items->names[i] + items->name_prefix_offsets[i])) {
return i;
@@ -218,7 +218,7 @@ int UI_search_items_find_index(uiSearchItems *items, const char *name)
/* region is the search box itself */
static void ui_searchbox_select(bContext *C, ARegion *region, uiBut *but, int step)
{
- uiSearchboxData *data = region->regiondata;
+ uiSearchboxData *data = static_cast<uiSearchboxData *>(region->regiondata);
/* apply step */
data->active += step;
@@ -285,14 +285,14 @@ static void ui_searchbox_butrect(rcti *r_rect, uiSearchboxData *data, int itemnr
int ui_searchbox_find_index(ARegion *region, const char *name)
{
- uiSearchboxData *data = region->regiondata;
+ uiSearchboxData *data = static_cast<uiSearchboxData *>(region->regiondata);
return UI_search_items_find_index(&data->items, name);
}
/* x and y in screen-coords. */
bool ui_searchbox_inside(ARegion *region, const int xy[2])
{
- uiSearchboxData *data = region->regiondata;
+ uiSearchboxData *data = static_cast<uiSearchboxData *>(region->regiondata);
return BLI_rcti_isect_pt(&data->bbox, xy[0] - region->winrct.xmin, xy[1] - region->winrct.ymin);
}
@@ -300,12 +300,12 @@ bool ui_searchbox_inside(ARegion *region, const int xy[2])
/* string validated to be of correct length (but->hardmax) */
bool ui_searchbox_apply(uiBut *but, ARegion *region)
{
- uiSearchboxData *data = region->regiondata;
+ uiSearchboxData *data = static_cast<uiSearchboxData *>(region->regiondata);
uiButSearch *search_but = (uiButSearch *)but;
BLI_assert(but->type == UI_BTYPE_SEARCH_MENU);
- search_but->item_active = NULL;
+ search_but->item_active = nullptr;
if (data->active != -1) {
const char *name = data->items.names[data->active] +
@@ -314,7 +314,7 @@ bool ui_searchbox_apply(uiBut *but, ARegion *region)
data->items.name_prefix_offsets[data->active] :
0);
- const char *name_sep = data->use_shortcut_sep ? strrchr(name, UI_SEP_CHAR) : NULL;
+ const char *name_sep = data->use_shortcut_sep ? strrchr(name, UI_SEP_CHAR) : nullptr;
/* Search button with dynamic string properties may have their own method of applying
* the search results, so only copy the result if there is a proper space for it. */
@@ -356,7 +356,7 @@ static struct ARegion *wm_searchbox_tooltip_init(struct bContext *C,
}
ARegion *searchbox_region = UI_region_searchbox_region_get(region);
- uiSearchboxData *data = searchbox_region->regiondata;
+ uiSearchboxData *data = static_cast<uiSearchboxData *>(searchbox_region->regiondata);
BLI_assert(data->items.pointers[data->active] == search_but->item_active);
@@ -367,13 +367,13 @@ static struct ARegion *wm_searchbox_tooltip_init(struct bContext *C,
C, region, &rect, search_but->arg, search_but->item_active);
}
}
- return NULL;
+ return nullptr;
}
bool ui_searchbox_event(
bContext *C, ARegion *region, uiBut *but, ARegion *butregion, const wmEvent *event)
{
- uiSearchboxData *data = region->regiondata;
+ uiSearchboxData *data = static_cast<uiSearchboxData *>(region->regiondata);
uiButSearch *search_but = (uiButSearch *)but;
int type = event->type, val = event->val;
bool handled = false;
@@ -481,7 +481,7 @@ static void ui_searchbox_update_fn(bContext *C,
void ui_searchbox_update(bContext *C, ARegion *region, uiBut *but, const bool reset)
{
uiButSearch *search_but = (uiButSearch *)but;
- uiSearchboxData *data = region->regiondata;
+ uiSearchboxData *data = static_cast<uiSearchboxData *>(region->regiondata);
BLI_assert(but->type == UI_BTYPE_SEARCH_MENU);
@@ -499,7 +499,7 @@ void ui_searchbox_update(bContext *C, ARegion *region, uiBut *but, const bool re
if (search_but->items_update_fn && search_but->item_active) {
data->items.active = search_but->item_active;
ui_searchbox_update_fn(C, search_but, but->editstr, &data->items);
- data->items.active = NULL;
+ data->items.active = nullptr;
/* found active item, calculate real offset by centering it */
if (data->items.totitem) {
@@ -538,7 +538,7 @@ void ui_searchbox_update(bContext *C, ARegion *region, uiBut *but, const bool re
/* Never include the prefix in the button. */
(data->items.name_prefix_offsets ? data->items.name_prefix_offsets[a] :
0);
- const char *name_sep = data->use_shortcut_sep ? strrchr(name, UI_SEP_CHAR) : NULL;
+ const char *name_sep = data->use_shortcut_sep ? strrchr(name, UI_SEP_CHAR) : nullptr;
if (STREQLEN(but->editstr, name, name_sep ? (name_sep - name) : data->items.maxstrlen)) {
data->active = a;
break;
@@ -558,7 +558,7 @@ void ui_searchbox_update(bContext *C, ARegion *region, uiBut *but, const bool re
int ui_searchbox_autocomplete(bContext *C, ARegion *region, uiBut *but, char *str)
{
uiButSearch *search_but = (uiButSearch *)but;
- uiSearchboxData *data = region->regiondata;
+ uiSearchboxData *data = static_cast<uiSearchboxData *>(region->regiondata);
int match = AUTOCOMPLETE_NO_MATCH;
BLI_assert(but->type == UI_BTYPE_SEARCH_MENU);
@@ -569,7 +569,7 @@ int ui_searchbox_autocomplete(bContext *C, ARegion *region, uiBut *but, char *st
ui_searchbox_update_fn(C, search_but, but->editstr, &data->items);
match = UI_autocomplete_end(data->items.autocpl, str);
- data->items.autocpl = NULL;
+ data->items.autocpl = nullptr;
}
return match;
@@ -577,7 +577,7 @@ int ui_searchbox_autocomplete(bContext *C, ARegion *region, uiBut *but, char *st
static void ui_searchbox_region_draw_fn(const bContext *C, ARegion *region)
{
- uiSearchboxData *data = region->regiondata;
+ uiSearchboxData *data = static_cast<uiSearchboxData *>(region->regiondata);
/* pixel space */
wmOrtho2_region_pixelspace(region);
@@ -630,7 +630,7 @@ static void ui_searchbox_region_draw_fn(const bContext *C, ARegion *region)
const int state = ((a == data->active) ? UI_ACTIVE : 0) | data->items.states[a];
char *name = data->items.names[a];
int icon = data->items.icons[a];
- char *name_sep_test = NULL;
+ char *name_sep_test = nullptr;
uiMenuItemSeparatorType separator_type = UI_MENU_ITEM_SEPARATOR_NONE;
if (data->use_shortcut_sep) {
@@ -652,15 +652,15 @@ static void ui_searchbox_region_draw_fn(const bContext *C, ARegion *region)
}
/* Simple menu item. */
- ui_draw_menu_item(&data->fstyle, &rect, name, icon, state, separator_type, NULL);
+ ui_draw_menu_item(&data->fstyle, &rect, name, icon, state, separator_type, nullptr);
}
else {
/* Split menu item, faded text before the separator. */
- char *name_sep = NULL;
+ char *name_sep = nullptr;
do {
name_sep = name_sep_test;
name_sep_test = strstr(name_sep + search_sep_len, data->sep_string);
- } while (name_sep_test != NULL);
+ } while (name_sep_test != nullptr);
name_sep += search_sep_len;
const char name_sep_prev = *name_sep;
@@ -683,7 +683,7 @@ static void ui_searchbox_region_draw_fn(const bContext *C, ARegion *region)
}
/* The previous menu item draws the active selection. */
- ui_draw_menu_item(&data->fstyle, &rect, name_sep, icon, state, separator_type, NULL);
+ ui_draw_menu_item(&data->fstyle, &rect, name_sep, icon, state, separator_type, nullptr);
}
}
/* indicate more */
@@ -705,7 +705,7 @@ static void ui_searchbox_region_draw_fn(const bContext *C, ARegion *region)
static void ui_searchbox_region_free_fn(ARegion *region)
{
- uiSearchboxData *data = region->regiondata;
+ uiSearchboxData *data = static_cast<uiSearchboxData *>(region->regiondata);
/* free search data */
for (int a = 0; a < data->items.maxitem; a++) {
@@ -716,12 +716,12 @@ static void ui_searchbox_region_free_fn(ARegion *region)
MEM_freeN(data->items.icons);
MEM_freeN(data->items.states);
- if (data->items.name_prefix_offsets != NULL) {
+ if (data->items.name_prefix_offsets != nullptr) {
MEM_freeN(data->items.name_prefix_offsets);
}
MEM_freeN(data);
- region->regiondata = NULL;
+ region->regiondata = nullptr;
}
static ARegion *ui_searchbox_create_generic_ex(bContext *C,
@@ -746,7 +746,7 @@ static ARegion *ui_searchbox_create_generic_ex(bContext *C,
region->type = &type;
/* create searchbox data */
- uiSearchboxData *data = MEM_callocN(sizeof(uiSearchboxData), "uiSearchboxData");
+ uiSearchboxData *data = (uiSearchboxData *)MEM_callocN(sizeof(uiSearchboxData), __func__);
/* set font, get bb */
data->fstyle = style->widget; /* copy struct */
@@ -767,7 +767,7 @@ static ARegion *ui_searchbox_create_generic_ex(bContext *C,
data->prv_cols = but->a2;
}
- if (but->optype != NULL || use_shortcut_sep) {
+ if (but->optype != nullptr || use_shortcut_sep) {
data->use_shortcut_sep = true;
}
data->sep_string = search_but->item_sep_string;
@@ -881,13 +881,13 @@ static ARegion *ui_searchbox_create_generic_ex(bContext *C,
/* In case the button's string is dynamic, make sure there are buffers available. */
data->items.maxstrlen = but->hardmax == 0 ? UI_MAX_NAME_STR : but->hardmax;
data->items.totitem = 0;
- data->items.names = MEM_callocN(data->items.maxitem * sizeof(void *), "search names");
- data->items.pointers = MEM_callocN(data->items.maxitem * sizeof(void *), "search pointers");
- data->items.icons = MEM_callocN(data->items.maxitem * sizeof(int), "search icons");
- data->items.states = MEM_callocN(data->items.maxitem * sizeof(int), "search flags");
- data->items.name_prefix_offsets = NULL; /* Lazy initialized as needed. */
+ data->items.names = (char **)MEM_callocN(data->items.maxitem * sizeof(void *), __func__);
+ data->items.pointers = (void **)MEM_callocN(data->items.maxitem * sizeof(void *), __func__);
+ data->items.icons = (int *)MEM_callocN(data->items.maxitem * sizeof(int), __func__);
+ data->items.states = (int *)MEM_callocN(data->items.maxitem * sizeof(int), __func__);
+ data->items.name_prefix_offsets = nullptr; /* Lazy initialized as needed. */
for (int i = 0; i < data->items.maxitem; i++) {
- data->items.names[i] = MEM_callocN(data->items.maxstrlen + 1, "search pointers");
+ data->items.names[i] = (char *)MEM_callocN(data->items.maxstrlen + 1, __func__);
}
return region;
@@ -924,7 +924,7 @@ static void str_tolower_titlecaps_ascii(char *str, const size_t len)
static void ui_searchbox_region_draw_cb__operator(const bContext *UNUSED(C), ARegion *region)
{
- uiSearchboxData *data = region->regiondata;
+ uiSearchboxData *data = static_cast<uiSearchboxData *>(region->regiondata);
/* pixel space */
wmOrtho2_region_pixelspace(region);
@@ -952,10 +952,10 @@ static void ui_searchbox_region_draw_cb__operator(const bContext *UNUSED(C), ARe
{
const int state = ((a == data->active) ? UI_ACTIVE : 0) | data->items.states[a];
- wmOperatorType *ot = data->items.pointers[a];
+ wmOperatorType *ot = static_cast<wmOperatorType *>(data->items.pointers[a]);
char text_pre[128];
- char *text_pre_p = strstr(ot->idname, "_OT_");
- if (text_pre_p == NULL) {
+ const char *text_pre_p = strstr(ot->idname, "_OT_");
+ if (text_pre_p == nullptr) {
text_pre[0] = '\0';
}
else {
@@ -975,7 +975,7 @@ static void ui_searchbox_region_draw_cb__operator(const bContext *UNUSED(C), ARe
data->items.icons[a],
state,
UI_MENU_ITEM_SEPARATOR_NONE,
- NULL);
+ nullptr);
ui_draw_menu_item(&data->fstyle,
&rect_post,
data->items.names[a],
@@ -983,7 +983,7 @@ static void ui_searchbox_region_draw_cb__operator(const bContext *UNUSED(C), ARe
state,
data->use_shortcut_sep ? UI_MENU_ITEM_SEPARATOR_SHORTCUT :
UI_MENU_ITEM_SEPARATOR_NONE,
- NULL);
+ nullptr);
}
}
/* indicate more */
@@ -1044,17 +1044,17 @@ void ui_but_search_refresh(uiButSearch *search_but)
return;
}
- uiSearchItems *items = MEM_callocN(sizeof(uiSearchItems), "search items");
+ uiSearchItems *items = (uiSearchItems *)MEM_callocN(sizeof(uiSearchItems), __func__);
/* setup search struct */
items->maxitem = 10;
items->maxstrlen = 256;
- items->names = MEM_callocN(items->maxitem * sizeof(void *), "search names");
+ items->names = (char **)MEM_callocN(items->maxitem * sizeof(void *), __func__);
for (int i = 0; i < items->maxitem; i++) {
- items->names[i] = MEM_callocN(but->hardmax + 1, "search names");
+ items->names[i] = (char *)MEM_callocN(but->hardmax + 1, __func__);
}
- ui_searchbox_update_fn(but->block->evil_C, search_but, but->drawstr, items);
+ ui_searchbox_update_fn((bContext *)but->block->evil_C, search_but, but->drawstr, items);
if (!search_but->results_are_suggestions) {
/* Only red-alert when we are sure of it, this can miss cases when >10 matches. */
diff --git a/source/blender/editors/interface/interface_region_tooltip.c b/source/blender/editors/interface/interface_region_tooltip.c
index eb25d896d26..0d8bdfc5817 100644
--- a/source/blender/editors/interface/interface_region_tooltip.c
+++ b/source/blender/editors/interface/interface_region_tooltip.c
@@ -960,7 +960,8 @@ static uiTooltipData *ui_tooltip_data_from_button_or_extra_icon(bContext *C,
/* if operator poll check failed, it can give pretty precise info why */
if (optype) {
- const int opcontext = extra_icon ? extra_icon->optype_params->opcontext : but->opcontext;
+ const wmOperatorCallContext opcontext = extra_icon ? extra_icon->optype_params->opcontext :
+ but->opcontext;
CTX_wm_operator_poll_msg_clear(C);
ui_but_context_poll_operator_ex(
C, but, &(wmOperatorCallParams){.optype = optype, .opcontext = opcontext});
diff --git a/source/blender/editors/interface/interface_regions_intern.h b/source/blender/editors/interface/interface_regions_intern.h
index 0cb1fee9a92..ce938852520 100644
--- a/source/blender/editors/interface/interface_regions_intern.h
+++ b/source/blender/editors/interface/interface_regions_intern.h
@@ -22,9 +22,17 @@
#pragma once
+#ifdef __cplusplus
+extern "C" {
+#endif
+
/* interface_region_menu_popup.c */
uint ui_popup_menu_hash(const char *str);
/* interface_regions_intern.h */
ARegion *ui_region_temp_add(bScreen *screen);
void ui_region_temp_remove(struct bContext *C, bScreen *screen, ARegion *region);
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/editors/interface/interface_style.c b/source/blender/editors/interface/interface_style.c
index 92a9f14c77d..8bb1e477506 100644
--- a/source/blender/editors/interface/interface_style.c
+++ b/source/blender/editors/interface/interface_style.c
@@ -419,7 +419,7 @@ int UI_fontstyle_height_max(const uiFontStyle *fs)
/* reading without uifont will create one */
void uiStyleInit(void)
{
- uiStyle *style = U.uistyles.first;
+ const uiStyle *style = U.uistyles.first;
/* recover from uninitialized dpi */
if (U.dpi == 0) {
@@ -483,16 +483,20 @@ void uiStyleInit(void)
* Yes, this build the glyph cache and create
* the texture.
*/
- BLF_size(font->blf_id, 11 * U.pixelsize, U.dpi);
- BLF_size(font->blf_id, 12 * U.pixelsize, U.dpi);
- BLF_size(font->blf_id, 14 * U.pixelsize, U.dpi);
+ BLF_size(font->blf_id, 11.0f * U.pixelsize, U.dpi);
+ BLF_size(font->blf_id, 12.0f * U.pixelsize, U.dpi);
+ BLF_size(font->blf_id, 14.0f * U.pixelsize, U.dpi);
}
}
if (style == NULL) {
- ui_style_new(&U.uistyles, "Default Style", UIFONT_DEFAULT);
+ style = ui_style_new(&U.uistyles, "Default Style", UIFONT_DEFAULT);
}
+ BLF_cache_flush_set_fn(UI_widgetbase_draw_cache_flush);
+
+ BLF_default_size(style->widgetlabel.points);
+
/* XXX, this should be moved into a style,
* but for now best only load the monospaced font once. */
BLI_assert(blf_mono_font == -1);
@@ -506,7 +510,7 @@ void uiStyleInit(void)
blf_mono_font = BLF_load_mono_default(unique);
}
- BLF_size(blf_mono_font, 12 * U.pixelsize, 72);
+ BLF_size(blf_mono_font, 12.0f * U.pixelsize, 72);
/* Set default flags based on UI preferences (not render fonts) */
{
@@ -551,7 +555,7 @@ void uiStyleInit(void)
blf_mono_font_render = BLF_load_mono_default(unique);
}
- BLF_size(blf_mono_font_render, 12 * U.pixelsize, 72);
+ BLF_size(blf_mono_font_render, 12.0f * U.pixelsize, 72);
}
void UI_fontstyle_set(const uiFontStyle *fs)
diff --git a/source/blender/editors/interface/interface_template_asset_view.cc b/source/blender/editors/interface/interface_template_asset_view.cc
index 0ce30fdeb1a..0a3cff5fa98 100644
--- a/source/blender/editors/interface/interface_template_asset_view.cc
+++ b/source/blender/editors/interface/interface_template_asset_view.cc
@@ -178,7 +178,7 @@ static void asset_view_template_refresh_asset_collection(
RNA_property_collection_clear(&assets_dataptr, assets_prop);
- ED_assetlist_iterate(&asset_library_ref, [&](AssetHandle asset) {
+ ED_assetlist_iterate(asset_library_ref, [&](AssetHandle asset) {
if (!ED_asset_filter_matches_asset(&filter_settings, &asset)) {
/* Don't do anything else, but return true to continue iterating. */
return true;
diff --git a/source/blender/editors/interface/interface_template_search_menu.c b/source/blender/editors/interface/interface_template_search_menu.cc
index 5877b4fe6d7..fe7660e4221 100644
--- a/source/blender/editors/interface/interface_template_search_menu.c
+++ b/source/blender/editors/interface/interface_template_search_menu.cc
@@ -21,8 +21,8 @@
* Accessed via the #WM_OT_search_menu operator.
*/
-#include <stdio.h>
-#include <string.h>
+#include <cstdio>
+#include <cstring>
#include "MEM_guardedalloc.h"
@@ -85,16 +85,16 @@ struct MenuSearch_Context {
};
struct MenuSearch_Parent {
- struct MenuSearch_Parent *parent;
+ MenuSearch_Parent *parent;
MenuType *parent_mt;
const char *drawstr;
/** Set while writing menu items only. */
- struct MenuSearch_Parent *temp_child;
+ MenuSearch_Parent *temp_child;
};
struct MenuSearch_Item {
- struct MenuSearch_Item *next, *prev;
+ MenuSearch_Item *next, *prev;
const char *drawstr;
const char *drawwstr_full;
/** Support a single level sub-menu nesting (for operator buttons that expand). */
@@ -102,12 +102,12 @@ struct MenuSearch_Item {
int icon;
int state;
- struct MenuSearch_Parent *menu_parent;
+ MenuSearch_Parent *menu_parent;
MenuType *mt;
- enum {
- MENU_SEARCH_TYPE_OP = 1,
- MENU_SEARCH_TYPE_RNA = 2,
+ enum Type {
+ Operator = 1,
+ RNA = 2,
} type;
union {
@@ -115,7 +115,7 @@ struct MenuSearch_Item {
struct {
wmOperatorType *type;
PointerRNA *opptr;
- short opcontext;
+ wmOperatorCallContext opcontext;
bContextStore *context;
} op;
@@ -129,8 +129,8 @@ struct MenuSearch_Item {
} rna;
};
- /** Set when we need each menu item to be able to set its own context. may be NULL. */
- struct MenuSearch_Context *wm_context;
+ /** Set when we need each menu item to be able to set its own context. may be nullptr. */
+ MenuSearch_Context *wm_context;
};
struct MenuSearch_Data {
@@ -148,15 +148,15 @@ struct MenuSearch_Data {
static int menu_item_sort_by_drawstr_full(const void *menu_item_a_v, const void *menu_item_b_v)
{
- const struct MenuSearch_Item *menu_item_a = menu_item_a_v;
- const struct MenuSearch_Item *menu_item_b = menu_item_b_v;
+ const MenuSearch_Item *menu_item_a = (MenuSearch_Item *)menu_item_a_v;
+ const MenuSearch_Item *menu_item_b = (MenuSearch_Item *)menu_item_b_v;
return strcmp(menu_item_a->drawwstr_full, menu_item_b->drawwstr_full);
}
static const char *strdup_memarena(MemArena *memarena, const char *str)
{
const uint str_size = strlen(str) + 1;
- char *str_dst = BLI_memarena_alloc(memarena, str_size);
+ char *str_dst = (char *)BLI_memarena_alloc(memarena, str_size);
memcpy(str_dst, str, str_size);
return str_dst;
}
@@ -164,50 +164,53 @@ static const char *strdup_memarena(MemArena *memarena, const char *str)
static const char *strdup_memarena_from_dynstr(MemArena *memarena, DynStr *dyn_str)
{
const uint str_size = BLI_dynstr_get_len(dyn_str) + 1;
- char *str_dst = BLI_memarena_alloc(memarena, str_size);
+ char *str_dst = (char *)BLI_memarena_alloc(memarena, str_size);
BLI_dynstr_get_cstring_ex(dyn_str, str_dst);
return str_dst;
}
-static bool menu_items_from_ui_create_item_from_button(struct MenuSearch_Data *data,
+static bool menu_items_from_ui_create_item_from_button(MenuSearch_Data *data,
MemArena *memarena,
struct MenuType *mt,
const char *drawstr_submenu,
uiBut *but,
- struct MenuSearch_Context *wm_context)
+ MenuSearch_Context *wm_context)
{
- struct MenuSearch_Item *item = NULL;
+ MenuSearch_Item *item = nullptr;
/* Use override if the name is empty, this can happen with popovers. */
- const char *drawstr_override = NULL;
+ const char *drawstr_override = nullptr;
const char *drawstr_sep = (but->flag & UI_BUT_HAS_SEP_CHAR) ?
strrchr(but->drawstr, UI_SEP_CHAR) :
- NULL;
+ nullptr;
const bool drawstr_is_empty = (drawstr_sep == but->drawstr) || (but->drawstr[0] == '\0');
- if (but->optype != NULL) {
+ if (but->optype != nullptr) {
if (drawstr_is_empty) {
drawstr_override = WM_operatortype_name(but->optype, but->opptr);
}
- item = BLI_memarena_calloc(memarena, sizeof(*item));
- item->type = MENU_SEARCH_TYPE_OP;
+ item = (MenuSearch_Item *)BLI_memarena_calloc(memarena, sizeof(*item));
+ item->type = MenuSearch_Item::Type::Operator;
item->op.type = but->optype;
item->op.opcontext = but->opcontext;
item->op.context = but->context;
item->op.opptr = but->opptr;
- but->opptr = NULL;
+ but->opptr = nullptr;
}
- else if (but->rnaprop != NULL) {
+ else if (but->rnaprop != nullptr) {
const int prop_type = RNA_property_type(but->rnaprop);
if (drawstr_is_empty) {
if (prop_type == PROP_ENUM) {
const int value_enum = (int)but->hardmax;
EnumPropertyItem enum_item;
- if (RNA_property_enum_item_from_value_gettexted(
- but->block->evil_C, &but->rnapoin, but->rnaprop, value_enum, &enum_item)) {
+ if (RNA_property_enum_item_from_value_gettexted((bContext *)but->block->evil_C,
+ &but->rnapoin,
+ but->rnaprop,
+ value_enum,
+ &enum_item)) {
drawstr_override = enum_item.name;
}
else {
@@ -229,8 +232,8 @@ static bool menu_items_from_ui_create_item_from_button(struct MenuSearch_Data *d
prop_type);
}
else {
- item = BLI_memarena_calloc(memarena, sizeof(*item));
- item->type = MENU_SEARCH_TYPE_RNA;
+ item = (MenuSearch_Item *)BLI_memarena_calloc(memarena, sizeof(*item));
+ item->type = MenuSearch_Item::Type::RNA;
item->rna.ptr = but->rnapoin;
item->rna.prop = but->rnaprop;
@@ -242,13 +245,12 @@ static bool menu_items_from_ui_create_item_from_button(struct MenuSearch_Data *d
}
}
- if (item != NULL) {
+ if (item != nullptr) {
/* Handle shared settings. */
- if (drawstr_override != NULL) {
+ if (drawstr_override != nullptr) {
const char *drawstr_suffix = drawstr_sep ? drawstr_sep : "";
- char *drawstr_alloc = BLI_string_joinN("(", drawstr_override, ")", drawstr_suffix);
- item->drawstr = strdup_memarena(memarena, drawstr_alloc);
- MEM_freeN(drawstr_alloc);
+ std::string drawstr = std::string("(") + drawstr_override + ")" + drawstr_suffix;
+ item->drawstr = strdup_memarena(memarena, drawstr.c_str());
}
else {
item->drawstr = strdup_memarena(memarena, but->drawstr);
@@ -258,7 +260,7 @@ static bool menu_items_from_ui_create_item_from_button(struct MenuSearch_Data *d
item->state = (but->flag &
(UI_BUT_DISABLED | UI_BUT_INACTIVE | UI_BUT_REDALERT | UI_BUT_HAS_SEP_CHAR));
item->mt = mt;
- item->drawstr_submenu = drawstr_submenu ? strdup_memarena(memarena, drawstr_submenu) : NULL;
+ item->drawstr_submenu = drawstr_submenu ? strdup_memarena(memarena, drawstr_submenu) : nullptr;
item->wm_context = wm_context;
@@ -272,11 +274,11 @@ static bool menu_items_from_ui_create_item_from_button(struct MenuSearch_Data *d
/**
* Populate a fake button from a menu item (use for context menu).
*/
-static bool menu_items_to_ui_button(struct MenuSearch_Item *item, uiBut *but)
+static bool menu_items_to_ui_button(MenuSearch_Item *item, uiBut *but)
{
bool changed = false;
switch (item->type) {
- case MENU_SEARCH_TYPE_OP: {
+ case MenuSearch_Item::Type::Operator: {
but->optype = item->op.type;
but->opcontext = item->op.opcontext;
but->context = item->op.context;
@@ -284,7 +286,7 @@ static bool menu_items_to_ui_button(struct MenuSearch_Item *item, uiBut *but)
changed = true;
break;
}
- case MENU_SEARCH_TYPE_RNA: {
+ case MenuSearch_Item::Type::RNA: {
const int prop_type = RNA_property_type(item->rna.prop);
but->rnapoin = item->rna.ptr;
@@ -302,12 +304,12 @@ static bool menu_items_to_ui_button(struct MenuSearch_Item *item, uiBut *but)
if (changed) {
STRNCPY(but->drawstr, item->drawstr);
char *drawstr_sep = (item->state & UI_BUT_HAS_SEP_CHAR) ? strrchr(but->drawstr, UI_SEP_CHAR) :
- NULL;
+ nullptr;
if (drawstr_sep) {
*drawstr_sep = '\0';
}
- but->icon = item->icon;
+ but->icon = (BIFIconID)item->icon;
but->str = but->strdata;
}
@@ -327,13 +329,13 @@ static void menu_types_add_from_keymap_items(bContext *C,
{
wmWindowManager *wm = CTX_wm_manager(C);
ListBase *handlers[] = {
- region ? &region->handlers : NULL,
- area ? &area->handlers : NULL,
+ region ? &region->handlers : nullptr,
+ area ? &area->handlers : nullptr,
&win->handlers,
};
for (int handler_index = 0; handler_index < ARRAY_SIZE(handlers); handler_index++) {
- if (handlers[handler_index] == NULL) {
+ if (handlers[handler_index] == nullptr) {
continue;
}
LISTBASE_FOREACH (wmEventHandler *, handler_base, handlers[handler_index]) {
@@ -345,7 +347,7 @@ static void menu_types_add_from_keymap_items(bContext *C,
continue;
}
- if (handler_base->poll == NULL || handler_base->poll(region, win->eventstate)) {
+ if (handler_base->poll == nullptr || handler_base->poll(region, win->eventstate)) {
wmEventHandler_Keymap *handler = (wmEventHandler_Keymap *)handler_base;
wmEventHandler_KeymapResult km_result;
WM_event_get_keymaps_from_handler(wm, win, handler, &km_result);
@@ -382,16 +384,16 @@ static void menu_types_add_from_keymap_items(bContext *C,
/**
* Display all operators (last). Developer-only convenience feature.
*/
-static void menu_items_from_all_operators(bContext *C, struct MenuSearch_Data *data)
+static void menu_items_from_all_operators(bContext *C, MenuSearch_Data *data)
{
/* Add to temporary list so we can sort them separately. */
- ListBase operator_items = {NULL, NULL};
+ ListBase operator_items = {nullptr, nullptr};
MemArena *memarena = data->memarena;
GHashIterator iter;
for (WM_operatortype_iter(&iter); !BLI_ghashIterator_done(&iter);
BLI_ghashIterator_step(&iter)) {
- wmOperatorType *ot = BLI_ghashIterator_getValue(&iter);
+ wmOperatorType *ot = (wmOperatorType *)BLI_ghashIterator_getValue(&iter);
if ((ot->flag & OPTYPE_INTERNAL) && (G.debug & G_DEBUG_WM) == 0) {
continue;
@@ -400,13 +402,13 @@ static void menu_items_from_all_operators(bContext *C, struct MenuSearch_Data *d
if (WM_operator_poll((bContext *)C, ot)) {
const char *ot_ui_name = CTX_IFACE_(ot->translation_context, ot->name);
- struct MenuSearch_Item *item = NULL;
- item = BLI_memarena_calloc(memarena, sizeof(*item));
- item->type = MENU_SEARCH_TYPE_OP;
+ MenuSearch_Item *item = nullptr;
+ item = (MenuSearch_Item *)BLI_memarena_calloc(memarena, sizeof(*item));
+ item->type = MenuSearch_Item::Type::Operator;
item->op.type = ot;
item->op.opcontext = WM_OP_INVOKE_DEFAULT;
- item->op.context = NULL;
+ item->op.context = nullptr;
char idname_as_py[OP_MAX_TYPENAME];
char uiname[256];
@@ -417,7 +419,7 @@ static void menu_items_from_all_operators(bContext *C, struct MenuSearch_Data *d
item->drawwstr_full = strdup_memarena(memarena, uiname);
item->drawstr = ot_ui_name;
- item->wm_context = NULL;
+ item->wm_context = nullptr;
BLI_addtail(&operator_items, item);
}
@@ -434,7 +436,7 @@ static void menu_items_from_all_operators(bContext *C, struct MenuSearch_Data *d
* - Look up predefined editor-menus.
* - Look up key-map items which call menus.
*/
-static struct MenuSearch_Data *menu_items_from_ui_create(
+static MenuSearch_Data *menu_items_from_ui_create(
bContext *C, wmWindow *win, ScrArea *area_init, ARegion *region_init, bool include_all_areas)
{
MemArena *memarena = BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE, __func__);
@@ -444,12 +446,12 @@ static struct MenuSearch_Data *menu_items_from_ui_create(
const uiStyle *style = UI_style_get_dpi();
/* Convert into non-ui structure. */
- struct MenuSearch_Data *data = MEM_callocN(sizeof(*data), __func__);
+ MenuSearch_Data *data = (MenuSearch_Data *)MEM_callocN(sizeof(*data), __func__);
DynStr *dyn_str = BLI_dynstr_new_memarena();
/* Use a stack of menus to handle and discover new menus in passes. */
- LinkNode *menu_stack = NULL;
+ LinkNode *menu_stack = nullptr;
/* Tag menu types not to add, either because they have already been added
* or they have been blacklisted.
@@ -466,7 +468,7 @@ static struct MenuSearch_Data *menu_items_from_ui_create(
};
for (int i = 0; i < ARRAY_SIZE(idname_array); i++) {
MenuType *mt = WM_menutype_find(idname_array[i], false);
- if (mt != NULL) {
+ if (mt != nullptr) {
BLI_gset_add(menu_tagged, mt);
}
}
@@ -483,7 +485,7 @@ static struct MenuSearch_Data *menu_items_from_ui_create(
for (WM_menutype_iter(&iter); (!BLI_ghashIterator_done(&iter));
(BLI_ghashIterator_step(&iter))) {
- MenuType *mt = BLI_ghashIterator_getValue(&iter);
+ MenuType *mt = (MenuType *)BLI_ghashIterator_getValue(&iter);
if (BLI_str_endswith(mt->idname, "_context_menu")) {
BLI_gset_add(menu_tagged, mt);
}
@@ -494,34 +496,33 @@ static struct MenuSearch_Data *menu_items_from_ui_create(
};
for (int i = 0; i < ARRAY_SIZE(idname_array); i++) {
MenuType *mt = WM_menutype_find(idname_array[i], false);
- if (mt != NULL) {
- BLI_gset_remove(menu_tagged, mt, NULL);
+ if (mt != nullptr) {
+ BLI_gset_remove(menu_tagged, mt, nullptr);
}
}
}
/* Collect contexts, one for each 'ui_type'. */
- struct MenuSearch_Context *wm_contexts = NULL;
+ MenuSearch_Context *wm_contexts = nullptr;
- const EnumPropertyItem *space_type_ui_items = NULL;
+ const EnumPropertyItem *space_type_ui_items = nullptr;
int space_type_ui_items_len = 0;
bool space_type_ui_items_free = false;
/* Text used as prefix for top-bar menu items. */
- const char *global_menu_prefix = NULL;
+ const char *global_menu_prefix = nullptr;
if (include_all_areas) {
bScreen *screen = WM_window_get_active_screen(win);
/* First create arrays for ui_type. */
- PropertyRNA *prop_ui_type = NULL;
+ PropertyRNA *prop_ui_type = nullptr;
{
/* This must be a valid pointer, with only it's type checked. */
- ScrArea area_dummy = {
- /* Anything besides #SPACE_EMPTY is fine,
- * as this value is only included in the enum when set. */
- .spacetype = SPACE_TOPBAR,
- };
+ ScrArea area_dummy = {nullptr};
+ /* Anything besides #SPACE_EMPTY is fine,
+ * as this value is only included in the enum when set. */
+ area_dummy.spacetype = SPACE_TOPBAR;
PointerRNA ptr;
RNA_pointer_create(&screen->id, &RNA_Area, &area_dummy, &ptr);
prop_ui_type = RNA_struct_find_property(&ptr, "ui_type");
@@ -532,7 +533,8 @@ static struct MenuSearch_Data *menu_items_from_ui_create(
&space_type_ui_items_len,
&space_type_ui_items_free);
- wm_contexts = BLI_memarena_calloc(memarena, sizeof(*wm_contexts) * space_type_ui_items_len);
+ wm_contexts = (MenuSearch_Context *)BLI_memarena_calloc(
+ memarena, sizeof(*wm_contexts) * space_type_ui_items_len);
for (int i = 0; i < space_type_ui_items_len; i++) {
wm_contexts[i].space_type_ui_index = -1;
}
@@ -540,7 +542,7 @@ static struct MenuSearch_Data *menu_items_from_ui_create(
LISTBASE_FOREACH (ScrArea *, area, &screen->areabase) {
ARegion *region = BKE_area_find_region_type(area, RGN_TYPE_WINDOW);
- if (region != NULL) {
+ if (region != nullptr) {
PointerRNA ptr;
RNA_pointer_create(&screen->id, &RNA_Area, area, &ptr);
const int space_type_ui = RNA_property_enum_get(&ptr, prop_ui_type);
@@ -573,16 +575,16 @@ static struct MenuSearch_Data *menu_items_from_ui_create(
for (int space_type_ui_index = -1; space_type_ui_index < space_type_ui_items_len;
space_type_ui_index += 1) {
- ScrArea *area = NULL;
- ARegion *region = NULL;
- struct MenuSearch_Context *wm_context = NULL;
+ ScrArea *area = nullptr;
+ ARegion *region = nullptr;
+ MenuSearch_Context *wm_context = nullptr;
if (include_all_areas) {
if (space_type_ui_index == -1) {
/* First run without any context, to populate the top-bar without. */
- wm_context = NULL;
- area = NULL;
- region = NULL;
+ wm_context = nullptr;
+ area = nullptr;
+ region = nullptr;
}
else {
wm_context = &wm_contexts[space_type_ui_index];
@@ -607,7 +609,7 @@ static struct MenuSearch_Data *menu_items_from_ui_create(
* from the buttons, however this is quite involved and can be avoided as by convention
* each space-type has a single root-menu that headers use. */
{
- const char *idname_array[2] = {NULL};
+ const char *idname_array[2] = {nullptr};
int idname_array_len = 0;
/* Use negative for global (no area) context, populate the top-bar. */
@@ -623,8 +625,8 @@ static struct MenuSearch_Data *menu_items_from_ui_create(
case space_type: \
break
- if (area != NULL) {
- SpaceLink *sl = area->spacedata.first;
+ if (area != nullptr) {
+ SpaceLink *sl = (SpaceLink *)area->spacedata.first;
switch ((eSpace_Type)area->spacetype) {
SPACE_MENU_MAP(SPACE_VIEW3D, "VIEW3D_MT_editor_menus");
SPACE_MENU_MAP(SPACE_GRAPH, "GRAPH_MT_editor_menus");
@@ -656,7 +658,7 @@ static struct MenuSearch_Data *menu_items_from_ui_create(
}
for (int i = 0; i < idname_array_len; i++) {
MenuType *mt = WM_menutype_find(idname_array[i], false);
- if (mt != NULL) {
+ if (mt != nullptr) {
/* Check if this exists because of 'include_all_areas'. */
if (BLI_gset_add(menu_tagged, mt)) {
BLI_linklist_prepend(&menu_stack, mt);
@@ -669,8 +671,8 @@ static struct MenuSearch_Data *menu_items_from_ui_create(
bool has_keymap_menu_items = false;
- while (menu_stack != NULL) {
- MenuType *mt = BLI_linklist_pop(&menu_stack);
+ while (menu_stack != nullptr) {
+ MenuType *mt = (MenuType *)BLI_linklist_pop(&menu_stack);
if (!WM_menutype_poll(C, mt)) {
continue;
}
@@ -687,7 +689,7 @@ static struct MenuSearch_Data *menu_items_from_ui_create(
UI_block_end(C, block);
LISTBASE_FOREACH (uiBut *, but, &block->buttons) {
- MenuType *mt_from_but = NULL;
+ MenuType *mt_from_but = nullptr;
/* Support menu titles with dynamic from initial labels
* (used by edit-mesh context menu). */
if (but->type == UI_BTYPE_LABEL) {
@@ -698,13 +700,13 @@ static struct MenuSearch_Data *menu_items_from_ui_create(
but_test = but_test->prev;
}
- if (but_test == NULL) {
+ if (but_test == nullptr) {
BLI_ghash_insert(
menu_display_name_map, mt, (void *)strdup_memarena(memarena, but->drawstr));
}
}
else if (menu_items_from_ui_create_item_from_button(
- data, memarena, mt, NULL, but, wm_context)) {
+ data, memarena, mt, nullptr, but, wm_context)) {
/* pass */
}
else if ((mt_from_but = UI_but_menutype_get(but))) {
@@ -714,8 +716,8 @@ static struct MenuSearch_Data *menu_items_from_ui_create(
}
if (!BLI_ghash_haskey(menu_parent_map, mt_from_but)) {
- struct MenuSearch_Parent *menu_parent = BLI_memarena_calloc(memarena,
- sizeof(*menu_parent));
+ MenuSearch_Parent *menu_parent = (MenuSearch_Parent *)BLI_memarena_calloc(
+ memarena, sizeof(*menu_parent));
/* Use brackets for menu key shortcuts,
* converting "Text|Some-Shortcut" to "Text (Some-Shortcut)".
* This is needed so we don't right align sub-menu contents
@@ -723,9 +725,9 @@ static struct MenuSearch_Data *menu_items_from_ui_create(
*/
const char *drawstr_sep = but->flag & UI_BUT_HAS_SEP_CHAR ?
strrchr(but->drawstr, UI_SEP_CHAR) :
- NULL;
+ nullptr;
bool drawstr_is_empty = false;
- if (drawstr_sep != NULL) {
+ if (drawstr_sep != nullptr) {
BLI_assert(BLI_dynstr_get_len(dyn_str) == 0);
/* Detect empty string, fallback to menu name. */
const char *drawstr = but->drawstr;
@@ -760,7 +762,7 @@ static struct MenuSearch_Data *menu_items_from_ui_create(
}
}
}
- else if (but->menu_create_func != NULL) {
+ else if (but->menu_create_func != nullptr) {
/* A non 'MenuType' menu button. */
/* Only expand one level deep, this is mainly for expanding operator menus. */
@@ -785,19 +787,21 @@ static struct MenuSearch_Data *menu_items_from_ui_create(
}
if (region) {
+ BLI_ghash_remove(region->runtime.block_name_map, sub_block->name, nullptr, nullptr);
BLI_remlink(&region->uiblocks, sub_block);
}
- UI_block_free(NULL, sub_block);
+ UI_block_free(nullptr, sub_block);
}
}
if (region) {
+ BLI_ghash_remove(region->runtime.block_name_map, block->name, nullptr, nullptr);
BLI_remlink(&region->uiblocks, block);
}
- UI_block_free(NULL, block);
+ UI_block_free(nullptr, block);
/* Add key-map items as a second pass,
* so all menus are accessed from the header & top-bar before key shortcuts are expanded. */
- if ((menu_stack == NULL) && (has_keymap_menu_items == false)) {
+ if ((menu_stack == nullptr) && (has_keymap_menu_items == false)) {
has_keymap_menu_items = true;
menu_types_add_from_keymap_items(
C, win, area, region, &menu_stack, menu_to_kmi, menu_tagged);
@@ -805,33 +809,34 @@ static struct MenuSearch_Data *menu_items_from_ui_create(
}
}
- LISTBASE_FOREACH (struct MenuSearch_Item *, item, &data->items) {
- item->menu_parent = BLI_ghash_lookup(menu_parent_map, item->mt);
+ LISTBASE_FOREACH (MenuSearch_Item *, item, &data->items) {
+ item->menu_parent = (MenuSearch_Parent *)BLI_ghash_lookup(menu_parent_map, item->mt);
}
GHASH_ITER (iter, menu_parent_map) {
- struct MenuSearch_Parent *menu_parent = BLI_ghashIterator_getValue(&iter);
- menu_parent->parent = BLI_ghash_lookup(menu_parent_map, menu_parent->parent_mt);
+ MenuSearch_Parent *menu_parent = (MenuSearch_Parent *)BLI_ghashIterator_getValue(&iter);
+ menu_parent->parent = (MenuSearch_Parent *)BLI_ghash_lookup(menu_parent_map,
+ menu_parent->parent_mt);
}
/* NOTE: currently this builds the full path for each menu item,
* that could be moved into the parent menu. */
/* Set names as full paths. */
- LISTBASE_FOREACH (struct MenuSearch_Item *, item, &data->items) {
+ LISTBASE_FOREACH (MenuSearch_Item *, item, &data->items) {
BLI_assert(BLI_dynstr_get_len(dyn_str) == 0);
if (include_all_areas) {
BLI_dynstr_appendf(dyn_str,
"%s: ",
- (item->wm_context != NULL) ?
+ (item->wm_context != nullptr) ?
space_type_ui_items[item->wm_context->space_type_ui_index].name :
global_menu_prefix);
}
- if (item->menu_parent != NULL) {
- struct MenuSearch_Parent *menu_parent = item->menu_parent;
- menu_parent->temp_child = NULL;
+ if (item->menu_parent != nullptr) {
+ MenuSearch_Parent *menu_parent = item->menu_parent;
+ menu_parent->temp_child = nullptr;
while (menu_parent && menu_parent->parent) {
menu_parent->parent->temp_child = menu_parent;
menu_parent = menu_parent->parent;
@@ -843,14 +848,14 @@ static struct MenuSearch_Data *menu_items_from_ui_create(
}
}
else {
- const char *drawstr = BLI_ghash_lookup(menu_display_name_map, item->mt);
- if (drawstr == NULL) {
+ const char *drawstr = (const char *)BLI_ghash_lookup(menu_display_name_map, item->mt);
+ if (drawstr == nullptr) {
drawstr = CTX_IFACE_(item->mt->translation_context, item->mt->label);
}
BLI_dynstr_append(dyn_str, drawstr);
- wmKeyMapItem *kmi = BLI_ghash_lookup(menu_to_kmi, item->mt);
- if (kmi != NULL) {
+ wmKeyMapItem *kmi = (wmKeyMapItem *)BLI_ghash_lookup(menu_to_kmi, item->mt);
+ if (kmi != nullptr) {
char kmi_str[128];
WM_keymap_item_to_string(kmi, false, kmi_str, sizeof(kmi_str));
BLI_dynstr_appendf(dyn_str, " (%s)", kmi_str);
@@ -860,7 +865,7 @@ static struct MenuSearch_Data *menu_items_from_ui_create(
}
/* Optional nested menu. */
- if (item->drawstr_submenu != NULL) {
+ if (item->drawstr_submenu != nullptr) {
BLI_dynstr_append(dyn_str, item->drawstr_submenu);
BLI_dynstr_append(dyn_str, " " UI_MENU_ARROW_SEP " ");
}
@@ -877,12 +882,12 @@ static struct MenuSearch_Data *menu_items_from_ui_create(
* NOTE: we might want to keep the in-menu order, for now sort all. */
BLI_listbase_sort(&data->items, menu_item_sort_by_drawstr_full);
- BLI_ghash_free(menu_parent_map, NULL, NULL);
- BLI_ghash_free(menu_display_name_map, NULL, NULL);
+ BLI_ghash_free(menu_parent_map, nullptr, nullptr);
+ BLI_ghash_free(menu_display_name_map, nullptr, nullptr);
- BLI_ghash_free(menu_to_kmi, NULL, NULL);
+ BLI_ghash_free(menu_to_kmi, nullptr, nullptr);
- BLI_gset_free(menu_tagged, NULL);
+ BLI_gset_free(menu_tagged, nullptr);
data->memarena = memarena;
@@ -915,16 +920,16 @@ static struct MenuSearch_Data *menu_items_from_ui_create(
static void menu_search_arg_free_fn(void *data_v)
{
- struct MenuSearch_Data *data = data_v;
- LISTBASE_FOREACH (struct MenuSearch_Item *, item, &data->items) {
+ MenuSearch_Data *data = (MenuSearch_Data *)data_v;
+ LISTBASE_FOREACH (MenuSearch_Item *, item, &data->items) {
switch (item->type) {
- case MENU_SEARCH_TYPE_OP: {
- if (item->op.opptr != NULL) {
+ case MenuSearch_Item::Type::Operator: {
+ if (item->op.opptr != nullptr) {
WM_operator_properties_free(item->op.opptr);
MEM_freeN(item->op.opptr);
}
}
- case MENU_SEARCH_TYPE_RNA: {
+ case MenuSearch_Item::Type::RNA: {
break;
}
}
@@ -937,8 +942,8 @@ static void menu_search_arg_free_fn(void *data_v)
static void menu_search_exec_fn(bContext *C, void *UNUSED(arg1), void *arg2)
{
- struct MenuSearch_Item *item = arg2;
- if (item == NULL) {
+ MenuSearch_Item *item = (MenuSearch_Item *)arg2;
+ if (item == nullptr) {
return;
}
if (item->state & UI_BUT_DISABLED) {
@@ -948,20 +953,20 @@ static void menu_search_exec_fn(bContext *C, void *UNUSED(arg1), void *arg2)
ScrArea *area_prev = CTX_wm_area(C);
ARegion *region_prev = CTX_wm_region(C);
- if (item->wm_context != NULL) {
+ if (item->wm_context != nullptr) {
CTX_wm_area_set(C, item->wm_context->area);
CTX_wm_region_set(C, item->wm_context->region);
}
switch (item->type) {
- case MENU_SEARCH_TYPE_OP: {
+ case MenuSearch_Item::Type::Operator: {
CTX_store_set(C, item->op.context);
WM_operator_name_call_ptr_with_depends_on_cursor(
C, item->op.type, item->op.opcontext, item->op.opptr, item->drawstr);
- CTX_store_set(C, NULL);
+ CTX_store_set(C, nullptr);
break;
}
- case MENU_SEARCH_TYPE_RNA: {
+ case MenuSearch_Item::Type::RNA: {
PointerRNA *ptr = &item->rna.ptr;
PropertyRNA *prop = item->rna.prop;
const int index = item->rna.index;
@@ -992,7 +997,7 @@ static void menu_search_exec_fn(bContext *C, void *UNUSED(arg1), void *arg2)
}
}
- if (item->wm_context != NULL) {
+ if (item->wm_context != nullptr) {
CTX_wm_area_set(C, area_prev);
CTX_wm_region_set(C, region_prev);
}
@@ -1004,19 +1009,19 @@ static void menu_search_update_fn(const bContext *UNUSED(C),
uiSearchItems *items,
const bool UNUSED(is_first))
{
- struct MenuSearch_Data *data = arg;
+ MenuSearch_Data *data = (MenuSearch_Data *)arg;
StringSearch *search = BLI_string_search_new();
- LISTBASE_FOREACH (struct MenuSearch_Item *, item, &data->items) {
+ LISTBASE_FOREACH (MenuSearch_Item *, item, &data->items) {
BLI_string_search_add(search, item->drawwstr_full, item);
}
- struct MenuSearch_Item **filtered_items;
+ MenuSearch_Item **filtered_items;
const int filtered_amount = BLI_string_search_query(search, str, (void ***)&filtered_items);
for (int i = 0; i < filtered_amount; i++) {
- struct MenuSearch_Item *item = filtered_items[i];
+ MenuSearch_Item *item = filtered_items[i];
if (!UI_search_item_add(items, item->drawwstr_full, item, item->icon, item->state, 0)) {
break;
}
@@ -1041,8 +1046,8 @@ static bool ui_search_menu_create_context_menu(struct bContext *C,
void *active,
const struct wmEvent *event)
{
- struct MenuSearch_Data *data = arg;
- struct MenuSearch_Item *item = active;
+ MenuSearch_Data *data = (MenuSearch_Data *)arg;
+ MenuSearch_Item *item = (MenuSearch_Item *)active;
bool has_menu = false;
memset(&data->context_menu_data, 0x0, sizeof(data->context_menu_data));
@@ -1055,7 +1060,7 @@ static bool ui_search_menu_create_context_menu(struct bContext *C,
ScrArea *area_prev = CTX_wm_area(C);
ARegion *region_prev = CTX_wm_region(C);
- if (item->wm_context != NULL) {
+ if (item->wm_context != nullptr) {
CTX_wm_area_set(C, item->wm_context->area);
CTX_wm_region_set(C, item->wm_context->region);
}
@@ -1064,7 +1069,7 @@ static bool ui_search_menu_create_context_menu(struct bContext *C,
has_menu = true;
}
- if (item->wm_context != NULL) {
+ if (item->wm_context != nullptr) {
CTX_wm_area_set(C, area_prev);
CTX_wm_region_set(C, region_prev);
}
@@ -1085,8 +1090,8 @@ static struct ARegion *ui_search_menu_create_tooltip(struct bContext *C,
void *arg,
void *active)
{
- struct MenuSearch_Data *data = arg;
- struct MenuSearch_Item *item = active;
+ MenuSearch_Data *data = (MenuSearch_Data *)arg;
+ MenuSearch_Item *item = (MenuSearch_Item *)active;
memset(&data->context_menu_data, 0x0, sizeof(data->context_menu_data));
uiBut *but = &data->context_menu_data.but;
@@ -1112,21 +1117,21 @@ static struct ARegion *ui_search_menu_create_tooltip(struct bContext *C,
ScrArea *area_prev = CTX_wm_area(C);
ARegion *region_prev = CTX_wm_region(C);
- if (item->wm_context != NULL) {
+ if (item->wm_context != nullptr) {
CTX_wm_area_set(C, item->wm_context->area);
CTX_wm_region_set(C, item->wm_context->region);
}
ARegion *region_tip = UI_tooltip_create_from_button(C, region, but, false);
- if (item->wm_context != NULL) {
+ if (item->wm_context != nullptr) {
CTX_wm_area_set(C, area_prev);
CTX_wm_region_set(C, region_prev);
}
return region_tip;
}
- return NULL;
+ return nullptr;
}
/** \} */
@@ -1137,14 +1142,13 @@ static struct ARegion *ui_search_menu_create_tooltip(struct bContext *C,
void UI_but_func_menu_search(uiBut *but)
{
- bContext *C = but->block->evil_C;
+ bContext *C = (bContext *)but->block->evil_C;
wmWindow *win = CTX_wm_window(C);
ScrArea *area = CTX_wm_area(C);
ARegion *region = CTX_wm_region(C);
/* When run from top-bar scan all areas in the current window. */
const bool include_all_areas = (area && (area->spacetype == SPACE_TOPBAR));
- struct MenuSearch_Data *data = menu_items_from_ui_create(
- C, win, area, region, include_all_areas);
+ MenuSearch_Data *data = menu_items_from_ui_create(C, win, area, region, include_all_areas);
UI_but_func_search_set(but,
/* Generic callback. */
ui_searchbox_create_menu,
@@ -1153,7 +1157,7 @@ void UI_but_func_menu_search(uiBut *but)
false,
menu_search_arg_free_fn,
menu_search_exec_fn,
- NULL);
+ nullptr);
UI_but_func_search_set_context_menu(but, ui_search_menu_create_context_menu);
UI_but_func_search_set_tooltip(but, ui_search_menu_create_tooltip);
diff --git a/source/blender/editors/interface/interface_templates.c b/source/blender/editors/interface/interface_templates.c
index ac2f1bc090c..cbd57176a31 100644
--- a/source/blender/editors/interface/interface_templates.c
+++ b/source/blender/editors/interface/interface_templates.c
@@ -1741,7 +1741,7 @@ static void template_search_add_button_name(uiBlock *block,
static void template_search_add_button_operator(uiBlock *block,
const char *const operator_name,
- const int opcontext,
+ const wmOperatorCallContext opcontext,
const int icon,
const bool editable)
{
diff --git a/source/blender/editors/interface/interface_widgets.c b/source/blender/editors/interface/interface_widgets.c
index 7d1b7b80ccd..784f87d36c1 100644
--- a/source/blender/editors/interface/interface_widgets.c
+++ b/source/blender/editors/interface/interface_widgets.c
@@ -114,7 +114,6 @@ typedef enum {
UI_WTYPE_LISTITEM,
UI_WTYPE_PROGRESSBAR,
UI_WTYPE_NODESOCKET,
- UI_WTYPE_DATASETROW,
UI_WTYPE_TREEROW,
} uiWidgetTypeEnum;
@@ -3675,13 +3674,7 @@ static void widget_treerow(
widget_treerow_exec(wcol, rect, state, roundboxalign, tree_row->indentation);
}
-static void widget_datasetrow(
- uiBut *but, uiWidgetColors *wcol, rcti *rect, int state, int roundboxalign)
-{
- uiButDatasetRow *dataset_row = (uiButDatasetRow *)but;
- BLI_assert(but->type == UI_BTYPE_DATASETROW);
- widget_treerow_exec(wcol, rect, state, roundboxalign, dataset_row->indentation);
-}
+
static void widget_nodesocket(
uiBut *but, uiWidgetColors *wcol, rcti *rect, int UNUSED(state), int UNUSED(roundboxalign))
@@ -4476,9 +4469,6 @@ static uiWidgetType *widget_type(uiWidgetTypeEnum type)
wt.custom = widget_progressbar;
break;
- case UI_WTYPE_DATASETROW:
- wt.custom = widget_datasetrow;
- break;
case UI_WTYPE_TREEROW:
wt.custom = widget_treerow;
@@ -4811,11 +4801,6 @@ void ui_draw_but(const bContext *C, struct ARegion *region, uiStyle *style, uiBu
fstyle = &style->widgetlabel;
break;
- case UI_BTYPE_DATASETROW:
- wt = widget_type(UI_WTYPE_DATASETROW);
- fstyle = &style->widgetlabel;
- break;
-
case UI_BTYPE_TREEROW:
wt = widget_type(UI_WTYPE_TREEROW);
fstyle = &style->widgetlabel;
diff --git a/source/blender/editors/interface/tree_view.cc b/source/blender/editors/interface/tree_view.cc
index fcc878c440c..5fcf78dd565 100644
--- a/source/blender/editors/interface/tree_view.cc
+++ b/source/blender/editors/interface/tree_view.cc
@@ -111,7 +111,10 @@ void AbstractTreeView::update_from_old(uiBlock &new_block)
uiTreeViewHandle *old_view_handle = ui_block_view_find_matching_in_old_block(
&new_block, reinterpret_cast<uiTreeViewHandle *>(this));
- BLI_assert(old_view_handle);
+ if (old_view_handle == nullptr) {
+ is_reconstructed_ = true;
+ return;
+ }
AbstractTreeView &old_view = reinterpret_cast<AbstractTreeView &>(*old_view_handle);
@@ -350,9 +353,14 @@ void AbstractTreeViewItem::on_activate()
/* Do nothing by default. */
}
-void AbstractTreeViewItem::is_active(IsActiveFn is_active_fn)
+std::optional<bool> AbstractTreeViewItem::should_be_active() const
{
- is_active_fn_ = is_active_fn;
+ return std::nullopt;
+}
+
+bool AbstractTreeViewItem::supports_collapsing() const
+{
+ return true;
}
std::unique_ptr<AbstractTreeViewItemDragController> AbstractTreeViewItem::create_drag_controller()
@@ -504,7 +512,10 @@ void AbstractTreeViewItem::set_collapsed(bool collapsed)
bool AbstractTreeViewItem::is_collapsible() const
{
- return !children_.is_empty();
+ if (children_.is_empty()) {
+ return false;
+ }
+ return this->supports_collapsing();
}
bool AbstractTreeViewItem::is_renaming() const
@@ -546,7 +557,8 @@ uiButTreeRow *AbstractTreeViewItem::tree_row_button()
void AbstractTreeViewItem::change_state_delayed()
{
- if (is_active_fn_()) {
+ const std::optional<bool> should_be_active = this->should_be_active();
+ if (should_be_active.has_value() && *should_be_active) {
activate();
}
}
@@ -670,11 +682,24 @@ void BasicTreeViewItem::on_activate()
}
}
-void BasicTreeViewItem::on_activate(ActivateFn fn)
+void BasicTreeViewItem::set_on_activate_fn(ActivateFn fn)
{
activate_fn_ = fn;
}
+void BasicTreeViewItem::set_is_active_fn(IsActiveFn is_active_fn)
+{
+ is_active_fn_ = is_active_fn;
+}
+
+std::optional<bool> BasicTreeViewItem::should_be_active() const
+{
+ if (is_active_fn_) {
+ return is_active_fn_();
+ }
+ return std::nullopt;
+}
+
} // namespace blender::ui
using namespace blender::ui;
diff --git a/source/blender/editors/io/io_gpencil_export.c b/source/blender/editors/io/io_gpencil_export.c
index b49be324372..556fae70828 100644
--- a/source/blender/editors/io/io_gpencil_export.c
+++ b/source/blender/editors/io/io_gpencil_export.c
@@ -410,6 +410,7 @@ void WM_OT_gpencil_export_pdf(wmOperatorType *ot)
static const EnumPropertyItem gpencil_export_frame_items[] = {
{GP_EXPORT_FRAME_ACTIVE, "ACTIVE", 0, "Active", "Include only active frame"},
{GP_EXPORT_FRAME_SELECTED, "SELECTED", 0, "Selected", "Include selected frames"},
+ {GP_EXPORT_FRAME_SCENE, "SCENE", 0, "Scene", "Include all scene frames"},
{0, NULL, 0, NULL, NULL},
};
diff --git a/source/blender/editors/mesh/editmesh_extrude.c b/source/blender/editors/mesh/editmesh_extrude.c
index e4cd48d95bb..912399c25b3 100644
--- a/source/blender/editors/mesh/editmesh_extrude.c
+++ b/source/blender/editors/mesh/editmesh_extrude.c
@@ -821,8 +821,8 @@ static int edbm_dupli_extrude_cursor_invoke(bContext *C, wmOperator *op, const w
float view_vec[3], cross[3];
/* convert the 2D normal into 3D */
- mul_mat3_m4_v3(vc.rv3d->viewinv, nor); /* worldspace */
- mul_mat3_m4_v3(vc.obedit->imat, nor); /* local space */
+ mul_mat3_m4_v3(vc.rv3d->viewinv, nor); /* World-space. */
+ mul_mat3_m4_v3(vc.obedit->imat, nor); /* Local-space. */
/* correct the normal to be aligned on the view plane */
mul_v3_mat3_m4v3(view_vec, vc.obedit->imat, vc.rv3d->viewinv[2]);
diff --git a/source/blender/editors/mesh/editmesh_extrude_spin.c b/source/blender/editors/mesh/editmesh_extrude_spin.c
index 2146207308c..d7eaf58653f 100644
--- a/source/blender/editors/mesh/editmesh_extrude_spin.c
+++ b/source/blender/editors/mesh/editmesh_extrude_spin.c
@@ -80,7 +80,7 @@ static int edbm_spin_exec(bContext *C, wmOperator *op)
BMesh *bm = em->bm;
BMOperator spinop;
- /* keep the values in worldspace since we're passing the obmat */
+ /* Keep the values in world-space since we're passing the `obmat`. */
if (!EDBM_op_init(em,
&spinop,
op,
diff --git a/source/blender/editors/mesh/editmesh_intersect.c b/source/blender/editors/mesh/editmesh_intersect.c
index ee227c58fe7..18fe9cf7ad3 100644
--- a/source/blender/editors/mesh/editmesh_intersect.c
+++ b/source/blender/editors/mesh/editmesh_intersect.c
@@ -114,6 +114,7 @@ static void edbm_intersect_select(BMEditMesh *em, struct Mesh *me, bool do_selec
}
}
}
+ EDBM_select_flush(em);
}
EDBM_update(me,
diff --git a/source/blender/editors/mesh/editmesh_knife.c b/source/blender/editors/mesh/editmesh_knife.c
index b712cfc24ed..76d48432834 100644
--- a/source/blender/editors/mesh/editmesh_knife.c
+++ b/source/blender/editors/mesh/editmesh_knife.c
@@ -236,7 +236,7 @@ typedef struct KnifeTool_OpData {
GHash *facetrimap;
KnifeBVH bvh;
- const float (**cagecos)[3];
+ float (**cagecos)[3];
BLI_mempool *kverts;
BLI_mempool *kedges;
@@ -491,7 +491,7 @@ static void knifetool_draw_visible_distances(const KnifeTool_OpData *kcd)
float numstr_size[2];
float posit[2];
const float bg_margin = 4.0f * U.dpi_fac;
- const int font_size = 14.0f * U.pixelsize;
+ const float font_size = 14.0f * U.pixelsize;
const int distance_precision = 4;
/* Calculate distance and convert to string. */
@@ -561,7 +561,7 @@ static void knifetool_draw_angle(const KnifeTool_OpData *kcd,
const float arc_size = 64.0f * U.dpi_fac;
const float bg_margin = 4.0f * U.dpi_fac;
const float cap_size = 4.0f * U.dpi_fac;
- const int font_size = 14 * U.pixelsize;
+ const float font_size = 14.0f * U.pixelsize;
const int angle_precision = 3;
/* Angle arc in 3d space. */
@@ -3975,7 +3975,7 @@ static void knifetool_init_cagecos(KnifeTool_OpData *kcd, Object *ob, uint base_
BM_mesh_elem_index_ensure(em_eval->bm, BM_VERT);
- kcd->cagecos[base_index] = (const float(*)[3])BKE_editmesh_vert_coords_alloc(
+ kcd->cagecos[base_index] = BKE_editmesh_vert_coords_alloc(
kcd->vc.depsgraph, em_eval, scene_eval, obedit_eval, NULL);
}
diff --git a/source/blender/editors/object/object_add.c b/source/blender/editors/object/object_add.c
index f81e2a65b9f..c77db10d74b 100644
--- a/source/blender/editors/object/object_add.c
+++ b/source/blender/editors/object/object_add.c
@@ -2166,7 +2166,7 @@ static void copy_object_set_idnew(bContext *C)
Main *bmain = CTX_data_main(C);
CTX_DATA_BEGIN (C, Object *, ob, selected_editable_objects) {
- BKE_libblock_relink_to_newid(&ob->id);
+ BKE_libblock_relink_to_newid(bmain, &ob->id, 0);
}
CTX_DATA_END;
@@ -2399,7 +2399,7 @@ static void make_object_duplilist_real(bContext *C,
Object *ob_dst = BLI_ghash_lookup(dupli_gh, dob);
/* Remap new object to itself, and clear again newid pointer of orig object. */
- BKE_libblock_relink_to_newid(&ob_dst->id);
+ BKE_libblock_relink_to_newid(bmain, &ob_dst->id, 0);
DEG_id_tag_update(&ob_dst->id, ID_RECALC_GEOMETRY);
@@ -3395,8 +3395,11 @@ Base *ED_object_add_duplicate(
ob = basen->object;
- /* link own references to the newly duplicated data T26816. */
- BKE_libblock_relink_to_newid(&ob->id);
+ /* Link own references to the newly duplicated data T26816.
+ * Note that this function can be called from edit-mode code, in which case we may have to
+ * enforce remapping obdata (by default this is forbidden in edit mode). */
+ const int remap_flag = BKE_object_is_in_editmode(ob) ? ID_REMAP_FORCE_OBDATA_IN_EDITMODE : 0;
+ BKE_libblock_relink_to_newid(bmain, &ob->id, remap_flag);
/* DAG_relations_tag_update(bmain); */ /* caller must do */
diff --git a/source/blender/editors/object/object_relations.c b/source/blender/editors/object/object_relations.c
index aa15ce36582..b51644eebf3 100644
--- a/source/blender/editors/object/object_relations.c
+++ b/source/blender/editors/object/object_relations.c
@@ -1685,18 +1685,20 @@ static bool single_data_needs_duplication(ID *id)
return (id != NULL && (id->us > 1 || ID_IS_LINKED(id)));
}
-static void libblock_relink_collection(Collection *collection, const bool do_collection)
+static void libblock_relink_collection(Main *bmain,
+ Collection *collection,
+ const bool do_collection)
{
if (do_collection) {
- BKE_libblock_relink_to_newid(&collection->id);
+ BKE_libblock_relink_to_newid(bmain, &collection->id, 0);
}
for (CollectionObject *cob = collection->gobject.first; cob != NULL; cob = cob->next) {
- BKE_libblock_relink_to_newid(&cob->ob->id);
+ BKE_libblock_relink_to_newid(bmain, &cob->ob->id, 0);
}
LISTBASE_FOREACH (CollectionChild *, child, &collection->children) {
- libblock_relink_collection(child->collection, true);
+ libblock_relink_collection(bmain, child->collection, true);
}
}
@@ -1766,10 +1768,10 @@ static void single_object_users(
single_object_users_collection(bmain, scene, master_collection, flag, copy_collections, true);
/* Will also handle the master collection. */
- BKE_libblock_relink_to_newid(&scene->id);
+ BKE_libblock_relink_to_newid(bmain, &scene->id, 0);
/* Collection and object pointers in collections */
- libblock_relink_collection(scene->master_collection, false);
+ libblock_relink_collection(bmain, scene->master_collection, false);
/* We also have to handle runtime things in UI. */
if (v3d) {
@@ -2654,7 +2656,7 @@ void OBJECT_OT_drop_named_material(wmOperatorType *ot)
/* api callbacks */
ot->invoke = drop_named_material_invoke;
- ot->poll = ED_operator_objectmode;
+ ot->poll = ED_operator_objectmode_poll_msg;
/* flags */
ot->flag = OPTYPE_UNDO | OPTYPE_INTERNAL;
diff --git a/source/blender/editors/physics/particle_edit.c b/source/blender/editors/physics/particle_edit.c
index 97f3b96cd18..fc80767be9e 100644
--- a/source/blender/editors/physics/particle_edit.c
+++ b/source/blender/editors/physics/particle_edit.c
@@ -3903,8 +3903,8 @@ static void brush_puff(PEData *data, int point_index, float mouse_distance)
copy_v3_v3(co, key->co);
mul_m4_v3(mat, co);
- /* use 'kco' as the object space version of worldspace 'co',
- * ob->imat is set before calling */
+ /* Use `kco` as the object space version of world-space `co`,
+ * `ob->imat` is set before calling. */
mul_v3_m4v3(kco, data->ob->imat, co);
point_index = BLI_kdtree_3d_find_nearest(edit->emitter_field, kco, NULL);
@@ -3993,15 +3993,15 @@ static void brush_puff(PEData *data, int point_index, float mouse_distance)
copy_v3_v3(oco, key->co);
mul_m4_v3(mat, oco);
- /* use 'kco' as the object space version of worldspace 'co',
- * ob->imat is set before calling */
+ /* Use `kco` as the object space version of world-space `co`,
+ * `ob->imat` is set before calling. */
mul_v3_m4v3(kco, data->ob->imat, oco);
point_index = BLI_kdtree_3d_find_nearest(edit->emitter_field, kco, NULL);
if (point_index != -1) {
copy_v3_v3(onor, &edit->emitter_cosnos[point_index * 6 + 3]);
- mul_mat3_m4_v3(data->ob->obmat, onor); /* normal into worldspace */
- mul_mat3_m4_v3(imat, onor); /* worldspace into particle space */
+ mul_mat3_m4_v3(data->ob->obmat, onor); /* Normal into world-space. */
+ mul_mat3_m4_v3(imat, onor); /* World-space into particle-space. */
normalize_v3(onor);
}
else {
diff --git a/source/blender/editors/screen/area.c b/source/blender/editors/screen/area.c
index 80c14371c16..38eadf95bde 100644
--- a/source/blender/editors/screen/area.c
+++ b/source/blender/editors/screen/area.c
@@ -594,7 +594,7 @@ void ED_region_do_draw(bContext *C, ARegion *region)
memset(&region->drawrct, 0, sizeof(region->drawrct));
- UI_blocklist_free_inactive(C, &region->uiblocks);
+ UI_blocklist_free_inactive(C, region);
if (area) {
const bScreen *screen = WM_window_get_active_screen(win);
@@ -1377,7 +1377,7 @@ static void region_rect_recursive(
else if (alignment == RGN_ALIGN_FLOAT) {
/**
* \note Currently this window type is only used for #RGN_TYPE_HUD,
- * We expect the panel to resize it's self to be larger.
+ * We expect the panel to resize itself to be larger.
*
* This aligns to the lower left of the area.
*/
@@ -1985,7 +1985,7 @@ void ED_area_init(wmWindowManager *wm, wmWindow *win, ScrArea *area)
}
else {
/* prevent uiblocks to run */
- UI_blocklist_free(NULL, &region->uiblocks);
+ UI_blocklist_free(NULL, region);
}
/* Some AZones use View2D data which is only updated in region init, so call that first! */
@@ -3323,7 +3323,7 @@ bool ED_region_property_search(const bContext *C,
}
/* Free the panels and blocks, as they are only used for search. */
- UI_blocklist_free(C, &region->uiblocks);
+ UI_blocklist_free(C, region);
UI_panels_free_instanced(C, region);
BKE_area_region_panels_free(&region->panels);
diff --git a/source/blender/editors/screen/screen_edit.c b/source/blender/editors/screen/screen_edit.c
index fa0cfd16817..3c8fb2e7446 100644
--- a/source/blender/editors/screen/screen_edit.c
+++ b/source/blender/editors/screen/screen_edit.c
@@ -1495,8 +1495,7 @@ ScrArea *ED_screen_state_toggle(bContext *C, wmWindow *win, ScrArea *area, const
* switching screens with tooltip open because region and tooltip
* are no longer in the same screen */
LISTBASE_FOREACH (ARegion *, region, &area->regionbase) {
- UI_blocklist_free(C, &region->uiblocks);
-
+ UI_blocklist_free(C, region);
if (region->regiontimer) {
WM_event_remove_timer(wm, NULL, region->regiontimer);
region->regiontimer = NULL;
diff --git a/source/blender/editors/screen/screen_user_menu.c b/source/blender/editors/screen/screen_user_menu.c
index bc370c64b0c..4cad97652dd 100644
--- a/source/blender/editors/screen/screen_user_menu.c
+++ b/source/blender/editors/screen/screen_user_menu.c
@@ -111,7 +111,7 @@ bUserMenu *ED_screen_user_menu_ensure(bContext *C)
bUserMenuItem_Op *ED_screen_user_menu_item_find_operator(ListBase *lb,
const wmOperatorType *ot,
IDProperty *prop,
- short opcontext)
+ wmOperatorCallContext opcontext)
{
LISTBASE_FOREACH (bUserMenuItem *, umi, lb) {
if (umi->type == USER_MENU_TYPE_OPERATOR) {
@@ -160,7 +160,7 @@ void ED_screen_user_menu_item_add_operator(ListBase *lb,
const char *ui_name,
const wmOperatorType *ot,
const IDProperty *prop,
- short opcontext)
+ wmOperatorCallContext opcontext)
{
bUserMenuItem_Op *umi_op = (bUserMenuItem_Op *)BKE_blender_user_menu_item_add(
lb, USER_MENU_TYPE_OPERATOR);
diff --git a/source/blender/editors/sculpt_paint/CMakeLists.txt b/source/blender/editors/sculpt_paint/CMakeLists.txt
index 3b668a1bd4c..b826ff8701d 100644
--- a/source/blender/editors/sculpt_paint/CMakeLists.txt
+++ b/source/blender/editors/sculpt_paint/CMakeLists.txt
@@ -44,6 +44,7 @@ set(SRC
paint_hide.c
paint_image.c
paint_image_2d.c
+ paint_image_2d_curve_mask.cc
paint_image_proj.c
paint_mask.c
paint_ops.c
diff --git a/source/blender/editors/sculpt_paint/paint_image_2d.c b/source/blender/editors/sculpt_paint/paint_image_2d.c
index 63f61b6c5c1..7191431cf4c 100644
--- a/source/blender/editors/sculpt_paint/paint_image_2d.c
+++ b/source/blender/editors/sculpt_paint/paint_image_2d.c
@@ -78,12 +78,13 @@ typedef struct BrushPainterCache {
ImBuf *ibuf;
ImBuf *texibuf;
- ushort *curve_mask;
ushort *tex_mask;
ushort *tex_mask_old;
uint tex_mask_old_w;
uint tex_mask_old_h;
+ CurveMaskCache curve_mask_cache;
+
int image_size[2];
} BrushPainterCache;
@@ -169,9 +170,6 @@ static void brush_painter_2d_require_imbuf(
if (cache->ibuf) {
IMB_freeImBuf(cache->ibuf);
}
- if (cache->curve_mask) {
- MEM_freeN(cache->curve_mask);
- }
if (cache->tex_mask) {
MEM_freeN(cache->tex_mask);
}
@@ -179,7 +177,6 @@ static void brush_painter_2d_require_imbuf(
MEM_freeN(cache->tex_mask_old);
}
cache->ibuf = NULL;
- cache->curve_mask = NULL;
cache->tex_mask = NULL;
cache->lastdiameter = -1; /* force ibuf create in refresh */
cache->invert = invert;
@@ -200,9 +197,7 @@ static void brush_painter_cache_2d_free(BrushPainterCache *cache)
if (cache->texibuf) {
IMB_freeImBuf(cache->texibuf);
}
- if (cache->curve_mask) {
- MEM_freeN(cache->curve_mask);
- }
+ paint_curve_mask_cache_free_data(&cache->curve_mask_cache);
if (cache->tex_mask) {
MEM_freeN(cache->tex_mask);
}
@@ -380,79 +375,6 @@ static void brush_painter_mask_imbuf_partial_update(BrushPainter *painter,
cache->tex_mask_old_h = diameter;
}
-/* create a mask with the falloff strength */
-static ushort *brush_painter_curve_mask_new(BrushPainter *painter,
- int diameter,
- float radius,
- const float pos[2])
-{
- Brush *brush = painter->brush;
-
- int offset = (int)floorf(diameter / 2.0f);
-
- ushort *mask, *m;
-
- mask = MEM_mallocN(sizeof(ushort) * diameter * diameter, "brush_painter_mask");
- m = mask;
-
- int aa_samples = 1.0f / (radius * 0.20f);
- if (brush->sampling_flag & BRUSH_PAINT_ANTIALIASING) {
- aa_samples = clamp_i(aa_samples, 3, 16);
- }
- else {
- aa_samples = 1;
- }
-
- /* Temporal until we have the brush properties */
- const float hardness = 1.0f;
- const float rotation = 0.0f;
-
- float aa_offset = 1.0f / (2.0f * (float)aa_samples);
- float aa_step = 1.0f / (float)aa_samples;
-
- float bpos[2];
- bpos[0] = pos[0] - floorf(pos[0]) + offset - aa_offset;
- bpos[1] = pos[1] - floorf(pos[1]) + offset - aa_offset;
-
- const float co = cosf(DEG2RADF(rotation));
- const float si = sinf(DEG2RADF(rotation));
-
- float norm_factor = 65535.0f / (float)(aa_samples * aa_samples);
-
- for (int y = 0; y < diameter; y++) {
- for (int x = 0; x < diameter; x++, m++) {
- float total_samples = 0;
- for (int i = 0; i < aa_samples; i++) {
- for (int j = 0; j < aa_samples; j++) {
- float pixel_xy[2] = {x + (aa_step * i), y + (aa_step * j)};
- float xy_rot[2];
- sub_v2_v2(pixel_xy, bpos);
-
- xy_rot[0] = co * pixel_xy[0] - si * pixel_xy[1];
- xy_rot[1] = si * pixel_xy[0] + co * pixel_xy[1];
-
- float len = len_v2(xy_rot);
- float p = len / radius;
- if (hardness < 1.0f) {
- p = (p - hardness) / (1.0f - hardness);
- p = 1.0f - p;
- CLAMP(p, 0.0f, 1.0f);
- }
- else {
- p = 1.0;
- }
- float hardness_factor = 3.0f * p * p - 2.0f * p * p * p;
- float curve = BKE_brush_curve_strength_clamped(brush, len, radius);
- total_samples += curve * hardness_factor;
- }
- }
- *m = (ushort)(total_samples * norm_factor);
- }
- }
-
- return mask;
-}
-
/* create imbuf with brush color */
static ImBuf *brush_painter_imbuf_new(
BrushPainter *painter, ImagePaintTile *tile, const int size, float pressure, float distance)
@@ -858,10 +780,8 @@ static void brush_painter_2d_refresh_cache(ImagePaintState *s,
}
}
- /* curve mask can only change if the size changes */
- MEM_SAFE_FREE(cache->curve_mask);
-
- cache->curve_mask = brush_painter_curve_mask_new(painter, diameter, size, pos);
+ /* Re-initialize the curve mask. Mask is always recreated due to the change of position. */
+ paint_curve_mask_cache_update(&cache->curve_mask_cache, brush, diameter, size, pos);
/* detect if we need to recreate image brush buffer */
if (diameter != cache->lastdiameter || (tex_rotation != cache->last_tex_rotation) || do_random ||
@@ -1325,7 +1245,7 @@ static void paint_2d_do_making_brush(ImagePaintState *s,
&tmpbuf,
frombuf,
mask,
- tile->cache.curve_mask,
+ tile->cache.curve_mask_cache.curve_mask,
tile->cache.tex_mask,
mask_max,
region->destx,
@@ -1474,7 +1394,7 @@ static int paint_2d_op(void *state,
canvas,
frombuf,
NULL,
- tile->cache.curve_mask,
+ tile->cache.curve_mask_cache.curve_mask,
tile->cache.tex_mask,
mask_max,
region[a].destx,
diff --git a/source/blender/editors/sculpt_paint/paint_image_2d_curve_mask.cc b/source/blender/editors/sculpt_paint/paint_image_2d_curve_mask.cc
new file mode 100644
index 00000000000..8d57a3d9152
--- /dev/null
+++ b/source/blender/editors/sculpt_paint/paint_image_2d_curve_mask.cc
@@ -0,0 +1,188 @@
+/*
+ * 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.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ */
+
+/** \file
+ * \ingroup ed
+ */
+
+#include "BLI_math.h"
+
+#include "MEM_guardedalloc.h"
+
+#include "DNA_brush_types.h"
+
+#include "BKE_brush.h"
+
+#include "paint_intern.h"
+
+namespace blender::ed::sculpt_paint {
+
+constexpr int AntiAliasingSamplesPerTexelAxisMin = 3;
+constexpr int AntiAliasingSamplesPerTexelAxisMax = 16;
+/**
+ * \brief Number of samples to use between 0..1.
+ */
+constexpr int CurveSamplesBaseLen = 1024;
+/**
+ * \brief Number of samples to store in the cache.
+ *
+ * M_SQRT2 is used as brushes are circles and the curve_mask is square.
+ * + 1 to fix floating rounding issues.
+ */
+constexpr int CurveSamplesLen = M_SQRT2 * CurveSamplesBaseLen + 1;
+
+static int aa_samples_per_texel_axis(const Brush *brush, const float radius)
+{
+ int aa_samples = 1.0f / (radius * 0.20f);
+ if (brush->sampling_flag & BRUSH_PAINT_ANTIALIASING) {
+ aa_samples = clamp_i(
+ aa_samples, AntiAliasingSamplesPerTexelAxisMin, AntiAliasingSamplesPerTexelAxisMax);
+ }
+ else {
+ aa_samples = 1;
+ }
+ return aa_samples;
+}
+
+/* create a mask with the falloff strength */
+static void update_curve_mask(CurveMaskCache *curve_mask_cache,
+ const Brush *brush,
+ const int diameter,
+ const float radius,
+ const float cursor_position[2])
+{
+ BLI_assert(curve_mask_cache->curve_mask != nullptr);
+ int offset = (int)floorf(diameter / 2.0f);
+
+ unsigned short *m = curve_mask_cache->curve_mask;
+
+ const int aa_samples = aa_samples_per_texel_axis(brush, radius);
+ const float aa_offset = 1.0f / (2.0f * (float)aa_samples);
+ const float aa_step = 1.0f / (float)aa_samples;
+
+ float bpos[2];
+ bpos[0] = cursor_position[0] - floorf(cursor_position[0]) + offset;
+ bpos[1] = cursor_position[1] - floorf(cursor_position[1]) + offset;
+
+ float weight_factor = 65535.0f / (float)(aa_samples * aa_samples);
+
+ for (int y = 0; y < diameter; y++) {
+ for (int x = 0; x < diameter; x++, m++) {
+ float pixel_xy[2];
+ pixel_xy[0] = static_cast<float>(x) + aa_offset;
+ float total_weight = 0;
+
+ for (int i = 0; i < aa_samples; i++) {
+ pixel_xy[1] = static_cast<float>(y) + aa_offset;
+ for (int j = 0; j < aa_samples; j++) {
+ const float len = len_v2v2(pixel_xy, bpos);
+ const int sample_index = min_ii((len / radius) * CurveSamplesBaseLen,
+ CurveSamplesLen - 1);
+ const float sample_weight = curve_mask_cache->sampled_curve[sample_index];
+
+ total_weight += sample_weight;
+
+ pixel_xy[1] += aa_step;
+ }
+ pixel_xy[0] += aa_step;
+ }
+ *m = (unsigned short)(total_weight * weight_factor);
+ }
+ }
+}
+
+static bool is_sampled_curve_valid(const CurveMaskCache *curve_mask_cache, const Brush *brush)
+{
+ if (curve_mask_cache->sampled_curve == nullptr) {
+ return false;
+ }
+ return curve_mask_cache->last_curve_timestamp == brush->curve->changed_timestamp;
+}
+
+static void sampled_curve_free(CurveMaskCache *curve_mask_cache)
+{
+ MEM_SAFE_FREE(curve_mask_cache->sampled_curve);
+ curve_mask_cache->last_curve_timestamp = 0;
+}
+
+static void update_sampled_curve(CurveMaskCache *curve_mask_cache, const Brush *brush)
+{
+ if (curve_mask_cache->sampled_curve == nullptr) {
+ curve_mask_cache->sampled_curve = static_cast<float *>(
+ MEM_mallocN(CurveSamplesLen * sizeof(float), __func__));
+ }
+
+ for (int i = 0; i < CurveSamplesLen; i++) {
+ const float len = i / float(CurveSamplesBaseLen);
+ const float sample_weight = BKE_brush_curve_strength_clamped(brush, len, 1.0f);
+ curve_mask_cache->sampled_curve[i] = sample_weight;
+ }
+ curve_mask_cache->last_curve_timestamp = brush->curve->changed_timestamp;
+}
+
+static size_t diameter_to_curve_mask_size(const int diameter)
+{
+ return diameter * diameter * sizeof(ushort);
+}
+
+static bool is_curve_mask_size_valid(const CurveMaskCache *curve_mask_cache, const int diameter)
+{
+ return curve_mask_cache->curve_mask_size == diameter_to_curve_mask_size(diameter);
+}
+
+static void curve_mask_free(CurveMaskCache *curve_mask_cache)
+{
+ curve_mask_cache->curve_mask_size = 0;
+ MEM_SAFE_FREE(curve_mask_cache->curve_mask);
+}
+
+static void curve_mask_allocate(CurveMaskCache *curve_mask_cache, const int diameter)
+{
+ const size_t curve_mask_size = diameter_to_curve_mask_size(diameter);
+ curve_mask_cache->curve_mask = static_cast<unsigned short *>(
+ MEM_mallocN(curve_mask_size, __func__));
+ curve_mask_cache->curve_mask_size = curve_mask_size;
+}
+
+} // namespace blender::ed::sculpt_paint
+
+using namespace blender::ed::sculpt_paint;
+
+void paint_curve_mask_cache_free_data(CurveMaskCache *curve_mask_cache)
+{
+ sampled_curve_free(curve_mask_cache);
+ curve_mask_free(curve_mask_cache);
+}
+
+void paint_curve_mask_cache_update(CurveMaskCache *curve_mask_cache,
+ const Brush *brush,
+ const int diameter,
+ const float radius,
+ const float cursor_position[2])
+{
+ if (!is_sampled_curve_valid(curve_mask_cache, brush)) {
+ update_sampled_curve(curve_mask_cache, brush);
+ }
+
+ if (!is_curve_mask_size_valid(curve_mask_cache, diameter)) {
+ curve_mask_free(curve_mask_cache);
+ curve_mask_allocate(curve_mask_cache, diameter);
+ }
+ update_curve_mask(curve_mask_cache, brush, diameter, radius, cursor_position);
+}
diff --git a/source/blender/editors/sculpt_paint/paint_image_proj.c b/source/blender/editors/sculpt_paint/paint_image_proj.c
index 89263bec7b1..db3e69b0953 100644
--- a/source/blender/editors/sculpt_paint/paint_image_proj.c
+++ b/source/blender/editors/sculpt_paint/paint_image_proj.c
@@ -3125,7 +3125,8 @@ static void project_paint_face_init(const ProjPaintState *ps,
uv, v1coSS, v2coSS, v3coSS, uv1co, uv2co, uv3co, pixelScreenCo, w);
}
- /* a pity we need to get the worldspace pixel location here */
+ /* A pity we need to get the world-space pixel location here
+ * because it is a relatively expensive operation. */
if (do_clip || do_3d_mapping) {
interp_v3_v3v3v3(wco,
ps->mvert_eval[lt_vtri[0]].co,
@@ -3208,7 +3209,10 @@ static void project_paint_face_init(const ProjPaintState *ps,
else {
/* we have a seam - deal with it! */
- /* inset face coords. NOTE!!! ScreenSace for ortho, Worldspace in perspective view */
+ /* Inset face coords.
+ * - screen-space in orthographic view.
+ * - world-space in perspective view.
+ */
float insetCos[3][3];
/* Vertex screen-space coords. */
@@ -3373,8 +3377,8 @@ static void project_paint_face_init(const ProjPaintState *ps,
if ((ps->do_occlude == false) ||
!project_bucket_point_occluded(
ps, bucketFaceNodes, tri_index, pixel_on_edge)) {
- /* a pity we need to get the worldspace
- * pixel location here */
+ /* A pity we need to get the world-space pixel location here
+ * because it is a relatively expensive operation. */
if (do_clip || do_3d_mapping) {
interp_v3_v3v3v3(wco, vCo[0], vCo[1], vCo[2], w);
diff --git a/source/blender/editors/sculpt_paint/paint_intern.h b/source/blender/editors/sculpt_paint/paint_intern.h
index 7341d984c91..62320defbb3 100644
--- a/source/blender/editors/sculpt_paint/paint_intern.h
+++ b/source/blender/editors/sculpt_paint/paint_intern.h
@@ -23,6 +23,13 @@
#pragma once
+#include "BKE_paint.h"
+#include "DNA_scene_types.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
struct ARegion;
struct Brush;
struct ColorManagedDisplay;
@@ -43,8 +50,6 @@ struct wmEvent;
struct wmKeyConfig;
struct wmOperator;
struct wmOperatorType;
-enum ePaintMode;
-enum ePaintSymmetryFlags;
typedef struct CoNo {
float co[3];
@@ -245,6 +250,45 @@ void PAINT_OT_add_texture_paint_slot(struct wmOperatorType *ot);
void PAINT_OT_image_paint(struct wmOperatorType *ot);
void PAINT_OT_add_simple_uvs(struct wmOperatorType *ot);
+/* paint_image_2d_curve_mask.cc */
+/**
+ * \brief Caching structure for curve mask.
+ *
+ * When 2d painting images the curve mask is used as an input.
+ */
+typedef struct CurveMaskCache {
+ /**
+ * \brief Last #CurveMapping.changed_timestamp being read.
+ *
+ * When different the input cache needs to be recalculated.
+ */
+ int last_curve_timestamp;
+
+ /**
+ * \brief sampled version of the brush curvemapping.
+ */
+ float *sampled_curve;
+
+ /**
+ * \brief Size in bytes of the curve_mask field.
+ *
+ * Used to determine if the curve_mask needs to be re-allocated.
+ */
+ size_t curve_mask_size;
+
+ /**
+ * \brief Curve mask that can be passed as curve_mask parameter when.
+ */
+ ushort *curve_mask;
+} CurveMaskCache;
+
+void paint_curve_mask_cache_free_data(CurveMaskCache *curve_mask_cache);
+void paint_curve_mask_cache_update(CurveMaskCache *curve_mask_cache,
+ const struct Brush *brush,
+ const int diameter,
+ const float radius,
+ const float cursor_position[2]);
+
/* sculpt_uv.c */
void SCULPT_OT_uv_sculpt_stroke(struct wmOperatorType *ot);
@@ -366,3 +410,8 @@ void paint_delete_blur_kernel(BlurKernel *);
/* paint curve defines */
#define PAINT_CURVE_NUM_SEGMENTS 40
+
+#ifdef __cplusplus
+}
+#endif
+
diff --git a/source/blender/editors/sculpt_paint/paint_vertex_color_ops.c b/source/blender/editors/sculpt_paint/paint_vertex_color_ops.c
index f95e1d8d89c..f62d91acddf 100644
--- a/source/blender/editors/sculpt_paint/paint_vertex_color_ops.c
+++ b/source/blender/editors/sculpt_paint/paint_vertex_color_ops.c
@@ -210,9 +210,6 @@ static void vertex_color_smooth_looptag(Mesh *me, const bool *mlooptag)
int(*scol)[4];
bool has_shared = false;
- /* if no mloopcol: do not do */
- /* if mtexpoly: only the involved faces, otherwise all */
-
if (me->mloopcol == NULL || me->totvert == 0 || me->totpoly == 0) {
return;
}
diff --git a/source/blender/editors/sculpt_paint/sculpt_intern.h b/source/blender/editors/sculpt_paint/sculpt_intern.h
index 696c3332a2b..16df1efd969 100644
--- a/source/blender/editors/sculpt_paint/sculpt_intern.h
+++ b/source/blender/editors/sculpt_paint/sculpt_intern.h
@@ -366,10 +366,12 @@ float *SCULPT_boundary_automasking_init(Object *ob,
/* Geodesic distances. */
-/* Returns an array indexed by vertex index containing the geodesic distance to the closest vertex
-in the initial vertex set. The caller is responsible for freeing the array.
-Geodesic distances will only work when used with PBVH_FACES, for other types of PBVH it will
-fallback to euclidean distances to one of the initial vertices in the set. */
+/**
+ * Returns an array indexed by vertex index containing the geodesic distance to the closest vertex
+ * in the initial vertex set. The caller is responsible for freeing the array.
+ * Geodesic distances will only work when used with PBVH_FACES, for other types of PBVH it will
+ * fallback to euclidean distances to one of the initial vertices in the set.
+ */
float *SCULPT_geodesic_distances_create(struct Object *ob,
struct GSet *initial_vertices,
const float limit_radius);
diff --git a/source/blender/editors/space_action/action_data.c b/source/blender/editors/space_action/action_data.c
index a4fd2d81778..9ff46d96207 100644
--- a/source/blender/editors/space_action/action_data.c
+++ b/source/blender/editors/space_action/action_data.c
@@ -702,6 +702,9 @@ void ACTION_OT_unlink(wmOperatorType *ot)
"Clear Fake User and remove "
"copy stashed in this data-block's NLA stack");
RNA_def_property_flag(prop, PROP_SKIP_SAVE);
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
/* ************************************************************************** */
diff --git a/source/blender/editors/space_buttons/space_buttons.c b/source/blender/editors/space_buttons/space_buttons.c
index b04291b7ab4..bc701bd7aa5 100644
--- a/source/blender/editors/space_buttons/space_buttons.c
+++ b/source/blender/editors/space_buttons/space_buttons.c
@@ -445,7 +445,7 @@ static void property_search_all_tabs(const bContext *C,
i,
property_search_for_context(C, region_copy, &sbuts_copy));
- UI_blocklist_free(C, &region_copy->uiblocks);
+ UI_blocklist_free(C, region_copy);
}
BKE_area_region_free(area_copy.type, region_copy);
diff --git a/source/blender/editors/space_clip/clip_editor.c b/source/blender/editors/space_clip/clip_editor.c
index 834ef847069..97fcf4ef8ba 100644
--- a/source/blender/editors/space_clip/clip_editor.c
+++ b/source/blender/editors/space_clip/clip_editor.c
@@ -272,7 +272,7 @@ ImBuf *ED_space_clip_get_stable_buffer(SpaceClip *sc, float loc[2], float *scale
}
bool ED_space_clip_get_position(struct SpaceClip *sc,
- struct ARegion *ar,
+ struct ARegion *region,
int mval[2],
float fpos[2])
{
@@ -282,7 +282,7 @@ bool ED_space_clip_get_position(struct SpaceClip *sc,
}
/* map the mouse coords to the backdrop image space */
- ED_clip_mouse_pos(sc, ar, mval, fpos);
+ ED_clip_mouse_pos(sc, region, mval, fpos);
IMB_freeImBuf(ibuf);
return true;
diff --git a/source/blender/editors/space_file/asset_catalog_tree_view.cc b/source/blender/editors/space_file/asset_catalog_tree_view.cc
index 41559278910..dee5168e30b 100644
--- a/source/blender/editors/space_file/asset_catalog_tree_view.cc
+++ b/source/blender/editors/space_file/asset_catalog_tree_view.cc
@@ -191,7 +191,8 @@ ui::BasicTreeViewItem &AssetCatalogTreeView::build_catalog_items_recursive(
{
ui::BasicTreeViewItem &view_item = view_parent_item.add_tree_item<AssetCatalogTreeViewItem>(
&catalog);
- view_item.is_active([this, &catalog]() { return is_active_catalog(catalog.get_catalog_id()); });
+ view_item.set_is_active_fn(
+ [this, &catalog]() { return is_active_catalog(catalog.get_catalog_id()); });
catalog.foreach_child([&view_item, this](AssetCatalogTreeItem &child) {
build_catalog_items_recursive(view_item, child);
@@ -205,11 +206,11 @@ void AssetCatalogTreeView::add_all_item()
AssetCatalogTreeViewAllItem &item = add_tree_item<AssetCatalogTreeViewAllItem>(IFACE_("All"),
ICON_HOME);
- item.on_activate([params](ui::BasicTreeViewItem & /*item*/) {
+ item.set_on_activate_fn([params](ui::BasicTreeViewItem & /*item*/) {
params->asset_catalog_visibility = FILE_SHOW_ASSETS_ALL_CATALOGS;
WM_main_add_notifier(NC_SPACE | ND_SPACE_ASSET_PARAMS, nullptr);
});
- item.is_active(
+ item.set_is_active_fn(
[params]() { return params->asset_catalog_visibility == FILE_SHOW_ASSETS_ALL_CATALOGS; });
}
@@ -220,11 +221,11 @@ void AssetCatalogTreeView::add_unassigned_item()
AssetCatalogTreeViewUnassignedItem &item = add_tree_item<AssetCatalogTreeViewUnassignedItem>(
IFACE_("Unassigned"), ICON_FILE_HIDDEN);
- item.on_activate([params](ui::BasicTreeViewItem & /*item*/) {
+ item.set_on_activate_fn([params](ui::BasicTreeViewItem & /*item*/) {
params->asset_catalog_visibility = FILE_SHOW_ASSETS_WITHOUT_CATALOG;
WM_main_add_notifier(NC_SPACE | ND_SPACE_ASSET_PARAMS, nullptr);
});
- item.is_active(
+ item.set_is_active_fn(
[params]() { return params->asset_catalog_visibility == FILE_SHOW_ASSETS_WITHOUT_CATALOG; });
}
diff --git a/source/blender/editors/space_file/filelist.c b/source/blender/editors/space_file/filelist.c
index 51a5c451f6d..6f929c43e13 100644
--- a/source/blender/editors/space_file/filelist.c
+++ b/source/blender/editors/space_file/filelist.c
@@ -1710,7 +1710,7 @@ static void filelist_cache_previews_push(FileList *filelist, FileDirEntry *entry
return;
}
- if (entry->flags & FILE_ENTRY_INVALID_PREVIEW) {
+ if (entry->flags & (FILE_ENTRY_INVALID_PREVIEW | FILE_ENTRY_PREVIEW_LOADING)) {
return;
}
@@ -1741,6 +1741,7 @@ static void filelist_cache_previews_push(FileList *filelist, FileDirEntry *entry
FileListEntryPreviewTaskData *preview_taskdata = MEM_mallocN(sizeof(*preview_taskdata),
__func__);
preview_taskdata->preview = preview;
+ entry->flags |= FILE_ENTRY_PREVIEW_LOADING;
BLI_task_pool_push(cache->previews_pool,
filelist_cache_preview_runf,
preview_taskdata,
@@ -1896,6 +1897,7 @@ static void filelist_clear_asset_library(FileList *filelist)
{
/* The AssetLibraryService owns the AssetLibrary pointer, so no need for us to free it. */
filelist->asset_library = NULL;
+ file_delete_asset_catalog_filter_settings(&filelist->filter_data.asset_catalog_filter);
}
void filelist_clear_ex(struct FileList *filelist,
@@ -1995,7 +1997,6 @@ void filelist_free(struct FileList *filelist)
filelist->selection_state = NULL;
}
- file_delete_asset_catalog_filter_settings(&filelist->filter_data.asset_catalog_filter);
MEM_SAFE_FREE(filelist->asset_library_ref);
memset(&filelist->filter_data, 0, sizeof(filelist->filter_data));
@@ -2659,24 +2660,27 @@ bool filelist_cache_previews_update(FileList *filelist)
// printf("%s: %d - %s - %p\n", __func__, preview->index, preview->path, preview->img);
- if (preview->icon_id) {
- /* Due to asynchronous process, a preview for a given image may be generated several times,
- * i.e. entry->image may already be set at this point. */
- if (entry && !entry->preview_icon_id) {
+ if (entry) {
+ if (preview->icon_id) {
+ /* The FILE_ENTRY_PREVIEW_LOADING flag should have prevented any other asynchronous
+ * process from trying to generate the same preview icon. */
+ BLI_assert_msg(!entry->preview_icon_id, "Preview icon should not have been generated yet");
+
/* Move ownership over icon. */
entry->preview_icon_id = preview->icon_id;
preview->icon_id = 0;
changed = true;
}
else {
- BKE_icon_delete(preview->icon_id);
+ /* We want to avoid re-processing this entry continuously!
+ * Note that, since entries only live in cache,
+ * preview will be retried quite often anyway. */
+ entry->flags |= FILE_ENTRY_INVALID_PREVIEW;
}
+ entry->flags &= ~FILE_ENTRY_PREVIEW_LOADING;
}
- else if (entry) {
- /* We want to avoid re-processing this entry continuously!
- * Note that, since entries only live in cache,
- * preview will be retried quite often anyway. */
- entry->flags |= FILE_ENTRY_INVALID_PREVIEW;
+ else {
+ BKE_icon_delete(preview->icon_id);
}
MEM_freeN(preview);
diff --git a/source/blender/editors/space_graph/graph_buttons.c b/source/blender/editors/space_graph/graph_buttons.c
index 26a056ce1fb..41f74b6ade9 100644
--- a/source/blender/editors/space_graph/graph_buttons.c
+++ b/source/blender/editors/space_graph/graph_buttons.c
@@ -19,6 +19,8 @@
/** \file
* \ingroup spgraph
+ *
+ * Graph editor space & buttons.
*/
#include <float.h>
@@ -66,11 +68,11 @@
#include "graph_intern.h" /* own include */
-/* ******************* graph editor space & buttons ************** */
-
#define B_REDR 1
-/* -------------- */
+/* -------------------------------------------------------------------- */
+/** \name Internal Utilities
+ * \{ */
static bool graph_panel_context(const bContext *C, bAnimListElem **ale, FCurve **fcu)
{
@@ -120,7 +122,11 @@ static bool graph_panel_poll(const bContext *C, PanelType *UNUSED(pt))
return graph_panel_context(C, NULL, NULL);
}
-/* -------------- */
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Cursor Header
+ * \{ */
static void graph_panel_cursor_header(const bContext *C, Panel *panel)
{
@@ -174,7 +180,11 @@ static void graph_panel_cursor(const bContext *C, Panel *panel)
uiItemO(sub, IFACE_("Cursor Value to Selection"), ICON_NONE, "GRAPH_OT_snap_cursor_value");
}
-/* ******************* active F-Curve ************** */
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Active F-Curve
+ * \{ */
static void graph_panel_properties(const bContext *C, Panel *panel)
{
@@ -243,7 +253,11 @@ static void graph_panel_properties(const bContext *C, Panel *panel)
MEM_freeN(ale);
}
-/* ******************* active Keyframe ************** */
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Active Keyframe
+ * \{ */
/* get 'active' keyframe for panel editing */
static bool get_active_fcurve_keyframe_edit(const FCurve *fcu,
@@ -610,7 +624,11 @@ static void graph_panel_key_properties(const bContext *C, Panel *panel)
MEM_freeN(ale);
}
-/* ******************* drivers ******************************** */
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Drivers
+ * \{ */
#define B_IPO_DEPCHANGE 10
@@ -1320,8 +1338,13 @@ static void graph_panel_drivers_popover(const bContext *C, Panel *panel)
uiItemO(layout, IFACE_("Show in Drivers Editor"), ICON_DRIVER, "SCREEN_OT_drivers_editor_show");
}
-/* ******************* F-Modifiers ******************************** */
-/* All the drawing code is in editors/animation/fmodifier_ui.c */
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name F-Curve Modifiers
+ *
+ * \note All the drawing code is in `editors/animation/fmodifier_ui.c`
+ * \{ */
#define B_FMODIFIER_REDRAW 20
/** The start of FModifier panels registered for the graph editor. */
@@ -1380,7 +1403,11 @@ static void graph_panel_modifiers(const bContext *C, Panel *panel)
MEM_freeN(ale);
}
-/* ******************* general ******************************** */
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Registration
+ * \{ */
void graph_buttons_register(ARegionType *art)
{
@@ -1456,3 +1483,5 @@ void graph_buttons_register(ARegionType *art)
pt->draw_header = graph_panel_cursor_header;
BLI_addtail(&art->paneltypes, pt);
}
+
+/** \} */
diff --git a/source/blender/editors/space_graph/graph_edit.c b/source/blender/editors/space_graph/graph_edit.c
index 1967dfabd21..2afee277847 100644
--- a/source/blender/editors/space_graph/graph_edit.c
+++ b/source/blender/editors/space_graph/graph_edit.c
@@ -19,6 +19,8 @@
/** \file
* \ingroup spgraph
+ *
+ * Insert duplicate and bake keyframes.
*/
#include <float.h>
@@ -69,9 +71,6 @@
#include "graph_intern.h"
-/* ************************************************************************** */
-/* INSERT DUPLICATE AND BAKE KEYFRAMES */
-
/* -------------------------------------------------------------------- */
/** \name Insert Keyframes Operator
* \{ */
diff --git a/source/blender/editors/space_graph/graph_ops.c b/source/blender/editors/space_graph/graph_ops.c
index 32396a70cce..ecafc75fc06 100644
--- a/source/blender/editors/space_graph/graph_ops.c
+++ b/source/blender/editors/space_graph/graph_ops.c
@@ -52,11 +52,13 @@
/* ************************** view-based operators **********************************/
/* XXX should these really be here? */
-/* Set Cursor --------------------------------------------------------------------- */
-/* The 'cursor' in the Graph Editor consists of two parts:
+/* -------------------------------------------------------------------- */
+/** \name Set Cursor
+ *
+ * The 'cursor' in the Graph Editor consists of two parts:
* 1) Current Frame Indicator (as per ANIM_OT_change_frame)
* 2) Value Indicator (stored per Graph Editor instance)
- */
+ * \{ */
static bool graphview_cursor_poll(bContext *C)
{
@@ -225,7 +227,11 @@ static void GRAPH_OT_cursor_set(wmOperatorType *ot)
RNA_def_float(ot->srna, "value", 0, -FLT_MAX, FLT_MAX, "Value", "", -100.0f, 100.0f);
}
-/* Hide/Reveal ------------------------------------------------------------ */
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Hide/Reveal
+ * \{ */
static int graphview_curves_hide_exec(bContext *C, wmOperator *op)
{
@@ -413,7 +419,11 @@ static void GRAPH_OT_reveal(wmOperatorType *ot)
RNA_def_boolean(ot->srna, "select", true, "Select", "");
}
-/* ************************** registration - operator types **********************************/
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Registration: operator types
+ * \{ */
void graphedit_operatortypes(void)
{
@@ -496,7 +506,11 @@ void ED_operatormacros_graph(void)
RNA_boolean_set(otmacro->ptr, "use_proportional_edit", false);
}
-/* ************************** registration - keymaps **********************************/
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Registration: Key-Maps
+ * \{ */
void graphedit_keymap(wmKeyConfig *keyconf)
{
@@ -514,3 +528,5 @@ void graphedit_keymap(wmKeyConfig *keyconf)
/* keyframes */
WM_keymap_ensure(keyconf, "Graph Editor", SPACE_GRAPH, 0);
}
+
+/** \} */
diff --git a/source/blender/editors/space_graph/graph_select.c b/source/blender/editors/space_graph/graph_select.c
index ffe74e20bdf..03bfd1092c6 100644
--- a/source/blender/editors/space_graph/graph_select.c
+++ b/source/blender/editors/space_graph/graph_select.c
@@ -56,8 +56,9 @@
#include "graph_intern.h"
-/* ************************************************************************** */
-/* KEYFRAMES STUFF */
+/* -------------------------------------------------------------------- */
+/** \name Internal Keyframe Utilities
+ * \{ */
/* temp info for caching handle vertices close */
typedef struct tNearestVertInfo {
@@ -334,14 +335,19 @@ static tNearestVertInfo *find_nearest_fcurve_vert(bAnimContext *ac, const int mv
return nvi;
}
-/* ******************** Deselect All Operator ***************************** */
-/* This operator works in one of three ways:
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Deselect All Operator
+ *
+ * This operator works in one of three ways:
* 1) (de)select all (AKEY) - test if select all or deselect all
* 2) invert all (CTRL-IKEY) - invert selection of all keyframes
* 3) (de)select all - no testing is done; only for use internal tools as normal function...
- */
+ * \{ */
-/* Deselects keyframes in the Graph Editor
+/**
+ * Deselects keyframes in the Graph Editor
* - This is called by the deselect all operator, as well as other ones!
*
* - test: check if select or deselect all
@@ -490,8 +496,12 @@ void GRAPH_OT_select_all(wmOperatorType *ot)
WM_operator_properties_select_all(ot);
}
-/* ******************** Box Select Operator **************************** */
-/* This operator currently works in one of three ways:
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Box Select Operator
+ *
+ * This operator currently works in one of three ways:
* -> BKEY - 1) all keyframes within region are selected (validation with BEZT_OK_REGION)
* -> ALT-BKEY - depending on which axis of the region was larger...
* -> 2) x-axis, so select all frames within frame range (validation with BEZT_OK_FRAMERANGE)
@@ -499,7 +509,7 @@ void GRAPH_OT_select_all(wmOperatorType *ot)
* (validation with BEZT_OK_VALUERANGE).
*
* The selection backend is also reused for the Lasso and Circle select operators.
- */
+ * \{ */
static rctf initialize_box_select_coords(const bAnimContext *ac, const rctf *rectf_view)
{
@@ -572,7 +582,8 @@ static void initialize_box_select_key_editing_data(const SpaceGraph *sipo,
*r_mapping_flag |= ANIM_get_normalization_flags(ac);
}
-/* Box Select only selects keyframes, as overshooting handles often get caught too,
+/**
+ * Box Select only selects keyframes, as overshooting handles often get caught too,
* which means that they may be inadvertently moved as well. However, incl_handles overrides
* this, and allow handles to be considered independently too.
* Also, for convenience, handles should get same status as keyframe (if it was within bounds).
@@ -667,7 +678,8 @@ static bool box_select_graphkeys(bAnimContext *ac,
return any_key_selection_changed;
}
-/* This function is used to set all the keyframes of a given curve as selectable
+/**
+ * This function is used to set all the keyframes of a given curve as selectable
* by the "select_cb" function inside of "box_select_graphcurves".
*/
static short ok_bezier_always_ok(KeyframeEditData *UNUSED(ked), BezTriple *UNUSED(bezt))
@@ -732,11 +744,12 @@ static bool rectf_curve_intersection(
#undef INSIDE
#undef BELOW
-/* Perform a box selection of the curves themselves. This means this function tries
+/**
+ * Perform a box selection of the curves themselves. This means this function tries
* to select a curve by sampling it at various points instead of trying to select the
* keyframes directly.
* The selection actions done to a curve are actually done on all the keyframes of the curve.
- * NOTE: This function is only called if no keyframe is in the selection area.
+ * \note This function is only called if no keyframe is in the selection area.
*/
static void box_select_graphcurves(bAnimContext *ac,
const rctf *rectf_view,
@@ -1107,13 +1120,17 @@ void GRAPH_OT_select_circle(wmOperatorType *ot)
RNA_def_property_flag(prop, PROP_SKIP_SAVE);
}
-/* ******************** Column Select Operator **************************** */
-/* This operator works in one of four ways:
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Column Select Operator
+ *
+ * This operator works in one of four ways:
* - 1) select all keyframes in the same frame as a selected one (KKEY)
* - 2) select all keyframes in the same frame as the current frame marker (CTRL-KKEY)
* - 3) select all keyframes in the same frame as a selected markers (SHIFT-KKEY)
* - 4) select all keyframes that occur between selected markers (ALT-KKEY)
- */
+ * \{ */
/* defines for column-select mode */
static const EnumPropertyItem prop_column_select_types[] = {
@@ -1297,7 +1314,11 @@ void GRAPH_OT_select_column(wmOperatorType *ot)
ot->prop = RNA_def_enum(ot->srna, "mode", prop_column_select_types, 0, "Mode", "");
}
-/* ******************** Select Linked Operator *********************** */
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Select Linked Operator
+ * \{ */
static int graphkeys_select_linked_exec(bContext *C, wmOperator *UNUSED(op))
{
@@ -1353,7 +1374,11 @@ void GRAPH_OT_select_linked(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
-/* ******************** Select More/Less Operators *********************** */
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Select More/Less Operators
+ * \{ */
/* Common code to perform selection */
static void select_moreless_graph_keys(bAnimContext *ac, short mode)
@@ -1467,8 +1492,13 @@ void GRAPH_OT_select_less(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
-/* ******************** Select Left/Right Operator ************************* */
-/* Select keyframes left/right of the current frame indicator */
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Select Left/Right Operator
+ *
+ * Select keyframes left/right of the current frame indicator.
+ * \{ */
/* defines for left-right select tool */
static const EnumPropertyItem prop_graphkeys_leftright_select_types[] = {
@@ -1628,15 +1658,19 @@ void GRAPH_OT_select_leftright(wmOperatorType *ot)
RNA_def_property_flag(prop, PROP_SKIP_SAVE);
}
-/* ******************** Mouse-Click Select Operator *********************** */
-/* This operator works in one of three ways:
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Mouse-Click Select Operator
+ *
+ * This operator works in one of three ways:
* - 1) keyframe under mouse - no special modifiers
* - 2) all keyframes on the same side of current frame indicator as mouse - ALT modifier
* - 3) column select all keyframes in frame under mouse - CTRL modifier
*
* In addition to these basic options, the SHIFT modifier can be used to toggle the
* selection mode between replacing the selection (without) and inverting the selection (with).
- */
+ * \{ */
/* option 1) select keyframe directly under mouse */
static int mouse_graph_keys(bAnimContext *ac,
@@ -1888,9 +1922,12 @@ static int graphkeys_mselect_column(bAnimContext *ac,
return run_modal ? OPERATOR_RUNNING_MODAL : OPERATOR_FINISHED;
}
-/* ------------------- */
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Click Select Operator
+ * \{ */
-/* handle clicking */
static int graphkeys_clickselect_exec(bContext *C, wmOperator *op)
{
bAnimContext ac;
@@ -1988,4 +2025,4 @@ void GRAPH_OT_clickselect(wmOperatorType *ot)
RNA_def_property_flag(prop, PROP_SKIP_SAVE);
}
-/* ************************************************************************** */
+/** \} */
diff --git a/source/blender/editors/space_graph/graph_slider_ops.c b/source/blender/editors/space_graph/graph_slider_ops.c
index f04336cab84..4e62ab2df2d 100644
--- a/source/blender/editors/space_graph/graph_slider_ops.c
+++ b/source/blender/editors/space_graph/graph_slider_ops.c
@@ -17,6 +17,16 @@
* All rights reserved.
*/
+/** \file
+ * \ingroup spgraph
+ *
+ * Graph Slider Operators
+ *
+ * This file contains a collection of operators to modify keyframes in the graph editor.
+ * All operators are modal and use a slider that allows the user to define a percentage
+ * to modify the operator.
+ */
+
#include <float.h>
#include <string.h>
@@ -48,42 +58,17 @@
#include "graph_intern.h"
-/* ******************** GRAPH SLIDER OPERATORS ************************* */
-/* This file contains a collection of operators to modify keyframes in the graph editor. All
- * operators are modal and use a slider that allows the user to define a percentage to modify the
- * operator. */
-
-/* ******************** Decimate Keyframes Operator ************************* */
-
-static void decimate_graph_keys(bAnimContext *ac, float remove_ratio, float error_sq_max)
-{
- ListBase anim_data = {NULL, NULL};
- bAnimListElem *ale;
- int filter;
-
- /* Filter data. */
- filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_CURVE_VISIBLE | ANIMFILTER_FOREDIT |
- ANIMFILTER_SEL | ANIMFILTER_NODUPLIS);
- ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
-
- /* Loop through filtered data and clean curves. */
- for (ale = anim_data.first; ale; ale = ale->next) {
- if (!decimate_fcurve(ale, remove_ratio, error_sq_max)) {
- /* The selection contains unsupported keyframe types! */
- WM_report(RPT_WARNING, "Decimate: Skipping non linear/bezier keyframes!");
- }
-
- ale->update |= ANIM_UPDATE_DEFAULT;
- }
-
- ANIM_animdata_update(ac, &anim_data);
- ANIM_animdata_freelist(&anim_data);
-}
+/* -------------------------------------------------------------------- */
+/** \name Internal Struct & Defines
+ * \{ */
-/* ------------------- */
+/* Used to obtain a list of animation channels for the operators to work on. */
+#define OPERATOR_DATA_FILTER \
+ (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_CURVE_VISIBLE | ANIMFILTER_FOREDIT | ANIMFILTER_SEL | \
+ ANIMFILTER_NODUPLIS)
/* This data type is only used for modal operation. */
-typedef struct tDecimateGraphOp {
+typedef struct tGraphSliderOp {
bAnimContext ac;
Scene *scene;
ScrArea *area;
@@ -98,35 +83,73 @@ typedef struct tDecimateGraphOp {
struct tSlider *slider;
NumInput num;
-} tDecimateGraphOp;
+} tGraphSliderOp;
typedef struct tBeztCopyData {
int tot_vert;
BezTriple *bezt;
} tBeztCopyData;
-typedef enum tDecimModes {
- DECIM_RATIO = 1,
- DECIM_ERROR,
-} tDecimModes;
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Utility Functions
+ * \{ */
+
+/* Construct a list with the original bezt arrays so we can restore them during modal operation.
+ * The data is stored on the struct that is passed.*/
+static void store_original_bezt_arrays(tGraphSliderOp *gso)
+{
+ ListBase anim_data = {NULL, NULL};
+ bAnimContext *ac = &gso->ac;
+ bAnimListElem *ale;
+
+ ANIM_animdata_filter(ac, &anim_data, OPERATOR_DATA_FILTER, ac->data, ac->datatype);
+
+ /* Loop through filtered data and copy the curves. */
+ for (ale = anim_data.first; ale; ale = ale->next) {
+ FCurve *fcu = (FCurve *)ale->key_data;
+
+ if (fcu->bezt == NULL) {
+ /* This curve is baked, skip it. */
+ continue;
+ }
+
+ const int arr_size = sizeof(BezTriple) * fcu->totvert;
+
+ tBeztCopyData *copy = MEM_mallocN(sizeof(tBeztCopyData), "bezts_copy");
+ BezTriple *bezts_copy = MEM_mallocN(arr_size, "bezts_copy_array");
+
+ copy->tot_vert = fcu->totvert;
+ memcpy(bezts_copy, fcu->bezt, arr_size);
+
+ copy->bezt = bezts_copy;
+
+ LinkData *link = NULL;
+
+ link = MEM_callocN(sizeof(LinkData), "Bezt Link");
+ link->data = copy;
+
+ BLI_addtail(&gso->bezt_arr_list, link);
+ }
+
+ ANIM_animdata_freelist(&anim_data);
+}
/* Overwrite the current bezts arrays with the original data. */
-static void decimate_reset_bezts(tDecimateGraphOp *dgo)
+static void reset_bezts(tGraphSliderOp *gso)
{
ListBase anim_data = {NULL, NULL};
LinkData *link_bezt;
bAnimListElem *ale;
- int filter;
- bAnimContext *ac = &dgo->ac;
+ bAnimContext *ac = &gso->ac;
/* Filter data. */
- filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_CURVE_VISIBLE | ANIMFILTER_FOREDIT |
- ANIMFILTER_SEL | ANIMFILTER_NODUPLIS);
- ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
+ ANIM_animdata_filter(ac, &anim_data, OPERATOR_DATA_FILTER, ac->data, ac->datatype);
/* Loop through filtered data and reset bezts. */
- for (ale = anim_data.first, link_bezt = dgo->bezt_arr_list.first; ale; ale = ale->next) {
+ for (ale = anim_data.first, link_bezt = gso->bezt_arr_list.first; ale; ale = ale->next) {
FCurve *fcu = (FCurve *)ale->key_data;
if (fcu->bezt == NULL) {
@@ -151,29 +174,62 @@ static void decimate_reset_bezts(tDecimateGraphOp *dgo)
ANIM_animdata_freelist(&anim_data);
}
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Decimate Keyframes Operator
+ * \{ */
+
+typedef enum tDecimModes {
+ DECIM_RATIO = 1,
+ DECIM_ERROR,
+} tDecimModes;
+
+static void decimate_graph_keys(bAnimContext *ac, float remove_ratio, float error_sq_max)
+{
+ ListBase anim_data = {NULL, NULL};
+ bAnimListElem *ale;
+
+ /* Filter data. */
+ ANIM_animdata_filter(ac, &anim_data, OPERATOR_DATA_FILTER, ac->data, ac->datatype);
+
+ /* Loop through filtered data and clean curves. */
+ for (ale = anim_data.first; ale; ale = ale->next) {
+ if (!decimate_fcurve(ale, remove_ratio, error_sq_max)) {
+ /* The selection contains unsupported keyframe types! */
+ WM_report(RPT_WARNING, "Decimate: Skipping non linear/bezier keyframes!");
+ }
+
+ ale->update |= ANIM_UPDATE_DEFAULT;
+ }
+
+ ANIM_animdata_update(ac, &anim_data);
+ ANIM_animdata_freelist(&anim_data);
+}
+
static void decimate_exit(bContext *C, wmOperator *op)
{
- tDecimateGraphOp *dgo = op->customdata;
+ tGraphSliderOp *gso = op->customdata;
wmWindow *win = CTX_wm_window(C);
/* If data exists, clear its data and exit. */
- if (dgo == NULL) {
+ if (gso == NULL) {
return;
}
- ScrArea *area = dgo->area;
+ ScrArea *area = gso->area;
LinkData *link;
- ED_slider_destroy(C, dgo->slider);
+ ED_slider_destroy(C, gso->slider);
- for (link = dgo->bezt_arr_list.first; link != NULL; link = link->next) {
+ for (link = gso->bezt_arr_list.first; link != NULL; link = link->next) {
tBeztCopyData *copy = link->data;
MEM_freeN(copy->bezt);
MEM_freeN(link->data);
}
- BLI_freelistN(&dgo->bezt_arr_list);
- MEM_freeN(dgo);
+ BLI_freelistN(&gso->bezt_arr_list);
+ MEM_freeN(gso);
/* Return to normal cursor and header status. */
WM_cursor_modal_restore(win);
@@ -184,20 +240,20 @@ static void decimate_exit(bContext *C, wmOperator *op)
}
/* Draw a percentage indicator in workspace footer. */
-static void decimate_draw_status(bContext *C, tDecimateGraphOp *dgo)
+static void decimate_draw_status(bContext *C, tGraphSliderOp *gso)
{
char status_str[UI_MAX_DRAW_STR];
char mode_str[32];
char slider_string[UI_MAX_DRAW_STR];
- ED_slider_status_string_get(dgo->slider, slider_string, UI_MAX_DRAW_STR);
+ ED_slider_status_string_get(gso->slider, slider_string, UI_MAX_DRAW_STR);
strcpy(mode_str, TIP_("Decimate Keyframes"));
- if (hasNumInput(&dgo->num)) {
+ if (hasNumInput(&gso->num)) {
char str_ofs[NUM_STR_REP_LEN];
- outputNumInput(&dgo->num, str_ofs, &dgo->scene->unit);
+ outputNumInput(&gso->num, str_ofs, &gso->scene->unit);
BLI_snprintf(status_str, sizeof(status_str), "%s: %s", mode_str, str_ofs);
}
@@ -210,76 +266,34 @@ static void decimate_draw_status(bContext *C, tDecimateGraphOp *dgo)
static int graphkeys_decimate_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
- tDecimateGraphOp *dgo;
+ tGraphSliderOp *gso;
WM_cursor_modal_set(CTX_wm_window(C), WM_CURSOR_EW_SCROLL);
/* Init slide-op data. */
- dgo = op->customdata = MEM_callocN(sizeof(tDecimateGraphOp), "tDecimateGraphOp");
+ gso = op->customdata = MEM_callocN(sizeof(tGraphSliderOp), "tGraphSliderOp");
/* Get editor data. */
- if (ANIM_animdata_get_context(C, &dgo->ac) == 0) {
+ if (ANIM_animdata_get_context(C, &gso->ac) == 0) {
decimate_exit(C, op);
return OPERATOR_CANCELLED;
}
- dgo->percentage_prop = RNA_struct_find_property(op->ptr, "remove_ratio");
-
- dgo->scene = CTX_data_scene(C);
- dgo->area = CTX_wm_area(C);
- dgo->region = CTX_wm_region(C);
-
- dgo->slider = ED_slider_create(C);
- ED_slider_init(dgo->slider, event);
- ED_slider_allow_overshoot_set(dgo->slider, false);
-
- decimate_draw_status(C, dgo);
-
- /* Construct a list with the original bezt arrays so we can restore them during modal operation.
- */
- {
- ListBase anim_data = {NULL, NULL};
- bAnimContext *ac = &dgo->ac;
- bAnimListElem *ale;
+ gso->percentage_prop = RNA_struct_find_property(op->ptr, "remove_ratio");
- int filter;
+ gso->scene = CTX_data_scene(C);
+ gso->area = CTX_wm_area(C);
+ gso->region = CTX_wm_region(C);
- /* Filter data. */
- filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_CURVE_VISIBLE | ANIMFILTER_FOREDIT |
- ANIMFILTER_SEL | ANIMFILTER_NODUPLIS);
- ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
+ store_original_bezt_arrays(gso);
- /* Loop through filtered data and copy the curves. */
- for (ale = anim_data.first; ale; ale = ale->next) {
- FCurve *fcu = (FCurve *)ale->key_data;
+ gso->slider = ED_slider_create(C);
+ ED_slider_init(gso->slider, event);
+ ED_slider_allow_overshoot_set(gso->slider, false);
- if (fcu->bezt == NULL) {
- /* This curve is baked, skip it. */
- continue;
- }
-
- const int arr_size = sizeof(BezTriple) * fcu->totvert;
-
- tBeztCopyData *copy = MEM_mallocN(sizeof(tBeztCopyData), "bezts_copy");
- BezTriple *bezts_copy = MEM_mallocN(arr_size, "bezts_copy_array");
-
- copy->tot_vert = fcu->totvert;
- memcpy(bezts_copy, fcu->bezt, arr_size);
-
- copy->bezt = bezts_copy;
-
- LinkData *link = NULL;
+ decimate_draw_status(C, gso);
- link = MEM_callocN(sizeof(LinkData), "Bezt Link");
- link->data = copy;
-
- BLI_addtail(&dgo->bezt_arr_list, link);
- }
-
- ANIM_animdata_freelist(&anim_data);
- }
-
- if (dgo->bezt_arr_list.first == NULL) {
+ if (gso->bezt_arr_list.first == NULL) {
WM_report(RPT_WARNING,
"Fcurve Decimate: Can't decimate baked channels. Unbake them and try again.");
decimate_exit(C, op);
@@ -294,19 +308,19 @@ static void graphkeys_decimate_modal_update(bContext *C, wmOperator *op)
{
/* Perform decimate updates - in response to some user action
* (e.g. pressing a key or moving the mouse). */
- tDecimateGraphOp *dgo = op->customdata;
+ tGraphSliderOp *gso = op->customdata;
- decimate_draw_status(C, dgo);
+ decimate_draw_status(C, gso);
/* Reset keyframe data (so we get back to the original state). */
- decimate_reset_bezts(dgo);
+ reset_bezts(gso);
/* Apply... */
- float remove_ratio = ED_slider_factor_get(dgo->slider);
- RNA_property_float_set(op->ptr, dgo->percentage_prop, remove_ratio);
+ float remove_ratio = ED_slider_factor_get(gso->slider);
+ RNA_property_float_set(op->ptr, gso->percentage_prop, remove_ratio);
/* We don't want to limit the decimation to a certain error margin. */
const float error_sq_max = FLT_MAX;
- decimate_graph_keys(&dgo->ac, remove_ratio, error_sq_max);
+ decimate_graph_keys(&gso->ac, remove_ratio, error_sq_max);
WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_EDITED, NULL);
}
@@ -316,11 +330,11 @@ static int graphkeys_decimate_modal(bContext *C, wmOperator *op, const wmEvent *
* and finicky to control with this modal mouse grab method. Therefore, it is expected that the
* error margin mode is not adjusted by the modal operator but instead tweaked via the redo
* panel. */
- tDecimateGraphOp *dgo = op->customdata;
+ tGraphSliderOp *gso = op->customdata;
- const bool has_numinput = hasNumInput(&dgo->num);
+ const bool has_numinput = hasNumInput(&gso->num);
- ED_slider_modal(dgo->slider, event);
+ ED_slider_modal(gso->slider, event);
switch (event->type) {
case LEFTMOUSE: /* Confirm */
@@ -337,7 +351,7 @@ static int graphkeys_decimate_modal(bContext *C, wmOperator *op, const wmEvent *
case EVT_ESCKEY: /* Cancel */
case RIGHTMOUSE: {
if (event->val == KM_PRESS) {
- decimate_reset_bezts(dgo);
+ reset_bezts(gso);
WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_EDITED, NULL);
@@ -358,18 +372,18 @@ static int graphkeys_decimate_modal(bContext *C, wmOperator *op, const wmEvent *
break;
}
default: {
- if ((event->val == KM_PRESS) && handleNumInput(C, &dgo->num, event)) {
+ if ((event->val == KM_PRESS) && handleNumInput(C, &gso->num, event)) {
float value;
- float percentage = RNA_property_float_get(op->ptr, dgo->percentage_prop);
+ float percentage = RNA_property_float_get(op->ptr, gso->percentage_prop);
/* Grab percentage from numeric input, and store this new value for redo
* NOTE: users see ints, while internally we use a 0-1 float.
*/
value = percentage * 100.0f;
- applyNumInput(&dgo->num, &value);
+ applyNumInput(&gso->num, &value);
percentage = value / 100.0f;
- RNA_property_float_set(op->ptr, dgo->percentage_prop, percentage);
+ RNA_property_float_set(op->ptr, gso->percentage_prop, percentage);
/* Update decimate output to reflect the new values. */
graphkeys_decimate_modal_update(C, op);
@@ -520,3 +534,5 @@ void GRAPH_OT_decimate(wmOperatorType *ot)
0.0f,
10.0f);
}
+
+/** \} */
diff --git a/source/blender/editors/space_graph/graph_utils.c b/source/blender/editors/space_graph/graph_utils.c
index c37d9f42c12..89e7fefd9ac 100644
--- a/source/blender/editors/space_graph/graph_utils.c
+++ b/source/blender/editors/space_graph/graph_utils.c
@@ -46,8 +46,9 @@
#include "graph_intern.h" /* own include */
-/* ************************************************************** */
-/* Set Up Drivers Editor */
+/* -------------------------------------------------------------------- */
+/** \name Set Up Drivers Editor
+ * \{ */
/* Set up UI configuration for Drivers Editor */
/* NOTE: Currently called from window-manager
@@ -89,8 +90,11 @@ void ED_drivers_editor_init(bContext *C, ScrArea *area)
}
}
-/* ************************************************************** */
-/* Active F-Curve */
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Active F-Curve
+ * \{ */
/**
* Find 'active' F-Curve.
@@ -124,8 +128,11 @@ bAnimListElem *get_active_fcurve_channel(bAnimContext *ac)
return NULL;
}
-/* ************************************************************** */
-/* Operator Polling Callbacks */
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Operator Polling Callbacks
+ * \{ */
/* Check if there are any visible keyframes (for selection tools) */
bool graphop_visible_keyframes_poll(bContext *C)
@@ -321,4 +328,4 @@ bool graphop_selected_fcurve_poll(bContext *C)
return true;
}
-/* ************************************************************** */
+/** \} */
diff --git a/source/blender/editors/space_graph/graph_view.c b/source/blender/editors/space_graph/graph_view.c
index 56649c50cfd..a12c6053877 100644
--- a/source/blender/editors/space_graph/graph_view.c
+++ b/source/blender/editors/space_graph/graph_view.c
@@ -17,6 +17,10 @@
* All rights reserved.
*/
+/** \file
+ * \ingroup spgraph
+ */
+
#include <math.h>
#include "MEM_guardedalloc.h"
@@ -48,7 +52,9 @@
#include "graph_intern.h"
-/* *************************** Calculate Range ************************** */
+/* -------------------------------------------------------------------- */
+/** \name Calculate Range
+ * \{ */
/* Get the min/max keyframes. */
/* NOTE: it should return total boundbox, filter for selection only can be argument... */
@@ -194,7 +200,11 @@ void get_graph_keyframe_extents(bAnimContext *ac,
}
}
-/* ****************** Automatic Preview-Range Operator ****************** */
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Automatic Preview-Range Operator
+ * \{ */
static int graphkeys_previewrange_exec(bContext *C, wmOperator *UNUSED(op))
{
@@ -241,7 +251,11 @@ void GRAPH_OT_previewrange_set(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
-/* ****************** View-All Operator ****************** */
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name View-All Operator
+ * \{ */
static int graphkeys_viewall(bContext *C,
const bool do_sel_only,
@@ -347,7 +361,11 @@ void GRAPH_OT_view_selected(wmOperatorType *ot)
"Include handles of keyframes when calculating extents");
}
-/* ********************** View Frame Operator ****************************** */
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name View Frame Operator
+ * \{ */
static int graphkeys_view_frame_exec(bContext *C, wmOperator *op)
{
@@ -371,10 +389,14 @@ void GRAPH_OT_view_frame(wmOperatorType *ot)
ot->flag = 0;
}
-/* ******************** Create Ghost-Curves Operator *********************** */
-/* This operator samples the data of the selected F-Curves to F-Points, storing them
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Create Ghost-Curves Operator
+ *
+ * This operator samples the data of the selected F-Curves to F-Points, storing them
* as 'ghost curves' in the active Graph Editor.
- */
+ * \{ */
/* Bake each F-Curve into a set of samples, and store as a ghost curve. */
static void create_ghost_curves(bAnimContext *ac, int start, int end)
@@ -493,8 +515,13 @@ void GRAPH_OT_ghost_curves_create(wmOperatorType *ot)
/* TODO: add props for start/end frames */
}
-/* ******************** Clear Ghost-Curves Operator *********************** */
-/* This operator clears the 'ghost curves' for the active Graph Editor */
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Clear Ghost-Curves Operator
+ *
+ * This operator clears the 'ghost curves' for the active Graph Editor.
+ * \{ */
static int graphkeys_clear_ghostcurves_exec(bContext *C, wmOperator *UNUSED(op))
{
@@ -534,3 +561,5 @@ void GRAPH_OT_ghost_curves_clear(wmOperatorType *ot)
/* Flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
+
+/** \} */
diff --git a/source/blender/editors/space_image/image_draw.c b/source/blender/editors/space_image/image_draw.c
index 22a43ea3794..d76b1842c94 100644
--- a/source/blender/editors/space_image/image_draw.c
+++ b/source/blender/editors/space_image/image_draw.c
@@ -185,7 +185,7 @@ void ED_image_draw_info(Scene *scene,
GPU_blend(GPU_BLEND_NONE);
- BLF_size(blf_mono_font, 11 * U.pixelsize, U.dpi);
+ BLF_size(blf_mono_font, 11.0f * U.pixelsize, U.dpi);
BLF_color3ub(blf_mono_font, 255, 255, 255);
SNPRINTF(str, "X:%-4d Y:%-4d |", x, y);
diff --git a/source/blender/editors/space_image/image_ops.c b/source/blender/editors/space_image/image_ops.c
index 478e484924a..44794439f5f 100644
--- a/source/blender/editors/space_image/image_ops.c
+++ b/source/blender/editors/space_image/image_ops.c
@@ -3191,7 +3191,10 @@ void IMAGE_OT_unpack(wmOperatorType *ot)
* \{ */
/* Returns mouse position in image space. */
-bool ED_space_image_get_position(SpaceImage *sima, struct ARegion *ar, int mval[2], float fpos[2])
+bool ED_space_image_get_position(SpaceImage *sima,
+ struct ARegion *region,
+ int mval[2],
+ float fpos[2])
{
void *lock;
ImBuf *ibuf = ED_space_image_acquire_buffer(sima, &lock, 0);
@@ -3201,7 +3204,7 @@ bool ED_space_image_get_position(SpaceImage *sima, struct ARegion *ar, int mval[
return false;
}
- UI_view2d_region_to_view(&ar->v2d, mval[0], mval[1], &fpos[0], &fpos[1]);
+ UI_view2d_region_to_view(&region->v2d, mval[0], mval[1], &fpos[0], &fpos[1]);
ED_space_image_release_buffer(sima, ibuf, lock);
return true;
diff --git a/source/blender/editors/space_info/CMakeLists.txt b/source/blender/editors/space_info/CMakeLists.txt
index b6df07eec4e..144b21fb9b8 100644
--- a/source/blender/editors/space_info/CMakeLists.txt
+++ b/source/blender/editors/space_info/CMakeLists.txt
@@ -37,7 +37,7 @@ set(SRC
info_draw.c
info_ops.c
info_report.c
- info_stats.c
+ info_stats.cc
space_info.c
textview.c
diff --git a/source/blender/editors/space_info/info_stats.c b/source/blender/editors/space_info/info_stats.cc
index 13d15bc50a6..19c98fb4d17 100644
--- a/source/blender/editors/space_info/info_stats.c
+++ b/source/blender/editors/space_info/info_stats.cc
@@ -18,8 +18,8 @@
* \ingroup spinfo
*/
-#include <stdio.h>
-#include <string.h>
+#include <cstdio>
+#include <cstring>
#include "MEM_guardedalloc.h"
@@ -70,9 +70,11 @@
#include "GPU_capabilities.h"
+ENUM_OPERATORS(eUserpref_StatusBar_Flag, STATUSBAR_SHOW_VERSION)
+
#define MAX_INFO_NUM_LEN 16
-typedef struct SceneStats {
+struct SceneStats {
uint64_t totvert, totvertsel, totvertsculpt;
uint64_t totedge, totedgesel;
uint64_t totface, totfacesel, totfacesculpt;
@@ -81,9 +83,9 @@ typedef struct SceneStats {
uint64_t totlamp, totlampsel;
uint64_t tottri;
uint64_t totgplayer, totgpframe, totgpstroke, totgppoint;
-} SceneStats;
+};
-typedef struct SceneStatsFmt {
+struct SceneStatsFmt {
/* Totals */
char totvert[MAX_INFO_NUM_LEN], totvertsel[MAX_INFO_NUM_LEN], totvertsculpt[MAX_INFO_NUM_LEN];
char totface[MAX_INFO_NUM_LEN], totfacesel[MAX_INFO_NUM_LEN];
@@ -94,16 +96,16 @@ typedef struct SceneStatsFmt {
char tottri[MAX_INFO_NUM_LEN];
char totgplayer[MAX_INFO_NUM_LEN], totgpframe[MAX_INFO_NUM_LEN];
char totgpstroke[MAX_INFO_NUM_LEN], totgppoint[MAX_INFO_NUM_LEN];
-} SceneStatsFmt;
+};
static bool stats_mesheval(const Mesh *me_eval, bool is_selected, SceneStats *stats)
{
- if (me_eval == NULL) {
+ if (me_eval == nullptr) {
return false;
}
int totvert, totedge, totface, totloop;
- if (me_eval->runtime.subdiv_ccg != NULL) {
+ if (me_eval->runtime.subdiv_ccg != nullptr) {
const SubdivCCG *subdiv_ccg = me_eval->runtime.subdiv_ccg;
BKE_subdiv_ccg_topology_counters(subdiv_ccg, &totvert, &totedge, &totface, &totloop);
}
@@ -166,14 +168,14 @@ static void stats_object(Object *ob,
case OB_CURVE:
case OB_FONT: {
const Mesh *me_eval = BKE_object_get_evaluated_mesh(ob);
- if ((me_eval != NULL) && !BLI_gset_add(objects_gset, (void *)me_eval)) {
+ if ((me_eval != nullptr) && !BLI_gset_add(objects_gset, (void *)me_eval)) {
break;
}
if (stats_mesheval(me_eval, is_selected, stats)) {
break;
}
- ATTR_FALLTHROUGH; /* Fallthrough to displist. */
+ ATTR_FALLTHROUGH; /* Fall-through to displist. */
}
case OB_MBALL: {
int totv = 0, totf = 0, tottri = 0;
@@ -242,10 +244,9 @@ static void stats_object_edit(Object *obedit, SceneStats *stats)
}
else if (obedit->type == OB_ARMATURE) {
/* Armature Edit */
- bArmature *arm = obedit->data;
- EditBone *ebo;
+ bArmature *arm = static_cast<bArmature *>(obedit->data);
- for (ebo = arm->edbo->first; ebo; ebo = ebo->next) {
+ LISTBASE_FOREACH (EditBone *, ebo, arm->edbo) {
stats->totbone++;
if ((ebo->flag & BONE_CONNECTED) && ebo->parent) {
@@ -274,14 +275,13 @@ static void stats_object_edit(Object *obedit, SceneStats *stats)
}
else if (ELEM(obedit->type, OB_CURVE, OB_SURF)) { /* OB_FONT has no cu->editnurb */
/* Curve Edit */
- Curve *cu = obedit->data;
- Nurb *nu;
+ Curve *cu = static_cast<Curve *>(obedit->data);
BezTriple *bezt;
BPoint *bp;
int a;
ListBase *nurbs = BKE_curve_editNurbs_get(cu);
- for (nu = nurbs->first; nu; nu = nu->next) {
+ LISTBASE_FOREACH (Nurb *, nu, nurbs) {
if (nu->type == CU_BEZIER) {
bezt = nu->bezt;
a = nu->pntsu;
@@ -314,10 +314,9 @@ static void stats_object_edit(Object *obedit, SceneStats *stats)
}
else if (obedit->type == OB_MBALL) {
/* MetaBall Edit */
- MetaBall *mball = obedit->data;
- MetaElem *ml;
+ MetaBall *mball = static_cast<MetaBall *>(obedit->data);
- for (ml = mball->editelems->first; ml; ml = ml->next) {
+ LISTBASE_FOREACH (MetaElem *, ml, mball->editelems) {
stats->totvert++;
if (ml->flag & SELECT) {
stats->totvertsel++;
@@ -326,7 +325,7 @@ static void stats_object_edit(Object *obedit, SceneStats *stats)
}
else if (obedit->type == OB_LATTICE) {
/* Lattice Edit */
- Lattice *lt = obedit->data;
+ Lattice *lt = static_cast<Lattice *>(obedit->data);
Lattice *editlatt = lt->editlatt->latt;
BPoint *bp;
int a;
@@ -347,10 +346,9 @@ static void stats_object_edit(Object *obedit, SceneStats *stats)
static void stats_object_pose(const Object *ob, SceneStats *stats)
{
if (ob->pose) {
- bArmature *arm = ob->data;
- bPoseChannel *pchan;
+ bArmature *arm = static_cast<bArmature *>(ob->data);
- for (pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) {
+ LISTBASE_FOREACH (bPoseChannel *, pchan, &ob->pose->chanbase) {
stats->totbone++;
if (pchan->bone && (pchan->bone->flag & BONE_SELECTED)) {
if (pchan->bone->layer & arm->layer) {
@@ -372,7 +370,7 @@ static void stats_object_sculpt(const Object *ob, SceneStats *stats)
SculptSession *ss = ob->sculpt;
- if (ss == NULL || ss->pbvh == NULL) {
+ if (ss == nullptr || ss->pbvh == nullptr) {
return;
}
@@ -460,7 +458,7 @@ static void stats_update(Depsgraph *depsgraph,
stats_object(ob_iter, v3d_local, stats, objects_gset);
}
DEG_OBJECT_ITER_FOR_RENDER_ENGINE_END;
- BLI_gset_free(objects_gset, NULL);
+ BLI_gset_free(objects_gset, nullptr);
}
}
@@ -476,7 +474,7 @@ void ED_info_stats_clear(wmWindowManager *wm, ViewLayer *view_layer)
const bScreen *screen = WM_window_get_active_screen(win);
LISTBASE_FOREACH (ScrArea *, area, &screen->areabase) {
if (area->spacetype == SPACE_VIEW3D) {
- View3D *v3d = area->spacedata.first;
+ View3D *v3d = (View3D *)area->spacedata.first;
if (v3d->localvd) {
MEM_SAFE_FREE(v3d->runtime.local_stats);
}
@@ -490,14 +488,14 @@ static bool format_stats(
{
/* Create stats if they don't already exist. */
SceneStats **stats_p = (v3d_local) ? &v3d_local->runtime.local_stats : &view_layer->stats;
- if (*stats_p == NULL) {
+ if (*stats_p == nullptr) {
/* Don't access dependency graph if interface is marked as locked. */
- wmWindowManager *wm = bmain->wm.first;
+ wmWindowManager *wm = (wmWindowManager *)bmain->wm.first;
if (wm->is_interface_locked) {
return false;
}
Depsgraph *depsgraph = BKE_scene_ensure_depsgraph(bmain, scene, view_layer);
- *stats_p = MEM_mallocN(sizeof(SceneStats), __func__);
+ *stats_p = (SceneStats *)MEM_mallocN(sizeof(SceneStats), __func__);
stats_update(depsgraph, view_layer, v3d_local, *stats_p);
}
@@ -542,7 +540,7 @@ static void get_stats_string(
{
Object *ob = OBACT(view_layer);
Object *obedit = OBEDIT_FROM_OBACT(ob);
- eObjectMode object_mode = ob ? ob->mode : OB_MODE_OBJECT;
+ eObjectMode object_mode = ob ? (eObjectMode)ob->mode : OB_MODE_OBJECT;
LayerCollection *layer_collection = view_layer->active_collection;
if (object_mode == OB_MODE_OBJECT) {
@@ -646,7 +644,7 @@ static const char *info_statusbar_string(Main *bmain,
/* Scene statistics. */
if (statusbar_flag & STATUSBAR_SHOW_STATS) {
SceneStatsFmt stats_fmt;
- if (format_stats(bmain, scene, view_layer, NULL, &stats_fmt)) {
+ if (format_stats(bmain, scene, view_layer, nullptr, &stats_fmt)) {
get_stats_string(info + ofs, len, &ofs, view_layer, &stats_fmt);
}
}
@@ -731,7 +729,7 @@ static void stats_row(int col1,
void ED_info_draw_stats(
Main *bmain, Scene *scene, ViewLayer *view_layer, View3D *v3d_local, int x, int *y, int height)
{
- BLI_assert(v3d_local == NULL || v3d_local->localvd != NULL);
+ BLI_assert(v3d_local == nullptr || v3d_local->localvd != nullptr);
SceneStatsFmt stats_fmt;
if (!format_stats(bmain, scene, view_layer, v3d_local, &stats_fmt)) {
return;
@@ -739,7 +737,7 @@ void ED_info_draw_stats(
Object *ob = OBACT(view_layer);
Object *obedit = OBEDIT_FROM_OBACT(ob);
- eObjectMode object_mode = ob ? ob->mode : OB_MODE_OBJECT;
+ eObjectMode object_mode = ob ? (eObjectMode)ob->mode : OB_MODE_OBJECT;
const int font_id = BLF_set_default();
UI_FontThemeColor(font_id, TH_TEXT_HI);
@@ -801,7 +799,7 @@ void ED_info_draw_stats(
stats_row(col1, labels[VERTS], col2, stats_fmt.totvertsel, stats_fmt.totvert, y, height);
stats_row(col1, labels[EDGES], col2, stats_fmt.totedgesel, stats_fmt.totedge, y, height);
stats_row(col1, labels[FACES], col2, stats_fmt.totfacesel, stats_fmt.totface, y, height);
- stats_row(col1, labels[TRIS], col2, stats_fmt.tottri, NULL, y, height);
+ stats_row(col1, labels[TRIS], col2, stats_fmt.tottri, nullptr, y, height);
}
else if (obedit->type == OB_ARMATURE) {
stats_row(col1, labels[JOINTS], col2, stats_fmt.totvertsel, stats_fmt.totvert, y, height);
@@ -816,15 +814,15 @@ void ED_info_draw_stats(
stats_row(col1, labels[BONES], col2, stats_fmt.totbonesel, stats_fmt.totbone, y, height);
}
else if ((ob) && (ob->type == OB_GPENCIL)) {
- stats_row(col1, labels[LAYERS], col2, stats_fmt.totgplayer, NULL, y, height);
- stats_row(col1, labels[FRAMES], col2, stats_fmt.totgpframe, NULL, y, height);
- stats_row(col1, labels[STROKES], col2, stats_fmt.totgpstroke, NULL, y, height);
- stats_row(col1, labels[POINTS], col2, stats_fmt.totgppoint, NULL, y, height);
+ stats_row(col1, labels[LAYERS], col2, stats_fmt.totgplayer, nullptr, y, height);
+ stats_row(col1, labels[FRAMES], col2, stats_fmt.totgpframe, nullptr, y, height);
+ stats_row(col1, labels[STROKES], col2, stats_fmt.totgpstroke, nullptr, y, height);
+ stats_row(col1, labels[POINTS], col2, stats_fmt.totgppoint, nullptr, y, height);
}
else if (ob && (object_mode & OB_MODE_SCULPT)) {
if (stats_is_object_dynamic_topology_sculpt(ob)) {
- stats_row(col1, labels[VERTS], col2, stats_fmt.totvertsculpt, NULL, y, height);
- stats_row(col1, labels[TRIS], col2, stats_fmt.tottri, NULL, y, height);
+ stats_row(col1, labels[VERTS], col2, stats_fmt.totvertsculpt, nullptr, y, height);
+ stats_row(col1, labels[TRIS], col2, stats_fmt.tottri, nullptr, y, height);
}
else {
stats_row(col1, labels[VERTS], col2, stats_fmt.totvertsculpt, stats_fmt.totvert, y, height);
@@ -835,10 +833,10 @@ void ED_info_draw_stats(
stats_row(col1, labels[LIGHTS], col2, stats_fmt.totlampsel, stats_fmt.totlamp, y, height);
}
else {
- stats_row(col1, labels[VERTS], col2, stats_fmt.totvert, NULL, y, height);
- stats_row(col1, labels[EDGES], col2, stats_fmt.totedge, NULL, y, height);
- stats_row(col1, labels[FACES], col2, stats_fmt.totface, NULL, y, height);
- stats_row(col1, labels[TRIS], col2, stats_fmt.tottri, NULL, y, height);
+ stats_row(col1, labels[VERTS], col2, stats_fmt.totvert, nullptr, y, height);
+ stats_row(col1, labels[EDGES], col2, stats_fmt.totedge, nullptr, y, height);
+ stats_row(col1, labels[FACES], col2, stats_fmt.totface, nullptr, y, height);
+ stats_row(col1, labels[TRIS], col2, stats_fmt.tottri, nullptr, y, height);
}
BLF_disable(font_id, BLF_SHADOW);
diff --git a/source/blender/editors/space_node/CMakeLists.txt b/source/blender/editors/space_node/CMakeLists.txt
index 600309c2c86..e88d61fe880 100644
--- a/source/blender/editors/space_node/CMakeLists.txt
+++ b/source/blender/editors/space_node/CMakeLists.txt
@@ -44,17 +44,17 @@ set(SRC
node_draw.cc
node_edit.cc
node_geometry_attribute_search.cc
- node_gizmo.c
+ node_gizmo.cc
node_group.cc
- node_ops.c
+ node_ops.cc
node_relationships.cc
node_select.cc
node_templates.cc
node_toolbar.cc
node_view.cc
- space_node.c
+ space_node.cc
- node_intern.h
+ node_intern.hh
)
set(LIB
diff --git a/source/blender/editors/space_node/drawnode.cc b/source/blender/editors/space_node/drawnode.cc
index 57fecba76f7..97fa93ab0bc 100644
--- a/source/blender/editors/space_node/drawnode.cc
+++ b/source/blender/editors/space_node/drawnode.cc
@@ -77,7 +77,7 @@
#include "NOD_node_declaration.hh"
#include "NOD_shader.h"
#include "NOD_texture.h"
-#include "node_intern.h" /* own include */
+#include "node_intern.hh" /* own include */
/* Default flags for uiItemR(). Name is kept short since this is used a lot in this file. */
#define DEFAULT_FLAGS UI_ITEM_R_SPLIT_EMPTY_NAME
@@ -152,7 +152,7 @@ static void node_buts_time(uiLayout *layout, bContext *UNUSED(C), PointerRNA *pt
uiTemplateCurveMapping(layout, ptr, "curve", 's', false, false, false, false);
uiLayout *row = uiLayoutRow(layout, true);
- uiItemR(row, ptr, "frame_start", DEFAULT_FLAGS, IFACE_("Sta"), ICON_NONE);
+ uiItemR(row, ptr, "frame_start", DEFAULT_FLAGS, IFACE_("Start"), ICON_NONE);
uiItemR(row, ptr, "frame_end", DEFAULT_FLAGS, IFACE_("End"), ICON_NONE);
}
@@ -337,12 +337,13 @@ static void node_draw_frame_prepare(const bContext *UNUSED(C), bNodeTree *ntree,
node->totr = rect;
}
-static void node_draw_frame_label(bNodeTree *ntree, bNode *node, const float aspect)
+static void node_draw_frame_label(bNodeTree *ntree, bNode *node, SpaceNode *snode)
{
+ const float aspect = snode->runtime->aspect;
/* XXX font id is crap design */
const int fontid = UI_style_get()->widgetlabel.uifont_id;
NodeFrame *data = (NodeFrame *)node->storage;
- const int font_size = data->label_size / aspect;
+ const float font_size = data->label_size / aspect;
char label[MAX_NAME];
nodeLabel(ntree, node, label, sizeof(label));
@@ -350,7 +351,7 @@ static void node_draw_frame_label(bNodeTree *ntree, bNode *node, const float asp
BLF_enable(fontid, BLF_ASPECT);
BLF_aspect(fontid, aspect, aspect, 1.0f);
/* clamp otherwise it can suck up a LOT of memory */
- BLF_size(fontid, MIN2(24, font_size), U.dpi);
+ BLF_size(fontid, MIN2(24.0f, font_size), U.dpi);
/* title color */
int color_id = node_get_colorid(node);
@@ -468,7 +469,9 @@ static void node_draw_frame(const bContext *C,
}
/* label and text */
- node_draw_frame_label(ntree, node, snode->runtime->aspect);
+ node_draw_frame_label(ntree, node, snode);
+
+ node_draw_extra_info_panel(snode, node);
UI_block_end(C, node->block);
UI_block_draw(C, node->block);
@@ -4399,7 +4402,10 @@ void node_draw_link_bezier(const bContext *C,
}
/* NOTE: this is used for fake links in groups too. */
-void node_draw_link(const bContext *C, View2D *v2d, SpaceNode *snode, bNodeLink *link)
+void node_draw_link(const bContext *C,
+ const View2D *v2d,
+ const SpaceNode *snode,
+ const bNodeLink *link)
{
int th_col1 = TH_WIRE_INNER, th_col2 = TH_WIRE_INNER, th_col3 = TH_WIRE;
diff --git a/source/blender/editors/space_node/node_add.cc b/source/blender/editors/space_node/node_add.cc
index f84de363430..2e3579caaa1 100644
--- a/source/blender/editors/space_node/node_add.cc
+++ b/source/blender/editors/space_node/node_add.cc
@@ -56,7 +56,7 @@
#include "UI_view2d.h"
-#include "node_intern.h" /* own include */
+#include "node_intern.hh" /* own include */
/* -------------------------------------------------------------------- */
/** \name Utilities
diff --git a/source/blender/editors/space_node/node_context_path.cc b/source/blender/editors/space_node/node_context_path.cc
index a0ff7f3ce25..2f3855fd654 100644
--- a/source/blender/editors/space_node/node_context_path.cc
+++ b/source/blender/editors/space_node/node_context_path.cc
@@ -43,7 +43,7 @@
#include "UI_interface.hh"
-#include "node_intern.h"
+#include "node_intern.hh"
struct Mesh;
struct Curve;
diff --git a/source/blender/editors/space_node/node_draw.cc b/source/blender/editors/space_node/node_draw.cc
index b6c24a55a78..1d62321cae3 100644
--- a/source/blender/editors/space_node/node_draw.cc
+++ b/source/blender/editors/space_node/node_draw.cc
@@ -85,7 +85,9 @@
#include "FN_field_cpp_type.hh"
-#include "node_intern.h" /* own include */
+#include "node_intern.hh" /* own include */
+
+#include <iomanip>
#ifdef WITH_COMPOSITOR
# include "COM_compositor.h"
@@ -843,29 +845,43 @@ struct SocketTooltipData {
bNodeSocket *socket;
};
-static void create_inspection_string_for_generic_value(const geo_log::GenericValueLog &value_log,
- std::stringstream &ss)
+static void create_inspection_string_for_generic_value(const GPointer value, std::stringstream &ss)
{
auto id_to_inspection_string = [&](ID *id, short idcode) {
ss << (id ? id->name + 2 : TIP_("None")) << " (" << BKE_idtype_idcode_to_name(idcode) << ")";
};
- const GPointer value = value_log.value();
const CPPType &type = *value.type();
+ const void *buffer = value.get();
if (type.is<Object *>()) {
- id_to_inspection_string((ID *)*value.get<Object *>(), ID_OB);
+ id_to_inspection_string((ID *)buffer, ID_OB);
}
else if (type.is<Material *>()) {
- id_to_inspection_string((ID *)*value.get<Material *>(), ID_MA);
+ id_to_inspection_string((ID *)buffer, ID_MA);
}
else if (type.is<Tex *>()) {
- id_to_inspection_string((ID *)*value.get<Tex *>(), ID_TE);
+ id_to_inspection_string((ID *)buffer, ID_TE);
}
else if (type.is<Image *>()) {
- id_to_inspection_string((ID *)*value.get<Image *>(), ID_IM);
+ id_to_inspection_string((ID *)buffer, ID_IM);
}
else if (type.is<Collection *>()) {
- id_to_inspection_string((ID *)*value.get<Collection *>(), ID_GR);
+ id_to_inspection_string((ID *)buffer, ID_GR);
+ }
+ else if (type.is<int>()) {
+ ss << *(int *)buffer << TIP_(" (Integer)");
+ }
+ else if (type.is<float>()) {
+ ss << *(float *)buffer << TIP_(" (Float)");
+ }
+ else if (type.is<blender::float3>()) {
+ ss << *(blender::float3 *)buffer << TIP_(" (Vector)");
+ }
+ else if (type.is<bool>()) {
+ ss << ((*(bool *)buffer) ? TIP_("True") : TIP_("False")) << TIP_(" (Boolean)");
+ }
+ else if (type.is<std::string>()) {
+ ss << *(std::string *)buffer << TIP_(" (String)");
}
}
@@ -880,21 +896,7 @@ static void create_inspection_string_for_gfield(const geo_log::GFieldValueLog &v
if (field) {
BUFFER_FOR_CPP_TYPE_VALUE(type, buffer);
blender::fn::evaluate_constant_field(field, buffer);
- if (type.is<int>()) {
- ss << *(int *)buffer << TIP_(" (Integer)");
- }
- else if (type.is<float>()) {
- ss << *(float *)buffer << TIP_(" (Float)");
- }
- else if (type.is<blender::float3>()) {
- ss << *(blender::float3 *)buffer << TIP_(" (Vector)");
- }
- else if (type.is<bool>()) {
- ss << ((*(bool *)buffer) ? TIP_("True") : TIP_("False")) << TIP_(" (Boolean)");
- }
- else if (type.is<std::string>()) {
- ss << *(std::string *)buffer << TIP_(" (String)");
- }
+ create_inspection_string_for_generic_value({type, buffer}, ss);
type.destruct(buffer);
}
else {
@@ -1023,7 +1025,7 @@ static std::optional<std::string> create_socket_inspection_string(bContext *C,
std::stringstream ss;
if (const geo_log::GenericValueLog *generic_value_log =
dynamic_cast<const geo_log::GenericValueLog *>(value_log)) {
- create_inspection_string_for_generic_value(*generic_value_log, ss);
+ create_inspection_string_for_generic_value(generic_value_log->value(), ss);
}
if (const geo_log::GFieldValueLog *gfield_value_log =
dynamic_cast<const geo_log::GFieldValueLog *>(value_log)) {
@@ -1107,21 +1109,8 @@ static void node_socket_draw_nested(const bContext *C,
C, *data->ntree, *data->node, *data->socket);
std::stringstream output;
- if (data->node->declaration != nullptr) {
- ListBase *list;
- Span<blender::nodes::SocketDeclarationPtr> decl_list;
-
- if (data->socket->in_out == SOCK_IN) {
- list = &data->node->inputs;
- decl_list = data->node->declaration->inputs();
- }
- else {
- list = &data->node->outputs;
- decl_list = data->node->declaration->outputs();
- }
-
- const int socket_index = BLI_findindex(list, data->socket);
- const blender::nodes::SocketDeclaration &socket_decl = *decl_list[socket_index];
+ if (data->socket->declaration != nullptr) {
+ const blender::nodes::SocketDeclaration &socket_decl = *data->socket->declaration;
blender::StringRef description = socket_decl.description();
if (!description.is_empty()) {
output << TIP_(description.data()) << ".\n\n";
@@ -1590,6 +1579,235 @@ static void node_add_error_message_button(
UI_block_emboss_set(node.block, UI_EMBOSS);
}
+static void get_exec_time_other_nodes(const bNode *node,
+ const SpaceNode *snode,
+ std::chrono::microseconds &exec_time,
+ int &node_count)
+{
+ if (node->type == NODE_GROUP) {
+ const geo_log::TreeLog *root_tree_log = geo_log::ModifierLog::find_tree_by_node_editor_context(
+ *snode);
+ if (root_tree_log == nullptr) {
+ return;
+ }
+ const geo_log::TreeLog *tree_log = root_tree_log->lookup_child_log(node->name);
+ if (tree_log == nullptr) {
+ return;
+ }
+ tree_log->foreach_node_log([&](const geo_log::NodeLog &node_log) {
+ exec_time += node_log.execution_time();
+ node_count++;
+ });
+ }
+ else {
+ const geo_log::NodeLog *node_log = geo_log::ModifierLog::find_node_by_node_editor_context(
+ *snode, *node);
+ if (node_log) {
+ exec_time += node_log->execution_time();
+ node_count++;
+ }
+ }
+}
+
+static std::chrono::microseconds node_get_execution_time(const bNodeTree *ntree,
+ const bNode *node,
+ const SpaceNode *snode,
+ int &node_count)
+{
+ std::chrono::microseconds exec_time = std::chrono::microseconds::zero();
+ if (node->type == NODE_GROUP_OUTPUT) {
+ const geo_log::TreeLog *tree_log = geo_log::ModifierLog::find_tree_by_node_editor_context(
+ *snode);
+
+ if (tree_log == nullptr) {
+ return exec_time;
+ }
+ tree_log->foreach_node_log([&](const geo_log::NodeLog &node_log) {
+ exec_time += node_log.execution_time();
+ node_count++;
+ });
+ }
+ else if (node->type == NODE_FRAME) {
+ /* Could be cached in the future if this recursive code turns out to be slow. */
+ LISTBASE_FOREACH (bNode *, tnode, &ntree->nodes) {
+ if (tnode->parent != node) {
+ continue;
+ }
+
+ if (tnode->type == NODE_FRAME) {
+ exec_time += node_get_execution_time(ntree, tnode, snode, node_count);
+ }
+ else {
+ get_exec_time_other_nodes(tnode, snode, exec_time, node_count);
+ }
+ }
+ }
+ else {
+ get_exec_time_other_nodes(node, snode, exec_time, node_count);
+ }
+ return exec_time;
+}
+
+static std::string node_get_execution_time_label(const SpaceNode *snode, const bNode *node)
+{
+ int node_count = 0;
+ std::chrono::microseconds exec_time = node_get_execution_time(
+ snode->nodetree, node, snode, node_count);
+
+ if (node_count == 0) {
+ return std::string("");
+ }
+
+ uint64_t exec_time_us = exec_time.count();
+
+ /* Don't show time if execution time is 0 microseconds. */
+ if (exec_time_us == 0) {
+ return std::string("-");
+ }
+ if (exec_time_us < 100) {
+ return std::string("< 0.1 ms");
+ }
+
+ int precision = 0;
+ /* Show decimal if value is below 1ms */
+ if (exec_time_us < 1000) {
+ precision = 2;
+ }
+ else if (exec_time_us < 10000) {
+ precision = 1;
+ }
+
+ std::stringstream stream;
+ stream << std::fixed << std::setprecision(precision) << (exec_time_us / 1000.0f);
+ return stream.str() + " ms";
+}
+
+struct NodeExtraInfoRow {
+ std::string text;
+ const char *tooltip;
+ int icon;
+};
+
+static Vector<NodeExtraInfoRow> node_get_extra_info(const SpaceNode *snode, const bNode *node)
+{
+ Vector<NodeExtraInfoRow> rows;
+ if (!(snode->overlay.flag & SN_OVERLAY_SHOW_OVERLAYS)) {
+ return rows;
+ }
+
+ if (snode->overlay.flag & SN_OVERLAY_SHOW_TIMINGS && snode->edittree->type == NTREE_GEOMETRY &&
+ (ELEM(node->typeinfo->nclass, NODE_CLASS_GEOMETRY, NODE_CLASS_GROUP, NODE_CLASS_ATTRIBUTE) ||
+ ELEM(node->type, NODE_FRAME, NODE_GROUP_OUTPUT))) {
+ NodeExtraInfoRow row;
+ row.text = node_get_execution_time_label(snode, node);
+ if (!row.text.empty()) {
+ row.tooltip = TIP_(
+ "The execution time from the node tree's latest evaluation. For frame and group nodes, "
+ "the time for all sub-nodes");
+ row.icon = ICON_PREVIEW_RANGE;
+ rows.append(std::move(row));
+ }
+ }
+ return rows;
+}
+
+static void node_draw_extra_info_row(const bNode *node,
+ const rctf *rect,
+ const int row,
+ const NodeExtraInfoRow &extra_info_row)
+{
+ uiBut *but_timing = uiDefBut(node->block,
+ UI_BTYPE_LABEL,
+ 0,
+ extra_info_row.text.c_str(),
+ (int)(rect->xmin + 4.0f * U.dpi_fac + NODE_MARGIN_X + 0.4f),
+ (int)(rect->ymin + row * (20.0f * U.dpi_fac)),
+ (short)(rect->xmax - rect->xmin),
+ (short)NODE_DY,
+ nullptr,
+ 0,
+ 0,
+ 0,
+ 0,
+ "");
+ UI_block_emboss_set(node->block, UI_EMBOSS_NONE);
+ uiBut *but_icon = uiDefIconBut(node->block,
+ UI_BTYPE_BUT,
+ 0,
+ extra_info_row.icon,
+ (int)(rect->xmin + 6.0f * U.dpi_fac),
+ (int)(rect->ymin + row * (20.0f * U.dpi_fac)),
+ NODE_HEADER_ICON_SIZE * 0.8f,
+ UI_UNIT_Y,
+ nullptr,
+ 0,
+ 0,
+ 0,
+ 0,
+ extra_info_row.tooltip);
+ UI_block_emboss_set(node->block, UI_EMBOSS);
+ if (node->flag & NODE_MUTED) {
+ UI_but_flag_enable(but_timing, UI_BUT_INACTIVE);
+ UI_but_flag_enable(but_icon, UI_BUT_INACTIVE);
+ }
+}
+
+void node_draw_extra_info_panel(const SpaceNode *snode, const bNode *node)
+{
+ Vector<NodeExtraInfoRow> extra_info_rows = node_get_extra_info(snode, node);
+
+ if (extra_info_rows.size() == 0) {
+ return;
+ }
+
+ const rctf *rct = &node->totr;
+ float color[4];
+ rctf extra_info_rect;
+
+ if (node->type == NODE_FRAME) {
+ extra_info_rect.xmin = rct->xmin;
+ extra_info_rect.xmax = rct->xmin + 95.0f * U.dpi_fac;
+ extra_info_rect.ymin = rct->ymin + 2.0f * U.dpi_fac;
+ extra_info_rect.ymax = rct->ymin + 2.0f * U.dpi_fac;
+ }
+ else {
+ extra_info_rect.xmin = rct->xmin + 3.0f * U.dpi_fac;
+ extra_info_rect.xmax = rct->xmin + 95.0f * U.dpi_fac;
+ extra_info_rect.ymin = rct->ymax;
+ extra_info_rect.ymax = rct->ymax + extra_info_rows.size() * (20.0f * U.dpi_fac);
+
+ if (node->flag & NODE_MUTED) {
+ UI_GetThemeColorBlend4f(TH_BACK, TH_NODE, 0.2f, color);
+ }
+ else {
+ UI_GetThemeColorBlend4f(TH_BACK, TH_NODE, 0.75f, color);
+ }
+ color[3] -= 0.35f;
+ UI_draw_roundbox_corner_set(
+ UI_CNR_ALL & ~UI_CNR_BOTTOM_LEFT &
+ ((rct->xmax) > extra_info_rect.xmax ? ~UI_CNR_BOTTOM_RIGHT : UI_CNR_ALL));
+ UI_draw_roundbox_4fv(&extra_info_rect, true, BASIS_RAD, color);
+
+ /* Draw outline. */
+ const float outline_width = 1.0f;
+ extra_info_rect.xmin = rct->xmin + 3.0f * U.dpi_fac - outline_width;
+ extra_info_rect.xmax = rct->xmin + 95.0f * U.dpi_fac + outline_width;
+ extra_info_rect.ymin = rct->ymax - outline_width;
+ extra_info_rect.ymax = rct->ymax + outline_width +
+ extra_info_rows.size() * (20.0f * U.dpi_fac);
+
+ UI_GetThemeColorBlendShade4fv(TH_BACK, TH_NODE, 0.4f, -20, color);
+ UI_draw_roundbox_corner_set(
+ UI_CNR_ALL & ~UI_CNR_BOTTOM_LEFT &
+ ((rct->xmax) > extra_info_rect.xmax ? ~UI_CNR_BOTTOM_RIGHT : UI_CNR_ALL));
+ UI_draw_roundbox_4fv(&extra_info_rect, false, BASIS_RAD, color);
+ }
+
+ for (int row : extra_info_rows.index_range()) {
+ node_draw_extra_info_row(node, &extra_info_rect, row, extra_info_rows[row]);
+ }
+}
+
static void node_draw_basis(const bContext *C,
const View2D *v2d,
const SpaceNode *snode,
@@ -1615,6 +1833,8 @@ static void node_draw_basis(const bContext *C,
GPU_line_width(1.0f);
+ node_draw_extra_info_panel(snode, node);
+
/* Header. */
{
const rctf rect = {
@@ -1855,7 +2075,13 @@ static void node_draw_basis(const bContext *C,
UI_draw_roundbox_4fv(&rect, false, BASIS_RAD, color_outline);
}
- node_draw_sockets(v2d, C, ntree, node, true, false);
+ float scale;
+ UI_view2d_scale_get(v2d, &scale, nullptr);
+
+ /* Skip slow socket drawing if zoom is small. */
+ if (scale > 0.2f) {
+ node_draw_sockets(v2d, C, ntree, node, true, false);
+ }
/* Preview. */
bNodeInstanceHash *previews = (bNodeInstanceHash *)CTX_data_pointer_get(C, "node_previews").data;
@@ -2123,15 +2349,15 @@ static void count_multi_input_socket_links(bNodeTree *ntree, SpaceNode *snode)
}
}
/* Count temporary links going into this socket. */
- LISTBASE_FOREACH (bNodeLinkDrag *, nldrag, &snode->runtime->linkdrag) {
- LISTBASE_FOREACH (LinkData *, linkdata, &nldrag->links) {
- bNodeLink *link = (bNodeLink *)linkdata->data;
+ if (snode->runtime->linkdrag) {
+ for (const bNodeLink *link : snode->runtime->linkdrag->links) {
if (link->tosock && (link->tosock->flag & SOCK_MULTI_INPUT)) {
int &count = counts.lookup_or_add(link->tosock, 0);
count++;
}
}
}
+
LISTBASE_FOREACH (bNode *, node, &ntree->nodes) {
LISTBASE_FOREACH (bNodeSocket *, socket, &node->inputs) {
if (socket->flag & SOCK_MULTI_INPUT) {
@@ -2390,9 +2616,9 @@ void node_draw_space(const bContext *C, ARegion *region)
/* Temporary links. */
GPU_blend(GPU_BLEND_ALPHA);
GPU_line_smooth(true);
- LISTBASE_FOREACH (bNodeLinkDrag *, nldrag, &snode->runtime->linkdrag) {
- LISTBASE_FOREACH (LinkData *, linkdata, &nldrag->links) {
- node_draw_link(C, v2d, snode, (bNodeLink *)linkdata->data);
+ if (snode->runtime->linkdrag) {
+ for (const bNodeLink *link : snode->runtime->linkdrag->links) {
+ node_draw_link(C, v2d, snode, link);
}
}
GPU_line_smooth(false);
diff --git a/source/blender/editors/space_node/node_edit.cc b/source/blender/editors/space_node/node_edit.cc
index 030d1672a08..30c9f7ea56b 100644
--- a/source/blender/editors/space_node/node_edit.cc
+++ b/source/blender/editors/space_node/node_edit.cc
@@ -76,7 +76,7 @@
#include "NOD_geometry.h"
#include "NOD_shader.h"
#include "NOD_texture.h"
-#include "node_intern.h" /* own include */
+#include "node_intern.hh" /* own include */
#define USE_ESC_COMPO
@@ -1192,7 +1192,7 @@ static bool cursor_isect_multi_input_socket(const float cursor[2], const bNodeSo
}
/* type is SOCK_IN and/or SOCK_OUT */
-int node_find_indicated_socket(
+bool node_find_indicated_socket(
SpaceNode *snode, bNode **nodep, bNodeSocket **sockp, const float cursor[2], int in_out)
{
rctf rect;
@@ -1224,7 +1224,7 @@ int node_find_indicated_socket(
if (node == visible_node(snode, &rect)) {
*nodep = node;
*sockp = sock;
- return 1;
+ return true;
}
}
}
@@ -1232,7 +1232,7 @@ int node_find_indicated_socket(
if (node == visible_node(snode, &rect)) {
*nodep = node;
*sockp = sock;
- return 1;
+ return true;
}
}
}
@@ -1245,7 +1245,7 @@ int node_find_indicated_socket(
if (node == visible_node(snode, &rect)) {
*nodep = node;
*sockp = sock;
- return 1;
+ return true;
}
}
}
@@ -1253,7 +1253,7 @@ int node_find_indicated_socket(
}
}
- return 0;
+ return false;
}
/* ****************** Link Dimming *********************** */
@@ -1775,8 +1775,7 @@ static int node_mute_exec(bContext *C, wmOperator *UNUSED(op))
ED_preview_kill_jobs(CTX_wm_manager(C), bmain);
LISTBASE_FOREACH (bNode *, node, &snode->edittree->nodes) {
- /* Only allow muting of nodes having a mute func! */
- if ((node->flag & SELECT) && node->typeinfo->update_internal_links) {
+ if ((node->flag & SELECT) && !node->typeinfo->no_muting) {
node->flag ^= NODE_MUTED;
snode_update(snode, node);
do_tag_update |= (do_tag_update || node_connected_to_output(bmain, snode->edittree, node));
diff --git a/source/blender/editors/space_node/node_geometry_attribute_search.cc b/source/blender/editors/space_node/node_geometry_attribute_search.cc
index 063e6348123..79ba9b8d2d9 100644
--- a/source/blender/editors/space_node/node_geometry_attribute_search.cc
+++ b/source/blender/editors/space_node/node_geometry_attribute_search.cc
@@ -44,7 +44,7 @@
#include "NOD_geometry_nodes_eval_log.hh"
-#include "node_intern.h"
+#include "node_intern.hh"
using blender::IndexRange;
using blender::Map;
diff --git a/source/blender/editors/space_node/node_gizmo.c b/source/blender/editors/space_node/node_gizmo.cc
index e1deca54890..717f4d2f4f9 100644
--- a/source/blender/editors/space_node/node_gizmo.c
+++ b/source/blender/editors/space_node/node_gizmo.cc
@@ -18,7 +18,7 @@
* \ingroup spnode
*/
-#include <math.h>
+#include <cmath>
#include "BLI_math_matrix.h"
#include "BLI_math_vector.h"
@@ -41,7 +41,7 @@
#include "WM_api.h"
#include "WM_types.h"
-#include "node_intern.h"
+#include "node_intern.hh"
/* -------------------------------------------------------------------- */
/** \name Local Utilities
@@ -80,9 +80,9 @@ static void gizmo_node_backdrop_prop_matrix_get(const wmGizmo *UNUSED(gz),
wmGizmoProperty *gz_prop,
void *value_p)
{
- float(*matrix)[4] = value_p;
+ float(*matrix)[4] = (float(*)[4])value_p;
BLI_assert(gz_prop->type->array_length == 16);
- const SpaceNode *snode = gz_prop->custom_func.user_data;
+ const SpaceNode *snode = (const SpaceNode *)gz_prop->custom_func.user_data;
matrix[0][0] = snode->zoom;
matrix[1][1] = snode->zoom;
matrix[3][0] = snode->xof;
@@ -93,9 +93,9 @@ static void gizmo_node_backdrop_prop_matrix_set(const wmGizmo *UNUSED(gz),
wmGizmoProperty *gz_prop,
const void *value_p)
{
- const float(*matrix)[4] = value_p;
+ const float(*matrix)[4] = (const float(*)[4])value_p;
BLI_assert(gz_prop->type->array_length == 16);
- SpaceNode *snode = gz_prop->custom_func.user_data;
+ SpaceNode *snode = (SpaceNode *)gz_prop->custom_func.user_data;
snode->zoom = matrix[0][0];
snode->xof = matrix[3][0];
snode->yof = matrix[3][1];
@@ -122,9 +122,9 @@ static bool WIDGETGROUP_node_transform_poll(const bContext *C, wmGizmoGroupType
static void WIDGETGROUP_node_transform_setup(const bContext *UNUSED(C), wmGizmoGroup *gzgroup)
{
- wmGizmoWrapper *wwrapper = MEM_mallocN(sizeof(wmGizmoWrapper), __func__);
+ wmGizmoWrapper *wwrapper = (wmGizmoWrapper *)MEM_mallocN(sizeof(wmGizmoWrapper), __func__);
- wwrapper->gizmo = WM_gizmo_new("GIZMO_GT_cage_2d", gzgroup, NULL);
+ wwrapper->gizmo = WM_gizmo_new("GIZMO_GT_cage_2d", gzgroup, nullptr);
RNA_enum_set(wwrapper->gizmo->ptr,
"transform",
@@ -139,11 +139,11 @@ static void WIDGETGROUP_node_transform_refresh(const bContext *C, wmGizmoGroup *
wmGizmo *cage = ((wmGizmoWrapper *)gzgroup->customdata)->gizmo;
const ARegion *region = CTX_wm_region(C);
/* center is always at the origin */
- const float origin[3] = {region->winx / 2, region->winy / 2};
+ const float origin[3] = {float(region->winx / 2), float(region->winy / 2), 0.0f};
void *lock;
Image *ima = BKE_image_ensure_viewer(bmain, IMA_TYPE_COMPOSITE, "Viewer Node");
- ImBuf *ibuf = BKE_image_acquire_ibuf(ima, NULL, &lock);
+ ImBuf *ibuf = BKE_image_acquire_ibuf(ima, nullptr, &lock);
if (ibuf) {
const float dims[2] = {
@@ -164,14 +164,12 @@ static void WIDGETGROUP_node_transform_refresh(const bContext *C, wmGizmoGroup *
WM_gizmo_target_property_def_rna(cage, "scale", &nodeptr, "backdrop_zoom", -1);
#endif
- WM_gizmo_target_property_def_func(cage,
- "matrix",
- &(const struct wmGizmoPropertyFnParams){
- .value_get_fn = gizmo_node_backdrop_prop_matrix_get,
- .value_set_fn = gizmo_node_backdrop_prop_matrix_set,
- .range_get_fn = NULL,
- .user_data = snode,
- });
+ wmGizmoPropertyFnParams params{};
+ params.value_get_fn = gizmo_node_backdrop_prop_matrix_get;
+ params.value_set_fn = gizmo_node_backdrop_prop_matrix_set;
+ params.range_get_fn = nullptr;
+ params.user_data = snode;
+ WM_gizmo_target_property_def_func(cage, "matrix", &params);
}
else {
WM_gizmo_set_flag(cage, WM_GIZMO_HIDDEN, true);
@@ -262,12 +260,12 @@ static void gizmo_node_crop_prop_matrix_get(const wmGizmo *gz,
wmGizmoProperty *gz_prop,
void *value_p)
{
- float(*matrix)[4] = value_p;
+ float(*matrix)[4] = (float(*)[4])value_p;
BLI_assert(gz_prop->type->array_length == 16);
- struct NodeCropWidgetGroup *crop_group = gz->parent_gzgroup->customdata;
+ NodeCropWidgetGroup *crop_group = (NodeCropWidgetGroup *)gz->parent_gzgroup->customdata;
const float *dims = crop_group->state.dims;
- const bNode *node = gz_prop->custom_func.user_data;
- const NodeTwoXYs *nxy = node->storage;
+ const bNode *node = (const bNode *)gz_prop->custom_func.user_data;
+ const NodeTwoXYs *nxy = (const NodeTwoXYs *)node->storage;
bool is_relative = (bool)node->custom2;
rctf rct;
two_xy_to_rect(nxy, &rct, dims, is_relative);
@@ -281,12 +279,12 @@ static void gizmo_node_crop_prop_matrix_set(const wmGizmo *gz,
wmGizmoProperty *gz_prop,
const void *value_p)
{
- const float(*matrix)[4] = value_p;
+ const float(*matrix)[4] = (const float(*)[4])value_p;
BLI_assert(gz_prop->type->array_length == 16);
- struct NodeCropWidgetGroup *crop_group = gz->parent_gzgroup->customdata;
+ NodeCropWidgetGroup *crop_group = (NodeCropWidgetGroup *)gz->parent_gzgroup->customdata;
const float *dims = crop_group->state.dims;
- bNode *node = gz_prop->custom_func.user_data;
- NodeTwoXYs *nxy = node->storage;
+ bNode *node = (bNode *)gz_prop->custom_func.user_data;
+ NodeTwoXYs *nxy = (NodeTwoXYs *)node->storage;
bool is_relative = (bool)node->custom2;
rctf rct;
two_xy_to_rect(nxy, &rct, dims, is_relative);
@@ -294,15 +292,8 @@ static void gizmo_node_crop_prop_matrix_set(const wmGizmo *gz,
const bool ny = rct.ymin > rct.ymax;
BLI_rctf_resize(&rct, fabsf(matrix[0][0]), fabsf(matrix[1][1]));
BLI_rctf_recenter(&rct, (matrix[3][0] / dims[0]) + 0.5f, (matrix[3][1] / dims[1]) + 0.5f);
- BLI_rctf_isect(
- &(rctf){
- .xmin = 0,
- .ymin = 0,
- .xmax = 1,
- .ymax = 1,
- },
- &rct,
- &rct);
+ const rctf rct_isect{0, 0, 1, 1};
+ BLI_rctf_isect(&rct_isect, &rct, &rct);
if (nx) {
SWAP(float, rct.xmin, rct.xmax);
}
@@ -337,10 +328,10 @@ static bool WIDGETGROUP_node_crop_poll(const bContext *C, wmGizmoGroupType *UNUS
static void WIDGETGROUP_node_crop_setup(const bContext *UNUSED(C), wmGizmoGroup *gzgroup)
{
- struct NodeCropWidgetGroup *crop_group = MEM_mallocN(sizeof(struct NodeCropWidgetGroup),
- __func__);
+ struct NodeCropWidgetGroup *crop_group = (NodeCropWidgetGroup *)MEM_mallocN(
+ sizeof(struct NodeCropWidgetGroup), __func__);
- crop_group->border = WM_gizmo_new("GIZMO_GT_cage_2d", gzgroup, NULL);
+ crop_group->border = WM_gizmo_new("GIZMO_GT_cage_2d", gzgroup, nullptr);
RNA_enum_set(crop_group->border->ptr,
"transform",
@@ -352,7 +343,7 @@ static void WIDGETGROUP_node_crop_setup(const bContext *UNUSED(C), wmGizmoGroup
static void WIDGETGROUP_node_crop_draw_prepare(const bContext *C, wmGizmoGroup *gzgroup)
{
ARegion *region = CTX_wm_region(C);
- wmGizmo *gz = gzgroup->gizmos.first;
+ wmGizmo *gz = (wmGizmo *)gzgroup->gizmos.first;
SpaceNode *snode = CTX_wm_space_node(C);
@@ -362,12 +353,12 @@ static void WIDGETGROUP_node_crop_draw_prepare(const bContext *C, wmGizmoGroup *
static void WIDGETGROUP_node_crop_refresh(const bContext *C, wmGizmoGroup *gzgroup)
{
Main *bmain = CTX_data_main(C);
- struct NodeCropWidgetGroup *crop_group = gzgroup->customdata;
+ NodeCropWidgetGroup *crop_group = (NodeCropWidgetGroup *)gzgroup->customdata;
wmGizmo *gz = crop_group->border;
void *lock;
Image *ima = BKE_image_ensure_viewer(bmain, IMA_TYPE_COMPOSITE, "Viewer Node");
- ImBuf *ibuf = BKE_image_acquire_ibuf(ima, NULL, &lock);
+ ImBuf *ibuf = BKE_image_acquire_ibuf(ima, nullptr, &lock);
if (ibuf) {
crop_group->state.dims[0] = (ibuf->x > 0) ? ibuf->x : 64.0f;
@@ -385,14 +376,12 @@ static void WIDGETGROUP_node_crop_refresh(const bContext *C, wmGizmoGroup *gzgro
crop_group->update_data.prop = RNA_struct_find_property(&crop_group->update_data.ptr,
"relative");
- WM_gizmo_target_property_def_func(gz,
- "matrix",
- &(const struct wmGizmoPropertyFnParams){
- .value_get_fn = gizmo_node_crop_prop_matrix_get,
- .value_set_fn = gizmo_node_crop_prop_matrix_set,
- .range_get_fn = NULL,
- .user_data = node,
- });
+ wmGizmoPropertyFnParams params{};
+ params.value_get_fn = gizmo_node_crop_prop_matrix_get;
+ params.value_set_fn = gizmo_node_crop_prop_matrix_set;
+ params.range_get_fn = nullptr;
+ params.user_data = snode;
+ WM_gizmo_target_property_def_func(gz, "matrix", &params);
}
else {
WM_gizmo_set_flag(gz, WM_GIZMO_HIDDEN, true);
@@ -450,10 +439,10 @@ static bool WIDGETGROUP_node_sbeam_poll(const bContext *C, wmGizmoGroupType *UNU
static void WIDGETGROUP_node_sbeam_setup(const bContext *UNUSED(C), wmGizmoGroup *gzgroup)
{
- struct NodeSunBeamsWidgetGroup *sbeam_group = MEM_mallocN(sizeof(struct NodeSunBeamsWidgetGroup),
- __func__);
+ NodeSunBeamsWidgetGroup *sbeam_group = (NodeSunBeamsWidgetGroup *)MEM_mallocN(
+ sizeof(NodeSunBeamsWidgetGroup), __func__);
- sbeam_group->gizmo = WM_gizmo_new("GIZMO_GT_move_3d", gzgroup, NULL);
+ sbeam_group->gizmo = WM_gizmo_new("GIZMO_GT_move_3d", gzgroup, nullptr);
wmGizmo *gz = sbeam_group->gizmo;
RNA_enum_set(gz->ptr, "draw_style", ED_GIZMO_MOVE_STYLE_CROSS_2D);
@@ -465,9 +454,9 @@ static void WIDGETGROUP_node_sbeam_setup(const bContext *UNUSED(C), wmGizmoGroup
static void WIDGETGROUP_node_sbeam_draw_prepare(const bContext *C, wmGizmoGroup *gzgroup)
{
- struct NodeSunBeamsWidgetGroup *sbeam_group = gzgroup->customdata;
+ NodeSunBeamsWidgetGroup *sbeam_group = (NodeSunBeamsWidgetGroup *)gzgroup->customdata;
ARegion *region = CTX_wm_region(C);
- wmGizmo *gz = gzgroup->gizmos.first;
+ wmGizmo *gz = (wmGizmo *)gzgroup->gizmos.first;
SpaceNode *snode = CTX_wm_space_node(C);
@@ -478,12 +467,12 @@ static void WIDGETGROUP_node_sbeam_draw_prepare(const bContext *C, wmGizmoGroup
static void WIDGETGROUP_node_sbeam_refresh(const bContext *C, wmGizmoGroup *gzgroup)
{
Main *bmain = CTX_data_main(C);
- struct NodeSunBeamsWidgetGroup *sbeam_group = gzgroup->customdata;
+ NodeSunBeamsWidgetGroup *sbeam_group = (NodeSunBeamsWidgetGroup *)gzgroup->customdata;
wmGizmo *gz = sbeam_group->gizmo;
void *lock;
Image *ima = BKE_image_ensure_viewer(bmain, IMA_TYPE_COMPOSITE, "Viewer Node");
- ImBuf *ibuf = BKE_image_acquire_ibuf(ima, NULL, &lock);
+ ImBuf *ibuf = BKE_image_acquire_ibuf(ima, nullptr, &lock);
if (ibuf) {
sbeam_group->state.dims[0] = (ibuf->x > 0) ? ibuf->x : 64.0f;
@@ -555,12 +544,12 @@ static bool WIDGETGROUP_node_corner_pin_poll(const bContext *C, wmGizmoGroupType
static void WIDGETGROUP_node_corner_pin_setup(const bContext *UNUSED(C), wmGizmoGroup *gzgroup)
{
- struct NodeCornerPinWidgetGroup *cpin_group = MEM_mallocN(
- sizeof(struct NodeCornerPinWidgetGroup), __func__);
+ NodeCornerPinWidgetGroup *cpin_group = (NodeCornerPinWidgetGroup *)MEM_mallocN(
+ sizeof(NodeCornerPinWidgetGroup), __func__);
const wmGizmoType *gzt_move_3d = WM_gizmotype_find("GIZMO_GT_move_3d", false);
for (int i = 0; i < 4; i++) {
- cpin_group->gizmos[i] = WM_gizmo_new_ptr(gzt_move_3d, gzgroup, NULL);
+ cpin_group->gizmos[i] = WM_gizmo_new_ptr(gzt_move_3d, gzgroup, nullptr);
wmGizmo *gz = cpin_group->gizmos[i];
RNA_enum_set(gz->ptr, "draw_style", ED_GIZMO_MOVE_STYLE_CROSS_2D);
@@ -573,7 +562,7 @@ static void WIDGETGROUP_node_corner_pin_setup(const bContext *UNUSED(C), wmGizmo
static void WIDGETGROUP_node_corner_pin_draw_prepare(const bContext *C, wmGizmoGroup *gzgroup)
{
- struct NodeCornerPinWidgetGroup *cpin_group = gzgroup->customdata;
+ NodeCornerPinWidgetGroup *cpin_group = (NodeCornerPinWidgetGroup *)gzgroup->customdata;
ARegion *region = CTX_wm_region(C);
SpaceNode *snode = CTX_wm_space_node(C);
@@ -591,11 +580,11 @@ static void WIDGETGROUP_node_corner_pin_draw_prepare(const bContext *C, wmGizmoG
static void WIDGETGROUP_node_corner_pin_refresh(const bContext *C, wmGizmoGroup *gzgroup)
{
Main *bmain = CTX_data_main(C);
- struct NodeCornerPinWidgetGroup *cpin_group = gzgroup->customdata;
+ NodeCornerPinWidgetGroup *cpin_group = (NodeCornerPinWidgetGroup *)gzgroup->customdata;
void *lock;
Image *ima = BKE_image_ensure_viewer(bmain, IMA_TYPE_COMPOSITE, "Viewer Node");
- ImBuf *ibuf = BKE_image_acquire_ibuf(ima, NULL, &lock);
+ ImBuf *ibuf = BKE_image_acquire_ibuf(ima, nullptr, &lock);
if (ibuf) {
cpin_group->state.dims[0] = (ibuf->x > 0) ? ibuf->x : 64.0f;
@@ -606,7 +595,7 @@ static void WIDGETGROUP_node_corner_pin_refresh(const bContext *C, wmGizmoGroup
/* need to set property here for undo. TODO: would prefer to do this in _init. */
int i = 0;
- for (bNodeSocket *sock = node->inputs.first; sock && i < 4; sock = sock->next) {
+ for (bNodeSocket *sock = (bNodeSocket *)node->inputs.first; sock && i < 4; sock = sock->next) {
if (sock->type == SOCK_VECTOR) {
wmGizmo *gz = cpin_group->gizmos[i++];
diff --git a/source/blender/editors/space_node/node_group.cc b/source/blender/editors/space_node/node_group.cc
index d7541d8f512..d9fbbc81a8f 100644
--- a/source/blender/editors/space_node/node_group.cc
+++ b/source/blender/editors/space_node/node_group.cc
@@ -58,7 +58,7 @@
#include "NOD_common.h"
#include "NOD_socket.h"
-#include "node_intern.h" /* own include */
+#include "node_intern.hh" /* own include */
/* -------------------------------------------------------------------- */
/** \name Local Utilities
diff --git a/source/blender/editors/space_node/node_intern.h b/source/blender/editors/space_node/node_intern.h
deleted file mode 100644
index 383fe5afdf9..00000000000
--- a/source/blender/editors/space_node/node_intern.h
+++ /dev/null
@@ -1,355 +0,0 @@
-/*
- * 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.
- *
- * The Original Code is Copyright (C) 2008 Blender Foundation.
- * All rights reserved.
- */
-
-/** \file
- * \ingroup spnode
- */
-
-#pragma once
-
-#include "BKE_node.h"
-#include "UI_interface.h"
-#include "UI_view2d.h"
-#include <stddef.h> /* for size_t */
-
-/* internal exports only */
-
-struct ARegion;
-struct ARegionType;
-struct Main;
-struct NodeInsertOfsData;
-struct View2D;
-struct bContext;
-struct bNode;
-struct bNodeLink;
-struct bNodeSocket;
-struct wmGizmoGroupType;
-struct wmKeyConfig;
-struct wmWindow;
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/* temp data to pass on to modal */
-typedef struct bNodeLinkDrag {
- struct bNodeLinkDrag *next, *prev;
-
- /* List of links dragged by the operator.
- * NOTE: This is a list of LinkData structs on top of the actual bNodeLinks.
- * This way the links can be added to the node tree while being stored in this list.
- */
- ListBase links;
- bool from_multi_input_socket;
- int in_out;
-
- /** Temporarily stores the last picked link from multi-input socket operator. */
- struct bNodeLink *last_picked_multi_input_socket_link;
-
- /** Temporarily stores the last hovered socket for multi-input socket operator.
- * Store it to recalculate sorting after it is no longer hovered. */
- struct bNode *last_node_hovered_while_dragging_a_link;
-
- /* Data for edge panning */
- View2DEdgePanData pan_data;
-} bNodeLinkDrag;
-
-typedef struct SpaceNode_Runtime {
- float aspect;
-
- /** Mouse position for drawing socket-less links and adding nodes. */
- float cursor[2];
-
- /** For auto compositing. */
- bool recalc;
-
- /** Temporary data for modal linking operator. */
- struct ListBase linkdrag;
-
- /* XXX hack for translate_attach op-macros to pass data from transform op to insert_offset op */
- /** Temporary data for node insert offset (in UI called Auto-offset). */
- struct NodeInsertOfsData *iofsd;
-} SpaceNode_Runtime;
-
-/* space_node.c */
-
-/* transform between View2Ds in the tree path */
-void space_node_group_offset(struct SpaceNode *snode, float *x, float *y);
-
-/* node_draw.cc */
-float node_socket_calculate_height(const bNodeSocket *socket);
-void node_link_calculate_multi_input_position(const float socket_x,
- const float socket_y,
- const int index,
- const int total_inputs,
- float r[2]);
-
-int node_get_colorid(struct bNode *node);
-int node_get_resize_cursor(int directions);
-void node_draw_shadow(const struct SpaceNode *snode,
- const struct bNode *node,
- float radius,
- float alpha);
-void node_draw_default(const struct bContext *C,
- struct ARegion *region,
- struct SpaceNode *snode,
- struct bNodeTree *ntree,
- struct bNode *node,
- bNodeInstanceKey key);
-void node_draw_sockets(const struct View2D *v2d,
- const struct bContext *C,
- struct bNodeTree *ntree,
- struct bNode *node,
- bool draw_outputs,
- bool select_all);
-void node_update_default(const struct bContext *C, struct bNodeTree *ntree, struct bNode *node);
-int node_select_area_default(struct bNode *node, int x, int y);
-int node_tweak_area_default(struct bNode *node, int x, int y);
-void node_socket_color_get(const struct bContext *C,
- struct bNodeTree *ntree,
- struct PointerRNA *node_ptr,
- struct bNodeSocket *sock,
- float r_color[4]);
-void node_update_nodetree(const struct bContext *C, struct bNodeTree *ntree);
-void node_draw_nodetree(const struct bContext *C,
- struct ARegion *region,
- struct SpaceNode *snode,
- struct bNodeTree *ntree,
- bNodeInstanceKey parent_key);
-void node_draw_space(const bContext *C, ARegion *region);
-
-void node_set_cursor(struct wmWindow *win, struct SpaceNode *snode, float cursor[2]);
-/* DPI scaled coords */
-void node_to_view(const struct bNode *node, float x, float y, float *rx, float *ry);
-void node_to_updated_rect(const struct bNode *node, rctf *r_rect);
-void node_from_view(const struct bNode *node, float x, float y, float *rx, float *ry);
-
-/* node_toolbar.c */
-void node_toolbar_register(struct ARegionType *art);
-
-/* node_ops.c */
-void node_operatortypes(void);
-void node_keymap(struct wmKeyConfig *keyconf);
-
-/* node_select.c */
-void node_deselect_all(struct SpaceNode *snode);
-void node_socket_select(struct bNode *node, struct bNodeSocket *sock);
-void node_socket_deselect(struct bNode *node, struct bNodeSocket *sock, const bool deselect_node);
-void node_deselect_all_input_sockets(struct SpaceNode *snode, const bool deselect_nodes);
-void node_deselect_all_output_sockets(struct SpaceNode *snode, const bool deselect_nodes);
-void node_select_single(struct bContext *C, struct bNode *node);
-
-void NODE_OT_select(struct wmOperatorType *ot);
-void NODE_OT_select_all(struct wmOperatorType *ot);
-void NODE_OT_select_linked_to(struct wmOperatorType *ot);
-void NODE_OT_select_linked_from(struct wmOperatorType *ot);
-void NODE_OT_select_box(struct wmOperatorType *ot);
-void NODE_OT_select_circle(struct wmOperatorType *ot);
-void NODE_OT_select_lasso(struct wmOperatorType *ot);
-void NODE_OT_select_grouped(struct wmOperatorType *ot);
-void NODE_OT_select_same_type_step(struct wmOperatorType *ot);
-void NODE_OT_find_node(struct wmOperatorType *ot);
-
-/* node_view.c */
-int space_node_view_flag(struct bContext *C,
- struct SpaceNode *snode,
- ARegion *region,
- const int node_flag,
- const int smooth_viewtx);
-
-void NODE_OT_view_all(struct wmOperatorType *ot);
-void NODE_OT_view_selected(struct wmOperatorType *ot);
-void NODE_OT_geometry_node_view_legacy(struct wmOperatorType *ot);
-
-void NODE_OT_backimage_move(struct wmOperatorType *ot);
-void NODE_OT_backimage_zoom(struct wmOperatorType *ot);
-void NODE_OT_backimage_fit(struct wmOperatorType *ot);
-void NODE_OT_backimage_sample(struct wmOperatorType *ot);
-
-/* drawnode.c */
-void nodelink_batch_start(struct SpaceNode *snode);
-void nodelink_batch_end(struct SpaceNode *snode);
-
-void node_draw_link(const struct bContext *C,
- struct View2D *v2d,
- struct SpaceNode *snode,
- struct bNodeLink *link);
-void node_draw_link_bezier(const struct bContext *C,
- const struct View2D *v2d,
- const struct SpaceNode *snode,
- const struct bNodeLink *link,
- int th_col1,
- int th_col2,
- int th_col3);
-bool node_link_bezier_points(const struct View2D *v2d,
- const struct SpaceNode *snode,
- const struct bNodeLink *link,
- float coord_array[][2],
- const int resol);
-bool node_link_bezier_handles(const struct View2D *v2d,
- const struct SpaceNode *snode,
- const struct bNodeLink *link,
- float vec[4][2]);
-void draw_nodespace_back_pix(const struct bContext *C,
- struct ARegion *region,
- struct SpaceNode *snode,
- bNodeInstanceKey parent_key);
-
-/* node_add.c */
-bNode *node_add_node(
- const struct bContext *C, const char *idname, int type, float locx, float locy);
-void NODE_OT_add_reroute(struct wmOperatorType *ot);
-void NODE_OT_add_group(struct wmOperatorType *ot);
-void NODE_OT_add_object(struct wmOperatorType *ot);
-void NODE_OT_add_collection(struct wmOperatorType *ot);
-void NODE_OT_add_texture(struct wmOperatorType *ot);
-void NODE_OT_add_file(struct wmOperatorType *ot);
-void NODE_OT_add_mask(struct wmOperatorType *ot);
-void NODE_OT_new_node_tree(struct wmOperatorType *ot);
-
-/* node_group.c */
-const char *node_group_idname(struct bContext *C);
-void NODE_OT_group_make(struct wmOperatorType *ot);
-void NODE_OT_group_insert(struct wmOperatorType *ot);
-void NODE_OT_group_ungroup(struct wmOperatorType *ot);
-void NODE_OT_group_separate(struct wmOperatorType *ot);
-void NODE_OT_group_edit(struct wmOperatorType *ot);
-
-/* node_relationships.c */
-void sort_multi_input_socket_links(struct SpaceNode *snode,
- struct bNode *node,
- struct bNodeLink *drag_link,
- float cursor[2]);
-bool node_connected_to_output(struct Main *bmain, struct bNodeTree *ntree, struct bNode *node);
-
-void NODE_OT_link(struct wmOperatorType *ot);
-void NODE_OT_link_make(struct wmOperatorType *ot);
-void NODE_OT_links_cut(struct wmOperatorType *ot);
-void NODE_OT_links_detach(struct wmOperatorType *ot);
-void NODE_OT_links_mute(struct wmOperatorType *ot);
-
-void NODE_OT_parent_set(struct wmOperatorType *ot);
-void NODE_OT_join(struct wmOperatorType *ot);
-void NODE_OT_attach(struct wmOperatorType *ot);
-void NODE_OT_detach(struct wmOperatorType *ot);
-
-void NODE_OT_link_viewer(struct wmOperatorType *ot);
-
-void NODE_OT_insert_offset(struct wmOperatorType *ot);
-
-/* node_edit.c */
-void snode_notify(struct bContext *C, struct SpaceNode *snode);
-void snode_dag_update(struct bContext *C, struct SpaceNode *snode);
-void snode_set_context(const struct bContext *C);
-
-void snode_update(struct SpaceNode *snode, struct bNode *node);
-bool composite_node_active(struct bContext *C);
-bool composite_node_editable(struct bContext *C);
-
-bool node_has_hidden_sockets(struct bNode *node);
-void node_set_hidden_sockets(struct SpaceNode *snode, bNode *node, int set);
-int node_render_changed_exec(bContext *, struct wmOperator *);
-int node_find_indicated_socket(struct SpaceNode *snode,
- struct bNode **nodep,
- struct bNodeSocket **sockp,
- const float cursor[2],
- int in_out);
-float node_link_dim_factor(const struct View2D *v2d, const struct bNodeLink *link);
-bool node_link_is_hidden_or_dimmed(const struct View2D *v2d, const struct bNodeLink *link);
-
-void NODE_OT_duplicate(struct wmOperatorType *ot);
-void NODE_OT_delete(struct wmOperatorType *ot);
-void NODE_OT_delete_reconnect(struct wmOperatorType *ot);
-void NODE_OT_resize(struct wmOperatorType *ot);
-
-void NODE_OT_mute_toggle(struct wmOperatorType *ot);
-void NODE_OT_hide_toggle(struct wmOperatorType *ot);
-void NODE_OT_hide_socket_toggle(struct wmOperatorType *ot);
-void NODE_OT_preview_toggle(struct wmOperatorType *ot);
-void NODE_OT_options_toggle(struct wmOperatorType *ot);
-void NODE_OT_node_copy_color(struct wmOperatorType *ot);
-
-void NODE_OT_read_viewlayers(struct wmOperatorType *ot);
-void NODE_OT_render_changed(struct wmOperatorType *ot);
-
-void NODE_OT_output_file_add_socket(struct wmOperatorType *ot);
-void NODE_OT_output_file_remove_active_socket(struct wmOperatorType *ot);
-void NODE_OT_output_file_move_active_socket(struct wmOperatorType *ot);
-
-void NODE_OT_switch_view_update(struct wmOperatorType *ot);
-
-/* NOTE: clipboard_cut is a simple macro of copy + delete. */
-void NODE_OT_clipboard_copy(struct wmOperatorType *ot);
-void NODE_OT_clipboard_paste(struct wmOperatorType *ot);
-
-void NODE_OT_tree_socket_add(struct wmOperatorType *ot);
-void NODE_OT_tree_socket_remove(struct wmOperatorType *ot);
-void NODE_OT_tree_socket_change_type(struct wmOperatorType *ot);
-void NODE_OT_tree_socket_move(struct wmOperatorType *ot);
-
-void NODE_OT_shader_script_update(struct wmOperatorType *ot);
-
-void NODE_OT_viewer_border(struct wmOperatorType *ot);
-void NODE_OT_clear_viewer_border(struct wmOperatorType *ot);
-
-/* node_widgets.c */
-void NODE_GGT_backdrop_transform(struct wmGizmoGroupType *gzgt);
-void NODE_GGT_backdrop_crop(struct wmGizmoGroupType *gzgt);
-void NODE_GGT_backdrop_sun_beams(struct wmGizmoGroupType *gzgt);
-void NODE_GGT_backdrop_corner_pin(struct wmGizmoGroupType *gzgt);
-
-void NODE_OT_cryptomatte_layer_add(struct wmOperatorType *ot);
-void NODE_OT_cryptomatte_layer_remove(struct wmOperatorType *ot);
-
-/* node_geometry_attribute_search.cc */
-void node_geometry_add_attribute_search_button(const struct bContext *C,
- const struct bNodeTree *node_tree,
- const struct bNode *node,
- struct PointerRNA *socket_ptr,
- struct uiLayout *layout);
-
-extern const char *node_context_dir[];
-
-/* XXXXXX */
-
-/* Nodes draw without dpi - the view zoom is flexible. */
-#define HIDDEN_RAD (0.75f * U.widget_unit)
-#define BASIS_RAD (0.2f * U.widget_unit)
-#define NODE_DYS (U.widget_unit / 2)
-#define NODE_DY U.widget_unit
-#define NODE_SOCKDY (0.1f * U.widget_unit)
-#define NODE_WIDTH(node) (node->width * UI_DPI_FAC)
-#define NODE_HEIGHT(node) (node->height * UI_DPI_FAC)
-#define NODE_MARGIN_X (1.2f * U.widget_unit)
-#define NODE_SOCKSIZE (0.25f * U.widget_unit)
-#define NODE_MULTI_INPUT_LINK_GAP (0.25f * U.widget_unit)
-#define NODE_RESIZE_MARGIN (0.20f * U.widget_unit)
-#define NODE_LINK_RESOL 12
-
-#ifdef __cplusplus
-}
-#endif
-
-#ifdef __cplusplus
-# include "BLI_vector.hh"
-# include "UI_interface.hh"
-namespace blender::ed::space_node {
-Vector<ui::ContextPathItem> context_path_for_space_node(const bContext &C);
-}
-#endif
diff --git a/source/blender/editors/space_node/node_intern.hh b/source/blender/editors/space_node/node_intern.hh
new file mode 100644
index 00000000000..6dc57c1fb79
--- /dev/null
+++ b/source/blender/editors/space_node/node_intern.hh
@@ -0,0 +1,333 @@
+/*
+ * 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.
+ *
+ * The Original Code is Copyright (C) 2008 Blender Foundation.
+ * All rights reserved.
+ */
+
+/** \file
+ * \ingroup spnode
+ */
+
+#pragma once
+
+#include "BKE_node.h"
+#include "UI_interface.h"
+#include "UI_view2d.h"
+
+#include "BLI_vector.hh"
+#include "UI_interface.hh"
+
+#include <stddef.h> /* for size_t */
+
+/* internal exports only */
+
+struct ARegion;
+struct ARegionType;
+struct Main;
+struct NodeInsertOfsData;
+struct View2D;
+struct bContext;
+struct bNode;
+struct bNodeLink;
+struct bNodeSocket;
+struct wmGizmoGroupType;
+struct wmKeyConfig;
+struct wmWindow;
+
+/* temp data to pass on to modal */
+struct bNodeLinkDrag {
+ /** Links dragged by the operator. */
+ blender::Vector<bNodeLink *> links;
+ bool from_multi_input_socket;
+ int in_out;
+
+ /** Temporarily stores the last picked link from multi-input socket operator. */
+ struct bNodeLink *last_picked_multi_input_socket_link;
+
+ /** Temporarily stores the last hovered socket for multi-input socket operator.
+ * Store it to recalculate sorting after it is no longer hovered. */
+ struct bNode *last_node_hovered_while_dragging_a_link;
+
+ /* Data for edge panning */
+ View2DEdgePanData pan_data;
+};
+
+struct SpaceNode_Runtime {
+ float aspect;
+
+ /** Mouse position for drawing socket-less links and adding nodes. */
+ float cursor[2];
+
+ /** For auto compositing. */
+ bool recalc;
+
+ /** Temporary data for modal linking operator. */
+ std::unique_ptr<bNodeLinkDrag> linkdrag;
+
+ /* XXX hack for translate_attach op-macros to pass data from transform op to insert_offset op */
+ /** Temporary data for node insert offset (in UI called Auto-offset). */
+ struct NodeInsertOfsData *iofsd;
+};
+
+/* space_node.c */
+
+/* transform between View2Ds in the tree path */
+void space_node_group_offset(SpaceNode *snode, float *x, float *y);
+
+/* node_draw.cc */
+float node_socket_calculate_height(const bNodeSocket *socket);
+void node_link_calculate_multi_input_position(const float socket_x,
+ const float socket_y,
+ const int index,
+ const int total_inputs,
+ float r[2]);
+
+int node_get_colorid(bNode *node);
+void node_draw_extra_info_panel(const SpaceNode *snode, const bNode *node);
+int node_get_resize_cursor(int directions);
+void node_draw_shadow(const SpaceNode *snode, const bNode *node, float radius, float alpha);
+void node_draw_default(const bContext *C,
+ ARegion *region,
+ SpaceNode *snode,
+ bNodeTree *ntree,
+ bNode *node,
+ bNodeInstanceKey key);
+void node_draw_sockets(const View2D *v2d,
+ const bContext *C,
+ bNodeTree *ntree,
+ bNode *node,
+ bool draw_outputs,
+ bool select_all);
+void node_update_default(const bContext *C, bNodeTree *ntree, bNode *node);
+int node_select_area_default(bNode *node, int x, int y);
+int node_tweak_area_default(bNode *node, int x, int y);
+void node_socket_color_get(const bContext *C,
+ bNodeTree *ntree,
+ PointerRNA *node_ptr,
+ bNodeSocket *sock,
+ float r_color[4]);
+void node_update_nodetree(const bContext *C, bNodeTree *ntree);
+void node_draw_nodetree(const bContext *C,
+ ARegion *region,
+ SpaceNode *snode,
+ bNodeTree *ntree,
+ bNodeInstanceKey parent_key);
+void node_draw_space(const bContext *C, ARegion *region);
+
+void node_set_cursor(wmWindow *win, SpaceNode *snode, float cursor[2]);
+/* DPI scaled coords */
+void node_to_view(const bNode *node, float x, float y, float *rx, float *ry);
+void node_to_updated_rect(const bNode *node, rctf *r_rect);
+void node_from_view(const bNode *node, float x, float y, float *rx, float *ry);
+
+/* node_toolbar.c */
+void node_toolbar_register(ARegionType *art);
+
+/* node_ops.c */
+void node_operatortypes(void);
+void node_keymap(wmKeyConfig *keyconf);
+
+/* node_select.c */
+void node_deselect_all(SpaceNode *snode);
+void node_socket_select(bNode *node, bNodeSocket *sock);
+void node_socket_deselect(bNode *node, bNodeSocket *sock, const bool deselect_node);
+void node_deselect_all_input_sockets(SpaceNode *snode, const bool deselect_nodes);
+void node_deselect_all_output_sockets(SpaceNode *snode, const bool deselect_nodes);
+void node_select_single(bContext *C, bNode *node);
+
+void NODE_OT_select(wmOperatorType *ot);
+void NODE_OT_select_all(wmOperatorType *ot);
+void NODE_OT_select_linked_to(wmOperatorType *ot);
+void NODE_OT_select_linked_from(wmOperatorType *ot);
+void NODE_OT_select_box(wmOperatorType *ot);
+void NODE_OT_select_circle(wmOperatorType *ot);
+void NODE_OT_select_lasso(wmOperatorType *ot);
+void NODE_OT_select_grouped(wmOperatorType *ot);
+void NODE_OT_select_same_type_step(wmOperatorType *ot);
+void NODE_OT_find_node(wmOperatorType *ot);
+
+/* node_view.c */
+int space_node_view_flag(
+ bContext *C, SpaceNode *snode, ARegion *region, const int node_flag, const int smooth_viewtx);
+
+void NODE_OT_view_all(wmOperatorType *ot);
+void NODE_OT_view_selected(wmOperatorType *ot);
+void NODE_OT_geometry_node_view_legacy(wmOperatorType *ot);
+
+void NODE_OT_backimage_move(wmOperatorType *ot);
+void NODE_OT_backimage_zoom(wmOperatorType *ot);
+void NODE_OT_backimage_fit(wmOperatorType *ot);
+void NODE_OT_backimage_sample(wmOperatorType *ot);
+
+/* drawnode.c */
+void nodelink_batch_start(SpaceNode *snode);
+void nodelink_batch_end(SpaceNode *snode);
+
+void node_draw_link(const bContext *C,
+ const View2D *v2d,
+ const SpaceNode *snode,
+ const bNodeLink *link);
+void node_draw_link_bezier(const bContext *C,
+ const View2D *v2d,
+ const SpaceNode *snode,
+ const bNodeLink *link,
+ int th_col1,
+ int th_col2,
+ int th_col3);
+bool node_link_bezier_points(const View2D *v2d,
+ const SpaceNode *snode,
+ const bNodeLink *link,
+ float coord_array[][2],
+ const int resol);
+bool node_link_bezier_handles(const View2D *v2d,
+ const SpaceNode *snode,
+ const bNodeLink *link,
+ float vec[4][2]);
+void draw_nodespace_back_pix(const bContext *C,
+ ARegion *region,
+ SpaceNode *snode,
+ bNodeInstanceKey parent_key);
+
+/* node_add.c */
+bNode *node_add_node(const bContext *C, const char *idname, int type, float locx, float locy);
+void NODE_OT_add_reroute(wmOperatorType *ot);
+void NODE_OT_add_group(wmOperatorType *ot);
+void NODE_OT_add_object(wmOperatorType *ot);
+void NODE_OT_add_collection(wmOperatorType *ot);
+void NODE_OT_add_texture(wmOperatorType *ot);
+void NODE_OT_add_file(wmOperatorType *ot);
+void NODE_OT_add_mask(wmOperatorType *ot);
+void NODE_OT_new_node_tree(wmOperatorType *ot);
+
+/* node_group.c */
+const char *node_group_idname(bContext *C);
+void NODE_OT_group_make(wmOperatorType *ot);
+void NODE_OT_group_insert(wmOperatorType *ot);
+void NODE_OT_group_ungroup(wmOperatorType *ot);
+void NODE_OT_group_separate(wmOperatorType *ot);
+void NODE_OT_group_edit(wmOperatorType *ot);
+
+/* node_relationships.c */
+void sort_multi_input_socket_links(SpaceNode *snode,
+ bNode *node,
+ bNodeLink *drag_link,
+ float cursor[2]);
+bool node_connected_to_output(Main *bmain, bNodeTree *ntree, bNode *node);
+
+void NODE_OT_link(wmOperatorType *ot);
+void NODE_OT_link_make(wmOperatorType *ot);
+void NODE_OT_links_cut(wmOperatorType *ot);
+void NODE_OT_links_detach(wmOperatorType *ot);
+void NODE_OT_links_mute(wmOperatorType *ot);
+
+void NODE_OT_parent_set(wmOperatorType *ot);
+void NODE_OT_join(wmOperatorType *ot);
+void NODE_OT_attach(wmOperatorType *ot);
+void NODE_OT_detach(wmOperatorType *ot);
+
+void NODE_OT_link_viewer(wmOperatorType *ot);
+
+void NODE_OT_insert_offset(wmOperatorType *ot);
+
+/* node_edit.c */
+void snode_notify(bContext *C, SpaceNode *snode);
+void snode_dag_update(bContext *C, SpaceNode *snode);
+void snode_set_context(const bContext *C);
+
+void snode_update(SpaceNode *snode, bNode *node);
+bool composite_node_active(bContext *C);
+bool composite_node_editable(bContext *C);
+
+bool node_has_hidden_sockets(bNode *node);
+void node_set_hidden_sockets(SpaceNode *snode, bNode *node, int set);
+int node_render_changed_exec(bContext *, wmOperator *);
+bool node_find_indicated_socket(
+ SpaceNode *snode, bNode **nodep, bNodeSocket **sockp, const float cursor[2], int in_out);
+float node_link_dim_factor(const View2D *v2d, const bNodeLink *link);
+bool node_link_is_hidden_or_dimmed(const View2D *v2d, const bNodeLink *link);
+
+void NODE_OT_duplicate(wmOperatorType *ot);
+void NODE_OT_delete(wmOperatorType *ot);
+void NODE_OT_delete_reconnect(wmOperatorType *ot);
+void NODE_OT_resize(wmOperatorType *ot);
+
+void NODE_OT_mute_toggle(wmOperatorType *ot);
+void NODE_OT_hide_toggle(wmOperatorType *ot);
+void NODE_OT_hide_socket_toggle(wmOperatorType *ot);
+void NODE_OT_preview_toggle(wmOperatorType *ot);
+void NODE_OT_options_toggle(wmOperatorType *ot);
+void NODE_OT_node_copy_color(wmOperatorType *ot);
+
+void NODE_OT_read_viewlayers(wmOperatorType *ot);
+void NODE_OT_render_changed(wmOperatorType *ot);
+
+void NODE_OT_output_file_add_socket(wmOperatorType *ot);
+void NODE_OT_output_file_remove_active_socket(wmOperatorType *ot);
+void NODE_OT_output_file_move_active_socket(wmOperatorType *ot);
+
+void NODE_OT_switch_view_update(wmOperatorType *ot);
+
+/* NOTE: clipboard_cut is a simple macro of copy + delete. */
+void NODE_OT_clipboard_copy(wmOperatorType *ot);
+void NODE_OT_clipboard_paste(wmOperatorType *ot);
+
+void NODE_OT_tree_socket_add(wmOperatorType *ot);
+void NODE_OT_tree_socket_remove(wmOperatorType *ot);
+void NODE_OT_tree_socket_change_type(wmOperatorType *ot);
+void NODE_OT_tree_socket_move(wmOperatorType *ot);
+
+void NODE_OT_shader_script_update(wmOperatorType *ot);
+
+void NODE_OT_viewer_border(wmOperatorType *ot);
+void NODE_OT_clear_viewer_border(wmOperatorType *ot);
+
+/* node_widgets.c */
+void NODE_GGT_backdrop_transform(wmGizmoGroupType *gzgt);
+void NODE_GGT_backdrop_crop(wmGizmoGroupType *gzgt);
+void NODE_GGT_backdrop_sun_beams(wmGizmoGroupType *gzgt);
+void NODE_GGT_backdrop_corner_pin(wmGizmoGroupType *gzgt);
+
+void NODE_OT_cryptomatte_layer_add(wmOperatorType *ot);
+void NODE_OT_cryptomatte_layer_remove(wmOperatorType *ot);
+
+/* node_geometry_attribute_search.cc */
+void node_geometry_add_attribute_search_button(const bContext *C,
+ const bNodeTree *node_tree,
+ const bNode *node,
+ PointerRNA *socket_ptr,
+ uiLayout *layout);
+
+extern const char *node_context_dir[];
+
+/* XXXXXX */
+
+/* Nodes draw without dpi - the view zoom is flexible. */
+#define HIDDEN_RAD (0.75f * U.widget_unit)
+#define BASIS_RAD (0.2f * U.widget_unit)
+#define NODE_DYS (U.widget_unit / 2)
+#define NODE_DY U.widget_unit
+#define NODE_SOCKDY (0.1f * U.widget_unit)
+#define NODE_WIDTH(node) (node->width * UI_DPI_FAC)
+#define NODE_HEIGHT(node) (node->height * UI_DPI_FAC)
+#define NODE_MARGIN_X (1.2f * U.widget_unit)
+#define NODE_SOCKSIZE (0.25f * U.widget_unit)
+#define NODE_MULTI_INPUT_LINK_GAP (0.25f * U.widget_unit)
+#define NODE_RESIZE_MARGIN (0.20f * U.widget_unit)
+#define NODE_LINK_RESOL 12
+
+namespace blender::ed::space_node {
+Vector<ui::ContextPathItem> context_path_for_space_node(const bContext &C);
+}
diff --git a/source/blender/editors/space_node/node_ops.c b/source/blender/editors/space_node/node_ops.cc
index 0c54da65e9c..4c08f4d7b47 100644
--- a/source/blender/editors/space_node/node_ops.c
+++ b/source/blender/editors/space_node/node_ops.cc
@@ -33,9 +33,9 @@
#include "WM_api.h"
#include "WM_types.h"
-#include "node_intern.h" /* own include */
+#include "node_intern.hh" /* own include */
-void node_operatortypes(void)
+void node_operatortypes()
{
WM_operatortype_append(NODE_OT_select);
WM_operatortype_append(NODE_OT_select_all);
diff --git a/source/blender/editors/space_node/node_relationships.cc b/source/blender/editors/space_node/node_relationships.cc
index 55b547d3195..aee749edbc4 100644
--- a/source/blender/editors/space_node/node_relationships.cc
+++ b/source/blender/editors/space_node/node_relationships.cc
@@ -60,9 +60,10 @@
#include "NOD_node_declaration.hh"
#include "NOD_node_tree_ref.hh"
-#include "node_intern.h" /* own include */
+#include "node_intern.hh" /* own include */
using namespace blender::nodes::node_tree_ref_types;
+using blender::Vector;
/* -------------------------------------------------------------------- */
/** \name Relations Helpers
@@ -207,11 +208,9 @@ static void clear_picking_highlight(ListBase *links)
}
}
-static LinkData *create_drag_link(Main *bmain, SpaceNode *snode, bNode *node, bNodeSocket *sock)
+static bNodeLink *create_drag_link(Main *bmain, SpaceNode *snode, bNode *node, bNodeSocket *sock)
{
- LinkData *linkdata = (LinkData *)MEM_callocN(sizeof(LinkData), "drag link op link data");
bNodeLink *oplink = (bNodeLink *)MEM_callocN(sizeof(bNodeLink), "drag link op link");
- linkdata->data = oplink;
if (sock->in_out == SOCK_OUT) {
oplink->fromnode = node;
oplink->fromsock = sock;
@@ -226,7 +225,7 @@ static LinkData *create_drag_link(Main *bmain, SpaceNode *snode, bNode *node, bN
oplink->flag |= NODE_LINK_TEST;
}
oplink->flag |= NODE_LINK_DRAGGED;
- return linkdata;
+ return oplink;
}
static void pick_link(const bContext *C,
@@ -240,10 +239,9 @@ static void pick_link(const bContext *C,
RNA_boolean_set(op->ptr, "has_link_picked", true);
Main *bmain = CTX_data_main(C);
- LinkData *linkdata = create_drag_link(
- bmain, snode, link_to_pick->fromnode, link_to_pick->fromsock);
+ bNodeLink *link = create_drag_link(bmain, snode, link_to_pick->fromnode, link_to_pick->fromsock);
- BLI_addtail(&nldrag->links, linkdata);
+ nldrag->links.append(link);
nodeRemLink(snode->edittree, link_to_pick);
BLI_assert(nldrag->last_node_hovered_while_dragging_a_link != nullptr);
@@ -324,19 +322,6 @@ static void pick_input_link_by_link_intersect(const bContext *C,
}
}
-static int sort_nodes_locx(const void *a, const void *b)
-{
- const bNodeListItem *nli1 = (const bNodeListItem *)a;
- const bNodeListItem *nli2 = (const bNodeListItem *)b;
- const bNode *node1 = nli1->node;
- const bNode *node2 = nli2->node;
-
- if (node1->locx > node2->locx) {
- return 1;
- }
- return 0;
-}
-
static bool socket_is_available(bNodeTree *UNUSED(ntree), bNodeSocket *sock, const bool allow_used)
{
if (nodeSocketIsHidden(sock)) {
@@ -527,30 +512,25 @@ static void snode_autoconnect(Main *bmain,
const bool replace)
{
bNodeTree *ntree = snode->edittree;
- ListBase *nodelist = (ListBase *)MEM_callocN(sizeof(ListBase), "items_list");
+ Vector<bNode *> sorted_nodes;
LISTBASE_FOREACH (bNode *, node, &ntree->nodes) {
if (node->flag & NODE_SELECT) {
- bNodeListItem *nli = (bNodeListItem *)MEM_mallocN(sizeof(bNodeListItem),
- "temporary node list item");
- nli->node = node;
- BLI_addtail(nodelist, nli);
+ sorted_nodes.append(node);
}
}
- /* sort nodes left to right */
- BLI_listbase_sort(nodelist, sort_nodes_locx);
+ /* Sort nodes left to right. */
+ std::sort(sorted_nodes.begin(), sorted_nodes.end(), [](const bNode *a, const bNode *b) {
+ return a->locx < b->locx;
+ });
int numlinks = 0;
- LISTBASE_FOREACH (bNodeListItem *, nli, nodelist) {
+ for (const int i : sorted_nodes.as_mutable_span().drop_back(1).index_range()) {
bool has_selected_inputs = false;
- if (nli->next == nullptr) {
- break;
- }
-
- bNode *node_fr = nli->node;
- bNode *node_to = nli->next->node;
+ bNode *node_fr = sorted_nodes[i];
+ bNode *node_to = sorted_nodes[i + 1];
/* corner case: input/output node aligned the wrong way around (T47729) */
if (BLI_listbase_is_empty(&node_to->inputs) || BLI_listbase_is_empty(&node_fr->outputs)) {
SWAP(bNode *, node_fr, node_to);
@@ -606,9 +586,6 @@ static void snode_autoconnect(Main *bmain,
if (numlinks > 0) {
ntreeUpdateTree(bmain, ntree);
}
-
- BLI_freelistN(nodelist);
- MEM_freeN(nodelist);
}
/** \} */
@@ -1013,9 +990,7 @@ static void node_link_exit(bContext *C, wmOperator *op, bool apply_links)
/* avoid updates while applying links */
ntree->is_updating = true;
- LISTBASE_FOREACH (LinkData *, linkdata, &nldrag->links) {
- bNodeLink *link = (bNodeLink *)linkdata->data;
-
+ for (bNodeLink *link : nldrag->links) {
/* See note below, but basically TEST flag means that the link
* was connected to output (or to a node which affects the
* output).
@@ -1068,10 +1043,7 @@ static void node_link_exit(bContext *C, wmOperator *op, bool apply_links)
UI_view2d_edge_pan_cancel(C, &nldrag->pan_data);
}
- BLI_remlink(&snode->runtime->linkdrag, nldrag);
- /* links->data pointers are either held by the tree or freed already */
- BLI_freelistN(&nldrag->links);
- MEM_freeN(nldrag);
+ snode->runtime->linkdrag.reset();
}
static void node_link_find_socket(bContext *C, wmOperator *op, float cursor[2])
@@ -1083,9 +1055,7 @@ static void node_link_find_socket(bContext *C, wmOperator *op, float cursor[2])
bNode *tnode;
bNodeSocket *tsock = nullptr;
if (node_find_indicated_socket(snode, &tnode, &tsock, cursor, SOCK_IN)) {
- LISTBASE_FOREACH (LinkData *, linkdata, &nldrag->links) {
- bNodeLink *link = (bNodeLink *)linkdata->data;
-
+ for (bNodeLink *link : nldrag->links) {
/* skip if socket is on the same node as the fromsock */
if (tnode && link->fromnode == tnode) {
continue;
@@ -1115,8 +1085,7 @@ static void node_link_find_socket(bContext *C, wmOperator *op, float cursor[2])
}
}
else {
- LISTBASE_FOREACH (LinkData *, linkdata, &nldrag->links) {
- bNodeLink *link = (bNodeLink *)linkdata->data;
+ for (bNodeLink *link : nldrag->links) {
if (nldrag->last_node_hovered_while_dragging_a_link) {
sort_multi_input_socket_links(
snode, nldrag->last_node_hovered_while_dragging_a_link, nullptr, cursor);
@@ -1130,9 +1099,7 @@ static void node_link_find_socket(bContext *C, wmOperator *op, float cursor[2])
bNode *tnode;
bNodeSocket *tsock = nullptr;
if (node_find_indicated_socket(snode, &tnode, &tsock, cursor, SOCK_OUT)) {
- LISTBASE_FOREACH (LinkData *, linkdata, &nldrag->links) {
- bNodeLink *link = (bNodeLink *)linkdata->data;
-
+ for (bNodeLink *link : nldrag->links) {
/* skip if this is already the target socket */
if (link->fromsock == tsock) {
continue;
@@ -1148,9 +1115,7 @@ static void node_link_find_socket(bContext *C, wmOperator *op, float cursor[2])
}
}
else {
- LISTBASE_FOREACH (LinkData *, linkdata, &nldrag->links) {
- bNodeLink *link = (bNodeLink *)linkdata->data;
-
+ for (bNodeLink *link : nldrag->links) {
link->fromnode = nullptr;
link->fromsock = nullptr;
}
@@ -1202,16 +1167,16 @@ static int node_link_modal(bContext *C, wmOperator *op, const wmEvent *event)
return OPERATOR_RUNNING_MODAL;
}
-/* return 1 when socket clicked */
-static bNodeLinkDrag *node_link_init(Main *bmain, SpaceNode *snode, float cursor[2], bool detach)
+static std::unique_ptr<bNodeLinkDrag> node_link_init(Main *bmain,
+ SpaceNode *snode,
+ float cursor[2],
+ bool detach)
{
- bNodeLinkDrag *nldrag = nullptr;
-
/* output indicated? */
bNode *node;
bNodeSocket *sock;
if (node_find_indicated_socket(snode, &node, &sock, cursor, SOCK_OUT)) {
- nldrag = (bNodeLinkDrag *)MEM_callocN(sizeof(bNodeLinkDrag), "drag link op customdata");
+ std::unique_ptr<bNodeLinkDrag> nldrag = std::make_unique<bNodeLinkDrag>();
const int num_links = nodeCountSocketLinks(snode->edittree, sock);
int link_limit = nodeSocketLinkLimit(sock);
@@ -1221,9 +1186,7 @@ static bNodeLinkDrag *node_link_init(Main *bmain, SpaceNode *snode, float cursor
/* detach current links and store them in the operator data */
LISTBASE_FOREACH_MUTABLE (bNodeLink *, link, &snode->edittree->links) {
if (link->fromsock == sock) {
- LinkData *linkdata = (LinkData *)MEM_callocN(sizeof(LinkData), "drag link op link data");
bNodeLink *oplink = (bNodeLink *)MEM_callocN(sizeof(bNodeLink), "drag link op link");
- linkdata->data = oplink;
*oplink = *link;
oplink->next = oplink->prev = nullptr;
oplink->flag |= NODE_LINK_VALID;
@@ -1240,7 +1203,7 @@ static bNodeLinkDrag *node_link_init(Main *bmain, SpaceNode *snode, float cursor
oplink->flag |= NODE_LINK_TEST;
}
- BLI_addtail(&nldrag->links, linkdata);
+ nldrag->links.append(oplink);
nodeRemLink(snode->edittree, link);
}
}
@@ -1249,14 +1212,14 @@ static bNodeLinkDrag *node_link_init(Main *bmain, SpaceNode *snode, float cursor
/* dragged links are fixed on output side */
nldrag->in_out = SOCK_OUT;
/* create a new link */
- LinkData *linkdata = create_drag_link(bmain, snode, node, sock);
-
- BLI_addtail(&nldrag->links, linkdata);
+ nldrag->links.append(create_drag_link(bmain, snode, node, sock));
}
+ return nldrag;
}
+
/* or an input? */
- else if (node_find_indicated_socket(snode, &node, &sock, cursor, SOCK_IN)) {
- nldrag = (bNodeLinkDrag *)MEM_callocN(sizeof(bNodeLinkDrag), "drag link op customdata");
+ if (node_find_indicated_socket(snode, &node, &sock, cursor, SOCK_IN)) {
+ std::unique_ptr<bNodeLinkDrag> nldrag = std::make_unique<bNodeLinkDrag>();
nldrag->last_node_hovered_while_dragging_a_link = node;
const int num_links = nodeCountSocketLinks(snode->edittree, sock);
@@ -1275,9 +1238,7 @@ static bNodeLinkDrag *node_link_init(Main *bmain, SpaceNode *snode, float cursor
}
if (link_to_pick != nullptr && !nldrag->from_multi_input_socket) {
- LinkData *linkdata = (LinkData *)MEM_callocN(sizeof(LinkData), "drag link op link data");
bNodeLink *oplink = (bNodeLink *)MEM_callocN(sizeof(bNodeLink), "drag link op link");
- linkdata->data = oplink;
*oplink = *link_to_pick;
oplink->next = oplink->prev = nullptr;
oplink->flag |= NODE_LINK_VALID;
@@ -1287,7 +1248,7 @@ static bNodeLinkDrag *node_link_init(Main *bmain, SpaceNode *snode, float cursor
oplink->flag |= NODE_LINK_TEST;
}
- BLI_addtail(&nldrag->links, linkdata);
+ nldrag->links.append(oplink);
nodeRemLink(snode->edittree, link_to_pick);
/* send changed event to original link->tonode */
@@ -1300,13 +1261,12 @@ static bNodeLinkDrag *node_link_init(Main *bmain, SpaceNode *snode, float cursor
/* dragged links are fixed on input side */
nldrag->in_out = SOCK_IN;
/* create a new link */
- LinkData *linkdata = create_drag_link(bmain, snode, node, sock);
-
- BLI_addtail(&nldrag->links, linkdata);
+ nldrag->links.append(create_drag_link(bmain, snode, node, sock));
}
+ return nldrag;
}
- return nldrag;
+ return {};
}
static int node_link_invoke(bContext *C, wmOperator *op, const wmEvent *event)
@@ -1324,13 +1284,13 @@ static int node_link_invoke(bContext *C, wmOperator *op, const wmEvent *event)
ED_preview_kill_jobs(CTX_wm_manager(C), bmain);
- bNodeLinkDrag *nldrag = node_link_init(bmain, snode, cursor, detach);
+ std::unique_ptr<bNodeLinkDrag> nldrag = node_link_init(bmain, snode, cursor, detach);
if (nldrag) {
UI_view2d_edge_pan_operator_init(C, &nldrag->pan_data, op);
- op->customdata = nldrag;
- BLI_addtail(&snode->runtime->linkdrag, nldrag);
+ snode->runtime->linkdrag = std::move(nldrag);
+ op->customdata = snode->runtime->linkdrag.get();
/* add modal handler */
WM_event_add_modal_handler(C, op);
@@ -1345,12 +1305,10 @@ static void node_link_cancel(bContext *C, wmOperator *op)
SpaceNode *snode = CTX_wm_space_node(C);
bNodeLinkDrag *nldrag = (bNodeLinkDrag *)op->customdata;
- BLI_remlink(&snode->runtime->linkdrag, nldrag);
-
UI_view2d_edge_pan_cancel(C, &nldrag->pan_data);
- BLI_freelistN(&nldrag->links);
- MEM_freeN(nldrag);
+ snode->runtime->linkdrag.reset();
+
clear_picking_highlight(&snode->edittree->links);
}
@@ -2369,8 +2327,8 @@ static void node_link_insert_offset_ntree(NodeInsertOfsData *iofsd,
/* NODE_TEST will be used later, so disable for all nodes */
ntreeNodeFlagSet(ntree, NODE_TEST, false);
- /* insert->totr isn't updated yet,
- * so totr_insert is used to get the correct worldspace coords */
+ /* `insert->totr` isn't updated yet,
+ * so `totr_insert` is used to get the correct world-space coords. */
rctf totr_insert;
node_to_updated_rect(insert, &totr_insert);
diff --git a/source/blender/editors/space_node/node_select.cc b/source/blender/editors/space_node/node_select.cc
index 29b8372d043..3c7b404547b 100644
--- a/source/blender/editors/space_node/node_select.cc
+++ b/source/blender/editors/space_node/node_select.cc
@@ -61,7 +61,7 @@
#include "MEM_guardedalloc.h"
-#include "node_intern.h" /* own include */
+#include "node_intern.hh" /* own include */
/**
* Function to detect if there is a visible view3d that uses workbench in texture mode.
diff --git a/source/blender/editors/space_node/node_templates.cc b/source/blender/editors/space_node/node_templates.cc
index f68d8589624..b2a7c1753fb 100644
--- a/source/blender/editors/space_node/node_templates.cc
+++ b/source/blender/editors/space_node/node_templates.cc
@@ -48,7 +48,7 @@
#include "UI_interface.h"
#include "ED_node.h" /* own include */
-#include "node_intern.h"
+#include "node_intern.hh"
#include "ED_undo.h"
diff --git a/source/blender/editors/space_node/node_toolbar.cc b/source/blender/editors/space_node/node_toolbar.cc
index 2e7d6ab6cd5..c32dcbef91b 100644
--- a/source/blender/editors/space_node/node_toolbar.cc
+++ b/source/blender/editors/space_node/node_toolbar.cc
@@ -30,7 +30,7 @@
#include "WM_api.h"
-#include "node_intern.h" /* own include */
+#include "node_intern.hh" /* own include */
/* ******************* node toolbar registration ************** */
diff --git a/source/blender/editors/space_node/node_view.cc b/source/blender/editors/space_node/node_view.cc
index 762b4b36a39..36b84bec7eb 100644
--- a/source/blender/editors/space_node/node_view.cc
+++ b/source/blender/editors/space_node/node_view.cc
@@ -54,7 +54,7 @@
#include "IMB_imbuf.h"
#include "IMB_imbuf_types.h"
-#include "node_intern.h" /* own include */
+#include "node_intern.hh" /* own include */
using blender::StringRef;
diff --git a/source/blender/editors/space_node/space_node.c b/source/blender/editors/space_node/space_node.cc
index 888aeb08334..ac64503cfc9 100644
--- a/source/blender/editors/space_node/space_node.c
+++ b/source/blender/editors/space_node/space_node.cc
@@ -52,21 +52,19 @@
#include "WM_api.h"
#include "WM_types.h"
-#include "node_intern.h" /* own include */
+#include "node_intern.hh" /* own include */
/* ******************** tree path ********************* */
void ED_node_tree_start(SpaceNode *snode, bNodeTree *ntree, ID *id, ID *from)
{
- bNodeTreePath *path, *path_next;
- for (path = snode->treepath.first; path; path = path_next) {
- path_next = path->next;
+ LISTBASE_FOREACH_MUTABLE (bNodeTreePath *, path, &snode->treepath) {
MEM_freeN(path);
}
BLI_listbase_clear(&snode->treepath);
if (ntree) {
- path = MEM_callocN(sizeof(bNodeTreePath), "node tree path");
+ bNodeTreePath *path = (bNodeTreePath *)MEM_callocN(sizeof(bNodeTreePath), "node tree path");
path->nodetree = ntree;
path->parent_key = NODE_INSTANCE_KEY_BASE;
@@ -94,13 +92,13 @@ void ED_node_tree_start(SpaceNode *snode, bNodeTree *ntree, ID *id, ID *from)
ED_node_set_active_viewer_key(snode);
- WM_main_add_notifier(NC_SCENE | ND_NODES, NULL);
+ WM_main_add_notifier(NC_SCENE | ND_NODES, nullptr);
}
void ED_node_tree_push(SpaceNode *snode, bNodeTree *ntree, bNode *gnode)
{
- bNodeTreePath *path = MEM_callocN(sizeof(bNodeTreePath), "node tree path");
- bNodeTreePath *prev_path = snode->treepath.last;
+ bNodeTreePath *path = (bNodeTreePath *)MEM_callocN(sizeof(bNodeTreePath), "node tree path");
+ bNodeTreePath *prev_path = (bNodeTreePath *)snode->treepath.last;
path->nodetree = ntree;
if (gnode) {
if (prev_path) {
@@ -129,12 +127,12 @@ void ED_node_tree_push(SpaceNode *snode, bNodeTree *ntree, bNode *gnode)
ED_node_set_active_viewer_key(snode);
- WM_main_add_notifier(NC_SCENE | ND_NODES, NULL);
+ WM_main_add_notifier(NC_SCENE | ND_NODES, nullptr);
}
void ED_node_tree_pop(SpaceNode *snode)
{
- bNodeTreePath *path = snode->treepath.last;
+ bNodeTreePath *path = (bNodeTreePath *)snode->treepath.last;
/* don't remove root */
if (path == snode->treepath.first) {
@@ -145,13 +143,13 @@ void ED_node_tree_pop(SpaceNode *snode)
MEM_freeN(path);
/* update current tree */
- path = snode->treepath.last;
+ path = (bNodeTreePath *)snode->treepath.last;
snode->edittree = path->nodetree;
ED_node_set_active_viewer_key(snode);
/* listener updates the View2D center from edittree */
- WM_main_add_notifier(NC_SCENE | ND_NODES, NULL);
+ WM_main_add_notifier(NC_SCENE | ND_NODES, nullptr);
}
int ED_node_tree_depth(SpaceNode *snode)
@@ -163,12 +161,12 @@ bNodeTree *ED_node_tree_get(SpaceNode *snode, int level)
{
bNodeTreePath *path;
int i;
- for (path = snode->treepath.last, i = 0; path; path = path->prev, i++) {
+ for (path = (bNodeTreePath *)snode->treepath.last, i = 0; path; path = path->prev, i++) {
if (i == level) {
return path->nodetree;
}
}
- return NULL;
+ return nullptr;
}
int ED_node_tree_path_length(SpaceNode *snode)
@@ -203,7 +201,7 @@ void ED_node_tree_path_get(SpaceNode *snode, char *value)
void ED_node_set_active_viewer_key(SpaceNode *snode)
{
- bNodeTreePath *path = snode->treepath.last;
+ bNodeTreePath *path = (bNodeTreePath *)snode->treepath.last;
if (snode->nodetree && path) {
snode->nodetree->active_viewer_key = path->parent_key;
}
@@ -211,7 +209,7 @@ void ED_node_set_active_viewer_key(SpaceNode *snode)
void space_node_group_offset(SpaceNode *snode, float *x, float *y)
{
- bNodeTreePath *path = snode->treepath.last;
+ bNodeTreePath *path = (bNodeTreePath *)snode->treepath.last;
if (path && path->prev) {
float dcenter[2];
@@ -228,10 +226,7 @@ void space_node_group_offset(SpaceNode *snode, float *x, float *y)
static SpaceLink *node_create(const ScrArea *UNUSED(area), const Scene *UNUSED(scene))
{
- ARegion *region;
- SpaceNode *snode;
-
- snode = MEM_callocN(sizeof(SpaceNode), "initnode");
+ SpaceNode *snode = (SpaceNode *)MEM_callocN(sizeof(SpaceNode), "initnode");
snode->spacetype = SPACE_NODE;
snode->flag = SNODE_SHOW_GPENCIL | SNODE_USE_ALPHA;
@@ -249,21 +244,21 @@ static SpaceLink *node_create(const ScrArea *UNUSED(area), const Scene *UNUSED(s
NODE_TREE_TYPES_END;
/* header */
- region = MEM_callocN(sizeof(ARegion), "header for node");
+ ARegion *region = (ARegion *)MEM_callocN(sizeof(ARegion), "header for node");
BLI_addtail(&snode->regionbase, region);
region->regiontype = RGN_TYPE_HEADER;
region->alignment = (U.uiflag & USER_HEADER_BOTTOM) ? RGN_ALIGN_BOTTOM : RGN_ALIGN_TOP;
/* buttons/list view */
- region = MEM_callocN(sizeof(ARegion), "buttons for node");
+ region = (ARegion *)MEM_callocN(sizeof(ARegion), "buttons for node");
BLI_addtail(&snode->regionbase, region);
region->regiontype = RGN_TYPE_UI;
region->alignment = RGN_ALIGN_RIGHT;
/* toolbar */
- region = MEM_callocN(sizeof(ARegion), "node tools");
+ region = (ARegion *)MEM_callocN(sizeof(ARegion), "node tools");
BLI_addtail(&snode->regionbase, region);
region->regiontype = RGN_TYPE_TOOLS;
@@ -272,7 +267,7 @@ static SpaceLink *node_create(const ScrArea *UNUSED(area), const Scene *UNUSED(s
region->flag = RGN_FLAG_HIDDEN;
/* main region */
- region = MEM_callocN(sizeof(ARegion), "main region for node");
+ region = (ARegion *)MEM_callocN(sizeof(ARegion), "main region for node");
BLI_addtail(&snode->regionbase, region);
region->regiontype = RGN_TYPE_WINDOW;
@@ -290,7 +285,7 @@ static SpaceLink *node_create(const ScrArea *UNUSED(area), const Scene *UNUSED(s
region->v2d.max[0] = 32000.0f;
region->v2d.max[1] = 32000.0f;
- region->v2d.minzoom = 0.09f;
+ region->v2d.minzoom = 0.05f;
region->v2d.maxzoom = 2.31f;
region->v2d.scroll = (V2D_SCROLL_RIGHT | V2D_SCROLL_BOTTOM);
@@ -308,7 +303,10 @@ static void node_free(SpaceLink *sl)
MEM_freeN(path);
}
- MEM_SAFE_FREE(snode->runtime);
+ if (snode->runtime) {
+ snode->runtime->linkdrag.reset();
+ MEM_freeN(snode->runtime);
+ }
}
/* spacetype; init callback */
@@ -316,8 +314,8 @@ static void node_init(struct wmWindowManager *UNUSED(wm), ScrArea *area)
{
SpaceNode *snode = (SpaceNode *)area->spacedata.first;
- if (snode->runtime == NULL) {
- snode->runtime = MEM_callocN(sizeof(SpaceNode_Runtime), __func__);
+ if (snode->runtime == nullptr) {
+ snode->runtime = (SpaceNode_Runtime *)MEM_callocN(sizeof(SpaceNode_Runtime), __func__);
}
}
@@ -327,7 +325,7 @@ static void node_area_listener(const wmSpaceTypeListenerParams *params)
wmNotifier *wmn = params->notifier;
/* NOTE: #ED_area_tag_refresh will re-execute compositor. */
- SpaceNode *snode = area->spacedata.first;
+ SpaceNode *snode = (SpaceNode *)area->spacedata.first;
/* shaderfrom is only used for new shading nodes, otherwise all shaders are from objects */
short shader_type = snode->shaderfrom;
@@ -337,7 +335,7 @@ static void node_area_listener(const wmSpaceTypeListenerParams *params)
switch (wmn->data) {
case ND_NODES: {
ARegion *region = BKE_area_find_region_type(area, RGN_TYPE_WINDOW);
- bNodeTreePath *path = snode->treepath.last;
+ bNodeTreePath *path = (bNodeTreePath *)snode->treepath.last;
/* shift view to node tree center */
if (region && path) {
UI_view2d_center_set(&region->v2d, path->view_center[0], path->view_center[1]);
@@ -379,7 +377,7 @@ static void node_area_listener(const wmSpaceTypeListenerParams *params)
ED_area_tag_refresh(area);
}
else if (wmn->action == NA_ADDED && snode->edittree) {
- nodeSetActiveID(snode->edittree, ID_MA, wmn->reference);
+ nodeSetActiveID(snode->edittree, ID_MA, (ID *)wmn->reference);
}
}
break;
@@ -404,7 +402,7 @@ static void node_area_listener(const wmSpaceTypeListenerParams *params)
else if (ED_node_is_geometry(snode)) {
/* Rather strict check: only redraw when the reference matches the current editor's ID. */
if (wmn->data == ND_MODIFIER) {
- if (wmn->reference == snode->id || snode->id == NULL) {
+ if (wmn->reference == snode->id || snode->id == nullptr) {
ED_area_tag_refresh(area);
}
}
@@ -447,7 +445,7 @@ static void node_area_listener(const wmSpaceTypeListenerParams *params)
/* note that nodeUpdateID is already called by BKE_image_signal() on all
* scenes so really this is just to know if the images is used in the compo else
* painting on images could become very slow when the compositor is open. */
- if (nodeUpdateID(snode->nodetree, wmn->reference)) {
+ if (nodeUpdateID(snode->nodetree, (ID *)wmn->reference)) {
ED_area_tag_refresh(area);
}
}
@@ -457,7 +455,7 @@ static void node_area_listener(const wmSpaceTypeListenerParams *params)
case NC_MOVIECLIP:
if (wmn->action == NA_EDITED) {
if (ED_node_is_compositor(snode)) {
- if (nodeUpdateID(snode->nodetree, wmn->reference)) {
+ if (nodeUpdateID(snode->nodetree, (ID *)wmn->reference)) {
ED_area_tag_refresh(area);
}
}
@@ -485,7 +483,7 @@ static void node_area_listener(const wmSpaceTypeListenerParams *params)
static void node_area_refresh(const struct bContext *C, ScrArea *area)
{
/* default now: refresh node is starting preview */
- SpaceNode *snode = area->spacedata.first;
+ SpaceNode *snode = (SpaceNode *)area->spacedata.first;
snode_set_context(C);
@@ -494,19 +492,19 @@ static void node_area_refresh(const struct bContext *C, ScrArea *area)
if (GS(snode->id->name) == ID_MA) {
Material *ma = (Material *)snode->id;
if (ma->use_nodes) {
- ED_preview_shader_job(C, area, snode->id, NULL, NULL, 100, 100, PR_NODE_RENDER);
+ ED_preview_shader_job(C, area, snode->id, nullptr, nullptr, 100, 100, PR_NODE_RENDER);
}
}
else if (GS(snode->id->name) == ID_LA) {
Light *la = (Light *)snode->id;
if (la->use_nodes) {
- ED_preview_shader_job(C, area, snode->id, NULL, NULL, 100, 100, PR_NODE_RENDER);
+ ED_preview_shader_job(C, area, snode->id, nullptr, nullptr, 100, 100, PR_NODE_RENDER);
}
}
else if (GS(snode->id->name) == ID_WO) {
World *wo = (World *)snode->id;
if (wo->use_nodes) {
- ED_preview_shader_job(C, area, snode->id, NULL, NULL, 100, 100, PR_NODE_RENDER);
+ ED_preview_shader_job(C, area, snode->id, nullptr, nullptr, 100, 100, PR_NODE_RENDER);
}
}
}
@@ -516,7 +514,7 @@ static void node_area_refresh(const struct bContext *C, ScrArea *area)
/* recalc is set on 3d view changes for auto compo */
if (snode->runtime->recalc) {
snode->runtime->recalc = false;
- node_render_changed_exec((struct bContext *)C, NULL);
+ node_render_changed_exec((struct bContext *)C, nullptr);
}
else {
ED_node_composite_job(C, snode->nodetree, scene);
@@ -526,7 +524,7 @@ static void node_area_refresh(const struct bContext *C, ScrArea *area)
else if (snode->nodetree->type == NTREE_TEXTURE) {
Tex *tex = (Tex *)snode->id;
if (tex->use_nodes) {
- ED_preview_shader_job(C, area, snode->id, NULL, NULL, 100, 100, PR_NODE_RENDER);
+ ED_preview_shader_job(C, area, snode->id, nullptr, nullptr, 100, 100, PR_NODE_RENDER);
}
}
}
@@ -535,14 +533,11 @@ static void node_area_refresh(const struct bContext *C, ScrArea *area)
static SpaceLink *node_duplicate(SpaceLink *sl)
{
SpaceNode *snode = (SpaceNode *)sl;
- SpaceNode *snoden = MEM_dupallocN(snode);
+ SpaceNode *snoden = (SpaceNode *)MEM_dupallocN(snode);
BLI_duplicatelist(&snoden->treepath, &snode->treepath);
- if (snode->runtime != NULL) {
- snoden->runtime = MEM_dupallocN(snode->runtime);
- BLI_listbase_clear(&snoden->runtime->linkdrag);
- }
+ snoden->runtime = nullptr;
/* NOTE: no need to set node tree user counts,
* the editor only keeps at least 1 (id_us_ensure_real),
@@ -596,7 +591,7 @@ void ED_node_cursor_location_set(SpaceNode *snode, const float value[2])
static void node_cursor(wmWindow *win, ScrArea *area, ARegion *region)
{
- SpaceNode *snode = area->spacedata.first;
+ SpaceNode *snode = (SpaceNode *)area->spacedata.first;
/* convert mouse coordinates to v2d space */
UI_view2d_region_to_view(&region->v2d,
@@ -710,7 +705,7 @@ static void node_id_path_drop_copy(wmDrag *drag, wmDropBox *drop)
}
/* this region dropbox definition */
-static void node_dropboxes(void)
+static void node_dropboxes()
{
ListBase *lb = WM_dropboxmap_find("Node Editor", SPACE_NODE, RGN_TYPE_WINDOW);
@@ -719,37 +714,37 @@ static void node_dropboxes(void)
node_object_drop_poll,
node_id_drop_copy,
WM_drag_free_imported_drag_ID,
- NULL);
+ nullptr);
WM_dropbox_add(lb,
"NODE_OT_add_collection",
node_collection_drop_poll,
node_id_drop_copy,
WM_drag_free_imported_drag_ID,
- NULL);
+ nullptr);
WM_dropbox_add(lb,
"NODE_OT_add_texture",
node_texture_drop_poll,
node_id_drop_copy,
WM_drag_free_imported_drag_ID,
- NULL);
+ nullptr);
WM_dropbox_add(lb,
"NODE_OT_add_group",
node_group_drop_poll,
node_group_drop_copy,
WM_drag_free_imported_drag_ID,
- NULL);
+ nullptr);
WM_dropbox_add(lb,
"NODE_OT_add_file",
node_ima_drop_poll,
node_id_path_drop_copy,
WM_drag_free_imported_drag_ID,
- NULL);
+ nullptr);
WM_dropbox_add(lb,
"NODE_OT_add_mask",
node_mask_drop_poll,
node_id_drop_copy,
WM_drag_free_imported_drag_ID,
- NULL);
+ nullptr);
}
/* ************* end drop *********** */
@@ -843,7 +838,7 @@ static void node_region_listener(const wmRegionListenerParams *params)
}
const char *node_context_dir[] = {
- "selected_nodes", "active_node", "light", "material", "world", NULL};
+ "selected_nodes", "active_node", "light", "material", "world", nullptr};
static int /*eContextResult*/ node_context(const bContext *C,
const char *member,
bContextDataResult *result)
@@ -855,10 +850,8 @@ static int /*eContextResult*/ node_context(const bContext *C,
return CTX_RESULT_OK;
}
if (CTX_data_equals(member, "selected_nodes")) {
- bNode *node;
-
if (snode->edittree) {
- for (node = snode->edittree->nodes.last; node; node = node->prev) {
+ LISTBASE_FOREACH_BACKWARD (bNode *, node, &snode->edittree->nodes) {
if (node->flag & NODE_SELECT) {
CTX_data_list_add(result, &snode->edittree->id, &RNA_Node, node);
}
@@ -907,11 +900,11 @@ static int /*eContextResult*/ node_context(const bContext *C,
return CTX_RESULT_MEMBER_NOT_FOUND;
}
-static void node_widgets(void)
+static void node_widgets()
{
- /* create the widgetmap for the area here */
- wmGizmoMapType *gzmap_type = WM_gizmomaptype_ensure(
- &(const struct wmGizmoMapType_Params){SPACE_NODE, RGN_TYPE_WINDOW});
+ /* Create the widget-map for the area here. */
+ wmGizmoMapType_Params params{SPACE_NODE, RGN_TYPE_WINDOW};
+ wmGizmoMapType *gzmap_type = WM_gizmomaptype_ensure(&params);
WM_gizmogrouptype_append_and_link(gzmap_type, NODE_GGT_backdrop_transform);
WM_gizmogrouptype_append_and_link(gzmap_type, NODE_GGT_backdrop_crop);
WM_gizmogrouptype_append_and_link(gzmap_type, NODE_GGT_backdrop_sun_beams);
@@ -928,15 +921,15 @@ static void node_id_remap(ScrArea *UNUSED(area), SpaceLink *slink, ID *old_id, I
*/
BLI_freelistN(&snode->treepath);
- /* XXX Untested in case new_id != NULL... */
+ /* XXX Untested in case new_id != nullptr... */
snode->id = new_id;
- snode->from = NULL;
- snode->nodetree = NULL;
- snode->edittree = NULL;
+ snode->from = nullptr;
+ snode->nodetree = nullptr;
+ snode->edittree = nullptr;
}
else if (GS(old_id->name) == ID_OB) {
if (snode->from == old_id) {
- if (new_id == NULL) {
+ if (new_id == nullptr) {
snode->flag &= ~SNODE_PIN;
}
snode->from = new_id;
@@ -952,7 +945,7 @@ static void node_id_remap(ScrArea *UNUSED(area), SpaceLink *slink, ID *old_id, I
else if (GS(old_id->name) == ID_NT) {
bNodeTreePath *path, *path_next;
- for (path = snode->treepath.first; path; path = path->next) {
+ for (path = (bNodeTreePath *)snode->treepath.first; path; path = path->next) {
if ((ID *)path->nodetree == old_id) {
path->nodetree = (bNodeTree *)new_id;
id_us_ensure_real(new_id);
@@ -961,7 +954,7 @@ static void node_id_remap(ScrArea *UNUSED(area), SpaceLink *slink, ID *old_id, I
/* first nodetree in path is same as snode->nodetree */
snode->nodetree = path->nodetree;
}
- if (path->nodetree == NULL) {
+ if (path->nodetree == nullptr) {
break;
}
}
@@ -977,24 +970,24 @@ static void node_id_remap(ScrArea *UNUSED(area), SpaceLink *slink, ID *old_id, I
/* edittree is just the last in the path,
* set this directly since the path may have been shortened above */
if (snode->treepath.last) {
- path = snode->treepath.last;
+ path = (bNodeTreePath *)snode->treepath.last;
snode->edittree = path->nodetree;
}
else {
- snode->edittree = NULL;
+ snode->edittree = nullptr;
}
}
}
static int node_space_subtype_get(ScrArea *area)
{
- SpaceNode *snode = area->spacedata.first;
+ SpaceNode *snode = (SpaceNode *)area->spacedata.first;
return rna_node_tree_idname_to_enum(snode->tree_idname);
}
static void node_space_subtype_set(ScrArea *area, int value)
{
- SpaceNode *snode = area->spacedata.first;
+ SpaceNode *snode = (SpaceNode *)area->spacedata.first;
ED_node_set_tree_type(snode, rna_node_tree_type_from_enum(value));
}
@@ -1011,7 +1004,7 @@ static void node_space_subtype_item_extend(bContext *C, EnumPropertyItem **item,
/* only called once, from space/spacetypes.c */
void ED_spacetype_node(void)
{
- SpaceType *st = MEM_callocN(sizeof(SpaceType), "spacetype node");
+ SpaceType *st = (SpaceType *)MEM_callocN(sizeof(SpaceType), "spacetype node");
ARegionType *art;
st->spaceid = SPACE_NODE;
@@ -1034,7 +1027,7 @@ void ED_spacetype_node(void)
st->space_subtype_set = node_space_subtype_set;
/* regions: main window */
- art = MEM_callocN(sizeof(ARegionType), "spacetype node region");
+ art = (ARegionType *)MEM_callocN(sizeof(ARegionType), "spacetype node region");
art->regionid = RGN_TYPE_WINDOW;
art->init = node_main_region_init;
art->draw = node_main_region_draw;
@@ -1048,7 +1041,7 @@ void ED_spacetype_node(void)
BLI_addhead(&st->regiontypes, art);
/* regions: header */
- art = MEM_callocN(sizeof(ARegionType), "spacetype node region");
+ art = (ARegionType *)MEM_callocN(sizeof(ARegionType), "spacetype node region");
art->regionid = RGN_TYPE_HEADER;
art->prefsizey = HEADERY;
art->keymapflag = ED_KEYMAP_UI | ED_KEYMAP_VIEW2D | ED_KEYMAP_FRAMES | ED_KEYMAP_HEADER;
@@ -1059,7 +1052,7 @@ void ED_spacetype_node(void)
BLI_addhead(&st->regiontypes, art);
/* regions: listview/buttons */
- art = MEM_callocN(sizeof(ARegionType), "spacetype node region");
+ art = (ARegionType *)MEM_callocN(sizeof(ARegionType), "spacetype node region");
art->regionid = RGN_TYPE_UI;
art->prefsizex = UI_SIDEBAR_PANEL_WIDTH;
art->keymapflag = ED_KEYMAP_UI | ED_KEYMAP_FRAMES;
@@ -1070,7 +1063,7 @@ void ED_spacetype_node(void)
BLI_addhead(&st->regiontypes, art);
/* regions: toolbar */
- art = MEM_callocN(sizeof(ARegionType), "spacetype view3d tools region");
+ art = (ARegionType *)MEM_callocN(sizeof(ARegionType), "spacetype view3d tools region");
art->regionid = RGN_TYPE_TOOLS;
art->prefsizex = 58; /* XXX */
art->prefsizey = 50; /* XXX */
diff --git a/source/blender/editors/space_outliner/outliner_edit.c b/source/blender/editors/space_outliner/outliner_edit.c
index 738db28a2b6..e449e4a609b 100644
--- a/source/blender/editors/space_outliner/outliner_edit.c
+++ b/source/blender/editors/space_outliner/outliner_edit.c
@@ -763,7 +763,7 @@ static int outliner_id_copy_tag(SpaceOutliner *space_outliner, ListBase *tree)
if (tselem->flag & TSE_SELECTED && ELEM(tselem->type, TSE_SOME_ID, TSE_LAYER_COLLECTION)) {
ID *id = tselem->id;
if (!(id->tag & LIB_TAG_DOIT)) {
- BKE_copybuffer_tag_ID(tselem->id);
+ BKE_copybuffer_copy_tag_ID(tselem->id);
num_ids++;
}
}
@@ -781,7 +781,7 @@ static int outliner_id_copy_exec(bContext *C, wmOperator *op)
SpaceOutliner *space_outliner = CTX_wm_space_outliner(C);
char str[FILE_MAX];
- BKE_copybuffer_begin(bmain);
+ BKE_copybuffer_copy_begin(bmain);
const int num_ids = outliner_id_copy_tag(space_outliner, &space_outliner->tree);
if (num_ids == 0) {
@@ -790,7 +790,7 @@ static int outliner_id_copy_exec(bContext *C, wmOperator *op)
}
BLI_join_dirfile(str, sizeof(str), BKE_tempdir_base(), "copybuffer.blend");
- BKE_copybuffer_save(bmain, str, op->reports);
+ BKE_copybuffer_copy_end(bmain, str, op->reports);
BKE_reportf(op->reports, RPT_INFO, "Copied %d selected data-block(s)", num_ids);
diff --git a/source/blender/editors/space_sequencer/space_sequencer.c b/source/blender/editors/space_sequencer/space_sequencer.c
index 4b6c5e29d77..f6f8e45590f 100644
--- a/source/blender/editors/space_sequencer/space_sequencer.c
+++ b/source/blender/editors/space_sequencer/space_sequencer.c
@@ -28,6 +28,7 @@
#include "DNA_gpencil_types.h"
#include "DNA_mask_types.h"
#include "DNA_scene_types.h"
+#include "DNA_sound_types.h"
#include "MEM_guardedalloc.h"
@@ -400,7 +401,7 @@ static bool image_drop_poll(bContext *C, wmDrag *drag, const wmEvent *event)
}
}
- return 0;
+ return WM_drag_is_ID_type(drag, ID_IM);
}
static bool movie_drop_poll(bContext *C, wmDrag *drag, const wmEvent *event)
@@ -416,7 +417,8 @@ static bool movie_drop_poll(bContext *C, wmDrag *drag, const wmEvent *event)
}
}
}
- return 0;
+
+ return WM_drag_is_ID_type(drag, ID_MC);
}
static bool sound_drop_poll(bContext *C, wmDrag *drag, const wmEvent *event)
@@ -432,35 +434,61 @@ static bool sound_drop_poll(bContext *C, wmDrag *drag, const wmEvent *event)
}
}
}
- return 0;
+
+ return WM_drag_is_ID_type(drag, ID_SO);
}
static void sequencer_drop_copy(wmDrag *drag, wmDropBox *drop)
{
- /* Copy drag path to properties. */
- if (RNA_struct_find_property(drop->ptr, "filepath")) {
- RNA_string_set(drop->ptr, "filepath", drag->path);
+ ID *id = WM_drag_get_local_ID_or_import_from_asset(drag, 0);
+ /* ID dropped. */
+ if (id != NULL) {
+ const ID_Type id_type = GS(id->name);
+ if (id_type == ID_IM) {
+ Image *ima = (Image *)id;
+ PointerRNA itemptr;
+ char dir[FILE_MAX], file[FILE_MAX];
+ BLI_split_dirfile(ima->filepath, dir, file, sizeof(dir), sizeof(file));
+ RNA_string_set(drop->ptr, "directory", dir);
+ RNA_collection_clear(drop->ptr, "files");
+ RNA_collection_add(drop->ptr, "files", &itemptr);
+ RNA_string_set(&itemptr, "name", file);
+ }
+ else if (id_type == ID_MC) {
+ MovieClip *clip = (MovieClip *)id;
+ RNA_string_set(drop->ptr, "filepath", clip->filepath);
+ RNA_struct_property_unset(drop->ptr, "name");
+ }
+ else if (id_type == ID_SO) {
+ bSound *sound = (bSound *)id;
+ RNA_string_set(drop->ptr, "filepath", sound->filepath);
+ RNA_struct_property_unset(drop->ptr, "name");
+ }
}
+ /* Path dropped. */
+ else if (drag->path[0]) {
+ if (RNA_struct_find_property(drop->ptr, "filepath")) {
+ RNA_string_set(drop->ptr, "filepath", drag->path);
+ }
+ if (RNA_struct_find_property(drop->ptr, "directory")) {
+ PointerRNA itemptr;
+ char dir[FILE_MAX], file[FILE_MAX];
- if (RNA_struct_find_property(drop->ptr, "directory")) {
- PointerRNA itemptr;
- char dir[FILE_MAX], file[FILE_MAX];
-
- BLI_split_dirfile(drag->path, dir, file, sizeof(dir), sizeof(file));
+ BLI_split_dirfile(drag->path, dir, file, sizeof(dir), sizeof(file));
- RNA_string_set(drop->ptr, "directory", dir);
+ RNA_string_set(drop->ptr, "directory", dir);
- RNA_collection_clear(drop->ptr, "files");
- RNA_collection_add(drop->ptr, "files", &itemptr);
- RNA_string_set(&itemptr, "name", file);
+ RNA_collection_clear(drop->ptr, "files");
+ RNA_collection_add(drop->ptr, "files", &itemptr);
+ RNA_string_set(&itemptr, "name", file);
+ }
}
}
/* This region dropbox definition. */
-static void sequencer_dropboxes(void)
-{
- ListBase *lb = WM_dropboxmap_find("Sequencer", SPACE_SEQ, RGN_TYPE_WINDOW);
+static void sequencer_dropboxes_add_to_lb(ListBase *lb)
+{
WM_dropbox_add(
lb, "SEQUENCER_OT_image_strip_add", image_drop_poll, sequencer_drop_copy, NULL, NULL);
WM_dropbox_add(
@@ -469,6 +497,14 @@ static void sequencer_dropboxes(void)
lb, "SEQUENCER_OT_sound_strip_add", sound_drop_poll, sequencer_drop_copy, NULL, NULL);
}
+static void sequencer_dropboxes(void)
+{
+ ListBase *lb = WM_dropboxmap_find("Sequencer", SPACE_SEQ, RGN_TYPE_WINDOW);
+ sequencer_dropboxes_add_to_lb(lb);
+ lb = WM_dropboxmap_find("Sequencer", SPACE_SEQ, RGN_TYPE_PREVIEW);
+ sequencer_dropboxes_add_to_lb(lb);
+}
+
/* ************* end drop *********** */
/* DO NOT make this static, this hides the symbol and breaks API generation script. */
@@ -757,6 +793,9 @@ static void sequencer_preview_region_init(wmWindowManager *wm, ARegion *region)
/* Own keymap. */
keymap = WM_keymap_ensure(wm->defaultconf, "SequencerPreview", SPACE_SEQ, 0);
WM_event_add_keymap_handler_v2d_mask(&region->handlers, keymap);
+
+ ListBase *lb = WM_dropboxmap_find("Sequencer", SPACE_SEQ, RGN_TYPE_PREVIEW);
+ WM_event_add_dropbox_handler(&region->handlers, lb);
}
static void sequencer_preview_region_layout(const bContext *C, ARegion *region)
diff --git a/source/blender/editors/space_spreadsheet/CMakeLists.txt b/source/blender/editors/space_spreadsheet/CMakeLists.txt
index 91fe1bc01b7..27446fe1a94 100644
--- a/source/blender/editors/space_spreadsheet/CMakeLists.txt
+++ b/source/blender/editors/space_spreadsheet/CMakeLists.txt
@@ -41,10 +41,10 @@ set(SRC
spreadsheet_data_source.cc
spreadsheet_data_source_geometry.cc
spreadsheet_dataset_draw.cc
- spreadsheet_dataset_layout.cc
spreadsheet_draw.cc
spreadsheet_layout.cc
spreadsheet_ops.cc
+ spreadsheet_panels.cc
spreadsheet_row_filter.cc
spreadsheet_row_filter_ui.cc
@@ -56,7 +56,6 @@ set(SRC
spreadsheet_data_source.hh
spreadsheet_data_source_geometry.hh
spreadsheet_dataset_draw.hh
- spreadsheet_dataset_layout.hh
spreadsheet_draw.hh
spreadsheet_intern.hh
spreadsheet_layout.hh
@@ -67,4 +66,14 @@ set(SRC
set(LIB
)
+if(WITH_OPENVDB)
+ list(APPEND INC_SYS
+ ${OPENVDB_INCLUDE_DIRS}
+ )
+ list(APPEND LIB
+ ${OPENVDB_LIBRARIES}
+ )
+ add_definitions(-DWITH_OPENVDB ${OPENVDB_DEFINITIONS})
+endif()
+
blender_add_lib(bf_editor_space_spreadsheet "${SRC}" "${INC}" "${INC_SYS}" "${LIB}")
diff --git a/source/blender/editors/space_spreadsheet/space_spreadsheet.cc b/source/blender/editors/space_spreadsheet/space_spreadsheet.cc
index d54af7ffe2c..b37706e02e8 100644
--- a/source/blender/editors/space_spreadsheet/space_spreadsheet.cc
+++ b/source/blender/editors/space_spreadsheet/space_spreadsheet.cc
@@ -41,6 +41,8 @@
#include "WM_api.h"
#include "WM_types.h"
+#include "BLT_translation.h"
+
#include "BLF_api.h"
#include "spreadsheet_intern.hh"
@@ -319,6 +321,8 @@ static float get_default_column_width(const ColumnValues &values)
return 4.0f * float_width;
case SPREADSHEET_VALUE_TYPE_INSTANCES:
return 8.0f;
+ case SPREADSHEET_VALUE_TYPE_STRING:
+ return 5.0f;
}
return float_width;
}
@@ -589,35 +593,10 @@ static void spreadsheet_dataset_region_listener(const wmRegionListenerParams *pa
spreadsheet_header_region_listener(params);
}
-static void spreadsheet_dataset_region_init(wmWindowManager *wm, ARegion *region)
-{
- region->v2d.scroll |= V2D_SCROLL_RIGHT;
- region->v2d.scroll &= ~(V2D_SCROLL_LEFT | V2D_SCROLL_TOP | V2D_SCROLL_BOTTOM);
- region->v2d.scroll |= V2D_SCROLL_HORIZONTAL_HIDE;
- region->v2d.scroll |= V2D_SCROLL_VERTICAL_HIDE;
-
- UI_view2d_region_reinit(&region->v2d, V2D_COMMONVIEW_LIST, region->winx, region->winy);
-
- wmKeyMap *keymap = WM_keymap_ensure(
- wm->defaultconf, "Spreadsheet Generic", SPACE_SPREADSHEET, 0);
- WM_event_add_keymap_handler(&region->handlers, keymap);
-}
-
static void spreadsheet_dataset_region_draw(const bContext *C, ARegion *region)
{
spreadsheet_update_context_path(C);
-
- View2D *v2d = &region->v2d;
- UI_view2d_view_ortho(v2d);
- UI_ThemeClearColor(TH_BACK);
-
- draw_dataset_in_region(C, region);
-
- /* reset view matrix */
- UI_view2d_view_restore(C);
-
- /* scrollers */
- UI_view2d_scrollers_draw(v2d, nullptr);
+ ED_region_panels(C, region);
}
static void spreadsheet_sidebar_init(wmWindowManager *wm, ARegion *region)
@@ -708,11 +687,12 @@ void ED_spacetype_spreadsheet(void)
/* regions: channels */
art = (ARegionType *)MEM_callocN(sizeof(ARegionType), "spreadsheet dataset region");
art->regionid = RGN_TYPE_CHANNELS;
- art->prefsizex = 200 + V2D_SCROLL_WIDTH;
+ art->prefsizex = 150 + V2D_SCROLL_WIDTH;
art->keymapflag = ED_KEYMAP_UI | ED_KEYMAP_VIEW2D;
- art->init = spreadsheet_dataset_region_init;
+ art->init = ED_region_panels_init;
art->draw = spreadsheet_dataset_region_draw;
art->listener = spreadsheet_dataset_region_listener;
+ blender::ed::spreadsheet::spreadsheet_data_set_region_panels_register(*art);
BLI_addhead(&st->regiontypes, art);
BKE_spacetype_register(st);
diff --git a/source/blender/editors/space_spreadsheet/spreadsheet_cell_value.hh b/source/blender/editors/space_spreadsheet/spreadsheet_cell_value.hh
index 97170693cb3..c11b4a2b23d 100644
--- a/source/blender/editors/space_spreadsheet/spreadsheet_cell_value.hh
+++ b/source/blender/editors/space_spreadsheet/spreadsheet_cell_value.hh
@@ -58,6 +58,7 @@ class CellValue {
std::optional<ObjectCellValue> value_object;
std::optional<CollectionCellValue> value_collection;
std::optional<GeometrySetCellValue> value_geometry_set;
+ std::optional<std::string> value_string;
};
} // namespace blender::ed::spreadsheet
diff --git a/source/blender/editors/space_spreadsheet/spreadsheet_data_source_geometry.cc b/source/blender/editors/space_spreadsheet/spreadsheet_data_source_geometry.cc
index c1d345d1861..8cdb462718d 100644
--- a/source/blender/editors/space_spreadsheet/spreadsheet_data_source_geometry.cc
+++ b/source/blender/editors/space_spreadsheet/spreadsheet_data_source_geometry.cc
@@ -20,6 +20,7 @@
#include "BKE_mesh.h"
#include "BKE_mesh_wrapper.h"
#include "BKE_modifier.h"
+#include "BKE_volume.h"
#include "DNA_ID.h"
#include "DNA_mesh_types.h"
@@ -33,6 +34,11 @@
#include "NOD_geometry_nodes_eval_log.hh"
+#include "BLT_translation.h"
+
+#include "RNA_access.h"
+#include "RNA_enum_types.h"
+
#include "FN_field_cpp_type.hh"
#include "bmesh.h"
@@ -72,7 +78,7 @@ static std::optional<eSpreadsheetColumnValueType> cpp_type_to_column_value_type(
void ExtraColumns::foreach_default_column_ids(
FunctionRef<void(const SpreadsheetColumnID &, bool is_extra)> fn) const
{
- for (const auto &item : columns_.items()) {
+ for (const auto item : columns_.items()) {
SpreadsheetColumnID column_id;
column_id.name = (char *)item.key.c_str();
fn(column_id, true);
@@ -112,6 +118,9 @@ std::unique_ptr<ColumnValues> ExtraColumns::get_column_values(
r_cell_value.value_color = *(
const ColorGeometry4f *)value;
break;
+ case SPREADSHEET_VALUE_TYPE_STRING:
+ r_cell_value.value_string = *(const std::string *)value;
+ break;
case SPREADSHEET_VALUE_TYPE_INSTANCES:
break;
}
@@ -159,12 +168,12 @@ std::unique_ptr<ColumnValues> GeometryDataSource::get_column_values(
if (!attribute) {
return {};
}
- const fn::GVArray *varray = scope_.add(std::move(attribute.varray));
+ fn::GVArray varray = std::move(attribute.varray);
if (attribute.domain != domain_) {
return {};
}
- int domain_size = varray->size();
- const CustomDataType type = bke::cpp_type_to_custom_data_type(varray->type());
+ int domain_size = varray.size();
+ const CustomDataType type = bke::cpp_type_to_custom_data_type(varray.type());
switch (type) {
case CD_PROP_FLOAT:
return column_values_from_function(SPREADSHEET_VALUE_TYPE_FLOAT,
@@ -172,7 +181,7 @@ std::unique_ptr<ColumnValues> GeometryDataSource::get_column_values(
domain_size,
[varray](int index, CellValue &r_cell_value) {
float value;
- varray->get(index, &value);
+ varray.get(index, &value);
r_cell_value.value_float = value;
});
case CD_PROP_INT32:
@@ -182,7 +191,7 @@ std::unique_ptr<ColumnValues> GeometryDataSource::get_column_values(
domain_size,
[varray](int index, CellValue &r_cell_value) {
int value;
- varray->get(index, &value);
+ varray.get(index, &value);
r_cell_value.value_int = value;
},
STREQ(column_id.name, "id") ? 5.5f : 0.0f);
@@ -192,7 +201,7 @@ std::unique_ptr<ColumnValues> GeometryDataSource::get_column_values(
domain_size,
[varray](int index, CellValue &r_cell_value) {
bool value;
- varray->get(index, &value);
+ varray.get(index, &value);
r_cell_value.value_bool = value;
});
case CD_PROP_FLOAT2: {
@@ -201,7 +210,7 @@ std::unique_ptr<ColumnValues> GeometryDataSource::get_column_values(
domain_size,
[varray](int index, CellValue &r_cell_value) {
float2 value;
- varray->get(index, &value);
+ varray.get(index, &value);
r_cell_value.value_float2 = value;
});
}
@@ -211,7 +220,7 @@ std::unique_ptr<ColumnValues> GeometryDataSource::get_column_values(
domain_size,
[varray](int index, CellValue &r_cell_value) {
float3 value;
- varray->get(index, &value);
+ varray.get(index, &value);
r_cell_value.value_float3 = value;
});
}
@@ -221,7 +230,7 @@ std::unique_ptr<ColumnValues> GeometryDataSource::get_column_values(
domain_size,
[varray](int index, CellValue &r_cell_value) {
ColorGeometry4f value;
- varray->get(index, &value);
+ varray.get(index, &value);
r_cell_value.value_color = value;
});
}
@@ -487,9 +496,93 @@ int InstancesDataSource::tot_rows() const
return component_->instances_amount();
}
+void VolumeDataSource::foreach_default_column_ids(
+ FunctionRef<void(const SpreadsheetColumnID &, bool is_extra)> fn) const
+{
+ if (component_->is_empty()) {
+ return;
+ }
+
+ for (const char *name : {"Grid Name", "Data Type", "Class"}) {
+ SpreadsheetColumnID column_id{(char *)name};
+ fn(column_id, false);
+ }
+}
+
+std::unique_ptr<ColumnValues> VolumeDataSource::get_column_values(
+ const SpreadsheetColumnID &column_id) const
+{
+ const Volume *volume = component_->get_for_read();
+ if (volume == nullptr) {
+ return {};
+ }
+
+#ifdef WITH_OPENVDB
+ const int size = this->tot_rows();
+ if (STREQ(column_id.name, "Grid Name")) {
+ return column_values_from_function(
+ SPREADSHEET_VALUE_TYPE_STRING,
+ IFACE_("Grid Name"),
+ size,
+ [volume](int index, CellValue &r_cell_value) {
+ const VolumeGrid *volume_grid = BKE_volume_grid_get_for_read(volume, index);
+ r_cell_value.value_string = BKE_volume_grid_name(volume_grid);
+ },
+ 6.0f);
+ }
+ if (STREQ(column_id.name, "Data Type")) {
+ return column_values_from_function(
+ SPREADSHEET_VALUE_TYPE_STRING,
+ IFACE_("Type"),
+ size,
+ [volume](int index, CellValue &r_cell_value) {
+ const VolumeGrid *volume_grid = BKE_volume_grid_get_for_read(volume, index);
+ const VolumeGridType type = BKE_volume_grid_type(volume_grid);
+ const char *name = nullptr;
+ RNA_enum_name_from_value(rna_enum_volume_grid_data_type_items, type, &name);
+ r_cell_value.value_string = IFACE_(name);
+ },
+ 5.0f);
+ }
+ if (STREQ(column_id.name, "Class")) {
+ return column_values_from_function(
+ SPREADSHEET_VALUE_TYPE_STRING,
+ IFACE_("Class"),
+ size,
+ [volume](int index, CellValue &r_cell_value) {
+ const VolumeGrid *volume_grid = BKE_volume_grid_get_for_read(volume, index);
+ openvdb::GridBase::ConstPtr grid = BKE_volume_grid_openvdb_for_read(volume, volume_grid);
+ openvdb::GridClass grid_class = grid->getGridClass();
+ if (grid_class == openvdb::GridClass::GRID_FOG_VOLUME) {
+ r_cell_value.value_string = IFACE_("Fog Volume");
+ }
+ else if (grid_class == openvdb::GridClass::GRID_LEVEL_SET) {
+ r_cell_value.value_string = IFACE_("Level Set");
+ }
+ else {
+ r_cell_value.value_string = IFACE_("Unkown");
+ }
+ },
+ 5.0f);
+ }
+#else
+ UNUSED_VARS(column_id);
+#endif
+
+ return {};
+}
+
+int VolumeDataSource::tot_rows() const
+{
+ const Volume *volume = component_->get_for_read();
+ if (volume == nullptr) {
+ return 0;
+ }
+ return BKE_volume_num_grids(volume);
+}
+
GeometrySet spreadsheet_get_display_geometry_set(const SpaceSpreadsheet *sspreadsheet,
- Object *object_eval,
- const GeometryComponentType used_component_type)
+ Object *object_eval)
{
GeometrySet geometry_set;
if (sspreadsheet->object_eval_state == SPREADSHEET_OBJECT_EVAL_STATE_ORIGINAL) {
@@ -521,7 +614,7 @@ GeometrySet spreadsheet_get_display_geometry_set(const SpaceSpreadsheet *sspread
}
}
else {
- if (used_component_type == GEO_COMPONENT_TYPE_MESH && object_eval->mode == OB_MODE_EDIT) {
+ if (object_eval->mode == OB_MODE_EDIT && object_eval->type == OB_MESH) {
Mesh *mesh = BKE_modifier_get_evaluated_mesh_from_evaluated_object(object_eval, false);
if (mesh == nullptr) {
return geometry_set;
@@ -644,7 +737,7 @@ static void add_fields_as_extra_columns(SpaceSpreadsheet *sspreadsheet,
const AttributeDomain domain = (AttributeDomain)sspreadsheet->attribute_domain;
const int domain_size = component.attribute_domain_size(domain);
- for (const auto &item : fields_to_show.items()) {
+ for (const auto item : fields_to_show.items()) {
StringRef name = item.key;
const GField &field = item.value;
@@ -668,8 +761,7 @@ std::unique_ptr<DataSource> data_source_from_geometry(const bContext *C, Object
SpaceSpreadsheet *sspreadsheet = CTX_wm_space_spreadsheet(C);
const AttributeDomain domain = (AttributeDomain)sspreadsheet->attribute_domain;
const GeometryComponentType component_type = get_display_component_type(C, object_eval);
- GeometrySet geometry_set = spreadsheet_get_display_geometry_set(
- sspreadsheet, object_eval, component_type);
+ GeometrySet geometry_set = spreadsheet_get_display_geometry_set(sspreadsheet, object_eval);
if (!geometry_set.has(component_type)) {
return {};
@@ -682,6 +774,9 @@ std::unique_ptr<DataSource> data_source_from_geometry(const bContext *C, Object
if (component_type == GEO_COMPONENT_TYPE_INSTANCES) {
return std::make_unique<InstancesDataSource>(geometry_set, std::move(extra_columns));
}
+ if (component_type == GEO_COMPONENT_TYPE_VOLUME) {
+ return std::make_unique<VolumeDataSource>(geometry_set);
+ }
return std::make_unique<GeometryDataSource>(
object_eval, geometry_set, component_type, domain, std::move(extra_columns));
}
diff --git a/source/blender/editors/space_spreadsheet/spreadsheet_data_source_geometry.hh b/source/blender/editors/space_spreadsheet/spreadsheet_data_source_geometry.hh
index 6c88a94f585..a4114dd1f6a 100644
--- a/source/blender/editors/space_spreadsheet/spreadsheet_data_source_geometry.hh
+++ b/source/blender/editors/space_spreadsheet/spreadsheet_data_source_geometry.hh
@@ -116,6 +116,26 @@ class InstancesDataSource : public DataSource {
int tot_rows() const override;
};
+class VolumeDataSource : public DataSource {
+ const GeometrySet geometry_set_;
+ const VolumeComponent *component_;
+
+ public:
+ VolumeDataSource(GeometrySet geometry_set)
+ : geometry_set_(std::move(geometry_set)),
+ component_(geometry_set_.get_component_for_read<VolumeComponent>())
+ {
+ }
+
+ void foreach_default_column_ids(
+ FunctionRef<void(const SpreadsheetColumnID &, bool is_extra)> fn) const override;
+
+ std::unique_ptr<ColumnValues> get_column_values(
+ const SpreadsheetColumnID &column_id) const override;
+
+ int tot_rows() const override;
+};
+
std::unique_ptr<DataSource> data_source_from_geometry(const bContext *C, Object *object_eval);
} // namespace blender::ed::spreadsheet
diff --git a/source/blender/editors/space_spreadsheet/spreadsheet_dataset_draw.cc b/source/blender/editors/space_spreadsheet/spreadsheet_dataset_draw.cc
index 4cf6d14cbda..2a81b56d129 100644
--- a/source/blender/editors/space_spreadsheet/spreadsheet_dataset_draw.cc
+++ b/source/blender/editors/space_spreadsheet/spreadsheet_dataset_draw.cc
@@ -14,275 +14,226 @@
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
-#include <array>
-
#include "DNA_space_types.h"
#include "DNA_windowmanager_types.h"
#include "BKE_context.h"
-
-#include "BLF_api.h"
-
-#include "BLI_rect.h"
+#include "BKE_volume.h"
#include "RNA_access.h"
#include "UI_interface.h"
-#include "UI_view2d.h"
+#include "UI_interface.hh"
+#include "UI_tree_view.hh"
#include "WM_types.h"
+#include "BLT_translation.h"
+
#include "spreadsheet_dataset_draw.hh"
#include "spreadsheet_draw.hh"
#include "spreadsheet_intern.hh"
-static int is_component_row_selected(struct uiBut *but, const void *arg)
-{
- SpaceSpreadsheet *sspreadsheet = (SpaceSpreadsheet *)arg;
+namespace blender::ed::spreadsheet {
- GeometryComponentType component = (GeometryComponentType)UI_but_datasetrow_component_get(but);
- AttributeDomain domain = (AttributeDomain)UI_but_datasetrow_domain_get(but);
+class GeometryDataSetTreeView;
- const bool is_component_selected = (GeometryComponentType)
- sspreadsheet->geometry_component_type == component;
- const bool is_domain_selected = (AttributeDomain)sspreadsheet->attribute_domain == domain;
- bool is_selected = is_component_selected && is_domain_selected;
+class GeometryDataSetTreeViewItem : public ui::AbstractTreeViewItem {
+ GeometryComponentType component_type_;
+ std::optional<AttributeDomain> domain_;
+ BIFIconID icon_;
- if (component == GEO_COMPONENT_TYPE_INSTANCES) {
- is_selected = is_component_selected;
- }
+ public:
+ GeometryDataSetTreeViewItem(GeometryComponentType component_type,
+ StringRef label,
+ BIFIconID icon);
+ GeometryDataSetTreeViewItem(GeometryComponentType component_type,
+ AttributeDomain domain,
+ StringRef label,
+ BIFIconID icon);
- return is_selected;
-}
+ void on_activate() override;
-namespace blender::ed::spreadsheet {
+ void build_row(uiLayout &row) override;
-/* -------------------------------------------------------------------- */
-/* Draw Context */
+ protected:
+ std::optional<bool> should_be_active() const override;
+ bool supports_collapsing() const override;
-class DatasetDrawContext {
- std::array<int, 2> mval_;
+ private:
+ GeometryDataSetTreeView &get_tree() const;
+ std::optional<int> count() const;
+};
- public:
- const SpaceSpreadsheet *sspreadsheet;
- Object *object_eval;
- /* Current geometry set, changes per component. */
- GeometrySet current_geometry_set;
+class GeometryDataSetTreeView : public ui::AbstractTreeView {
+ GeometrySet geometry_set_;
+ const bContext &C_;
+ SpaceSpreadsheet &sspreadsheet_;
+ bScreen &screen_;
- DatasetDrawContext(const bContext *C);
+ friend class GeometryDataSetTreeViewItem;
- GeometrySet geometry_set_from_component(GeometryComponentType component);
- const std::array<int, 2> &cursor_mval() const;
-};
-
-DatasetDrawContext::DatasetDrawContext(const bContext *C)
- : sspreadsheet(CTX_wm_space_spreadsheet(C)),
- object_eval(spreadsheet_get_object_eval(sspreadsheet, CTX_data_depsgraph_pointer(C)))
-{
- const wmWindow *win = CTX_wm_window(C);
- const ARegion *region = CTX_wm_region(C);
- mval_ = {win->eventstate->xy[0] - region->winrct.xmin,
- win->eventstate->xy[1] - region->winrct.ymin};
-}
+ public:
+ GeometryDataSetTreeView(GeometrySet geometry_set, const bContext &C)
+ : geometry_set_(std::move(geometry_set)),
+ C_(C),
+ sspreadsheet_(*CTX_wm_space_spreadsheet(&C)),
+ screen_(*CTX_wm_screen(&C))
+ {
+ }
-GeometrySet DatasetDrawContext::geometry_set_from_component(GeometryComponentType component)
-{
- return spreadsheet_get_display_geometry_set(sspreadsheet, object_eval, component);
-}
+ void build_tree() override
+ {
+ GeometryDataSetTreeViewItem &mesh = this->add_tree_item<GeometryDataSetTreeViewItem>(
+ GEO_COMPONENT_TYPE_MESH, IFACE_("Mesh"), ICON_MESH_DATA);
+ mesh.add_tree_item<GeometryDataSetTreeViewItem>(
+ GEO_COMPONENT_TYPE_MESH, ATTR_DOMAIN_POINT, IFACE_("Vertex"), ICON_VERTEXSEL);
+ mesh.add_tree_item<GeometryDataSetTreeViewItem>(
+ GEO_COMPONENT_TYPE_MESH, ATTR_DOMAIN_EDGE, IFACE_("Edge"), ICON_EDGESEL);
+ mesh.add_tree_item<GeometryDataSetTreeViewItem>(
+ GEO_COMPONENT_TYPE_MESH, ATTR_DOMAIN_FACE, IFACE_("Face"), ICON_FACESEL);
+ mesh.add_tree_item<GeometryDataSetTreeViewItem>(
+ GEO_COMPONENT_TYPE_MESH, ATTR_DOMAIN_CORNER, IFACE_("Face Corner"), ICON_NODE_CORNER);
+
+ GeometryDataSetTreeViewItem &curve = this->add_tree_item<GeometryDataSetTreeViewItem>(
+ GEO_COMPONENT_TYPE_CURVE, IFACE_("Curve"), ICON_CURVE_DATA);
+ curve.add_tree_item<GeometryDataSetTreeViewItem>(GEO_COMPONENT_TYPE_CURVE,
+ ATTR_DOMAIN_POINT,
+ IFACE_("Control Point"),
+ ICON_CURVE_BEZCIRCLE);
+ curve.add_tree_item<GeometryDataSetTreeViewItem>(
+ GEO_COMPONENT_TYPE_CURVE, ATTR_DOMAIN_CURVE, IFACE_("Spline"), ICON_CURVE_PATH);
+
+ GeometryDataSetTreeViewItem &pointcloud = this->add_tree_item<GeometryDataSetTreeViewItem>(
+ GEO_COMPONENT_TYPE_POINT_CLOUD, IFACE_("Point Cloud"), ICON_POINTCLOUD_DATA);
+ pointcloud.add_tree_item<GeometryDataSetTreeViewItem>(
+ GEO_COMPONENT_TYPE_POINT_CLOUD, ATTR_DOMAIN_POINT, IFACE_("Point"), ICON_PARTICLE_POINT);
+
+ this->add_tree_item<GeometryDataSetTreeViewItem>(
+ GEO_COMPONENT_TYPE_VOLUME, IFACE_("Volume Grids"), ICON_VOLUME_DATA);
+
+ this->add_tree_item<GeometryDataSetTreeViewItem>(
+ GEO_COMPONENT_TYPE_INSTANCES, ATTR_DOMAIN_INSTANCE, IFACE_("Instances"), ICON_EMPTY_AXIS);
+ }
+};
-const std::array<int, 2> &DatasetDrawContext::cursor_mval() const
+GeometryDataSetTreeViewItem::GeometryDataSetTreeViewItem(GeometryComponentType component_type,
+ StringRef label,
+ BIFIconID icon)
+ : component_type_(component_type), domain_(std::nullopt), icon_(icon)
{
- return mval_;
+ label_ = label;
+ this->set_collapsed(false);
}
-
-/* -------------------------------------------------------------------- */
-/* Drawer */
-
-DatasetRegionDrawer::DatasetRegionDrawer(const ARegion *region,
- uiBlock &block,
- DatasetDrawContext &draw_context)
- : row_height(UI_UNIT_Y),
- xmin(region->v2d.cur.xmin),
- xmax(region->v2d.cur.xmax),
- block(block),
- v2d(region->v2d),
- draw_context(draw_context)
+GeometryDataSetTreeViewItem::GeometryDataSetTreeViewItem(GeometryComponentType component_type,
+ AttributeDomain domain,
+ StringRef label,
+ BIFIconID icon)
+ : component_type_(component_type), domain_(domain), icon_(icon)
{
+ label_ = label;
}
-void DatasetRegionDrawer::draw_hierarchy(const DatasetLayoutHierarchy &layout)
+void GeometryDataSetTreeViewItem::on_activate()
{
- for (const DatasetComponentLayoutInfo &component : layout.components) {
- draw_context.current_geometry_set = draw_context.geometry_set_from_component(component.type);
-
- draw_component_row(component);
-
- /* Iterate attribute domains, skip unset ones (storage has to be in a enum-based, fixed size
- * array so uses optionals to support skipping enum values that shouldn't be displayed for a
- * component). */
- for (const auto &optional_domain : component.attr_domains) {
- if (!optional_domain) {
- continue;
- }
-
- const DatasetAttrDomainLayoutInfo &domain_info = *optional_domain;
- draw_attribute_domain_row(component, domain_info);
- }
+ GeometryDataSetTreeView &tree_view = this->get_tree();
+ bContext &C = const_cast<bContext &>(tree_view.C_);
+ SpaceSpreadsheet &sspreadsheet = tree_view.sspreadsheet_;
+ tree_view.sspreadsheet_.geometry_component_type = component_type_;
+ if (domain_) {
+ tree_view.sspreadsheet_.attribute_domain = *domain_;
}
+ PointerRNA ptr;
+ RNA_pointer_create(&tree_view.screen_.id, &RNA_SpaceSpreadsheet, &sspreadsheet, &ptr);
+ RNA_property_update(&C, &ptr, RNA_struct_find_property(&ptr, "attribute_domain"));
+ RNA_property_update(&C, &ptr, RNA_struct_find_property(&ptr, "geometry_component_type"));
}
-static int element_count_from_instances(const GeometrySet &geometry_set)
+void GeometryDataSetTreeViewItem::build_row(uiLayout &row)
{
- if (geometry_set.has_instances()) {
- const InstancesComponent *instances_component =
- geometry_set.get_component_for_read<InstancesComponent>();
- return instances_component->instances_amount();
+ uiItemL(&row, label_.c_str(), icon_);
+
+ if (const std::optional<int> count = this->count()) {
+ /* Using the tree row button instead of a separate right aligned button gives padding
+ * to the right side of the number, which it didn't have with the button. */
+ char element_count[7];
+ BLI_str_format_attribute_domain_size(element_count, *count);
+ UI_but_hint_drawstr_set((uiBut *)this->tree_row_button(), element_count);
}
- return 0;
}
-static int element_count_from_component_domain(const GeometrySet &geometry_set,
- GeometryComponentType component,
- AttributeDomain domain)
+std::optional<bool> GeometryDataSetTreeViewItem::should_be_active() const
{
- if (geometry_set.has_mesh() && component == GEO_COMPONENT_TYPE_MESH) {
- const MeshComponent *mesh_component = geometry_set.get_component_for_read<MeshComponent>();
- return mesh_component->attribute_domain_size(domain);
- }
+ GeometryDataSetTreeView &tree_view = this->get_tree();
+ SpaceSpreadsheet &sspreadsheet = tree_view.sspreadsheet_;
- if (geometry_set.has_pointcloud() && component == GEO_COMPONENT_TYPE_POINT_CLOUD) {
- const PointCloudComponent *point_cloud_component =
- geometry_set.get_component_for_read<PointCloudComponent>();
- return point_cloud_component->attribute_domain_size(domain);
+ if (component_type_ == GEO_COMPONENT_TYPE_VOLUME) {
+ return sspreadsheet.geometry_component_type == component_type_;
}
- if (geometry_set.has_volume() && component == GEO_COMPONENT_TYPE_VOLUME) {
- const VolumeComponent *volume_component =
- geometry_set.get_component_for_read<VolumeComponent>();
- return volume_component->attribute_domain_size(domain);
+ if (!domain_) {
+ return false;
}
- if (geometry_set.has_curve() && component == GEO_COMPONENT_TYPE_CURVE) {
- const CurveComponent *curve_component = geometry_set.get_component_for_read<CurveComponent>();
- return curve_component->attribute_domain_size(domain);
- }
-
- return 0;
+ return sspreadsheet.geometry_component_type == component_type_ &&
+ sspreadsheet.attribute_domain == *domain_;
}
-void DatasetRegionDrawer::draw_dataset_row(const int indentation,
- const GeometryComponentType component,
- const std::optional<AttributeDomain> domain,
- BIFIconID icon,
- const char *label,
- const bool is_active)
+bool GeometryDataSetTreeViewItem::supports_collapsing() const
{
+ return false;
+}
- const float row_height = UI_UNIT_Y;
- const float padding_x = UI_UNIT_X * 0.25f;
-
- const rctf rect = {float(xmin) + padding_x,
- float(xmax) - V2D_SCROLL_HANDLE_WIDTH,
- ymin_offset - row_height,
- ymin_offset};
-
- char element_count[7];
- if (component == GEO_COMPONENT_TYPE_INSTANCES) {
- BLI_str_format_attribute_domain_size(
- element_count, element_count_from_instances(draw_context.current_geometry_set));
- }
- else {
- BLI_str_format_attribute_domain_size(
- element_count,
- domain ? element_count_from_component_domain(
- draw_context.current_geometry_set, component, *domain) :
- 0);
- }
+GeometryDataSetTreeView &GeometryDataSetTreeViewItem::get_tree() const
+{
+ return static_cast<GeometryDataSetTreeView &>(this->get_tree_view());
+}
- std::string label_and_element_count = label;
- label_and_element_count += UI_SEP_CHAR;
- label_and_element_count += element_count;
-
- uiBut *bt = uiDefIconTextButO(&block,
- UI_BTYPE_DATASETROW,
- "SPREADSHEET_OT_change_spreadsheet_data_source",
- 0,
- icon,
- label,
- rect.xmin,
- rect.ymin,
- BLI_rctf_size_x(&rect),
- BLI_rctf_size_y(&rect),
- nullptr);
-
- UI_but_datasetrow_indentation_set(bt, indentation);
-
- if (is_active) {
- UI_but_hint_drawstr_set(bt, element_count);
- UI_but_datasetrow_component_set(bt, component);
- if (domain) {
- UI_but_datasetrow_domain_set(bt, *domain);
- }
- UI_but_func_pushed_state_set(bt, &is_component_row_selected, draw_context.sspreadsheet);
+std::optional<int> GeometryDataSetTreeViewItem::count() const
+{
+ GeometryDataSetTreeView &tree_view = this->get_tree();
+ GeometrySet &geometry = tree_view.geometry_set_;
- PointerRNA *but_ptr = UI_but_operator_ptr_get((uiBut *)bt);
- RNA_int_set(but_ptr, "component_type", component);
- if (domain) {
- RNA_int_set(but_ptr, "attribute_domain_type", *domain);
+ /* Special case for volumes since there is no grid domain. */
+ if (component_type_ == GEO_COMPONENT_TYPE_VOLUME) {
+ if (const Volume *volume = geometry.get_volume_for_read()) {
+ return BKE_volume_num_grids(volume);
}
+ return 0;
}
- ymin_offset -= row_height;
-}
-
-void DatasetRegionDrawer::draw_component_row(const DatasetComponentLayoutInfo &component_info)
-{
- if (component_info.type == GEO_COMPONENT_TYPE_INSTANCES) {
- draw_dataset_row(
- 0, component_info.type, std::nullopt, component_info.icon, component_info.label, true);
+ if (!domain_) {
+ return std::nullopt;
}
- else {
- draw_dataset_row(
- 0, component_info.type, std::nullopt, component_info.icon, component_info.label, false);
+
+ if (const GeometryComponent *component = geometry.get_component_for_read(component_type_)) {
+ return component->attribute_domain_size(*domain_);
}
-}
-void DatasetRegionDrawer::draw_attribute_domain_row(
- const DatasetComponentLayoutInfo &component_info,
- const DatasetAttrDomainLayoutInfo &domain_info)
-{
- draw_dataset_row(
- 1, component_info.type, domain_info.type, domain_info.icon, domain_info.label, true);
+ return 0;
}
-/* -------------------------------------------------------------------- */
-/* Drawer */
-
-void draw_dataset_in_region(const bContext *C, ARegion *region)
+void spreadsheet_data_set_panel_draw(const bContext *C, Panel *panel)
{
- DatasetDrawContext draw_context{C};
- if (!draw_context.object_eval) {
- /* No object means nothing to display. Keep the region empty. */
+ const SpaceSpreadsheet *sspreadsheet = CTX_wm_space_spreadsheet(C);
+ Object *object = spreadsheet_get_object_eval(sspreadsheet, CTX_data_depsgraph_pointer(C));
+ if (!object) {
return;
}
+ uiLayout *layout = panel->layout;
- uiBlock *block = UI_block_begin(C, region, __func__, UI_EMBOSS);
-
- DatasetRegionDrawer drawer{region, *block, draw_context};
+ uiBlock *block = uiLayoutGetBlock(layout);
- /* Start with an offset to align buttons to spreadsheet rows. Use spreadsheet drawing info for
- * that. */
- drawer.ymin_offset = -SpreadsheetDrawer().top_row_height + drawer.row_height;
+ UI_block_layout_set_current(block, layout);
- const DatasetLayoutHierarchy hierarchy = dataset_layout_hierarchy();
- drawer.draw_hierarchy(hierarchy);
-#ifndef NDEBUG
- dataset_layout_hierarchy_sanity_check(hierarchy);
-#endif
+ ui::AbstractTreeView *tree_view = UI_block_add_view(
+ *block,
+ "Data Set Tree View",
+ std::make_unique<GeometryDataSetTreeView>(
+ spreadsheet_get_display_geometry_set(sspreadsheet, object), *C));
- UI_block_end(C, block);
- UI_view2d_totRect_set(&region->v2d, region->winx, abs(drawer.ymin_offset));
- UI_block_draw(C, block);
+ ui::TreeViewBuilder builder(*block);
+ builder.build_tree_view(*tree_view);
}
} // namespace blender::ed::spreadsheet
diff --git a/source/blender/editors/space_spreadsheet/spreadsheet_dataset_draw.hh b/source/blender/editors/space_spreadsheet/spreadsheet_dataset_draw.hh
index 19906d73e7f..4a604533f11 100644
--- a/source/blender/editors/space_spreadsheet/spreadsheet_dataset_draw.hh
+++ b/source/blender/editors/space_spreadsheet/spreadsheet_dataset_draw.hh
@@ -16,49 +16,11 @@
#pragma once
-#include <array>
-
-#include "BKE_geometry_set.hh"
-#include "UI_interface.h"
-#include "spreadsheet_dataset_layout.hh"
-
-struct ARegion;
-struct View2D;
+struct Panel;
struct bContext;
-struct uiBlock;
namespace blender::ed::spreadsheet {
-class DatasetDrawContext;
-
-class DatasetRegionDrawer {
- public:
- const int row_height;
- float ymin_offset = 0;
-
- int xmin;
- int xmax;
- uiBlock &block;
- const View2D &v2d;
- DatasetDrawContext &draw_context;
-
- DatasetRegionDrawer(const ARegion *region, uiBlock &block, DatasetDrawContext &draw_context);
-
- void draw_hierarchy(const DatasetLayoutHierarchy &layout);
-
- void draw_attribute_domain_row(const DatasetComponentLayoutInfo &component,
- const DatasetAttrDomainLayoutInfo &domain_info);
- void draw_component_row(const DatasetComponentLayoutInfo &component_info);
-
- private:
- void draw_dataset_row(const int indentation,
- const GeometryComponentType component,
- const std::optional<AttributeDomain> domain,
- const BIFIconID icon,
- const char *label,
- const bool is_active);
-};
-
-void draw_dataset_in_region(const bContext *C, ARegion *region);
+void spreadsheet_data_set_panel_draw(const bContext *C, Panel *panel);
} // namespace blender::ed::spreadsheet
diff --git a/source/blender/editors/space_spreadsheet/spreadsheet_dataset_layout.cc b/source/blender/editors/space_spreadsheet/spreadsheet_dataset_layout.cc
deleted file mode 100644
index abbad8c7088..00000000000
--- a/source/blender/editors/space_spreadsheet/spreadsheet_dataset_layout.cc
+++ /dev/null
@@ -1,112 +0,0 @@
-/*
- * 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 <optional>
-
-#include "BLI_span.hh"
-
-#include "BLT_translation.h"
-
-#include "spreadsheet_dataset_layout.hh"
-
-namespace blender::ed::spreadsheet {
-
-#define ATTR_INFO(type, label, icon) \
- std::optional<DatasetAttrDomainLayoutInfo> \
- { \
- std::in_place, type, label, icon \
- }
-#define ATTR_INFO_NONE(type) \
- { \
- std::nullopt \
- }
-
-/**
- * Definition for the component->attribute-domain hierarchy.
- * Constructed at compile time.
- *
- * \warning Order of attribute-domains matters! It __must__ match the #AttributeDomain
- * definition and fill gaps with unset optionals (i.e. `std::nullopt`). Would be nice to use
- * array designators for this (which C++ doesn't support).
- */
-constexpr DatasetComponentLayoutInfo DATASET_layout_hierarchy[] = {
- {
- GEO_COMPONENT_TYPE_MESH,
- N_("Mesh"),
- ICON_MESH_DATA,
- {
- ATTR_INFO(ATTR_DOMAIN_POINT, N_("Vertex"), ICON_VERTEXSEL),
- ATTR_INFO(ATTR_DOMAIN_EDGE, N_("Edge"), ICON_EDGESEL),
- ATTR_INFO(ATTR_DOMAIN_FACE, N_("Face"), ICON_FACESEL),
- ATTR_INFO(ATTR_DOMAIN_CORNER, N_("Face Corner"), ICON_NODE_CORNER),
- },
- },
- {
- GEO_COMPONENT_TYPE_CURVE,
- N_("Curves"),
- ICON_CURVE_DATA,
- {
- ATTR_INFO(ATTR_DOMAIN_POINT, N_("Control Point"), ICON_CURVE_BEZCIRCLE),
- ATTR_INFO_NONE(ATTR_DOMAIN_EDGE),
- ATTR_INFO_NONE(ATTR_DOMAIN_CORNER),
- ATTR_INFO_NONE(ATTR_DOMAIN_FACE),
- ATTR_INFO(ATTR_DOMAIN_CURVE, N_("Spline"), ICON_CURVE_PATH),
- },
- },
- {
- GEO_COMPONENT_TYPE_POINT_CLOUD,
- N_("Point Cloud"),
- ICON_POINTCLOUD_DATA,
- {
- ATTR_INFO(ATTR_DOMAIN_POINT, N_("Point"), ICON_PARTICLE_POINT),
- },
- },
- {
- GEO_COMPONENT_TYPE_INSTANCES,
- N_("Instances"),
- ICON_EMPTY_AXIS,
- {},
- },
-};
-
-#undef ATTR_INFO
-#undef ATTR_INFO_LABEL
-
-DatasetLayoutHierarchy dataset_layout_hierarchy()
-{
- return DatasetLayoutHierarchy{
- Span{DATASET_layout_hierarchy, ARRAY_SIZE(DATASET_layout_hierarchy)}};
-}
-
-#ifndef NDEBUG
-/**
- * Debug-only sanity check for correct attribute domain initialization (order/indices must
- * match AttributeDomain). This doesn't check for all possible missuses, but should catch the most
- * likely mistakes.
- */
-void dataset_layout_hierarchy_sanity_check(const DatasetLayoutHierarchy &hierarchy)
-{
- for (const DatasetComponentLayoutInfo &component : hierarchy.components) {
- for (uint i = 0; i < component.attr_domains.size(); i++) {
- if (component.attr_domains[i]) {
- BLI_assert(component.attr_domains[i]->type == static_cast<AttributeDomain>(i));
- }
- }
- }
-}
-#endif
-
-} // namespace blender::ed::spreadsheet
diff --git a/source/blender/editors/space_spreadsheet/spreadsheet_dataset_layout.hh b/source/blender/editors/space_spreadsheet/spreadsheet_dataset_layout.hh
deleted file mode 100644
index d463739a0fa..00000000000
--- a/source/blender/editors/space_spreadsheet/spreadsheet_dataset_layout.hh
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- * 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.
- */
-
-#pragma once
-
-#include <array>
-#include <optional>
-
-/* Enum definitions... */
-#include "BKE_attribute.h"
-#include "BKE_geometry_set.h"
-
-#include "BLI_span.hh"
-
-/* More enum definitions... */
-#include "UI_resources.h"
-
-#pragma once
-
-namespace blender::ed::spreadsheet {
-
-struct DatasetAttrDomainLayoutInfo {
- AttributeDomain type;
- const char *label;
- BIFIconID icon;
-
- constexpr DatasetAttrDomainLayoutInfo(AttributeDomain type, const char *label, BIFIconID icon)
- : type(type), label(label), icon(icon)
- {
- }
-};
-
-struct DatasetComponentLayoutInfo {
- GeometryComponentType type;
- const char *label;
- BIFIconID icon;
- /** Array of attribute-domains. Has to be fixed size based on #AttributeDomain enum, but not all
- * values need displaying for all parent components. Hence the optional use. */
- using AttrDomainArray = std::array<std::optional<DatasetAttrDomainLayoutInfo>, ATTR_DOMAIN_NUM>;
- const AttrDomainArray attr_domains;
-};
-
-struct DatasetLayoutHierarchy {
- /** The components for display (with layout info like icon and label). Each component stores
- * the attribute domains it wants to display (also with layout info like icon and label). */
- const Span<DatasetComponentLayoutInfo> components;
-};
-
-DatasetLayoutHierarchy dataset_layout_hierarchy();
-
-#ifndef NDEBUG
-void dataset_layout_hierarchy_sanity_check(const DatasetLayoutHierarchy &hierarchy);
-#endif
-
-} // namespace blender::ed::spreadsheet
diff --git a/source/blender/editors/space_spreadsheet/spreadsheet_intern.hh b/source/blender/editors/space_spreadsheet/spreadsheet_intern.hh
index 8b050c2e69b..e62835d5792 100644
--- a/source/blender/editors/space_spreadsheet/spreadsheet_intern.hh
+++ b/source/blender/editors/space_spreadsheet/spreadsheet_intern.hh
@@ -37,6 +37,7 @@ struct SpaceSpreadsheet_Runtime {
};
struct bContext;
+struct ARegionType;
void spreadsheet_operatortypes(void);
void spreadsheet_update_context_path(const bContext *C);
@@ -45,6 +46,8 @@ Object *spreadsheet_get_object_eval(const SpaceSpreadsheet *sspreadsheet,
namespace blender::ed::spreadsheet {
GeometrySet spreadsheet_get_display_geometry_set(const SpaceSpreadsheet *sspreadsheet,
- Object *object_eval,
- const GeometryComponentType used_component_type);
-}
+ Object *object_eval);
+
+void spreadsheet_data_set_region_panels_register(ARegionType &region_type);
+
+} // namespace blender::ed::spreadsheet
diff --git a/source/blender/editors/space_spreadsheet/spreadsheet_layout.cc b/source/blender/editors/space_spreadsheet/spreadsheet_layout.cc
index 355899be279..202523c0e64 100644
--- a/source/blender/editors/space_spreadsheet/spreadsheet_layout.cc
+++ b/source/blender/editors/space_spreadsheet/spreadsheet_layout.cc
@@ -228,6 +228,23 @@ class SpreadsheetLayoutDrawer : public SpreadsheetDrawer {
0,
nullptr);
}
+ else if (cell_value.value_string.has_value()) {
+ uiDefIconTextBut(params.block,
+ UI_BTYPE_LABEL,
+ 0,
+ ICON_NONE,
+ cell_value.value_string->c_str(),
+ params.xmin,
+ params.ymin,
+ params.width,
+ params.height,
+ nullptr,
+ 0,
+ 0,
+ 0,
+ 0,
+ nullptr);
+ }
}
void draw_float_vector(const CellDrawParams &params, const Span<float> values) const
diff --git a/source/blender/editors/space_spreadsheet/spreadsheet_panels.cc b/source/blender/editors/space_spreadsheet/spreadsheet_panels.cc
new file mode 100644
index 00000000000..8f923ea4a63
--- /dev/null
+++ b/source/blender/editors/space_spreadsheet/spreadsheet_panels.cc
@@ -0,0 +1,37 @@
+/*
+ * 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 "BKE_screen.h"
+
+#include "BLT_translation.h"
+
+#include "spreadsheet_dataset_draw.hh"
+#include "spreadsheet_intern.hh"
+
+namespace blender::ed::spreadsheet {
+
+void spreadsheet_data_set_region_panels_register(ARegionType &region_type)
+{
+ PanelType *panel_type = (PanelType *)MEM_callocN(sizeof(PanelType), __func__);
+ strcpy(panel_type->idname, "SPREADSHEET_PT_data_set");
+ strcpy(panel_type->label, N_("Data Set"));
+ strcpy(panel_type->translation_context, BLT_I18NCONTEXT_DEFAULT_BPYRNA);
+ panel_type->flag = PANEL_TYPE_NO_HEADER;
+ panel_type->draw = spreadsheet_data_set_panel_draw;
+ BLI_addtail(&region_type.paneltypes, panel_type);
+}
+
+} // namespace blender::ed::spreadsheet \ No newline at end of file
diff --git a/source/blender/editors/space_spreadsheet/spreadsheet_row_filter_ui.cc b/source/blender/editors/space_spreadsheet/spreadsheet_row_filter_ui.cc
index d56049990b4..a07abac4474 100644
--- a/source/blender/editors/space_spreadsheet/spreadsheet_row_filter_ui.cc
+++ b/source/blender/editors/space_spreadsheet/spreadsheet_row_filter_ui.cc
@@ -105,12 +105,15 @@ static std::string value_string(const SpreadsheetRowFilter &row_filter,
return row_filter.value_string;
}
return "";
- case SPREADSHEET_VALUE_TYPE_COLOR:
+ case SPREADSHEET_VALUE_TYPE_COLOR: {
std::ostringstream result;
result.precision(3);
result << std::fixed << "(" << row_filter.value_color[0] << ", " << row_filter.value_color[1]
<< ", " << row_filter.value_color[2] << ", " << row_filter.value_color[3] << ")";
return result.str();
+ }
+ case SPREADSHEET_VALUE_TYPE_STRING:
+ return row_filter.value_string;
}
BLI_assert_unreachable();
return "";
@@ -234,6 +237,8 @@ static void spreadsheet_filter_panel_draw(const bContext *C, Panel *panel)
uiItemR(layout, filter_ptr, "value_color", 0, IFACE_("Value"), ICON_NONE);
uiItemR(layout, filter_ptr, "threshold", 0, nullptr, ICON_NONE);
break;
+ case SPREADSHEET_VALUE_TYPE_STRING:
+ break;
}
}
diff --git a/source/blender/editors/space_text/text_draw.c b/source/blender/editors/space_text/text_draw.c
index b541b65d676..f8d16e396d4 100644
--- a/source/blender/editors/space_text/text_draw.c
+++ b/source/blender/editors/space_text/text_draw.c
@@ -70,7 +70,7 @@ static void text_draw_context_init(const SpaceText *st, TextDrawContext *tdc)
static void text_font_begin(const TextDrawContext *tdc)
{
- BLF_size(tdc->font_id, tdc->lheight_px, 72);
+ BLF_size(tdc->font_id, (float)tdc->lheight_px, 72);
}
static void text_font_end(const TextDrawContext *UNUSED(tdc))
diff --git a/source/blender/editors/space_text/text_ops.c b/source/blender/editors/space_text/text_ops.c
index 458a1be0308..3c0ffa29bbd 100644
--- a/source/blender/editors/space_text/text_ops.c
+++ b/source/blender/editors/space_text/text_ops.c
@@ -86,6 +86,30 @@ static void test_line_start(char c, bool *r_last_state)
}
/**
+ * This function receives a character and returns its closing pair if it exists.
+ * \param character: Character to find the closing pair.
+ * \return The closing pair of the character if it exists.
+ */
+static char text_closing_character_pair_get(const char character)
+{
+
+ switch (character) {
+ case '(':
+ return ')';
+ case '[':
+ return ']';
+ case '{':
+ return '}';
+ case '"':
+ return '"';
+ case '\'':
+ return '\'';
+ default:
+ return 0;
+ }
+}
+
+/**
* This function converts the indentation tabs from a buffer to spaces.
* \param in_buf: A pointer to a cstring.
* \param tab_size: The size, in spaces, of the tab character.
@@ -2403,7 +2427,17 @@ static int text_delete_exec(bContext *C, wmOperator *op)
}
}
}
-
+ if (U.text_flag & USER_TEXT_EDIT_AUTO_CLOSE) {
+ const char *curr = text->curl->line + text->curc;
+ if (*curr != '\0') {
+ const char *prev = BLI_str_find_prev_char_utf8(curr, text->curl->line);
+ if ((curr != prev) && /* When back-spacing from the start of the line. */
+ (*curr == text_closing_character_pair_get(*prev))) {
+ txt_move_right(text, false);
+ txt_backspace_char(text);
+ }
+ }
+ }
txt_backspace_char(text);
}
else if (type == DEL_NEXT_WORD) {
@@ -3443,6 +3477,12 @@ static int text_insert_exec(bContext *C, wmOperator *op)
while (str[i]) {
code = BLI_str_utf8_as_unicode_step(str, str_len, &i);
done |= txt_add_char(text, code);
+ if (U.text_flag & USER_TEXT_EDIT_AUTO_CLOSE) {
+ if (text_closing_character_pair_get(code)) {
+ done |= txt_add_char(text, text_closing_character_pair_get(code));
+ txt_move_left(text, false);
+ }
+ }
}
}
diff --git a/source/blender/editors/space_view3d/drawobject.c b/source/blender/editors/space_view3d/drawobject.c
index 6b9da431510..48f39f835c5 100644
--- a/source/blender/editors/space_view3d/drawobject.c
+++ b/source/blender/editors/space_view3d/drawobject.c
@@ -48,58 +48,6 @@
#include "view3d_intern.h" /* bad level include */
-/* OpenGL Circle Drawing - Tables for Optimized Drawing Speed */
-/* 32 values of sin function (still same result!) */
-#define CIRCLE_RESOL 32
-
-static const float sinval[CIRCLE_RESOL] = {
- 0.00000000, 0.20129852, 0.39435585, 0.57126821, 0.72479278, 0.84864425, 0.93775213,
- 0.98846832, 0.99871650, 0.96807711, 0.89780453, 0.79077573, 0.65137248, 0.48530196,
- 0.29936312, 0.10116832, -0.10116832, -0.29936312, -0.48530196, -0.65137248, -0.79077573,
- -0.89780453, -0.96807711, -0.99871650, -0.98846832, -0.93775213, -0.84864425, -0.72479278,
- -0.57126821, -0.39435585, -0.20129852, 0.00000000,
-};
-
-/* 32 values of cos function (still same result!) */
-static const float cosval[CIRCLE_RESOL] = {
- 1.00000000, 0.97952994, 0.91895781, 0.82076344, 0.68896691, 0.52896401, 0.34730525,
- 0.15142777, -0.05064916, -0.25065253, -0.44039415, -0.61210598, -0.75875812, -0.87434661,
- -0.95413925, -0.99486932, -0.99486932, -0.95413925, -0.87434661, -0.75875812, -0.61210598,
- -0.44039415, -0.25065253, -0.05064916, 0.15142777, 0.34730525, 0.52896401, 0.68896691,
- 0.82076344, 0.91895781, 0.97952994, 1.00000000,
-};
-
-static void circball_array_fill(const float verts[CIRCLE_RESOL][3],
- const float cent[3],
- float rad,
- const float tmat[4][4])
-{
- float vx[3], vy[3];
- float *viter = (float *)verts;
-
- mul_v3_v3fl(vx, tmat[0], rad);
- mul_v3_v3fl(vy, tmat[1], rad);
-
- for (uint a = 0; a < CIRCLE_RESOL; a++, viter += 3) {
- viter[0] = cent[0] + sinval[a] * vx[0] + cosval[a] * vy[0];
- viter[1] = cent[1] + sinval[a] * vx[1] + cosval[a] * vy[1];
- viter[2] = cent[2] + sinval[a] * vx[2] + cosval[a] * vy[2];
- }
-}
-
-void imm_drawcircball(const float cent[3], float rad, const float tmat[4][4], uint pos)
-{
- float verts[CIRCLE_RESOL][3];
-
- circball_array_fill(verts, cent, rad, tmat);
-
- immBegin(GPU_PRIM_LINE_LOOP, CIRCLE_RESOL);
- for (int i = 0; i < CIRCLE_RESOL; i++) {
- immVertex3fv(pos, verts[i]);
- }
- immEnd();
-}
-
#ifdef VIEW3D_CAMERA_BORDER_HACK
uchar view3d_camera_border_hack_col[3];
bool view3d_camera_border_hack_test = false;
diff --git a/source/blender/editors/space_view3d/space_view3d.c b/source/blender/editors/space_view3d/space_view3d.c
index bf16dfb469c..e54ef3c931a 100644
--- a/source/blender/editors/space_view3d/space_view3d.c
+++ b/source/blender/editors/space_view3d/space_view3d.c
@@ -853,7 +853,6 @@ static void view3d_dropboxes(void)
drop->draw = WM_drag_draw_item_name_fn;
drop->draw_activate = view3d_ob_drop_draw_activate;
drop->draw_deactivate = view3d_ob_drop_draw_deactivate;
- drop->opcontext = WM_OP_EXEC_DEFAULT; /* Not really needed. */
drop = WM_dropbox_add(lb,
"OBJECT_OT_transform_to_mouse",
@@ -865,7 +864,6 @@ static void view3d_dropboxes(void)
drop->draw = WM_drag_draw_item_name_fn;
drop->draw_activate = view3d_ob_drop_draw_activate;
drop->draw_deactivate = view3d_ob_drop_draw_deactivate;
- drop->opcontext = WM_OP_INVOKE_DEFAULT;
WM_dropbox_add(lb,
"OBJECT_OT_drop_named_material",
diff --git a/source/blender/editors/space_view3d/view3d_cursor_snap.c b/source/blender/editors/space_view3d/view3d_cursor_snap.c
index 1213614704d..ac80a70011a 100644
--- a/source/blender/editors/space_view3d/view3d_cursor_snap.c
+++ b/source/blender/editors/space_view3d/view3d_cursor_snap.c
@@ -95,9 +95,7 @@ typedef struct SnapCursorDataIntern {
static SnapCursorDataIntern g_data_intern = {
.state_default = {.prevpoint = NULL,
- .snap_elem_force = (SCE_SNAP_MODE_VERTEX | SCE_SNAP_MODE_EDGE |
- SCE_SNAP_MODE_FACE | SCE_SNAP_MODE_EDGE_PERPENDICULAR |
- SCE_SNAP_MODE_EDGE_MIDPOINT),
+ .snap_elem_force = SCE_SNAP_MODE_GEOM,
.plane_axis = 2,
.color_point = {255, 255, 255, 255},
.color_line = {255, 255, 255, 128},
diff --git a/source/blender/editors/space_view3d/view3d_draw.c b/source/blender/editors/space_view3d/view3d_draw.c
index fceb6553cab..6f6fa8b7576 100644
--- a/source/blender/editors/space_view3d/view3d_draw.c
+++ b/source/blender/editors/space_view3d/view3d_draw.c
@@ -1318,10 +1318,9 @@ static void draw_viewport_name(ARegion *region, View3D *v3d, int xoffset, int *y
}
/**
- * Draw info beside axes in bottom left-corner:
+ * Draw info beside axes in top-left corner:
* frame-number, collection, object name, bone name (if available), marker name (if available).
*/
-
static void draw_selected_name(
Scene *scene, ViewLayer *view_layer, Object *ob, int xoffset, int *yoffset)
{
@@ -1344,14 +1343,13 @@ static void draw_selected_name(
(ob == NULL) ? "" : " |");
}
- /*
- * info can contain:
- * - a frame (7 + 2)
- * - a collection name (MAX_NAME + 3)
- * - 3 object names (MAX_NAME)
- * - 2 BREAD_CRUMB_SEPARATORs (6)
- * - a SHAPE_KEY_PINNED marker and a trailing '\0' (9+1) - translated, so give some room!
- * - a marker name (MAX_NAME + 3)
+ /* Info can contain:
+ * - A frame `(7 + 2)`.
+ * - A collection name `(MAX_NAME + 3)`.
+ * - 3 object names `(MAX_NAME)`.
+ * - 2 BREAD_CRUMB_SEPARATOR(s) `(6)`.
+ * - A SHAPE_KEY_PINNED marker and a trailing '\0' `(9+1)` - translated, so give some room!
+ * - A marker name `(MAX_NAME + 3)`.
*/
/* get name of marker on current frame (if available) */
diff --git a/source/blender/editors/space_view3d/view3d_gizmo_ruler.c b/source/blender/editors/space_view3d/view3d_gizmo_ruler.c
index 34e3b808b50..1082483dcd7 100644
--- a/source/blender/editors/space_view3d/view3d_gizmo_ruler.c
+++ b/source/blender/editors/space_view3d/view3d_gizmo_ruler.c
@@ -115,8 +115,10 @@ enum {
CONSTRAIN_AXIS_Z = 2,
};
-/* Constraining modes.
- Off / Scene orientation / Global (or Local if Scene orientation is Global) */
+/**
+ * Constraining modes.
+ * Off / Scene orientation / Global (or Local if Scene orientation is Global).
+ */
enum {
CONSTRAIN_MODE_OFF = 0,
CONSTRAIN_MODE_1 = 1,
@@ -163,7 +165,7 @@ typedef struct RulerInfo {
typedef struct RulerItem {
wmGizmo gz;
- /* worldspace coords, middle being optional */
+ /** World-space coords, middle being optional. */
float co[3][3];
int flag;
@@ -643,7 +645,7 @@ static void gizmo_ruler_draw(const bContext *C, wmGizmo *gz)
GPU_line_width(1.0f);
BLF_enable(blf_mono_font, BLF_ROTATION);
- BLF_size(blf_mono_font, 14 * U.pixelsize, U.dpi);
+ BLF_size(blf_mono_font, 14.0f * U.pixelsize, U.dpi);
BLF_rotation(blf_mono_font, 0.0f);
UI_GetThemeColor3ubv(TH_TEXT, color_text);
diff --git a/source/blender/editors/space_view3d/view3d_ops.c b/source/blender/editors/space_view3d/view3d_ops.c
index eb8c043319c..823aa3b6643 100644
--- a/source/blender/editors/space_view3d/view3d_ops.c
+++ b/source/blender/editors/space_view3d/view3d_ops.c
@@ -63,19 +63,19 @@ static int view3d_copybuffer_exec(bContext *C, wmOperator *op)
char str[FILE_MAX];
int num_copied = 0;
- BKE_copybuffer_begin(bmain);
+ BKE_copybuffer_copy_begin(bmain);
/* context, selection, could be generalized */
CTX_DATA_BEGIN (C, Object *, ob, selected_objects) {
if ((ob->id.tag & LIB_TAG_DOIT) == 0) {
- BKE_copybuffer_tag_ID(&ob->id);
+ BKE_copybuffer_copy_tag_ID(&ob->id);
num_copied++;
}
}
CTX_DATA_END;
BLI_join_dirfile(str, sizeof(str), BKE_tempdir_base(), "copybuffer.blend");
- BKE_copybuffer_save(bmain, str, op->reports);
+ BKE_copybuffer_copy_end(bmain, str, op->reports);
BKE_reportf(op->reports, RPT_INFO, "Copied %d selected object(s)", num_copied);
diff --git a/source/blender/editors/space_view3d/view3d_placement.c b/source/blender/editors/space_view3d/view3d_placement.c
index cecd1765a17..8c1cab6bf14 100644
--- a/source/blender/editors/space_view3d/view3d_placement.c
+++ b/source/blender/editors/space_view3d/view3d_placement.c
@@ -45,10 +45,6 @@
#include "view3d_intern.h"
-#define SNAP_MODE_GEOM \
- (SCE_SNAP_MODE_VERTEX | SCE_SNAP_MODE_EDGE | SCE_SNAP_MODE_FACE | \
- SCE_SNAP_MODE_EDGE_PERPENDICULAR | SCE_SNAP_MODE_EDGE_MIDPOINT)
-
static const char *view3d_gzgt_placement_id = "VIEW3D_GGT_placement";
/**
@@ -1308,7 +1304,7 @@ static int idp_rna_snap_target_get_fn(struct PointerRNA *UNUSED(ptr),
}
/* Make sure you keep a consistent #snap_mode. */
- snap_state->snap_elem_force = SNAP_MODE_GEOM;
+ snap_state->snap_elem_force = SCE_SNAP_MODE_GEOM;
return PLACE_SNAP_TO_GEOMETRY;
}
@@ -1319,7 +1315,7 @@ static void idp_rna_snap_target_set_fn(struct PointerRNA *UNUSED(ptr),
short snap_mode = 0; /* #toolsettings->snap_mode. */
const enum ePlace_SnapTo snap_to = value;
if (snap_to == PLACE_SNAP_TO_GEOMETRY) {
- snap_mode = SNAP_MODE_GEOM;
+ snap_mode = SCE_SNAP_MODE_GEOM;
}
V3DSnapCursorState *snap_state = ED_view3d_cursor_snap_state_get();
diff --git a/source/blender/editors/space_view3d/view3d_utils.c b/source/blender/editors/space_view3d/view3d_utils.c
index e09453b9957..d6a1cd930fc 100644
--- a/source/blender/editors/space_view3d/view3d_utils.c
+++ b/source/blender/editors/space_view3d/view3d_utils.c
@@ -1094,17 +1094,10 @@ bool ED_view3d_autodist_simple(ARegion *region,
return ED_view3d_unproject_v3(region, centx, centy, depth, mouse_worldloc);
}
-bool ED_view3d_autodist_depth(ARegion *region, const int mval[2], int margin, float *depth)
-{
- *depth = view_autodist_depth_margin(region, mval, margin);
-
- return (*depth != FLT_MAX);
-}
-
static bool depth_segment_cb(int x, int y, void *userData)
{
struct {
- ARegion *region;
+ const ViewDepths *vd;
int margin;
float depth;
} *data = userData;
@@ -1114,27 +1107,25 @@ static bool depth_segment_cb(int x, int y, void *userData)
mval[0] = x;
mval[1] = y;
- depth = view_autodist_depth_margin(data->region, mval, data->margin);
-
- if (depth != FLT_MAX) {
+ if (ED_view3d_depth_read_cached(data->vd, mval, data->margin, &depth)) {
data->depth = depth;
return false;
}
return true;
}
-bool ED_view3d_autodist_depth_seg(
- ARegion *region, const int mval_sta[2], const int mval_end[2], int margin, float *depth)
+bool ED_view3d_depth_read_cached_seg(
+ const ViewDepths *vd, const int mval_sta[2], const int mval_end[2], int margin, float *depth)
{
struct {
- ARegion *region;
+ const ViewDepths *vd;
int margin;
float depth;
} data = {NULL};
int p1[2];
int p2[2];
- data.region = region;
+ data.vd = vd;
data.margin = margin;
data.depth = FLT_MAX;
@@ -1691,6 +1682,9 @@ bool ED_view3d_depth_read_cached(const ViewDepths *vd,
return true;
}
+ /* Grease-pencil and annotations also need the returned depth value to be high
+ * so the caller can detect it's invalid. */
+ *r_depth = FLT_MAX;
return false;
}
diff --git a/source/blender/editors/space_view3d/view3d_view.c b/source/blender/editors/space_view3d/view3d_view.c
index 46a664f10fa..6f0ce6c9326 100644
--- a/source/blender/editors/space_view3d/view3d_view.c
+++ b/source/blender/editors/space_view3d/view3d_view.c
@@ -1731,9 +1731,9 @@ void ED_view3d_xr_shading_update(wmWindowManager *wm, const View3D *v3d, const S
View3DShading *xr_shading = &wm->xr.session_settings.shading;
/* Flags that shouldn't be overridden by the 3D View shading. */
int flag_copy = 0;
- if (v3d->shading.type !=
- OB_SOLID) { /* Don't set V3D_SHADING_WORLD_ORIENTATION for solid shading since it results
- in distorted lighting when the view matrix has a scale factor. */
+ if (v3d->shading.type != OB_SOLID) {
+ /* Don't set V3D_SHADING_WORLD_ORIENTATION for solid shading since it results in distorted
+ * lighting when the view matrix has a scale factor. */
flag_copy |= V3D_SHADING_WORLD_ORIENTATION;
}
diff --git a/source/blender/editors/transform/transform.h b/source/blender/editors/transform/transform.h
index e13e7c3f93a..d78cd13f8b8 100644
--- a/source/blender/editors/transform/transform.h
+++ b/source/blender/editors/transform/transform.h
@@ -317,9 +317,9 @@ typedef struct TransSnap {
/* Snapped Element Type (currently for objects only). */
char snapElem;
/** snapping from this point (in global-space). */
- float snapPoint[3];
- /** to this point (in global-space). */
float snapTarget[3];
+ /** to this point (in global-space). */
+ float snapPoint[3];
float snapTargetGrid[3];
float snapNormal[3];
char snapNodeBorder;
diff --git a/source/blender/editors/transform/transform_convert_action.c b/source/blender/editors/transform/transform_convert_action.c
index a6658ae00a3..24d84bc2de8 100644
--- a/source/blender/editors/transform/transform_convert_action.c
+++ b/source/blender/editors/transform/transform_convert_action.c
@@ -159,8 +159,11 @@ static void TimeToTransData(
copy_v2_v2(td2d->ih2, td2d->h2);
/* Setup #TransData. */
- td->loc = time; /* Usually #td2d->loc is used here. But this is for when the original location is
- not float[3]. */
+
+ /* Usually #td2d->loc is used here.
+ * But this is for when the original location is not float[3]. */
+ td->loc = time;
+
copy_v3_v3(td->iloc, td->loc);
td->val = time;
td->ival = *(time);
diff --git a/source/blender/editors/transform/transform_generics.c b/source/blender/editors/transform/transform_generics.c
index 87cc7a27829..c911331404f 100644
--- a/source/blender/editors/transform/transform_generics.c
+++ b/source/blender/editors/transform/transform_generics.c
@@ -144,7 +144,6 @@ static void *t_view_get(TransInfo *t)
View3D *v3d = t->area->spacedata.first;
return (void *)v3d;
}
-
if (t->region) {
return (void *)&t->region->v2d;
}
diff --git a/source/blender/editors/transform/transform_mode_translate.c b/source/blender/editors/transform/transform_mode_translate.c
index 82574cffb82..233e32c0e48 100644
--- a/source/blender/editors/transform/transform_mode_translate.c
+++ b/source/blender/editors/transform/transform_mode_translate.c
@@ -403,7 +403,7 @@ static void applyTranslationValue(TransInfo *t, const float vec[3])
* since re-applying translation without rotation removes rotation. */
}
else {
- /* When transforming data that it's self stores rotation (objects, bones etc),
+ /* When transforming data that itself stores rotation (objects, bones etc),
* apply rotation if it was applied (with the snap normal) previously.
* This is needed because failing to rotate will leave the rotation at the last
* value used before snapping was disabled. */
diff --git a/source/blender/editors/transform/transform_snap.c b/source/blender/editors/transform/transform_snap.c
index 7f27d5fb180..71f26ef0594 100644
--- a/source/blender/editors/transform/transform_snap.c
+++ b/source/blender/editors/transform/transform_snap.c
@@ -200,7 +200,7 @@ void drawSnapping(const struct bContext *C, TransInfo *t)
if (t->spacetype == SPACE_VIEW3D) {
bool draw_target = (t->tsnap.status & TARGET_INIT) &&
- (t->scene->toolsettings->snap_mode & SCE_SNAP_MODE_EDGE_PERPENDICULAR);
+ (t->tsnap.mode & SCE_SNAP_MODE_EDGE_PERPENDICULAR);
if (draw_target || validSnap(t)) {
const float *loc_cur = NULL;
@@ -483,7 +483,7 @@ void applySnapping(TransInfo *t, float *vec)
}
if (t->tsnap.project && t->tsnap.mode == SCE_SNAP_MODE_FACE) {
- /* The snap has already been resolved for each transdata. */
+ /* A similar snap will be applied to each transdata in `applyProject`. */
return;
}
@@ -574,70 +574,61 @@ static bool bm_face_is_snap_target(BMFace *f, void *UNUSED(user_data))
return true;
}
-static void initSnappingMode(TransInfo *t)
+static short snap_mode_from_scene(TransInfo *t)
{
ToolSettings *ts = t->settings;
- /* All obedit types will match. */
- const int obedit_type = t->obedit_type;
- ViewLayer *view_layer = t->view_layer;
- Base *base_act = view_layer->basact;
+ short r_snap_mode = SCE_SNAP_MODE_INCREMENT;
if (t->spacetype == SPACE_NODE) {
- /* force project off when not supported */
- t->tsnap.project = 0;
-
- t->tsnap.mode = ts->snap_node_mode;
+ r_snap_mode = ts->snap_node_mode;
}
else if (t->spacetype == SPACE_IMAGE) {
- /* force project off when not supported */
- t->tsnap.project = 0;
-
- t->tsnap.mode = ts->snap_uv_mode;
- if ((t->tsnap.mode & SCE_SNAP_MODE_INCREMENT) && (ts->snap_uv_flag & SCE_SNAP_ABS_GRID) &&
+ r_snap_mode = ts->snap_uv_mode;
+ if ((r_snap_mode & SCE_SNAP_MODE_INCREMENT) && (ts->snap_uv_flag & SCE_SNAP_ABS_GRID) &&
(t->mode == TFM_TRANSLATION)) {
- t->tsnap.mode &= ~SCE_SNAP_MODE_INCREMENT;
- t->tsnap.mode |= SCE_SNAP_MODE_GRID;
+ r_snap_mode &= ~SCE_SNAP_MODE_INCREMENT;
+ r_snap_mode |= SCE_SNAP_MODE_GRID;
}
}
else if (t->spacetype == SPACE_SEQ) {
- t->tsnap.mode = SEQ_tool_settings_snap_mode_get(t->scene);
+ r_snap_mode = SEQ_tool_settings_snap_mode_get(t->scene);
}
else if (ELEM(t->spacetype, SPACE_VIEW3D, SPACE_IMAGE) && !(t->options & CTX_CAMERA)) {
- /* force project off when not supported */
- if ((ts->snap_mode & SCE_SNAP_MODE_FACE) == 0) {
- t->tsnap.project = 0;
- }
-
- t->tsnap.mode = ts->snap_mode;
- if ((t->tsnap.mode & SCE_SNAP_MODE_INCREMENT) && (ts->snap_flag & SCE_SNAP_ABS_GRID) &&
- (t->mode == TFM_TRANSLATION)) {
- /* Special case in which snap to increments is transformed to snap to grid. */
- t->tsnap.mode &= ~SCE_SNAP_MODE_INCREMENT;
- t->tsnap.mode |= SCE_SNAP_MODE_GRID;
+ /* All obedit types will match. */
+ const int obedit_type = t->obedit_type;
+ if ((t->options & (CTX_GPENCIL_STROKES | CTX_CURSOR | CTX_OBMODE_XFORM_OBDATA)) ||
+ ELEM(obedit_type, OB_MESH, OB_ARMATURE, OB_CURVE, OB_LATTICE, OB_MBALL, -1)) {
+ r_snap_mode = ts->snap_mode;
+ if ((r_snap_mode & SCE_SNAP_MODE_INCREMENT) && (ts->snap_flag & SCE_SNAP_ABS_GRID) &&
+ (t->mode == TFM_TRANSLATION)) {
+ /* Special case in which snap to increments is transformed to snap to grid. */
+ r_snap_mode &= ~SCE_SNAP_MODE_INCREMENT;
+ r_snap_mode |= SCE_SNAP_MODE_GRID;
+ }
}
}
else if (ELEM(t->spacetype, SPACE_ACTION, SPACE_NLA)) {
/* No incremental snapping. */
- t->tsnap.mode = 0;
- }
- else {
- /* Fallback. */
- t->tsnap.mode = SCE_SNAP_MODE_INCREMENT;
+ r_snap_mode = 0;
}
- if (ELEM(t->spacetype, SPACE_VIEW3D, SPACE_IMAGE) && !(t->options & CTX_CAMERA)) {
- /* Only 3D view or UV. */
- /* Not with camera selected in camera view. */
+ return r_snap_mode;
+}
- setSnappingCallback(t);
+static short snap_select_type_get(TransInfo *t)
+{
+ short r_snap_select = SNAP_ALL;
+ ViewLayer *view_layer = t->view_layer;
+ Base *base_act = view_layer->basact;
+ if (ELEM(t->spacetype, SPACE_VIEW3D, SPACE_IMAGE) && !(t->options & CTX_CAMERA)) {
+ const int obedit_type = t->obedit_type;
if (t->options & (CTX_GPENCIL_STROKES | CTX_CURSOR | CTX_OBMODE_XFORM_OBDATA)) {
/* In "Edit Strokes" mode,
* snap tool can perform snap to selected or active objects (see T49632)
* TODO: perform self snap in gpencil_strokes.
*
* When we're moving the origins, allow snapping onto our own geometry (see T69132). */
- t->tsnap.modeSelect = SNAP_ALL;
}
else if ((obedit_type != -1) &&
ELEM(obedit_type, OB_MESH, OB_ARMATURE, OB_CURVE, OB_LATTICE, OB_MBALL)) {
@@ -646,29 +637,44 @@ static void initSnappingMode(TransInfo *t)
if ((obedit_type == OB_MESH) && (t->flag & T_PROP_EDIT)) {
/* Exclude editmesh if using proportional edit */
- t->tsnap.modeSelect = SNAP_NOT_ACTIVE;
+ r_snap_select = SNAP_NOT_ACTIVE;
}
- else {
- t->tsnap.modeSelect = t->tsnap.snap_self ? SNAP_ALL : SNAP_NOT_ACTIVE;
+ else if (!t->tsnap.snap_self) {
+ r_snap_select = SNAP_NOT_ACTIVE;
}
}
else if ((obedit_type == -1) && base_act && base_act->object &&
(base_act->object->mode & OB_MODE_PARTICLE_EDIT)) {
/* Particles edit mode. */
- t->tsnap.modeSelect = SNAP_ALL;
}
else if (obedit_type == -1) {
/* Object mode */
- t->tsnap.modeSelect = SNAP_NOT_SELECTED;
- }
- else {
- /* Increment if snap is not possible */
- t->tsnap.mode = SCE_SNAP_MODE_INCREMENT;
+ r_snap_select = SNAP_NOT_SELECTED;
}
}
else if (ELEM(t->spacetype, SPACE_NODE, SPACE_SEQ)) {
- setSnappingCallback(t);
- t->tsnap.modeSelect = SNAP_NOT_SELECTED;
+ r_snap_select = SNAP_NOT_SELECTED;
+ }
+
+ return r_snap_select;
+}
+
+static void initSnappingMode(TransInfo *t)
+{
+ ToolSettings *ts = t->settings;
+ t->tsnap.mode = snap_mode_from_scene(t);
+ t->tsnap.modeSelect = snap_select_type_get(t);
+
+ if ((t->spacetype != SPACE_VIEW3D) || !(ts->snap_mode & SCE_SNAP_MODE_FACE)) {
+ /* Force project off when not supported. */
+ t->tsnap.project = 0;
+ }
+
+ if (ELEM(t->spacetype, SPACE_VIEW3D, SPACE_IMAGE, SPACE_NODE, SPACE_SEQ)) {
+ /* Not with camera selected in camera view. */
+ if (!(t->options & CTX_CAMERA)) {
+ setSnappingCallback(t);
+ }
}
if (t->spacetype == SPACE_VIEW3D) {
@@ -918,8 +924,7 @@ static void snap_calc_view3d_fn(TransInfo *t, float *UNUSED(vec))
mval[0] = t->mval[0];
mval[1] = t->mval[1];
- if (t->tsnap.mode & (SCE_SNAP_MODE_VERTEX | SCE_SNAP_MODE_EDGE | SCE_SNAP_MODE_FACE |
- SCE_SNAP_MODE_EDGE_MIDPOINT | SCE_SNAP_MODE_EDGE_PERPENDICULAR)) {
+ if (t->tsnap.mode & SCE_SNAP_MODE_GEOM) {
zero_v3(no); /* objects won't set this */
snap_elem = snapObjectsTransform(t, mval, &dist_px, loc, no);
found = snap_elem != 0;
@@ -1249,7 +1254,7 @@ short snapObjectsTransform(
t->depsgraph,
t->region,
t->view,
- t->settings->snap_mode,
+ t->tsnap.mode,
&(const struct SnapObjectParams){
.snap_select = t->tsnap.modeSelect,
.edit_mode_type = (t->flag & T_EDIT) != 0 ? SNAP_GEOM_EDIT : SNAP_GEOM_FINAL,
diff --git a/source/blender/editors/transform/transform_snap_object.c b/source/blender/editors/transform/transform_snap_object.c
index 4a2ac806b2c..4b981e763f1 100644
--- a/source/blender/editors/transform/transform_snap_object.c
+++ b/source/blender/editors/transform/transform_snap_object.c
@@ -581,15 +581,15 @@ static void raycast_all_cb(void *userdata, int index, const BVHTreeRay *ray, BVH
struct RayCastAll_Data *data = userdata;
data->raycast_callback(data->bvhdata, index, ray, hit);
if (hit->index != -1) {
- /* get all values in worldspace */
+ /* Get all values in world-space. */
float location[3], normal[3];
float depth;
- /* worldspace location */
+ /* World-space location. */
mul_v3_m4v3(location, (float(*)[4])data->obmat, hit->co);
depth = (hit->dist + data->len_diff) / data->local_scale;
- /* worldspace normal */
+ /* World-space normal. */
copy_v3_v3(normal, hit->no);
mul_m3_v3((float(*)[3])data->timat, normal);
normalize_v3(normal);
@@ -783,7 +783,7 @@ static bool raycastMesh(SnapObjectContext *sctx,
*ray_depth = hit.dist;
copy_v3_v3(r_loc, hit.co);
- /* back to worldspace */
+ /* Back to world-space. */
mul_m4_v3(obmat, r_loc);
if (r_no) {
@@ -953,7 +953,7 @@ static bool raycastEditMesh(SnapObjectContext *sctx,
*ray_depth = hit.dist;
copy_v3_v3(r_loc, hit.co);
- /* back to worldspace */
+ /* Back to world-space. */
mul_m4_v3(obmat, r_loc);
if (r_no) {
diff --git a/source/blender/freestyle/intern/view_map/FEdgeXDetector.cpp b/source/blender/freestyle/intern/view_map/FEdgeXDetector.cpp
index 9bf00ed7092..de7fcb7a728 100644
--- a/source/blender/freestyle/intern/view_map/FEdgeXDetector.cpp
+++ b/source/blender/freestyle/intern/view_map/FEdgeXDetector.cpp
@@ -190,7 +190,7 @@ void FEdgeXDetector::computeCurvatures(WXVertex *vertex)
}
// CURVATURE LAYER
- // store all the curvature datas for each vertex
+ // store all the curvature data for each vertex
// soc unused - real K1, K2
real cos2theta, sin2theta;
diff --git a/source/blender/functions/FN_field.hh b/source/blender/functions/FN_field.hh
index 5e0302130af..28bb120bb17 100644
--- a/source/blender/functions/FN_field.hh
+++ b/source/blender/functions/FN_field.hh
@@ -178,11 +178,19 @@ class GFieldRef : public GFieldBase<const FieldNode *> {
}
};
+namespace detail {
+/* Utility class to make #is_field_v work. */
+struct TypedFieldBase {
+};
+} // namespace detail
+
/**
* A typed version of #GField. It has the same memory layout as #GField.
*/
-template<typename T> class Field : public GField {
+template<typename T> class Field : public GField, detail::TypedFieldBase {
public:
+ using base_type = T;
+
Field() = default;
Field(GField field) : GField(std::move(field))
@@ -196,6 +204,11 @@ template<typename T> class Field : public GField {
}
};
+/** True when T is any Field<...> type. */
+template<typename T>
+static constexpr bool is_field_v = std::is_base_of_v<detail::TypedFieldBase, T> &&
+ !std::is_same_v<detail::TypedFieldBase, T>;
+
/**
* A #FieldNode that allows composing existing fields into new fields.
*/
@@ -248,9 +261,9 @@ class FieldInput : public FieldNode {
* Get the value of this specific input based on the given context. The returned virtual array,
* should live at least as long as the passed in #scope. May return null.
*/
- virtual const GVArray *get_varray_for_context(const FieldContext &context,
- IndexMask mask,
- ResourceScope &scope) const = 0;
+ virtual GVArray get_varray_for_context(const FieldContext &context,
+ IndexMask mask,
+ ResourceScope &scope) const = 0;
virtual std::string socket_inspection_name() const;
blender::StringRef debug_name() const;
@@ -268,9 +281,9 @@ class FieldContext {
public:
~FieldContext() = default;
- virtual const GVArray *get_varray_for_input(const FieldInput &field_input,
- IndexMask mask,
- ResourceScope &scope) const;
+ virtual GVArray get_varray_for_input(const FieldInput &field_input,
+ IndexMask mask,
+ ResourceScope &scope) const;
};
/**
@@ -289,8 +302,8 @@ class FieldEvaluator : NonMovable, NonCopyable {
const FieldContext &context_;
const IndexMask mask_;
Vector<GField> fields_to_evaluate_;
- Vector<GVMutableArray *> dst_varrays_;
- Vector<const GVArray *> evaluated_varrays_;
+ Vector<GVMutableArray> dst_varrays_;
+ Vector<GVArray> evaluated_varrays_;
Vector<OutputPointerInfo> output_pointer_infos_;
bool is_evaluated_ = false;
@@ -317,13 +330,12 @@ class FieldEvaluator : NonMovable, NonCopyable {
* \param field: Field to add to the evaluator.
* \param dst: Mutable virtual array that the evaluated result for this field is be written into.
*/
- int add_with_destination(GField field, GVMutableArray &dst);
+ int add_with_destination(GField field, GVMutableArray dst);
/** Same as #add_with_destination but typed. */
- template<typename T> int add_with_destination(Field<T> field, VMutableArray<T> &dst)
+ template<typename T> int add_with_destination(Field<T> field, VMutableArray<T> dst)
{
- GVMutableArray &varray = scope_.construct<GVMutableArray_For_VMutableArray<T>>(dst);
- return this->add_with_destination(GField(std::move(field)), varray);
+ return this->add_with_destination(GField(std::move(field)), GVMutableArray(std::move(dst)));
}
/**
@@ -342,11 +354,10 @@ class FieldEvaluator : NonMovable, NonCopyable {
*/
template<typename T> int add_with_destination(Field<T> field, MutableSpan<T> dst)
{
- GVMutableArray &varray = scope_.construct<GVMutableArray_For_MutableSpan<T>>(dst);
- return this->add_with_destination(std::move(field), varray);
+ return this->add_with_destination(std::move(field), VMutableArray<T>::ForSpan(dst));
}
- int add(GField field, const GVArray **varray_ptr);
+ int add(GField field, GVArray *varray_ptr);
/**
* \param field: Field to add to the evaluator.
@@ -354,14 +365,14 @@ class FieldEvaluator : NonMovable, NonCopyable {
* assigned to the given position.
* \return Index of the field in the evaluator which can be used in the #get_evaluated methods.
*/
- template<typename T> int add(Field<T> field, const VArray<T> **varray_ptr)
+ template<typename T> int add(Field<T> field, VArray<T> *varray_ptr)
{
const int field_index = fields_to_evaluate_.append_and_get_index(std::move(field));
- dst_varrays_.append(nullptr);
- output_pointer_infos_.append(
- OutputPointerInfo{varray_ptr, [](void *dst, const GVArray &varray, ResourceScope &scope) {
- *(const VArray<T> **)dst = &*scope.construct<GVArray_Typed<T>>(varray);
- }});
+ dst_varrays_.append({});
+ output_pointer_infos_.append(OutputPointerInfo{
+ varray_ptr, [](void *dst, const GVArray &varray, ResourceScope &UNUSED(scope)) {
+ *(VArray<T> *)dst = varray.typed<T>();
+ }});
return field_index;
}
@@ -378,14 +389,12 @@ class FieldEvaluator : NonMovable, NonCopyable {
const GVArray &get_evaluated(const int field_index) const
{
BLI_assert(is_evaluated_);
- return *evaluated_varrays_[field_index];
+ return evaluated_varrays_[field_index];
}
- template<typename T> const VArray<T> &get_evaluated(const int field_index)
+ template<typename T> VArray<T> get_evaluated(const int field_index)
{
- const GVArray &varray = this->get_evaluated(field_index);
- GVArray_Typed<T> &typed_varray = scope_.construct<GVArray_Typed<T>>(varray);
- return *typed_varray;
+ return this->get_evaluated(field_index).typed<T>();
}
/**
@@ -396,11 +405,11 @@ class FieldEvaluator : NonMovable, NonCopyable {
IndexMask get_evaluated_as_mask(const int field_index);
};
-Vector<const GVArray *> evaluate_fields(ResourceScope &scope,
- Span<GFieldRef> fields_to_evaluate,
- IndexMask mask,
- const FieldContext &context,
- Span<GVMutableArray *> dst_varrays = {});
+Vector<GVArray> evaluate_fields(ResourceScope &scope,
+ Span<GFieldRef> fields_to_evaluate,
+ IndexMask mask,
+ const FieldContext &context,
+ Span<GVMutableArray> dst_varrays = {});
/* -------------------------------------------------------------------- */
/** \name Utility functions for simple field creation and evaluation
@@ -423,17 +432,19 @@ template<typename T> Field<T> make_constant_field(T value)
return Field<T>{GField{std::move(operation), 0}};
}
+GField make_constant_field(const CPPType &type, const void *value);
+
GField make_field_constant_if_possible(GField field);
class IndexFieldInput final : public FieldInput {
public:
IndexFieldInput();
- static GVArray *get_index_varray(IndexMask mask, ResourceScope &scope);
+ static GVArray get_index_varray(IndexMask mask, ResourceScope &scope);
- const GVArray *get_varray_for_context(const FieldContext &context,
- IndexMask mask,
- ResourceScope &scope) const final;
+ GVArray get_varray_for_context(const FieldContext &context,
+ IndexMask mask,
+ ResourceScope &scope) const final;
uint64_t hash() const override;
bool is_equal_to(const fn::FieldNode &other) const override;
@@ -442,6 +453,52 @@ class IndexFieldInput final : public FieldInput {
/** \} */
/* -------------------------------------------------------------------- */
+/** \name Value or Field Class
+ *
+ * Utility class that wraps a single value and a field, to simplify accessing both of the types.
+ * \{ */
+
+template<typename T> struct ValueOrField {
+ /** Value that is used when the field is empty. */
+ T value{};
+ Field<T> field;
+
+ ValueOrField() = default;
+
+ ValueOrField(T value) : value(std::move(value))
+ {
+ }
+
+ ValueOrField(Field<T> field) : field(std::move(field))
+ {
+ }
+
+ bool is_field() const
+ {
+ return (bool)this->field;
+ }
+
+ Field<T> as_field() const
+ {
+ if (this->field) {
+ return this->field;
+ }
+ return make_constant_field(this->value);
+ }
+
+ T as_value() const
+ {
+ if (this->field) {
+ /* This returns a default value when the field is not constant. */
+ return evaluate_constant_field(this->field);
+ }
+ return this->value;
+ }
+};
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
/** \name #FieldNode Inline Methods
* \{ */
diff --git a/source/blender/functions/FN_field_cpp_type.hh b/source/blender/functions/FN_field_cpp_type.hh
index 5e6f1b5a585..940faba6d70 100644
--- a/source/blender/functions/FN_field_cpp_type.hh
+++ b/source/blender/functions/FN_field_cpp_type.hh
@@ -30,19 +30,19 @@ template<typename T> struct FieldCPPTypeParam {
class FieldCPPType : public CPPType {
private:
- const CPPType &field_type_;
+ const CPPType &base_type_;
public:
template<typename T>
FieldCPPType(FieldCPPTypeParam<Field<T>> /* unused */, StringRef debug_name)
: CPPType(CPPTypeParam<Field<T>, CPPTypeFlags::None>(), debug_name),
- field_type_(CPPType::get<T>())
+ base_type_(CPPType::get<T>())
{
}
- const CPPType &field_type() const
+ const CPPType &base_type() const
{
- return field_type_;
+ return base_type_;
}
/* Ensure that #GField and #Field<T> have the same layout, to enable casting between the two. */
@@ -60,6 +60,84 @@ class FieldCPPType : public CPPType {
}
};
+class ValueOrFieldCPPType : public CPPType {
+ private:
+ const CPPType &base_type_;
+ void (*construct_from_value_)(void *dst, const void *value);
+ void (*construct_from_field_)(void *dst, GField field);
+ const void *(*get_value_ptr_)(const void *value_or_field);
+ const GField *(*get_field_ptr_)(const void *value_or_field);
+ bool (*is_field_)(const void *value_or_field);
+ GField (*as_field_)(const void *value_or_field);
+
+ public:
+ template<typename T>
+ ValueOrFieldCPPType(FieldCPPTypeParam<ValueOrField<T>> /* unused */, StringRef debug_name)
+ : CPPType(CPPTypeParam<ValueOrField<T>, CPPTypeFlags::None>(), debug_name),
+ base_type_(CPPType::get<T>())
+ {
+ construct_from_value_ = [](void *dst, const void *value_or_field) {
+ new (dst) ValueOrField<T>(*(const T *)value_or_field);
+ };
+ construct_from_field_ = [](void *dst, GField field) {
+ new (dst) ValueOrField<T>(Field<T>(std::move(field)));
+ };
+ get_value_ptr_ = [](const void *value_or_field) {
+ return (const void *)&((ValueOrField<T> *)value_or_field)->value;
+ };
+ get_field_ptr_ = [](const void *value_or_field) -> const GField * {
+ return &((ValueOrField<T> *)value_or_field)->field;
+ };
+ is_field_ = [](const void *value_or_field) {
+ return ((ValueOrField<T> *)value_or_field)->is_field();
+ };
+ as_field_ = [](const void *value_or_field) -> GField {
+ return ((ValueOrField<T> *)value_or_field)->as_field();
+ };
+ }
+
+ const CPPType &base_type() const
+ {
+ return base_type_;
+ }
+
+ void construct_from_value(void *dst, const void *value) const
+ {
+ construct_from_value_(dst, value);
+ }
+
+ void construct_from_field(void *dst, GField field) const
+ {
+ construct_from_field_(dst, field);
+ }
+
+ const void *get_value_ptr(const void *value_or_field) const
+ {
+ return get_value_ptr_(value_or_field);
+ }
+
+ void *get_value_ptr(void *value_or_field) const
+ {
+ /* Use `const_cast` to avoid duplicating the callback for the non-const case. */
+ return const_cast<void *>(get_value_ptr_(value_or_field));
+ }
+
+ const GField *get_field_ptr(const void *value_or_field) const
+ {
+ return get_field_ptr_(value_or_field);
+ }
+
+ bool is_field(const void *value_or_field) const
+ {
+ return is_field_(value_or_field);
+ }
+
+ GField as_field(const void *value_or_field) const
+ {
+ return as_field_(value_or_field);
+ }
+};
+
} // namespace blender::fn
#define MAKE_FIELD_CPP_TYPE(DEBUG_NAME, FIELD_TYPE) \
@@ -69,4 +147,13 @@ class FieldCPPType : public CPPType {
static blender::fn::FieldCPPType cpp_type{ \
blender::fn::FieldCPPTypeParam<blender::fn::Field<FIELD_TYPE>>(), STRINGIFY(DEBUG_NAME)}; \
return cpp_type; \
+ } \
+ template<> \
+ const blender::fn::CPPType & \
+ blender::fn::CPPType::get_impl<blender::fn::ValueOrField<FIELD_TYPE>>() \
+ { \
+ static blender::fn::ValueOrFieldCPPType cpp_type{ \
+ blender::fn::FieldCPPTypeParam<blender::fn::ValueOrField<FIELD_TYPE>>(), \
+ STRINGIFY(DEBUG_NAME##OrValue)}; \
+ return cpp_type; \
}
diff --git a/source/blender/functions/FN_generic_vector_array.hh b/source/blender/functions/FN_generic_vector_array.hh
index 179e85671f8..57efa1b5ba9 100644
--- a/source/blender/functions/FN_generic_vector_array.hh
+++ b/source/blender/functions/FN_generic_vector_array.hh
@@ -125,8 +125,7 @@ template<typename T> class GVectorArray_TypedMutableRef {
void extend(const int64_t index, const VArray<T> &values)
{
- GVArray_For_VArray<T> array{values};
- this->extend(index, array);
+ vector_array_->extend(index, values);
}
MutableSpan<T> operator[](const int64_t index)
diff --git a/source/blender/functions/FN_generic_virtual_array.hh b/source/blender/functions/FN_generic_virtual_array.hh
index 8aad017e68b..b822f3a7c33 100644
--- a/source/blender/functions/FN_generic_virtual_array.hh
+++ b/source/blender/functions/FN_generic_virtual_array.hh
@@ -23,8 +23,7 @@
* the data type is only known at runtime.
*/
-#include <optional>
-
+#include "BLI_timeit.hh"
#include "BLI_virtual_array.hh"
#include "FN_generic_array.hh"
@@ -32,940 +31,845 @@
namespace blender::fn {
-template<typename T> class GVArray_Typed;
-template<typename T> class GVMutableArray_Typed;
+/* -------------------------------------------------------------------- */
+/** \name #GVArrayImpl and #GVMutableArrayImpl.
+ * \{ */
class GVArray;
+class GVArrayImpl;
class GVMutableArray;
+class GVMutableArrayImpl;
-using GVArrayPtr = std::unique_ptr<GVArray>;
-using GVMutableArrayPtr = std::unique_ptr<GVMutableArray>;
-
-/* A generically typed version of `VArray<T>`. */
-class GVArray {
+/* A generically typed version of #VArrayImpl. */
+class GVArrayImpl {
protected:
const CPPType *type_;
int64_t size_;
public:
- GVArray(const CPPType &type, const int64_t size) : type_(&type), size_(size)
- {
- BLI_assert(size_ >= 0);
- }
+ GVArrayImpl(const CPPType &type, const int64_t size);
+ virtual ~GVArrayImpl() = default;
- virtual ~GVArray() = default;
+ const CPPType &type() const;
- const CPPType &type() const
- {
- return *type_;
- }
+ int64_t size() const;
- int64_t size() const
- {
- return size_;
- }
+ virtual void get(const int64_t index, void *r_value) const;
+ virtual void get_to_uninitialized(const int64_t index, void *r_value) const = 0;
- bool is_empty() const
- {
- return size_ == 0;
- }
+ virtual bool is_span() const;
+ virtual GSpan get_internal_span() const;
- /* Copies the value at the given index into the provided storage. The `r_value` pointer is
- * expected to point to initialized memory. */
- void get(const int64_t index, void *r_value) const
- {
- BLI_assert(index >= 0);
- BLI_assert(index < size_);
- this->get_impl(index, r_value);
- }
+ virtual bool is_single() const;
+ virtual void get_internal_single(void *UNUSED(r_value)) const;
- /* Same as `get`, but `r_value` is expected to point to uninitialized memory. */
- void get_to_uninitialized(const int64_t index, void *r_value) const
- {
- BLI_assert(index >= 0);
- BLI_assert(index < size_);
- this->get_to_uninitialized_impl(index, r_value);
- }
+ virtual void materialize(const IndexMask mask, void *dst) const;
+ virtual void materialize_to_uninitialized(const IndexMask mask, void *dst) const;
- /* Returns true when the virtual array is stored as a span internally. */
- bool is_span() const
- {
- if (size_ == 0) {
- return true;
- }
- return this->is_span_impl();
- }
+ virtual bool try_assign_VArray(void *varray) const;
+ virtual bool may_have_ownership() const;
+};
- /* Returns the internally used span of the virtual array. This invokes undefined behavior is the
- * virtual array is not stored as a span internally. */
- GSpan get_internal_span() const
- {
- BLI_assert(this->is_span());
- if (size_ == 0) {
- return GSpan(*type_);
- }
- return this->get_internal_span_impl();
- }
+/* A generic version of #VMutableArrayImpl. */
+class GVMutableArrayImpl : public GVArrayImpl {
+ public:
+ GVMutableArrayImpl(const CPPType &type, const int64_t size);
- /* Returns true when the virtual array returns the same value for every index. */
- bool is_single() const
- {
- if (size_ == 1) {
- return true;
- }
- return this->is_single_impl();
- }
+ virtual void set_by_copy(const int64_t index, const void *value);
+ virtual void set_by_relocate(const int64_t index, void *value);
+ virtual void set_by_move(const int64_t index, void *value) = 0;
- /* Copies the value that is used for every element into `r_value`, which is expected to point to
- * initialized memory. This invokes undefined behavior if the virtual array would not return the
- * same value for every index. */
- void get_internal_single(void *r_value) const
- {
- BLI_assert(this->is_single());
- if (size_ == 1) {
- this->get(0, r_value);
- return;
- }
- this->get_internal_single_impl(r_value);
- }
+ virtual void set_all(const void *src);
- /* Same as `get_internal_single`, but `r_value` points to initialized memory. */
- void get_internal_single_to_uninitialized(void *r_value) const
- {
- type_->default_construct(r_value);
- this->get_internal_single(r_value);
- }
+ virtual bool try_assign_VMutableArray(void *varray) const;
+};
- void materialize(void *dst) const;
- void materialize(const IndexMask mask, void *dst) const;
+/** \} */
- void materialize_to_uninitialized(void *dst) const;
- void materialize_to_uninitialized(const IndexMask mask, void *dst) const;
+/* -------------------------------------------------------------------- */
+/** \name #GVArray and #GVMutableArray
+ * \{ */
- template<typename T> const VArray<T> *try_get_internal_varray() const
- {
- BLI_assert(type_->is<T>());
- return (const VArray<T> *)this->try_get_internal_varray_impl();
- }
+namespace detail {
+struct GVArrayAnyExtraInfo {
+ const GVArrayImpl *(*get_varray)(const void *buffer) =
+ [](const void *UNUSED(buffer)) -> const GVArrayImpl * { return nullptr; };
- /* Create a typed virtual array for this generic virtual array. */
- template<typename T> GVArray_Typed<T> typed() const
- {
- return GVArray_Typed<T>(*this);
- }
+ template<typename StorageT> static GVArrayAnyExtraInfo get();
+};
+} // namespace detail
- GVArrayPtr shallow_copy() const;
+class GVMutableArray;
+/**
+ * Utility class to reduce code duplication between #GVArray and #GVMutableArray.
+ * It pretty much follows #VArrayCommon. Don't use this class outside of this header.
+ */
+class GVArrayCommon {
protected:
- virtual void get_impl(const int64_t index, void *r_value) const;
- virtual void get_to_uninitialized_impl(const int64_t index, void *r_value) const = 0;
+ /**
+ * See #VArrayCommon for more information. The inline buffer is a bit larger here, because
+ * generic virtual array implementations often require a bit more space than typed ones.
+ */
+ using Storage = Any<detail::GVArrayAnyExtraInfo, 40, 8>;
- virtual bool is_span_impl() const;
- virtual GSpan get_internal_span_impl() const;
+ const GVArrayImpl *impl_ = nullptr;
+ Storage storage_;
- virtual bool is_single_impl() const;
- virtual void get_internal_single_impl(void *UNUSED(r_value)) const;
+ protected:
+ GVArrayCommon();
+ GVArrayCommon(const GVArrayCommon &other);
+ GVArrayCommon(GVArrayCommon &&other) noexcept;
+ GVArrayCommon(const GVArrayImpl *impl);
+ GVArrayCommon(std::shared_ptr<const GVArrayImpl> impl);
+ ~GVArrayCommon();
- virtual void materialize_impl(const IndexMask mask, void *dst) const;
- virtual void materialize_to_uninitialized_impl(const IndexMask mask, void *dst) const;
+ template<typename ImplT, typename... Args> void emplace(Args &&...args);
- virtual const void *try_get_internal_varray_impl() const;
-};
+ void copy_from(const GVArrayCommon &other);
+ void move_from(GVArrayCommon &&other) noexcept;
+
+ const GVArrayImpl *impl_from_storage() const;
-/* Similar to GVArray, but supports changing the elements in the virtual array. */
-class GVMutableArray : public GVArray {
public:
- GVMutableArray(const CPPType &type, const int64_t size) : GVArray(type, size)
- {
- }
+ const CPPType &type() const;
+ operator bool() const;
- void set_by_copy(const int64_t index, const void *value)
- {
- BLI_assert(index >= 0);
- BLI_assert(index < size_);
- this->set_by_copy_impl(index, value);
- }
+ int64_t size() const;
+ bool is_empty() const;
+ IndexRange index_range() const;
- void set_by_move(const int64_t index, void *value)
- {
- BLI_assert(index >= 0);
- BLI_assert(index < size_);
- this->set_by_move_impl(index, value);
- }
+ template<typename T> bool try_assign_VArray(VArray<T> &varray) const;
+ bool may_have_ownership() const;
- void set_by_relocate(const int64_t index, void *value)
- {
- BLI_assert(index >= 0);
- BLI_assert(index < size_);
- this->set_by_relocate_impl(index, value);
- }
+ void materialize(void *dst) const;
+ void materialize(const IndexMask mask, void *dst) const;
- GMutableSpan get_internal_span()
- {
- BLI_assert(this->is_span());
- GSpan span = static_cast<const GVArray *>(this)->get_internal_span();
- return GMutableSpan(span.type(), const_cast<void *>(span.data()), span.size());
- }
+ void materialize_to_uninitialized(void *dst) const;
+ void materialize_to_uninitialized(const IndexMask mask, void *dst) const;
- template<typename T> VMutableArray<T> *try_get_internal_mutable_varray()
- {
- BLI_assert(type_->is<T>());
- return (VMutableArray<T> *)this->try_get_internal_mutable_varray_impl();
- }
+ bool is_span() const;
+ GSpan get_internal_span() const;
- /* Create a typed virtual array for this generic virtual array. */
- template<typename T> GVMutableArray_Typed<T> typed()
- {
- return GVMutableArray_Typed<T>(*this);
- }
+ bool is_single() const;
+ void get_internal_single(void *r_value) const;
+ void get_internal_single_to_uninitialized(void *r_value) const;
- void fill(const void *value);
+ void get(const int64_t index, void *r_value) const;
+ void get_to_uninitialized(const int64_t index, void *r_value) const;
+};
- /* Copy the values from the source buffer to all elements in the virtual array. */
- void set_all(const void *src)
- {
- this->set_all_impl(src);
- }
+/** Generic version of #VArray. */
+class GVArray : public GVArrayCommon {
+ private:
+ friend GVMutableArray;
- protected:
- virtual void set_by_copy_impl(const int64_t index, const void *value);
- virtual void set_by_relocate_impl(const int64_t index, void *value);
- virtual void set_by_move_impl(const int64_t index, void *value) = 0;
+ public:
+ GVArray() = default;
- virtual void set_all_impl(const void *src);
+ GVArray(const GVArray &other);
+ GVArray(GVArray &&other) noexcept;
+ GVArray(const GVArrayImpl *impl);
+ GVArray(std::shared_ptr<const GVArrayImpl> impl);
- virtual void *try_get_internal_mutable_varray_impl();
-};
+ template<typename T> GVArray(const VArray<T> &varray);
+ template<typename T> VArray<T> typed() const;
-class GVArray_For_GSpan : public GVArray {
- protected:
- const void *data_ = nullptr;
- const int64_t element_size_;
+ template<typename ImplT, typename... Args> static GVArray For(Args &&...args);
- public:
- GVArray_For_GSpan(const GSpan span)
- : GVArray(span.type(), span.size()), data_(span.data()), element_size_(span.type().size())
- {
- }
+ static GVArray ForSingle(const CPPType &type, const int64_t size, const void *value);
+ static GVArray ForSingleRef(const CPPType &type, const int64_t size, const void *value);
+ static GVArray ForSingleDefault(const CPPType &type, const int64_t size);
+ static GVArray ForSpan(GSpan span);
+ static GVArray ForGArray(GArray<> array);
+ static GVArray ForEmpty(const CPPType &type);
- protected:
- GVArray_For_GSpan(const CPPType &type, const int64_t size)
- : GVArray(type, size), element_size_(type.size())
- {
- }
+ GVArray slice(IndexRange slice) const;
- void get_impl(const int64_t index, void *r_value) const override;
- void get_to_uninitialized_impl(const int64_t index, void *r_value) const override;
+ GVArray &operator=(const GVArray &other);
+ GVArray &operator=(GVArray &&other) noexcept;
- bool is_span_impl() const override;
- GSpan get_internal_span_impl() const override;
+ const GVArrayImpl *get_implementation() const
+ {
+ return impl_;
+ }
};
-class GVArray_For_Empty : public GVArray {
+/** Generic version of #VMutableArray. */
+class GVMutableArray : public GVArrayCommon {
public:
- GVArray_For_Empty(const CPPType &type) : GVArray(type, 0)
- {
- }
+ GVMutableArray() = default;
+ GVMutableArray(const GVMutableArray &other);
+ GVMutableArray(GVMutableArray &&other) noexcept;
+ GVMutableArray(GVMutableArrayImpl *impl);
+ GVMutableArray(std::shared_ptr<GVMutableArrayImpl> impl);
- protected:
- void get_to_uninitialized_impl(const int64_t UNUSED(index), void *UNUSED(r_value)) const override
- {
- BLI_assert(false);
- }
-};
+ template<typename T> GVMutableArray(const VMutableArray<T> &varray);
+ template<typename T> VMutableArray<T> typed() const;
-class GVMutableArray_For_GMutableSpan : public GVMutableArray {
- protected:
- void *data_ = nullptr;
- const int64_t element_size_;
+ template<typename ImplT, typename... Args> static GVMutableArray For(Args &&...args);
- public:
- GVMutableArray_For_GMutableSpan(const GMutableSpan span)
- : GVMutableArray(span.type(), span.size()),
- data_(span.data()),
- element_size_(span.type().size())
- {
- }
+ static GVMutableArray ForSpan(GMutableSpan span);
- protected:
- GVMutableArray_For_GMutableSpan(const CPPType &type, const int64_t size)
- : GVMutableArray(type, size), element_size_(type.size())
- {
- }
+ operator GVArray() const &;
+ operator GVArray() &&noexcept;
- void get_impl(const int64_t index, void *r_value) const override;
- void get_to_uninitialized_impl(const int64_t index, void *r_value) const override;
+ GVMutableArray &operator=(const GVMutableArray &other);
+ GVMutableArray &operator=(GVMutableArray &&other) noexcept;
- void set_by_copy_impl(const int64_t index, const void *value) override;
- void set_by_move_impl(const int64_t index, void *value) override;
- void set_by_relocate_impl(const int64_t index, void *value) override;
+ GMutableSpan get_internal_span() const;
- bool is_span_impl() const override;
- GSpan get_internal_span_impl() const override;
-};
+ template<typename T> bool try_assign_VMutableArray(VMutableArray<T> &varray) const;
-/* Generic virtual array where each element has the same value. The value is not owned. */
-class GVArray_For_SingleValueRef : public GVArray {
- protected:
- const void *value_ = nullptr;
+ void set_by_copy(const int64_t index, const void *value);
+ void set_by_move(const int64_t index, void *value);
+ void set_by_relocate(const int64_t index, void *value);
- public:
- GVArray_For_SingleValueRef(const CPPType &type, const int64_t size, const void *value)
- : GVArray(type, size), value_(value)
- {
- }
+ void fill(const void *value);
+ void set_all(const void *src);
- protected:
- GVArray_For_SingleValueRef(const CPPType &type, const int64_t size) : GVArray(type, size)
- {
- }
+ GVMutableArrayImpl *get_implementation() const;
- void get_impl(const int64_t index, void *r_value) const override;
- void get_to_uninitialized_impl(const int64_t index, void *r_value) const override;
+ private:
+ GVMutableArrayImpl *get_impl() const;
+};
- bool is_span_impl() const override;
- GSpan get_internal_span_impl() const override;
+/** \} */
- bool is_single_impl() const override;
- void get_internal_single_impl(void *r_value) const override;
+/* -------------------------------------------------------------------- */
+/** \name #GVArray_GSpan and #GVMutableArray_GSpan.
+ * \{ */
+
+/* A generic version of VArray_Span. */
+class GVArray_GSpan : public GSpan {
+ private:
+ GVArray varray_;
+ void *owned_data_ = nullptr;
+
+ public:
+ GVArray_GSpan(GVArray varray);
+ ~GVArray_GSpan();
};
-/* Same as GVArray_For_SingleValueRef, but the value is owned. */
-class GVArray_For_SingleValue : public GVArray_For_SingleValueRef {
+/* A generic version of VMutableArray_Span. */
+class GVMutableArray_GSpan : public GMutableSpan {
+ private:
+ GVMutableArray varray_;
+ void *owned_data_ = nullptr;
+ bool save_has_been_called_ = false;
+ bool show_not_saved_warning_ = true;
+
public:
- GVArray_For_SingleValue(const CPPType &type, const int64_t size, const void *value);
- ~GVArray_For_SingleValue();
+ GVMutableArray_GSpan(GVMutableArray varray, bool copy_values_to_span = true);
+ ~GVMutableArray_GSpan();
+
+ void save();
+ void disable_not_applied_warning();
};
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Conversions between generic and typed virtual arrays.
+ * \{ */
+
/* Used to convert a typed virtual array into a generic one. */
-template<typename T> class GVArray_For_VArray : public GVArray {
+template<typename T> class GVArrayImpl_For_VArray : public GVArrayImpl {
protected:
- const VArray<T> *varray_ = nullptr;
+ VArray<T> varray_;
public:
- GVArray_For_VArray(const VArray<T> &varray)
- : GVArray(CPPType::get<T>(), varray.size()), varray_(&varray)
+ GVArrayImpl_For_VArray(VArray<T> varray)
+ : GVArrayImpl(CPPType::get<T>(), varray.size()), varray_(std::move(varray))
{
}
protected:
- GVArray_For_VArray(const int64_t size) : GVArray(CPPType::get<T>(), size)
+ void get(const int64_t index, void *r_value) const override
{
+ *(T *)r_value = varray_[index];
}
- void get_impl(const int64_t index, void *r_value) const override
+ void get_to_uninitialized(const int64_t index, void *r_value) const override
{
- *(T *)r_value = varray_->get(index);
+ new (r_value) T(varray_[index]);
}
- void get_to_uninitialized_impl(const int64_t index, void *r_value) const override
+ bool is_span() const override
{
- new (r_value) T(varray_->get(index));
+ return varray_.is_span();
}
- bool is_span_impl() const override
+ GSpan get_internal_span() const override
{
- return varray_->is_span();
+ return GSpan(varray_.get_internal_span());
}
- GSpan get_internal_span_impl() const override
+ bool is_single() const override
{
- return GSpan(varray_->get_internal_span());
+ return varray_.is_single();
}
- bool is_single_impl() const override
+ void get_internal_single(void *r_value) const override
{
- return varray_->is_single();
+ *(T *)r_value = varray_.get_internal_single();
}
- void get_internal_single_impl(void *r_value) const override
+ void materialize(const IndexMask mask, void *dst) const override
{
- *(T *)r_value = varray_->get_internal_single();
+ varray_.materialize(mask, MutableSpan((T *)dst, mask.min_array_size()));
}
- void materialize_impl(const IndexMask mask, void *dst) const override
+ void materialize_to_uninitialized(const IndexMask mask, void *dst) const override
{
- varray_->materialize(mask, MutableSpan((T *)dst, mask.min_array_size()));
+ varray_.materialize_to_uninitialized(mask, MutableSpan((T *)dst, mask.min_array_size()));
}
- void materialize_to_uninitialized_impl(const IndexMask mask, void *dst) const override
+ bool try_assign_VArray(void *varray) const override
{
- varray_->materialize_to_uninitialized(mask, MutableSpan((T *)dst, mask.min_array_size()));
+ *(VArray<T> *)varray = varray_;
+ return true;
}
- const void *try_get_internal_varray_impl() const override
- {
- return varray_;
- }
-};
-
-class GVArray_For_GArray : public GVArray_For_GSpan {
- protected:
- GArray<> array_;
-
- public:
- GVArray_For_GArray(GArray<> array) : GVArray_For_GSpan(array.as_span()), array_(std::move(array))
+ bool may_have_ownership() const override
{
+ return varray_.may_have_ownership();
}
};
/* Used to convert any generic virtual array into a typed one. */
-template<typename T> class VArray_For_GVArray : public VArray<T> {
+template<typename T> class VArrayImpl_For_GVArray : public VArrayImpl<T> {
protected:
- const GVArray *varray_ = nullptr;
+ GVArray varray_;
public:
- VArray_For_GVArray(const GVArray &varray) : VArray<T>(varray.size()), varray_(&varray)
+ VArrayImpl_For_GVArray(GVArray varray) : VArrayImpl<T>(varray.size()), varray_(std::move(varray))
{
- BLI_assert(varray_->type().template is<T>());
+ BLI_assert(varray_);
+ BLI_assert(varray_.type().template is<T>());
}
protected:
- VArray_For_GVArray(const int64_t size) : VArray<T>(size)
- {
- }
-
- T get_impl(const int64_t index) const override
+ T get(const int64_t index) const override
{
T value;
- varray_->get(index, &value);
+ varray_.get(index, &value);
return value;
}
- bool is_span_impl() const override
+ bool is_span() const override
{
- return varray_->is_span();
+ return varray_.is_span();
}
- Span<T> get_internal_span_impl() const override
+ Span<T> get_internal_span() const override
{
- return varray_->get_internal_span().template typed<T>();
+ return varray_.get_internal_span().template typed<T>();
}
- bool is_single_impl() const override
+ bool is_single() const override
{
- return varray_->is_single();
+ return varray_.is_single();
}
- T get_internal_single_impl() const override
+ T get_internal_single() const override
{
T value;
- varray_->get_internal_single(&value);
+ varray_.get_internal_single(&value);
return value;
}
-};
-
-/* Used to convert an generic mutable virtual array into a typed one. */
-template<typename T> class VMutableArray_For_GVMutableArray : public VMutableArray<T> {
- protected:
- GVMutableArray *varray_ = nullptr;
-
- public:
- VMutableArray_For_GVMutableArray(GVMutableArray &varray)
- : VMutableArray<T>(varray.size()), varray_(&varray)
- {
- BLI_assert(varray.type().template is<T>());
- }
-
- VMutableArray_For_GVMutableArray(const int64_t size) : VMutableArray<T>(size)
- {
- }
-
- private:
- T get_impl(const int64_t index) const override
- {
- T value;
- varray_->get(index, &value);
- return value;
- }
-
- void set_impl(const int64_t index, T value) override
- {
- varray_->set_by_relocate(index, &value);
- }
-
- bool is_span_impl() const override
- {
- return varray_->is_span();
- }
- Span<T> get_internal_span_impl() const override
+ bool try_assign_GVArray(GVArray &varray) const override
{
- return varray_->get_internal_span().template typed<T>();
+ varray = varray_;
+ return true;
}
- bool is_single_impl() const override
+ bool may_have_ownership() const override
{
- return varray_->is_single();
- }
-
- T get_internal_single_impl() const override
- {
- T value;
- varray_->get_internal_single(&value);
- return value;
+ return varray_.may_have_ownership();
}
};
/* Used to convert any typed virtual mutable array into a generic one. */
-template<typename T> class GVMutableArray_For_VMutableArray : public GVMutableArray {
+template<typename T> class GVMutableArrayImpl_For_VMutableArray : public GVMutableArrayImpl {
protected:
- VMutableArray<T> *varray_ = nullptr;
+ VMutableArray<T> varray_;
public:
- GVMutableArray_For_VMutableArray(VMutableArray<T> &varray)
- : GVMutableArray(CPPType::get<T>(), varray.size()), varray_(&varray)
+ GVMutableArrayImpl_For_VMutableArray(VMutableArray<T> varray)
+ : GVMutableArrayImpl(CPPType::get<T>(), varray.size()), varray_(std::move(varray))
{
}
protected:
- GVMutableArray_For_VMutableArray(const int64_t size) : GVMutableArray(CPPType::get<T>(), size)
+ void get(const int64_t index, void *r_value) const override
{
+ *(T *)r_value = varray_[index];
}
- void get_impl(const int64_t index, void *r_value) const override
+ void get_to_uninitialized(const int64_t index, void *r_value) const override
{
- *(T *)r_value = varray_->get(index);
+ new (r_value) T(varray_[index]);
}
- void get_to_uninitialized_impl(const int64_t index, void *r_value) const override
+ bool is_span() const override
{
- new (r_value) T(varray_->get(index));
+ return varray_.is_span();
}
- bool is_span_impl() const override
+ GSpan get_internal_span() const override
{
- return varray_->is_span();
- }
-
- GSpan get_internal_span_impl() const override
- {
- Span<T> span = varray_->get_internal_span();
+ Span<T> span = varray_.get_internal_span();
return span;
}
- bool is_single_impl() const override
+ bool is_single() const override
{
- return varray_->is_single();
+ return varray_.is_single();
}
- void get_internal_single_impl(void *r_value) const override
+ void get_internal_single(void *r_value) const override
{
- *(T *)r_value = varray_->get_internal_single();
+ *(T *)r_value = varray_.get_internal_single();
}
- void set_by_copy_impl(const int64_t index, const void *value) override
+ void set_by_copy(const int64_t index, const void *value) override
{
const T &value_ = *(const T *)value;
- varray_->set(index, value_);
+ varray_.set(index, value_);
}
- void set_by_relocate_impl(const int64_t index, void *value) override
+ void set_by_relocate(const int64_t index, void *value) override
{
T &value_ = *(T *)value;
- varray_->set(index, std::move(value_));
+ varray_.set(index, std::move(value_));
value_.~T();
}
- void set_by_move_impl(const int64_t index, void *value) override
+ void set_by_move(const int64_t index, void *value) override
{
T &value_ = *(T *)value;
- varray_->set(index, std::move(value_));
+ varray_.set(index, std::move(value_));
}
- void set_all_impl(const void *src) override
+ void set_all(const void *src) override
{
- varray_->set_all(Span((T *)src, size_));
+ varray_.set_all(Span((T *)src, size_));
}
- void materialize_impl(const IndexMask mask, void *dst) const override
+ void materialize(const IndexMask mask, void *dst) const override
{
- varray_->materialize(mask, MutableSpan((T *)dst, mask.min_array_size()));
+ varray_.materialize(mask, MutableSpan((T *)dst, mask.min_array_size()));
}
- void materialize_to_uninitialized_impl(const IndexMask mask, void *dst) const override
+ void materialize_to_uninitialized(const IndexMask mask, void *dst) const override
{
- varray_->materialize_to_uninitialized(mask, MutableSpan((T *)dst, mask.min_array_size()));
+ varray_.materialize_to_uninitialized(mask, MutableSpan((T *)dst, mask.min_array_size()));
}
- const void *try_get_internal_varray_impl() const override
+ bool try_assign_VArray(void *varray) const override
{
- return (const VArray<T> *)varray_;
+ *(VArray<T> *)varray = varray_;
+ return true;
}
- void *try_get_internal_mutable_varray_impl() override
+ bool try_assign_VMutableArray(void *varray) const override
{
- return varray_;
+ *(VMutableArray<T> *)varray = varray_;
+ return true;
}
-};
-
-/* A generic version of VArray_Span. */
-class GVArray_GSpan : public GSpan {
- private:
- const GVArray &varray_;
- void *owned_data_ = nullptr;
-
- public:
- GVArray_GSpan(const GVArray &varray);
- ~GVArray_GSpan();
-};
-
-/* A generic version of VMutableArray_Span. */
-class GVMutableArray_GSpan : public GMutableSpan {
- private:
- GVMutableArray &varray_;
- void *owned_data_ = nullptr;
- bool save_has_been_called_ = false;
- bool show_not_saved_warning_ = true;
-
- public:
- GVMutableArray_GSpan(GVMutableArray &varray, bool copy_values_to_span = true);
- ~GVMutableArray_GSpan();
-
- void save();
- void disable_not_applied_warning();
-};
-
-/* Similar to GVArray_GSpan, but the resulting span is typed. */
-template<typename T> class GVArray_Span : public Span<T> {
- private:
- GVArray_GSpan varray_gspan_;
- public:
- GVArray_Span(const GVArray &varray) : varray_gspan_(varray)
+ bool may_have_ownership() const override
{
- BLI_assert(varray.type().is<T>());
- this->data_ = (const T *)varray_gspan_.data();
- this->size_ = varray_gspan_.size();
+ return varray_.may_have_ownership();
}
};
-template<typename T> class GVArray_For_OwnedVArray : public GVArray_For_VArray<T> {
- private:
- VArrayPtr<T> owned_varray_;
+/* Used to convert an generic mutable virtual array into a typed one. */
+template<typename T> class VMutableArrayImpl_For_GVMutableArray : public VMutableArrayImpl<T> {
+ protected:
+ GVMutableArray varray_;
public:
- /* Takes ownership of varray and passes a reference to the base class. */
- GVArray_For_OwnedVArray(VArrayPtr<T> varray)
- : GVArray_For_VArray<T>(*varray), owned_varray_(std::move(varray))
+ VMutableArrayImpl_For_GVMutableArray(GVMutableArray varray)
+ : VMutableArrayImpl<T>(varray.size()), varray_(varray)
{
+ BLI_assert(varray_);
+ BLI_assert(varray_.type().template is<T>());
}
-};
-template<typename T> class VArray_For_OwnedGVArray : public VArray_For_GVArray<T> {
private:
- GVArrayPtr owned_varray_;
-
- public:
- /* Takes ownership of varray and passes a reference to the base class. */
- VArray_For_OwnedGVArray(GVArrayPtr varray)
- : VArray_For_GVArray<T>(*varray), owned_varray_(std::move(varray))
+ T get(const int64_t index) const override
{
+ T value;
+ varray_.get(index, &value);
+ return value;
}
-};
-template<typename T>
-class GVMutableArray_For_OwnedVMutableArray : public GVMutableArray_For_VMutableArray<T> {
- private:
- VMutableArrayPtr<T> owned_varray_;
-
- public:
- /* Takes ownership of varray and passes a reference to the base class. */
- GVMutableArray_For_OwnedVMutableArray(VMutableArrayPtr<T> varray)
- : GVMutableArray_For_VMutableArray<T>(*varray), owned_varray_(std::move(varray))
+ void set(const int64_t index, T value) override
{
+ varray_.set_by_relocate(index, &value);
}
-};
-template<typename T>
-class VMutableArray_For_OwnedGVMutableArray : public VMutableArray_For_GVMutableArray<T> {
- private:
- GVMutableArrayPtr owned_varray_;
-
- public:
- /* Takes ownership of varray and passes a reference to the base class. */
- VMutableArray_For_OwnedGVMutableArray(GVMutableArrayPtr varray)
- : VMutableArray_For_GVMutableArray<T>(*varray), owned_varray_(std::move(varray))
+ bool is_span() const override
{
+ return varray_.is_span();
}
-};
-
-/* Utility to embed a typed virtual array into a generic one. This avoids one allocation and give
- * the compiler more opportunity to optimize the generic virtual array. */
-template<typename T, typename VArrayT>
-class GVArray_For_EmbeddedVArray : public GVArray_For_VArray<T> {
- private:
- VArrayT embedded_varray_;
- public:
- template<typename... Args>
- GVArray_For_EmbeddedVArray(const int64_t size, Args &&...args)
- : GVArray_For_VArray<T>(size), embedded_varray_(std::forward<Args>(args)...)
+ Span<T> get_internal_span() const override
{
- this->varray_ = &embedded_varray_;
+ return varray_.get_internal_span().template typed<T>();
}
-};
-/* Same as GVArray_For_EmbeddedVArray, but for mutable virtual arrays. */
-template<typename T, typename VMutableArrayT>
-class GVMutableArray_For_EmbeddedVMutableArray : public GVMutableArray_For_VMutableArray<T> {
- private:
- VMutableArrayT embedded_varray_;
-
- public:
- template<typename... Args>
- GVMutableArray_For_EmbeddedVMutableArray(const int64_t size, Args &&...args)
- : GVMutableArray_For_VMutableArray<T>(size), embedded_varray_(std::forward<Args>(args)...)
+ bool is_single() const override
{
- this->varray_ = &embedded_varray_;
+ return varray_.is_single();
}
-};
-/* Same as VArray_For_ArrayContainer, but for a generic virtual array. */
-template<typename Container, typename T = typename Container::value_type>
-class GVArray_For_ArrayContainer
- : public GVArray_For_EmbeddedVArray<T, VArray_For_ArrayContainer<Container, T>> {
- public:
- GVArray_For_ArrayContainer(Container container)
- : GVArray_For_EmbeddedVArray<T, VArray_For_ArrayContainer<Container, T>>(
- container.size(), std::move(container))
+ T get_internal_single() const override
{
+ T value;
+ varray_.get_internal_single(&value);
+ return value;
}
-};
-/* Same as VArray_For_DerivedSpan, but for a generic virtual array. */
-template<typename StructT, typename ElemT, ElemT (*GetFunc)(const StructT &)>
-class GVArray_For_DerivedSpan
- : public GVArray_For_EmbeddedVArray<ElemT, VArray_For_DerivedSpan<StructT, ElemT, GetFunc>> {
- public:
- GVArray_For_DerivedSpan(const Span<StructT> data)
- : GVArray_For_EmbeddedVArray<ElemT, VArray_For_DerivedSpan<StructT, ElemT, GetFunc>>(
- data.size(), data)
+ bool try_assign_GVArray(GVArray &varray) const override
{
+ varray = varray_;
+ return true;
}
-};
-/* Same as VMutableArray_For_DerivedSpan, but for a generic virtual array. */
-template<typename StructT,
- typename ElemT,
- ElemT (*GetFunc)(const StructT &),
- void (*SetFunc)(StructT &, ElemT)>
-class GVMutableArray_For_DerivedSpan
- : public GVMutableArray_For_EmbeddedVMutableArray<
- ElemT,
- VMutableArray_For_DerivedSpan<StructT, ElemT, GetFunc, SetFunc>> {
- public:
- GVMutableArray_For_DerivedSpan(const MutableSpan<StructT> data)
- : GVMutableArray_For_EmbeddedVMutableArray<
- ElemT,
- VMutableArray_For_DerivedSpan<StructT, ElemT, GetFunc, SetFunc>>(data.size(), data)
+ bool try_assign_GVMutableArray(GVMutableArray &varray) const override
{
+ varray = varray_;
+ return true;
}
-};
-/* Same as VArray_For_Span, but for a generic virtual array. */
-template<typename T>
-class GVArray_For_Span : public GVArray_For_EmbeddedVArray<T, VArray_For_Span<T>> {
- public:
- GVArray_For_Span(const Span<T> data)
- : GVArray_For_EmbeddedVArray<T, VArray_For_Span<T>>(data.size(), data)
+ bool may_have_ownership() const override
{
+ return varray_.may_have_ownership();
}
};
-/* Same as VMutableArray_For_MutableSpan, but for a generic virtual array. */
-template<typename T>
-class GVMutableArray_For_MutableSpan
- : public GVMutableArray_For_EmbeddedVMutableArray<T, VMutableArray_For_MutableSpan<T>> {
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name #GVArrayImpl_For_GSpan and #GVMutableArrayImpl_For_GMutableSpan.
+ * \{ */
+
+class GVArrayImpl_For_GSpan : public GVArrayImpl {
+ protected:
+ const void *data_ = nullptr;
+ const int64_t element_size_;
+
public:
- GVMutableArray_For_MutableSpan(const MutableSpan<T> data)
- : GVMutableArray_For_EmbeddedVMutableArray<T, VMutableArray_For_MutableSpan<T>>(data.size(),
- data)
- {
- }
+ GVArrayImpl_For_GSpan(const GSpan span);
+
+ protected:
+ GVArrayImpl_For_GSpan(const CPPType &type, const int64_t size);
+
+ void get(const int64_t index, void *r_value) const override;
+ void get_to_uninitialized(const int64_t index, void *r_value) const override;
+
+ bool is_span() const override;
+ GSpan get_internal_span() const override;
};
-/**
- * Utility class to create the "best" typed virtual array for a given generic virtual array.
- * In most cases we don't just want to use VArray_For_GVArray, because it adds an additional
- * indirection on element-access that can be avoided in many cases (e.g. when the virtual array is
- * just a span or single value).
- *
- * This is not a virtual array itself, but is used to get a virtual array.
- */
-template<typename T> class GVArray_Typed {
- private:
- const VArray<T> *varray_;
- /* Of these optional virtual arrays, at most one is constructed at any time. */
- std::optional<VArray_For_Span<T>> varray_span_;
- std::optional<VArray_For_Single<T>> varray_single_;
- std::optional<VArray_For_GVArray<T>> varray_any_;
- GVArrayPtr owned_gvarray_;
+class GVMutableArrayImpl_For_GMutableSpan : public GVMutableArrayImpl {
+ protected:
+ void *data_ = nullptr;
+ const int64_t element_size_;
public:
- explicit GVArray_Typed(const GVArray &gvarray)
- {
- BLI_assert(gvarray.type().is<T>());
- if (gvarray.is_span()) {
- const GSpan span = gvarray.get_internal_span();
- varray_span_.emplace(span.typed<T>());
- varray_ = &*varray_span_;
- }
- else if (gvarray.is_single()) {
- T single_value;
- gvarray.get_internal_single(&single_value);
- varray_single_.emplace(single_value, gvarray.size());
- varray_ = &*varray_single_;
- }
- else if (const VArray<T> *internal_varray = gvarray.try_get_internal_varray<T>()) {
- varray_ = internal_varray;
- }
- else {
- varray_any_.emplace(gvarray);
- varray_ = &*varray_any_;
- }
- }
+ GVMutableArrayImpl_For_GMutableSpan(const GMutableSpan span);
- /* Same as the constructor above, but also takes ownership of the passed in virtual array. */
- explicit GVArray_Typed(GVArrayPtr gvarray) : GVArray_Typed(*gvarray)
- {
- owned_gvarray_ = std::move(gvarray);
- }
+ protected:
+ GVMutableArrayImpl_For_GMutableSpan(const CPPType &type, const int64_t size);
- const VArray<T> &operator*() const
- {
- return *varray_;
- }
+ public:
+ void get(const int64_t index, void *r_value) const override;
+ void get_to_uninitialized(const int64_t index, void *r_value) const override;
- const VArray<T> *operator->() const
- {
- return varray_;
- }
+ void set_by_copy(const int64_t index, const void *value) override;
+ void set_by_move(const int64_t index, void *value) override;
+ void set_by_relocate(const int64_t index, void *value) override;
- /* Support implicit cast to the typed virtual array for convenience when `varray->typed<T>()` is
- * used within an expression. */
- operator const VArray<T> &() const
- {
- return *varray_;
- }
+ bool is_span() const override;
+ GSpan get_internal_span() const override;
+};
- T operator[](const int64_t index) const
- {
- return varray_->get(index);
- }
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Inline methods for #GVArrayImpl.
+ * \{ */
+
+inline GVArrayImpl::GVArrayImpl(const CPPType &type, const int64_t size)
+ : type_(&type), size_(size)
+{
+ BLI_assert(size_ >= 0);
+}
+
+inline const CPPType &GVArrayImpl::type() const
+{
+ return *type_;
+}
+
+inline int64_t GVArrayImpl::size() const
+{
+ return size_;
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Inline methods for #GVMutableArrayImpl.
+ * \{ */
+
+inline void GVMutableArray::set_by_copy(const int64_t index, const void *value)
+{
+ BLI_assert(index >= 0);
+ BLI_assert(index < this->size());
+ this->get_impl()->set_by_copy(index, value);
+}
+
+inline void GVMutableArray::set_by_move(const int64_t index, void *value)
+{
+ BLI_assert(index >= 0);
+ BLI_assert(index < this->size());
+ this->get_impl()->set_by_move(index, value);
+}
+
+inline void GVMutableArray::set_by_relocate(const int64_t index, void *value)
+{
+ BLI_assert(index >= 0);
+ BLI_assert(index < this->size());
+ this->get_impl()->set_by_relocate(index, value);
+}
- int64_t size() const
- {
- return varray_->size();
+template<typename T>
+inline bool GVMutableArray::try_assign_VMutableArray(VMutableArray<T> &varray) const
+{
+ BLI_assert(impl_->type().is<T>());
+ return this->get_impl()->try_assign_VMutableArray(&varray);
+}
+
+inline GVMutableArrayImpl *GVMutableArray::get_impl() const
+{
+ return (GVMutableArrayImpl *)impl_;
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Inline methods for #GVArrayCommon.
+ * \{ */
+
+template<typename ImplT, typename... Args> inline void GVArrayCommon::emplace(Args &&...args)
+{
+ static_assert(std::is_base_of_v<GVArrayImpl, ImplT>);
+ if constexpr (std::is_copy_constructible_v<ImplT> && Storage::template is_inline_v<ImplT>) {
+ impl_ = &storage_.template emplace<ImplT>(std::forward<Args>(args)...);
+ }
+ else {
+ std::shared_ptr<const GVArrayImpl> ptr = std::make_shared<ImplT>(std::forward<Args>(args)...);
+ impl_ = &*ptr;
+ storage_ = std::move(ptr);
+ }
+}
+
+/* Copies the value at the given index into the provided storage. The `r_value` pointer is
+ * expected to point to initialized memory. */
+inline void GVArrayCommon::get(const int64_t index, void *r_value) const
+{
+ BLI_assert(index >= 0);
+ BLI_assert(index < this->size());
+ impl_->get(index, r_value);
+}
+
+/* Same as `get`, but `r_value` is expected to point to uninitialized memory. */
+inline void GVArrayCommon::get_to_uninitialized(const int64_t index, void *r_value) const
+{
+ BLI_assert(index >= 0);
+ BLI_assert(index < this->size());
+ impl_->get_to_uninitialized(index, r_value);
+}
+
+template<typename T> inline bool GVArrayCommon::try_assign_VArray(VArray<T> &varray) const
+{
+ BLI_assert(impl_->type().is<T>());
+ return impl_->try_assign_VArray(&varray);
+}
+
+inline const CPPType &GVArrayCommon::type() const
+{
+ return impl_->type();
+}
+
+inline GVArrayCommon::operator bool() const
+{
+ return impl_ != nullptr;
+}
+
+inline int64_t GVArrayCommon::size() const
+{
+ if (impl_ == nullptr) {
+ return 0;
+ }
+ return impl_->size();
+}
+
+inline bool GVArrayCommon::is_empty() const
+{
+ return this->size() == 0;
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Inline methods for #GVArray.
+ * \{ */
+
+namespace detail {
+template<typename StorageT> inline GVArrayAnyExtraInfo GVArrayAnyExtraInfo::get()
+{
+ static_assert(std::is_base_of_v<GVArrayImpl, StorageT> ||
+ std::is_same_v<StorageT, const GVArrayImpl *> ||
+ std::is_same_v<StorageT, std::shared_ptr<const GVArrayImpl>>);
+
+ if constexpr (std::is_base_of_v<GVArrayImpl, StorageT>) {
+ return {[](const void *buffer) {
+ return static_cast<const GVArrayImpl *>((const StorageT *)buffer);
+ }};
+ }
+ else if constexpr (std::is_same_v<StorageT, const GVArrayImpl *>) {
+ return {[](const void *buffer) { return *(const StorageT *)buffer; }};
+ }
+ else if constexpr (std::is_same_v<StorageT, std::shared_ptr<const GVArrayImpl>>) {
+ return {[](const void *buffer) { return ((const StorageT *)buffer)->get(); }};
+ }
+ else {
+ BLI_assert_unreachable();
+ return {};
+ }
+}
+} // namespace detail
+
+template<typename ImplT, typename... Args> inline GVArray GVArray::For(Args &&...args)
+{
+ static_assert(std::is_base_of_v<GVArrayImpl, ImplT>);
+ GVArray varray;
+ varray.template emplace<ImplT>(std::forward<Args>(args)...);
+ return varray;
+}
+
+template<typename T> inline GVArray::GVArray(const VArray<T> &varray)
+{
+ if (!varray) {
+ return;
+ }
+ if (varray.try_assign_GVArray(*this)) {
+ return;
+ }
+ /* Need to check this before the span/single special cases, because otherwise we might loose
+ * ownership to the referenced data when #varray goes out of scope. */
+ if (varray.may_have_ownership()) {
+ *this = GVArray::For<GVArrayImpl_For_VArray<T>>(varray);
+ }
+ else if (varray.is_span()) {
+ Span<T> data = varray.get_internal_span();
+ *this = GVArray::ForSpan(data);
+ }
+ else if (varray.is_single()) {
+ T value = varray.get_internal_single();
+ *this = GVArray::ForSingle(CPPType::get<T>(), varray.size(), &value);
+ }
+ else {
+ *this = GVArray::For<GVArrayImpl_For_VArray<T>>(varray);
+ }
+}
+
+template<typename T> inline VArray<T> GVArray::typed() const
+{
+ if (!*this) {
+ return {};
+ }
+ BLI_assert(impl_->type().is<T>());
+ VArray<T> varray;
+ if (this->try_assign_VArray(varray)) {
+ return varray;
+ }
+ if (this->may_have_ownership()) {
+ return VArray<T>::template For<VArrayImpl_For_GVArray<T>>(*this);
+ }
+ if (this->is_span()) {
+ const Span<T> span = this->get_internal_span().typed<T>();
+ return VArray<T>::ForSpan(span);
}
-
- IndexRange index_range() const
- {
- return IndexRange(this->size());
+ if (this->is_single()) {
+ T value;
+ this->get_internal_single(&value);
+ return VArray<T>::ForSingle(value, this->size());
}
-};
+ return VArray<T>::template For<VArrayImpl_For_GVArray<T>>(*this);
+}
-/* Same as GVArray_Typed, but for mutable virtual arrays. */
-template<typename T> class GVMutableArray_Typed {
- private:
- VMutableArray<T> *varray_;
- std::optional<VMutableArray_For_MutableSpan<T>> varray_span_;
- std::optional<VMutableArray_For_GVMutableArray<T>> varray_any_;
- GVMutableArrayPtr owned_gvarray_;
+/** \} */
- public:
- explicit GVMutableArray_Typed(GVMutableArray &gvarray)
- {
- BLI_assert(gvarray.type().is<T>());
- if (gvarray.is_span()) {
- const GMutableSpan span = gvarray.get_internal_span();
- varray_span_.emplace(span.typed<T>());
- varray_ = &*varray_span_;
- }
- else if (VMutableArray<T> *internal_varray = gvarray.try_get_internal_mutable_varray<T>()) {
- varray_ = internal_varray;
- }
- else {
- varray_any_.emplace(gvarray);
- varray_ = &*varray_any_;
- }
- }
+/* -------------------------------------------------------------------- */
+/** \name Inline methods for #GVMutableArray.
+ * \{ */
- explicit GVMutableArray_Typed(GVMutableArrayPtr gvarray) : GVMutableArray_Typed(*gvarray)
- {
- owned_gvarray_ = std::move(gvarray);
- }
+template<typename ImplT, typename... Args>
+inline GVMutableArray GVMutableArray::For(Args &&...args)
+{
+ static_assert(std::is_base_of_v<GVMutableArrayImpl, ImplT>);
+ GVMutableArray varray;
+ varray.emplace<ImplT>(std::forward<Args>(args)...);
+ return varray;
+}
- VMutableArray<T> &operator*()
- {
- return *varray_;
+template<typename T> inline GVMutableArray::GVMutableArray(const VMutableArray<T> &varray)
+{
+ if (!varray) {
+ return;
}
-
- VMutableArray<T> *operator->()
- {
- return varray_;
+ if (varray.try_assign_GVMutableArray(*this)) {
+ return;
}
-
- operator VMutableArray<T> &()
- {
- return *varray_;
+ if (varray.may_have_ownership()) {
+ *this = GVMutableArray::For<GVMutableArrayImpl_For_VMutableArray<T>>(varray);
}
-
- T operator[](const int64_t index) const
- {
- return varray_->get(index);
+ else if (varray.is_span()) {
+ MutableSpan<T> data = varray.get_internal_span();
+ *this = GVMutableArray::ForSpan(data);
}
-
- int64_t size() const
- {
- return varray_->size();
+ else {
+ *this = GVMutableArray::For<GVMutableArrayImpl_For_VMutableArray<T>>(varray);
}
-};
-
-class GVArray_For_SlicedGVArray : public GVArray {
- protected:
- const GVArray &varray_;
- int64_t offset_;
+}
- public:
- GVArray_For_SlicedGVArray(const GVArray &varray, const IndexRange slice)
- : GVArray(varray.type(), slice.size()), varray_(varray), offset_(slice.start())
- {
- BLI_assert(slice.one_after_last() <= varray.size());
+template<typename T> inline VMutableArray<T> GVMutableArray::typed() const
+{
+ if (!*this) {
+ return {};
}
-
- /* TODO: Add #materialize method. */
- void get_impl(const int64_t index, void *r_value) const override;
- void get_to_uninitialized_impl(const int64_t index, void *r_value) const override;
-};
-
-/**
- * Utility class to create the "best" sliced virtual array.
- */
-class GVArray_Slice {
- private:
- const GVArray *varray_;
- /* Of these optional virtual arrays, at most one is constructed at any time. */
- std::optional<GVArray_For_GSpan> varray_span_;
- std::optional<GVArray_For_SlicedGVArray> varray_any_;
-
- public:
- GVArray_Slice(const GVArray &varray, const IndexRange slice);
-
- const GVArray &operator*()
- {
- return *varray_;
+ BLI_assert(this->type().is<T>());
+ VMutableArray<T> varray;
+ if (this->try_assign_VMutableArray(varray)) {
+ return varray;
}
-
- const GVArray *operator->()
- {
- return varray_;
+ if (this->may_have_ownership()) {
+ return VMutableArray<T>::template For<VMutableArrayImpl_For_GVMutableArray<T>>(*this);
}
-
- operator const GVArray &()
- {
- return *varray_;
+ if (this->is_span()) {
+ const MutableSpan<T> span = this->get_internal_span().typed<T>();
+ return VMutableArray<T>::ForSpan(span);
}
-};
+ return VMutableArray<T>::template For<VMutableArrayImpl_For_GVMutableArray<T>>(*this);
+}
+
+/** \} */
} // namespace blender::fn
diff --git a/source/blender/functions/FN_generic_virtual_vector_array.hh b/source/blender/functions/FN_generic_virtual_vector_array.hh
index 4155a55a801..b80e21eaef1 100644
--- a/source/blender/functions/FN_generic_virtual_vector_array.hh
+++ b/source/blender/functions/FN_generic_virtual_vector_array.hh
@@ -100,31 +100,31 @@ class GVVectorArray {
}
};
-class GVArray_For_GVVectorArrayIndex : public GVArray {
+class GVArray_For_GVVectorArrayIndex : public GVArrayImpl {
private:
const GVVectorArray &vector_array_;
const int64_t index_;
public:
GVArray_For_GVVectorArrayIndex(const GVVectorArray &vector_array, const int64_t index)
- : GVArray(vector_array.type(), vector_array.get_vector_size(index)),
+ : GVArrayImpl(vector_array.type(), vector_array.get_vector_size(index)),
vector_array_(vector_array),
index_(index)
{
}
protected:
- void get_impl(const int64_t index_in_vector, void *r_value) const override;
- void get_to_uninitialized_impl(const int64_t index_in_vector, void *r_value) const override;
+ void get(const int64_t index_in_vector, void *r_value) const override;
+ void get_to_uninitialized(const int64_t index_in_vector, void *r_value) const override;
};
class GVVectorArray_For_SingleGVArray : public GVVectorArray {
private:
- const GVArray &array_;
+ GVArray varray_;
public:
- GVVectorArray_For_SingleGVArray(const GVArray &array, const int64_t size)
- : GVVectorArray(array.type(), size), array_(array)
+ GVVectorArray_For_SingleGVArray(GVArray varray, const int64_t size)
+ : GVVectorArray(varray.type(), size), varray_(std::move(varray))
{
}
diff --git a/source/blender/functions/FN_multi_function.hh b/source/blender/functions/FN_multi_function.hh
index 98788025558..3059fe59ca7 100644
--- a/source/blender/functions/FN_multi_function.hh
+++ b/source/blender/functions/FN_multi_function.hh
@@ -97,6 +97,8 @@ class MultiFunction {
return signature_ref_->function_name;
}
+ virtual std::string debug_name() const;
+
bool depends_on_context() const
{
return signature_ref_->depends_on_context;
@@ -131,8 +133,6 @@ inline MFParamsBuilder::MFParamsBuilder(const MultiFunction &fn, const IndexMask
{
}
-extern const MultiFunction &dummy_multi_function;
-
namespace multi_function_types {
using fn::CPPType;
using fn::GMutableSpan;
diff --git a/source/blender/functions/FN_multi_function_builder.hh b/source/blender/functions/FN_multi_function_builder.hh
index 0ce05cbca30..eaf9e5ce70f 100644
--- a/source/blender/functions/FN_multi_function_builder.hh
+++ b/source/blender/functions/FN_multi_function_builder.hh
@@ -43,7 +43,7 @@ template<typename In1, typename Out1> class CustomMF_SI_SO : public MultiFunctio
MFSignature signature_;
public:
- CustomMF_SI_SO(StringRef name, FunctionT function) : function_(std::move(function))
+ CustomMF_SI_SO(const char *name, FunctionT function) : function_(std::move(function))
{
MFSignatureBuilder signature{name};
signature.single_input<In1>("In1");
@@ -53,7 +53,7 @@ template<typename In1, typename Out1> class CustomMF_SI_SO : public MultiFunctio
}
template<typename ElementFuncT>
- CustomMF_SI_SO(StringRef name, ElementFuncT element_fn)
+ CustomMF_SI_SO(const char *name, ElementFuncT element_fn)
: CustomMF_SI_SO(name, CustomMF_SI_SO::create_function(element_fn))
{
}
@@ -92,7 +92,7 @@ class CustomMF_SI_SI_SO : public MultiFunction {
MFSignature signature_;
public:
- CustomMF_SI_SI_SO(StringRef name, FunctionT function) : function_(std::move(function))
+ CustomMF_SI_SI_SO(const char *name, FunctionT function) : function_(std::move(function))
{
MFSignatureBuilder signature{name};
signature.single_input<In1>("In1");
@@ -103,7 +103,7 @@ class CustomMF_SI_SI_SO : public MultiFunction {
}
template<typename ElementFuncT>
- CustomMF_SI_SI_SO(StringRef name, ElementFuncT element_fn)
+ CustomMF_SI_SI_SO(const char *name, ElementFuncT element_fn)
: CustomMF_SI_SI_SO(name, CustomMF_SI_SI_SO::create_function(element_fn))
{
}
@@ -150,7 +150,7 @@ class CustomMF_SI_SI_SI_SO : public MultiFunction {
MFSignature signature_;
public:
- CustomMF_SI_SI_SI_SO(StringRef name, FunctionT function) : function_(std::move(function))
+ CustomMF_SI_SI_SI_SO(const char *name, FunctionT function) : function_(std::move(function))
{
MFSignatureBuilder signature{name};
signature.single_input<In1>("In1");
@@ -162,7 +162,7 @@ class CustomMF_SI_SI_SI_SO : public MultiFunction {
}
template<typename ElementFuncT>
- CustomMF_SI_SI_SI_SO(StringRef name, ElementFuncT element_fn)
+ CustomMF_SI_SI_SI_SO(const char *name, ElementFuncT element_fn)
: CustomMF_SI_SI_SI_SO(name, CustomMF_SI_SI_SI_SO::create_function(element_fn))
{
}
@@ -211,7 +211,7 @@ class CustomMF_SI_SI_SI_SI_SO : public MultiFunction {
MFSignature signature_;
public:
- CustomMF_SI_SI_SI_SI_SO(StringRef name, FunctionT function) : function_(std::move(function))
+ CustomMF_SI_SI_SI_SI_SO(const char *name, FunctionT function) : function_(std::move(function))
{
MFSignatureBuilder signature{name};
signature.single_input<In1>("In1");
@@ -224,7 +224,7 @@ class CustomMF_SI_SI_SI_SI_SO : public MultiFunction {
}
template<typename ElementFuncT>
- CustomMF_SI_SI_SI_SI_SO(StringRef name, ElementFuncT element_fn)
+ CustomMF_SI_SI_SI_SI_SO(const char *name, ElementFuncT element_fn)
: CustomMF_SI_SI_SI_SI_SO(name, CustomMF_SI_SI_SI_SI_SO::create_function(element_fn))
{
}
@@ -265,7 +265,7 @@ template<typename Mut1> class CustomMF_SM : public MultiFunction {
MFSignature signature_;
public:
- CustomMF_SM(StringRef name, FunctionT function) : function_(std::move(function))
+ CustomMF_SM(const char *name, FunctionT function) : function_(std::move(function))
{
MFSignatureBuilder signature{name};
signature.single_mutable<Mut1>("Mut1");
@@ -274,7 +274,7 @@ template<typename Mut1> class CustomMF_SM : public MultiFunction {
}
template<typename ElementFuncT>
- CustomMF_SM(StringRef name, ElementFuncT element_fn)
+ CustomMF_SM(const char *name, ElementFuncT element_fn)
: CustomMF_SM(name, CustomMF_SM::create_function(element_fn))
{
}
@@ -306,8 +306,8 @@ template<typename From, typename To> class CustomMF_Convert : public MultiFuncti
static MFSignature create_signature()
{
- std::string name = CPPType::get<From>().name() + " to " + CPPType::get<To>().name();
- MFSignatureBuilder signature{std::move(name)};
+ static std::string name = CPPType::get<From>().name() + " to " + CPPType::get<To>().name();
+ MFSignatureBuilder signature{name.c_str()};
signature.single_input<From>("Input");
signature.single_output<To>("Output");
return signature.build();
@@ -372,9 +372,7 @@ template<typename T> class CustomMF_Constant : public MultiFunction {
template<typename U> CustomMF_Constant(U &&value) : value_(std::forward<U>(value))
{
MFSignatureBuilder signature{"Constant"};
- std::stringstream ss;
- ss << value_;
- signature.single_output<T>(ss.str());
+ signature.single_output<T>("Value");
signature_ = signature.build();
this->set_signature(&signature_);
}
@@ -414,9 +412,7 @@ class CustomMF_DefaultOutput : public MultiFunction {
MFSignature signature_;
public:
- CustomMF_DefaultOutput(StringRef name,
- Span<MFDataType> input_types,
- Span<MFDataType> output_types);
+ CustomMF_DefaultOutput(Span<MFDataType> input_types, Span<MFDataType> output_types);
void call(IndexMask mask, MFParams params, MFContext context) const override;
};
@@ -425,7 +421,7 @@ class CustomMF_GenericCopy : public MultiFunction {
MFSignature signature_;
public:
- CustomMF_GenericCopy(StringRef name, MFDataType data_type);
+ CustomMF_GenericCopy(MFDataType data_type);
void call(IndexMask mask, MFParams params, MFContext context) const override;
};
diff --git a/source/blender/functions/FN_multi_function_params.hh b/source/blender/functions/FN_multi_function_params.hh
index d187985de9d..5c7e75230f3 100644
--- a/source/blender/functions/FN_multi_function_params.hh
+++ b/source/blender/functions/FN_multi_function_params.hh
@@ -40,7 +40,7 @@ class MFParamsBuilder {
const MFSignature *signature_;
IndexMask mask_;
int64_t min_array_size_;
- Vector<const GVArray *> virtual_arrays_;
+ Vector<GVArray> virtual_arrays_;
Vector<GMutableSpan> mutable_spans_;
Vector<const GVVectorArray *> virtual_vector_arrays_;
Vector<GVectorArray *> vector_arrays_;
@@ -68,24 +68,22 @@ class MFParamsBuilder {
template<typename T> void add_readonly_single_input(const T *value, StringRef expected_name = "")
{
this->add_readonly_single_input(
- scope_.construct<GVArray_For_SingleValueRef>(CPPType::get<T>(), min_array_size_, value),
- expected_name);
+ GVArray::ForSingleRef(CPPType::get<T>(), min_array_size_, value), expected_name);
}
void add_readonly_single_input(const GSpan span, StringRef expected_name = "")
{
- this->add_readonly_single_input(scope_.construct<GVArray_For_GSpan>(span), expected_name);
+ this->add_readonly_single_input(GVArray::ForSpan(span), expected_name);
}
void add_readonly_single_input(GPointer value, StringRef expected_name = "")
{
this->add_readonly_single_input(
- scope_.construct<GVArray_For_SingleValueRef>(*value.type(), min_array_size_, value.get()),
- expected_name);
+ GVArray::ForSingleRef(*value.type(), min_array_size_, value.get()), expected_name);
}
- void add_readonly_single_input(const GVArray &ref, StringRef expected_name = "")
+ void add_readonly_single_input(GVArray varray, StringRef expected_name = "")
{
- this->assert_current_param_type(MFParamType::ForSingleInput(ref.type()), expected_name);
- BLI_assert(ref.size() >= min_array_size_);
- virtual_arrays_.append(&ref);
+ this->assert_current_param_type(MFParamType::ForSingleInput(varray.type()), expected_name);
+ BLI_assert(varray.size() >= min_array_size_);
+ virtual_arrays_.append(varray);
}
void add_readonly_vector_input(const GVectorArray &vector_array, StringRef expected_name = "")
@@ -221,16 +219,16 @@ class MFParams {
{
}
- template<typename T> const VArray<T> &readonly_single_input(int param_index, StringRef name = "")
+ template<typename T> VArray<T> readonly_single_input(int param_index, StringRef name = "")
{
- const GVArray &array = this->readonly_single_input(param_index, name);
- return builder_->scope_.construct<GVArray_Typed<T>>(array);
+ const GVArray &varray = this->readonly_single_input(param_index, name);
+ return varray.typed<T>();
}
const GVArray &readonly_single_input(int param_index, StringRef name = "")
{
this->assert_correct_param(param_index, name, MFParamType::SingleInput);
int data_index = builder_->signature_->data_index(param_index);
- return *builder_->virtual_arrays_[data_index];
+ return builder_->virtual_arrays_[data_index];
}
/**
diff --git a/source/blender/functions/FN_multi_function_procedure_executor.hh b/source/blender/functions/FN_multi_function_procedure_executor.hh
index 9c8b59739b8..b12e3a91210 100644
--- a/source/blender/functions/FN_multi_function_procedure_executor.hh
+++ b/source/blender/functions/FN_multi_function_procedure_executor.hh
@@ -31,7 +31,7 @@ class MFProcedureExecutor : public MultiFunction {
const MFProcedure &procedure_;
public:
- MFProcedureExecutor(std::string name, const MFProcedure &procedure);
+ MFProcedureExecutor(const MFProcedure &procedure);
void call(IndexMask mask, MFParams params, MFContext context) const override;
};
diff --git a/source/blender/functions/FN_multi_function_signature.hh b/source/blender/functions/FN_multi_function_signature.hh
index d05948cc645..3c991bc9c56 100644
--- a/source/blender/functions/FN_multi_function_signature.hh
+++ b/source/blender/functions/FN_multi_function_signature.hh
@@ -30,8 +30,15 @@
namespace blender::fn {
struct MFSignature {
- std::string function_name;
- Vector<std::string> param_names;
+ /**
+ * The name should be statically allocated so that it lives longer than this signature. This is
+ * used instead of an #std::string because of the overhead when many functions are created.
+ * If the name of the function has to be more dynamic for debugging purposes, override
+ * #MultiFunction::debug_name() instead. Then the dynamic name will only be computed when it is
+ * actually needed.
+ */
+ const char *function_name;
+ Vector<const char *> param_names;
Vector<MFParamType> param_types;
Vector<int> param_data_indices;
bool depends_on_context = false;
@@ -51,9 +58,9 @@ class MFSignatureBuilder {
int vector_array_count_ = 0;
public:
- MFSignatureBuilder(std::string function_name)
+ MFSignatureBuilder(const char *function_name)
{
- signature_.function_name = std::move(function_name);
+ signature_.function_name = function_name;
}
MFSignature build() const
@@ -63,23 +70,23 @@ class MFSignatureBuilder {
/* Input Parameter Types */
- template<typename T> void single_input(StringRef name)
+ template<typename T> void single_input(const char *name)
{
this->single_input(name, CPPType::get<T>());
}
- void single_input(StringRef name, const CPPType &type)
+ void single_input(const char *name, const CPPType &type)
{
this->input(name, MFDataType::ForSingle(type));
}
- template<typename T> void vector_input(StringRef name)
+ template<typename T> void vector_input(const char *name)
{
this->vector_input(name, CPPType::get<T>());
}
- void vector_input(StringRef name, const CPPType &base_type)
+ void vector_input(const char *name, const CPPType &base_type)
{
this->input(name, MFDataType::ForVector(base_type));
}
- void input(StringRef name, MFDataType data_type)
+ void input(const char *name, MFDataType data_type)
{
signature_.param_names.append(name);
signature_.param_types.append(MFParamType(MFParamType::Input, data_type));
@@ -96,23 +103,23 @@ class MFSignatureBuilder {
/* Output Parameter Types */
- template<typename T> void single_output(StringRef name)
+ template<typename T> void single_output(const char *name)
{
this->single_output(name, CPPType::get<T>());
}
- void single_output(StringRef name, const CPPType &type)
+ void single_output(const char *name, const CPPType &type)
{
this->output(name, MFDataType::ForSingle(type));
}
- template<typename T> void vector_output(StringRef name)
+ template<typename T> void vector_output(const char *name)
{
this->vector_output(name, CPPType::get<T>());
}
- void vector_output(StringRef name, const CPPType &base_type)
+ void vector_output(const char *name, const CPPType &base_type)
{
this->output(name, MFDataType::ForVector(base_type));
}
- void output(StringRef name, MFDataType data_type)
+ void output(const char *name, MFDataType data_type)
{
signature_.param_names.append(name);
signature_.param_types.append(MFParamType(MFParamType::Output, data_type));
@@ -129,23 +136,23 @@ class MFSignatureBuilder {
/* Mutable Parameter Types */
- template<typename T> void single_mutable(StringRef name)
+ template<typename T> void single_mutable(const char *name)
{
this->single_mutable(name, CPPType::get<T>());
}
- void single_mutable(StringRef name, const CPPType &type)
+ void single_mutable(const char *name, const CPPType &type)
{
this->mutable_(name, MFDataType::ForSingle(type));
}
- template<typename T> void vector_mutable(StringRef name)
+ template<typename T> void vector_mutable(const char *name)
{
this->vector_mutable(name, CPPType::get<T>());
}
- void vector_mutable(StringRef name, const CPPType &base_type)
+ void vector_mutable(const char *name, const CPPType &base_type)
{
this->mutable_(name, MFDataType::ForVector(base_type));
}
- void mutable_(StringRef name, MFDataType data_type)
+ void mutable_(const char *name, MFDataType data_type)
{
signature_.param_names.append(name);
signature_.param_types.append(MFParamType(MFParamType::Mutable, data_type));
@@ -160,7 +167,7 @@ class MFSignatureBuilder {
}
}
- void add(StringRef name, const MFParamType &param_type)
+ void add(const char *name, const MFParamType &param_type)
{
switch (param_type.interface_type()) {
case MFParamType::Input:
diff --git a/source/blender/functions/intern/field.cc b/source/blender/functions/intern/field.cc
index 4de5e71c910..7934490a6d9 100644
--- a/source/blender/functions/intern/field.cc
+++ b/source/blender/functions/intern/field.cc
@@ -81,19 +81,18 @@ static FieldTreeInfo preprocess_field_tree(Span<GFieldRef> entry_fields)
/**
* Retrieves the data from the context that is passed as input into the field.
*/
-static Vector<const GVArray *> get_field_context_inputs(
+static Vector<GVArray> get_field_context_inputs(
ResourceScope &scope,
const IndexMask mask,
const FieldContext &context,
const Span<std::reference_wrapper<const FieldInput>> field_inputs)
{
- Vector<const GVArray *> field_context_inputs;
+ Vector<GVArray> field_context_inputs;
for (const FieldInput &field_input : field_inputs) {
- const GVArray *varray = context.get_varray_for_input(field_input, mask, scope);
- if (varray == nullptr) {
+ GVArray varray = context.get_varray_for_input(field_input, mask, scope);
+ if (!varray) {
const CPPType &type = field_input.cpp_type();
- varray = &scope.construct<GVArray_For_SingleValueRef>(
- type, mask.min_array_size(), type.default_value());
+ varray = GVArray::ForSingleDefault(type, mask.min_array_size());
}
field_context_inputs.append(varray);
}
@@ -105,7 +104,7 @@ static Vector<const GVArray *> get_field_context_inputs(
* for different indices.
*/
static Set<GFieldRef> find_varying_fields(const FieldTreeInfo &field_tree_info,
- Span<const GVArray *> field_context_inputs)
+ Span<GVArray> field_context_inputs)
{
Set<GFieldRef> found_fields;
Stack<GFieldRef> fields_to_check;
@@ -114,8 +113,8 @@ static Set<GFieldRef> find_varying_fields(const FieldTreeInfo &field_tree_info,
* start the tree search at the non-constant input fields and traverse through all fields that
* depend on them. */
for (const int i : field_context_inputs.index_range()) {
- const GVArray *varray = field_context_inputs[i];
- if (varray->is_single()) {
+ const GVArray &varray = field_context_inputs[i];
+ if (varray.is_single()) {
continue;
}
const FieldInput &field_input = field_tree_info.deduplicated_field_inputs[i];
@@ -238,8 +237,7 @@ static void build_multi_function_procedure_for_fields(MFProcedure &procedure,
if (!already_output_variables.add(variable)) {
/* One variable can be output at most once. To output the same value twice, we have to make
* a copy first. */
- const MultiFunction &copy_fn = scope.construct<CustomMF_GenericCopy>("copy",
- variable->data_type());
+ const MultiFunction &copy_fn = scope.construct<CustomMF_GenericCopy>(variable->data_type());
variable = builder.add_call<1>(copy_fn, {variable})[0];
}
builder.add_output_parameter(*variable);
@@ -278,29 +276,42 @@ static void build_multi_function_procedure_for_fields(MFProcedure &procedure,
* \return The computed virtual arrays for each provided field. If #dst_varrays is passed, the
* provided virtual arrays are returned.
*/
-Vector<const GVArray *> evaluate_fields(ResourceScope &scope,
- Span<GFieldRef> fields_to_evaluate,
- IndexMask mask,
- const FieldContext &context,
- Span<GVMutableArray *> dst_varrays)
+Vector<GVArray> evaluate_fields(ResourceScope &scope,
+ Span<GFieldRef> fields_to_evaluate,
+ IndexMask mask,
+ const FieldContext &context,
+ Span<GVMutableArray> dst_varrays)
{
- Vector<const GVArray *> r_varrays(fields_to_evaluate.size(), nullptr);
+ Vector<GVArray> r_varrays(fields_to_evaluate.size());
+ Array<bool> is_output_written_to_dst(fields_to_evaluate.size(), false);
const int array_size = mask.min_array_size();
+ if (mask.is_empty()) {
+ for (const int i : fields_to_evaluate.index_range()) {
+ const CPPType &type = fields_to_evaluate[i].cpp_type();
+ r_varrays[i] = GVArray::ForEmpty(type);
+ }
+ return r_varrays;
+ }
+
/* Destination arrays are optional. Create a small utility method to access them. */
- auto get_dst_varray_if_available = [&](int index) -> GVMutableArray * {
+ auto get_dst_varray = [&](int index) -> GVMutableArray {
if (dst_varrays.is_empty()) {
- return nullptr;
+ return {};
+ }
+ const GVMutableArray &varray = dst_varrays[index];
+ if (!varray) {
+ return {};
}
- BLI_assert(dst_varrays[index] == nullptr || dst_varrays[index]->size() >= array_size);
- return dst_varrays[index];
+ BLI_assert(varray.size() >= array_size);
+ return varray;
};
/* Traverse the field tree and prepare some data that is used in later steps. */
FieldTreeInfo field_tree_info = preprocess_field_tree(fields_to_evaluate);
/* Get inputs that will be passed into the field when evaluated. */
- Vector<const GVArray *> field_context_inputs = get_field_context_inputs(
+ Vector<GVArray> field_context_inputs = get_field_context_inputs(
scope, mask, context, field_tree_info.deduplicated_field_inputs);
/* Finish fields that output an input varray directly. For those we don't have to do any further
@@ -312,7 +323,7 @@ Vector<const GVArray *> evaluate_fields(ResourceScope &scope,
}
const FieldInput &field_input = static_cast<const FieldInput &>(field.node());
const int field_input_index = field_tree_info.deduplicated_field_inputs.index_of(field_input);
- const GVArray *varray = field_context_inputs[field_input_index];
+ const GVArray &varray = field_context_inputs[field_input_index];
r_varrays[out_index] = varray;
}
@@ -325,7 +336,7 @@ Vector<const GVArray *> evaluate_fields(ResourceScope &scope,
Vector<GFieldRef> constant_fields_to_evaluate;
Vector<int> constant_field_indices;
for (const int i : fields_to_evaluate.index_range()) {
- if (r_varrays[i] != nullptr) {
+ if (r_varrays[i]) {
/* Already done. */
continue;
}
@@ -346,7 +357,7 @@ Vector<const GVArray *> evaluate_fields(ResourceScope &scope,
MFProcedure procedure;
build_multi_function_procedure_for_fields(
procedure, scope, field_tree_info, varying_fields_to_evaluate);
- MFProcedureExecutor procedure_executor{"Procedure", procedure};
+ MFProcedureExecutor procedure_executor{procedure};
/* Add multi threading capabilities to the field evaluation. */
const int grain_size = 10000;
fn::ParallelMultiFunction parallel_procedure_executor{procedure_executor, grain_size};
@@ -357,8 +368,8 @@ Vector<const GVArray *> evaluate_fields(ResourceScope &scope,
MFContextBuilder mf_context;
/* Provide inputs to the procedure executor. */
- for (const GVArray *varray : field_context_inputs) {
- mf_params.add_readonly_single_input(*varray);
+ for (const GVArray &varray : field_context_inputs) {
+ mf_params.add_readonly_single_input(varray);
}
for (const int i : varying_fields_to_evaluate.index_range()) {
@@ -367,9 +378,9 @@ Vector<const GVArray *> evaluate_fields(ResourceScope &scope,
const int out_index = varying_field_indices[i];
/* Try to get an existing virtual array that the result should be written into. */
- GVMutableArray *output_varray = get_dst_varray_if_available(out_index);
+ GVMutableArray dst_varray = get_dst_varray(out_index);
void *buffer;
- if (output_varray == nullptr || !output_varray->is_span()) {
+ if (!dst_varray || !dst_varray.is_span()) {
/* Allocate a new buffer for the computed result. */
buffer = scope.linear_allocator().allocate(type.size() * array_size, type.alignment());
@@ -379,14 +390,14 @@ Vector<const GVArray *> evaluate_fields(ResourceScope &scope,
[buffer, mask, &type]() { type.destruct_indices(buffer, mask); });
}
- r_varrays[out_index] = &scope.construct<GVArray_For_GSpan>(
- GSpan{type, buffer, array_size});
+ r_varrays[out_index] = GVArray::ForSpan({type, buffer, array_size});
}
else {
/* Write the result into the existing span. */
- buffer = output_varray->get_internal_span().data();
+ buffer = dst_varray.get_internal_span().data();
- r_varrays[out_index] = output_varray;
+ r_varrays[out_index] = dst_varray;
+ is_output_written_to_dst[out_index] = true;
}
/* Pass output buffer to the procedure executor. */
@@ -403,16 +414,13 @@ Vector<const GVArray *> evaluate_fields(ResourceScope &scope,
MFProcedure procedure;
build_multi_function_procedure_for_fields(
procedure, scope, field_tree_info, constant_fields_to_evaluate);
- MFProcedureExecutor procedure_executor{"Procedure", procedure};
- /* Run the code below even when the mask is empty, so that outputs are properly prepared.
- * Higher level code can detect this as well and just skip evaluating the field. */
- const int mask_size = mask.is_empty() ? 0 : 1;
- MFParamsBuilder mf_params{procedure_executor, mask_size};
+ MFProcedureExecutor procedure_executor{procedure};
+ MFParamsBuilder mf_params{procedure_executor, 1};
MFContextBuilder mf_context;
/* Provide inputs to the procedure executor. */
- for (const GVArray *varray : field_context_inputs) {
- mf_params.add_readonly_single_input(*varray);
+ for (const GVArray &varray : field_context_inputs) {
+ mf_params.add_readonly_single_input(varray);
}
for (const int i : constant_fields_to_evaluate.index_range()) {
@@ -421,55 +429,52 @@ Vector<const GVArray *> evaluate_fields(ResourceScope &scope,
/* Allocate memory where the computed value will be stored in. */
void *buffer = scope.linear_allocator().allocate(type.size(), type.alignment());
- if (!type.is_trivially_destructible() && mask_size > 0) {
- BLI_assert(mask_size == 1);
+ if (!type.is_trivially_destructible()) {
/* Destruct value in the end. */
scope.add_destruct_call([buffer, &type]() { type.destruct(buffer); });
}
/* Pass output buffer to the procedure executor. */
- mf_params.add_uninitialized_single_output({type, buffer, mask_size});
+ mf_params.add_uninitialized_single_output({type, buffer, 1});
/* Create virtual array that can be used after the procedure has been executed below. */
const int out_index = constant_field_indices[i];
- r_varrays[out_index] = &scope.construct<GVArray_For_SingleValueRef>(
- type, array_size, buffer);
+ r_varrays[out_index] = GVArray::ForSingleRef(type, array_size, buffer);
}
- procedure_executor.call(IndexRange(mask_size), mf_params, mf_context);
+ procedure_executor.call(IndexRange(1), mf_params, mf_context);
}
- /* Copy data to supplied destination arrays if necessary. In some cases the evaluation above has
- * written the computed data in the right place already. */
+ /* Copy data to supplied destination arrays if necessary. In some cases the evaluation above
+ * has written the computed data in the right place already. */
if (!dst_varrays.is_empty()) {
for (const int out_index : fields_to_evaluate.index_range()) {
- GVMutableArray *output_varray = get_dst_varray_if_available(out_index);
- if (output_varray == nullptr) {
+ GVMutableArray dst_varray = get_dst_varray(out_index);
+ if (!dst_varray) {
/* Caller did not provide a destination for this output. */
continue;
}
- const GVArray *computed_varray = r_varrays[out_index];
- BLI_assert(computed_varray->type() == output_varray->type());
- if (output_varray == computed_varray) {
+ const GVArray &computed_varray = r_varrays[out_index];
+ BLI_assert(computed_varray.type() == dst_varray.type());
+ if (is_output_written_to_dst[out_index]) {
/* The result has been written into the destination provided by the caller already. */
continue;
}
/* Still have to copy over the data in the destination provided by the caller. */
- if (output_varray->is_span()) {
+ if (dst_varray.is_span()) {
/* Materialize into a span. */
- computed_varray->materialize_to_uninitialized(mask,
- output_varray->get_internal_span().data());
+ computed_varray.materialize_to_uninitialized(mask, dst_varray.get_internal_span().data());
}
else {
/* Slower materialize into a different structure. */
- const CPPType &type = computed_varray->type();
+ const CPPType &type = computed_varray.type();
BUFFER_FOR_CPP_TYPE_VALUE(type, buffer);
for (const int i : mask) {
- computed_varray->get_to_uninitialized(i, buffer);
- output_varray->set_by_relocate(i, buffer);
+ computed_varray.get_to_uninitialized(i, buffer);
+ dst_varray.set_by_relocate(i, buffer);
}
}
- r_varrays[out_index] = output_varray;
+ r_varrays[out_index] = dst_varray;
}
}
return r_varrays;
@@ -485,8 +490,8 @@ void evaluate_constant_field(const GField &field, void *r_value)
ResourceScope scope;
FieldContext context;
- Vector<const GVArray *> varrays = evaluate_fields(scope, {field}, IndexRange(1), context);
- varrays[0]->get_to_uninitialized(0, r_value);
+ Vector<GVArray> varrays = evaluate_fields(scope, {field}, IndexRange(1), context);
+ varrays[0].get_to_uninitialized(0, r_value);
}
/**
@@ -506,15 +511,21 @@ GField make_field_constant_if_possible(GField field)
const CPPType &type = field.cpp_type();
BUFFER_FOR_CPP_TYPE_VALUE(type, buffer);
evaluate_constant_field(field, buffer);
- auto constant_fn = std::make_unique<CustomMF_GenericConstant>(type, buffer, true);
+ GField new_field = make_constant_field(type, buffer);
type.destruct(buffer);
+ return new_field;
+}
+
+GField make_constant_field(const CPPType &type, const void *value)
+{
+ auto constant_fn = std::make_unique<CustomMF_GenericConstant>(type, value, true);
auto operation = std::make_shared<FieldOperation>(std::move(constant_fn));
- return GField{operation, 0};
+ return GField{std::move(operation), 0};
}
-const GVArray *FieldContext::get_varray_for_input(const FieldInput &field_input,
- IndexMask mask,
- ResourceScope &scope) const
+GVArray FieldContext::get_varray_for_input(const FieldInput &field_input,
+ IndexMask mask,
+ ResourceScope &scope) const
{
/* By default ask the field input to create the varray. Another field context might overwrite
* the context here. */
@@ -526,17 +537,15 @@ IndexFieldInput::IndexFieldInput() : FieldInput(CPPType::get<int>(), "Index")
category_ = Category::Generated;
}
-GVArray *IndexFieldInput::get_index_varray(IndexMask mask, ResourceScope &scope)
+GVArray IndexFieldInput::get_index_varray(IndexMask mask, ResourceScope &UNUSED(scope))
{
auto index_func = [](int i) { return i; };
- return &scope.construct<
- fn::GVArray_For_EmbeddedVArray<int, VArray_For_Func<int, decltype(index_func)>>>(
- mask.min_array_size(), mask.min_array_size(), index_func);
+ return VArray<int>::ForFunc(mask.min_array_size(), index_func);
}
-const GVArray *IndexFieldInput::get_varray_for_context(const fn::FieldContext &UNUSED(context),
- IndexMask mask,
- ResourceScope &scope) const
+GVArray IndexFieldInput::get_varray_for_context(const fn::FieldContext &UNUSED(context),
+ IndexMask mask,
+ ResourceScope &scope) const
{
/* TODO: Investigate a similar method to IndexRange::as_span() */
return get_index_varray(mask, scope);
@@ -631,27 +640,26 @@ static Vector<int64_t> indices_from_selection(const VArray<bool> &selection)
return indices;
}
-int FieldEvaluator::add_with_destination(GField field, GVMutableArray &dst)
+int FieldEvaluator::add_with_destination(GField field, GVMutableArray dst)
{
const int field_index = fields_to_evaluate_.append_and_get_index(std::move(field));
- dst_varrays_.append(&dst);
+ dst_varrays_.append(dst);
output_pointer_infos_.append({});
return field_index;
}
int FieldEvaluator::add_with_destination(GField field, GMutableSpan dst)
{
- GVMutableArray &varray = scope_.construct<GVMutableArray_For_GMutableSpan>(dst);
- return this->add_with_destination(std::move(field), varray);
+ return this->add_with_destination(std::move(field), GVMutableArray::ForSpan(dst));
}
-int FieldEvaluator::add(GField field, const GVArray **varray_ptr)
+int FieldEvaluator::add(GField field, GVArray *varray_ptr)
{
const int field_index = fields_to_evaluate_.append_and_get_index(std::move(field));
dst_varrays_.append(nullptr);
output_pointer_infos_.append(OutputPointerInfo{
varray_ptr, [](void *dst, const GVArray &varray, ResourceScope &UNUSED(scope)) {
- *(const GVArray **)dst = &varray;
+ *(GVArray *)dst = varray;
}});
return field_index;
}
@@ -676,7 +684,7 @@ void FieldEvaluator::evaluate()
for (const int i : fields_to_evaluate_.index_range()) {
OutputPointerInfo &info = output_pointer_infos_[i];
if (info.dst != nullptr) {
- info.set(info.dst, *evaluated_varrays_[i], scope_);
+ info.set(info.dst, evaluated_varrays_[i], scope_);
}
}
is_evaluated_ = true;
@@ -684,17 +692,16 @@ void FieldEvaluator::evaluate()
IndexMask FieldEvaluator::get_evaluated_as_mask(const int field_index)
{
- const GVArray &varray = this->get_evaluated(field_index);
- GVArray_Typed<bool> typed_varray{varray};
+ VArray<bool> varray = this->get_evaluated(field_index).typed<bool>();
- if (typed_varray->is_single()) {
- if (typed_varray->get_internal_single()) {
- return IndexRange(typed_varray.size());
+ if (varray.is_single()) {
+ if (varray.get_internal_single()) {
+ return IndexRange(varray.size());
}
return IndexRange(0);
}
- return scope_.add_value(indices_from_selection(*typed_varray)).as_span();
+ return scope_.add_value(indices_from_selection(varray)).as_span();
}
} // namespace blender::fn
diff --git a/source/blender/functions/intern/generic_vector_array.cc b/source/blender/functions/intern/generic_vector_array.cc
index ec95a283919..0d478007a5a 100644
--- a/source/blender/functions/intern/generic_vector_array.cc
+++ b/source/blender/functions/intern/generic_vector_array.cc
@@ -60,15 +60,14 @@ void GVectorArray::extend(const int64_t index, const GVArray &values)
void GVectorArray::extend(const int64_t index, const GSpan values)
{
- GVArray_For_GSpan varray{values};
- this->extend(index, varray);
+ this->extend(index, GVArray::ForSpan(values));
}
void GVectorArray::extend(IndexMask mask, const GVVectorArray &values)
{
for (const int i : mask) {
GVArray_For_GVVectorArrayIndex array{values, i};
- this->extend(i, array);
+ this->extend(i, GVArray(&array));
}
}
diff --git a/source/blender/functions/intern/generic_virtual_array.cc b/source/blender/functions/intern/generic_virtual_array.cc
index ea54f1e7c00..1fe1c2fc229 100644
--- a/source/blender/functions/intern/generic_virtual_array.cc
+++ b/source/blender/functions/intern/generic_virtual_array.cc
@@ -19,52 +19,10 @@
namespace blender::fn {
/* -------------------------------------------------------------------- */
-/** \name #GVArray_For_ShallowCopy
+/** \name #GVArrayImpl
* \{ */
-class GVArray_For_ShallowCopy : public GVArray {
- private:
- const GVArray &varray_;
-
- public:
- GVArray_For_ShallowCopy(const GVArray &varray)
- : GVArray(varray.type(), varray.size()), varray_(varray)
- {
- }
-
- private:
- void get_impl(const int64_t index, void *r_value) const override
- {
- varray_.get(index, r_value);
- }
-
- void get_to_uninitialized_impl(const int64_t index, void *r_value) const override
- {
- varray_.get_to_uninitialized(index, r_value);
- }
-
- void materialize_to_uninitialized_impl(const IndexMask mask, void *dst) const override
- {
- varray_.materialize_to_uninitialized(mask, dst);
- }
-};
-/** \} */
-
-/* -------------------------------------------------------------------- */
-/** \name #GVArray
- * \{ */
-
-void GVArray::materialize(void *dst) const
-{
- this->materialize(IndexMask(size_), dst);
-}
-
-void GVArray::materialize(const IndexMask mask, void *dst) const
-{
- this->materialize_impl(mask, dst);
-}
-
-void GVArray::materialize_impl(const IndexMask mask, void *dst) const
+void GVArrayImpl::materialize(const IndexMask mask, void *dst) const
{
for (const int64_t i : mask) {
void *elem_dst = POINTER_OFFSET(dst, type_->size() * i);
@@ -72,18 +30,7 @@ void GVArray::materialize_impl(const IndexMask mask, void *dst) const
}
}
-void GVArray::materialize_to_uninitialized(void *dst) const
-{
- this->materialize_to_uninitialized(IndexMask(size_), dst);
-}
-
-void GVArray::materialize_to_uninitialized(const IndexMask mask, void *dst) const
-{
- BLI_assert(mask.min_array_size() <= size_);
- this->materialize_to_uninitialized_impl(mask, dst);
-}
-
-void GVArray::materialize_to_uninitialized_impl(const IndexMask mask, void *dst) const
+void GVArrayImpl::materialize_to_uninitialized(const IndexMask mask, void *dst) const
{
for (const int64_t i : mask) {
void *elem_dst = POINTER_OFFSET(dst, type_->size() * i);
@@ -91,83 +38,75 @@ void GVArray::materialize_to_uninitialized_impl(const IndexMask mask, void *dst)
}
}
-void GVArray::get_impl(const int64_t index, void *r_value) const
+void GVArrayImpl::get(const int64_t index, void *r_value) const
{
type_->destruct(r_value);
- this->get_to_uninitialized_impl(index, r_value);
+ this->get_to_uninitialized(index, r_value);
}
-bool GVArray::is_span_impl() const
+bool GVArrayImpl::is_span() const
{
return false;
}
-GSpan GVArray::get_internal_span_impl() const
+GSpan GVArrayImpl::get_internal_span() const
{
BLI_assert(false);
return GSpan(*type_);
}
-bool GVArray::is_single_impl() const
+bool GVArrayImpl::is_single() const
{
return false;
}
-void GVArray::get_internal_single_impl(void *UNUSED(r_value)) const
+void GVArrayImpl::get_internal_single(void *UNUSED(r_value)) const
{
BLI_assert(false);
}
-const void *GVArray::try_get_internal_varray_impl() const
+bool GVArrayImpl::try_assign_VArray(void *UNUSED(varray)) const
{
- return nullptr;
+ return false;
}
-/**
- * Creates a new `std::unique_ptr<GVArray>` based on this `GVArray`.
- * The lifetime of the returned virtual array must not be longer than the lifetime of this virtual
- * array.
- */
-GVArrayPtr GVArray::shallow_copy() const
+bool GVArrayImpl::may_have_ownership() const
{
- if (this->is_span()) {
- return std::make_unique<GVArray_For_GSpan>(this->get_internal_span());
- }
- if (this->is_single()) {
- BUFFER_FOR_CPP_TYPE_VALUE(*type_, buffer);
- this->get_internal_single(buffer);
- std::unique_ptr new_varray = std::make_unique<GVArray_For_SingleValue>(*type_, size_, buffer);
- type_->destruct(buffer);
- return new_varray;
- }
- return std::make_unique<GVArray_For_ShallowCopy>(*this);
+ /* Use true as default to avoid accidentally creating subclasses that have this set to false but
+ * actually own data. Subclasses should set the to false instead. */
+ return true;
}
/** \} */
/* -------------------------------------------------------------------- */
-/** \name #GVMutableArray
+/** \name #GVMutableArrayImpl
* \{ */
-void GVMutableArray::set_by_copy_impl(const int64_t index, const void *value)
+GVMutableArrayImpl::GVMutableArrayImpl(const CPPType &type, const int64_t size)
+ : GVArrayImpl(type, size)
+{
+}
+
+void GVMutableArrayImpl::set_by_copy(const int64_t index, const void *value)
{
BUFFER_FOR_CPP_TYPE_VALUE(*type_, buffer);
type_->copy_construct(value, buffer);
- this->set_by_move_impl(index, buffer);
+ this->set_by_move(index, buffer);
type_->destruct(buffer);
}
-void GVMutableArray::set_by_relocate_impl(const int64_t index, void *value)
+void GVMutableArrayImpl::set_by_relocate(const int64_t index, void *value)
{
- this->set_by_move_impl(index, value);
+ this->set_by_move(index, value);
type_->destruct(value);
}
-void GVMutableArray::set_all_impl(const void *src)
+void GVMutableArrayImpl::set_all(const void *src)
{
if (this->is_span()) {
- const GMutableSpan span = this->get_internal_span();
- type_->copy_assign_n(src, span.data(), size_);
+ const GSpan span = this->get_internal_span();
+ type_->copy_assign_n(src, const_cast<void *>(span.data()), size_);
}
else {
for (int64_t i : IndexRange(size_)) {
@@ -176,149 +115,224 @@ void GVMutableArray::set_all_impl(const void *src)
}
}
-void *GVMutableArray::try_get_internal_mutable_varray_impl()
-{
- return nullptr;
-}
-
void GVMutableArray::fill(const void *value)
{
if (this->is_span()) {
- const GMutableSpan span = this->get_internal_span();
- type_->fill_assign_n(value, span.data(), size_);
+ const GSpan span = this->get_internal_span();
+ this->type().fill_assign_n(value, const_cast<void *>(span.data()), this->size());
}
else {
- for (int64_t i : IndexRange(size_)) {
+ for (int64_t i : IndexRange(this->size())) {
this->set_by_copy(i, value);
}
}
}
+bool GVMutableArrayImpl::try_assign_VMutableArray(void *UNUSED(varray)) const
+{
+ return false;
+}
+
/** \} */
/* -------------------------------------------------------------------- */
-/** \name #GVArray_For_GSpan
+/** \name #GVArrayImpl_For_GSpan
* \{ */
-void GVArray_For_GSpan::get_impl(const int64_t index, void *r_value) const
+GVArrayImpl_For_GSpan::GVArrayImpl_For_GSpan(const GSpan span)
+ : GVArrayImpl(span.type(), span.size()), data_(span.data()), element_size_(span.type().size())
+{
+}
+
+GVArrayImpl_For_GSpan::GVArrayImpl_For_GSpan(const CPPType &type, const int64_t size)
+ : GVArrayImpl(type, size), element_size_(type.size())
+{
+}
+
+void GVArrayImpl_For_GSpan::get(const int64_t index, void *r_value) const
{
type_->copy_assign(POINTER_OFFSET(data_, element_size_ * index), r_value);
}
-void GVArray_For_GSpan::get_to_uninitialized_impl(const int64_t index, void *r_value) const
+void GVArrayImpl_For_GSpan::get_to_uninitialized(const int64_t index, void *r_value) const
{
type_->copy_construct(POINTER_OFFSET(data_, element_size_ * index), r_value);
}
-bool GVArray_For_GSpan::is_span_impl() const
+bool GVArrayImpl_For_GSpan::is_span() const
{
return true;
}
-GSpan GVArray_For_GSpan::get_internal_span_impl() const
+GSpan GVArrayImpl_For_GSpan::get_internal_span() const
{
return GSpan(*type_, data_, size_);
}
+/** See #VArrayImpl_For_Span_final. */
+class GVArrayImpl_For_GSpan_final final : public GVArrayImpl_For_GSpan {
+ public:
+ using GVArrayImpl_For_GSpan::GVArrayImpl_For_GSpan;
+
+ private:
+ bool may_have_ownership() const override
+ {
+ return false;
+ }
+};
+
/** \} */
/* -------------------------------------------------------------------- */
-/** \name #GVMutableArray_For_GMutableSpan
+/** \name #GVMutableArrayImpl_For_GMutableSpan
* \{ */
-void GVMutableArray_For_GMutableSpan::get_impl(const int64_t index, void *r_value) const
+GVMutableArrayImpl_For_GMutableSpan::GVMutableArrayImpl_For_GMutableSpan(const GMutableSpan span)
+ : GVMutableArrayImpl(span.type(), span.size()),
+ data_(span.data()),
+ element_size_(span.type().size())
+{
+}
+
+GVMutableArrayImpl_For_GMutableSpan::GVMutableArrayImpl_For_GMutableSpan(const CPPType &type,
+ const int64_t size)
+ : GVMutableArrayImpl(type, size), element_size_(type.size())
+{
+}
+
+void GVMutableArrayImpl_For_GMutableSpan::get(const int64_t index, void *r_value) const
{
type_->copy_assign(POINTER_OFFSET(data_, element_size_ * index), r_value);
}
-void GVMutableArray_For_GMutableSpan::get_to_uninitialized_impl(const int64_t index,
- void *r_value) const
+void GVMutableArrayImpl_For_GMutableSpan::get_to_uninitialized(const int64_t index,
+ void *r_value) const
{
type_->copy_construct(POINTER_OFFSET(data_, element_size_ * index), r_value);
}
-void GVMutableArray_For_GMutableSpan::set_by_copy_impl(const int64_t index, const void *value)
+void GVMutableArrayImpl_For_GMutableSpan::set_by_copy(const int64_t index, const void *value)
{
type_->copy_assign(value, POINTER_OFFSET(data_, element_size_ * index));
}
-void GVMutableArray_For_GMutableSpan::set_by_move_impl(const int64_t index, void *value)
+void GVMutableArrayImpl_For_GMutableSpan::set_by_move(const int64_t index, void *value)
{
type_->move_construct(value, POINTER_OFFSET(data_, element_size_ * index));
}
-void GVMutableArray_For_GMutableSpan::set_by_relocate_impl(const int64_t index, void *value)
+void GVMutableArrayImpl_For_GMutableSpan::set_by_relocate(const int64_t index, void *value)
{
type_->relocate_assign(value, POINTER_OFFSET(data_, element_size_ * index));
}
-bool GVMutableArray_For_GMutableSpan::is_span_impl() const
+bool GVMutableArrayImpl_For_GMutableSpan::is_span() const
{
return true;
}
-GSpan GVMutableArray_For_GMutableSpan::get_internal_span_impl() const
+GSpan GVMutableArrayImpl_For_GMutableSpan::get_internal_span() const
{
return GSpan(*type_, data_, size_);
}
+class GVMutableArrayImpl_For_GMutableSpan_final final
+ : public GVMutableArrayImpl_For_GMutableSpan {
+ public:
+ using GVMutableArrayImpl_For_GMutableSpan::GVMutableArrayImpl_For_GMutableSpan;
+
+ private:
+ bool may_have_ownership() const override
+ {
+ return false;
+ }
+};
+
/** \} */
/* -------------------------------------------------------------------- */
-/** \name #GVArray_For_SingleValueRef
+/** \name #GVArrayImpl_For_SingleValueRef
* \{ */
-void GVArray_For_SingleValueRef::get_impl(const int64_t UNUSED(index), void *r_value) const
-{
- type_->copy_assign(value_, r_value);
-}
+/* Generic virtual array where each element has the same value. The value is not owned. */
+class GVArrayImpl_For_SingleValueRef : public GVArrayImpl {
+ protected:
+ const void *value_ = nullptr;
-void GVArray_For_SingleValueRef::get_to_uninitialized_impl(const int64_t UNUSED(index),
- void *r_value) const
-{
- type_->copy_construct(value_, r_value);
-}
+ public:
+ GVArrayImpl_For_SingleValueRef(const CPPType &type, const int64_t size, const void *value)
+ : GVArrayImpl(type, size), value_(value)
+ {
+ }
-bool GVArray_For_SingleValueRef::is_span_impl() const
-{
- return size_ == 1;
-}
+ protected:
+ GVArrayImpl_For_SingleValueRef(const CPPType &type, const int64_t size) : GVArrayImpl(type, size)
+ {
+ }
-GSpan GVArray_For_SingleValueRef::get_internal_span_impl() const
-{
- return GSpan{*type_, value_, 1};
-}
+ void get(const int64_t UNUSED(index), void *r_value) const override
+ {
+ type_->copy_assign(value_, r_value);
+ }
+ void get_to_uninitialized(const int64_t UNUSED(index), void *r_value) const override
+ {
+ type_->copy_construct(value_, r_value);
+ }
-bool GVArray_For_SingleValueRef::is_single_impl() const
-{
- return true;
-}
+ bool is_span() const override
+ {
+ return size_ == 1;
+ }
+ GSpan get_internal_span() const override
+ {
+ return GSpan{*type_, value_, 1};
+ }
-void GVArray_For_SingleValueRef::get_internal_single_impl(void *r_value) const
-{
- type_->copy_assign(value_, r_value);
-}
+ bool is_single() const override
+ {
+ return true;
+ }
+ void get_internal_single(void *r_value) const override
+ {
+ type_->copy_assign(value_, r_value);
+ }
+};
+
+class GVArrayImpl_For_SingleValueRef_final final : public GVArrayImpl_For_SingleValueRef {
+ public:
+ using GVArrayImpl_For_SingleValueRef::GVArrayImpl_For_SingleValueRef;
+
+ private:
+ bool may_have_ownership() const override
+ {
+ return false;
+ }
+};
/** \} */
/* -------------------------------------------------------------------- */
-/** \name #GVArray_For_SingleValue
+/** \name #GVArrayImpl_For_SingleValue
* \{ */
-GVArray_For_SingleValue::GVArray_For_SingleValue(const CPPType &type,
- const int64_t size,
- const void *value)
- : GVArray_For_SingleValueRef(type, size)
-{
- value_ = MEM_mallocN_aligned(type.size(), type.alignment(), __func__);
- type.copy_construct(value, (void *)value_);
-}
+/* Same as GVArrayImpl_For_SingleValueRef, but the value is owned. */
+class GVArrayImpl_For_SingleValue : public GVArrayImpl_For_SingleValueRef,
+ NonCopyable,
+ NonMovable {
+ public:
+ GVArrayImpl_For_SingleValue(const CPPType &type, const int64_t size, const void *value)
+ : GVArrayImpl_For_SingleValueRef(type, size)
+ {
+ value_ = MEM_mallocN_aligned(type.size(), type.alignment(), __func__);
+ type.copy_construct(value, (void *)value_);
+ }
-GVArray_For_SingleValue::~GVArray_For_SingleValue()
-{
- type_->destruct((void *)value_);
- MEM_freeN((void *)value_);
-}
+ ~GVArrayImpl_For_SingleValue() override
+ {
+ type_->destruct((void *)value_);
+ MEM_freeN((void *)value_);
+ }
+};
/** \} */
@@ -326,7 +340,7 @@ GVArray_For_SingleValue::~GVArray_For_SingleValue()
/** \name #GVArray_GSpan
* \{ */
-GVArray_GSpan::GVArray_GSpan(const GVArray &varray) : GSpan(varray.type()), varray_(varray)
+GVArray_GSpan::GVArray_GSpan(GVArray varray) : GSpan(varray.type()), varray_(std::move(varray))
{
size_ = varray_.size();
if (varray_.is_span()) {
@@ -353,8 +367,8 @@ GVArray_GSpan::~GVArray_GSpan()
/** \name #GVMutableArray_GSpan
* \{ */
-GVMutableArray_GSpan::GVMutableArray_GSpan(GVMutableArray &varray, const bool copy_values_to_span)
- : GMutableSpan(varray.type()), varray_(varray)
+GVMutableArray_GSpan::GVMutableArray_GSpan(GVMutableArray varray, const bool copy_values_to_span)
+ : GMutableSpan(varray.type()), varray_(std::move(varray))
{
size_ = varray_.size();
if (varray_.is_span()) {
@@ -405,48 +419,314 @@ void GVMutableArray_GSpan::disable_not_applied_warning()
/** \} */
/* -------------------------------------------------------------------- */
-/** \name #GVArray_For_SlicedGVArray
+/** \name #GVArrayImpl_For_SlicedGVArray
* \{ */
-void GVArray_For_SlicedGVArray::get_impl(const int64_t index, void *r_value) const
+class GVArrayImpl_For_SlicedGVArray : public GVArrayImpl {
+ protected:
+ GVArray varray_;
+ int64_t offset_;
+
+ public:
+ GVArrayImpl_For_SlicedGVArray(GVArray varray, const IndexRange slice)
+ : GVArrayImpl(varray.type(), slice.size()),
+ varray_(std::move(varray)),
+ offset_(slice.start())
+ {
+ BLI_assert(slice.one_after_last() <= varray_.size());
+ }
+
+ void get(const int64_t index, void *r_value) const override
+ {
+ varray_.get(index + offset_, r_value);
+ }
+
+ void get_to_uninitialized(const int64_t index, void *r_value) const override
+ {
+ varray_.get_to_uninitialized(index + offset_, r_value);
+ }
+};
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name #GVArrayCommon
+ * \{ */
+
+GVArrayCommon::GVArrayCommon() = default;
+
+GVArrayCommon::GVArrayCommon(const GVArrayCommon &other) : storage_(other.storage_)
+{
+ impl_ = this->impl_from_storage();
+}
+
+GVArrayCommon::GVArrayCommon(GVArrayCommon &&other) noexcept : storage_(std::move(other.storage_))
+{
+ impl_ = this->impl_from_storage();
+ other.storage_.reset();
+ other.impl_ = nullptr;
+}
+
+GVArrayCommon::GVArrayCommon(const GVArrayImpl *impl) : impl_(impl)
+{
+ storage_ = impl_;
+}
+
+GVArrayCommon::GVArrayCommon(std::shared_ptr<const GVArrayImpl> impl) : impl_(impl.get())
+{
+ if (impl) {
+ storage_ = std::move(impl);
+ }
+}
+
+GVArrayCommon::~GVArrayCommon() = default;
+
+void GVArrayCommon::materialize(void *dst) const
+{
+ this->materialize(IndexMask(impl_->size()), dst);
+}
+
+void GVArrayCommon::materialize(const IndexMask mask, void *dst) const
+{
+ impl_->materialize(mask, dst);
+}
+
+void GVArrayCommon::materialize_to_uninitialized(void *dst) const
+{
+ this->materialize_to_uninitialized(IndexMask(impl_->size()), dst);
+}
+
+void GVArrayCommon::materialize_to_uninitialized(const IndexMask mask, void *dst) const
+{
+ BLI_assert(mask.min_array_size() <= impl_->size());
+ impl_->materialize_to_uninitialized(mask, dst);
+}
+
+bool GVArrayCommon::may_have_ownership() const
+{
+ return impl_->may_have_ownership();
+}
+
+void GVArrayCommon::copy_from(const GVArrayCommon &other)
+{
+ if (this == &other) {
+ return;
+ }
+ storage_ = other.storage_;
+ impl_ = this->impl_from_storage();
+}
+
+void GVArrayCommon::move_from(GVArrayCommon &&other) noexcept
+{
+ if (this == &other) {
+ return;
+ }
+ storage_ = std::move(other.storage_);
+ impl_ = this->impl_from_storage();
+ other.storage_.reset();
+ other.impl_ = nullptr;
+}
+
+/* Returns true when the virtual array is stored as a span internally. */
+bool GVArrayCommon::is_span() const
+{
+ if (this->is_empty()) {
+ return true;
+ }
+ return impl_->is_span();
+}
+
+/* Returns the internally used span of the virtual array. This invokes undefined behavior is the
+ * virtual array is not stored as a span internally. */
+GSpan GVArrayCommon::get_internal_span() const
{
- varray_.get(index + offset_, r_value);
+ BLI_assert(this->is_span());
+ if (this->is_empty()) {
+ return GSpan(impl_->type());
+ }
+ return impl_->get_internal_span();
}
-void GVArray_For_SlicedGVArray::get_to_uninitialized_impl(const int64_t index, void *r_value) const
+/* Returns true when the virtual array returns the same value for every index. */
+bool GVArrayCommon::is_single() const
{
- varray_.get_to_uninitialized(index + offset_, r_value);
+ if (impl_->size() == 1) {
+ return true;
+ }
+ return impl_->is_single();
+}
+
+/* Copies the value that is used for every element into `r_value`, which is expected to point to
+ * initialized memory. This invokes undefined behavior if the virtual array would not return the
+ * same value for every index. */
+void GVArrayCommon::get_internal_single(void *r_value) const
+{
+ BLI_assert(this->is_single());
+ if (impl_->size() == 1) {
+ impl_->get(0, r_value);
+ return;
+ }
+ impl_->get_internal_single(r_value);
+}
+
+/* Same as `get_internal_single`, but `r_value` points to initialized memory. */
+void GVArrayCommon::get_internal_single_to_uninitialized(void *r_value) const
+{
+ impl_->type().default_construct(r_value);
+ this->get_internal_single(r_value);
+}
+
+const GVArrayImpl *GVArrayCommon::impl_from_storage() const
+{
+ return storage_.extra_info().get_varray(storage_.get());
+}
+
+IndexRange GVArrayCommon::index_range() const
+{
+ return IndexRange(this->size());
}
/** \} */
/* -------------------------------------------------------------------- */
-/** \name #GVArray_Slice
+/** \name #GVArray
* \{ */
-GVArray_Slice::GVArray_Slice(const GVArray &varray, const IndexRange slice)
+GVArray::GVArray(const GVArray &other) = default;
+
+GVArray::GVArray(GVArray &&other) noexcept = default;
+
+GVArray::GVArray(const GVArrayImpl *impl) : GVArrayCommon(impl)
{
- if (varray.is_span()) {
- /* Create a new virtual for the sliced span. */
- const GSpan span = varray.get_internal_span();
- const GSpan sliced_span = span.slice(slice.start(), slice.size());
- varray_span_.emplace(sliced_span);
- varray_ = &*varray_span_;
- }
- else if (varray.is_single()) {
- /* Can just use the existing virtual array, because it's the same value for the indices in the
- * slice anyway. */
- varray_ = &varray;
- }
- else {
- /* Generic version when none of the above method works.
- * We don't necessarily want to materialize the input varray because there might be
- * large distances between the required indices. Then we would materialize many elements that
- * are not accessed later on.
- */
- varray_any_.emplace(varray, slice);
- varray_ = &*varray_any_;
+}
+
+GVArray::GVArray(std::shared_ptr<const GVArrayImpl> impl) : GVArrayCommon(std::move(impl))
+{
+}
+
+GVArray GVArray::ForSingle(const CPPType &type, const int64_t size, const void *value)
+{
+ return GVArray::For<GVArrayImpl_For_SingleValue>(type, size, value);
+}
+
+GVArray GVArray::ForSingleRef(const CPPType &type, const int64_t size, const void *value)
+{
+ return GVArray::For<GVArrayImpl_For_SingleValueRef_final>(type, size, value);
+}
+
+GVArray GVArray::ForSingleDefault(const CPPType &type, const int64_t size)
+{
+ return GVArray::ForSingleRef(type, size, type.default_value());
+}
+
+GVArray GVArray::ForSpan(GSpan span)
+{
+ return GVArray::For<GVArrayImpl_For_GSpan_final>(span);
+}
+
+class GVArrayImpl_For_GArray : public GVArrayImpl_For_GSpan {
+ protected:
+ GArray<> array_;
+
+ public:
+ GVArrayImpl_For_GArray(GArray<> array)
+ : GVArrayImpl_For_GSpan(array.as_span()), array_(std::move(array))
+ {
}
+};
+
+GVArray GVArray::ForGArray(GArray<> array)
+{
+ return GVArray::For<GVArrayImpl_For_GArray>(array);
+}
+
+GVArray GVArray::ForEmpty(const CPPType &type)
+{
+ return GVArray::ForSpan(GSpan(type));
+}
+
+GVArray GVArray::slice(IndexRange slice) const
+{
+ return GVArray::For<GVArrayImpl_For_SlicedGVArray>(*this, slice);
+}
+
+GVArray &GVArray::operator=(const GVArray &other)
+{
+ this->copy_from(other);
+ return *this;
+}
+
+GVArray &GVArray::operator=(GVArray &&other) noexcept
+{
+ this->move_from(std::move(other));
+ return *this;
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name #GVMutableArray
+ * \{ */
+
+GVMutableArray::GVMutableArray(const GVMutableArray &other) = default;
+GVMutableArray::GVMutableArray(GVMutableArray &&other) noexcept = default;
+
+GVMutableArray::GVMutableArray(GVMutableArrayImpl *impl) : GVArrayCommon(impl)
+{
+}
+
+GVMutableArray::GVMutableArray(std::shared_ptr<GVMutableArrayImpl> impl)
+ : GVArrayCommon(std::move(impl))
+{
+}
+
+GVMutableArray GVMutableArray::ForSpan(GMutableSpan span)
+{
+ return GVMutableArray::For<GVMutableArrayImpl_For_GMutableSpan_final>(span);
+}
+
+GVMutableArray::operator GVArray() const &
+{
+ GVArray varray;
+ varray.copy_from(*this);
+ return varray;
+}
+
+GVMutableArray::operator GVArray() &&noexcept
+{
+ GVArray varray;
+ varray.move_from(std::move(*this));
+ return varray;
+}
+
+GVMutableArray &GVMutableArray::operator=(const GVMutableArray &other)
+{
+ this->copy_from(other);
+ return *this;
+}
+
+GVMutableArray &GVMutableArray::operator=(GVMutableArray &&other) noexcept
+{
+ this->move_from(std::move(other));
+ return *this;
+}
+
+GVMutableArrayImpl *GVMutableArray::get_implementation() const
+{
+ return this->get_impl();
+}
+
+/* Copy the values from the source buffer to all elements in the virtual array. */
+void GVMutableArray::set_all(const void *src)
+{
+ this->get_impl()->set_all(src);
+}
+
+GMutableSpan GVMutableArray::get_internal_span() const
+{
+ BLI_assert(this->is_span());
+ const GSpan span = impl_->get_internal_span();
+ return GMutableSpan(span.type(), const_cast<void *>(span.data()), span.size());
}
/** \} */
diff --git a/source/blender/functions/intern/generic_virtual_vector_array.cc b/source/blender/functions/intern/generic_virtual_vector_array.cc
index 6b90ce993ae..e3c0d3109fa 100644
--- a/source/blender/functions/intern/generic_virtual_vector_array.cc
+++ b/source/blender/functions/intern/generic_virtual_vector_array.cc
@@ -18,13 +18,13 @@
namespace blender::fn {
-void GVArray_For_GVVectorArrayIndex::get_impl(const int64_t index_in_vector, void *r_value) const
+void GVArray_For_GVVectorArrayIndex::get(const int64_t index_in_vector, void *r_value) const
{
vector_array_.get_vector_element(index_, index_in_vector, r_value);
}
-void GVArray_For_GVVectorArrayIndex::get_to_uninitialized_impl(const int64_t index_in_vector,
- void *r_value) const
+void GVArray_For_GVVectorArrayIndex::get_to_uninitialized(const int64_t index_in_vector,
+ void *r_value) const
{
type_->default_construct(r_value);
vector_array_.get_vector_element(index_, index_in_vector, r_value);
@@ -32,14 +32,14 @@ void GVArray_For_GVVectorArrayIndex::get_to_uninitialized_impl(const int64_t ind
int64_t GVVectorArray_For_SingleGVArray::get_vector_size_impl(const int64_t UNUSED(index)) const
{
- return array_.size();
+ return varray_.size();
}
void GVVectorArray_For_SingleGVArray::get_vector_element_impl(const int64_t UNUSED(index),
const int64_t index_in_vector,
void *r_value) const
{
- array_.get(index_in_vector, r_value);
+ varray_.get(index_in_vector, r_value);
}
bool GVVectorArray_For_SingleGVArray::is_single_vector_impl() const
diff --git a/source/blender/functions/intern/multi_function.cc b/source/blender/functions/intern/multi_function.cc
index bb657f321ec..ee2c69068db 100644
--- a/source/blender/functions/intern/multi_function.cc
+++ b/source/blender/functions/intern/multi_function.cc
@@ -18,28 +18,9 @@
namespace blender::fn {
-class DummyMultiFunction : public MultiFunction {
- public:
- DummyMultiFunction()
- {
- static MFSignature signature = create_signature();
- this->set_signature(&signature);
- }
-
- static MFSignature create_signature()
- {
- MFSignatureBuilder signature{"Dummy"};
- return signature.build();
- }
-
- void call(IndexMask UNUSED(mask),
- MFParams UNUSED(params),
- MFContext UNUSED(context)) const override
- {
- }
-};
-
-static DummyMultiFunction dummy_multi_function_;
-const MultiFunction &dummy_multi_function = dummy_multi_function_;
+std::string MultiFunction::debug_name() const
+{
+ return signature_ref_->function_name;
+}
} // namespace blender::fn
diff --git a/source/blender/functions/intern/multi_function_builder.cc b/source/blender/functions/intern/multi_function_builder.cc
index f891f162820..24f9bbe0179 100644
--- a/source/blender/functions/intern/multi_function_builder.cc
+++ b/source/blender/functions/intern/multi_function_builder.cc
@@ -32,10 +32,8 @@ CustomMF_GenericConstant::CustomMF_GenericConstant(const CPPType &type,
}
value_ = value;
- MFSignatureBuilder signature{"Constant " + type.name()};
- std::stringstream ss;
- type.print_or_default(value, ss, type.name());
- signature.single_output(ss.str(), type);
+ MFSignatureBuilder signature{"Constant"};
+ signature.single_output("Value", type);
signature_ = signature.build();
this->set_signature(&signature_);
}
@@ -73,28 +71,11 @@ bool CustomMF_GenericConstant::equals(const MultiFunction &other) const
return type_.is_equal(value_, _other->value_);
}
-static std::string gspan_to_string(GSpan array)
-{
- const CPPType &type = array.type();
- std::stringstream ss;
- ss << "[";
- const int64_t max_amount = 5;
- for (int64_t i : IndexRange(std::min(max_amount, array.size()))) {
- type.print_or_default(array[i], ss, type.name());
- ss << ", ";
- }
- if (max_amount < array.size()) {
- ss << "...";
- }
- ss << "]";
- return ss.str();
-}
-
CustomMF_GenericConstantArray::CustomMF_GenericConstantArray(GSpan array) : array_(array)
{
const CPPType &type = array.type();
- MFSignatureBuilder signature{"Constant " + type.name() + " Vector"};
- signature.vector_output(gspan_to_string(array), type);
+ MFSignatureBuilder signature{"Constant Vector"};
+ signature.vector_output("Value", type);
signature_ = signature.build();
this->set_signature(&signature_);
}
@@ -109,12 +90,11 @@ void CustomMF_GenericConstantArray::call(IndexMask mask,
}
}
-CustomMF_DefaultOutput::CustomMF_DefaultOutput(StringRef name,
- Span<MFDataType> input_types,
+CustomMF_DefaultOutput::CustomMF_DefaultOutput(Span<MFDataType> input_types,
Span<MFDataType> output_types)
: output_amount_(output_types.size())
{
- MFSignatureBuilder signature{name};
+ MFSignatureBuilder signature{"Default Output"};
for (MFDataType data_type : input_types) {
signature.input("Input", data_type);
}
@@ -140,9 +120,9 @@ void CustomMF_DefaultOutput::call(IndexMask mask, MFParams params, MFContext UNU
}
}
-CustomMF_GenericCopy::CustomMF_GenericCopy(StringRef name, MFDataType data_type)
+CustomMF_GenericCopy::CustomMF_GenericCopy(MFDataType data_type)
{
- MFSignatureBuilder signature{name};
+ MFSignatureBuilder signature{"Copy"};
signature.input("Input", data_type);
signature.output("Output", data_type);
signature_ = signature.build();
diff --git a/source/blender/functions/intern/multi_function_parallel.cc b/source/blender/functions/intern/multi_function_parallel.cc
index 5a8c621f0b3..eefe647644d 100644
--- a/source/blender/functions/intern/multi_function_parallel.cc
+++ b/source/blender/functions/intern/multi_function_parallel.cc
@@ -54,7 +54,6 @@ void ParallelMultiFunction::call(IndexMask full_mask, MFParams params, MFContext
const IndexRange input_slice_range{input_slice_start, input_slice_size};
MFParamsBuilder sub_params{fn_, sub_mask.min_array_size()};
- ResourceScope &scope = sub_params.resource_scope();
/* All parameters are sliced so that the wrapped multi-function does not have to take care of
* the index offset. */
@@ -63,8 +62,7 @@ void ParallelMultiFunction::call(IndexMask full_mask, MFParams params, MFContext
switch (param_type.category()) {
case MFParamType::SingleInput: {
const GVArray &varray = params.readonly_single_input(param_index);
- const GVArray &sliced_varray = scope.construct<GVArray_Slice>(varray, input_slice_range);
- sub_params.add_readonly_single_input(sliced_varray);
+ sub_params.add_readonly_single_input(varray.slice(input_slice_range));
break;
}
case MFParamType::SingleMutable: {
diff --git a/source/blender/functions/intern/multi_function_procedure.cc b/source/blender/functions/intern/multi_function_procedure.cc
index 986c5dff0c4..804beb7d66f 100644
--- a/source/blender/functions/intern/multi_function_procedure.cc
+++ b/source/blender/functions/intern/multi_function_procedure.cc
@@ -782,7 +782,7 @@ class MFProcedureDotExport {
void instruction_to_string(const MFCallInstruction &instruction, std::stringstream &ss)
{
const MultiFunction &fn = instruction.fn();
- this->instruction_name_format(fn.name() + ": ", ss);
+ this->instruction_name_format(fn.debug_name() + ": ", ss);
for (const int param_index : fn.param_indices()) {
const MFParamType param_type = fn.param_type(param_index);
const MFVariable *variable = instruction.params()[param_index];
diff --git a/source/blender/functions/intern/multi_function_procedure_executor.cc b/source/blender/functions/intern/multi_function_procedure_executor.cc
index 6d2d121bafd..06c97fd1173 100644
--- a/source/blender/functions/intern/multi_function_procedure_executor.cc
+++ b/source/blender/functions/intern/multi_function_procedure_executor.cc
@@ -20,13 +20,12 @@
namespace blender::fn {
-MFProcedureExecutor::MFProcedureExecutor(std::string name, const MFProcedure &procedure)
- : procedure_(procedure)
+MFProcedureExecutor::MFProcedureExecutor(const MFProcedure &procedure) : procedure_(procedure)
{
- MFSignatureBuilder signature(std::move(name));
+ MFSignatureBuilder signature("Procedure Executor");
for (const ConstMFParameter &param : procedure.params()) {
- signature.add(param.variable->name(), MFParamType(param.type, param.variable->data_type()));
+ signature.add("Parameter", MFParamType(param.type, param.variable->data_type()));
}
signature_ = signature.build();
@@ -66,6 +65,7 @@ struct VariableValue_GVArray : public VariableValue {
VariableValue_GVArray(const GVArray &data) : VariableValue(static_type), data(data)
{
+ BLI_assert(data);
}
};
@@ -756,7 +756,7 @@ class VariableState : NonCopyable, NonMovable {
switch (value_->type) {
case ValueType::GVArray: {
- const GVArray_Typed<bool> varray{this->value_as<VariableValue_GVArray>()->data};
+ const VArray<bool> varray = this->value_as<VariableValue_GVArray>()->data.typed<bool>();
for (const int i : mask) {
r_indices[varray[i]].append(i);
}
diff --git a/source/blender/functions/tests/FN_field_test.cc b/source/blender/functions/tests/FN_field_test.cc
index 041cdbd0f00..4614f9eee58 100644
--- a/source/blender/functions/tests/FN_field_test.cc
+++ b/source/blender/functions/tests/FN_field_test.cc
@@ -34,14 +34,12 @@ class IndexFieldInput final : public FieldInput {
{
}
- const GVArray *get_varray_for_context(const FieldContext &UNUSED(context),
- IndexMask mask,
- ResourceScope &scope) const final
+ GVArray get_varray_for_context(const FieldContext &UNUSED(context),
+ IndexMask mask,
+ ResourceScope &UNUSED(scope)) const final
{
auto index_func = [](int i) { return i; };
- return &scope.construct<
- GVArray_For_EmbeddedVArray<int, VArray_For_Func<int, decltype(index_func)>>>(
- mask.min_array_size(), mask.min_array_size(), index_func);
+ return VArray<int>::ForFunc(mask.min_array_size(), index_func);
}
};
@@ -162,9 +160,9 @@ class TwoOutputFunction : public MultiFunction {
MFSignature signature_;
public:
- TwoOutputFunction(StringRef name)
+ TwoOutputFunction()
{
- MFSignatureBuilder signature{name};
+ MFSignatureBuilder signature{"Two Outputs"};
signature.single_input<int>("In1");
signature.single_input<int>("In2");
signature.single_output<int>("Add");
@@ -192,8 +190,8 @@ TEST(field, FunctionTwoOutputs)
GField index_field_1{std::make_shared<IndexFieldInput>()};
GField index_field_2{std::make_shared<IndexFieldInput>()};
- std::shared_ptr<FieldOperation> fn = std::make_shared<FieldOperation>(FieldOperation(
- std::make_unique<TwoOutputFunction>("SI_SI_SO_SO"), {index_field_1, index_field_2}));
+ std::shared_ptr<FieldOperation> fn = std::make_shared<FieldOperation>(
+ FieldOperation(std::make_unique<TwoOutputFunction>(), {index_field_1, index_field_2}));
GField result_field_1{fn, 0};
GField result_field_2{fn, 1};
@@ -223,8 +221,8 @@ TEST(field, TwoFunctionsTwoOutputs)
{
GField index_field{std::make_shared<IndexFieldInput>()};
- std::shared_ptr<FieldOperation> fn = std::make_shared<FieldOperation>(FieldOperation(
- std::make_unique<TwoOutputFunction>("SI_SI_SO_SO"), {index_field, index_field}));
+ std::shared_ptr<FieldOperation> fn = std::make_shared<FieldOperation>(
+ FieldOperation(std::make_unique<TwoOutputFunction>(), {index_field, index_field}));
Array<int64_t> mask_indices = {2, 4, 6, 8};
IndexMask mask = mask_indices.as_span();
@@ -240,20 +238,20 @@ TEST(field, TwoFunctionsTwoOutputs)
FieldContext field_context;
FieldEvaluator field_evaluator{field_context, &mask};
- const VArray<int> *result_1 = nullptr;
- const VArray<int> *result_2 = nullptr;
+ VArray<int> result_1;
+ VArray<int> result_2;
field_evaluator.add(result_field_1, &result_1);
field_evaluator.add(result_field_2, &result_2);
field_evaluator.evaluate();
- EXPECT_EQ(result_1->get(2), 4);
- EXPECT_EQ(result_1->get(4), 8);
- EXPECT_EQ(result_1->get(6), 12);
- EXPECT_EQ(result_1->get(8), 16);
- EXPECT_EQ(result_2->get(2), 24);
- EXPECT_EQ(result_2->get(4), 28);
- EXPECT_EQ(result_2->get(6), 32);
- EXPECT_EQ(result_2->get(8), 36);
+ EXPECT_EQ(result_1.get(2), 4);
+ EXPECT_EQ(result_1.get(4), 8);
+ EXPECT_EQ(result_1.get(6), 12);
+ EXPECT_EQ(result_1.get(8), 16);
+ EXPECT_EQ(result_2.get(2), 24);
+ EXPECT_EQ(result_2.get(4), 28);
+ EXPECT_EQ(result_2.get(6), 32);
+ EXPECT_EQ(result_2.get(8), 36);
}
TEST(field, SameFieldTwice)
@@ -264,16 +262,16 @@ TEST(field, SameFieldTwice)
FieldContext field_context;
IndexMask mask{IndexRange(2)};
ResourceScope scope;
- Vector<const GVArray *> results = evaluate_fields(
+ Vector<GVArray> results = evaluate_fields(
scope, {constant_field, constant_field}, mask, field_context);
- GVArray_Typed<int> varray1{*results[0]};
- GVArray_Typed<int> varray2{*results[1]};
+ VArray<int> varray1 = results[0].typed<int>();
+ VArray<int> varray2 = results[1].typed<int>();
- EXPECT_EQ(varray1->get(0), 10);
- EXPECT_EQ(varray1->get(1), 10);
- EXPECT_EQ(varray2->get(0), 10);
- EXPECT_EQ(varray2->get(1), 10);
+ EXPECT_EQ(varray1.get(0), 10);
+ EXPECT_EQ(varray1.get(1), 10);
+ EXPECT_EQ(varray2.get(0), 10);
+ EXPECT_EQ(varray2.get(1), 10);
}
TEST(field, IgnoredOutput)
@@ -283,12 +281,12 @@ TEST(field, IgnoredOutput)
FieldContext field_context;
FieldEvaluator field_evaluator{field_context, 10};
- const VArray<int> *results = nullptr;
+ VArray<int> results;
field_evaluator.add(field, &results);
field_evaluator.evaluate();
- EXPECT_EQ(results->get(0), 5);
- EXPECT_EQ(results->get(3), 5);
+ EXPECT_EQ(results.get(0), 5);
+ EXPECT_EQ(results.get(3), 5);
}
} // namespace blender::fn::tests
diff --git a/source/blender/functions/tests/FN_multi_function_procedure_test.cc b/source/blender/functions/tests/FN_multi_function_procedure_test.cc
index 0b4b88fba3d..e3de23550c5 100644
--- a/source/blender/functions/tests/FN_multi_function_procedure_test.cc
+++ b/source/blender/functions/tests/FN_multi_function_procedure_test.cc
@@ -9,6 +9,43 @@
namespace blender::fn::tests {
+TEST(multi_function_procedure, ConstantOutput)
+{
+ /**
+ * procedure(int *var2) {
+ * var1 = 5;
+ * var2 = var1 + var1;
+ * }
+ */
+
+ CustomMF_Constant<int> constant_fn{5};
+ CustomMF_SI_SI_SO<int, int, int> add_fn{"Add", [](int a, int b) { return a + b; }};
+
+ MFProcedure procedure;
+ MFProcedureBuilder builder{procedure};
+
+ auto [var1] = builder.add_call<1>(constant_fn);
+ auto [var2] = builder.add_call<1>(add_fn, {var1, var1});
+ builder.add_destruct(*var1);
+ builder.add_return();
+ builder.add_output_parameter(*var2);
+
+ EXPECT_TRUE(procedure.validate());
+
+ MFProcedureExecutor executor{procedure};
+
+ MFParamsBuilder params{executor, 2};
+ MFContextBuilder context;
+
+ Array<int> output_array(2);
+ params.add_uninitialized_single_output(output_array.as_mutable_span());
+
+ executor.call(IndexRange(2), params, context);
+
+ EXPECT_EQ(output_array[0], 10);
+ EXPECT_EQ(output_array[1], 10);
+}
+
TEST(multi_function_procedure, SimpleTest)
{
/**
@@ -36,7 +73,7 @@ TEST(multi_function_procedure, SimpleTest)
EXPECT_TRUE(procedure.validate());
- MFProcedureExecutor executor{"My Procedure", procedure};
+ MFProcedureExecutor executor{procedure};
MFParamsBuilder params{executor, 3};
MFContextBuilder context;
@@ -88,7 +125,7 @@ TEST(multi_function_procedure, BranchTest)
EXPECT_TRUE(procedure.validate());
- MFProcedureExecutor procedure_fn{"Condition Test", procedure};
+ MFProcedureExecutor procedure_fn{procedure};
MFParamsBuilder params(procedure_fn, 5);
Array<int> values_a = {1, 5, 3, 6, 2};
@@ -130,7 +167,7 @@ TEST(multi_function_procedure, EvaluateOne)
builder.add_return();
builder.add_output_parameter(*var2);
- MFProcedureExecutor procedure_fn{"Evaluate One", procedure};
+ MFProcedureExecutor procedure_fn{procedure};
MFParamsBuilder params{procedure_fn, 5};
Array<int> values_out = {1, 2, 3, 4, 5};
@@ -202,7 +239,7 @@ TEST(multi_function_procedure, SimpleLoop)
EXPECT_TRUE(procedure.validate());
- MFProcedureExecutor procedure_fn{"Simple Loop", procedure};
+ MFProcedureExecutor procedure_fn{procedure};
MFParamsBuilder params{procedure_fn, 5};
Array<int> counts = {4, 3, 7, 6, 4};
@@ -258,7 +295,7 @@ TEST(multi_function_procedure, Vectors)
EXPECT_TRUE(procedure.validate());
- MFProcedureExecutor procedure_fn{"Vectors", procedure};
+ MFProcedureExecutor procedure_fn{procedure};
MFParamsBuilder params{procedure_fn, 5};
Array<int> v1 = {5, 2, 3};
@@ -322,7 +359,7 @@ TEST(multi_function_procedure, BufferReuse)
EXPECT_TRUE(procedure.validate());
- MFProcedureExecutor procedure_fn{"Buffer Reuse", procedure};
+ MFProcedureExecutor procedure_fn{procedure};
Array<int> inputs = {4, 1, 6, 2, 3};
Array<int> results(5, -1);
diff --git a/source/blender/functions/tests/FN_multi_function_test.cc b/source/blender/functions/tests/FN_multi_function_test.cc
index d99993b35ac..20ca00cf598 100644
--- a/source/blender/functions/tests/FN_multi_function_test.cc
+++ b/source/blender/functions/tests/FN_multi_function_test.cc
@@ -264,7 +264,6 @@ TEST(multi_function, CustomMF_GenericConstant)
{
int value = 42;
CustomMF_GenericConstant fn{CPPType::get<int32_t>(), (const void *)&value, false};
- EXPECT_EQ(fn.param_name(0), "42");
Array<int> outputs(4, 0);
@@ -285,7 +284,6 @@ TEST(multi_function, CustomMF_GenericConstantArray)
{
std::array<int, 4> values = {3, 4, 5, 6};
CustomMF_GenericConstantArray fn{GSpan(Span(values))};
- EXPECT_EQ(fn.param_name(0), "[3, 4, 5, 6, ]");
GVectorArray vector_array{CPPType::get<int32_t>(), 4};
GVectorArray_TypedMutableRef<int> vector_array_ref{vector_array};
diff --git a/source/blender/geometry/intern/mesh_to_curve_convert.cc b/source/blender/geometry/intern/mesh_to_curve_convert.cc
index 24f0b6308ba..7aaaec9f0c5 100644
--- a/source/blender/geometry/intern/mesh_to_curve_convert.cc
+++ b/source/blender/geometry/intern/mesh_to_curve_convert.cc
@@ -50,23 +50,23 @@ static void copy_attributes_to_points(CurveEval &curve,
/* Copy builtin control point attributes. */
if (source_attribute_ids.contains("tilt")) {
- const fn::GVArray_Typed<float> tilt_attribute = mesh_component.attribute_get_for_read<float>(
+ const VArray<float> tilt_attribute = mesh_component.attribute_get_for_read<float>(
"tilt", ATTR_DOMAIN_POINT, 0.0f);
threading::parallel_for(splines.index_range(), 256, [&](IndexRange range) {
for (const int i : range) {
copy_attribute_to_points<float>(
- *tilt_attribute, point_to_vert_maps[i], splines[i]->tilts());
+ tilt_attribute, point_to_vert_maps[i], splines[i]->tilts());
}
});
source_attribute_ids.remove_contained("tilt");
}
if (source_attribute_ids.contains("radius")) {
- const fn::GVArray_Typed<float> radius_attribute = mesh_component.attribute_get_for_read<float>(
+ const VArray<float> radius_attribute = mesh_component.attribute_get_for_read<float>(
"radius", ATTR_DOMAIN_POINT, 1.0f);
threading::parallel_for(splines.index_range(), 256, [&](IndexRange range) {
for (const int i : range) {
copy_attribute_to_points<float>(
- *radius_attribute, point_to_vert_maps[i], splines[i]->radii());
+ radius_attribute, point_to_vert_maps[i], splines[i]->radii());
}
});
source_attribute_ids.remove_contained("radius");
@@ -82,7 +82,7 @@ static void copy_attributes_to_points(CurveEval &curve,
continue;
}
- const fn::GVArrayPtr mesh_attribute = mesh_component.attribute_try_get_for_read(
+ const fn::GVArray mesh_attribute = mesh_component.attribute_try_get_for_read(
attribute_id, ATTR_DOMAIN_POINT);
/* Some attributes might not exist if they were builtin attribute on domains that don't
* have any elements, i.e. a face attribute on the output of the line primitive node. */
@@ -90,7 +90,7 @@ static void copy_attributes_to_points(CurveEval &curve,
continue;
}
- const CustomDataType data_type = bke::cpp_type_to_custom_data_type(mesh_attribute->type());
+ const CustomDataType data_type = bke::cpp_type_to_custom_data_type(mesh_attribute.type());
threading::parallel_for(splines.index_range(), 128, [&](IndexRange range) {
for (const int i : range) {
@@ -101,10 +101,10 @@ static void copy_attributes_to_points(CurveEval &curve,
BLI_assert(spline_attribute);
/* Copy attribute based on the map for this spline. */
- attribute_math::convert_to_static_type(mesh_attribute->type(), [&](auto dummy) {
+ attribute_math::convert_to_static_type(mesh_attribute.type(), [&](auto dummy) {
using T = decltype(dummy);
copy_attribute_to_points<T>(
- mesh_attribute->typed<T>(), point_to_vert_maps[i], spline_attribute->typed<T>());
+ mesh_attribute.typed<T>(), point_to_vert_maps[i], spline_attribute->typed<T>());
});
}
});
diff --git a/source/blender/gpencil_modifiers/intern/lineart/lineart_cpu.c b/source/blender/gpencil_modifiers/intern/lineart/lineart_cpu.c
index 88d717eb032..3773af70498 100644
--- a/source/blender/gpencil_modifiers/intern/lineart/lineart_cpu.c
+++ b/source/blender/gpencil_modifiers/intern/lineart/lineart_cpu.c
@@ -579,9 +579,7 @@ static int lineart_point_on_line_segment(double v[2], double v0[2], double v1[2]
c2 = ratiod(v0[1], v1[1], v[1]);
return (c2 >= -DBL_TRIANGLE_LIM && c2 <= 1 + DBL_TRIANGLE_LIM);
}
- else {
- return false;
- }
+ return false;
}
if (!LRT_DOUBLE_CLOSE_ENOUGH(v1[1], v0[1])) {
@@ -592,9 +590,7 @@ static int lineart_point_on_line_segment(double v[2], double v0[2], double v1[2]
c1 = ratiod(v0[0], v1[0], v[0]);
return (c1 >= -DBL_TRIANGLE_LIM && c1 <= 1 + DBL_TRIANGLE_LIM);
}
- else {
- return false;
- }
+ return false;
}
if (LRT_DOUBLE_CLOSE_ENOUGH(c1, c2) && c1 >= 0 && c1 <= 1) {
diff --git a/source/blender/gpu/CMakeLists.txt b/source/blender/gpu/CMakeLists.txt
index b92b341fb73..4868096e594 100644
--- a/source/blender/gpu/CMakeLists.txt
+++ b/source/blender/gpu/CMakeLists.txt
@@ -37,6 +37,7 @@ set(INC
../imbuf
../makesdna
../makesrna
+ ../windowmanager
../editors/include
diff --git a/source/blender/gpu/GPU_immediate_util.h b/source/blender/gpu/GPU_immediate_util.h
index 0d3d39839b2..047c3d3da00 100644
--- a/source/blender/gpu/GPU_immediate_util.h
+++ b/source/blender/gpu/GPU_immediate_util.h
@@ -92,6 +92,7 @@ void imm_draw_cylinder_wire_3d(
void imm_draw_cylinder_fill_3d(
uint pos, float base, float top, float height, int slices, int stacks);
+void imm_drawcircball(const float cent[3], float rad, const float tmat[4][4], uint pos);
#ifdef __cplusplus
}
#endif
diff --git a/source/blender/gpu/intern/gpu_immediate_util.c b/source/blender/gpu/intern/gpu_immediate_util.c
index 032974db8d1..df18b89bd67 100644
--- a/source/blender/gpu/intern/gpu_immediate_util.c
+++ b/source/blender/gpu/intern/gpu_immediate_util.c
@@ -602,3 +602,55 @@ void imm_draw_cylinder_fill_3d(
}
immEnd();
}
+
+/* Circle Drawing - Tables for Optimized Drawing Speed */
+#define CIRCLE_RESOL 32
+
+static void circball_array_fill(const float verts[CIRCLE_RESOL][3],
+ const float cent[3],
+ float rad,
+ const float tmat[4][4])
+{
+ /* 32 values of sin function (still same result!) */
+ const float sinval[CIRCLE_RESOL] = {
+ 0.00000000, 0.20129852, 0.39435585, 0.57126821, 0.72479278, 0.84864425, 0.93775213,
+ 0.98846832, 0.99871650, 0.96807711, 0.89780453, 0.79077573, 0.65137248, 0.48530196,
+ 0.29936312, 0.10116832, -0.10116832, -0.29936312, -0.48530196, -0.65137248, -0.79077573,
+ -0.89780453, -0.96807711, -0.99871650, -0.98846832, -0.93775213, -0.84864425, -0.72479278,
+ -0.57126821, -0.39435585, -0.20129852, 0.00000000,
+ };
+
+ /* 32 values of cos function (still same result!) */
+ const float cosval[CIRCLE_RESOL] = {
+ 1.00000000, 0.97952994, 0.91895781, 0.82076344, 0.68896691, 0.52896401, 0.34730525,
+ 0.15142777, -0.05064916, -0.25065253, -0.44039415, -0.61210598, -0.75875812, -0.87434661,
+ -0.95413925, -0.99486932, -0.99486932, -0.95413925, -0.87434661, -0.75875812, -0.61210598,
+ -0.44039415, -0.25065253, -0.05064916, 0.15142777, 0.34730525, 0.52896401, 0.68896691,
+ 0.82076344, 0.91895781, 0.97952994, 1.00000000,
+ };
+
+ float vx[3], vy[3];
+ float *viter = (float *)verts;
+
+ mul_v3_v3fl(vx, tmat[0], rad);
+ mul_v3_v3fl(vy, tmat[1], rad);
+
+ for (uint a = 0; a < CIRCLE_RESOL; a++, viter += 3) {
+ viter[0] = cent[0] + sinval[a] * vx[0] + cosval[a] * vy[0];
+ viter[1] = cent[1] + sinval[a] * vx[1] + cosval[a] * vy[1];
+ viter[2] = cent[2] + sinval[a] * vx[2] + cosval[a] * vy[2];
+ }
+}
+
+void imm_drawcircball(const float cent[3], float rad, const float tmat[4][4], uint pos)
+{
+ float verts[CIRCLE_RESOL][3];
+
+ circball_array_fill(verts, cent, rad, tmat);
+
+ immBegin(GPU_PRIM_LINE_LOOP, CIRCLE_RESOL);
+ for (int i = 0; i < CIRCLE_RESOL; i++) {
+ immVertex3fv(pos, verts[i]);
+ }
+ immEnd();
+}
diff --git a/source/blender/gpu/tests/gpu_testing.cc b/source/blender/gpu/tests/gpu_testing.cc
index ac42c5875c8..7fd473069c2 100644
--- a/source/blender/gpu/tests/gpu_testing.cc
+++ b/source/blender/gpu/tests/gpu_testing.cc
@@ -18,6 +18,7 @@ void GPUTest::SetUp()
CLG_init();
ghost_system = GHOST_CreateSystem();
ghost_context = GHOST_CreateOpenGLContext(ghost_system, glSettings);
+ GHOST_ActivateOpenGLContext(ghost_context);
context = GPU_context_create(nullptr);
GPU_init();
}
diff --git a/source/blender/imbuf/intern/anim_movie.c b/source/blender/imbuf/intern/anim_movie.c
index 87f2fd124c0..1d81653c7cd 100644
--- a/source/blender/imbuf/intern/anim_movie.c
+++ b/source/blender/imbuf/intern/anim_movie.c
@@ -58,6 +58,8 @@
#include "BLI_threads.h"
#include "BLI_utildefines.h"
+#include "DNA_scene_types.h"
+
#include "MEM_guardedalloc.h"
#ifdef WITH_AVI
@@ -1443,7 +1445,15 @@ static ImBuf *ffmpeg_fetchibuf(struct anim *anim, int position, IMB_Timecode_Typ
*
* The issue was reported to FFmpeg under ticket #8747 in the FFmpeg tracker
* and is fixed in the newer versions than 4.3.1. */
- anim->cur_frame_final = IMB_allocImBuf(anim->x, anim->y, 32, 0);
+
+ const AVPixFmtDescriptor *pix_fmt_descriptor = av_pix_fmt_desc_get(anim->pCodecCtx->pix_fmt);
+
+ int planes = R_IMF_PLANES_RGBA;
+ if ((pix_fmt_descriptor->flags & AV_PIX_FMT_FLAG_ALPHA) == 0) {
+ planes = R_IMF_PLANES_RGB;
+ }
+
+ anim->cur_frame_final = IMB_allocImBuf(anim->x, anim->y, planes, 0);
anim->cur_frame_final->rect = MEM_mallocN_aligned(
(size_t)4 * anim->x * anim->y, 32, "ffmpeg ibuf");
anim->cur_frame_final->mall |= IB_rect;
diff --git a/source/blender/imbuf/intern/indexer.c b/source/blender/imbuf/intern/indexer.c
index bbb0f3b5b22..6cd87e29c9d 100644
--- a/source/blender/imbuf/intern/indexer.c
+++ b/source/blender/imbuf/intern/indexer.c
@@ -183,13 +183,13 @@ struct anim_index *IMB_indexer_open(const char *name)
header[12] = 0;
if (memcmp(header, binary_header_str, 8) != 0) {
- fprintf(stderr, "Error reading %s: Binary file type string missmatch\n", name);
+ fprintf(stderr, "Error reading %s: Binary file type string mismatch\n", name);
fclose(fp);
return NULL;
}
if (atoi(header + 9) != INDEX_FILE_VERSION) {
- fprintf(stderr, "Error reading %s: File version missmatch\n", name);
+ fprintf(stderr, "Error reading %s: File version mismatch\n", name);
fclose(fp);
return NULL;
}
@@ -222,7 +222,7 @@ struct anim_index *IMB_indexer_open(const char *name)
}
if (UNLIKELY(items_read != idx->num_entries * 5)) {
- fprintf(stderr, "Error: Element data size missmatch in: %s\n", name);
+ fprintf(stderr, "Error: Element data size mismatch in: %s\n", name);
MEM_freeN(idx->entries);
MEM_freeN(idx);
fclose(fp);
diff --git a/source/blender/imbuf/intern/moviecache.c b/source/blender/imbuf/intern/moviecache.c
index 4f316150e10..773a3486233 100644
--- a/source/blender/imbuf/intern/moviecache.c
+++ b/source/blender/imbuf/intern/moviecache.c
@@ -122,7 +122,12 @@ static void moviecache_valfree(void *val)
PRINT("%s: cache '%s' free item %p buffer %p\n", __func__, cache->name, item, item->ibuf);
- MEM_CacheLimiter_unmanage(item->c_handle);
+ if (item->c_handle) {
+ BLI_mutex_lock(&limitor_lock);
+ MEM_CacheLimiter_unmanage(item->c_handle);
+ BLI_mutex_unlock(&limitor_lock);
+ }
+
if (item->ibuf) {
IMB_freeImBuf(item->ibuf);
}
@@ -263,6 +268,7 @@ void IMB_moviecache_destruct(void)
{
if (limitor) {
delete_MEM_CacheLimiter(limitor);
+ limitor = NULL;
}
}
diff --git a/source/blender/io/alembic/exporter/abc_writer_mesh.cc b/source/blender/io/alembic/exporter/abc_writer_mesh.cc
index 8f410978211..7275d0addf0 100644
--- a/source/blender/io/alembic/exporter/abc_writer_mesh.cc
+++ b/source/blender/io/alembic/exporter/abc_writer_mesh.cc
@@ -166,9 +166,10 @@ void ABCGenericMeshWriter::do_write(HierarchyContext &context)
const int quad_method = args_.export_params->quad_method;
const int ngon_method = args_.export_params->ngon_method;
- struct BMeshCreateParams bmcp = {false};
- struct BMeshFromMeshParams bmfmp = {true, false, false, 0};
- BMesh *bm = BKE_mesh_to_bmesh_ex(mesh, &bmcp, &bmfmp);
+ BMeshCreateParams bmesh_create_params{};
+ BMeshFromMeshParams bmesh_from_mesh_params{};
+ bmesh_from_mesh_params.calc_face_normal = true;
+ BMesh *bm = BKE_mesh_to_bmesh_ex(mesh, &bmesh_create_params, &bmesh_from_mesh_params);
BM_mesh_triangulate(bm, quad_method, ngon_method, 4, tag_only, nullptr, nullptr, nullptr);
@@ -189,6 +190,7 @@ void ABCGenericMeshWriter::do_write(HierarchyContext &context)
m_custom_data_config.totpoly = mesh->totpoly;
m_custom_data_config.totloop = mesh->totloop;
m_custom_data_config.totvert = mesh->totvert;
+ m_custom_data_config.timesample_index = timesample_index_;
try {
if (is_subd_) {
@@ -350,7 +352,7 @@ void ABCGenericMeshWriter::write_face_sets(Object *object, struct Mesh *mesh, Sc
void ABCGenericMeshWriter::write_arb_geo_params(struct Mesh *me)
{
- if (frame_has_been_written_ || !args_.export_params->vcolors) {
+ if (!args_.export_params->vcolors) {
return;
}
diff --git a/source/blender/io/alembic/intern/abc_customdata.cc b/source/blender/io/alembic/intern/abc_customdata.cc
index 087d60f8896..188e8daac8f 100644
--- a/source/blender/io/alembic/intern/abc_customdata.cc
+++ b/source/blender/io/alembic/intern/abc_customdata.cc
@@ -176,29 +176,23 @@ static void write_uv(const OCompoundProperty &prop,
UInt32ArraySample(&indices.front(), indices.size()),
kFacevaryingScope);
param.set(sample);
+ param.setTimeSampling(config.timesample_index);
config.abc_uv_maps[uv_map_name] = param;
}
-/* Convention to write Vertex Colors:
- * - C3fGeomParam/C4fGeomParam on the arbGeomParam
- * - set scope as vertex varying
- */
-static void write_mcol(const OCompoundProperty &prop,
- const CDStreamConfig &config,
- void *data,
- const char *name)
+static void get_cols(const CDStreamConfig &config,
+ std::vector<Imath::C4f> &buffer,
+ std::vector<uint32_t> &uvidx,
+ void *cd_data)
{
const float cscale = 1.0f / 255.0f;
MPoly *polys = config.mpoly;
MLoop *mloops = config.mloop;
- MCol *cfaces = static_cast<MCol *>(data);
-
- std::vector<Imath::C4f> buffer;
- std::vector<uint32_t> indices;
+ MCol *cfaces = static_cast<MCol *>(cd_data);
buffer.reserve(config.totvert);
- indices.reserve(config.totvert);
+ uvidx.reserve(config.totvert);
Imath::C4f col;
@@ -217,17 +211,44 @@ static void write_mcol(const OCompoundProperty &prop,
col[3] = cface->b * cscale;
buffer.push_back(col);
- indices.push_back(buffer.size() - 1);
+ uvidx.push_back(buffer.size() - 1);
}
}
+}
+
+/* Convention to write Vertex Colors:
+ * - C3fGeomParam/C4fGeomParam on the arbGeomParam
+ * - set scope as vertex varying
+ */
+static void write_mcol(const OCompoundProperty &prop,
+ CDStreamConfig &config,
+ void *data,
+ const char *name)
+{
+ std::vector<uint32_t> indices;
+ std::vector<Imath::C4f> buffer;
+
+ get_cols(config, buffer, indices, data);
+
+ if (indices.empty() || buffer.empty()) {
+ return;
+ }
- OC4fGeomParam param(prop, name, true, kFacevaryingScope, 1);
+ std::string vcol_name(name);
+ OC4fGeomParam param = config.abc_vertex_colors[vcol_name];
+
+ if (!param.valid()) {
+ param = OC4fGeomParam(prop, name, true, kFacevaryingScope, 1);
+ }
OC4fGeomParam::Sample sample(C4fArraySample(&buffer.front(), buffer.size()),
UInt32ArraySample(&indices.front(), indices.size()),
kVertexScope);
param.set(sample);
+ param.setTimeSampling(config.timesample_index);
+
+ config.abc_vertex_colors[vcol_name] = param;
}
void write_generated_coordinates(const OCompoundProperty &prop, CDStreamConfig &config)
diff --git a/source/blender/io/alembic/intern/abc_customdata.h b/source/blender/io/alembic/intern/abc_customdata.h
index 03e6f697f0c..5eae6307474 100644
--- a/source/blender/io/alembic/intern/abc_customdata.h
+++ b/source/blender/io/alembic/intern/abc_customdata.h
@@ -66,6 +66,7 @@ struct CDStreamConfig {
float weight;
float time;
+ int timesample_index;
bool use_vertex_interpolation;
Alembic::AbcGeom::index_t index;
Alembic::AbcGeom::index_t ceil_index;
@@ -82,6 +83,9 @@ struct CDStreamConfig {
/* ORCO coordinates, aka Generated Coordinates. */
Alembic::AbcGeom::OV3fGeomParam abc_orco;
+ /* Mapping from vertex color layer name to its Alembic color data. */
+ std::map<std::string, Alembic::AbcGeom::OC4fGeomParam> abc_vertex_colors;
+
CDStreamConfig()
: mloop(NULL),
totloop(0),
diff --git a/source/blender/io/avi/intern/avi.c b/source/blender/io/avi/intern/avi.c
index 87058693378..221e56ac793 100644
--- a/source/blender/io/avi/intern/avi.c
+++ b/source/blender/io/avi/intern/avi.c
@@ -591,7 +591,7 @@ AviError AVI_open_movie(const char *name, AviMovie *movie)
BLI_fseek(movie->fp, size - 4, SEEK_CUR);
if (GET_FCC(movie->fp) != FCC("idx1")) {
- DEBUG_PRINT("bad index informatio\n");
+ DEBUG_PRINT("bad index information\n");
return AVI_ERROR_FORMAT;
}
diff --git a/source/blender/io/collada/AnimationExporter.cpp b/source/blender/io/collada/AnimationExporter.cpp
index 9ba59c0414d..56274e7e6ca 100644
--- a/source/blender/io/collada/AnimationExporter.cpp
+++ b/source/blender/io/collada/AnimationExporter.cpp
@@ -549,7 +549,7 @@ void AnimationExporter::add_source_parameters(COLLADASW::SourceBase::ParameterNa
param.push_back("TRANSFORM");
}
else {
- /* assumes if axis isn't specified all axises are added */
+ /* assumes if axis isn't specified all axes are added */
param.push_back("X");
param.push_back("Y");
param.push_back("Z");
diff --git a/source/blender/io/collada/collada_utils.cpp b/source/blender/io/collada/collada_utils.cpp
index 60c4a9bad13..c1f25ea9a26 100644
--- a/source/blender/io/collada/collada_utils.cpp
+++ b/source/blender/io/collada/collada_utils.cpp
@@ -444,14 +444,14 @@ void bc_triangulate_mesh(Mesh *me)
/* XXX: The triangulation method selection could be offered in the UI. */
int quad_method = MOD_TRIANGULATE_QUAD_SHORTEDGE;
- const struct BMeshCreateParams bm_create_params = {0};
+ const BMeshCreateParams bm_create_params{};
BMesh *bm = BM_mesh_create(&bm_mesh_allocsize_default, &bm_create_params);
- BMeshFromMeshParams bm_from_me_params = {0};
+ BMeshFromMeshParams bm_from_me_params{};
bm_from_me_params.calc_face_normal = true;
BM_mesh_bm_from_me(bm, me, &bm_from_me_params);
BM_mesh_triangulate(bm, quad_method, use_beauty, 4, tag_only, nullptr, nullptr, nullptr);
- BMeshToMeshParams bm_to_me_params = {0};
+ BMeshToMeshParams bm_to_me_params{};
bm_to_me_params.calc_object_remap = false;
BM_mesh_bm_to_me(nullptr, bm, me, &bm_to_me_params);
BM_mesh_free(bm);
diff --git a/source/blender/io/gpencil/gpencil_io.h b/source/blender/io/gpencil/gpencil_io.h
index fab867b38b3..cb004910c1e 100644
--- a/source/blender/io/gpencil/gpencil_io.h
+++ b/source/blender/io/gpencil/gpencil_io.h
@@ -82,6 +82,7 @@ typedef enum eGpencilExportSelect {
typedef enum eGpencilExportFrame {
GP_EXPORT_FRAME_ACTIVE = 0,
GP_EXPORT_FRAME_SELECTED = 1,
+ GP_EXPORT_FRAME_SCENE = 2,
} eGpencilExportFrame;
bool gpencil_io_export(const char *filename, struct GpencilIOParams *iparams);
diff --git a/source/blender/io/gpencil/intern/gpencil_io_capi.cc b/source/blender/io/gpencil/intern/gpencil_io_capi.cc
index 544c51e0b4f..95f5839682f 100644
--- a/source/blender/io/gpencil/intern/gpencil_io_capi.cc
+++ b/source/blender/io/gpencil/intern/gpencil_io_capi.cc
@@ -112,32 +112,39 @@ static bool gpencil_io_export_pdf(Depsgraph *depsgraph,
exporter->frame_number_set(iparams->frame_cur);
result |= exporter->new_document();
- const bool use_frame_selected = (iparams->frame_mode == GP_EXPORT_FRAME_SELECTED);
- if (use_frame_selected) {
- for (int32_t i = iparams->frame_start; i < iparams->frame_end + 1; i++) {
- if (!is_keyframe_included(gpd_eval, i, use_frame_selected)) {
- continue;
- }
-
- CFRA = i;
- BKE_scene_graph_update_for_newframe(depsgraph);
+ switch (iparams->frame_mode) {
+ case GP_EXPORT_FRAME_ACTIVE: {
exporter->prepare_camera_params(scene, iparams);
- exporter->frame_number_set(i);
exporter->add_newpage();
exporter->add_body();
+ result = exporter->write();
+ break;
}
- result = exporter->write();
- /* Back to original frame. */
- exporter->frame_number_set(iparams->frame_cur);
- CFRA = iparams->frame_cur;
- BKE_scene_camera_switch_update(scene);
- BKE_scene_graph_update_for_newframe(depsgraph);
- }
- else {
- exporter->prepare_camera_params(scene, iparams);
- exporter->add_newpage();
- exporter->add_body();
- result = exporter->write();
+ case GP_EXPORT_FRAME_SELECTED:
+ case GP_EXPORT_FRAME_SCENE: {
+ for (int32_t i = iparams->frame_start; i < iparams->frame_end + 1; i++) {
+ if ((iparams->frame_mode == GP_EXPORT_FRAME_SELECTED) &&
+ (!is_keyframe_included(gpd_eval, i, true))) {
+ continue;
+ }
+
+ CFRA = i;
+ BKE_scene_graph_update_for_newframe(depsgraph);
+ exporter->prepare_camera_params(scene, iparams);
+ exporter->frame_number_set(i);
+ exporter->add_newpage();
+ exporter->add_body();
+ }
+ result = exporter->write();
+ /* Back to original frame. */
+ exporter->frame_number_set(iparams->frame_cur);
+ CFRA = iparams->frame_cur;
+ BKE_scene_camera_switch_update(scene);
+ BKE_scene_graph_update_for_newframe(depsgraph);
+ break;
+ }
+ default:
+ break;
}
return result;
diff --git a/source/blender/makesdna/DNA_constraint_types.h b/source/blender/makesdna/DNA_constraint_types.h
index 6dc2d00252f..d587bd8082b 100644
--- a/source/blender/makesdna/DNA_constraint_types.h
+++ b/source/blender/makesdna/DNA_constraint_types.h
@@ -728,7 +728,7 @@ typedef enum eBConstraint_Flags {
/* bConstraint->ownspace/tarspace */
typedef enum eBConstraint_SpaceTypes {
- /** Default for all - worldspace. */
+ /** Default for all - world-space. */
CONSTRAINT_SPACE_WORLD = 0,
/** For all - custom space. */
CONSTRAINT_SPACE_CUSTOM = 5,
diff --git a/source/blender/makesdna/DNA_fluid_types.h b/source/blender/makesdna/DNA_fluid_types.h
index 0cbef540306..d8065410f2b 100644
--- a/source/blender/makesdna/DNA_fluid_types.h
+++ b/source/blender/makesdna/DNA_fluid_types.h
@@ -513,7 +513,7 @@ typedef struct FluidDomainSettings {
float p1[3]; /* End point of BB in local space. */
float dp0[3]; /* Difference from object center to grid start point. */
float cell_size[3]; /* Size of simulation cell in local space. */
- float global_size[3]; /* Global size of domain axises. */
+ float global_size[3]; /* Global size of domain axes. */
float prev_loc[3];
int shift[3]; /* Current domain shift in simulation cells. */
float shift_f[3]; /* Exact domain shift. */
@@ -694,7 +694,7 @@ typedef struct FluidDomainSettings {
char openvdb_data_depth;
char _pad11[7]; /* Unused. */
- /* -- Deprecated / unsed options (below). -- */
+ /* -- Deprecated / unused options (below). -- */
/* View options. */
int viewsettings;
diff --git a/source/blender/makesdna/DNA_image_types.h b/source/blender/makesdna/DNA_image_types.h
index 2464eb05a6d..64c8fd3e3a9 100644
--- a/source/blender/makesdna/DNA_image_types.h
+++ b/source/blender/makesdna/DNA_image_types.h
@@ -142,6 +142,12 @@ typedef enum eImageTextureResolution {
IMA_TEXTURE_RESOLUTION_LEN
} eImageTextureResolution;
+typedef struct Image_Runtime {
+ /* Mutex used to guarantee thread-safe access to the cached ImBuf of the corresponding image ID.
+ */
+ void *cache_mutex;
+} Image_Runtime;
+
typedef struct Image {
ID id;
@@ -208,6 +214,8 @@ typedef struct Image {
/** ImageView. */
ListBase views;
struct Stereo3dFormat *stereo3d_format;
+
+ Image_Runtime runtime;
} Image;
/* **************** IMAGE ********************* */
diff --git a/source/blender/makesdna/DNA_lightprobe_types.h b/source/blender/makesdna/DNA_lightprobe_types.h
index 038de8e49cc..1a3bda34a84 100644
--- a/source/blender/makesdna/DNA_lightprobe_types.h
+++ b/source/blender/makesdna/DNA_lightprobe_types.h
@@ -149,7 +149,7 @@ BLI_STATIC_ASSERT_ALIGN(LightGridCache, 16)
typedef struct LightCacheTexture {
struct GPUTexture *tex;
- /** Copy of GPU datas to create GPUTextures on file read. */
+ /** Copy of GPU data to create GPUTextures on file read. */
char *data;
int tex_size[3];
char data_type;
diff --git a/source/blender/makesdna/DNA_node_types.h b/source/blender/makesdna/DNA_node_types.h
index d5d2520ddf6..59cf4da26f6 100644
--- a/source/blender/makesdna/DNA_node_types.h
+++ b/source/blender/makesdna/DNA_node_types.h
@@ -46,6 +46,7 @@ struct bNodePreview;
struct bNodeTreeExec;
struct bNodeType;
struct uiBlock;
+struct PreviewImage;
#define NODE_MAXSTR 64
@@ -80,6 +81,19 @@ typedef struct bNodeStack {
#define NS_CR_FIT 4
#define NS_CR_STRETCH 5
+/** Workaround to forward-declare C++ type in C header. */
+#ifdef __cplusplus
+namespace blender::nodes {
+class NodeDeclaration;
+class SocketDeclaration;
+} // namespace blender::nodes
+using NodeDeclarationHandle = blender::nodes::NodeDeclaration;
+using SocketDeclarationHandle = blender::nodes::SocketDeclaration;
+#else
+typedef struct NodeDeclarationHandle NodeDeclarationHandle;
+typedef struct SocketDeclarationHandle SocketDeclarationHandle;
+#endif
+
typedef struct bNodeSocket {
struct bNodeSocket *next, *prev, *new_sock;
@@ -152,6 +166,12 @@ typedef struct bNodeSocket {
* kept for forward compatibility */
/** Custom data for inputs, only UI writes in this. */
bNodeStack ns DNA_DEPRECATED;
+
+ /**
+ * References a socket declaration that is owned by `node->declaration`. This is only runtime
+ * data. It has to be updated when the node declaration changes.
+ */
+ const SocketDeclarationHandle *declaration;
} bNodeSocket;
/* sock->type */
@@ -219,16 +239,6 @@ typedef enum eNodeSocketFlag {
SOCK_HIDE_LABEL = (1 << 12),
} eNodeSocketFlag;
-/** Workaround to forward-declare C++ type in C header. */
-#ifdef __cplusplus
-namespace blender::nodes {
-class NodeDeclaration;
-}
-using NodeDeclarationHandle = blender::nodes::NodeDeclaration;
-#else
-typedef struct NodeDeclarationHandle NodeDeclarationHandle;
-#endif
-
/* TODO: Limit data in bNode to what we want to see saved. */
typedef struct bNode {
struct bNode *next, *prev, *new_node;
@@ -292,7 +302,7 @@ typedef struct bNode {
char _pad1[4];
- /** Entire boundbox (worldspace). */
+ /** Entire boundbox (world-space). */
rctf totr;
/** Optional buttons area. */
rctf butr;
@@ -561,10 +571,15 @@ typedef struct bNodeTree {
int (*test_break)(void *);
void (*update_draw)(void *);
void *tbh, *prh, *sdh, *udh;
+
+ /** Image representing what the node group does. */
+ struct PreviewImage *preview;
} bNodeTree;
/* ntree->type, index */
-#define NTREE_CUSTOM -1 /* for dynamically registered custom types */
+
+#define NTREE_UNDEFINED -2 /* Represents #NodeTreeTypeUndefined type. */
+#define NTREE_CUSTOM -1 /* for dynamically registered custom types */
#define NTREE_SHADER 0
#define NTREE_COMPOSIT 1
#define NTREE_TEXTURE 2
diff --git a/source/blender/makesdna/DNA_object_types.h b/source/blender/makesdna/DNA_object_types.h
index e94541fdc7f..57c8ef200ae 100644
--- a/source/blender/makesdna/DNA_object_types.h
+++ b/source/blender/makesdna/DNA_object_types.h
@@ -311,7 +311,7 @@ typedef struct Object {
float rotAxis[3], drotAxis[3];
/** Axis angle rotation - angle part. */
float rotAngle, drotAngle;
- /** Final worldspace matrix with constraints & animsys applied. */
+ /** Final world-space matrix with constraints & animsys applied. */
float obmat[4][4];
/** Inverse result of parent, so that object doesn't 'stick' to parent. */
float parentinv[4][4];
diff --git a/source/blender/makesdna/DNA_scene_types.h b/source/blender/makesdna/DNA_scene_types.h
index eeff5473d16..634e97f782f 100644
--- a/source/blender/makesdna/DNA_scene_types.h
+++ b/source/blender/makesdna/DNA_scene_types.h
@@ -2066,6 +2066,9 @@ enum {
#define SCE_SNAP_MODE_VOLUME (1 << 3)
#define SCE_SNAP_MODE_EDGE_MIDPOINT (1 << 4)
#define SCE_SNAP_MODE_EDGE_PERPENDICULAR (1 << 5)
+#define SCE_SNAP_MODE_GEOM \
+ (SCE_SNAP_MODE_VERTEX | SCE_SNAP_MODE_EDGE | SCE_SNAP_MODE_FACE | \
+ SCE_SNAP_MODE_EDGE_PERPENDICULAR | SCE_SNAP_MODE_EDGE_MIDPOINT)
/** #SequencerToolSettings.snap_mode */
#define SEQ_SNAP_TO_STRIPS (1 << 0)
diff --git a/source/blender/makesdna/DNA_screen_types.h b/source/blender/makesdna/DNA_screen_types.h
index 607b00a833f..a4c254d6e5a 100644
--- a/source/blender/makesdna/DNA_screen_types.h
+++ b/source/blender/makesdna/DNA_screen_types.h
@@ -461,6 +461,9 @@ typedef struct ARegion_Runtime {
/* The offset needed to not overlap with window scrollbars. Only used by HUD regions for now. */
int offset_x, offset_y;
+
+ /* Maps uiBlock->name to uiBlock for faster lookups. */
+ struct GHash *block_name_map;
} ARegion_Runtime;
typedef struct ARegion {
@@ -670,7 +673,7 @@ typedef enum eRegion_Type {
RGN_TYPE_FOOTER = 11,
RGN_TYPE_TOOL_HEADER = 12,
/* Region type used exclusively by internal code and add-ons to register draw callbacks to the XR
- context (surface, mirror view). Does not represent any real region. */
+ * context (surface, mirror view). Does not represent any real region. */
RGN_TYPE_XR = 13,
#define RGN_TYPE_LEN (RGN_TYPE_XR + 1)
diff --git a/source/blender/makesdna/DNA_sequence_types.h b/source/blender/makesdna/DNA_sequence_types.h
index fc23d3c69a3..9e6cf907444 100644
--- a/source/blender/makesdna/DNA_sequence_types.h
+++ b/source/blender/makesdna/DNA_sequence_types.h
@@ -378,7 +378,7 @@ typedef struct TextVars {
char text[512];
struct VFont *text_font;
int text_blf_id;
- int text_size;
+ float text_size;
float color[4], shadow_color[4], box_color[4];
float loc[2];
float wrap_width;
diff --git a/source/blender/makesdna/DNA_space_types.h b/source/blender/makesdna/DNA_space_types.h
index 5ebc81fff4f..88c5ace9cb3 100644
--- a/source/blender/makesdna/DNA_space_types.h
+++ b/source/blender/makesdna/DNA_space_types.h
@@ -64,7 +64,7 @@ struct wmTimer;
/* Defined in `buttons_intern.h`. */
typedef struct SpaceProperties_Runtime SpaceProperties_Runtime;
-/* Defined in `node_intern.h`. */
+/* Defined in `node_intern.hh`. */
typedef struct SpaceNode_Runtime SpaceNode_Runtime;
/* Defined in `file_intern.h`. */
@@ -1158,8 +1158,12 @@ typedef struct FileDirEntryArr {
/* FileDirEntry.flags */
enum {
- FILE_ENTRY_INVALID_PREVIEW = 1 << 0, /* The preview for this entry could not be generated. */
+ /* The preview for this entry could not be generated. */
+ FILE_ENTRY_INVALID_PREVIEW = 1 << 0,
+ /* The entry name needs to be freed when clearing file list. */
FILE_ENTRY_NAME_FREE = 1 << 1,
+ /* The preview for this entry is being loaded on another thread. */
+ FILE_ENTRY_PREVIEW_LOADING = 1 << 2,
};
/** \} */
@@ -1516,6 +1520,7 @@ typedef struct SpaceNodeOverlay {
typedef enum eSpaceNodeOverlay_Flag {
SN_OVERLAY_SHOW_OVERLAYS = (1 << 1),
SN_OVERLAY_SHOW_WIRE_COLORS = (1 << 2),
+ SN_OVERLAY_SHOW_TIMINGS = (1 << 3),
} eSpaceNodeOverlay_Flag;
typedef struct SpaceNode {
@@ -2006,6 +2011,7 @@ typedef enum eSpreadsheetColumnValueType {
SPREADSHEET_VALUE_TYPE_FLOAT3 = 4,
SPREADSHEET_VALUE_TYPE_COLOR = 5,
SPREADSHEET_VALUE_TYPE_INSTANCES = 6,
+ SPREADSHEET_VALUE_TYPE_STRING = 7,
} eSpreadsheetColumnValueType;
/**
diff --git a/source/blender/makesdna/DNA_texture_types.h b/source/blender/makesdna/DNA_texture_types.h
index ee33e8666ec..2c3cd8eab77 100644
--- a/source/blender/makesdna/DNA_texture_types.h
+++ b/source/blender/makesdna/DNA_texture_types.h
@@ -128,9 +128,9 @@ typedef struct PointDensity {
struct Object *object;
/** `index + 1` in ob.particlesystem, non-ID pointer not allowed */
int psys;
- /** cache points in worldspace, object space, ... ? */
+ /** cache points in world-space, object space, ... ? */
short psys_cache_space;
- /** cache points in worldspace, object space, ... ? */
+ /** cache points in world-space, object space, ... ? */
short ob_cache_space;
/** vertex attribute layer for color source, MAX_CUSTOMDATA_LAYER_NAME */
char vertex_attribute_name[64];
diff --git a/source/blender/makesdna/DNA_userdef_types.h b/source/blender/makesdna/DNA_userdef_types.h
index 104f335cd16..c8fdac19b61 100644
--- a/source/blender/makesdna/DNA_userdef_types.h
+++ b/source/blender/makesdna/DNA_userdef_types.h
@@ -69,8 +69,9 @@ typedef struct uiFont {
typedef struct uiFontStyle {
/** Saved in file, 0 is default. */
short uifont_id;
+ char _pad1[2];
/** Actual size depends on 'global' dpi. */
- short points;
+ float points;
/** Style hint. */
short italic, bold;
/** Value is amount of pixels blur. */
@@ -82,6 +83,7 @@ typedef struct uiFontStyle {
float shadowalpha;
/** 1 value, typically white or black anyway. */
float shadowcolor;
+ char _pad2[4];
} uiFontStyle;
/* this is fed to the layout engine and widget code */
@@ -557,7 +559,7 @@ typedef struct bUserMenuItem_Op {
bUserMenuItem item;
char op_idname[64];
struct IDProperty *prop;
- char opcontext;
+ char opcontext; /* #wmOperatorCallContext */
char _pad0[7];
} bUserMenuItem_Op;
@@ -939,7 +941,8 @@ typedef struct UserDef {
short sequencer_proxy_setup; /* eUserpref_SeqProxySetup */
float collection_instance_empty_size;
- char _pad10[2];
+ char text_flag;
+ char _pad10[1];
char file_preview_type; /* eUserpref_File_Preview_Type */
char statusbar_flag; /* eUserpref_StatusBar_Flag */
@@ -1264,6 +1267,14 @@ typedef enum eDupli_ID_Flags {
} eDupli_ID_Flags;
/**
+ * Text Editor options
+ * #UserDef.text_flag
+ */
+typedef enum eTextEdit_Flags {
+ USER_TEXT_EDIT_AUTO_CLOSE = (1 << 0),
+} eTextEdit_Flags;
+
+/**
* Text draw options
* #UserDef.text_render
*/
diff --git a/source/blender/makesdna/DNA_view3d_types.h b/source/blender/makesdna/DNA_view3d_types.h
index 9b5ed133feb..3fd2f1208dd 100644
--- a/source/blender/makesdna/DNA_view3d_types.h
+++ b/source/blender/makesdna/DNA_view3d_types.h
@@ -64,8 +64,10 @@ typedef struct RegionView3D {
/** User defined clipping planes. */
float clip[6][4];
- /** Clip in object space,
- * means we can test for clipping in editmode without first going into worldspace. */
+ /**
+ * Clip in object space,
+ * means we can test for clipping in edit-mode without first going into world-space.
+ */
float clip_local[6][4];
struct BoundBox *clipbb;
@@ -94,8 +96,8 @@ typedef struct RegionView3D {
/** Runtime only. */
float pixsize;
/**
- * View center & orbit pivot, negative of worldspace location,
- * also matches -viewinv[3][0:3] in ortho mode.
+ * View center & orbit pivot, negative of world-space location,
+ * also matches `-viewinv[3][0:3]` in orthographic mode.
*/
float ofs[3];
/** Viewport zoom on the camera frame, see BKE_screen_view3d_zoom_to_fac. */
diff --git a/source/blender/makesrna/RNA_enum_items.h b/source/blender/makesrna/RNA_enum_items.h
index f3e15d08fa3..fb18802483d 100644
--- a/source/blender/makesrna/RNA_enum_items.h
+++ b/source/blender/makesrna/RNA_enum_items.h
@@ -211,6 +211,8 @@ DEF_ENUM(rna_enum_attribute_domain_items)
DEF_ENUM(rna_enum_attribute_domain_without_corner_items)
DEF_ENUM(rna_enum_attribute_domain_with_auto_items)
+DEF_ENUM(rna_enum_volume_grid_data_type_items)
+
DEF_ENUM(rna_enum_collection_color_items)
DEF_ENUM(rna_enum_strip_color_items)
diff --git a/source/blender/makesrna/intern/makesrna.c b/source/blender/makesrna/intern/makesrna.c
index f2e87b29c1f..a6732ca1760 100644
--- a/source/blender/makesrna/intern/makesrna.c
+++ b/source/blender/makesrna/intern/makesrna.c
@@ -4698,6 +4698,19 @@ static const char *cpp_classes =
" inline static int sname##_##identifier##_length_wrap(PointerRNA *ptr) \\\n"
" { return sname##_##identifier##_length(ptr); } \n"
"\n"
+ "#define COLLECTION_PROPERTY_EMPTY_false(sname, identifier) \\\n"
+ " inline static bool sname##_##identifier##_empty_wrap(PointerRNA *ptr) \\\n"
+ " { \\\n"
+ " CollectionPropertyIterator iter; \\\n"
+ " sname##_##identifier##_begin(&iter, ptr); \\\n"
+ " bool empty = !iter.valid; \\\n"
+ " sname##_##identifier##_end(&iter); \\\n"
+ " return empty; \\\n"
+ " } \n"
+ "#define COLLECTION_PROPERTY_EMPTY_true(sname, identifier) \\\n"
+ " inline static bool sname##_##identifier##_empty_wrap(PointerRNA *ptr) \\\n"
+ " { return sname##_##identifier##_length(ptr) == 0; } \n"
+ "\n"
"#define COLLECTION_PROPERTY_LOOKUP_INT_false(sname, identifier) \\\n"
" inline static int sname##_##identifier##_lookup_int_wrap(PointerRNA *ptr, int key, "
"PointerRNA *r_ptr) \\\n"
@@ -4774,11 +4787,13 @@ static const char *cpp_classes =
" typedef CollectionIterator<type, sname##_##identifier##_begin, \\\n"
" sname##_##identifier##_next, sname##_##identifier##_end> identifier##_iterator; \\\n"
" COLLECTION_PROPERTY_LENGTH_##has_length(sname, identifier) \\\n"
+ " COLLECTION_PROPERTY_EMPTY_##has_length(sname, identifier) \\\n"
" COLLECTION_PROPERTY_LOOKUP_INT_##has_lookup_int(sname, identifier) \\\n"
" COLLECTION_PROPERTY_LOOKUP_STRING_##has_lookup_string(sname, identifier) \\\n"
" CollectionRef<sname, type, sname##_##identifier##_begin, \\\n"
" sname##_##identifier##_next, sname##_##identifier##_end, \\\n"
" sname##_##identifier##_length_wrap, \\\n"
+ " sname##_##identifier##_empty_wrap, \\\n"
" sname##_##identifier##_lookup_int_wrap, sname##_##identifier##_lookup_string_wrap, "
"collection_funcs> identifier;\n"
"\n"
@@ -4844,6 +4859,7 @@ static const char *cpp_classes =
"typedef void (*TNextFunc)(CollectionPropertyIterator *iter);\n"
"typedef void (*TEndFunc)(CollectionPropertyIterator *iter);\n"
"typedef int (*TLengthFunc)(PointerRNA *ptr);\n"
+ "typedef bool (*TEmptyFunc)(PointerRNA *ptr);\n"
"typedef int (*TLookupIntFunc)(PointerRNA *ptr, int key, PointerRNA *r_ptr);\n"
"typedef int (*TLookupStringFunc)(PointerRNA *ptr, const char *key, PointerRNA *r_ptr);\n"
"\n"
@@ -4882,8 +4898,8 @@ static const char *cpp_classes =
"};\n"
"\n"
"template<typename Tp, typename T, TBeginFunc Tbegin, TNextFunc Tnext, TEndFunc Tend,\n"
- " TLengthFunc Tlength, TLookupIntFunc Tlookup_int, TLookupStringFunc Tlookup_string,\n"
- " typename Tcollection_funcs>\n"
+ " TLengthFunc Tlength, TEmptyFunc Tempty, TLookupIntFunc Tlookup_int,\n"
+ " TLookupStringFunc Tlookup_string, typename Tcollection_funcs>\n"
"class CollectionRef : public Tcollection_funcs {\n"
"public:\n"
" CollectionRef(const PointerRNA &p) : Tcollection_funcs(p), ptr(p) {}\n"
@@ -4897,6 +4913,8 @@ static const char *cpp_classes =
""
" int length()\n"
" { return Tlength(&ptr); }\n"
+ " bool empty()\n"
+ " { return Tempty(&ptr); }\n"
" T operator[](int key)\n"
" { PointerRNA r_ptr; Tlookup_int(&ptr, key, &r_ptr); return T(r_ptr); }\n"
" T operator[](const std::string &key)\n"
diff --git a/source/blender/makesrna/intern/rna_animviz.c b/source/blender/makesrna/intern/rna_animviz.c
index b205b3d7139..1511921cef0 100644
--- a/source/blender/makesrna/intern/rna_animviz.c
+++ b/source/blender/makesrna/intern/rna_animviz.c
@@ -117,7 +117,7 @@ static void rna_def_animviz_motion_path(BlenderRNA *brna)
srna = RNA_def_struct(brna, "MotionPath", NULL);
RNA_def_struct_sdna(srna, "bMotionPath");
RNA_def_struct_ui_text(
- srna, "Motion Path", "Cache of the worldspace positions of an element over a frame range");
+ srna, "Motion Path", "Cache of the world-space positions of an element over a frame range");
/* Collections */
prop = RNA_def_property(srna, "points", PROP_COLLECTION, PROP_NONE);
diff --git a/source/blender/makesrna/intern/rna_attribute.c b/source/blender/makesrna/intern/rna_attribute.c
index dbf20896463..78c15444308 100644
--- a/source/blender/makesrna/intern/rna_attribute.c
+++ b/source/blender/makesrna/intern/rna_attribute.c
@@ -72,6 +72,7 @@ const EnumPropertyItem rna_enum_attribute_domain_items[] = {
/* Not implement yet */
// {ATTR_DOMAIN_GRIDS, "GRIDS", 0, "Grids", "Attribute on mesh multires grids"},
{ATTR_DOMAIN_CURVE, "CURVE", 0, "Spline", "Attribute on spline"},
+ {ATTR_DOMAIN_INSTANCE, "INSTANCE", 0, "Instance", "Attribute on instance"},
{0, NULL, 0, NULL, NULL},
};
@@ -80,6 +81,7 @@ const EnumPropertyItem rna_enum_attribute_domain_without_corner_items[] = {
{ATTR_DOMAIN_EDGE, "EDGE", 0, "Edge", "Attribute on mesh edge"},
{ATTR_DOMAIN_FACE, "FACE", 0, "Face", "Attribute on mesh faces"},
{ATTR_DOMAIN_CURVE, "CURVE", 0, "Spline", "Attribute on spline"},
+ {ATTR_DOMAIN_INSTANCE, "INSTANCE", 0, "Instance", "Attribute on instance"},
{0, NULL, 0, NULL, NULL},
};
@@ -90,6 +92,7 @@ const EnumPropertyItem rna_enum_attribute_domain_with_auto_items[] = {
{ATTR_DOMAIN_FACE, "FACE", 0, "Face", "Attribute on mesh faces"},
{ATTR_DOMAIN_CORNER, "CORNER", 0, "Face Corner", "Attribute on mesh face corner"},
{ATTR_DOMAIN_CURVE, "CURVE", 0, "Spline", "Attribute on spline"},
+ {ATTR_DOMAIN_INSTANCE, "INSTANCE", 0, "Instance", "Attribute on instance"},
{0, NULL, 0, NULL, NULL},
};
diff --git a/source/blender/makesrna/intern/rna_brush.c b/source/blender/makesrna/intern/rna_brush.c
index 1d3b8cd9f9c..b4cf15ebfc6 100644
--- a/source/blender/makesrna/intern/rna_brush.c
+++ b/source/blender/makesrna/intern/rna_brush.c
@@ -1283,7 +1283,7 @@ static void rna_def_gpencil_options(BlenderRNA *brna)
static EnumPropertyItem gppaint_mode_types_items[] = {
{GPPAINT_MODE_STROKE, "STROKE", 0, "Stroke", "Vertex Color affects to Stroke only"},
{GPPAINT_MODE_FILL, "FILL", 0, "Fill", "Vertex Color affects to Fill only"},
- {GPPAINT_MODE_BOTH, "BOTH", 0, "Stroke and Fill", "Vertex Color affects to Stroke and Fill"},
+ {GPPAINT_MODE_BOTH, "BOTH", 0, "Stroke & Fill", "Vertex Color affects to Stroke and Fill"},
{0, NULL, 0, NULL, NULL},
};
diff --git a/source/blender/makesrna/intern/rna_gpencil_modifier.c b/source/blender/makesrna/intern/rna_gpencil_modifier.c
index 7fe51d45eb2..82f3279146a 100644
--- a/source/blender/makesrna/intern/rna_gpencil_modifier.c
+++ b/source/blender/makesrna/intern/rna_gpencil_modifier.c
@@ -167,14 +167,14 @@ const EnumPropertyItem rna_enum_object_greasepencil_modifier_type_items[] = {
#ifndef RNA_RUNTIME
static const EnumPropertyItem modifier_modify_color_items[] = {
- {GP_MODIFY_COLOR_BOTH, "BOTH", 0, "Stroke and Fill", "Modify fill and stroke colors"},
+ {GP_MODIFY_COLOR_BOTH, "BOTH", 0, "Stroke & Fill", "Modify fill and stroke colors"},
{GP_MODIFY_COLOR_STROKE, "STROKE", 0, "Stroke", "Modify stroke color only"},
{GP_MODIFY_COLOR_FILL, "FILL", 0, "Fill", "Modify fill color only"},
{0, NULL, 0, NULL, NULL},
};
static const EnumPropertyItem modifier_modify_opacity_items[] = {
- {GP_MODIFY_COLOR_BOTH, "BOTH", 0, "Stroke and Fill", "Modify fill and stroke colors"},
+ {GP_MODIFY_COLOR_BOTH, "BOTH", 0, "Stroke & Fill", "Modify fill and stroke colors"},
{GP_MODIFY_COLOR_STROKE, "STROKE", 0, "Stroke", "Modify stroke color only"},
{GP_MODIFY_COLOR_FILL, "FILL", 0, "Fill", "Modify fill color only"},
{GP_MODIFY_COLOR_HARDNESS, "HARDNESS", 0, "Hardness", "Modify stroke hardness"},
@@ -1450,7 +1450,7 @@ static void rna_def_modifier_gpenciltint(BlenderRNA *brna)
static EnumPropertyItem tint_mode_types_items[] = {
{GPPAINT_MODE_STROKE, "STROKE", 0, "Stroke", "Vertex Color affects to Stroke only"},
{GPPAINT_MODE_FILL, "FILL", 0, "Fill", "Vertex Color affects to Fill only"},
- {GPPAINT_MODE_BOTH, "BOTH", 0, "Stroke and Fill", "Vertex Color affects to Stroke and Fill"},
+ {GPPAINT_MODE_BOTH, "BOTH", 0, "Stroke & Fill", "Vertex Color affects to Stroke and Fill"},
{0, NULL, 0, NULL, NULL},
};
@@ -2677,7 +2677,7 @@ static void rna_def_modifier_gpenciltexture(BlenderRNA *brna)
{STROKE_AND_FILL,
"STROKE_AND_FILL",
0,
- "Stroke and Fill",
+ "Stroke & Fill",
"Manipulate both stroke and fill texture coordinates"},
{0, NULL, 0, NULL, NULL},
};
diff --git a/source/blender/makesrna/intern/rna_nodetree.c b/source/blender/makesrna/intern/rna_nodetree.c
index e6b732aabd4..aef3823338b 100644
--- a/source/blender/makesrna/intern/rna_nodetree.c
+++ b/source/blender/makesrna/intern/rna_nodetree.c
@@ -12754,6 +12754,11 @@ static void rna_def_nodetree(BlenderRNA *brna)
PropertyRNA *parm;
static const EnumPropertyItem static_type_items[] = {
+ {NTREE_UNDEFINED,
+ "UNDEFINED",
+ ICON_QUESTION,
+ "Undefined",
+ "Undefined type of nodes (can happen e.g. when a linked node tree goes missing)"},
{NTREE_SHADER, "SHADER", ICON_MATERIAL, "Shader", "Shader nodes"},
{NTREE_TEXTURE, "TEXTURE", ICON_TEXTURE, "Texture", "Texture nodes"},
{NTREE_COMPOSIT, "COMPOSITING", ICON_RENDERLAYERS, "Compositing", "Compositing nodes"},
diff --git a/source/blender/makesrna/intern/rna_object_api.c b/source/blender/makesrna/intern/rna_object_api.c
index 10094ade711..63c4774d0e5 100644
--- a/source/blender/makesrna/intern/rna_object_api.c
+++ b/source/blender/makesrna/intern/rna_object_api.c
@@ -530,7 +530,7 @@ static int mesh_looptri_to_poly_index(Mesh *me_eval, const MLoopTri *lt)
return index_mp_to_orig ? index_mp_to_orig[lt->poly] : lt->poly;
}
-/* TOOD(sergey): Make the Python API more clear that evaluation might happen, or requite
+/* TODO(sergey): Make the Python API more clear that evaluation might happen, or require
* passing fully evaluated depsgraph. */
static Object *eval_object_ensure(Object *ob,
bContext *C,
diff --git a/source/blender/makesrna/intern/rna_object_force.c b/source/blender/makesrna/intern/rna_object_force.c
index 186222d2ca0..2fca9f0af7a 100644
--- a/source/blender/makesrna/intern/rna_object_force.c
+++ b/source/blender/makesrna/intern/rna_object_force.c
@@ -1006,8 +1006,7 @@ static void rna_def_pointcache_common(StructRNA *srna)
prop = RNA_def_property(srna, "is_frame_skip", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", PTCACHE_FRAMES_SKIPPED);
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
- RNA_def_property_ui_text(
- prop, "", "Some frames were skipped while baking/saving that cache");
+ RNA_def_property_ui_text(prop, "", "Some frames were skipped while baking/saving that cache");
prop = RNA_def_property(srna, "name", PROP_STRING, PROP_NONE);
RNA_def_property_string_sdna(prop, NULL, "name");
diff --git a/source/blender/makesrna/intern/rna_sequencer.c b/source/blender/makesrna/intern/rna_sequencer.c
index 9f92f1c6e5f..f92043995dd 100644
--- a/source/blender/makesrna/intern/rna_sequencer.c
+++ b/source/blender/makesrna/intern/rna_sequencer.c
@@ -1366,6 +1366,28 @@ static float rna_Sequence_fps_get(PointerRNA *ptr)
return SEQ_time_sequence_get_fps(scene, seq);
}
+static void rna_Sequence_separate(ID *id, Sequence *seqm, Main *bmain)
+{
+ Scene *scene = (Scene *)id;
+
+ /* Find the appropriate seqbase */
+ Editing *ed = SEQ_editing_get(scene);
+ ListBase *seqbase = SEQ_get_seqbase_by_seq(&ed->seqbase, seqm);
+
+ LISTBASE_FOREACH_MUTABLE (Sequence *, seq, &seqm->seqbase) {
+ SEQ_edit_move_strip_to_seqbase(scene, &seqm->seqbase, seq, seqbase);
+ }
+
+ SEQ_edit_flag_for_removal(scene, seqbase, seqm);
+ SEQ_edit_remove_flagged_sequences(scene, seqbase);
+
+ /* Update depsgraph. */
+ DEG_relations_tag_update(bmain);
+ DEG_id_tag_update(&scene->id, ID_RECALC_SEQUENCER_STRIPS);
+
+ WM_main_add_notifier(NC_SCENE | ND_SEQUENCER, scene);
+}
+
#else
static void rna_def_strip_element(BlenderRNA *brna)
@@ -2439,6 +2461,7 @@ static void rna_def_image(BlenderRNA *brna)
static void rna_def_meta(BlenderRNA *brna)
{
StructRNA *srna;
+ FunctionRNA *func;
PropertyRNA *prop;
srna = RNA_def_struct(brna, "MetaSequence", "Sequence");
@@ -2452,6 +2475,10 @@ static void rna_def_meta(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Sequences", "Sequences nested in meta strip");
RNA_api_sequences(brna, prop, true);
+ func = RNA_def_function(srna, "separate", "rna_Sequence_separate");
+ RNA_def_function_flag(func, FUNC_USE_SELF_ID | FUNC_USE_MAIN);
+ RNA_def_function_ui_description(func, "Separate meta");
+
rna_def_filter_video(srna);
rna_def_proxy(srna);
rna_def_input(srna);
@@ -2980,11 +3007,11 @@ static void rna_def_text(StructRNA *srna)
RNA_def_property_pointer_funcs(prop, NULL, "rna_Sequence_text_font_set", NULL, NULL);
RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_invalidate_raw_update");
- prop = RNA_def_property(srna, "font_size", PROP_INT, PROP_UNSIGNED);
- RNA_def_property_int_sdna(prop, NULL, "text_size");
+ prop = RNA_def_property(srna, "font_size", PROP_FLOAT, PROP_UNSIGNED);
+ RNA_def_property_float_sdna(prop, NULL, "text_size");
RNA_def_property_ui_text(prop, "Size", "Size of the text");
RNA_def_property_range(prop, 0.0, 2000);
- RNA_def_property_ui_range(prop, 0.0f, 2000, 1, -1);
+ RNA_def_property_ui_range(prop, 0.0f, 2000, 10.f, 1);
RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_invalidate_raw_update");
prop = RNA_def_property(srna, "color", PROP_FLOAT, PROP_COLOR_GAMMA);
diff --git a/source/blender/makesrna/intern/rna_space.c b/source/blender/makesrna/intern/rna_space.c
index 03976967e9f..8f04524c5c1 100644
--- a/source/blender/makesrna/intern/rna_space.c
+++ b/source/blender/makesrna/intern/rna_space.c
@@ -3090,7 +3090,7 @@ static void rna_SpaceSpreadsheet_geometry_component_type_update(Main *UNUSED(bma
break;
}
case GEO_COMPONENT_TYPE_INSTANCES: {
- sspreadsheet->attribute_domain = ATTR_DOMAIN_POINT;
+ sspreadsheet->attribute_domain = ATTR_DOMAIN_INSTANCE;
break;
}
case GEO_COMPONENT_TYPE_VOLUME: {
@@ -7110,6 +7110,12 @@ static void rna_def_space_node_overlay(BlenderRNA *brna)
RNA_def_property_ui_text(
prop, "Show Wire Colors", "Color node links based on their connected sockets");
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_NODE, NULL);
+
+ prop = RNA_def_property(srna, "show_timing", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "overlay.flag", SN_OVERLAY_SHOW_TIMINGS);
+ RNA_def_property_boolean_default(prop, false);
+ RNA_def_property_ui_text(prop, "Show Timing", "Display each node's last execution time");
+ RNA_def_property_update(prop, NC_SPACE | ND_SPACE_NODE, NULL);
}
static void rna_def_space_node(BlenderRNA *brna)
diff --git a/source/blender/makesrna/intern/rna_ui.c b/source/blender/makesrna/intern/rna_ui.c
index c73599c19ac..05ed5e096d8 100644
--- a/source/blender/makesrna/intern/rna_ui.c
+++ b/source/blender/makesrna/intern/rna_ui.c
@@ -1471,15 +1471,12 @@ static void rna_def_panel(BlenderRNA *brna)
RNA_def_property_string_sdna(prop, NULL, "type->category");
RNA_def_property_flag(prop, PROP_REGISTER_OPTIONAL);
RNA_def_property_ui_text(
- prop,
- "",
- "The category (tab) in which the panel will be displayed, when applicable");
+ prop, "", "The category (tab) in which the panel will be displayed, when applicable");
prop = RNA_def_property(srna, "bl_owner_id", PROP_STRING, PROP_NONE);
RNA_def_property_string_sdna(prop, NULL, "type->owner_id");
RNA_def_property_flag(prop, PROP_REGISTER_OPTIONAL);
- RNA_def_property_ui_text(
- prop, "", "The ID owning the data displayed in the panel, if any");
+ RNA_def_property_ui_text(prop, "", "The ID owning the data displayed in the panel, if any");
prop = RNA_def_property(srna, "bl_space_type", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_sdna(prop, NULL, "type->space_type");
diff --git a/source/blender/makesrna/intern/rna_userdef.c b/source/blender/makesrna/intern/rna_userdef.c
index 4542f8fa1d7..dd1252ffebf 100644
--- a/source/blender/makesrna/intern/rna_userdef.c
+++ b/source/blender/makesrna/intern/rna_userdef.c
@@ -265,6 +265,14 @@ static void rna_userdef_theme_update(Main *bmain, Scene *scene, PointerRNA *ptr)
rna_userdef_update(bmain, scene, ptr);
}
+static void rna_userdef_theme_text_style_update(Main *bmain, Scene *scene, PointerRNA *ptr)
+{
+ const uiStyle *style = UI_style_get();
+ BLF_default_size(style->widgetlabel.points);
+
+ rna_userdef_update(bmain, scene, ptr);
+}
+
static void rna_userdef_gizmo_update(Main *bmain, Scene *scene, PointerRNA *ptr)
{
WM_reinit_gizmomap_all(bmain);
@@ -1134,39 +1142,40 @@ static void rna_def_userdef_theme_ui_font_style(BlenderRNA *brna)
RNA_def_struct_clear_flag(srna, STRUCT_UNDO);
RNA_def_struct_ui_text(srna, "Font Style", "Theme settings for Font");
- prop = RNA_def_property(srna, "points", PROP_INT, PROP_NONE);
- RNA_def_property_range(prop, 6, 24);
+ prop = RNA_def_property(srna, "points", PROP_FLOAT, PROP_UNSIGNED);
+ RNA_def_property_range(prop, 6.0f, 32.0f);
+ RNA_def_property_ui_range(prop, 8.0f, 20.0f, 10.0f, 1);
RNA_def_property_ui_text(prop, "Points", "Font size in points");
- RNA_def_property_update(prop, 0, "rna_userdef_theme_update");
+ RNA_def_property_update(prop, 0, "rna_userdef_dpi_update");
prop = RNA_def_property(srna, "shadow", PROP_INT, PROP_PIXEL);
RNA_def_property_range(prop, 0, 5);
RNA_def_property_ui_text(prop, "Shadow Size", "Shadow size (0, 3 and 5 supported)");
- RNA_def_property_update(prop, 0, "rna_userdef_theme_update");
+ RNA_def_property_update(prop, 0, "rna_userdef_theme_text_style_update");
prop = RNA_def_property(srna, "shadow_offset_x", PROP_INT, PROP_PIXEL);
RNA_def_property_int_sdna(prop, NULL, "shadx");
RNA_def_property_range(prop, -10, 10);
RNA_def_property_ui_text(prop, "Shadow X Offset", "Shadow offset in pixels");
- RNA_def_property_update(prop, 0, "rna_userdef_theme_update");
+ RNA_def_property_update(prop, 0, "rna_userdef_theme_text_style_update");
prop = RNA_def_property(srna, "shadow_offset_y", PROP_INT, PROP_PIXEL);
RNA_def_property_int_sdna(prop, NULL, "shady");
RNA_def_property_range(prop, -10, 10);
RNA_def_property_ui_text(prop, "Shadow Y Offset", "Shadow offset in pixels");
- RNA_def_property_update(prop, 0, "rna_userdef_theme_update");
+ RNA_def_property_update(prop, 0, "rna_userdef_theme_text_style_update");
prop = RNA_def_property(srna, "shadow_alpha", PROP_FLOAT, PROP_FACTOR);
RNA_def_property_float_sdna(prop, NULL, "shadowalpha");
RNA_def_property_range(prop, 0.0f, 1.0f);
RNA_def_property_ui_text(prop, "Shadow Alpha", "");
- RNA_def_property_update(prop, 0, "rna_userdef_theme_update");
+ RNA_def_property_update(prop, 0, "rna_userdef_theme_text_style_update");
prop = RNA_def_property(srna, "shadow_value", PROP_FLOAT, PROP_FACTOR);
RNA_def_property_float_sdna(prop, NULL, "shadowcolor");
RNA_def_property_range(prop, 0.0f, 1.0f);
RNA_def_property_ui_text(prop, "Shadow Brightness", "Shadow color in gray value");
- RNA_def_property_update(prop, 0, "rna_userdef_theme_update");
+ RNA_def_property_update(prop, 0, "rna_userdef_theme_text_style_update");
}
static void rna_def_userdef_theme_ui_style(BlenderRNA *brna)
@@ -5022,6 +5031,14 @@ static void rna_def_userdef_edit(BlenderRNA *brna)
"Collection Instance Empty Size",
"Display size of the empty when new collection instances are created");
+ /* Text Editor */
+
+ prop = RNA_def_property(srna, "use_text_edit_auto_close", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "text_flag", USER_TEXT_EDIT_AUTO_CLOSE);
+ RNA_def_property_ui_text(
+ prop, "Auto Close", "Auto close relevant characters inside the text editor");
+ RNA_def_property_update(prop, NC_SPACE | ND_SPACE_TEXT, NULL);
+
/* Undo */
prop = RNA_def_property(srna, "undo_steps", PROP_INT, PROP_NONE);
diff --git a/source/blender/makesrna/intern/rna_volume.c b/source/blender/makesrna/intern/rna_volume.c
index f6b8b55688c..3100c1195f4 100644
--- a/source/blender/makesrna/intern/rna_volume.c
+++ b/source/blender/makesrna/intern/rna_volume.c
@@ -33,6 +33,26 @@
#include "BLI_math_base.h"
+const EnumPropertyItem rna_enum_volume_grid_data_type_items[] = {
+ {VOLUME_GRID_BOOLEAN, "BOOLEAN", 0, "Boolean", "Boolean"},
+ {VOLUME_GRID_FLOAT, "FLOAT", 0, "Float", "Single precision float"},
+ {VOLUME_GRID_DOUBLE, "DOUBLE", 0, "Double", "Double precision"},
+ {VOLUME_GRID_INT, "INT", 0, "Integer", "32-bit integer"},
+ {VOLUME_GRID_INT64, "INT64", 0, "Integer 64-bit", "64-bit integer"},
+ {VOLUME_GRID_MASK, "MASK", 0, "Mask", "No data, boolean mask of active voxels"},
+ {VOLUME_GRID_STRING, "STRING", 0, "String", "Text string"},
+ {VOLUME_GRID_VECTOR_FLOAT, "VECTOR_FLOAT", 0, "Float Vector", "3D float vector"},
+ {VOLUME_GRID_VECTOR_DOUBLE, "VECTOR_DOUBLE", 0, "Double Vector", "3D double vector"},
+ {VOLUME_GRID_VECTOR_INT, "VECTOR_INT", 0, "Integer Vector", "3D integer vector"},
+ {VOLUME_GRID_POINTS,
+ "POINTS",
+ 0,
+ "Points (Unsupported)",
+ "Points grid, currently unsupported by volume objects"},
+ {VOLUME_GRID_UNKNOWN, "UNKNOWN", 0, "Unknown", "Unsupported data type"},
+ {0, NULL, 0, NULL, NULL},
+};
+
#ifdef RNA_RUNTIME
# include "DEG_depsgraph.h"
@@ -244,30 +264,10 @@ static void rna_def_volume_grid(BlenderRNA *brna)
prop, "rna_VolumeGrid_name_get", "rna_VolumeGrid_name_length", NULL);
RNA_def_property_ui_text(prop, "Name", "Volume grid name");
- static const EnumPropertyItem data_type_items[] = {
- {VOLUME_GRID_BOOLEAN, "BOOLEAN", 0, "Boolean", "Boolean"},
- {VOLUME_GRID_FLOAT, "FLOAT", 0, "Float", "Single precision float"},
- {VOLUME_GRID_DOUBLE, "DOUBLE", 0, "Double", "Double precision"},
- {VOLUME_GRID_INT, "INT", 0, "Integer", "32-bit integer"},
- {VOLUME_GRID_INT64, "INT64", 0, "Integer 64-bit", "64-bit integer"},
- {VOLUME_GRID_MASK, "MASK", 0, "Mask", "No data, boolean mask of active voxels"},
- {VOLUME_GRID_STRING, "STRING", 0, "String", "Text string"},
- {VOLUME_GRID_VECTOR_FLOAT, "VECTOR_FLOAT", 0, "Float Vector", "3D float vector"},
- {VOLUME_GRID_VECTOR_DOUBLE, "VECTOR_DOUBLE", 0, "Double Vector", "3D double vector"},
- {VOLUME_GRID_VECTOR_INT, "VECTOR_INT", 0, "Integer Vector", "3D integer vector"},
- {VOLUME_GRID_POINTS,
- "POINTS",
- 0,
- "Points (Unsupported)",
- "Points grid, currently unsupported by volume objects"},
- {VOLUME_GRID_UNKNOWN, "UNKNOWN", 0, "Unknown", "Unsupported data type"},
- {0, NULL, 0, NULL, NULL},
- };
-
prop = RNA_def_property(srna, "data_type", PROP_ENUM, PROP_NONE);
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
RNA_def_property_enum_funcs(prop, "rna_VolumeGrid_data_type_get", NULL, NULL);
- RNA_def_property_enum_items(prop, data_type_items);
+ RNA_def_property_enum_items(prop, rna_enum_volume_grid_data_type_items);
RNA_def_property_ui_text(prop, "Data Type", "Data type of voxel values");
prop = RNA_def_property(srna, "channels", PROP_INT, PROP_UNSIGNED);
diff --git a/source/blender/modifiers/intern/MOD_boolean.cc b/source/blender/modifiers/intern/MOD_boolean.cc
index 1121e30b0ff..f8c181905b5 100644
--- a/source/blender/modifiers/intern/MOD_boolean.cc
+++ b/source/blender/modifiers/intern/MOD_boolean.cc
@@ -245,16 +245,16 @@ static BMesh *BMD_mesh_bm_create(
const BMAllocTemplate allocsize = BMALLOC_TEMPLATE_FROM_ME(mesh, mesh_operand_ob);
- BMeshCreateParams bmcp = {false};
- BMesh *bm = BM_mesh_create(&allocsize, &bmcp);
+ BMeshCreateParams bmesh_create_params{};
+ BMesh *bm = BM_mesh_create(&allocsize, &bmesh_create_params);
/* Needed so active layers are set based on `mesh` not `mesh_operand_ob`,
* otherwise the wrong active render layer is used, see T92384. */
BM_mesh_copy_init_customdata_from_mesh(bm, mesh, &allocsize);
- BMeshFromMeshParams params{};
- params.calc_face_normal = true;
- BM_mesh_bm_from_me(bm, mesh_operand_ob, &params);
+ BMeshFromMeshParams bmesh_from_mesh_params{};
+ bmesh_from_mesh_params.calc_face_normal = true;
+ BM_mesh_bm_from_me(bm, mesh_operand_ob, &bmesh_from_mesh_params);
if (UNLIKELY(*r_is_flip)) {
const int cd_loop_mdisp_offset = CustomData_get_offset(&bm->ldata, CD_MDISPS);
@@ -265,7 +265,7 @@ static BMesh *BMD_mesh_bm_create(
}
}
- BM_mesh_bm_from_me(bm, mesh, &params);
+ BM_mesh_bm_from_me(bm, mesh, &bmesh_from_mesh_params);
return bm;
}
@@ -539,9 +539,9 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh *
BMD_mesh_intersection(bm, md, ctx, mesh_operand_ob, object, operand_ob, is_flip);
/* Needed for multiple objects to work. */
- BMeshToMeshParams params{};
- params.calc_object_remap = false;
- BM_mesh_bm_to_me(nullptr, bm, mesh, &params);
+ BMeshToMeshParams bmesh_to_mesh_params{};
+ bmesh_to_mesh_params.calc_object_remap = false;
+ BM_mesh_bm_to_me(nullptr, bm, mesh, &bmesh_to_mesh_params);
result = BKE_mesh_from_bmesh_for_eval_nomain(bm, nullptr, mesh);
BM_mesh_free(bm);
diff --git a/source/blender/modifiers/intern/MOD_meshdeform.c b/source/blender/modifiers/intern/MOD_meshdeform.c
index c997cd7377f..cb043643dd9 100644
--- a/source/blender/modifiers/intern/MOD_meshdeform.c
+++ b/source/blender/modifiers/intern/MOD_meshdeform.c
@@ -426,7 +426,7 @@ static void meshdeformModifier_do(ModifierData *md,
bindcagecos = (float(*)[3])mmd->bindcagecos;
for (a = 0; a < totcagevert; a++) {
- /* get cage vertex in world space with binding transform */
+ /* Get cage vertex in world-space with binding transform. */
float co[3];
mul_v3_m4v3(co, mmd->bindmat, dco[a]);
/* compute difference with world space bind coord */
diff --git a/source/blender/modifiers/intern/MOD_nodes.cc b/source/blender/modifiers/intern/MOD_nodes.cc
index c1cdfa43920..05e9bd7d233 100644
--- a/source/blender/modifiers/intern/MOD_nodes.cc
+++ b/source/blender/modifiers/intern/MOD_nodes.cc
@@ -98,6 +98,7 @@
#include "NOD_node_declaration.hh"
#include "FN_field.hh"
+#include "FN_field_cpp_type.hh"
#include "FN_multi_function.hh"
using blender::Array;
@@ -113,9 +114,11 @@ using blender::StringRef;
using blender::StringRefNull;
using blender::Vector;
using blender::bke::OutputAttribute;
+using blender::fn::Field;
using blender::fn::GField;
using blender::fn::GMutablePointer;
using blender::fn::GPointer;
+using blender::fn::ValueOrField;
using blender::nodes::FieldInferencingInterface;
using blender::nodes::GeoNodeExecParams;
using blender::nodes::InputSocketFieldType;
@@ -491,35 +494,34 @@ static void init_socket_cpp_value_from_property(const IDProperty &property,
else if (property.type == IDP_DOUBLE) {
value = (float)IDP_Double(&property);
}
- new (r_value) blender::fn::Field<float>(blender::fn::make_constant_field(value));
+ new (r_value) ValueOrField<float>(value);
break;
}
case SOCK_INT: {
int value = IDP_Int(&property);
- new (r_value) blender::fn::Field<int>(blender::fn::make_constant_field(value));
+ new (r_value) ValueOrField<int>(value);
break;
}
case SOCK_VECTOR: {
float3 value;
copy_v3_v3(value, (const float *)IDP_Array(&property));
- new (r_value) blender::fn::Field<float3>(blender::fn::make_constant_field(value));
+ new (r_value) ValueOrField<float3>(value);
break;
}
case SOCK_RGBA: {
blender::ColorGeometry4f value;
copy_v4_v4((float *)value, (const float *)IDP_Array(&property));
- new (r_value) blender::fn::Field<ColorGeometry4f>(blender::fn::make_constant_field(value));
+ new (r_value) ValueOrField<ColorGeometry4f>(value);
break;
}
case SOCK_BOOLEAN: {
bool value = IDP_Int(&property) != 0;
- new (r_value) blender::fn::Field<bool>(blender::fn::make_constant_field(value));
+ new (r_value) ValueOrField<bool>(value);
break;
}
case SOCK_STRING: {
std::string value = IDP_String(&property);
- new (r_value)
- blender::fn::Field<std::string>(blender::fn::make_constant_field(std::move(value)));
+ new (r_value) ValueOrField<std::string>(std::move(value));
break;
}
case SOCK_OBJECT: {
@@ -739,8 +741,13 @@ static void initialize_group_input(NodesModifierData &nmd,
if (use_attribute) {
const StringRef attribute_name{IDP_String(property_attribute_name)};
auto attribute_input = std::make_shared<blender::bke::AttributeFieldInput>(
- attribute_name, *socket_type.get_base_cpp_type());
- new (r_value) blender::fn::GField(std::move(attribute_input), 0);
+ attribute_name, *socket_type.base_cpp_type);
+ GField attribute_field{std::move(attribute_input), 0};
+ const blender::fn::ValueOrFieldCPPType *cpp_type =
+ dynamic_cast<const blender::fn::ValueOrFieldCPPType *>(
+ socket_type.geometry_nodes_cpp_type);
+ BLI_assert(cpp_type != nullptr);
+ cpp_type->construct_from_field(r_value, std::move(attribute_field));
}
else {
init_socket_cpp_value_from_property(
@@ -904,7 +911,11 @@ static void store_output_value_in_geometry(GeometrySet &geometry_set,
if (attribute_name.is_empty()) {
return;
}
- const GField &field = *(const GField *)value.get();
+ const blender::fn::ValueOrFieldCPPType *cpp_type =
+ dynamic_cast<const blender::fn::ValueOrFieldCPPType *>(value.type());
+ BLI_assert(cpp_type != nullptr);
+
+ const GField field = cpp_type->as_field(value.get());
const bNodeSocket *interface_socket = (bNodeSocket *)BLI_findlink(&nmd->node_group->outputs,
socket.index());
const AttributeDomain domain = (AttributeDomain)interface_socket->attribute_domain;
@@ -963,7 +974,7 @@ static GeometrySet compute_geometry(const DerivedNodeTree &tree,
/* Initialize remaining group inputs. */
for (const OutputSocketRef *socket : remaining_input_sockets) {
- const CPPType &cpp_type = *socket->typeinfo()->get_geometry_nodes_cpp_type();
+ const CPPType &cpp_type = *socket->typeinfo()->geometry_nodes_cpp_type;
void *value_in = allocator.allocate(cpp_type.size(), cpp_type.alignment());
initialize_group_input(*nmd, *socket, value_in);
group_inputs.add_new({root_context, socket}, {cpp_type, value_in});
diff --git a/source/blender/modifiers/intern/MOD_nodes_evaluator.cc b/source/blender/modifiers/intern/MOD_nodes_evaluator.cc
index 094649baa87..0deef91d413 100644
--- a/source/blender/modifiers/intern/MOD_nodes_evaluator.cc
+++ b/source/blender/modifiers/intern/MOD_nodes_evaluator.cc
@@ -35,13 +35,17 @@
#include "BLI_task.hh"
#include "BLI_vector_set.hh"
+#include <chrono>
+
namespace blender::modifiers::geometry_nodes {
using fn::CPPType;
using fn::Field;
-using fn::FieldCPPType;
using fn::GField;
using fn::GValueMap;
+using fn::GVArray;
+using fn::ValueOrField;
+using fn::ValueOrFieldCPPType;
using nodes::GeoNodeExecParams;
using namespace fn::multi_function_types;
@@ -309,10 +313,10 @@ class LockedNode : NonCopyable, NonMovable {
static const CPPType *get_socket_cpp_type(const SocketRef &socket)
{
const bNodeSocketType *typeinfo = socket.typeinfo();
- if (typeinfo->get_geometry_nodes_cpp_type == nullptr) {
+ if (typeinfo->geometry_nodes_cpp_type == nullptr) {
return nullptr;
}
- const CPPType *type = typeinfo->get_geometry_nodes_cpp_type();
+ const CPPType *type = typeinfo->geometry_nodes_cpp_type;
if (type == nullptr) {
return nullptr;
}
@@ -348,18 +352,19 @@ static bool get_implicit_socket_input(const SocketRef &socket, void *r_value)
GEO_NODE_CURVE_HANDLE_LEFT ?
"handle_left" :
"handle_right";
- new (r_value) Field<float3>(bke::AttributeFieldInput::Create<float3>(side));
+ new (r_value) ValueOrField<float3>(bke::AttributeFieldInput::Create<float3>(side));
return true;
}
- new (r_value) Field<float3>(bke::AttributeFieldInput::Create<float3>("position"));
+ new (r_value) ValueOrField<float3>(bke::AttributeFieldInput::Create<float3>("position"));
return true;
}
if (socket.typeinfo()->type == SOCK_INT) {
if (ELEM(bnode.type, FN_NODE_RANDOM_VALUE, GEO_NODE_INSTANCE_ON_POINTS)) {
- new (r_value) Field<int>(std::make_shared<bke::IDAttributeFieldInput>());
+ new (r_value)
+ ValueOrField<int>(Field<int>(std::make_shared<bke::IDAttributeFieldInput>()));
return true;
}
- new (r_value) Field<int>(std::make_shared<fn::IndexFieldInput>());
+ new (r_value) ValueOrField<int>(Field<int>(std::make_shared<fn::IndexFieldInput>()));
return true;
}
}
@@ -926,7 +931,13 @@ class GeometryNodesEvaluator {
params.error_message_add(geo_log::NodeWarningType::Legacy,
TIP_("Legacy node will be removed before Blender 4.0"));
}
+ using Clock = std::chrono::steady_clock;
+ Clock::time_point begin = Clock::now();
bnode.typeinfo->geometry_node_execute(params);
+ Clock::time_point end = Clock::now();
+ const std::chrono::microseconds duration =
+ std::chrono::duration_cast<std::chrono::microseconds>(end - begin);
+ params_.geo_logger->local().log_execution_time(node, duration);
}
void execute_multi_function_node(const DNode node,
@@ -943,8 +954,9 @@ class GeometryNodesEvaluator {
LinearAllocator<> &allocator = local_allocators_.local();
- /* Prepare the inputs for the multi function. */
- Vector<GField> input_fields;
+ bool any_input_is_field = false;
+ Vector<const void *, 16> input_values;
+ Vector<const ValueOrFieldCPPType *, 16> input_types;
for (const int i : node->inputs().index_range()) {
const InputSocketRef &socket_ref = node->input(i);
if (!socket_ref.is_available()) {
@@ -955,7 +967,37 @@ class GeometryNodesEvaluator {
BLI_assert(input_state.was_ready_for_execution);
SingleInputValue &single_value = *input_state.value.single;
BLI_assert(single_value.value != nullptr);
- input_fields.append(std::move(*(GField *)single_value.value));
+ const ValueOrFieldCPPType &field_cpp_type = static_cast<const ValueOrFieldCPPType &>(
+ *input_state.type);
+ input_values.append(single_value.value);
+ input_types.append(&field_cpp_type);
+ if (field_cpp_type.is_field(single_value.value)) {
+ any_input_is_field = true;
+ }
+ }
+
+ if (any_input_is_field) {
+ this->execute_multi_function_node__field(
+ node, fn_item, node_state, allocator, input_values, input_types);
+ }
+ else {
+ this->execute_multi_function_node__value(
+ node, *fn_item.fn, node_state, allocator, input_values, input_types);
+ }
+ }
+
+ void execute_multi_function_node__field(const DNode node,
+ const nodes::NodeMultiFunctions::Item &fn_item,
+ NodeState &node_state,
+ LinearAllocator<> &allocator,
+ Span<const void *> input_values,
+ Span<const ValueOrFieldCPPType *> input_types)
+ {
+ Vector<GField> input_fields;
+ for (const int i : input_values.index_range()) {
+ const void *input_value_or_field = input_values[i];
+ const ValueOrFieldCPPType &field_cpp_type = *input_types[i];
+ input_fields.append(field_cpp_type.as_field(input_value_or_field));
}
std::shared_ptr<fn::FieldOperation> operation;
@@ -966,7 +1008,6 @@ class GeometryNodesEvaluator {
operation = std::make_shared<fn::FieldOperation>(*fn_item.fn, std::move(input_fields));
}
- /* Forward outputs. */
int output_index = 0;
for (const int i : node->outputs().index_range()) {
const OutputSocketRef &socket_ref = node->output(i);
@@ -975,16 +1016,68 @@ class GeometryNodesEvaluator {
}
OutputState &output_state = node_state.outputs[i];
const DOutputSocket socket{node.context(), &socket_ref};
- const CPPType *cpp_type = get_socket_cpp_type(socket_ref);
+ const ValueOrFieldCPPType *cpp_type = static_cast<const ValueOrFieldCPPType *>(
+ get_socket_cpp_type(socket_ref));
GField new_field{operation, output_index};
- new_field = fn::make_field_constant_if_possible(std::move(new_field));
- GField &field_to_forward = *allocator.construct<GField>(std::move(new_field)).release();
- this->forward_output(socket, {cpp_type, &field_to_forward});
+ void *buffer = allocator.allocate(cpp_type->size(), cpp_type->alignment());
+ cpp_type->construct_from_field(buffer, std::move(new_field));
+ this->forward_output(socket, {cpp_type, buffer});
output_state.has_been_computed = true;
output_index++;
}
}
+ void execute_multi_function_node__value(const DNode node,
+ const MultiFunction &fn,
+ NodeState &node_state,
+ LinearAllocator<> &allocator,
+ Span<const void *> input_values,
+ Span<const ValueOrFieldCPPType *> input_types)
+ {
+ MFParamsBuilder params{fn, 1};
+ for (const int i : input_values.index_range()) {
+ const void *input_value_or_field = input_values[i];
+ const ValueOrFieldCPPType &field_cpp_type = *input_types[i];
+ const CPPType &base_type = field_cpp_type.base_type();
+ const void *input_value = field_cpp_type.get_value_ptr(input_value_or_field);
+ params.add_readonly_single_input(GVArray::ForSingleRef(base_type, 1, input_value));
+ }
+
+ Vector<GMutablePointer, 16> output_buffers;
+ for (const int i : node->outputs().index_range()) {
+ const DOutputSocket socket = node.output(i);
+ if (!socket->is_available()) {
+ output_buffers.append({});
+ continue;
+ }
+ const ValueOrFieldCPPType *value_or_field_type = static_cast<const ValueOrFieldCPPType *>(
+ get_socket_cpp_type(socket));
+ const CPPType &base_type = value_or_field_type->base_type();
+ void *value_or_field_buffer = allocator.allocate(value_or_field_type->size(),
+ value_or_field_type->alignment());
+ value_or_field_type->default_construct(value_or_field_buffer);
+ void *value_buffer = value_or_field_type->get_value_ptr(value_or_field_buffer);
+ base_type.destruct(value_buffer);
+ params.add_uninitialized_single_output(GMutableSpan{base_type, value_buffer, 1});
+ output_buffers.append({value_or_field_type, value_or_field_buffer});
+ }
+
+ MFContextBuilder context;
+ fn.call(IndexRange(1), params, context);
+
+ for (const int i : output_buffers.index_range()) {
+ GMutablePointer buffer = output_buffers[i];
+ if (buffer.get() == nullptr) {
+ continue;
+ }
+ const DOutputSocket socket = node.output(i);
+ this->forward_output(socket, buffer);
+
+ OutputState &output_state = node_state.outputs[i];
+ output_state.has_been_computed = true;
+ }
+ }
+
void execute_unknown_node(const DNode node, NodeState &node_state)
{
LinearAllocator<> &allocator = local_allocators_.local();
@@ -1482,19 +1575,28 @@ class GeometryNodesEvaluator {
from_type.copy_construct(from_value, to_value);
return;
}
-
- const FieldCPPType *from_field_type = dynamic_cast<const FieldCPPType *>(&from_type);
- const FieldCPPType *to_field_type = dynamic_cast<const FieldCPPType *>(&to_type);
+ const ValueOrFieldCPPType *from_field_type = dynamic_cast<const ValueOrFieldCPPType *>(
+ &from_type);
+ const ValueOrFieldCPPType *to_field_type = dynamic_cast<const ValueOrFieldCPPType *>(&to_type);
if (from_field_type != nullptr && to_field_type != nullptr) {
- const CPPType &from_base_type = from_field_type->field_type();
- const CPPType &to_base_type = to_field_type->field_type();
+ const CPPType &from_base_type = from_field_type->base_type();
+ const CPPType &to_base_type = to_field_type->base_type();
if (conversions_.is_convertible(from_base_type, to_base_type)) {
- const MultiFunction &fn = *conversions_.get_conversion_multi_function(
- MFDataType::ForSingle(from_base_type), MFDataType::ForSingle(to_base_type));
- const GField &from_field = *(const GField *)from_value;
- auto operation = std::make_shared<fn::FieldOperation>(fn, Vector<GField>{from_field});
- new (to_value) GField(std::move(operation), 0);
+ if (from_field_type->is_field(from_value)) {
+ const GField &from_field = *from_field_type->get_field_ptr(from_value);
+ const MultiFunction &fn = *conversions_.get_conversion_multi_function(
+ MFDataType::ForSingle(from_base_type), MFDataType::ForSingle(to_base_type));
+ auto operation = std::make_shared<fn::FieldOperation>(fn, Vector<GField>{from_field});
+ to_field_type->construct_from_field(to_value, GField(std::move(operation), 0));
+ }
+ else {
+ to_field_type->default_construct(to_value);
+ const void *from_value_ptr = from_field_type->get_value_ptr(from_value);
+ void *to_value_ptr = to_field_type->get_value_ptr(to_value);
+ conversions_.get_conversion_functions(from_base_type, to_base_type)
+ ->convert_single_to_initialized(from_value_ptr, to_value_ptr);
+ }
return;
}
}
@@ -1510,14 +1612,6 @@ class GeometryNodesEvaluator {
void construct_default_value(const CPPType &type, void *r_value)
{
- if (const FieldCPPType *field_cpp_type = dynamic_cast<const FieldCPPType *>(&type)) {
- const CPPType &base_type = field_cpp_type->field_type();
- auto constant_fn = std::make_unique<fn::CustomMF_GenericConstant>(
- base_type, base_type.default_value(), false);
- auto operation = std::make_shared<fn::FieldOperation>(std::move(constant_fn));
- new (r_value) GField(std::move(operation), 0);
- return;
- }
type.copy_construct(type.default_value(), r_value);
}
diff --git a/source/blender/modifiers/intern/MOD_uvproject.c b/source/blender/modifiers/intern/MOD_uvproject.c
index 2c28e9710ef..238952fde00 100644
--- a/source/blender/modifiers/intern/MOD_uvproject.c
+++ b/source/blender/modifiers/intern/MOD_uvproject.c
@@ -192,7 +192,7 @@ static Mesh *uvprojectModifier_do(UVProjectModifierData *umd,
mul_m4_m4m4(projectors[i].projmat, offsetmat, tmpmat);
- /* calculate worldspace projector normal (for best projector test) */
+ /* Calculate world-space projector normal (for best projector test). */
projectors[i].normal[0] = 0;
projectors[i].normal[1] = 0;
projectors[i].normal[2] = 1;
@@ -208,7 +208,7 @@ static Mesh *uvprojectModifier_do(UVProjectModifierData *umd,
coords = BKE_mesh_vert_coords_alloc(mesh, &numVerts);
- /* convert coords to world space */
+ /* Convert coords to world-space. */
for (i = 0, co = coords; i < numVerts; i++, co++) {
mul_m4_v3(ob->obmat, *co);
}
diff --git a/source/blender/nodes/CMakeLists.txt b/source/blender/nodes/CMakeLists.txt
index f4ca9f51b1b..e256ebcff56 100644
--- a/source/blender/nodes/CMakeLists.txt
+++ b/source/blender/nodes/CMakeLists.txt
@@ -18,6 +18,8 @@
# All rights reserved.
# ***** END GPL LICENSE BLOCK *****
+add_subdirectory(geometry)
+
set(INC
.
composite
@@ -39,6 +41,7 @@ set(INC
../makesdna
../makesrna
../render
+ ../windowmanager
../../../intern/glew-mx
../../../intern/guardedalloc
../../../intern/sky/include
@@ -154,148 +157,6 @@ set(SRC
function/nodes/node_fn_value_to_string.cc
function/node_function_util.cc
- geometry/nodes/legacy/node_geo_align_rotation_to_vector.cc
- geometry/nodes/legacy/node_geo_attribute_clamp.cc
- geometry/nodes/legacy/node_geo_attribute_color_ramp.cc
- geometry/nodes/legacy/node_geo_attribute_combine_xyz.cc
- geometry/nodes/legacy/node_geo_attribute_compare.cc
- geometry/nodes/legacy/node_geo_attribute_convert.cc
- geometry/nodes/legacy/node_geo_attribute_curve_map.cc
- geometry/nodes/legacy/node_geo_attribute_fill.cc
- geometry/nodes/legacy/node_geo_attribute_map_range.cc
- geometry/nodes/legacy/node_geo_attribute_math.cc
- geometry/nodes/legacy/node_geo_attribute_mix.cc
- geometry/nodes/legacy/node_geo_attribute_proximity.cc
- geometry/nodes/legacy/node_geo_attribute_randomize.cc
- geometry/nodes/legacy/node_geo_attribute_sample_texture.cc
- geometry/nodes/legacy/node_geo_attribute_separate_xyz.cc
- geometry/nodes/legacy/node_geo_attribute_transfer.cc
- geometry/nodes/legacy/node_geo_attribute_vector_math.cc
- geometry/nodes/legacy/node_geo_attribute_vector_rotate.cc
- geometry/nodes/legacy/node_geo_curve_endpoints.cc
- geometry/nodes/legacy/node_geo_curve_reverse.cc
- geometry/nodes/legacy/node_geo_curve_select_by_handle_type.cc
- geometry/nodes/legacy/node_geo_curve_set_handles.cc
- geometry/nodes/legacy/node_geo_curve_spline_type.cc
- geometry/nodes/legacy/node_geo_curve_subdivide.cc
- geometry/nodes/legacy/node_geo_curve_to_points.cc
- geometry/nodes/legacy/node_geo_delete_geometry.cc
- geometry/nodes/legacy/node_geo_edge_split.cc
- geometry/nodes/legacy/node_geo_material_assign.cc
- geometry/nodes/legacy/node_geo_mesh_to_curve.cc
- geometry/nodes/legacy/node_geo_point_distribute.cc
- geometry/nodes/legacy/node_geo_point_instance.cc
- geometry/nodes/legacy/node_geo_point_rotate.cc
- geometry/nodes/legacy/node_geo_point_scale.cc
- geometry/nodes/legacy/node_geo_point_separate.cc
- geometry/nodes/legacy/node_geo_point_translate.cc
- geometry/nodes/legacy/node_geo_points_to_volume.cc
- geometry/nodes/legacy/node_geo_raycast.cc
- geometry/nodes/legacy/node_geo_select_by_material.cc
- geometry/nodes/legacy/node_geo_subdivision_surface.cc
- geometry/nodes/legacy/node_geo_volume_to_mesh.cc
-
- geometry/nodes/node_geo_attribute_capture.cc
- geometry/nodes/node_geo_attribute_remove.cc
- geometry/nodes/node_geo_attribute_statistic.cc
- geometry/nodes/node_geo_boolean.cc
- geometry/nodes/node_geo_bounding_box.cc
- geometry/nodes/node_geo_collection_info.cc
- geometry/nodes/node_geo_common.cc
- geometry/nodes/node_geo_convex_hull.cc
- geometry/nodes/node_geo_curve_endpoint_selection.cc
- geometry/nodes/node_geo_curve_fill.cc
- geometry/nodes/node_geo_curve_fillet.cc
- geometry/nodes/node_geo_curve_handle_type_selection.cc
- geometry/nodes/node_geo_curve_length.cc
- geometry/nodes/node_geo_curve_parameter.cc
- geometry/nodes/node_geo_curve_primitive_bezier_segment.cc
- geometry/nodes/node_geo_curve_primitive_circle.cc
- geometry/nodes/node_geo_curve_primitive_line.cc
- geometry/nodes/node_geo_curve_primitive_quadratic_bezier.cc
- geometry/nodes/node_geo_curve_primitive_quadrilateral.cc
- geometry/nodes/node_geo_curve_primitive_spiral.cc
- geometry/nodes/node_geo_curve_primitive_star.cc
- geometry/nodes/node_geo_curve_resample.cc
- geometry/nodes/node_geo_curve_reverse.cc
- geometry/nodes/node_geo_curve_sample.cc
- geometry/nodes/node_geo_curve_set_handles.cc
- geometry/nodes/node_geo_curve_spline_type.cc
- geometry/nodes/node_geo_curve_subdivide.cc
- geometry/nodes/node_geo_curve_to_mesh.cc
- geometry/nodes/node_geo_curve_to_points.cc
- geometry/nodes/node_geo_curve_trim.cc
- geometry/nodes/node_geo_delete_geometry.cc
- geometry/nodes/node_geo_distribute_points_on_faces.cc
- geometry/nodes/node_geo_edge_split.cc
- geometry/nodes/node_geo_image_texture.cc
- geometry/nodes/node_geo_input_curve_handles.cc
- geometry/nodes/node_geo_input_curve_tilt.cc
- geometry/nodes/node_geo_input_id.cc
- geometry/nodes/node_geo_input_index.cc
- geometry/nodes/node_geo_input_material_index.cc
- geometry/nodes/node_geo_input_material.cc
- geometry/nodes/node_geo_input_normal.cc
- geometry/nodes/node_geo_input_position.cc
- geometry/nodes/node_geo_input_radius.cc
- geometry/nodes/node_geo_input_shade_smooth.cc
- geometry/nodes/node_geo_input_spline_cyclic.cc
- geometry/nodes/node_geo_input_spline_length.cc
- geometry/nodes/node_geo_input_spline_resolution.cc
- geometry/nodes/node_geo_input_tangent.cc
- geometry/nodes/node_geo_instance_on_points.cc
- geometry/nodes/node_geo_instances_to_points.cc
- geometry/nodes/node_geo_is_viewport.cc
- geometry/nodes/node_geo_join_geometry.cc
- geometry/nodes/node_geo_material_replace.cc
- geometry/nodes/node_geo_material_selection.cc
- geometry/nodes/node_geo_mesh_primitive_circle.cc
- geometry/nodes/node_geo_mesh_primitive_cone.cc
- geometry/nodes/node_geo_mesh_primitive_cube.cc
- geometry/nodes/node_geo_mesh_primitive_cylinder.cc
- geometry/nodes/node_geo_mesh_primitive_grid.cc
- geometry/nodes/node_geo_mesh_primitive_ico_sphere.cc
- geometry/nodes/node_geo_mesh_primitive_line.cc
- geometry/nodes/node_geo_mesh_primitive_uv_sphere.cc
- geometry/nodes/node_geo_mesh_subdivide.cc
- geometry/nodes/node_geo_mesh_to_curve.cc
- geometry/nodes/node_geo_mesh_to_points.cc
- geometry/nodes/node_geo_object_info.cc
- geometry/nodes/node_geo_points_to_vertices.cc
- geometry/nodes/node_geo_points_to_volume.cc
- geometry/nodes/node_geo_proximity.cc
- geometry/nodes/node_geo_raycast.cc
- geometry/nodes/node_geo_realize_instances.cc
- geometry/nodes/node_geo_rotate_instances.cc
- geometry/nodes/node_geo_scale_instances.cc
- geometry/nodes/node_geo_separate_components.cc
- geometry/nodes/node_geo_separate_geometry.cc
- geometry/nodes/node_geo_set_curve_handles.cc
- geometry/nodes/node_geo_set_curve_radius.cc
- geometry/nodes/node_geo_set_curve_tilt.cc
- geometry/nodes/node_geo_set_id.cc
- geometry/nodes/node_geo_set_material_index.cc
- geometry/nodes/node_geo_set_material.cc
- geometry/nodes/node_geo_set_point_radius.cc
- geometry/nodes/node_geo_set_position.cc
- geometry/nodes/node_geo_set_shade_smooth.cc
- geometry/nodes/node_geo_set_spline_cyclic.cc
- geometry/nodes/node_geo_set_spline_resolution.cc
- geometry/nodes/node_geo_string_join.cc
- geometry/nodes/node_geo_string_to_curves.cc
- geometry/nodes/node_geo_subdivision_surface.cc
- geometry/nodes/node_geo_switch.cc
- geometry/nodes/node_geo_transfer_attribute.cc
- geometry/nodes/node_geo_transform.cc
- geometry/nodes/node_geo_translate_instances.cc
- geometry/nodes/node_geo_triangulate.cc
- geometry/nodes/node_geo_viewer.cc
- geometry/nodes/node_geo_volume_to_mesh.cc
-
- geometry/node_geometry_exec.cc
- geometry/node_geometry_tree.cc
- geometry/node_geometry_util.cc
-
shader/nodes/node_shader_add_shader.c
shader/nodes/node_shader_ambient_occlusion.c
shader/nodes/node_shader_attribute.c
@@ -433,7 +294,6 @@ set(SRC
composite/node_composite_util.hh
function/node_function_util.hh
shader/node_shader_util.h
- geometry/node_geometry_util.hh
texture/node_texture_util.h
NOD_common.h
@@ -462,8 +322,8 @@ set(SRC
set(LIB
bf_bmesh
bf_functions
- bf_geometry
bf_intern_sky
+ bf_nodes_geometry
)
if(WITH_BULLET)
diff --git a/source/blender/nodes/NOD_common.h b/source/blender/nodes/NOD_common.h
index 50ed992dcb6..fa979bb4799 100644
--- a/source/blender/nodes/NOD_common.h
+++ b/source/blender/nodes/NOD_common.h
@@ -45,6 +45,8 @@ struct bNodeSocket *node_group_output_find_socket(struct bNode *node, const char
void node_group_input_update(struct bNodeTree *ntree, struct bNode *node);
void node_group_output_update(struct bNodeTree *ntree, struct bNode *node);
+void node_internal_links_create(struct bNodeTree *ntree, struct bNode *node);
+
#ifdef __cplusplus
}
#endif
diff --git a/source/blender/nodes/NOD_geometry_exec.hh b/source/blender/nodes/NOD_geometry_exec.hh
index 6e1f21dbae0..6b6e8a89240 100644
--- a/source/blender/nodes/NOD_geometry_exec.hh
+++ b/source/blender/nodes/NOD_geometry_exec.hh
@@ -57,13 +57,9 @@ using fn::GPointer;
using fn::GSpan;
using fn::GVArray;
using fn::GVArray_GSpan;
-using fn::GVArray_Span;
-using fn::GVArray_Typed;
-using fn::GVArrayPtr;
using fn::GVMutableArray;
using fn::GVMutableArray_GSpan;
-using fn::GVMutableArray_Typed;
-using fn::GVMutableArrayPtr;
+using fn::ValueOrField;
using geometry_nodes_eval_log::NodeWarningType;
/**
@@ -134,7 +130,7 @@ class GeoNodeExecParams {
}
template<typename T>
- static inline constexpr bool is_stored_as_field_v = std::is_same_v<T, float> ||
+ static inline constexpr bool is_field_base_type_v = std::is_same_v<T, float> ||
std::is_same_v<T, int> ||
std::is_same_v<T, bool> ||
std::is_same_v<T, ColorGeometry4f> ||
@@ -162,9 +158,15 @@ class GeoNodeExecParams {
*/
template<typename T> T extract_input(StringRef identifier)
{
- if constexpr (is_stored_as_field_v<T>) {
- Field<T> field = this->extract_input<Field<T>>(identifier);
- return fn::evaluate_constant_field(field);
+ if constexpr (is_field_base_type_v<T>) {
+ ValueOrField<T> value_or_field = this->extract_input<ValueOrField<T>>(identifier);
+ return value_or_field.as_value();
+ }
+ else if constexpr (fn::is_field_v<T>) {
+ using BaseType = typename T::base_type;
+ ValueOrField<BaseType> value_or_field = this->extract_input<ValueOrField<BaseType>>(
+ identifier);
+ return value_or_field.as_field();
}
else {
#ifdef DEBUG
@@ -191,9 +193,9 @@ class GeoNodeExecParams {
Vector<GMutablePointer> gvalues = provider_->extract_multi_input(identifier);
Vector<T> values;
for (GMutablePointer gvalue : gvalues) {
- if constexpr (is_stored_as_field_v<T>) {
- const Field<T> field = gvalue.relocate_out<Field<T>>();
- values.append(fn::evaluate_constant_field(field));
+ if constexpr (is_field_base_type_v<T>) {
+ const ValueOrField<T> value_or_field = gvalue.relocate_out<ValueOrField<T>>();
+ values.append(value_or_field.as_value());
}
else {
values.append(gvalue.relocate_out<T>());
@@ -205,11 +207,16 @@ class GeoNodeExecParams {
/**
* Get the input value for the input socket with the given identifier.
*/
- template<typename T> const T get_input(StringRef identifier) const
+ template<typename T> T get_input(StringRef identifier) const
{
- if constexpr (is_stored_as_field_v<T>) {
- const Field<T> &field = this->get_input<Field<T>>(identifier);
- return fn::evaluate_constant_field(field);
+ if constexpr (is_field_base_type_v<T>) {
+ ValueOrField<T> value_or_field = this->get_input<ValueOrField<T>>(identifier);
+ return value_or_field.as_value();
+ }
+ else if constexpr (fn::is_field_v<T>) {
+ using BaseType = typename T::base_type;
+ ValueOrField<BaseType> value_or_field = this->get_input<ValueOrField<BaseType>>(identifier);
+ return value_or_field.as_field();
}
else {
#ifdef DEBUG
@@ -231,9 +238,12 @@ class GeoNodeExecParams {
template<typename T> void set_output(StringRef identifier, T &&value)
{
using StoredT = std::decay_t<T>;
- if constexpr (is_stored_as_field_v<StoredT>) {
- this->set_output<Field<StoredT>>(identifier,
- fn::make_constant_field<StoredT>(std::forward<T>(value)));
+ if constexpr (is_field_base_type_v<StoredT>) {
+ this->set_output(identifier, ValueOrField<StoredT>(std::forward<T>(value)));
+ }
+ else if constexpr (fn::is_field_v<StoredT>) {
+ using BaseType = typename StoredT::base_type;
+ this->set_output(identifier, ValueOrField<BaseType>(std::forward<T>(value)));
}
else {
const CPPType &type = CPPType::get<StoredT>();
@@ -316,21 +326,21 @@ class GeoNodeExecParams {
* \note This will add an error message if the string socket is active and
* the input attribute does not exist.
*/
- GVArrayPtr get_input_attribute(const StringRef name,
- const GeometryComponent &component,
- const AttributeDomain domain,
- const CustomDataType type,
- const void *default_value) const;
+ GVArray get_input_attribute(const StringRef name,
+ const GeometryComponent &component,
+ const AttributeDomain domain,
+ const CustomDataType type,
+ const void *default_value) const;
template<typename T>
- GVArray_Typed<T> get_input_attribute(const StringRef name,
- const GeometryComponent &component,
- const AttributeDomain domain,
- const T &default_value) const
+ VArray<T> get_input_attribute(const StringRef name,
+ const GeometryComponent &component,
+ const AttributeDomain domain,
+ const T &default_value) const
{
const CustomDataType type = bke::cpp_type_to_custom_data_type(CPPType::get<T>());
- GVArrayPtr varray = this->get_input_attribute(name, component, domain, type, &default_value);
- return GVArray_Typed<T>(std::move(varray));
+ GVArray varray = this->get_input_attribute(name, component, domain, type, &default_value);
+ return varray.typed<T>();
}
/**
diff --git a/source/blender/nodes/NOD_geometry_nodes_eval_log.hh b/source/blender/nodes/NOD_geometry_nodes_eval_log.hh
index 2a118057a03..0fbc1803db6 100644
--- a/source/blender/nodes/NOD_geometry_nodes_eval_log.hh
+++ b/source/blender/nodes/NOD_geometry_nodes_eval_log.hh
@@ -41,6 +41,8 @@
#include "NOD_derived_node_tree.hh"
+#include <chrono>
+
struct SpaceNode;
struct SpaceSpreadsheet;
@@ -169,6 +171,11 @@ struct NodeWithWarning {
NodeWarning warning;
};
+struct NodeWithExecutionTime {
+ DNode node;
+ std::chrono::microseconds exec_time;
+};
+
/** The same value can be referenced by multiple sockets when they are linked. */
struct ValueOfSockets {
Span<DSocket> sockets;
@@ -189,6 +196,7 @@ class LocalGeoLogger {
std::unique_ptr<LinearAllocator<>> allocator_;
Vector<ValueOfSockets> values_;
Vector<NodeWithWarning> node_warnings_;
+ Vector<NodeWithExecutionTime> node_exec_times_;
friend ModifierLog;
@@ -201,6 +209,7 @@ class LocalGeoLogger {
void log_value_for_sockets(Span<DSocket> sockets, GPointer value);
void log_multi_value_socket(DSocket socket, Span<GPointer> values);
void log_node_warning(DNode node, NodeWarningType type, std::string message);
+ void log_execution_time(DNode node, std::chrono::microseconds exec_time);
};
/** The root logger class. */
@@ -274,12 +283,14 @@ class NodeLog {
Vector<SocketLog> input_logs_;
Vector<SocketLog> output_logs_;
Vector<NodeWarning, 0> warnings_;
+ std::chrono::microseconds exec_time_;
friend ModifierLog;
public:
const SocketLog *lookup_socket_log(eNodeSocketInOut in_out, int index) const;
const SocketLog *lookup_socket_log(const bNode &node, const bNodeSocket &socket) const;
+ void execution_time(std::chrono::microseconds exec_time);
Span<SocketLog> input_logs() const
{
@@ -296,6 +307,11 @@ class NodeLog {
return warnings_;
}
+ std::chrono::microseconds execution_time() const
+ {
+ return exec_time_;
+ }
+
Vector<const GeometryAttributeInfo *> lookup_available_attributes() const;
};
diff --git a/source/blender/nodes/NOD_node_declaration.hh b/source/blender/nodes/NOD_node_declaration.hh
index e9f2996bb30..9b99026d6a7 100644
--- a/source/blender/nodes/NOD_node_declaration.hh
+++ b/source/blender/nodes/NOD_node_declaration.hh
@@ -228,7 +228,6 @@ class NodeDeclaration {
friend NodeDeclarationBuilder;
public:
- void build(bNodeTree &ntree, bNode &node) const;
bool matches(const bNode &node) const;
Span<SocketDeclarationPtr> inputs() const;
diff --git a/source/blender/nodes/NOD_type_conversions.hh b/source/blender/nodes/NOD_type_conversions.hh
index ec4859f0657..c8b24fd1260 100644
--- a/source/blender/nodes/NOD_type_conversions.hh
+++ b/source/blender/nodes/NOD_type_conversions.hh
@@ -21,7 +21,6 @@
namespace blender::nodes {
using fn::CPPType;
-using fn::GVArray;
struct ConversionFunctions {
const fn::MultiFunction *multi_function;
@@ -73,9 +72,9 @@ class DataTypeConversions {
const void *from_value,
void *to_value) const;
- fn::GVArrayPtr try_convert(fn::GVArrayPtr varray, const CPPType &to_type) const;
+ fn::GVArray try_convert(fn::GVArray varray, const CPPType &to_type) const;
- fn::GVMutableArrayPtr try_convert(fn::GVMutableArrayPtr varray, const CPPType &to_type) const;
+ fn::GVMutableArray try_convert(fn::GVMutableArray varray, const CPPType &to_type) const;
};
const DataTypeConversions &get_implicit_type_conversions();
diff --git a/source/blender/nodes/composite/node_composite_util.cc b/source/blender/nodes/composite/node_composite_util.cc
index 86aaec61bc3..21269b92e65 100644
--- a/source/blender/nodes/composite/node_composite_util.cc
+++ b/source/blender/nodes/composite/node_composite_util.cc
@@ -52,5 +52,4 @@ void cmp_node_type_base(bNodeType *ntype, int type, const char *name, short ncla
ntype->poll = cmp_node_poll_default;
ntype->updatefunc = cmp_node_update_default;
ntype->insert_link = node_insert_link_default;
- ntype->update_internal_links = node_update_internal_links_default;
}
diff --git a/source/blender/nodes/composite/nodes/node_composite_common.cc b/source/blender/nodes/composite/nodes/node_composite_common.cc
index fecf6795ef7..6432a89ffa0 100644
--- a/source/blender/nodes/composite/nodes/node_composite_common.cc
+++ b/source/blender/nodes/composite/nodes/node_composite_common.cc
@@ -44,7 +44,6 @@ void register_node_type_cmp_group(void)
ntype.poll = cmp_node_poll_default;
ntype.poll_instance = node_group_poll_instance;
ntype.insert_link = node_insert_link_default;
- ntype.update_internal_links = node_update_internal_links_default;
ntype.rna_ext.srna = RNA_struct_find("CompositorNodeGroup");
BLI_assert(ntype.rna_ext.srna != nullptr);
RNA_struct_blender_type_set(ntype.rna_ext.srna, &ntype);
@@ -66,7 +65,4 @@ void register_node_type_cmp_custom_group(bNodeType *ntype)
if (ntype->insert_link == nullptr) {
ntype->insert_link = node_insert_link_default;
}
- if (ntype->update_internal_links == nullptr) {
- ntype->update_internal_links = node_update_internal_links_default;
- }
}
diff --git a/source/blender/nodes/composite/nodes/node_composite_composite.cc b/source/blender/nodes/composite/nodes/node_composite_composite.cc
index 4247e81e9b2..a1a49133a3a 100644
--- a/source/blender/nodes/composite/nodes/node_composite_composite.cc
+++ b/source/blender/nodes/composite/nodes/node_composite_composite.cc
@@ -43,8 +43,7 @@ void register_node_type_cmp_composite(void)
cmp_node_type_base(&ntype, CMP_NODE_COMPOSITE, "Composite", NODE_CLASS_OUTPUT, NODE_PREVIEW);
ntype.declare = blender::nodes::cmp_node_composite_declare;
- /* Do not allow muting for this node. */
- node_type_internal_links(&ntype, nullptr);
+ ntype.no_muting = true;
nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/composite/nodes/node_composite_image.cc b/source/blender/nodes/composite/nodes/node_composite_image.cc
index 79cb0bd0f8c..40d4d4563c9 100644
--- a/source/blender/nodes/composite/nodes/node_composite_image.cc
+++ b/source/blender/nodes/composite/nodes/node_composite_image.cc
@@ -372,7 +372,8 @@ static void cmp_node_image_verify_outputs(bNodeTree *ntree, bNode *node, bool rl
for (sock = (bNodeSocket *)node->outputs.first; sock; sock = sock_next, sock_index++) {
sock_next = sock->next;
if (BLI_linklist_index(available_sockets.list, sock) >= 0) {
- sock->flag &= ~(SOCK_UNAVAIL | SOCK_HIDDEN);
+ sock->flag &= ~SOCK_HIDDEN;
+ nodeSetSocketAvailability(ntree, sock, true);
}
else {
bNodeLink *link;
@@ -386,7 +387,7 @@ static void cmp_node_image_verify_outputs(bNodeTree *ntree, bNode *node, bool rl
nodeRemoveSocket(ntree, node, sock);
}
else {
- sock->flag |= SOCK_UNAVAIL;
+ nodeSetSocketAvailability(ntree, sock, false);
}
}
}
diff --git a/source/blender/nodes/composite/nodes/node_composite_scale.cc b/source/blender/nodes/composite/nodes/node_composite_scale.cc
index 3972fc0d949..284d16b9b0d 100644
--- a/source/blender/nodes/composite/nodes/node_composite_scale.cc
+++ b/source/blender/nodes/composite/nodes/node_composite_scale.cc
@@ -32,7 +32,7 @@ static bNodeSocketTemplate cmp_node_scale_in[] = {
{-1, ""}};
static bNodeSocketTemplate cmp_node_scale_out[] = {{SOCK_RGBA, N_("Image")}, {-1, ""}};
-static void node_composite_update_scale(bNodeTree *UNUSED(ntree), bNode *node)
+static void node_composite_update_scale(bNodeTree *ntree, bNode *node)
{
bNodeSocket *sock;
bool use_xy_scale = ELEM(node->custom1, CMP_SCALE_RELATIVE, CMP_SCALE_ABSOLUTE);
@@ -40,12 +40,7 @@ static void node_composite_update_scale(bNodeTree *UNUSED(ntree), bNode *node)
/* Only show X/Y scale factor inputs for modes using them! */
for (sock = (bNodeSocket *)node->inputs.first; sock; sock = sock->next) {
if (STR_ELEM(sock->name, "X", "Y")) {
- if (use_xy_scale) {
- sock->flag &= ~SOCK_UNAVAIL;
- }
- else {
- sock->flag |= SOCK_UNAVAIL;
- }
+ nodeSetSocketAvailability(ntree, sock, use_xy_scale);
}
}
}
diff --git a/source/blender/nodes/composite/nodes/node_composite_splitViewer.cc b/source/blender/nodes/composite/nodes/node_composite_splitViewer.cc
index 68c5ecdf48e..c0403a041db 100644
--- a/source/blender/nodes/composite/nodes/node_composite_splitViewer.cc
+++ b/source/blender/nodes/composite/nodes/node_composite_splitViewer.cc
@@ -53,8 +53,7 @@ void register_node_type_cmp_splitviewer(void)
node_type_init(&ntype, node_composit_init_splitviewer);
node_type_storage(&ntype, "ImageUser", node_free_standard_storage, node_copy_standard_storage);
- /* Do not allow muting for this node. */
- node_type_internal_links(&ntype, nullptr);
+ ntype.no_muting = true;
nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/composite/nodes/node_composite_viewer.cc b/source/blender/nodes/composite/nodes/node_composite_viewer.cc
index 969e2409898..90f9882099b 100644
--- a/source/blender/nodes/composite/nodes/node_composite_viewer.cc
+++ b/source/blender/nodes/composite/nodes/node_composite_viewer.cc
@@ -59,7 +59,7 @@ void register_node_type_cmp_viewer(void)
node_type_init(&ntype, node_composit_init_viewer);
node_type_storage(&ntype, "ImageUser", node_free_standard_storage, node_copy_standard_storage);
- node_type_internal_links(&ntype, nullptr);
+ ntype.no_muting = true;
nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/function/node_function_util.cc b/source/blender/nodes/function/node_function_util.cc
index 8ff8b416310..a1493d51a11 100644
--- a/source/blender/nodes/function/node_function_util.cc
+++ b/source/blender/nodes/function/node_function_util.cc
@@ -33,6 +33,5 @@ void fn_node_type_base(bNodeType *ntype, int type, const char *name, short nclas
{
node_type_base(ntype, type, name, nclass, flag);
ntype->poll = fn_node_poll_default;
- ntype->update_internal_links = node_update_internal_links_default;
ntype->insert_link = node_insert_link_default;
}
diff --git a/source/blender/nodes/function/nodes/node_fn_boolean_math.cc b/source/blender/nodes/function/nodes/node_fn_boolean_math.cc
index b44e8d54ff1..ed03cc0025d 100644
--- a/source/blender/nodes/function/nodes/node_fn_boolean_math.cc
+++ b/source/blender/nodes/function/nodes/node_fn_boolean_math.cc
@@ -39,12 +39,12 @@ static void fn_node_boolean_math_layout(uiLayout *layout, bContext *UNUSED(C), P
uiItemR(layout, ptr, "operation", 0, "", ICON_NONE);
}
-static void node_boolean_math_update(bNodeTree *UNUSED(ntree), bNode *node)
+static void node_boolean_math_update(bNodeTree *ntree, bNode *node)
{
bNodeSocket *sockB = (bNodeSocket *)BLI_findlink(&node->inputs, 1);
- nodeSetSocketAvailability(sockB,
- ELEM(node->custom1, NODE_BOOLEAN_MATH_AND, NODE_BOOLEAN_MATH_OR));
+ nodeSetSocketAvailability(
+ ntree, sockB, ELEM(node->custom1, NODE_BOOLEAN_MATH_AND, NODE_BOOLEAN_MATH_OR));
}
static void node_boolean_math_label(bNodeTree *UNUSED(ntree), bNode *node, char *label, int maxlen)
diff --git a/source/blender/nodes/function/nodes/node_fn_float_compare.cc b/source/blender/nodes/function/nodes/node_fn_float_compare.cc
index 2e1f2aaeeef..b31611a1df2 100644
--- a/source/blender/nodes/function/nodes/node_fn_float_compare.cc
+++ b/source/blender/nodes/function/nodes/node_fn_float_compare.cc
@@ -42,12 +42,14 @@ static void geo_node_float_compare_layout(uiLayout *layout, bContext *UNUSED(C),
uiItemR(layout, ptr, "operation", 0, "", ICON_NONE);
}
-static void node_float_compare_update(bNodeTree *UNUSED(ntree), bNode *node)
+static void node_float_compare_update(bNodeTree *ntree, bNode *node)
{
bNodeSocket *sockEpsilon = (bNodeSocket *)BLI_findlink(&node->inputs, 2);
nodeSetSocketAvailability(
- sockEpsilon, ELEM(node->custom1, NODE_FLOAT_COMPARE_EQUAL, NODE_FLOAT_COMPARE_NOT_EQUAL));
+ ntree,
+ sockEpsilon,
+ ELEM(node->custom1, NODE_FLOAT_COMPARE_EQUAL, NODE_FLOAT_COMPARE_NOT_EQUAL));
}
static void node_float_compare_label(bNodeTree *UNUSED(ntree),
diff --git a/source/blender/nodes/function/nodes/node_fn_random_value.cc b/source/blender/nodes/function/nodes/node_fn_random_value.cc
index d48b9f3461a..9720a39b740 100644
--- a/source/blender/nodes/function/nodes/node_fn_random_value.cc
+++ b/source/blender/nodes/function/nodes/node_fn_random_value.cc
@@ -63,7 +63,7 @@ static void fn_node_random_value_init(bNodeTree *UNUSED(tree), bNode *node)
node->storage = data;
}
-static void fn_node_random_value_update(bNodeTree *UNUSED(ntree), bNode *node)
+static void fn_node_random_value_update(bNodeTree *ntree, bNode *node)
{
const NodeRandomValue &storage = *(const NodeRandomValue *)node->storage;
const CustomDataType data_type = static_cast<CustomDataType>(storage.data_type);
@@ -81,18 +81,18 @@ static void fn_node_random_value_update(bNodeTree *UNUSED(ntree), bNode *node)
bNodeSocket *sock_out_int = sock_out_float->next;
bNodeSocket *sock_out_bool = sock_out_int->next;
- nodeSetSocketAvailability(sock_min_vector, data_type == CD_PROP_FLOAT3);
- nodeSetSocketAvailability(sock_max_vector, data_type == CD_PROP_FLOAT3);
- nodeSetSocketAvailability(sock_min_float, data_type == CD_PROP_FLOAT);
- nodeSetSocketAvailability(sock_max_float, data_type == CD_PROP_FLOAT);
- nodeSetSocketAvailability(sock_min_int, data_type == CD_PROP_INT32);
- nodeSetSocketAvailability(sock_max_int, data_type == CD_PROP_INT32);
- nodeSetSocketAvailability(sock_probability, data_type == CD_PROP_BOOL);
-
- nodeSetSocketAvailability(sock_out_vector, data_type == CD_PROP_FLOAT3);
- nodeSetSocketAvailability(sock_out_float, data_type == CD_PROP_FLOAT);
- nodeSetSocketAvailability(sock_out_int, data_type == CD_PROP_INT32);
- nodeSetSocketAvailability(sock_out_bool, data_type == CD_PROP_BOOL);
+ nodeSetSocketAvailability(ntree, sock_min_vector, data_type == CD_PROP_FLOAT3);
+ nodeSetSocketAvailability(ntree, sock_max_vector, data_type == CD_PROP_FLOAT3);
+ nodeSetSocketAvailability(ntree, sock_min_float, data_type == CD_PROP_FLOAT);
+ nodeSetSocketAvailability(ntree, sock_max_float, data_type == CD_PROP_FLOAT);
+ nodeSetSocketAvailability(ntree, sock_min_int, data_type == CD_PROP_INT32);
+ nodeSetSocketAvailability(ntree, sock_max_int, data_type == CD_PROP_INT32);
+ nodeSetSocketAvailability(ntree, sock_probability, data_type == CD_PROP_BOOL);
+
+ nodeSetSocketAvailability(ntree, sock_out_vector, data_type == CD_PROP_FLOAT3);
+ nodeSetSocketAvailability(ntree, sock_out_float, data_type == CD_PROP_FLOAT);
+ nodeSetSocketAvailability(ntree, sock_out_int, data_type == CD_PROP_INT32);
+ nodeSetSocketAvailability(ntree, sock_out_bool, data_type == CD_PROP_BOOL);
}
class RandomVectorFunction : public fn::MultiFunction {
diff --git a/source/blender/nodes/function/nodes/node_fn_rotate_euler.cc b/source/blender/nodes/function/nodes/node_fn_rotate_euler.cc
index fc4c3d8221f..7dbc11fb161 100644
--- a/source/blender/nodes/function/nodes/node_fn_rotate_euler.cc
+++ b/source/blender/nodes/function/nodes/node_fn_rotate_euler.cc
@@ -36,18 +36,18 @@ static void fn_node_rotate_euler_declare(NodeDeclarationBuilder &b)
b.add_output<decl::Vector>(N_("Rotation"));
};
-static void fn_node_rotate_euler_update(bNodeTree *UNUSED(ntree), bNode *node)
+static void fn_node_rotate_euler_update(bNodeTree *ntree, bNode *node)
{
bNodeSocket *rotate_by_socket = static_cast<bNodeSocket *>(BLI_findlink(&node->inputs, 1));
bNodeSocket *axis_socket = static_cast<bNodeSocket *>(BLI_findlink(&node->inputs, 2));
bNodeSocket *angle_socket = static_cast<bNodeSocket *>(BLI_findlink(&node->inputs, 3));
- nodeSetSocketAvailability(rotate_by_socket,
- ELEM(node->custom1, FN_NODE_ROTATE_EULER_TYPE_EULER));
- nodeSetSocketAvailability(axis_socket,
- ELEM(node->custom1, FN_NODE_ROTATE_EULER_TYPE_AXIS_ANGLE));
- nodeSetSocketAvailability(angle_socket,
- ELEM(node->custom1, FN_NODE_ROTATE_EULER_TYPE_AXIS_ANGLE));
+ nodeSetSocketAvailability(
+ ntree, rotate_by_socket, ELEM(node->custom1, FN_NODE_ROTATE_EULER_TYPE_EULER));
+ nodeSetSocketAvailability(
+ ntree, axis_socket, ELEM(node->custom1, FN_NODE_ROTATE_EULER_TYPE_AXIS_ANGLE));
+ nodeSetSocketAvailability(
+ ntree, angle_socket, ELEM(node->custom1, FN_NODE_ROTATE_EULER_TYPE_AXIS_ANGLE));
}
static void fn_node_rotate_euler_layout(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
diff --git a/source/blender/nodes/geometry/CMakeLists.txt b/source/blender/nodes/geometry/CMakeLists.txt
new file mode 100644
index 00000000000..61b5bbf6e7e
--- /dev/null
+++ b/source/blender/nodes/geometry/CMakeLists.txt
@@ -0,0 +1,267 @@
+# ***** BEGIN GPL LICENSE BLOCK *****
+#
+# 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.
+#
+# ***** END GPL LICENSE BLOCK *****
+
+set(INC
+ .
+ ../
+ ../intern
+ ../../editors/include
+ ../../blenkernel
+ ../../blenlib
+ ../../blentranslation
+ ../../bmesh
+ ../../depsgraph
+ ../../functions
+ ../../geometry
+ ../../gpu
+ ../../imbuf
+ ../../makesdna
+ ../../makesrna
+ ../../render
+ ../../windowmanager
+ ../../../../intern/guardedalloc
+)
+
+
+set(SRC
+ nodes/legacy/node_geo_legacy_align_rotation_to_vector.cc
+ nodes/legacy/node_geo_legacy_attribute_clamp.cc
+ nodes/legacy/node_geo_legacy_attribute_color_ramp.cc
+ nodes/legacy/node_geo_legacy_attribute_combine_xyz.cc
+ nodes/legacy/node_geo_legacy_attribute_compare.cc
+ nodes/legacy/node_geo_legacy_attribute_convert.cc
+ nodes/legacy/node_geo_legacy_attribute_curve_map.cc
+ nodes/legacy/node_geo_legacy_attribute_fill.cc
+ nodes/legacy/node_geo_legacy_attribute_map_range.cc
+ nodes/legacy/node_geo_legacy_attribute_math.cc
+ nodes/legacy/node_geo_legacy_attribute_mix.cc
+ nodes/legacy/node_geo_legacy_attribute_proximity.cc
+ nodes/legacy/node_geo_legacy_attribute_randomize.cc
+ nodes/legacy/node_geo_legacy_attribute_sample_texture.cc
+ nodes/legacy/node_geo_legacy_attribute_separate_xyz.cc
+ nodes/legacy/node_geo_legacy_attribute_transfer.cc
+ nodes/legacy/node_geo_legacy_attribute_vector_math.cc
+ nodes/legacy/node_geo_legacy_attribute_vector_rotate.cc
+ nodes/legacy/node_geo_legacy_curve_endpoints.cc
+ nodes/legacy/node_geo_legacy_curve_reverse.cc
+ nodes/legacy/node_geo_legacy_curve_select_by_handle_type.cc
+ nodes/legacy/node_geo_legacy_curve_set_handles.cc
+ nodes/legacy/node_geo_legacy_curve_spline_type.cc
+ nodes/legacy/node_geo_legacy_curve_subdivide.cc
+ nodes/legacy/node_geo_legacy_curve_to_points.cc
+ nodes/legacy/node_geo_legacy_delete_geometry.cc
+ nodes/legacy/node_geo_legacy_edge_split.cc
+ nodes/legacy/node_geo_legacy_material_assign.cc
+ nodes/legacy/node_geo_legacy_mesh_to_curve.cc
+ nodes/legacy/node_geo_legacy_point_distribute.cc
+ nodes/legacy/node_geo_legacy_point_instance.cc
+ nodes/legacy/node_geo_legacy_point_rotate.cc
+ nodes/legacy/node_geo_legacy_point_scale.cc
+ nodes/legacy/node_geo_legacy_point_separate.cc
+ nodes/legacy/node_geo_legacy_point_translate.cc
+ nodes/legacy/node_geo_legacy_points_to_volume.cc
+ nodes/legacy/node_geo_legacy_raycast.cc
+ nodes/legacy/node_geo_legacy_select_by_material.cc
+ nodes/legacy/node_geo_legacy_subdivision_surface.cc
+ nodes/legacy/node_geo_legacy_volume_to_mesh.cc
+
+ nodes/node_geo_attribute_capture.cc
+ nodes/node_geo_attribute_remove.cc
+ nodes/node_geo_attribute_statistic.cc
+ nodes/node_geo_boolean.cc
+ nodes/node_geo_bounding_box.cc
+ nodes/node_geo_collection_info.cc
+ nodes/node_geo_common.cc
+ nodes/node_geo_convex_hull.cc
+ nodes/node_geo_curve_endpoint_selection.cc
+ nodes/node_geo_curve_fill.cc
+ nodes/node_geo_curve_fillet.cc
+ nodes/node_geo_curve_handle_type_selection.cc
+ nodes/node_geo_curve_length.cc
+ nodes/node_geo_curve_parameter.cc
+ nodes/node_geo_curve_primitive_bezier_segment.cc
+ nodes/node_geo_curve_primitive_circle.cc
+ nodes/node_geo_curve_primitive_line.cc
+ nodes/node_geo_curve_primitive_quadratic_bezier.cc
+ nodes/node_geo_curve_primitive_quadrilateral.cc
+ nodes/node_geo_curve_primitive_spiral.cc
+ nodes/node_geo_curve_primitive_star.cc
+ nodes/node_geo_curve_resample.cc
+ nodes/node_geo_curve_reverse.cc
+ nodes/node_geo_curve_sample.cc
+ nodes/node_geo_curve_set_handles.cc
+ nodes/node_geo_curve_spline_type.cc
+ nodes/node_geo_curve_subdivide.cc
+ nodes/node_geo_curve_to_mesh.cc
+ nodes/node_geo_curve_to_points.cc
+ nodes/node_geo_curve_trim.cc
+ nodes/node_geo_delete_geometry.cc
+ nodes/node_geo_distribute_points_on_faces.cc
+ nodes/node_geo_edge_split.cc
+ nodes/node_geo_image_texture.cc
+ nodes/node_geo_input_curve_handles.cc
+ nodes/node_geo_input_curve_tilt.cc
+ nodes/node_geo_input_id.cc
+ nodes/node_geo_input_index.cc
+ nodes/node_geo_input_material_index.cc
+ nodes/node_geo_input_material.cc
+ nodes/node_geo_input_normal.cc
+ nodes/node_geo_input_position.cc
+ nodes/node_geo_input_radius.cc
+ nodes/node_geo_input_shade_smooth.cc
+ nodes/node_geo_input_spline_cyclic.cc
+ nodes/node_geo_input_spline_length.cc
+ nodes/node_geo_input_spline_resolution.cc
+ nodes/node_geo_input_tangent.cc
+ nodes/node_geo_instance_on_points.cc
+ nodes/node_geo_instances_to_points.cc
+ nodes/node_geo_is_viewport.cc
+ nodes/node_geo_join_geometry.cc
+ nodes/node_geo_material_replace.cc
+ nodes/node_geo_material_selection.cc
+ nodes/node_geo_mesh_primitive_circle.cc
+ nodes/node_geo_mesh_primitive_cone.cc
+ nodes/node_geo_mesh_primitive_cube.cc
+ nodes/node_geo_mesh_primitive_cylinder.cc
+ nodes/node_geo_mesh_primitive_grid.cc
+ nodes/node_geo_mesh_primitive_ico_sphere.cc
+ nodes/node_geo_mesh_primitive_line.cc
+ nodes/node_geo_mesh_primitive_uv_sphere.cc
+ nodes/node_geo_mesh_subdivide.cc
+ nodes/node_geo_mesh_to_curve.cc
+ nodes/node_geo_mesh_to_points.cc
+ nodes/node_geo_object_info.cc
+ nodes/node_geo_points_to_vertices.cc
+ nodes/node_geo_points_to_volume.cc
+ nodes/node_geo_proximity.cc
+ nodes/node_geo_raycast.cc
+ nodes/node_geo_realize_instances.cc
+ nodes/node_geo_rotate_instances.cc
+ nodes/node_geo_scale_instances.cc
+ nodes/node_geo_separate_components.cc
+ nodes/node_geo_separate_geometry.cc
+ nodes/node_geo_set_curve_handles.cc
+ nodes/node_geo_set_curve_radius.cc
+ nodes/node_geo_set_curve_tilt.cc
+ nodes/node_geo_set_id.cc
+ nodes/node_geo_set_material_index.cc
+ nodes/node_geo_set_material.cc
+ nodes/node_geo_set_point_radius.cc
+ nodes/node_geo_set_position.cc
+ nodes/node_geo_set_shade_smooth.cc
+ nodes/node_geo_set_spline_cyclic.cc
+ nodes/node_geo_set_spline_resolution.cc
+ nodes/node_geo_string_join.cc
+ nodes/node_geo_string_to_curves.cc
+ nodes/node_geo_subdivision_surface.cc
+ nodes/node_geo_switch.cc
+ nodes/node_geo_transfer_attribute.cc
+ nodes/node_geo_transform.cc
+ nodes/node_geo_translate_instances.cc
+ nodes/node_geo_triangulate.cc
+ nodes/node_geo_viewer.cc
+ nodes/node_geo_volume_to_mesh.cc
+
+ node_geometry_exec.cc
+ node_geometry_tree.cc
+ node_geometry_util.cc
+
+ node_geometry_util.hh
+)
+
+set(LIB
+ bf_bmesh
+ bf_functions
+ bf_geometry
+)
+
+if(WITH_BULLET)
+ list(APPEND INC_SYS
+ ${BULLET_INCLUDE_DIRS}
+ "../../../../intern/rigidbody/"
+ )
+ if(NOT WITH_SYSTEM_BULLET)
+ list(APPEND LIB
+ extern_bullet
+ )
+ endif()
+
+ list(APPEND LIB
+ ${BULLET_LIBRARIES}
+ )
+ add_definitions(-DWITH_BULLET)
+endif()
+
+if(WITH_PYTHON)
+ list(APPEND INC
+ ../../python
+ )
+ list(APPEND INC_SYS
+ ${PYTHON_INCLUDE_DIRS}
+ )
+ list(APPEND LIB
+ ${PYTHON_LINKFLAGS}
+ ${PYTHON_LIBRARIES}
+ )
+ add_definitions(-DWITH_PYTHON)
+endif()
+
+if(WITH_INTERNATIONAL)
+ add_definitions(-DWITH_INTERNATIONAL)
+endif()
+
+if(WITH_TBB)
+ list(APPEND INC_SYS
+ ${TBB_INCLUDE_DIRS}
+ )
+ add_definitions(-DWITH_TBB)
+ if(WIN32)
+ # TBB includes Windows.h which will define min/max macros
+ # that will collide with the stl versions.
+ add_definitions(-DNOMINMAX)
+ endif()
+endif()
+
+if(WITH_IMAGE_OPENEXR)
+ add_definitions(-DWITH_OPENEXR)
+endif()
+
+if(WITH_OPENSUBDIV)
+ add_definitions(-DWITH_OPENSUBDIV)
+endif()
+
+if(WITH_GMP)
+ add_definitions(-DWITH_GMP)
+
+ list(APPEND INC_SYS
+ ${GMP_INCLUDE_DIRS}
+ )
+
+ list(APPEND LIB
+ ${GMP_LIBRARIES}
+ )
+endif()
+
+if(WITH_OPENVDB)
+ list(APPEND INC_SYS
+ ${OPENVDB_INCLUDE_DIRS}
+ )
+ add_definitions(-DWITH_OPENVDB ${OPENVDB_DEFINITIONS})
+endif()
+
+blender_add_lib(bf_nodes_geometry "${SRC}" "${INC}" "${INC_SYS}" "${LIB}")
diff --git a/source/blender/nodes/geometry/node_geometry_util.cc b/source/blender/nodes/geometry/node_geometry_util.cc
index 46e9d36c09c..5c1d507041c 100644
--- a/source/blender/nodes/geometry/node_geometry_util.cc
+++ b/source/blender/nodes/geometry/node_geometry_util.cc
@@ -35,7 +35,8 @@ using bke::GeometryInstanceGroup;
* \param mode: Controls which socket of the group to make available.
* \param name_is_available: If false, make all sockets with this name unavailable.
*/
-void update_attribute_input_socket_availabilities(bNode &node,
+void update_attribute_input_socket_availabilities(bNodeTree &ntree,
+ bNode &node,
const StringRef name,
const GeometryNodeAttributeInputMode mode,
const bool name_is_available)
@@ -50,7 +51,7 @@ void update_attribute_input_socket_availabilities(bNode &node,
(socket->type == SOCK_INT && mode_ == GEO_NODE_ATTRIBUTE_INPUT_INTEGER) ||
(socket->type == SOCK_VECTOR && mode_ == GEO_NODE_ATTRIBUTE_INPUT_VECTOR) ||
(socket->type == SOCK_RGBA && mode_ == GEO_NODE_ATTRIBUTE_INPUT_COLOR));
- nodeSetSocketAvailability(socket, socket_is_available);
+ nodeSetSocketAvailability(&ntree, socket, socket_is_available);
}
}
}
@@ -72,6 +73,5 @@ void geo_node_type_base(bNodeType *ntype, int type, const char *name, short ncla
{
node_type_base(ntype, type, name, nclass, flag);
ntype->poll = geo_node_poll_default;
- ntype->update_internal_links = node_update_internal_links_default;
ntype->insert_link = node_insert_link_default;
}
diff --git a/source/blender/nodes/geometry/node_geometry_util.hh b/source/blender/nodes/geometry/node_geometry_util.hh
index 167765fa131..79fe2ffc42b 100644
--- a/source/blender/nodes/geometry/node_geometry_util.hh
+++ b/source/blender/nodes/geometry/node_geometry_util.hh
@@ -43,7 +43,8 @@ bool geo_node_poll_default(struct bNodeType *ntype,
const char **r_disabled_hint);
namespace blender::nodes {
-void update_attribute_input_socket_availabilities(bNode &node,
+void update_attribute_input_socket_availabilities(bNodeTree &ntree,
+ bNode &node,
const StringRef name,
const GeometryNodeAttributeInputMode mode,
const bool name_is_available = true);
@@ -67,13 +68,20 @@ Mesh *create_grid_mesh(const int verts_x,
const float size_x,
const float size_y);
+struct ConeAttributeOutputs {
+ StrongAnonymousAttributeID top_id;
+ StrongAnonymousAttributeID bottom_id;
+ StrongAnonymousAttributeID side_id;
+};
+
Mesh *create_cylinder_or_cone_mesh(const float radius_top,
const float radius_bottom,
const float depth,
const int circle_segments,
const int side_segments,
const int fill_segments,
- const GeometryNodeMeshCircleFillType fill_type);
+ const GeometryNodeMeshCircleFillType fill_type,
+ ConeAttributeOutputs &attribute_outputs);
Mesh *create_cuboid_mesh(float3 size, int verts_x, int verts_y, int verts_z);
diff --git a/source/blender/nodes/geometry/nodes/legacy/node_geo_align_rotation_to_vector.cc b/source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_align_rotation_to_vector.cc
index b92d4704d63..5a5b0dbee9a 100644
--- a/source/blender/nodes/geometry/nodes/legacy/node_geo_align_rotation_to_vector.cc
+++ b/source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_align_rotation_to_vector.cc
@@ -22,9 +22,9 @@
#include "node_geometry_util.hh"
-namespace blender::nodes {
+namespace blender::nodes::node_geo_legacy_align_rotation_to_vector_cc {
-static void geo_node_align_rotation_to_vector_declare(NodeDeclarationBuilder &b)
+static void node_declare(NodeDeclarationBuilder &b)
{
b.add_input<decl::Geometry>(N_("Geometry"));
b.add_input<decl::String>(N_("Factor"));
@@ -40,9 +40,7 @@ static void geo_node_align_rotation_to_vector_declare(NodeDeclarationBuilder &b)
b.add_output<decl::Geometry>(N_("Geometry"));
}
-static void geo_node_align_rotation_to_vector_layout(uiLayout *layout,
- bContext *UNUSED(C),
- PointerRNA *ptr)
+static void node_layout(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
{
uiItemR(layout, ptr, "axis", UI_ITEM_R_EXPAND, nullptr, ICON_NONE);
uiLayoutSetPropSep(layout, true);
@@ -53,7 +51,7 @@ static void geo_node_align_rotation_to_vector_layout(uiLayout *layout,
uiItemR(col, ptr, "input_type_vector", 0, IFACE_("Vector"), ICON_NONE);
}
-static void geo_node_align_rotation_to_vector_init(bNodeTree *UNUSED(ntree), bNode *node)
+static void node_init(bNodeTree *UNUSED(ntree), bNode *node)
{
NodeGeometryAlignRotationToVector *node_storage = (NodeGeometryAlignRotationToVector *)
MEM_callocN(sizeof(NodeGeometryAlignRotationToVector), __func__);
@@ -65,14 +63,14 @@ static void geo_node_align_rotation_to_vector_init(bNodeTree *UNUSED(ntree), bNo
node->storage = node_storage;
}
-static void geo_node_align_rotation_to_vector_update(bNodeTree *UNUSED(ntree), bNode *node)
+static void node_update(bNodeTree *ntree, bNode *node)
{
NodeGeometryAlignRotationToVector *node_storage = (NodeGeometryAlignRotationToVector *)
node->storage;
update_attribute_input_socket_availabilities(
- *node, "Factor", (GeometryNodeAttributeInputMode)node_storage->input_type_factor);
+ *ntree, *node, "Factor", (GeometryNodeAttributeInputMode)node_storage->input_type_factor);
update_attribute_input_socket_availabilities(
- *node, "Vector", (GeometryNodeAttributeInputMode)node_storage->input_type_vector);
+ *ntree, *node, "Vector", (GeometryNodeAttributeInputMode)node_storage->input_type_vector);
}
static void align_rotations_auto_pivot(const VArray<float3> &vectors,
@@ -179,9 +177,9 @@ static void align_rotations_on_component(GeometryComponent &component,
return;
}
- GVArray_Typed<float> factors = params.get_input_attribute<float>(
+ VArray<float> factors = params.get_input_attribute<float>(
"Factor", component, ATTR_DOMAIN_POINT, 1.0f);
- GVArray_Typed<float3> vectors = params.get_input_attribute<float3>(
+ VArray<float3> vectors = params.get_input_attribute<float3>(
"Vector", component, ATTR_DOMAIN_POINT, {0, 0, 1});
float3 local_main_axis{0, 0, 0};
@@ -199,7 +197,7 @@ static void align_rotations_on_component(GeometryComponent &component,
rotations.save();
}
-static void geo_node_align_rotation_to_vector_exec(GeoNodeExecParams params)
+static void node_geo_exec(GeoNodeExecParams params)
{
GeometrySet geometry_set = params.extract_input<GeometrySet>("Geometry");
@@ -219,10 +217,12 @@ static void geo_node_align_rotation_to_vector_exec(GeoNodeExecParams params)
params.set_output("Geometry", geometry_set);
}
-} // namespace blender::nodes
+} // namespace blender::nodes::node_geo_legacy_align_rotation_to_vector_cc
void register_node_type_geo_align_rotation_to_vector()
{
+ namespace file_ns = blender::nodes::node_geo_legacy_align_rotation_to_vector_cc;
+
static bNodeType ntype;
geo_node_type_base(&ntype,
@@ -230,14 +230,14 @@ void register_node_type_geo_align_rotation_to_vector()
"Align Rotation to Vector",
NODE_CLASS_GEOMETRY,
0);
- node_type_init(&ntype, blender::nodes::geo_node_align_rotation_to_vector_init);
- node_type_update(&ntype, blender::nodes::geo_node_align_rotation_to_vector_update);
+ node_type_init(&ntype, file_ns::node_init);
+ node_type_update(&ntype, file_ns::node_update);
node_type_storage(&ntype,
"NodeGeometryAlignRotationToVector",
node_free_standard_storage,
node_copy_standard_storage);
- ntype.declare = blender::nodes::geo_node_align_rotation_to_vector_declare;
- ntype.geometry_node_execute = blender::nodes::geo_node_align_rotation_to_vector_exec;
- ntype.draw_buttons = blender::nodes::geo_node_align_rotation_to_vector_layout;
+ ntype.declare = file_ns::node_declare;
+ ntype.geometry_node_execute = file_ns::node_geo_exec;
+ ntype.draw_buttons = file_ns::node_layout;
nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/geometry/nodes/legacy/node_geo_attribute_clamp.cc b/source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_attribute_clamp.cc
index 91ff114a480..40af5b7ec82 100644
--- a/source/blender/nodes/geometry/nodes/legacy/node_geo_attribute_clamp.cc
+++ b/source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_attribute_clamp.cc
@@ -20,9 +20,9 @@
#include "node_geometry_util.hh"
-namespace blender::nodes {
+namespace blender::nodes::node_geo_legacy_attribute_clamp_cc {
-static void geo_node_attribute_clamp_declare(NodeDeclarationBuilder &b)
+static void node_declare(NodeDeclarationBuilder &b)
{
b.add_input<decl::Geometry>(N_("Geometry"));
b.add_input<decl::String>(N_("Attribute"));
@@ -38,13 +38,13 @@ static void geo_node_attribute_clamp_declare(NodeDeclarationBuilder &b)
b.add_output<decl::Geometry>(N_("Geometry"));
}
-static void geo_node_attribute_clamp_layout(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
+static void node_layout(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
{
uiItemR(layout, ptr, "data_type", 0, "", ICON_NONE);
uiItemR(layout, ptr, "operation", 0, "", ICON_NONE);
}
-static void geo_node_attribute_clamp_init(bNodeTree *UNUSED(tree), bNode *node)
+static void node_init(bNodeTree *UNUSED(tree), bNode *node)
{
NodeAttributeClamp *data = (NodeAttributeClamp *)MEM_callocN(sizeof(NodeAttributeClamp),
__func__);
@@ -53,7 +53,7 @@ static void geo_node_attribute_clamp_init(bNodeTree *UNUSED(tree), bNode *node)
node->storage = data;
}
-static void geo_node_attribute_clamp_update(bNodeTree *UNUSED(ntree), bNode *node)
+static void node_update(bNodeTree *ntree, bNode *node)
{
bNodeSocket *sock_min_vector = (bNodeSocket *)BLI_findlink(&node->inputs, 3);
bNodeSocket *sock_max_vector = sock_min_vector->next;
@@ -66,14 +66,14 @@ static void geo_node_attribute_clamp_update(bNodeTree *UNUSED(ntree), bNode *nod
const NodeAttributeClamp &storage = *(const NodeAttributeClamp *)node->storage;
const CustomDataType data_type = static_cast<CustomDataType>(storage.data_type);
- nodeSetSocketAvailability(sock_min_vector, data_type == CD_PROP_FLOAT3);
- nodeSetSocketAvailability(sock_max_vector, data_type == CD_PROP_FLOAT3);
- nodeSetSocketAvailability(sock_min_float, data_type == CD_PROP_FLOAT);
- nodeSetSocketAvailability(sock_max_float, data_type == CD_PROP_FLOAT);
- nodeSetSocketAvailability(sock_min_int, data_type == CD_PROP_INT32);
- nodeSetSocketAvailability(sock_max_int, data_type == CD_PROP_INT32);
- nodeSetSocketAvailability(sock_min_color, data_type == CD_PROP_COLOR);
- nodeSetSocketAvailability(sock_max_color, data_type == CD_PROP_COLOR);
+ nodeSetSocketAvailability(ntree, sock_min_vector, data_type == CD_PROP_FLOAT3);
+ nodeSetSocketAvailability(ntree, sock_max_vector, data_type == CD_PROP_FLOAT3);
+ nodeSetSocketAvailability(ntree, sock_min_float, data_type == CD_PROP_FLOAT);
+ nodeSetSocketAvailability(ntree, sock_max_float, data_type == CD_PROP_FLOAT);
+ nodeSetSocketAvailability(ntree, sock_min_int, data_type == CD_PROP_INT32);
+ nodeSetSocketAvailability(ntree, sock_max_int, data_type == CD_PROP_INT32);
+ nodeSetSocketAvailability(ntree, sock_min_color, data_type == CD_PROP_COLOR);
+ nodeSetSocketAvailability(ntree, sock_max_color, data_type == CD_PROP_COLOR);
}
template<typename T> T clamp_value(const T val, const T min, const T max);
@@ -156,7 +156,7 @@ static void clamp_attribute(GeometryComponent &component, const GeoNodeExecParam
const AttributeDomain domain = get_result_domain(component, attribute_name, result_name);
const int operation = static_cast<int>(storage.operation);
- GVArrayPtr attribute_input = component.attribute_try_get_for_read(
+ GVArray attribute_input = component.attribute_try_get_for_read(
attribute_name, domain, data_type);
OutputAttribute attribute_result = component.attribute_try_get_for_output_only(
@@ -185,7 +185,7 @@ static void clamp_attribute(GeometryComponent &component, const GeoNodeExecParam
}
}
MutableSpan<float3> results = attribute_result.as_span<float3>();
- clamp_attribute<float3>(attribute_input->typed<float3>(), results, min, max);
+ clamp_attribute<float3>(attribute_input.typed<float3>(), results, min, max);
break;
}
case CD_PROP_FLOAT: {
@@ -193,10 +193,10 @@ static void clamp_attribute(GeometryComponent &component, const GeoNodeExecParam
const float max = params.get_input<float>("Max_001");
MutableSpan<float> results = attribute_result.as_span<float>();
if (operation == NODE_CLAMP_RANGE && min > max) {
- clamp_attribute<float>(attribute_input->typed<float>(), results, max, min);
+ clamp_attribute<float>(attribute_input.typed<float>(), results, max, min);
}
else {
- clamp_attribute<float>(attribute_input->typed<float>(), results, min, max);
+ clamp_attribute<float>(attribute_input.typed<float>(), results, min, max);
}
break;
}
@@ -205,10 +205,10 @@ static void clamp_attribute(GeometryComponent &component, const GeoNodeExecParam
const int max = params.get_input<int>("Max_002");
MutableSpan<int> results = attribute_result.as_span<int>();
if (operation == NODE_CLAMP_RANGE && min > max) {
- clamp_attribute<int>(attribute_input->typed<int>(), results, max, min);
+ clamp_attribute<int>(attribute_input.typed<int>(), results, max, min);
}
else {
- clamp_attribute<int>(attribute_input->typed<int>(), results, min, max);
+ clamp_attribute<int>(attribute_input.typed<int>(), results, min, max);
}
break;
}
@@ -231,7 +231,7 @@ static void clamp_attribute(GeometryComponent &component, const GeoNodeExecParam
}
MutableSpan<ColorGeometry4f> results = attribute_result.as_span<ColorGeometry4f>();
clamp_attribute<ColorGeometry4f>(
- attribute_input->typed<ColorGeometry4f>(), results, min, max);
+ attribute_input.typed<ColorGeometry4f>(), results, min, max);
break;
}
default: {
@@ -243,7 +243,7 @@ static void clamp_attribute(GeometryComponent &component, const GeoNodeExecParam
attribute_result.save();
}
-static void geo_node_attribute_clamp_exec(GeoNodeExecParams params)
+static void node_geo_exec(GeoNodeExecParams params)
{
GeometrySet geometry_set = params.extract_input<GeometrySet>("Geometry");
@@ -262,19 +262,21 @@ static void geo_node_attribute_clamp_exec(GeoNodeExecParams params)
params.set_output("Geometry", geometry_set);
}
-} // namespace blender::nodes
+} // namespace blender::nodes::node_geo_legacy_attribute_clamp_cc
void register_node_type_geo_attribute_clamp()
{
+ namespace file_ns = blender::nodes::node_geo_legacy_attribute_clamp_cc;
+
static bNodeType ntype;
geo_node_type_base(
&ntype, GEO_NODE_LEGACY_ATTRIBUTE_CLAMP, "Attribute Clamp", NODE_CLASS_ATTRIBUTE, 0);
- node_type_init(&ntype, blender::nodes::geo_node_attribute_clamp_init);
- node_type_update(&ntype, blender::nodes::geo_node_attribute_clamp_update);
- ntype.declare = blender::nodes::geo_node_attribute_clamp_declare;
- ntype.geometry_node_execute = blender::nodes::geo_node_attribute_clamp_exec;
- ntype.draw_buttons = blender::nodes::geo_node_attribute_clamp_layout;
+ node_type_init(&ntype, file_ns::node_init);
+ node_type_update(&ntype, file_ns::node_update);
+ ntype.declare = file_ns::node_declare;
+ ntype.geometry_node_execute = file_ns::node_geo_exec;
+ ntype.draw_buttons = file_ns::node_layout;
node_type_storage(
&ntype, "NodeAttributeClamp", node_free_standard_storage, node_copy_standard_storage);
nodeRegisterType(&ntype);
diff --git a/source/blender/nodes/geometry/nodes/legacy/node_geo_attribute_color_ramp.cc b/source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_attribute_color_ramp.cc
index ab4b6aad545..66790acb712 100644
--- a/source/blender/nodes/geometry/nodes/legacy/node_geo_attribute_color_ramp.cc
+++ b/source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_attribute_color_ramp.cc
@@ -23,9 +23,9 @@
#include "node_geometry_util.hh"
-namespace blender::nodes {
+namespace blender::nodes::node_geo_legacy_attributes_color_ramp_cc {
-static void geo_node_attribute_color_ramp_declare(NodeDeclarationBuilder &b)
+static void node_declare(NodeDeclarationBuilder &b)
{
b.add_input<decl::Geometry>(N_("Geometry"));
b.add_input<decl::String>(N_("Attribute"));
@@ -33,14 +33,12 @@ static void geo_node_attribute_color_ramp_declare(NodeDeclarationBuilder &b)
b.add_output<decl::Geometry>(N_("Geometry"));
}
-static void geo_node_attribute_color_ramp_layout(uiLayout *layout,
- bContext *UNUSED(C),
- PointerRNA *ptr)
+static void node_layout(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
{
uiTemplateColorRamp(layout, ptr, "color_ramp", false);
}
-static void geo_node_attribute_color_ramp_init(bNodeTree *UNUSED(ntree), bNode *node)
+static void node_init(bNodeTree *UNUSED(ntree), bNode *node)
{
NodeAttributeColorRamp *node_storage = (NodeAttributeColorRamp *)MEM_callocN(
sizeof(NodeAttributeColorRamp), __func__);
@@ -85,7 +83,7 @@ static void execute_on_component(const GeoNodeExecParams &params, GeometryCompon
return;
}
- GVArray_Typed<float> attribute_in = component.attribute_get_for_read<float>(
+ VArray<float> attribute_in = component.attribute_get_for_read<float>(
input_name, result_domain, 0.0f);
MutableSpan<ColorGeometry4f> results = attribute_result.as_span();
@@ -100,7 +98,7 @@ static void execute_on_component(const GeoNodeExecParams &params, GeometryCompon
attribute_result.save();
}
-static void geo_node_attribute_color_ramp_exec(GeoNodeExecParams params)
+static void node_geo_exec(GeoNodeExecParams params)
{
GeometrySet geometry_set = params.extract_input<GeometrySet>("Geometry");
@@ -119,10 +117,12 @@ static void geo_node_attribute_color_ramp_exec(GeoNodeExecParams params)
params.set_output("Geometry", std::move(geometry_set));
}
-} // namespace blender::nodes
+} // namespace blender::nodes::node_geo_legacy_attributes_color_ramp_cc
void register_node_type_geo_attribute_color_ramp()
{
+ namespace file_ns = blender::nodes::node_geo_legacy_attributes_color_ramp_cc;
+
static bNodeType ntype;
geo_node_type_base(&ntype,
@@ -132,10 +132,10 @@ void register_node_type_geo_attribute_color_ramp()
0);
node_type_storage(
&ntype, "NodeAttributeColorRamp", node_free_standard_storage, node_copy_standard_storage);
- node_type_init(&ntype, blender::nodes::geo_node_attribute_color_ramp_init);
+ node_type_init(&ntype, file_ns::node_init);
node_type_size_preset(&ntype, NODE_SIZE_LARGE);
- ntype.declare = blender::nodes::geo_node_attribute_color_ramp_declare;
- ntype.geometry_node_execute = blender::nodes::geo_node_attribute_color_ramp_exec;
- ntype.draw_buttons = blender::nodes::geo_node_attribute_color_ramp_layout;
+ ntype.declare = file_ns::node_declare;
+ ntype.geometry_node_execute = file_ns::node_geo_exec;
+ ntype.draw_buttons = file_ns::node_layout;
nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/geometry/nodes/legacy/node_geo_attribute_combine_xyz.cc b/source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_attribute_combine_xyz.cc
index d4c23380b4e..f8320c57f92 100644
--- a/source/blender/nodes/geometry/nodes/legacy/node_geo_attribute_combine_xyz.cc
+++ b/source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_attribute_combine_xyz.cc
@@ -19,9 +19,9 @@
#include "node_geometry_util.hh"
-namespace blender::nodes {
+namespace blender::nodes::node_geo_legacy_attribute_combine_xyz_cc {
-static void geo_node_attribute_combine_xyz_declare(NodeDeclarationBuilder &b)
+static void node_declare(NodeDeclarationBuilder &b)
{
b.add_input<decl::Geometry>(N_("Geometry"));
b.add_input<decl::String>(N_("X"));
@@ -34,9 +34,7 @@ static void geo_node_attribute_combine_xyz_declare(NodeDeclarationBuilder &b)
b.add_output<decl::Geometry>(N_("Geometry"));
}
-static void geo_node_attribute_combine_xyz_layout(uiLayout *layout,
- bContext *UNUSED(C),
- PointerRNA *ptr)
+static void node_layout(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
{
uiLayoutSetPropSep(layout, true);
uiLayoutSetPropDecorate(layout, false);
@@ -46,7 +44,7 @@ static void geo_node_attribute_combine_xyz_layout(uiLayout *layout,
uiItemR(col, ptr, "input_type_z", 0, IFACE_("Z"), ICON_NONE);
}
-static void geo_node_attribute_combine_xyz_init(bNodeTree *UNUSED(tree), bNode *node)
+static void node_init(bNodeTree *UNUSED(tree), bNode *node)
{
NodeAttributeCombineXYZ *data = (NodeAttributeCombineXYZ *)MEM_callocN(
sizeof(NodeAttributeCombineXYZ), __func__);
@@ -57,15 +55,15 @@ static void geo_node_attribute_combine_xyz_init(bNodeTree *UNUSED(tree), bNode *
node->storage = data;
}
-static void geo_node_attribute_combine_xyz_update(bNodeTree *UNUSED(ntree), bNode *node)
+static void node_update(bNodeTree *ntree, bNode *node)
{
NodeAttributeCombineXYZ *node_storage = (NodeAttributeCombineXYZ *)node->storage;
update_attribute_input_socket_availabilities(
- *node, "X", (GeometryNodeAttributeInputMode)node_storage->input_type_x);
+ *ntree, *node, "X", (GeometryNodeAttributeInputMode)node_storage->input_type_x);
update_attribute_input_socket_availabilities(
- *node, "Y", (GeometryNodeAttributeInputMode)node_storage->input_type_y);
+ *ntree, *node, "Y", (GeometryNodeAttributeInputMode)node_storage->input_type_y);
update_attribute_input_socket_availabilities(
- *node, "Z", (GeometryNodeAttributeInputMode)node_storage->input_type_z);
+ *ntree, *node, "Z", (GeometryNodeAttributeInputMode)node_storage->input_type_z);
}
static AttributeDomain get_result_domain(const GeometryComponent &component,
@@ -95,11 +93,11 @@ static void combine_attributes(GeometryComponent &component, const GeoNodeExecPa
if (!attribute_result) {
return;
}
- GVArray_Typed<float> attribute_x = params.get_input_attribute<float>(
+ VArray<float> attribute_x = params.get_input_attribute<float>(
"X", component, result_domain, 0.0f);
- GVArray_Typed<float> attribute_y = params.get_input_attribute<float>(
+ VArray<float> attribute_y = params.get_input_attribute<float>(
"Y", component, result_domain, 0.0f);
- GVArray_Typed<float> attribute_z = params.get_input_attribute<float>(
+ VArray<float> attribute_z = params.get_input_attribute<float>(
"Z", component, result_domain, 0.0f);
for (const int i : IndexRange(attribute_result->size())) {
@@ -111,7 +109,7 @@ static void combine_attributes(GeometryComponent &component, const GeoNodeExecPa
attribute_result.save();
}
-static void geo_node_attribute_combine_xyz_exec(GeoNodeExecParams params)
+static void node_geo_exec(GeoNodeExecParams params)
{
GeometrySet geometry_set = params.extract_input<GeometrySet>("Geometry");
@@ -130,10 +128,12 @@ static void geo_node_attribute_combine_xyz_exec(GeoNodeExecParams params)
params.set_output("Geometry", geometry_set);
}
-} // namespace blender::nodes
+} // namespace blender::nodes::node_geo_legacy_attribute_combine_xyz_cc
void register_node_type_geo_attribute_combine_xyz()
{
+ namespace file_ns = blender::nodes::node_geo_legacy_attribute_combine_xyz_cc;
+
static bNodeType ntype;
geo_node_type_base(&ntype,
@@ -141,13 +141,13 @@ void register_node_type_geo_attribute_combine_xyz()
"Attribute Combine XYZ",
NODE_CLASS_ATTRIBUTE,
0);
- node_type_init(&ntype, blender::nodes::geo_node_attribute_combine_xyz_init);
- node_type_update(&ntype, blender::nodes::geo_node_attribute_combine_xyz_update);
+ node_type_init(&ntype, file_ns::node_init);
+ node_type_update(&ntype, file_ns::node_update);
node_type_storage(
&ntype, "NodeAttributeCombineXYZ", node_free_standard_storage, node_copy_standard_storage);
- ntype.declare = blender::nodes::geo_node_attribute_combine_xyz_declare;
- ntype.geometry_node_execute = blender::nodes::geo_node_attribute_combine_xyz_exec;
- ntype.draw_buttons = blender::nodes::geo_node_attribute_combine_xyz_layout;
+ ntype.declare = file_ns::node_declare;
+ ntype.geometry_node_execute = file_ns::node_geo_exec;
+ ntype.draw_buttons = file_ns::node_layout;
nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/geometry/nodes/legacy/node_geo_attribute_compare.cc b/source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_attribute_compare.cc
index e4e43a7b724..e64f41cca72 100644
--- a/source/blender/nodes/geometry/nodes/legacy/node_geo_attribute_compare.cc
+++ b/source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_attribute_compare.cc
@@ -21,9 +21,9 @@
#include "node_geometry_util.hh"
-namespace blender::nodes {
+namespace blender::nodes::node_geo_legacy_attribute_compare_cc {
-static void geo_node_attribute_compare_declare(NodeDeclarationBuilder &b)
+static void node_declare(NodeDeclarationBuilder &b)
{
b.add_input<decl::Geometry>(N_("Geometry"));
b.add_input<decl::String>(N_("A"));
@@ -39,9 +39,7 @@ static void geo_node_attribute_compare_declare(NodeDeclarationBuilder &b)
b.add_output<decl::Geometry>(N_("Geometry"));
}
-static void geo_node_attribute_compare_layout(uiLayout *layout,
- bContext *UNUSED(C),
- PointerRNA *ptr)
+static void node_layout(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
{
uiItemR(layout, ptr, "operation", 0, "", ICON_NONE);
uiLayoutSetPropSep(layout, true);
@@ -50,7 +48,7 @@ static void geo_node_attribute_compare_layout(uiLayout *layout,
uiItemR(layout, ptr, "input_type_b", 0, IFACE_("B"), ICON_NONE);
}
-static void geo_node_attribute_compare_init(bNodeTree *UNUSED(tree), bNode *node)
+static void node_init(bNodeTree *UNUSED(tree), bNode *node)
{
NodeAttributeCompare *data = (NodeAttributeCompare *)MEM_callocN(sizeof(NodeAttributeCompare),
__func__);
@@ -65,16 +63,16 @@ static bool operation_tests_equality(const NodeAttributeCompare &node_storage)
return ELEM(node_storage.operation, NODE_FLOAT_COMPARE_EQUAL, NODE_FLOAT_COMPARE_NOT_EQUAL);
}
-static void geo_node_attribute_compare_update(bNodeTree *UNUSED(ntree), bNode *node)
+static void node_update(bNodeTree *ntree, bNode *node)
{
NodeAttributeCompare *node_storage = (NodeAttributeCompare *)node->storage;
update_attribute_input_socket_availabilities(
- *node, "A", (GeometryNodeAttributeInputMode)node_storage->input_type_a);
+ *ntree, *node, "A", (GeometryNodeAttributeInputMode)node_storage->input_type_a);
update_attribute_input_socket_availabilities(
- *node, "B", (GeometryNodeAttributeInputMode)node_storage->input_type_b);
+ *ntree, *node, "B", (GeometryNodeAttributeInputMode)node_storage->input_type_b);
bNodeSocket *socket_threshold = (bNodeSocket *)BLI_findlink(&node->inputs, 9);
- nodeSetSocketAvailability(socket_threshold, operation_tests_equality(*node_storage));
+ nodeSetSocketAvailability(ntree, socket_threshold, operation_tests_equality(*node_storage));
}
static void do_math_operation(const VArray<float> &input_a,
@@ -257,9 +255,9 @@ static void attribute_compare_calc(GeometryComponent &component, const GeoNodeEx
const CustomDataType input_data_type = get_data_type(component, params, *node_storage);
- GVArrayPtr attribute_a = params.get_input_attribute(
+ GVArray attribute_a = params.get_input_attribute(
"A", component, result_domain, input_data_type, nullptr);
- GVArrayPtr attribute_b = params.get_input_attribute(
+ GVArray attribute_b = params.get_input_attribute(
"B", component, result_domain, input_data_type, nullptr);
if (!attribute_a || !attribute_b) {
@@ -276,53 +274,53 @@ static void attribute_compare_calc(GeometryComponent &component, const GeoNodeEx
if (operation == NODE_FLOAT_COMPARE_EQUAL) {
if (input_data_type == CD_PROP_FLOAT) {
do_equal_operation_float(
- attribute_a->typed<float>(), attribute_b->typed<float>(), threshold, result_span);
+ attribute_a.typed<float>(), attribute_b.typed<float>(), threshold, result_span);
}
else if (input_data_type == CD_PROP_FLOAT3) {
do_equal_operation_float3(
- attribute_a->typed<float3>(), attribute_b->typed<float3>(), threshold, result_span);
+ attribute_a.typed<float3>(), attribute_b.typed<float3>(), threshold, result_span);
}
else if (input_data_type == CD_PROP_COLOR) {
- do_equal_operation_color4f(attribute_a->typed<ColorGeometry4f>(),
- attribute_b->typed<ColorGeometry4f>(),
+ do_equal_operation_color4f(attribute_a.typed<ColorGeometry4f>(),
+ attribute_b.typed<ColorGeometry4f>(),
threshold,
result_span);
}
else if (input_data_type == CD_PROP_BOOL) {
do_equal_operation_bool(
- attribute_a->typed<bool>(), attribute_b->typed<bool>(), threshold, result_span);
+ attribute_a.typed<bool>(), attribute_b.typed<bool>(), threshold, result_span);
}
}
else if (operation == NODE_FLOAT_COMPARE_NOT_EQUAL) {
if (input_data_type == CD_PROP_FLOAT) {
do_not_equal_operation_float(
- attribute_a->typed<float>(), attribute_b->typed<float>(), threshold, result_span);
+ attribute_a.typed<float>(), attribute_b.typed<float>(), threshold, result_span);
}
else if (input_data_type == CD_PROP_FLOAT3) {
do_not_equal_operation_float3(
- attribute_a->typed<float3>(), attribute_b->typed<float3>(), threshold, result_span);
+ attribute_a.typed<float3>(), attribute_b.typed<float3>(), threshold, result_span);
}
else if (input_data_type == CD_PROP_COLOR) {
- do_not_equal_operation_color4f(attribute_a->typed<ColorGeometry4f>(),
- attribute_b->typed<ColorGeometry4f>(),
+ do_not_equal_operation_color4f(attribute_a.typed<ColorGeometry4f>(),
+ attribute_b.typed<ColorGeometry4f>(),
threshold,
result_span);
}
else if (input_data_type == CD_PROP_BOOL) {
do_not_equal_operation_bool(
- attribute_a->typed<bool>(), attribute_b->typed<bool>(), threshold, result_span);
+ attribute_a.typed<bool>(), attribute_b.typed<bool>(), threshold, result_span);
}
}
}
else {
do_math_operation(
- attribute_a->typed<float>(), attribute_b->typed<float>(), operation, result_span);
+ attribute_a.typed<float>(), attribute_b.typed<float>(), operation, result_span);
}
attribute_result.save();
}
-static void geo_node_attribute_compare_exec(GeoNodeExecParams params)
+static void node_geo_exec(GeoNodeExecParams params)
{
GeometrySet geometry_set = params.extract_input<GeometrySet>("Geometry");
@@ -341,20 +339,22 @@ static void geo_node_attribute_compare_exec(GeoNodeExecParams params)
params.set_output("Geometry", geometry_set);
}
-} // namespace blender::nodes
+} // namespace blender::nodes::node_geo_legacy_attribute_compare_cc
void register_node_type_geo_attribute_compare()
{
+ namespace file_ns = blender::nodes::node_geo_legacy_attribute_compare_cc;
+
static bNodeType ntype;
geo_node_type_base(
&ntype, GEO_NODE_LEGACY_ATTRIBUTE_COMPARE, "Attribute Compare", NODE_CLASS_ATTRIBUTE, 0);
- ntype.declare = blender::nodes::geo_node_attribute_compare_declare;
- ntype.geometry_node_execute = blender::nodes::geo_node_attribute_compare_exec;
- ntype.draw_buttons = blender::nodes::geo_node_attribute_compare_layout;
- node_type_update(&ntype, blender::nodes::geo_node_attribute_compare_update);
+ ntype.declare = file_ns::node_declare;
+ ntype.geometry_node_execute = file_ns::node_geo_exec;
+ ntype.draw_buttons = file_ns::node_layout;
+ node_type_update(&ntype, file_ns::node_update);
node_type_storage(
&ntype, "NodeAttributeCompare", node_free_standard_storage, node_copy_standard_storage);
- node_type_init(&ntype, blender::nodes::geo_node_attribute_compare_init);
+ node_type_init(&ntype, file_ns::node_init);
nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/geometry/nodes/legacy/node_geo_attribute_convert.cc b/source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_attribute_convert.cc
index dc05fa2c125..1f241e1f20e 100644
--- a/source/blender/nodes/geometry/nodes/legacy/node_geo_attribute_convert.cc
+++ b/source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_attribute_convert.cc
@@ -19,9 +19,9 @@
#include "node_geometry_util.hh"
-namespace blender::nodes {
+namespace blender::nodes::node_geo_legacy_attribute_convert_cc {
-static void geo_node_attribute_convert_declare(NodeDeclarationBuilder &b)
+static void node_declare(NodeDeclarationBuilder &b)
{
b.add_input<decl::Geometry>(N_("Geometry"));
b.add_input<decl::String>(N_("Attribute"));
@@ -29,9 +29,7 @@ static void geo_node_attribute_convert_declare(NodeDeclarationBuilder &b)
b.add_output<decl::Geometry>(N_("Geometry"));
}
-static void geo_node_attribute_convert_layout(uiLayout *layout,
- bContext *UNUSED(C),
- PointerRNA *ptr)
+static void node_layout(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
{
uiLayoutSetPropSep(layout, true);
uiLayoutSetPropDecorate(layout, false);
@@ -39,7 +37,7 @@ static void geo_node_attribute_convert_layout(uiLayout *layout,
uiItemR(layout, ptr, "data_type", 0, IFACE_("Type"), ICON_NONE);
}
-static void geo_node_attribute_convert_init(bNodeTree *UNUSED(tree), bNode *node)
+static void node_init(bNodeTree *UNUSED(tree), bNode *node)
{
NodeAttributeConvert *data = (NodeAttributeConvert *)MEM_callocN(sizeof(NodeAttributeConvert),
__func__);
@@ -104,7 +102,7 @@ static void attribute_convert_calc(GeometryComponent &component,
return;
}
- GVArrayPtr source_attribute = component.attribute_try_get_for_read(
+ GVArray source_attribute = component.attribute_try_get_for_read(
source_name, result_domain, result_type);
if (!source_attribute) {
params.error_message_add(NodeWarningType::Error,
@@ -118,7 +116,7 @@ static void attribute_convert_calc(GeometryComponent &component,
return;
}
- GVArray_GSpan source_span{*source_attribute};
+ GVArray_GSpan source_span{source_attribute};
GMutableSpan result_span = result_attribute.as_span();
BLI_assert(source_span.size() == result_span.size());
@@ -130,7 +128,7 @@ static void attribute_convert_calc(GeometryComponent &component,
result_attribute.save();
}
-static void geo_node_attribute_convert_exec(GeoNodeExecParams params)
+static void node_geo_exec(GeoNodeExecParams params)
{
GeometrySet geometry_set = params.extract_input<GeometrySet>("Geometry");
@@ -175,18 +173,20 @@ static void geo_node_attribute_convert_exec(GeoNodeExecParams params)
params.set_output("Geometry", geometry_set);
}
-} // namespace blender::nodes
+} // namespace blender::nodes::node_geo_legacy_attribute_convert_cc
void register_node_type_geo_attribute_convert()
{
+ namespace file_ns = blender::nodes::node_geo_legacy_attribute_convert_cc;
+
static bNodeType ntype;
geo_node_type_base(
&ntype, GEO_NODE_LEGACY_ATTRIBUTE_CONVERT, "Attribute Convert", NODE_CLASS_ATTRIBUTE, 0);
- ntype.declare = blender::nodes::geo_node_attribute_convert_declare;
- ntype.geometry_node_execute = blender::nodes::geo_node_attribute_convert_exec;
- ntype.draw_buttons = blender::nodes::geo_node_attribute_convert_layout;
- node_type_init(&ntype, blender::nodes::geo_node_attribute_convert_init);
+ ntype.declare = file_ns::node_declare;
+ ntype.geometry_node_execute = file_ns::node_geo_exec;
+ ntype.draw_buttons = file_ns::node_layout;
+ node_type_init(&ntype, file_ns::node_init);
node_type_storage(
&ntype, "NodeAttributeConvert", node_free_standard_storage, node_copy_standard_storage);
diff --git a/source/blender/nodes/geometry/nodes/legacy/node_geo_attribute_curve_map.cc b/source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_attribute_curve_map.cc
index 669ac21436f..8c8b43825ec 100644
--- a/source/blender/nodes/geometry/nodes/legacy/node_geo_attribute_curve_map.cc
+++ b/source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_attribute_curve_map.cc
@@ -24,9 +24,9 @@
#include "node_geometry_util.hh"
-namespace blender::nodes {
+namespace blender::nodes::node_geo_legacy_attribute_curve_map_cc {
-static void geo_node_attribute_curve_map_declare(NodeDeclarationBuilder &b)
+static void node_declare(NodeDeclarationBuilder &b)
{
b.add_input<decl::Geometry>(N_("Geometry"));
b.add_input<decl::String>(N_("Attribute"));
@@ -34,9 +34,7 @@ static void geo_node_attribute_curve_map_declare(NodeDeclarationBuilder &b)
b.add_output<decl::Geometry>(N_("Geometry"));
}
-static void geo_node_attribute_curve_map_layout(uiLayout *layout,
- bContext *UNUSED(C),
- PointerRNA *ptr)
+static void node_layout(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
{
uiItemR(layout, ptr, "data_type", 0, "", ICON_NONE);
bNode *node = (bNode *)ptr->data;
@@ -54,7 +52,7 @@ static void geo_node_attribute_curve_map_layout(uiLayout *layout,
}
}
-static void geo_node_attribute_curve_map_free_storage(bNode *node)
+static void node_free_storage(bNode *node)
{
if (node->storage) {
NodeAttributeCurveMap *data = (NodeAttributeCurveMap *)node->storage;
@@ -64,9 +62,9 @@ static void geo_node_attribute_curve_map_free_storage(bNode *node)
}
}
-static void geo_node_attribute_curve_map_copy_storage(bNodeTree *UNUSED(dest_ntree),
- bNode *dest_node,
- const bNode *src_node)
+static void node_copy_storage(bNodeTree *UNUSED(dest_ntree),
+ bNode *dest_node,
+ const bNode *src_node)
{
dest_node->storage = MEM_dupallocN(src_node->storage);
NodeAttributeCurveMap *src_data = (NodeAttributeCurveMap *)src_node->storage;
@@ -75,7 +73,7 @@ static void geo_node_attribute_curve_map_copy_storage(bNodeTree *UNUSED(dest_ntr
dest_data->curve_rgb = BKE_curvemapping_copy(src_data->curve_rgb);
}
-static void geo_node_attribute_curve_map_init(bNodeTree *UNUSED(ntree), bNode *node)
+static void node_init(bNodeTree *UNUSED(ntree), bNode *node)
{
NodeAttributeCurveMap *data = (NodeAttributeCurveMap *)MEM_callocN(sizeof(NodeAttributeCurveMap),
__func__);
@@ -87,7 +85,7 @@ static void geo_node_attribute_curve_map_init(bNodeTree *UNUSED(ntree), bNode *n
node->storage = data;
}
-static void geo_node_attribute_curve_map_update(bNodeTree *UNUSED(ntree), bNode *node)
+static void node_update(bNodeTree *UNUSED(ntree), bNode *node)
{
/* Set the active curve when data type is changed. */
NodeAttributeCurveMap *data = (NodeAttributeCurveMap *)node->storage;
@@ -136,10 +134,10 @@ static void execute_on_component(const GeoNodeExecParams &params, GeometryCompon
switch (result_type) {
case CD_PROP_FLOAT: {
const CurveMapping *cumap = (CurveMapping *)node_storage.curve_vec;
- GVArray_Typed<float> attribute_in = component.attribute_get_for_read<float>(
+ VArray<float> attribute_in = component.attribute_get_for_read<float>(
input_name, result_domain, float(0.0f));
MutableSpan<float> results = attribute_result.as_span<float>();
- threading::parallel_for(IndexRange(attribute_in.size()), 512, [&](IndexRange range) {
+ threading::parallel_for(attribute_in.index_range(), 512, [&](IndexRange range) {
for (const int i : range) {
results[i] = BKE_curvemapping_evaluateF(cumap, 3, attribute_in[i]);
}
@@ -148,10 +146,10 @@ static void execute_on_component(const GeoNodeExecParams &params, GeometryCompon
}
case CD_PROP_FLOAT3: {
const CurveMapping *cumap = (CurveMapping *)node_storage.curve_vec;
- GVArray_Typed<float3> attribute_in = component.attribute_get_for_read<float3>(
+ VArray<float3> attribute_in = component.attribute_get_for_read<float3>(
input_name, result_domain, float3(0.0f));
MutableSpan<float3> results = attribute_result.as_span<float3>();
- threading::parallel_for(IndexRange(attribute_in.size()), 512, [&](IndexRange range) {
+ threading::parallel_for(attribute_in.index_range(), 512, [&](IndexRange range) {
for (const int i : range) {
BKE_curvemapping_evaluate3F(cumap, results[i], attribute_in[i]);
}
@@ -160,11 +158,10 @@ static void execute_on_component(const GeoNodeExecParams &params, GeometryCompon
}
case CD_PROP_COLOR: {
const CurveMapping *cumap = (CurveMapping *)node_storage.curve_rgb;
- GVArray_Typed<ColorGeometry4f> attribute_in =
- component.attribute_get_for_read<ColorGeometry4f>(
- input_name, result_domain, ColorGeometry4f(0.0f, 0.0f, 0.0f, 1.0f));
+ VArray<ColorGeometry4f> attribute_in = component.attribute_get_for_read<ColorGeometry4f>(
+ input_name, result_domain, ColorGeometry4f(0.0f, 0.0f, 0.0f, 1.0f));
MutableSpan<ColorGeometry4f> results = attribute_result.as_span<ColorGeometry4f>();
- threading::parallel_for(IndexRange(attribute_in.size()), 512, [&](IndexRange range) {
+ threading::parallel_for(attribute_in.index_range(), 512, [&](IndexRange range) {
for (const int i : range) {
BKE_curvemapping_evaluateRGBF(cumap, results[i], attribute_in[i]);
}
@@ -180,7 +177,7 @@ static void execute_on_component(const GeoNodeExecParams &params, GeometryCompon
attribute_result.save();
}
-static void geo_node_attribute_curve_map_exec(GeoNodeExecParams params)
+static void node_geo_exec(GeoNodeExecParams params)
{
const bNode &bnode = params.node();
NodeAttributeCurveMap *data = (NodeAttributeCurveMap *)bnode.storage;
@@ -204,23 +201,23 @@ static void geo_node_attribute_curve_map_exec(GeoNodeExecParams params)
params.set_output("Geometry", std::move(geometry_set));
}
-} // namespace blender::nodes
+} // namespace blender::nodes::node_geo_legacy_attribute_curve_map_cc
void register_node_type_geo_attribute_curve_map()
{
+ namespace file_ns = blender::nodes::node_geo_legacy_attribute_curve_map_cc;
+
static bNodeType ntype;
geo_node_type_base(
&ntype, GEO_NODE_LEGACY_ATTRIBUTE_CURVE_MAP, "Attribute Curve Map", NODE_CLASS_ATTRIBUTE, 0);
- node_type_update(&ntype, blender::nodes::geo_node_attribute_curve_map_update);
- node_type_init(&ntype, blender::nodes::geo_node_attribute_curve_map_init);
+ node_type_update(&ntype, file_ns::node_update);
+ node_type_init(&ntype, file_ns::node_init);
node_type_size_preset(&ntype, NODE_SIZE_LARGE);
- node_type_storage(&ntype,
- "NodeAttributeCurveMap",
- blender::nodes::geo_node_attribute_curve_map_free_storage,
- blender::nodes::geo_node_attribute_curve_map_copy_storage);
- ntype.declare = blender::nodes::geo_node_attribute_curve_map_declare;
- ntype.geometry_node_execute = blender::nodes::geo_node_attribute_curve_map_exec;
- ntype.draw_buttons = blender::nodes::geo_node_attribute_curve_map_layout;
+ node_type_storage(
+ &ntype, "NodeAttributeCurveMap", file_ns::node_free_storage, file_ns::node_copy_storage);
+ ntype.declare = file_ns::node_declare;
+ ntype.geometry_node_execute = file_ns::node_geo_exec;
+ ntype.draw_buttons = file_ns::node_layout;
nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/geometry/nodes/legacy/node_geo_attribute_fill.cc b/source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_attribute_fill.cc
index 5cb49dd83d0..e84c35eeada 100644
--- a/source/blender/nodes/geometry/nodes/legacy/node_geo_attribute_fill.cc
+++ b/source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_attribute_fill.cc
@@ -19,9 +19,9 @@
#include "node_geometry_util.hh"
-namespace blender::nodes {
+namespace blender::nodes::node_geo_legacy_attribute_fill_cc {
-static void geo_node_attribute_fill_declare(NodeDeclarationBuilder &b)
+static void node_declare(NodeDeclarationBuilder &b)
{
b.add_input<decl::Geometry>(N_("Geometry"));
b.add_input<decl::String>(N_("Attribute")).is_attribute_name();
@@ -33,7 +33,7 @@ static void geo_node_attribute_fill_declare(NodeDeclarationBuilder &b)
b.add_output<decl::Geometry>(N_("Geometry"));
}
-static void geo_node_attribute_fill_layout(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
+static void node_layout(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
{
uiLayoutSetPropSep(layout, true);
uiLayoutSetPropDecorate(layout, false);
@@ -41,13 +41,13 @@ static void geo_node_attribute_fill_layout(uiLayout *layout, bContext *UNUSED(C)
uiItemR(layout, ptr, "data_type", 0, "", ICON_NONE);
}
-static void geo_node_attribute_fill_init(bNodeTree *UNUSED(tree), bNode *node)
+static void node_init(bNodeTree *UNUSED(tree), bNode *node)
{
node->custom1 = CD_PROP_FLOAT;
node->custom2 = ATTR_DOMAIN_AUTO;
}
-static void geo_node_attribute_fill_update(bNodeTree *UNUSED(ntree), bNode *node)
+static void node_update(bNodeTree *ntree, bNode *node)
{
bNodeSocket *socket_value_vector = (bNodeSocket *)BLI_findlink(&node->inputs, 2);
bNodeSocket *socket_value_float = socket_value_vector->next;
@@ -57,11 +57,11 @@ static void geo_node_attribute_fill_update(bNodeTree *UNUSED(ntree), bNode *node
const CustomDataType data_type = static_cast<CustomDataType>(node->custom1);
- nodeSetSocketAvailability(socket_value_vector, data_type == CD_PROP_FLOAT3);
- nodeSetSocketAvailability(socket_value_float, data_type == CD_PROP_FLOAT);
- nodeSetSocketAvailability(socket_value_color4f, data_type == CD_PROP_COLOR);
- nodeSetSocketAvailability(socket_value_boolean, data_type == CD_PROP_BOOL);
- nodeSetSocketAvailability(socket_value_int32, data_type == CD_PROP_INT32);
+ nodeSetSocketAvailability(ntree, socket_value_vector, data_type == CD_PROP_FLOAT3);
+ nodeSetSocketAvailability(ntree, socket_value_float, data_type == CD_PROP_FLOAT);
+ nodeSetSocketAvailability(ntree, socket_value_color4f, data_type == CD_PROP_COLOR);
+ nodeSetSocketAvailability(ntree, socket_value_boolean, data_type == CD_PROP_BOOL);
+ nodeSetSocketAvailability(ntree, socket_value_int32, data_type == CD_PROP_INT32);
}
static AttributeDomain get_result_domain(const GeometryComponent &component, const StringRef name)
@@ -127,7 +127,7 @@ static void fill_attribute(GeometryComponent &component, const GeoNodeExecParams
attribute.save();
}
-static void geo_node_attribute_fill_exec(GeoNodeExecParams params)
+static void node_geo_exec(GeoNodeExecParams params)
{
GeometrySet geometry_set = params.extract_input<GeometrySet>("Geometry");
@@ -146,18 +146,20 @@ static void geo_node_attribute_fill_exec(GeoNodeExecParams params)
params.set_output("Geometry", geometry_set);
}
-} // namespace blender::nodes
+} // namespace blender::nodes::node_geo_legacy_attribute_fill_cc
void register_node_type_geo_attribute_fill()
{
+ namespace file_ns = blender::nodes::node_geo_legacy_attribute_fill_cc;
+
static bNodeType ntype;
geo_node_type_base(
&ntype, GEO_NODE_LEGACY_ATTRIBUTE_FILL, "Attribute Fill", NODE_CLASS_ATTRIBUTE, 0);
- node_type_init(&ntype, blender::nodes::geo_node_attribute_fill_init);
- node_type_update(&ntype, blender::nodes::geo_node_attribute_fill_update);
- ntype.geometry_node_execute = blender::nodes::geo_node_attribute_fill_exec;
- ntype.draw_buttons = blender::nodes::geo_node_attribute_fill_layout;
- ntype.declare = blender::nodes::geo_node_attribute_fill_declare;
+ node_type_init(&ntype, file_ns::node_init);
+ node_type_update(&ntype, file_ns::node_update);
+ ntype.geometry_node_execute = file_ns::node_geo_exec;
+ ntype.draw_buttons = file_ns::node_layout;
+ ntype.declare = file_ns::node_declare;
nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/geometry/nodes/legacy/node_geo_attribute_map_range.cc b/source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_attribute_map_range.cc
index 978c75187fe..8ebcf34ad0b 100644
--- a/source/blender/nodes/geometry/nodes/legacy/node_geo_attribute_map_range.cc
+++ b/source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_attribute_map_range.cc
@@ -22,9 +22,9 @@
#include "node_geometry_util.hh"
-namespace blender::nodes {
+namespace blender::nodes::node_geo_legacy_attribute_map_range_cc {
-static void geo_node_attribute_map_range_declare(NodeDeclarationBuilder &b)
+static void node_declare(NodeDeclarationBuilder &b)
{
b.add_input<decl::Geometry>(N_("Geometry"));
b.add_input<decl::String>(N_("Attribute"));
@@ -49,7 +49,7 @@ static void fn_attribute_map_range_layout(uiLayout *layout, bContext *UNUSED(C),
uiItemR(layout, ptr, "interpolation_type", 0, "", ICON_NONE);
}
-static void geo_node_attribute_map_range_init(bNodeTree *UNUSED(ntree), bNode *node)
+static void node_init(bNodeTree *UNUSED(ntree), bNode *node)
{
NodeAttributeMapRange *data = (NodeAttributeMapRange *)MEM_callocN(sizeof(NodeAttributeMapRange),
__func__);
@@ -58,7 +58,7 @@ static void geo_node_attribute_map_range_init(bNodeTree *UNUSED(ntree), bNode *n
node->storage = data;
}
-static void geo_node_attribute_map_range_update(bNodeTree *UNUSED(ntree), bNode *node)
+static void node_update(bNodeTree *ntree, bNode *node)
{
NodeAttributeMapRange &node_storage = *(NodeAttributeMapRange *)node->storage;
@@ -78,23 +78,26 @@ static void geo_node_attribute_map_range_update(bNodeTree *UNUSED(ntree), bNode
const CustomDataType data_type = static_cast<CustomDataType>(node_storage.data_type);
- nodeSetSocketAvailability(sock_clamp,
+ nodeSetSocketAvailability(ntree,
+ sock_clamp,
node_storage.interpolation_type == NODE_MAP_RANGE_LINEAR ||
node_storage.interpolation_type == NODE_MAP_RANGE_STEPPED);
- nodeSetSocketAvailability(sock_from_min_float, data_type == CD_PROP_FLOAT);
- nodeSetSocketAvailability(sock_from_max_float, data_type == CD_PROP_FLOAT);
- nodeSetSocketAvailability(sock_to_min_float, data_type == CD_PROP_FLOAT);
- nodeSetSocketAvailability(sock_to_max_float, data_type == CD_PROP_FLOAT);
- nodeSetSocketAvailability(sock_steps_float,
+ nodeSetSocketAvailability(ntree, sock_from_min_float, data_type == CD_PROP_FLOAT);
+ nodeSetSocketAvailability(ntree, sock_from_max_float, data_type == CD_PROP_FLOAT);
+ nodeSetSocketAvailability(ntree, sock_to_min_float, data_type == CD_PROP_FLOAT);
+ nodeSetSocketAvailability(ntree, sock_to_max_float, data_type == CD_PROP_FLOAT);
+ nodeSetSocketAvailability(ntree,
+ sock_steps_float,
data_type == CD_PROP_FLOAT &&
node_storage.interpolation_type == NODE_MAP_RANGE_STEPPED);
- nodeSetSocketAvailability(sock_from_min_vector, data_type == CD_PROP_FLOAT3);
- nodeSetSocketAvailability(sock_from_max_vector, data_type == CD_PROP_FLOAT3);
- nodeSetSocketAvailability(sock_to_min_vector, data_type == CD_PROP_FLOAT3);
- nodeSetSocketAvailability(sock_to_max_vector, data_type == CD_PROP_FLOAT3);
- nodeSetSocketAvailability(sock_steps_vector,
+ nodeSetSocketAvailability(ntree, sock_from_min_vector, data_type == CD_PROP_FLOAT3);
+ nodeSetSocketAvailability(ntree, sock_from_max_vector, data_type == CD_PROP_FLOAT3);
+ nodeSetSocketAvailability(ntree, sock_to_min_vector, data_type == CD_PROP_FLOAT3);
+ nodeSetSocketAvailability(ntree, sock_to_max_vector, data_type == CD_PROP_FLOAT3);
+ nodeSetSocketAvailability(ntree,
+ sock_steps_vector,
data_type == CD_PROP_FLOAT3 &&
node_storage.interpolation_type == NODE_MAP_RANGE_STEPPED);
}
@@ -362,7 +365,7 @@ static void map_range_attribute(GeometryComponent &component, const GeoNodeExecP
const AttributeDomain domain = get_result_domain(component, input_name, result_name);
- GVArrayPtr attribute_input = component.attribute_try_get_for_read(input_name, domain, data_type);
+ GVArray attribute_input = component.attribute_try_get_for_read(input_name, domain, data_type);
if (!attribute_input) {
params.error_message_add(NodeWarningType::Error,
@@ -381,12 +384,12 @@ static void map_range_attribute(GeometryComponent &component, const GeoNodeExecP
switch (data_type) {
case CD_PROP_FLOAT: {
- map_range_float(attribute_input->typed<float>(), attribute_result.as_span<float>(), params);
+ map_range_float(attribute_input.typed<float>(), attribute_result.as_span<float>(), params);
break;
}
case CD_PROP_FLOAT3: {
map_range_float3(
- attribute_input->typed<float3>(), attribute_result.as_span<float3>(), params);
+ attribute_input.typed<float3>(), attribute_result.as_span<float3>(), params);
break;
}
default:
@@ -396,7 +399,7 @@ static void map_range_attribute(GeometryComponent &component, const GeoNodeExecP
attribute_result.save();
}
-static void geo_node_attribute_map_range_exec(GeoNodeExecParams params)
+static void node_geo_exec(GeoNodeExecParams params)
{
GeometrySet geometry_set = params.extract_input<GeometrySet>("Geometry");
@@ -413,20 +416,22 @@ static void geo_node_attribute_map_range_exec(GeoNodeExecParams params)
params.set_output("Geometry", geometry_set);
}
-} // namespace blender::nodes
+} // namespace blender::nodes::node_geo_legacy_attribute_map_range_cc
void register_node_type_geo_attribute_map_range()
{
+ namespace file_ns = blender::nodes::node_geo_legacy_attribute_map_range_cc;
+
static bNodeType ntype;
geo_node_type_base(
&ntype, GEO_NODE_LEGACY_ATTRIBUTE_MAP_RANGE, "Attribute Map Range", NODE_CLASS_ATTRIBUTE, 0);
- ntype.geometry_node_execute = blender::nodes::geo_node_attribute_map_range_exec;
- node_type_init(&ntype, blender::nodes::geo_node_attribute_map_range_init);
- node_type_update(&ntype, blender::nodes::geo_node_attribute_map_range_update);
+ ntype.geometry_node_execute = file_ns::node_geo_exec;
+ node_type_init(&ntype, file_ns::node_init);
+ node_type_update(&ntype, file_ns::node_update);
node_type_storage(
&ntype, "NodeAttributeMapRange", node_free_standard_storage, node_copy_standard_storage);
- ntype.declare = blender::nodes::geo_node_attribute_map_range_declare;
- ntype.draw_buttons = blender::nodes::fn_attribute_map_range_layout;
+ ntype.declare = file_ns::node_declare;
+ ntype.draw_buttons = file_ns::fn_attribute_map_range_layout;
nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/geometry/nodes/legacy/node_geo_attribute_math.cc b/source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_attribute_math.cc
index 55d35f87cda..11f06adcf50 100644
--- a/source/blender/nodes/geometry/nodes/legacy/node_geo_attribute_math.cc
+++ b/source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_attribute_math.cc
@@ -25,9 +25,9 @@
#include "node_geometry_util.hh"
-namespace blender::nodes {
+namespace blender::nodes::node_geo_legacy_attribute_math_cc {
-static void geo_node_attribute_math_declare(NodeDeclarationBuilder &b)
+static void node_declare(NodeDeclarationBuilder &b)
{
b.add_input<decl::Geometry>(N_("Geometry"));
b.add_input<decl::String>(N_("A"));
@@ -100,7 +100,7 @@ static bool operation_use_input_b(const NodeMathOperation operation)
return false;
}
-static void geo_node_attribute_math_layout(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
+static void node_layout(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
{
bNode *node = (bNode *)ptr->data;
NodeAttributeMath *node_storage = (NodeAttributeMath *)node->storage;
@@ -119,7 +119,7 @@ static void geo_node_attribute_math_layout(uiLayout *layout, bContext *UNUSED(C)
}
}
-static void geo_node_attribute_math_init(bNodeTree *UNUSED(tree), bNode *node)
+static void node_init(bNodeTree *UNUSED(tree), bNode *node)
{
NodeAttributeMath *data = (NodeAttributeMath *)MEM_callocN(sizeof(NodeAttributeMath), __func__);
@@ -141,19 +141,21 @@ static void geo_node_math_label(bNodeTree *UNUSED(ntree), bNode *node, char *lab
BLI_strncpy(label, IFACE_(name), maxlen);
}
-static void geo_node_attribute_math_update(bNodeTree *UNUSED(ntree), bNode *node)
+static void node_update(bNodeTree *ntree, bNode *node)
{
NodeAttributeMath &node_storage = *(NodeAttributeMath *)node->storage;
NodeMathOperation operation = static_cast<NodeMathOperation>(node_storage.operation);
update_attribute_input_socket_availabilities(
- *node, "A", (GeometryNodeAttributeInputMode)node_storage.input_type_a);
+ *ntree, *node, "A", (GeometryNodeAttributeInputMode)node_storage.input_type_a);
update_attribute_input_socket_availabilities(
+ *ntree,
*node,
"B",
(GeometryNodeAttributeInputMode)node_storage.input_type_b,
operation_use_input_b(operation));
update_attribute_input_socket_availabilities(
+ *ntree,
*node,
"C",
(GeometryNodeAttributeInputMode)node_storage.input_type_c,
@@ -250,7 +252,7 @@ static void attribute_math_calc(GeometryComponent &component, const GeoNodeExecP
return;
}
- GVArray_Typed<float> attribute_a = params.get_input_attribute<float>(
+ VArray<float> attribute_a = params.get_input_attribute<float>(
"A", component, result_domain, 0.0f);
MutableSpan<float> result_span = attribute_result.as_span();
@@ -258,10 +260,10 @@ static void attribute_math_calc(GeometryComponent &component, const GeoNodeExecP
/* Note that passing the data with `get_internal_span<float>()` works
* because the attributes were accessed with #CD_PROP_FLOAT. */
if (operation_use_input_b(operation)) {
- GVArray_Typed<float> attribute_b = params.get_input_attribute<float>(
+ VArray<float> attribute_b = params.get_input_attribute<float>(
"B", component, result_domain, 0.0f);
if (operation_use_input_c(operation)) {
- GVArray_Typed<float> attribute_c = params.get_input_attribute<float>(
+ VArray<float> attribute_c = params.get_input_attribute<float>(
"C", component, result_domain, 0.0f);
do_math_operation(attribute_a, attribute_b, attribute_c, result_span, operation);
}
@@ -276,7 +278,7 @@ static void attribute_math_calc(GeometryComponent &component, const GeoNodeExecP
attribute_result.save();
}
-static void geo_node_attribute_math_exec(GeoNodeExecParams params)
+static void node_geo_exec(GeoNodeExecParams params)
{
GeometrySet geometry_set = params.extract_input<GeometrySet>("Geometry");
@@ -295,20 +297,22 @@ static void geo_node_attribute_math_exec(GeoNodeExecParams params)
params.set_output("Geometry", geometry_set);
}
-} // namespace blender::nodes
+} // namespace blender::nodes::node_geo_legacy_attribute_math_cc
void register_node_type_geo_attribute_math()
{
+ namespace file_ns = blender::nodes::node_geo_legacy_attribute_math_cc;
+
static bNodeType ntype;
geo_node_type_base(
&ntype, GEO_NODE_LEGACY_ATTRIBUTE_MATH, "Attribute Math", NODE_CLASS_ATTRIBUTE, 0);
- ntype.declare = blender::nodes::geo_node_attribute_math_declare;
- ntype.geometry_node_execute = blender::nodes::geo_node_attribute_math_exec;
- ntype.draw_buttons = blender::nodes::geo_node_attribute_math_layout;
- node_type_label(&ntype, blender::nodes::geo_node_math_label);
- node_type_update(&ntype, blender::nodes::geo_node_attribute_math_update);
- node_type_init(&ntype, blender::nodes::geo_node_attribute_math_init);
+ ntype.declare = file_ns::node_declare;
+ ntype.geometry_node_execute = file_ns::node_geo_exec;
+ ntype.draw_buttons = file_ns::node_layout;
+ node_type_label(&ntype, file_ns::geo_node_math_label);
+ node_type_update(&ntype, file_ns::node_update);
+ node_type_init(&ntype, file_ns::node_init);
node_type_storage(
&ntype, "NodeAttributeMath", node_free_standard_storage, node_copy_standard_storage);
nodeRegisterType(&ntype);
diff --git a/source/blender/nodes/geometry/nodes/legacy/node_geo_attribute_mix.cc b/source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_attribute_mix.cc
index b4205bc91b7..e99c75dbd68 100644
--- a/source/blender/nodes/geometry/nodes/legacy/node_geo_attribute_mix.cc
+++ b/source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_attribute_mix.cc
@@ -25,9 +25,9 @@
#include "node_geometry_util.hh"
-namespace blender::nodes {
+namespace blender::nodes::node_geo_legacy_attribute_mix_cc {
-static void geo_node_mix_attribute_declare(NodeDeclarationBuilder &b)
+static void node_declare(NodeDeclarationBuilder &b)
{
b.add_input<decl::Geometry>(N_("Geometry"));
b.add_input<decl::String>(N_("Factor"));
@@ -48,7 +48,7 @@ static void geo_node_mix_attribute_declare(NodeDeclarationBuilder &b)
b.add_output<decl::Geometry>(N_("Geometry"));
}
-static void geo_node_attribute_mix_layout(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
+static void node_layout(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
{
uiLayoutSetPropSep(layout, true);
uiLayoutSetPropDecorate(layout, false);
@@ -59,7 +59,7 @@ static void geo_node_attribute_mix_layout(uiLayout *layout, bContext *UNUSED(C),
uiItemR(col, ptr, "input_type_b", 0, IFACE_("B"), ICON_NONE);
}
-static void geo_node_attribute_mix_init(bNodeTree *UNUSED(ntree), bNode *node)
+static void node_init(bNodeTree *UNUSED(ntree), bNode *node)
{
NodeAttributeMix *data = (NodeAttributeMix *)MEM_callocN(sizeof(NodeAttributeMix),
"attribute mix node");
@@ -70,15 +70,15 @@ static void geo_node_attribute_mix_init(bNodeTree *UNUSED(ntree), bNode *node)
node->storage = data;
}
-static void geo_node_attribute_mix_update(bNodeTree *UNUSED(ntree), bNode *node)
+static void node_update(bNodeTree *ntree, bNode *node)
{
NodeAttributeMix *node_storage = (NodeAttributeMix *)node->storage;
update_attribute_input_socket_availabilities(
- *node, "Factor", (GeometryNodeAttributeInputMode)node_storage->input_type_factor);
+ *ntree, *node, "Factor", (GeometryNodeAttributeInputMode)node_storage->input_type_factor);
update_attribute_input_socket_availabilities(
- *node, "A", (GeometryNodeAttributeInputMode)node_storage->input_type_a);
+ *ntree, *node, "A", (GeometryNodeAttributeInputMode)node_storage->input_type_a);
update_attribute_input_socket_availabilities(
- *node, "B", (GeometryNodeAttributeInputMode)node_storage->input_type_b);
+ *ntree, *node, "B", (GeometryNodeAttributeInputMode)node_storage->input_type_b);
}
static void do_mix_operation_float(const int blend_mode,
@@ -144,25 +144,28 @@ static void do_mix_operation(const CustomDataType result_type,
GVMutableArray &attribute_result)
{
if (result_type == CD_PROP_FLOAT) {
+ VMutableArray<float> result = attribute_result.typed<float>();
do_mix_operation_float(blend_mode,
attribute_factor,
attribute_a.typed<float>(),
attribute_b.typed<float>(),
- attribute_result.typed<float>());
+ result);
}
else if (result_type == CD_PROP_FLOAT3) {
+ VMutableArray<float3> result = attribute_result.typed<float3>();
do_mix_operation_float3(blend_mode,
attribute_factor,
attribute_a.typed<float3>(),
attribute_b.typed<float3>(),
- attribute_result.typed<float3>());
+ result);
}
else if (result_type == CD_PROP_COLOR) {
+ VMutableArray<ColorGeometry4f> result = attribute_result.typed<ColorGeometry4f>();
do_mix_operation_color4f(blend_mode,
attribute_factor,
attribute_a.typed<ColorGeometry4f>(),
attribute_b.typed<ColorGeometry4f>(),
- attribute_result.typed<ColorGeometry4f>());
+ result);
}
}
@@ -203,23 +206,23 @@ static void attribute_mix_calc(GeometryComponent &component, const GeoNodeExecPa
return;
}
- GVArray_Typed<float> attribute_factor = params.get_input_attribute<float>(
+ VArray<float> attribute_factor = params.get_input_attribute<float>(
"Factor", component, result_domain, 0.5f);
- GVArrayPtr attribute_a = params.get_input_attribute(
+ GVArray attribute_a = params.get_input_attribute(
"A", component, result_domain, result_type, nullptr);
- GVArrayPtr attribute_b = params.get_input_attribute(
+ GVArray attribute_b = params.get_input_attribute(
"B", component, result_domain, result_type, nullptr);
do_mix_operation(result_type,
node_storage->blend_type,
attribute_factor,
- *attribute_a,
- *attribute_b,
- *attribute_result);
+ attribute_a,
+ attribute_b,
+ attribute_result.varray());
attribute_result.save();
}
-static void geo_node_attribute_mix_exec(GeoNodeExecParams params)
+static void node_geo_exec(GeoNodeExecParams params)
{
GeometrySet geometry_set = params.extract_input<GeometrySet>("Geometry");
@@ -238,19 +241,21 @@ static void geo_node_attribute_mix_exec(GeoNodeExecParams params)
params.set_output("Geometry", geometry_set);
}
-} // namespace blender::nodes
+} // namespace blender::nodes::node_geo_legacy_attribute_mix_cc
void register_node_type_geo_attribute_mix()
{
+ namespace file_ns = blender::nodes::node_geo_legacy_attribute_mix_cc;
+
static bNodeType ntype;
geo_node_type_base(
&ntype, GEO_NODE_LEGACY_ATTRIBUTE_MIX, "Attribute Mix", NODE_CLASS_ATTRIBUTE, 0);
- node_type_init(&ntype, blender::nodes::geo_node_attribute_mix_init);
- node_type_update(&ntype, blender::nodes::geo_node_attribute_mix_update);
- ntype.declare = blender::nodes::geo_node_mix_attribute_declare;
- ntype.draw_buttons = blender::nodes::geo_node_attribute_mix_layout;
+ node_type_init(&ntype, file_ns::node_init);
+ node_type_update(&ntype, file_ns::node_update);
+ ntype.declare = file_ns::node_declare;
+ ntype.draw_buttons = file_ns::node_layout;
node_type_storage(
&ntype, "NodeAttributeMix", node_free_standard_storage, node_copy_standard_storage);
- ntype.geometry_node_execute = blender::nodes::geo_node_attribute_mix_exec;
+ ntype.geometry_node_execute = file_ns::node_geo_exec;
nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/geometry/nodes/legacy/node_geo_attribute_proximity.cc b/source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_attribute_proximity.cc
index 9e3a7984c53..9090503924e 100644
--- a/source/blender/nodes/geometry/nodes/legacy/node_geo_attribute_proximity.cc
+++ b/source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_attribute_proximity.cc
@@ -26,9 +26,9 @@
#include "node_geometry_util.hh"
-namespace blender::nodes {
+namespace blender::nodes::node_geo_legacy_attribute_proximity_cc {
-static void geo_node_attribute_proximity_declare(NodeDeclarationBuilder &b)
+static void node_declare(NodeDeclarationBuilder &b)
{
b.add_input<decl::Geometry>(N_("Geometry"));
b.add_input<decl::Geometry>(N_("Target"));
@@ -37,14 +37,12 @@ static void geo_node_attribute_proximity_declare(NodeDeclarationBuilder &b)
b.add_output<decl::Geometry>(N_("Geometry"));
}
-static void geo_node_attribute_proximity_layout(uiLayout *layout,
- bContext *UNUSED(C),
- PointerRNA *ptr)
+static void node_layout(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
{
uiItemR(layout, ptr, "target_geometry_element", 0, "", ICON_NONE);
}
-static void geo_attribute_proximity_init(bNodeTree *UNUSED(ntree), bNode *node)
+static void node_init(bNodeTree *UNUSED(ntree), bNode *node)
{
NodeGeometryAttributeProximity *node_storage = (NodeGeometryAttributeProximity *)MEM_callocN(
sizeof(NodeGeometryAttributeProximity), __func__);
@@ -153,7 +151,7 @@ static void attribute_calc_proximity(GeometryComponent &component,
if (!position_attribute || (!distance_attribute && !location_attribute)) {
return;
}
- GVArray_Typed<float3> positions{*position_attribute.varray};
+ VArray<float3> positions = position_attribute.varray.typed<float3>();
const NodeGeometryAttributeProximity &storage =
*(const NodeGeometryAttributeProximity *)params.node().storage;
@@ -203,7 +201,7 @@ static void attribute_calc_proximity(GeometryComponent &component,
}
}
-static void geo_node_attribute_proximity_exec(GeoNodeExecParams params)
+static void node_geo_exec(GeoNodeExecParams params)
{
GeometrySet geometry_set = params.extract_input<GeometrySet>("Geometry");
GeometrySet geometry_set_target = params.extract_input<GeometrySet>("Target");
@@ -230,22 +228,24 @@ static void geo_node_attribute_proximity_exec(GeoNodeExecParams params)
params.set_output("Geometry", geometry_set);
}
-} // namespace blender::nodes
+} // namespace blender::nodes::node_geo_legacy_attribute_proximity_cc
void register_node_type_geo_legacy_attribute_proximity()
{
+ namespace file_ns = blender::nodes::node_geo_legacy_attribute_proximity_cc;
+
static bNodeType ntype;
geo_node_type_base(
&ntype, GEO_NODE_LEGACY_ATTRIBUTE_PROXIMITY, "Attribute Proximity", NODE_CLASS_ATTRIBUTE, 0);
- node_type_init(&ntype, blender::nodes::geo_attribute_proximity_init);
+ node_type_init(&ntype, file_ns::node_init);
node_type_storage(&ntype,
"NodeGeometryAttributeProximity",
node_free_standard_storage,
node_copy_standard_storage);
- ntype.declare = blender::nodes::geo_node_attribute_proximity_declare;
- ntype.geometry_node_execute = blender::nodes::geo_node_attribute_proximity_exec;
- ntype.draw_buttons = blender::nodes::geo_node_attribute_proximity_layout;
+ ntype.declare = file_ns::node_declare;
+ ntype.geometry_node_execute = file_ns::node_geo_exec;
+ ntype.draw_buttons = file_ns::node_layout;
nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/geometry/nodes/legacy/node_geo_attribute_randomize.cc b/source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_attribute_randomize.cc
index 2901472d661..8fb05d031a6 100644
--- a/source/blender/nodes/geometry/nodes/legacy/node_geo_attribute_randomize.cc
+++ b/source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_attribute_randomize.cc
@@ -25,7 +25,41 @@
namespace blender::nodes {
-static void geo_node_legacy_attribute_randomize_declare(NodeDeclarationBuilder &b)
+Array<uint32_t> get_geometry_element_ids_as_uints(const GeometryComponent &component,
+ const AttributeDomain domain)
+{
+ const int domain_size = component.attribute_domain_size(domain);
+
+ /* Hash the reserved name attribute "id" as a (hopefully) stable seed for each point. */
+ GVArray hash_attribute = component.attribute_try_get_for_read("id", domain);
+ Array<uint32_t> hashes(domain_size);
+ if (hash_attribute) {
+ BLI_assert(hashes.size() == hash_attribute.size());
+ const CPPType &cpp_type = hash_attribute.type();
+ BLI_assert(cpp_type.is_hashable());
+ GVArray_GSpan items{hash_attribute};
+ threading::parallel_for(hashes.index_range(), 512, [&](IndexRange range) {
+ for (const int i : range) {
+ hashes[i] = cpp_type.hash(items[i]);
+ }
+ });
+ }
+ else {
+ /* If there is no "id" attribute for per-point variation, just create it here. */
+ RandomNumberGenerator rng(0);
+ for (const int i : hashes.index_range()) {
+ hashes[i] = rng.get_uint32();
+ }
+ }
+
+ return hashes;
+}
+
+} // namespace blender::nodes
+
+namespace blender::nodes::node_geo_legacy_attribute_randomize_cc {
+
+static void node_declare(NodeDeclarationBuilder &b)
{
b.add_input<decl::Geometry>(N_("Geometry"));
b.add_input<decl::String>(N_("Attribute"));
@@ -39,15 +73,13 @@ static void geo_node_legacy_attribute_randomize_declare(NodeDeclarationBuilder &
b.add_output<decl::Geometry>(N_("Geometry"));
}
-static void geo_node_legacy_attribute_random_layout(uiLayout *layout,
- bContext *UNUSED(C),
- PointerRNA *ptr)
+static void node_layout(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
{
uiItemR(layout, ptr, "data_type", 0, "", ICON_NONE);
uiItemR(layout, ptr, "operation", 0, "", ICON_NONE);
}
-static void geo_node_legacy_attribute_randomize_init(bNodeTree *UNUSED(tree), bNode *node)
+static void node_init(bNodeTree *UNUSED(tree), bNode *node)
{
NodeAttributeRandomize *data = (NodeAttributeRandomize *)MEM_callocN(
sizeof(NodeAttributeRandomize), __func__);
@@ -57,7 +89,7 @@ static void geo_node_legacy_attribute_randomize_init(bNodeTree *UNUSED(tree), bN
node->storage = data;
}
-static void geo_node_legacy_attribute_randomize_update(bNodeTree *UNUSED(ntree), bNode *node)
+static void node_update(bNodeTree *ntree, bNode *node)
{
bNodeSocket *sock_min_vector = (bNodeSocket *)BLI_findlink(&node->inputs, 2);
bNodeSocket *sock_max_vector = sock_min_vector->next;
@@ -68,12 +100,12 @@ static void geo_node_legacy_attribute_randomize_update(bNodeTree *UNUSED(ntree),
const NodeAttributeRandomize &storage = *(const NodeAttributeRandomize *)node->storage;
const CustomDataType data_type = static_cast<CustomDataType>(storage.data_type);
- nodeSetSocketAvailability(sock_min_vector, data_type == CD_PROP_FLOAT3);
- nodeSetSocketAvailability(sock_max_vector, data_type == CD_PROP_FLOAT3);
- nodeSetSocketAvailability(sock_min_float, data_type == CD_PROP_FLOAT);
- nodeSetSocketAvailability(sock_max_float, data_type == CD_PROP_FLOAT);
- nodeSetSocketAvailability(sock_min_int, data_type == CD_PROP_INT32);
- nodeSetSocketAvailability(sock_max_int, data_type == CD_PROP_INT32);
+ nodeSetSocketAvailability(ntree, sock_min_vector, data_type == CD_PROP_FLOAT3);
+ nodeSetSocketAvailability(ntree, sock_max_vector, data_type == CD_PROP_FLOAT3);
+ nodeSetSocketAvailability(ntree, sock_min_float, data_type == CD_PROP_FLOAT);
+ nodeSetSocketAvailability(ntree, sock_max_float, data_type == CD_PROP_FLOAT);
+ nodeSetSocketAvailability(ntree, sock_min_int, data_type == CD_PROP_INT32);
+ nodeSetSocketAvailability(ntree, sock_max_int, data_type == CD_PROP_INT32);
}
template<typename T>
@@ -174,36 +206,6 @@ static void randomize_attribute_bool(MutableSpan<bool> span,
});
}
-Array<uint32_t> get_geometry_element_ids_as_uints(const GeometryComponent &component,
- const AttributeDomain domain)
-{
- const int domain_size = component.attribute_domain_size(domain);
-
- /* Hash the reserved name attribute "id" as a (hopefully) stable seed for each point. */
- GVArrayPtr hash_attribute = component.attribute_try_get_for_read("id", domain);
- Array<uint32_t> hashes(domain_size);
- if (hash_attribute) {
- BLI_assert(hashes.size() == hash_attribute->size());
- const CPPType &cpp_type = hash_attribute->type();
- BLI_assert(cpp_type.is_hashable());
- GVArray_GSpan items{*hash_attribute};
- threading::parallel_for(hashes.index_range(), 512, [&](IndexRange range) {
- for (const int i : range) {
- hashes[i] = cpp_type.hash(items[i]);
- }
- });
- }
- else {
- /* If there is no "id" attribute for per-point variation, just create it here. */
- RandomNumberGenerator rng(0);
- for (const int i : hashes.index_range()) {
- hashes[i] = rng.get_uint32();
- }
- }
-
- return hashes;
-}
-
static AttributeDomain get_result_domain(const GeometryComponent &component,
const GeoNodeExecParams &params,
const StringRef name)
@@ -280,7 +282,7 @@ static void randomize_attribute_on_component(GeometryComponent &component,
attribute.save();
}
-static void geo_node_legacy_random_attribute_exec(GeoNodeExecParams params)
+static void node_geo_exec(GeoNodeExecParams params)
{
GeometrySet geometry_set = params.extract_input<GeometrySet>("Geometry");
const std::string attribute_name = params.get_input<std::string>("Attribute");
@@ -324,20 +326,22 @@ static void geo_node_legacy_random_attribute_exec(GeoNodeExecParams params)
params.set_output("Geometry", geometry_set);
}
-} // namespace blender::nodes
+} // namespace blender::nodes::node_geo_legacy_attribute_randomize_cc
void register_node_type_geo_legacy_attribute_randomize()
{
+ namespace file_ns = blender::nodes::node_geo_legacy_attribute_randomize_cc;
+
static bNodeType ntype;
geo_node_type_base(
&ntype, GEO_NODE_LEGACY_ATTRIBUTE_RANDOMIZE, "Attribute Randomize", NODE_CLASS_ATTRIBUTE, 0);
- node_type_init(&ntype, blender::nodes::geo_node_legacy_attribute_randomize_init);
- node_type_update(&ntype, blender::nodes::geo_node_legacy_attribute_randomize_update);
+ node_type_init(&ntype, file_ns::node_init);
+ node_type_update(&ntype, file_ns::node_update);
- ntype.declare = blender::nodes::geo_node_legacy_attribute_randomize_declare;
- ntype.geometry_node_execute = blender::nodes::geo_node_legacy_random_attribute_exec;
- ntype.draw_buttons = blender::nodes::geo_node_legacy_attribute_random_layout;
+ ntype.declare = file_ns::node_declare;
+ ntype.geometry_node_execute = file_ns::node_geo_exec;
+ ntype.draw_buttons = file_ns::node_layout;
node_type_storage(
&ntype, "NodeAttributeRandomize", node_free_standard_storage, node_copy_standard_storage);
nodeRegisterType(&ntype);
diff --git a/source/blender/nodes/geometry/nodes/legacy/node_geo_attribute_sample_texture.cc b/source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_attribute_sample_texture.cc
index 19d6ced6eb6..70fa0af956f 100644
--- a/source/blender/nodes/geometry/nodes/legacy/node_geo_attribute_sample_texture.cc
+++ b/source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_attribute_sample_texture.cc
@@ -28,9 +28,9 @@
#include "node_geometry_util.hh"
-namespace blender::nodes {
+namespace blender::nodes::node_geo_legacy_attribute_sample_texture_cc {
-static void geo_node_attribute_sample_texture_declare(NodeDeclarationBuilder &b)
+static void node_declare(NodeDeclarationBuilder &b)
{
b.add_input<decl::Geometry>(N_("Geometry"));
b.add_input<decl::Texture>(N_("Texture")).hide_label();
@@ -82,7 +82,7 @@ static void execute_on_component(GeometryComponent &component, const GeoNodeExec
return;
}
- GVArray_Typed<float3> mapping_attribute = component.attribute_get_for_read<float3>(
+ VArray<float3> mapping_attribute = component.attribute_get_for_read<float3>(
mapping_name, result_domain, {0, 0, 0});
MutableSpan<ColorGeometry4f> colors = attribute_out.as_span();
@@ -100,7 +100,7 @@ static void execute_on_component(GeometryComponent &component, const GeoNodeExec
attribute_out.save();
}
-static void geo_node_attribute_sample_texture_exec(GeoNodeExecParams params)
+static void node_geo_exec(GeoNodeExecParams params)
{
GeometrySet geometry_set = params.extract_input<GeometrySet>("Geometry");
@@ -119,10 +119,12 @@ static void geo_node_attribute_sample_texture_exec(GeoNodeExecParams params)
params.set_output("Geometry", geometry_set);
}
-} // namespace blender::nodes
+} // namespace blender::nodes::node_geo_legacy_attribute_sample_texture_cc
void register_node_type_geo_sample_texture()
{
+ namespace file_ns = blender::nodes::node_geo_legacy_attribute_sample_texture_cc;
+
static bNodeType ntype;
geo_node_type_base(&ntype,
@@ -131,7 +133,7 @@ void register_node_type_geo_sample_texture()
NODE_CLASS_ATTRIBUTE,
0);
node_type_size_preset(&ntype, NODE_SIZE_LARGE);
- ntype.declare = blender::nodes::geo_node_attribute_sample_texture_declare;
- ntype.geometry_node_execute = blender::nodes::geo_node_attribute_sample_texture_exec;
+ ntype.declare = file_ns::node_declare;
+ ntype.geometry_node_execute = file_ns::node_geo_exec;
nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/geometry/nodes/legacy/node_geo_attribute_separate_xyz.cc b/source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_attribute_separate_xyz.cc
index 809e75e73a3..04de44446af 100644
--- a/source/blender/nodes/geometry/nodes/legacy/node_geo_attribute_separate_xyz.cc
+++ b/source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_attribute_separate_xyz.cc
@@ -19,9 +19,9 @@
#include "node_geometry_util.hh"
-namespace blender::nodes {
+namespace blender::nodes::node_geo_legacy_attribute_separate_xyz_cc {
-static void geo_node_attribute_separate_xyz_declare(NodeDeclarationBuilder &b)
+static void node_declare(NodeDeclarationBuilder &b)
{
b.add_input<decl::Geometry>(N_("Geometry"));
b.add_input<decl::String>(N_("Vector"));
@@ -32,16 +32,14 @@ static void geo_node_attribute_separate_xyz_declare(NodeDeclarationBuilder &b)
b.add_output<decl::Geometry>(N_("Geometry"));
}
-static void geo_node_attribute_separate_xyz_layout(uiLayout *layout,
- bContext *UNUSED(C),
- PointerRNA *ptr)
+static void node_layout(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
{
uiLayoutSetPropSep(layout, true);
uiLayoutSetPropDecorate(layout, false);
uiItemR(layout, ptr, "input_type", 0, IFACE_("Type"), ICON_NONE);
}
-static void geo_node_attribute_separate_xyz_init(bNodeTree *UNUSED(tree), bNode *node)
+static void node_init(bNodeTree *UNUSED(tree), bNode *node)
{
NodeAttributeSeparateXYZ *data = (NodeAttributeSeparateXYZ *)MEM_callocN(
sizeof(NodeAttributeSeparateXYZ), __func__);
@@ -49,11 +47,11 @@ static void geo_node_attribute_separate_xyz_init(bNodeTree *UNUSED(tree), bNode
node->storage = data;
}
-static void geo_node_attribute_separate_xyz_update(bNodeTree *UNUSED(ntree), bNode *node)
+static void node_update(bNodeTree *ntree, bNode *node)
{
NodeAttributeSeparateXYZ *node_storage = (NodeAttributeSeparateXYZ *)node->storage;
update_attribute_input_socket_availabilities(
- *node, "Vector", (GeometryNodeAttributeInputMode)node_storage->input_type);
+ *ntree, *node, "Vector", (GeometryNodeAttributeInputMode)node_storage->input_type);
}
static void extract_input(const int index, const Span<float3> &input, MutableSpan<float> result)
@@ -106,9 +104,9 @@ static void separate_attribute(GeometryComponent &component, const GeoNodeExecPa
const AttributeDomain result_domain = get_result_domain(
component, params, result_name_x, result_name_y, result_name_z);
- GVArray_Typed<float3> attribute_input = params.get_input_attribute<float3>(
+ VArray<float3> attribute_input = params.get_input_attribute<float3>(
"Vector", component, result_domain, {0, 0, 0});
- VArray_Span<float3> input_span{*attribute_input};
+ VArray_Span<float3> input_span{attribute_input};
OutputAttribute_Typed<float> attribute_result_x =
component.attribute_try_get_for_output_only<float>(result_name_x, result_domain);
@@ -132,7 +130,7 @@ static void separate_attribute(GeometryComponent &component, const GeoNodeExecPa
}
}
-static void geo_node_attribute_separate_xyz_exec(GeoNodeExecParams params)
+static void node_geo_exec(GeoNodeExecParams params)
{
GeometrySet geometry_set = params.extract_input<GeometrySet>("Geometry");
@@ -151,10 +149,12 @@ static void geo_node_attribute_separate_xyz_exec(GeoNodeExecParams params)
params.set_output("Geometry", geometry_set);
}
-} // namespace blender::nodes
+} // namespace blender::nodes::node_geo_legacy_attribute_separate_xyz_cc
void register_node_type_geo_attribute_separate_xyz()
{
+ namespace file_ns = blender::nodes::node_geo_legacy_attribute_separate_xyz_cc;
+
static bNodeType ntype;
geo_node_type_base(&ntype,
@@ -162,12 +162,12 @@ void register_node_type_geo_attribute_separate_xyz()
"Attribute Separate XYZ",
NODE_CLASS_ATTRIBUTE,
0);
- ntype.declare = blender::nodes::geo_node_attribute_separate_xyz_declare;
- node_type_init(&ntype, blender::nodes::geo_node_attribute_separate_xyz_init);
- node_type_update(&ntype, blender::nodes::geo_node_attribute_separate_xyz_update);
+ ntype.declare = file_ns::node_declare;
+ node_type_init(&ntype, file_ns::node_init);
+ node_type_update(&ntype, file_ns::node_update);
node_type_storage(
&ntype, "NodeAttributeSeparateXYZ", node_free_standard_storage, node_copy_standard_storage);
- ntype.geometry_node_execute = blender::nodes::geo_node_attribute_separate_xyz_exec;
- ntype.draw_buttons = blender::nodes::geo_node_attribute_separate_xyz_layout;
+ ntype.geometry_node_execute = file_ns::node_geo_exec;
+ ntype.draw_buttons = file_ns::node_layout;
nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/geometry/nodes/legacy/node_geo_attribute_transfer.cc b/source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_attribute_transfer.cc
index 3a9cd52661a..afdadee97c7 100644
--- a/source/blender/nodes/geometry/nodes/legacy/node_geo_attribute_transfer.cc
+++ b/source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_attribute_transfer.cc
@@ -29,9 +29,9 @@
#include "node_geometry_util.hh"
-namespace blender::nodes {
+namespace blender::nodes::node_geo_legacy_attribute_transfer_cc {
-static void geo_node_attribute_transfer_declare(NodeDeclarationBuilder &b)
+static void node_declare(NodeDeclarationBuilder &b)
{
b.add_input<decl::Geometry>(N_("Geometry"));
b.add_input<decl::Geometry>(N_("Source Geometry"));
@@ -40,9 +40,7 @@ static void geo_node_attribute_transfer_declare(NodeDeclarationBuilder &b)
b.add_output<decl::Geometry>(N_("Geometry"));
}
-static void geo_node_attribute_transfer_layout(uiLayout *layout,
- bContext *UNUSED(C),
- PointerRNA *ptr)
+static void node_layout(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
{
uiLayoutSetPropSep(layout, true);
uiLayoutSetPropDecorate(layout, false);
@@ -50,7 +48,7 @@ static void geo_node_attribute_transfer_layout(uiLayout *layout,
uiItemR(layout, ptr, "mapping", 0, IFACE_("Mapping"), ICON_NONE);
}
-static void geo_node_attribute_transfer_init(bNodeTree *UNUSED(tree), bNode *node)
+static void node_init(bNodeTree *UNUSED(tree), bNode *node)
{
NodeGeometryAttributeTransfer *data = (NodeGeometryAttributeTransfer *)MEM_callocN(
sizeof(NodeGeometryAttributeTransfer), __func__);
@@ -407,13 +405,13 @@ static void transfer_attribute_nearest(const GeometrySet &src_geometry,
if (pointcloud_distances_sq[i] < mesh_distances_sq[i]) {
/* Point-cloud point is closer. */
const int index = pointcloud_indices[i];
- pointcloud_src_attribute.varray->get(index, buffer);
+ pointcloud_src_attribute.varray.get(index, buffer);
dst_attribute->set_by_relocate(i, buffer);
}
else {
/* Mesh element is closer. */
const int index = mesh_indices[i];
- mesh_src_attribute.varray->get(index, buffer);
+ mesh_src_attribute.varray.get(index, buffer);
dst_attribute->set_by_relocate(i, buffer);
}
}
@@ -424,7 +422,7 @@ static void transfer_attribute_nearest(const GeometrySet &src_geometry,
src_name, data_type);
for (const int i : IndexRange(tot_samples)) {
const int index = pointcloud_indices[i];
- src_attribute.varray->get(index, buffer);
+ src_attribute.varray.get(index, buffer);
dst_attribute->set_by_relocate(i, buffer);
}
}
@@ -434,7 +432,7 @@ static void transfer_attribute_nearest(const GeometrySet &src_geometry,
data_type);
for (const int i : IndexRange(tot_samples)) {
const int index = mesh_indices[i];
- src_attribute.varray->get(index, buffer);
+ src_attribute.varray.get(index, buffer);
dst_attribute->set_by_relocate(i, buffer);
}
}
@@ -460,7 +458,7 @@ static void transfer_attribute(const GeoNodeExecParams &params,
const AttributeDomain dst_domain = (input_domain == ATTR_DOMAIN_AUTO) ? auto_domain :
input_domain;
- GVArray_Typed<float3> dst_positions = dst_component.attribute_get_for_read<float3>(
+ VArray<float3> dst_positions = dst_component.attribute_get_for_read<float3>(
"position", dst_domain, {0, 0, 0});
switch (mapping) {
@@ -477,7 +475,7 @@ static void transfer_attribute(const GeoNodeExecParams &params,
}
}
-static void geo_node_attribute_transfer_exec(GeoNodeExecParams params)
+static void node_geo_exec(GeoNodeExecParams params)
{
GeometrySet dst_geometry_set = params.extract_input<GeometrySet>("Geometry");
GeometrySet src_geometry_set = params.extract_input<GeometrySet>("Source Geometry");
@@ -510,21 +508,23 @@ static void geo_node_attribute_transfer_exec(GeoNodeExecParams params)
params.set_output("Geometry", dst_geometry_set);
}
-} // namespace blender::nodes
+} // namespace blender::nodes::node_geo_legacy_attribute_transfer_cc
void register_node_type_geo_legacy_attribute_transfer()
{
+ namespace file_ns = blender::nodes::node_geo_legacy_attribute_transfer_cc;
+
static bNodeType ntype;
geo_node_type_base(
&ntype, GEO_NODE_LEGACY_ATTRIBUTE_TRANSFER, "Attribute Transfer", NODE_CLASS_ATTRIBUTE, 0);
- node_type_init(&ntype, blender::nodes::geo_node_attribute_transfer_init);
+ node_type_init(&ntype, file_ns::node_init);
node_type_storage(&ntype,
"NodeGeometryAttributeTransfer",
node_free_standard_storage,
node_copy_standard_storage);
- ntype.declare = blender::nodes::geo_node_attribute_transfer_declare;
- ntype.geometry_node_execute = blender::nodes::geo_node_attribute_transfer_exec;
- ntype.draw_buttons = blender::nodes::geo_node_attribute_transfer_layout;
+ ntype.declare = file_ns::node_declare;
+ ntype.geometry_node_execute = file_ns::node_geo_exec;
+ ntype.draw_buttons = file_ns::node_layout;
nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/geometry/nodes/legacy/node_geo_attribute_vector_math.cc b/source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_attribute_vector_math.cc
index 4c351846243..1bd1712f22d 100644
--- a/source/blender/nodes/geometry/nodes/legacy/node_geo_attribute_vector_math.cc
+++ b/source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_attribute_vector_math.cc
@@ -26,9 +26,9 @@
#include "node_geometry_util.hh"
-namespace blender::nodes {
+namespace blender::nodes::node_geo_legacy_attribute_vector_math_cc {
-static void geo_node_attribute_vector_math_declare(NodeDeclarationBuilder &b)
+static void node_declare(NodeDeclarationBuilder &b)
{
b.add_input<decl::Geometry>(N_("Geometry"));
b.add_input<decl::String>(N_("A"));
@@ -66,9 +66,7 @@ static bool operation_use_input_c(const NodeVectorMathOperation operation)
NODE_VECTOR_MATH_MULTIPLY_ADD);
}
-static void geo_node_attribute_vector_math_layout(uiLayout *layout,
- bContext *UNUSED(C),
- PointerRNA *ptr)
+static void node_layout(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
{
bNode *node = (bNode *)ptr->data;
const NodeAttributeVectorMath &node_storage = *(NodeAttributeVectorMath *)node->storage;
@@ -103,7 +101,7 @@ static CustomDataType operation_get_read_type_c(const NodeVectorMathOperation op
return CD_PROP_FLOAT3;
}
-static void geo_node_attribute_vector_math_init(bNodeTree *UNUSED(tree), bNode *node)
+static void node_init(bNodeTree *UNUSED(tree), bNode *node)
{
NodeAttributeVectorMath *data = (NodeAttributeVectorMath *)MEM_callocN(
sizeof(NodeAttributeVectorMath), __func__);
@@ -166,19 +164,21 @@ static void geo_node_vector_math_label(bNodeTree *UNUSED(ntree),
BLI_snprintf(label, maxlen, IFACE_("Vector %s"), IFACE_(name));
}
-static void geo_node_attribute_vector_math_update(bNodeTree *UNUSED(ntree), bNode *node)
+static void node_update(bNodeTree *ntree, bNode *node)
{
const NodeAttributeVectorMath *node_storage = (NodeAttributeVectorMath *)node->storage;
const NodeVectorMathOperation operation = (const NodeVectorMathOperation)node_storage->operation;
update_attribute_input_socket_availabilities(
- *node, "A", (GeometryNodeAttributeInputMode)node_storage->input_type_a);
+ *ntree, *node, "A", (GeometryNodeAttributeInputMode)node_storage->input_type_a);
update_attribute_input_socket_availabilities(
+ *ntree,
*node,
"B",
(GeometryNodeAttributeInputMode)node_storage->input_type_b,
operation_use_input_b(operation));
update_attribute_input_socket_availabilities(
+ *ntree,
*node,
"C",
(GeometryNodeAttributeInputMode)node_storage->input_type_c,
@@ -187,7 +187,7 @@ static void geo_node_attribute_vector_math_update(bNodeTree *UNUSED(ntree), bNod
static void do_math_operation_fl3_fl3_to_fl3(const VArray<float3> &input_a,
const VArray<float3> &input_b,
- VMutableArray<float3> &result,
+ const VMutableArray<float3> &result,
const NodeVectorMathOperation operation)
{
const int size = input_a.size();
@@ -218,7 +218,7 @@ static void do_math_operation_fl3_fl3_to_fl3(const VArray<float3> &input_a,
static void do_math_operation_fl3_fl3_fl3_to_fl3(const VArray<float3> &input_a,
const VArray<float3> &input_b,
const VArray<float3> &input_c,
- VMutableArray<float3> &result,
+ const VMutableArray<float3> &result,
const NodeVectorMathOperation operation)
{
const int size = input_a.size();
@@ -251,7 +251,7 @@ static void do_math_operation_fl3_fl3_fl3_to_fl3(const VArray<float3> &input_a,
static void do_math_operation_fl3_fl3_fl_to_fl3(const VArray<float3> &input_a,
const VArray<float3> &input_b,
const VArray<float> &input_c,
- VMutableArray<float3> &result,
+ const VMutableArray<float3> &result,
const NodeVectorMathOperation operation)
{
const int size = input_a.size();
@@ -283,7 +283,7 @@ static void do_math_operation_fl3_fl3_fl_to_fl3(const VArray<float3> &input_a,
static void do_math_operation_fl3_fl3_to_fl(const VArray<float3> &input_a,
const VArray<float3> &input_b,
- VMutableArray<float> &result,
+ const VMutableArray<float> &result,
const NodeVectorMathOperation operation)
{
const int size = input_a.size();
@@ -313,7 +313,7 @@ static void do_math_operation_fl3_fl3_to_fl(const VArray<float3> &input_a,
static void do_math_operation_fl3_fl_to_fl3(const VArray<float3> &input_a,
const VArray<float> &input_b,
- VMutableArray<float3> &result,
+ const VMutableArray<float3> &result,
const NodeVectorMathOperation operation)
{
const int size = input_a.size();
@@ -342,7 +342,7 @@ static void do_math_operation_fl3_fl_to_fl3(const VArray<float3> &input_a,
}
static void do_math_operation_fl3_to_fl3(const VArray<float3> &input_a,
- VMutableArray<float3> &result,
+ const VMutableArray<float3> &result,
const NodeVectorMathOperation operation)
{
const int size = input_a.size();
@@ -369,7 +369,7 @@ static void do_math_operation_fl3_to_fl3(const VArray<float3> &input_a,
}
static void do_math_operation_fl3_to_fl(const VArray<float3> &input_a,
- VMutableArray<float> &result,
+ const VMutableArray<float> &result,
const NodeVectorMathOperation operation)
{
const int size = input_a.size();
@@ -437,13 +437,13 @@ static void attribute_vector_math_calc(GeometryComponent &component,
const AttributeDomain result_domain = get_result_domain(
component, params, operation, result_name);
- GVArrayPtr attribute_a = params.get_input_attribute(
+ GVArray attribute_a = params.get_input_attribute(
"A", component, result_domain, read_type_a, nullptr);
if (!attribute_a) {
return;
}
- GVArrayPtr attribute_b;
- GVArrayPtr attribute_c;
+ GVArray attribute_b;
+ GVArray attribute_c;
if (use_input_b) {
attribute_b = params.get_input_attribute("B", component, result_domain, read_type_b, nullptr);
if (!attribute_b) {
@@ -476,26 +476,26 @@ static void attribute_vector_math_calc(GeometryComponent &component,
case NODE_VECTOR_MATH_MODULO:
case NODE_VECTOR_MATH_MINIMUM:
case NODE_VECTOR_MATH_MAXIMUM:
- do_math_operation_fl3_fl3_to_fl3(attribute_a->typed<float3>(),
- attribute_b->typed<float3>(),
- attribute_result->typed<float3>(),
+ do_math_operation_fl3_fl3_to_fl3(attribute_a.typed<float3>(),
+ attribute_b.typed<float3>(),
+ attribute_result.varray().typed<float3>(),
operation);
break;
case NODE_VECTOR_MATH_DOT_PRODUCT:
case NODE_VECTOR_MATH_DISTANCE:
- do_math_operation_fl3_fl3_to_fl(attribute_a->typed<float3>(),
- attribute_b->typed<float3>(),
- attribute_result->typed<float>(),
+ do_math_operation_fl3_fl3_to_fl(attribute_a.typed<float3>(),
+ attribute_b.typed<float3>(),
+ attribute_result.varray().typed<float>(),
operation);
break;
case NODE_VECTOR_MATH_LENGTH:
do_math_operation_fl3_to_fl(
- attribute_a->typed<float3>(), attribute_result->typed<float>(), operation);
+ attribute_a.typed<float3>(), attribute_result.varray().typed<float>(), operation);
break;
case NODE_VECTOR_MATH_SCALE:
- do_math_operation_fl3_fl_to_fl3(attribute_a->typed<float3>(),
- attribute_b->typed<float>(),
- attribute_result->typed<float3>(),
+ do_math_operation_fl3_fl_to_fl3(attribute_a.typed<float3>(),
+ attribute_b.typed<float>(),
+ attribute_result.varray().typed<float3>(),
operation);
break;
case NODE_VECTOR_MATH_NORMALIZE:
@@ -507,29 +507,29 @@ static void attribute_vector_math_calc(GeometryComponent &component,
case NODE_VECTOR_MATH_COSINE:
case NODE_VECTOR_MATH_TANGENT:
do_math_operation_fl3_to_fl3(
- attribute_a->typed<float3>(), attribute_result->typed<float3>(), operation);
+ attribute_a.typed<float3>(), attribute_result.varray().typed<float3>(), operation);
break;
case NODE_VECTOR_MATH_WRAP:
case NODE_VECTOR_MATH_FACEFORWARD:
case NODE_VECTOR_MATH_MULTIPLY_ADD:
- do_math_operation_fl3_fl3_fl3_to_fl3(attribute_a->typed<float3>(),
- attribute_b->typed<float3>(),
- attribute_c->typed<float3>(),
- attribute_result->typed<float3>(),
+ do_math_operation_fl3_fl3_fl3_to_fl3(attribute_a.typed<float3>(),
+ attribute_b.typed<float3>(),
+ attribute_c.typed<float3>(),
+ attribute_result.varray().typed<float3>(),
operation);
break;
case NODE_VECTOR_MATH_REFRACT:
- do_math_operation_fl3_fl3_fl_to_fl3(attribute_a->typed<float3>(),
- attribute_b->typed<float3>(),
- attribute_c->typed<float>(),
- attribute_result->typed<float3>(),
+ do_math_operation_fl3_fl3_fl_to_fl3(attribute_a.typed<float3>(),
+ attribute_b.typed<float3>(),
+ attribute_c.typed<float>(),
+ attribute_result.varray().typed<float3>(),
operation);
break;
}
attribute_result.save();
}
-static void geo_node_attribute_vector_math_exec(GeoNodeExecParams params)
+static void node_geo_exec(GeoNodeExecParams params)
{
GeometrySet geometry_set = params.extract_input<GeometrySet>("Geometry");
@@ -549,10 +549,12 @@ static void geo_node_attribute_vector_math_exec(GeoNodeExecParams params)
params.set_output("Geometry", geometry_set);
}
-} // namespace blender::nodes
+} // namespace blender::nodes::node_geo_legacy_attribute_vector_math_cc
void register_node_type_geo_attribute_vector_math()
{
+ namespace file_ns = blender::nodes::node_geo_legacy_attribute_vector_math_cc;
+
static bNodeType ntype;
geo_node_type_base(&ntype,
@@ -560,12 +562,12 @@ void register_node_type_geo_attribute_vector_math()
"Attribute Vector Math",
NODE_CLASS_ATTRIBUTE,
0);
- ntype.declare = blender::nodes::geo_node_attribute_vector_math_declare;
- ntype.geometry_node_execute = blender::nodes::geo_node_attribute_vector_math_exec;
- ntype.draw_buttons = blender::nodes::geo_node_attribute_vector_math_layout;
- node_type_label(&ntype, blender::nodes::geo_node_vector_math_label);
- node_type_update(&ntype, blender::nodes::geo_node_attribute_vector_math_update);
- node_type_init(&ntype, blender::nodes::geo_node_attribute_vector_math_init);
+ ntype.declare = file_ns::node_declare;
+ ntype.geometry_node_execute = file_ns::node_geo_exec;
+ ntype.draw_buttons = file_ns::node_layout;
+ node_type_label(&ntype, file_ns::geo_node_vector_math_label);
+ node_type_update(&ntype, file_ns::node_update);
+ node_type_init(&ntype, file_ns::node_init);
node_type_storage(
&ntype, "NodeAttributeVectorMath", node_free_standard_storage, node_copy_standard_storage);
diff --git a/source/blender/nodes/geometry/nodes/legacy/node_geo_attribute_vector_rotate.cc b/source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_attribute_vector_rotate.cc
index 9ab8ec25fb6..309518e58ce 100644
--- a/source/blender/nodes/geometry/nodes/legacy/node_geo_attribute_vector_rotate.cc
+++ b/source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_attribute_vector_rotate.cc
@@ -21,9 +21,9 @@
#include "UI_interface.h"
#include "UI_resources.h"
-namespace blender::nodes {
+namespace blender::nodes::node_geo_legacy_attribute_vector_rotate_cc {
-static void geo_node_attribute_vector_rotate_declare(NodeDeclarationBuilder &b)
+static void node_declare(NodeDeclarationBuilder &b)
{
b.add_input<decl::Geometry>(N_("Geometry"));
b.add_input<decl::String>(N_("Vector"));
@@ -42,9 +42,7 @@ static void geo_node_attribute_vector_rotate_declare(NodeDeclarationBuilder &b)
b.add_output<decl::Geometry>(N_("Geometry"));
}
-static void geo_node_attribute_vector_rotate_layout(uiLayout *layout,
- bContext *UNUSED(C),
- PointerRNA *ptr)
+static void node_layout(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
{
bNode *node = (bNode *)ptr->data;
const NodeAttributeVectorRotate &node_storage = *(NodeAttributeVectorRotate *)node->storage;
@@ -70,27 +68,30 @@ static void geo_node_attribute_vector_rotate_layout(uiLayout *layout,
}
}
-static void geo_node_attribute_vector_rotate_update(bNodeTree *UNUSED(ntree), bNode *node)
+static void node_update(bNodeTree *ntree, bNode *node)
{
const NodeAttributeVectorRotate *node_storage = (NodeAttributeVectorRotate *)node->storage;
const GeometryNodeAttributeVectorRotateMode mode = (const GeometryNodeAttributeVectorRotateMode)
node_storage->mode;
update_attribute_input_socket_availabilities(
- *node, "Vector", (GeometryNodeAttributeInputMode)node_storage->input_type_vector);
+ *ntree, *node, "Vector", (GeometryNodeAttributeInputMode)node_storage->input_type_vector);
update_attribute_input_socket_availabilities(
- *node, "Center", (GeometryNodeAttributeInputMode)node_storage->input_type_center);
+ *ntree, *node, "Center", (GeometryNodeAttributeInputMode)node_storage->input_type_center);
update_attribute_input_socket_availabilities(
+ *ntree,
*node,
"Axis",
(GeometryNodeAttributeInputMode)node_storage->input_type_axis,
(mode == GEO_NODE_VECTOR_ROTATE_TYPE_AXIS));
update_attribute_input_socket_availabilities(
+ *ntree,
*node,
"Angle",
(GeometryNodeAttributeInputMode)node_storage->input_type_angle,
(mode != GEO_NODE_VECTOR_ROTATE_TYPE_EULER_XYZ));
update_attribute_input_socket_availabilities(
+ *ntree,
*node,
"Rotation",
(GeometryNodeAttributeInputMode)node_storage->input_type_rotation,
@@ -109,7 +110,7 @@ static float3 vector_rotate_around_axis(const float3 vector,
return result + center;
}
-static void geo_node_attribute_vector_rotate_init(bNodeTree *UNUSED(ntree), bNode *node)
+static void node_init(bNodeTree *UNUSED(ntree), bNode *node)
{
NodeAttributeVectorRotate *node_storage = (NodeAttributeVectorRotate *)MEM_callocN(
sizeof(NodeAttributeVectorRotate), __func__);
@@ -220,12 +221,12 @@ static void execute_on_component(const GeoNodeExecParams &params, GeometryCompon
const AttributeDomain result_domain = get_result_domain(component, params, result_name);
const bool invert = params.get_input<bool>("Invert");
- GVArrayPtr attribute_vector = params.get_input_attribute(
+ GVArray attribute_vector = params.get_input_attribute(
"Vector", component, result_domain, CD_PROP_FLOAT3, nullptr);
if (!attribute_vector) {
return;
}
- GVArrayPtr attribute_center = params.get_input_attribute(
+ GVArray attribute_center = params.get_input_attribute(
"Center", component, result_domain, CD_PROP_FLOAT3, nullptr);
if (!attribute_center) {
return;
@@ -238,21 +239,21 @@ static void execute_on_component(const GeoNodeExecParams &params, GeometryCompon
}
if (mode == GEO_NODE_VECTOR_ROTATE_TYPE_EULER_XYZ) {
- GVArrayPtr attribute_rotation = params.get_input_attribute(
+ GVArray attribute_rotation = params.get_input_attribute(
"Rotation", component, result_domain, CD_PROP_FLOAT3, nullptr);
if (!attribute_rotation) {
return;
}
- do_vector_rotate_euler(attribute_vector->typed<float3>(),
- attribute_center->typed<float3>(),
- attribute_rotation->typed<float3>(),
+ do_vector_rotate_euler(attribute_vector.typed<float3>(),
+ attribute_center.typed<float3>(),
+ attribute_rotation.typed<float3>(),
attribute_result.as_span<float3>(),
invert);
attribute_result.save();
return;
}
- GVArrayPtr attribute_angle = params.get_input_attribute(
+ GVArray attribute_angle = params.get_input_attribute(
"Angle", component, result_domain, CD_PROP_FLOAT, nullptr);
if (!attribute_angle) {
return;
@@ -260,40 +261,40 @@ static void execute_on_component(const GeoNodeExecParams &params, GeometryCompon
switch (mode) {
case GEO_NODE_VECTOR_ROTATE_TYPE_AXIS: {
- GVArrayPtr attribute_axis = params.get_input_attribute(
+ GVArray attribute_axis = params.get_input_attribute(
"Axis", component, result_domain, CD_PROP_FLOAT3, nullptr);
if (!attribute_axis) {
return;
}
- do_vector_rotate_around_axis(attribute_vector->typed<float3>(),
- attribute_center->typed<float3>(),
- attribute_axis->typed<float3>(),
- attribute_angle->typed<float>(),
+ do_vector_rotate_around_axis(attribute_vector.typed<float3>(),
+ attribute_center.typed<float3>(),
+ attribute_axis.typed<float3>(),
+ attribute_angle.typed<float>(),
attribute_result.as_span<float3>(),
invert);
} break;
case GEO_NODE_VECTOR_ROTATE_TYPE_AXIS_X:
- do_vector_rotate_around_fixed_axis(attribute_vector->typed<float3>(),
- attribute_center->typed<float3>(),
+ do_vector_rotate_around_fixed_axis(attribute_vector.typed<float3>(),
+ attribute_center.typed<float3>(),
float3(1.0f, 0.0f, 0.0f),
- attribute_angle->typed<float>(),
+ attribute_angle.typed<float>(),
attribute_result.as_span<float3>(),
invert);
break;
case GEO_NODE_VECTOR_ROTATE_TYPE_AXIS_Y:
- do_vector_rotate_around_fixed_axis(attribute_vector->typed<float3>(),
- attribute_center->typed<float3>(),
+ do_vector_rotate_around_fixed_axis(attribute_vector.typed<float3>(),
+ attribute_center.typed<float3>(),
float3(0.0f, 1.0f, 0.0f),
- attribute_angle->typed<float>(),
+ attribute_angle.typed<float>(),
attribute_result.as_span<float3>(),
invert);
break;
case GEO_NODE_VECTOR_ROTATE_TYPE_AXIS_Z:
- do_vector_rotate_around_fixed_axis(attribute_vector->typed<float3>(),
- attribute_center->typed<float3>(),
+ do_vector_rotate_around_fixed_axis(attribute_vector.typed<float3>(),
+ attribute_center.typed<float3>(),
float3(0.0f, 0.0f, 1.0f),
- attribute_angle->typed<float>(),
+ attribute_angle.typed<float>(),
attribute_result.as_span<float3>(),
invert);
@@ -306,7 +307,7 @@ static void execute_on_component(const GeoNodeExecParams &params, GeometryCompon
attribute_result.save();
}
-static void geo_node_attribute_vector_rotate_exec(GeoNodeExecParams params)
+static void node_geo_exec(GeoNodeExecParams params)
{
GeometrySet geometry_set = params.extract_input<GeometrySet>("Geometry");
@@ -325,10 +326,12 @@ static void geo_node_attribute_vector_rotate_exec(GeoNodeExecParams params)
params.set_output("Geometry", std::move(geometry_set));
}
-} // namespace blender::nodes
+} // namespace blender::nodes::node_geo_legacy_attribute_vector_rotate_cc
void register_node_type_geo_attribute_vector_rotate()
{
+ namespace file_ns = blender::nodes::node_geo_legacy_attribute_vector_rotate_cc;
+
static bNodeType ntype;
geo_node_type_base(&ntype,
@@ -336,13 +339,13 @@ void register_node_type_geo_attribute_vector_rotate()
"Attribute Vector Rotate",
NODE_CLASS_ATTRIBUTE,
0);
- node_type_update(&ntype, blender::nodes::geo_node_attribute_vector_rotate_update);
- node_type_init(&ntype, blender::nodes::geo_node_attribute_vector_rotate_init);
+ node_type_update(&ntype, file_ns::node_update);
+ node_type_init(&ntype, file_ns::node_init);
node_type_size(&ntype, 165, 100, 600);
node_type_storage(
&ntype, "NodeAttributeVectorRotate", node_free_standard_storage, node_copy_standard_storage);
- ntype.geometry_node_execute = blender::nodes::geo_node_attribute_vector_rotate_exec;
- ntype.draw_buttons = blender::nodes::geo_node_attribute_vector_rotate_layout;
- ntype.declare = blender::nodes::geo_node_attribute_vector_rotate_declare;
+ ntype.geometry_node_execute = file_ns::node_geo_exec;
+ ntype.draw_buttons = file_ns::node_layout;
+ ntype.declare = file_ns::node_declare;
nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/geometry/nodes/legacy/node_geo_curve_endpoints.cc b/source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_curve_endpoints.cc
index 8b81008ff34..184f39ba094 100644
--- a/source/blender/nodes/geometry/nodes/legacy/node_geo_curve_endpoints.cc
+++ b/source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_curve_endpoints.cc
@@ -25,9 +25,9 @@
#include "node_geometry_util.hh"
-namespace blender::nodes {
+namespace blender::nodes::node_geo_legacy_curve_endpoints_cc {
-static void geo_node_curve_endpoints_declare(NodeDeclarationBuilder &b)
+static void node_declare(NodeDeclarationBuilder &b)
{
b.add_input<decl::Geometry>(N_("Geometry"));
b.add_output<decl::Geometry>(N_("Start Points"));
@@ -61,7 +61,7 @@ static void copy_spline_domain_attributes(const CurveComponent &curve_component,
if (meta_data.domain != ATTR_DOMAIN_CURVE) {
return true;
}
- GVArrayPtr spline_attribute = curve_component.attribute_get_for_read(
+ GVArray spline_attribute = curve_component.attribute_get_for_read(
attribute_id, ATTR_DOMAIN_CURVE, meta_data.data_type);
OutputAttribute result_attribute = points.attribute_try_get_for_output_only(
@@ -70,7 +70,7 @@ static void copy_spline_domain_attributes(const CurveComponent &curve_component,
/* Only copy the attributes of splines in the offsets. */
for (const int i : offsets.index_range()) {
- spline_attribute->get(offsets[i], result[i]);
+ spline_attribute.get(offsets[i], result[i]);
}
result_attribute.save();
@@ -130,7 +130,7 @@ static void copy_endpoint_attributes(Span<SplinePtr> splines,
BLI_assert(spline.attributes.get_for_read(attribute_id));
GSpan spline_span = *spline.attributes.get_for_read(attribute_id);
- blender::fn::GVArray_For_GSpan(spline_span).get(0, point_span[i]);
+ spline_span.type().copy_assign(spline_span[0], point_span[i]);
}
for (const auto item : end_data.point_attributes.items()) {
@@ -139,13 +139,13 @@ static void copy_endpoint_attributes(Span<SplinePtr> splines,
BLI_assert(spline.attributes.get_for_read(attribute_id));
GSpan spline_span = *spline.attributes.get_for_read(attribute_id);
- blender::fn::GVArray_For_GSpan(spline_span).get(spline.size() - 1, point_span[i]);
+ spline_span.type().copy_assign(spline_span[spline.size() - 1], point_span[i]);
}
}
});
}
-static void geo_node_curve_endpoints_exec(GeoNodeExecParams params)
+static void node_geo_exec(GeoNodeExecParams params)
{
GeometrySet geometry_set = params.extract_input<GeometrySet>("Geometry");
@@ -206,16 +206,18 @@ static void geo_node_curve_endpoints_exec(GeoNodeExecParams params)
params.set_output("End Points", std::move(end_result));
}
-} // namespace blender::nodes
+} // namespace blender::nodes::node_geo_legacy_curve_endpoints_cc
void register_node_type_geo_legacy_curve_endpoints()
{
+ namespace file_ns = blender::nodes::node_geo_legacy_curve_endpoints_cc;
+
static bNodeType ntype;
geo_node_type_base(
&ntype, GEO_NODE_LEGACY_CURVE_ENDPOINTS, "Curve Endpoints", NODE_CLASS_GEOMETRY, 0);
- ntype.declare = blender::nodes::geo_node_curve_endpoints_declare;
- ntype.geometry_node_execute = blender::nodes::geo_node_curve_endpoints_exec;
+ ntype.declare = file_ns::node_declare;
+ ntype.geometry_node_execute = file_ns::node_geo_exec;
nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/geometry/nodes/legacy/node_geo_curve_reverse.cc b/source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_curve_reverse.cc
index ba76fafe3e6..cfc67e13a8d 100644
--- a/source/blender/nodes/geometry/nodes/legacy/node_geo_curve_reverse.cc
+++ b/source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_curve_reverse.cc
@@ -20,16 +20,16 @@
#include "node_geometry_util.hh"
-namespace blender::nodes {
+namespace blender::nodes::node_geo_legacy_curve_reverse_cc {
-static void geo_node_curve_reverse_declare(NodeDeclarationBuilder &b)
+static void node_declare(NodeDeclarationBuilder &b)
{
b.add_input<decl::Geometry>(N_("Curve"));
b.add_input<decl::String>(N_("Selection"));
b.add_output<decl::Geometry>(N_("Curve"));
}
-static void geo_node_curve_reverse_exec(GeoNodeExecParams params)
+static void node_geo_exec(GeoNodeExecParams params)
{
GeometrySet geometry_set = params.extract_input<GeometrySet>("Curve");
geometry_set = bke::geometry_set_realize_instances(geometry_set);
@@ -44,7 +44,7 @@ static void geo_node_curve_reverse_exec(GeoNodeExecParams params)
MutableSpan<SplinePtr> splines = curve.splines();
const std::string selection_name = params.extract_input<std::string>("Selection");
- GVArray_Typed<bool> selection = curve_component.attribute_get_for_read(
+ VArray<bool> selection = curve_component.attribute_get_for_read(
selection_name, ATTR_DOMAIN_CURVE, true);
threading::parallel_for(splines.index_range(), 128, [&](IndexRange range) {
@@ -58,14 +58,16 @@ static void geo_node_curve_reverse_exec(GeoNodeExecParams params)
params.set_output("Curve", geometry_set);
}
-} // namespace blender::nodes
+} // namespace blender::nodes::node_geo_legacy_curve_reverse_cc
void register_node_type_geo_legacy_curve_reverse()
{
+ namespace file_ns = blender::nodes::node_geo_legacy_curve_reverse_cc;
+
static bNodeType ntype;
geo_node_type_base(
&ntype, GEO_NODE_LEGACY_CURVE_REVERSE, "Curve Reverse", NODE_CLASS_GEOMETRY, 0);
- ntype.declare = blender::nodes::geo_node_curve_reverse_declare;
- ntype.geometry_node_execute = blender::nodes::geo_node_curve_reverse_exec;
+ ntype.declare = file_ns::node_declare;
+ ntype.geometry_node_execute = file_ns::node_geo_exec;
nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/geometry/nodes/legacy/node_geo_curve_select_by_handle_type.cc b/source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_curve_select_by_handle_type.cc
index 40d827ae141..a839c53c855 100644
--- a/source/blender/nodes/geometry/nodes/legacy/node_geo_curve_select_by_handle_type.cc
+++ b/source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_curve_select_by_handle_type.cc
@@ -23,24 +23,22 @@
#include "node_geometry_util.hh"
-namespace blender::nodes {
+namespace blender::nodes::node_geo_legacy_curve_select_by_handle_type_cc {
-static void geo_node_select_by_handle_type_declare(NodeDeclarationBuilder &b)
+static void node_declare(NodeDeclarationBuilder &b)
{
b.add_input<decl::Geometry>(N_("Geometry"));
b.add_input<decl::String>(N_("Selection"));
b.add_output<decl::Geometry>(N_("Geometry"));
}
-static void geo_node_curve_select_by_handle_type_layout(uiLayout *layout,
- bContext *UNUSED(C),
- PointerRNA *ptr)
+static void node_layout(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
{
uiItemR(layout, ptr, "mode", UI_ITEM_R_EXPAND, nullptr, ICON_NONE);
uiItemR(layout, ptr, "handle_type", 0, "", ICON_NONE);
}
-static void geo_node_curve_select_by_handle_type_init(bNodeTree *UNUSED(tree), bNode *node)
+static void node_init(bNodeTree *UNUSED(tree), bNode *node)
{
NodeGeometryCurveSelectHandles *data = (NodeGeometryCurveSelectHandles *)MEM_callocN(
sizeof(NodeGeometryCurveSelectHandles), __func__);
@@ -94,7 +92,7 @@ static void select_curve_by_handle_type(const CurveEval &curve,
});
}
-static void geo_node_select_by_handle_type_exec(GeoNodeExecParams params)
+static void node_geo_exec(GeoNodeExecParams params)
{
const NodeGeometryCurveSelectHandles *storage =
(const NodeGeometryCurveSelectHandles *)params.node().storage;
@@ -121,10 +119,12 @@ static void geo_node_select_by_handle_type_exec(GeoNodeExecParams params)
params.set_output("Geometry", std::move(geometry_set));
}
-} // namespace blender::nodes
+} // namespace blender::nodes::node_geo_legacy_curve_select_by_handle_type_cc
void register_node_type_geo_legacy_select_by_handle_type()
{
+ namespace file_ns = blender::nodes::node_geo_legacy_curve_select_by_handle_type_cc;
+
static bNodeType ntype;
geo_node_type_base(&ntype,
@@ -132,14 +132,14 @@ void register_node_type_geo_legacy_select_by_handle_type()
"Select by Handle Type",
NODE_CLASS_GEOMETRY,
0);
- ntype.declare = blender::nodes::geo_node_select_by_handle_type_declare;
- ntype.geometry_node_execute = blender::nodes::geo_node_select_by_handle_type_exec;
- node_type_init(&ntype, blender::nodes::geo_node_curve_select_by_handle_type_init);
+ ntype.declare = file_ns::node_declare;
+ ntype.geometry_node_execute = file_ns::node_geo_exec;
+ node_type_init(&ntype, file_ns::node_init);
node_type_storage(&ntype,
"NodeGeometryCurveSelectHandles",
node_free_standard_storage,
node_copy_standard_storage);
- ntype.draw_buttons = blender::nodes::geo_node_curve_select_by_handle_type_layout;
+ ntype.draw_buttons = file_ns::node_layout;
nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/geometry/nodes/legacy/node_geo_curve_set_handles.cc b/source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_curve_set_handles.cc
index 4bac9cb976e..fbc56adf44c 100644
--- a/source/blender/nodes/geometry/nodes/legacy/node_geo_curve_set_handles.cc
+++ b/source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_curve_set_handles.cc
@@ -21,24 +21,22 @@
#include "node_geometry_util.hh"
-namespace blender::nodes {
+namespace blender::nodes::node_geo_legacy_curve_set_handles_cc {
-static void geo_node_curve_set_handles_decalre(NodeDeclarationBuilder &b)
+static void node_decalre(NodeDeclarationBuilder &b)
{
b.add_input<decl::Geometry>(N_("Curve"));
b.add_input<decl::String>(N_("Selection"));
b.add_output<decl::Geometry>(N_("Curve"));
}
-static void geo_node_curve_set_handles_layout(uiLayout *layout,
- bContext *UNUSED(C),
- PointerRNA *ptr)
+static void node_layout(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
{
uiItemR(layout, ptr, "mode", UI_ITEM_R_EXPAND, nullptr, ICON_NONE);
uiItemR(layout, ptr, "handle_type", 0, "", ICON_NONE);
}
-static void geo_node_curve_set_handles_init(bNodeTree *UNUSED(tree), bNode *node)
+static void node_init(bNodeTree *UNUSED(tree), bNode *node)
{
NodeGeometryCurveSetHandles *data = (NodeGeometryCurveSetHandles *)MEM_callocN(
sizeof(NodeGeometryCurveSetHandles), __func__);
@@ -64,7 +62,7 @@ static BezierSpline::HandleType handle_type_from_input_type(GeometryNodeCurveHan
return BezierSpline::HandleType::Auto;
}
-static void geo_node_curve_set_handles_exec(GeoNodeExecParams params)
+static void node_geo_exec(GeoNodeExecParams params)
{
const NodeGeometryCurveSetHandles *node_storage =
(NodeGeometryCurveSetHandles *)params.node().storage;
@@ -84,7 +82,7 @@ static void geo_node_curve_set_handles_exec(GeoNodeExecParams params)
MutableSpan<SplinePtr> splines = curve.splines();
const std::string selection_name = params.extract_input<std::string>("Selection");
- GVArray_Typed<bool> selection = curve_component.attribute_get_for_read(
+ VArray<bool> selection = curve_component.attribute_get_for_read(
selection_name, ATTR_DOMAIN_POINT, true);
const BezierSpline::HandleType new_handle_type = handle_type_from_input_type(type);
@@ -124,21 +122,23 @@ static void geo_node_curve_set_handles_exec(GeoNodeExecParams params)
params.set_output("Curve", geometry_set);
}
-} // namespace blender::nodes
+} // namespace blender::nodes::node_geo_legacy_curve_set_handles_cc
void register_node_type_geo_legacy_curve_set_handles()
{
+ namespace file_ns = blender::nodes::node_geo_legacy_curve_set_handles_cc;
+
static bNodeType ntype;
geo_node_type_base(
&ntype, GEO_NODE_LEGACY_CURVE_SET_HANDLES, "Set Handle Type", NODE_CLASS_GEOMETRY, 0);
- ntype.declare = blender::nodes::geo_node_curve_set_handles_decalre;
- ntype.geometry_node_execute = blender::nodes::geo_node_curve_set_handles_exec;
- node_type_init(&ntype, blender::nodes::geo_node_curve_set_handles_init);
+ ntype.declare = file_ns::node_decalre;
+ ntype.geometry_node_execute = file_ns::node_geo_exec;
+ node_type_init(&ntype, file_ns::node_init);
node_type_storage(&ntype,
"NodeGeometryCurveSetHandles",
node_free_standard_storage,
node_copy_standard_storage);
- ntype.draw_buttons = blender::nodes::geo_node_curve_set_handles_layout;
+ ntype.draw_buttons = file_ns::node_layout;
nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/geometry/nodes/legacy/node_geo_curve_spline_type.cc b/source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_curve_spline_type.cc
index df53c96e6ca..7c76f97c97f 100644
--- a/source/blender/nodes/geometry/nodes/legacy/node_geo_curve_spline_type.cc
+++ b/source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_curve_spline_type.cc
@@ -23,23 +23,21 @@
#include "node_geometry_util.hh"
-namespace blender::nodes {
+namespace blender::nodes::node_geo_legacy_curve_spline_type_cc {
-static void geo_node_legacy_curve_spline_type_declare(NodeDeclarationBuilder &b)
+static void node_declare(NodeDeclarationBuilder &b)
{
b.add_input<decl::Geometry>(N_("Curve"));
b.add_input<decl::String>(N_("Selection"));
b.add_output<decl::Geometry>(N_("Curve"));
}
-static void geo_node_legacy_curve_spline_type_layout(uiLayout *layout,
- bContext *UNUSED(C),
- PointerRNA *ptr)
+static void node_layout(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
{
uiItemR(layout, ptr, "spline_type", 0, "", ICON_NONE);
}
-static void geo_node_legacy_curve_spline_type_init(bNodeTree *UNUSED(tree), bNode *node)
+static void node_init(bNodeTree *UNUSED(tree), bNode *node)
{
NodeGeometryCurveSplineType *data = (NodeGeometryCurveSplineType *)MEM_callocN(
sizeof(NodeGeometryCurveSplineType), __func__);
@@ -238,7 +236,7 @@ static SplinePtr convert_to_nurbs(const Spline &input)
return {};
}
-static void geo_node_legacy_curve_spline_type_exec(GeoNodeExecParams params)
+static void node_geo_exec(GeoNodeExecParams params)
{
const NodeGeometryCurveSplineType *storage =
(const NodeGeometryCurveSplineType *)params.node().storage;
@@ -255,7 +253,7 @@ static void geo_node_legacy_curve_spline_type_exec(GeoNodeExecParams params)
const CurveEval &curve = *curve_component->get_for_read();
const std::string selection_name = params.extract_input<std::string>("Selection");
- GVArray_Typed<bool> selection = curve_component->attribute_get_for_read(
+ VArray<bool> selection = curve_component->attribute_get_for_read(
selection_name, ATTR_DOMAIN_CURVE, true);
std::unique_ptr<CurveEval> new_curve = std::make_unique<CurveEval>();
@@ -282,21 +280,23 @@ static void geo_node_legacy_curve_spline_type_exec(GeoNodeExecParams params)
params.set_output("Curve", GeometrySet::create_with_curve(new_curve.release()));
}
-} // namespace blender::nodes
+} // namespace blender::nodes::node_geo_legacy_curve_spline_type_cc
void register_node_type_geo_legacy_curve_spline_type()
{
+ namespace file_ns = blender::nodes::node_geo_legacy_curve_spline_type_cc;
+
static bNodeType ntype;
geo_node_type_base(
&ntype, GEO_NODE_LEGACY_CURVE_SPLINE_TYPE, "Set Spline Type", NODE_CLASS_GEOMETRY, 0);
- ntype.declare = blender::nodes::geo_node_legacy_curve_spline_type_declare;
- ntype.geometry_node_execute = blender::nodes::geo_node_legacy_curve_spline_type_exec;
- node_type_init(&ntype, blender::nodes::geo_node_legacy_curve_spline_type_init);
+ ntype.declare = file_ns::node_declare;
+ ntype.geometry_node_execute = file_ns::node_geo_exec;
+ node_type_init(&ntype, file_ns::node_init);
node_type_storage(&ntype,
"NodeGeometryCurveSplineType",
node_free_standard_storage,
node_copy_standard_storage);
- ntype.draw_buttons = blender::nodes::geo_node_legacy_curve_spline_type_layout;
+ ntype.draw_buttons = file_ns::node_layout;
nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/geometry/nodes/legacy/node_geo_curve_subdivide.cc b/source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_curve_subdivide.cc
index f9b0a9d128e..b7cddb927f8 100644
--- a/source/blender/nodes/geometry/nodes/legacy/node_geo_curve_subdivide.cc
+++ b/source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_curve_subdivide.cc
@@ -25,13 +25,9 @@
#include "node_geometry_util.hh"
-using blender::fn::GVArray_For_GSpan;
-using blender::fn::GVArray_For_Span;
-using blender::fn::GVArray_Typed;
+namespace blender::nodes::node_geo_legacy_curve_subdivide_cc {
-namespace blender::nodes {
-
-static void geo_node_curve_subdivide_declare(NodeDeclarationBuilder &b)
+static void node_declare(NodeDeclarationBuilder &b)
{
b.add_input<decl::Geometry>(N_("Geometry"));
b.add_input<decl::String>(N_("Cuts"));
@@ -39,14 +35,14 @@ static void geo_node_curve_subdivide_declare(NodeDeclarationBuilder &b)
b.add_output<decl::Geometry>(N_("Geometry"));
}
-static void geo_node_curve_subdivide_layout(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
+static void node_layout(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
{
uiLayoutSetPropSep(layout, true);
uiLayoutSetPropDecorate(layout, false);
uiItemR(layout, ptr, "cuts_type", 0, IFACE_("Cuts"), ICON_NONE);
}
-static void geo_node_curve_subdivide_init(bNodeTree *UNUSED(tree), bNode *node)
+static void node_init(bNodeTree *UNUSED(tree), bNode *node)
{
NodeGeometryCurveSubdivide *data = (NodeGeometryCurveSubdivide *)MEM_callocN(
sizeof(NodeGeometryCurveSubdivide), __func__);
@@ -55,12 +51,12 @@ static void geo_node_curve_subdivide_init(bNodeTree *UNUSED(tree), bNode *node)
node->storage = data;
}
-static void geo_node_curve_subdivide_update(bNodeTree *UNUSED(ntree), bNode *node)
+static void node_update(bNodeTree *ntree, bNode *node)
{
NodeGeometryPointTranslate &node_storage = *(NodeGeometryPointTranslate *)node->storage;
update_attribute_input_socket_availabilities(
- *node, "Cuts", (GeometryNodeAttributeInputMode)node_storage.input_type);
+ *ntree, *node, "Cuts", (GeometryNodeAttributeInputMode)node_storage.input_type);
}
static Array<int> get_subdivided_offsets(const Spline &spline,
@@ -351,7 +347,7 @@ static std::unique_ptr<CurveEval> subdivide_curve(const CurveEval &input_curve,
return output_curve;
}
-static void geo_node_subdivide_exec(GeoNodeExecParams params)
+static void node_geo_exec(GeoNodeExecParams params)
{
GeometrySet geometry_set = params.extract_input<GeometrySet>("Geometry");
@@ -363,34 +359,35 @@ static void geo_node_subdivide_exec(GeoNodeExecParams params)
}
const CurveComponent &component = *geometry_set.get_component_for_read<CurveComponent>();
- GVArray_Typed<int> cuts = params.get_input_attribute<int>(
- "Cuts", component, ATTR_DOMAIN_POINT, 0);
- if (cuts->is_single() && cuts->get_internal_single() < 1) {
+ VArray<int> cuts = params.get_input_attribute<int>("Cuts", component, ATTR_DOMAIN_POINT, 0);
+ if (cuts.is_single() && cuts.get_internal_single() < 1) {
params.set_output("Geometry", geometry_set);
return;
}
- std::unique_ptr<CurveEval> output_curve = subdivide_curve(*component.get_for_read(), *cuts);
+ std::unique_ptr<CurveEval> output_curve = subdivide_curve(*component.get_for_read(), cuts);
params.set_output("Geometry", GeometrySet::create_with_curve(output_curve.release()));
}
-} // namespace blender::nodes
+} // namespace blender::nodes::node_geo_legacy_curve_subdivide_cc
void register_node_type_geo_legacy_curve_subdivide()
{
+ namespace file_ns = blender::nodes::node_geo_legacy_curve_subdivide_cc;
+
static bNodeType ntype;
geo_node_type_base(
&ntype, GEO_NODE_LEGACY_CURVE_SUBDIVIDE, "Curve Subdivide", NODE_CLASS_GEOMETRY, 0);
- ntype.declare = blender::nodes::geo_node_curve_subdivide_declare;
- ntype.draw_buttons = blender::nodes::geo_node_curve_subdivide_layout;
+ ntype.declare = file_ns::node_declare;
+ ntype.draw_buttons = file_ns::node_layout;
node_type_storage(&ntype,
"NodeGeometryCurveSubdivide",
node_free_standard_storage,
node_copy_standard_storage);
- node_type_init(&ntype, blender::nodes::geo_node_curve_subdivide_init);
- node_type_update(&ntype, blender::nodes::geo_node_curve_subdivide_update);
- ntype.geometry_node_execute = blender::nodes::geo_node_subdivide_exec;
+ node_type_init(&ntype, file_ns::node_init);
+ node_type_update(&ntype, file_ns::node_update);
+ ntype.geometry_node_execute = file_ns::node_geo_exec;
nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/geometry/nodes/legacy/node_geo_curve_to_points.cc b/source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_curve_to_points.cc
index c171d485a6a..a64443261ae 100644
--- a/source/blender/nodes/geometry/nodes/legacy/node_geo_curve_to_points.cc
+++ b/source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_curve_to_points.cc
@@ -28,7 +28,59 @@
namespace blender::nodes {
-static void geo_node_curve_to_points_declare(NodeDeclarationBuilder &b)
+static GMutableSpan create_attribute_and_retrieve_span(PointCloudComponent &points,
+ const AttributeIDRef &attribute_id,
+ const CustomDataType data_type)
+{
+ points.attribute_try_create(attribute_id, ATTR_DOMAIN_POINT, data_type, AttributeInitDefault());
+ WriteAttributeLookup attribute = points.attribute_try_get_for_write(attribute_id);
+ BLI_assert(attribute);
+ return attribute.varray.get_internal_span();
+}
+
+template<typename T>
+static MutableSpan<T> create_attribute_and_retrieve_span(PointCloudComponent &points,
+ const AttributeIDRef &attribute_id)
+{
+ GMutableSpan attribute = create_attribute_and_retrieve_span(
+ points, attribute_id, bke::cpp_type_to_custom_data_type(CPPType::get<T>()));
+ return attribute.typed<T>();
+}
+
+CurveToPointsResults curve_to_points_create_result_attributes(PointCloudComponent &points,
+ const CurveEval &curve)
+{
+ CurveToPointsResults attributes;
+
+ attributes.result_size = points.attribute_domain_size(ATTR_DOMAIN_POINT);
+
+ attributes.positions = create_attribute_and_retrieve_span<float3>(points, "position");
+ attributes.radii = create_attribute_and_retrieve_span<float>(points, "radius");
+ attributes.tilts = create_attribute_and_retrieve_span<float>(points, "tilt");
+
+ /* Because of the invariants of the curve component, we use the attributes of the
+ * first spline as a representative for the attribute meta data all splines. */
+ curve.splines().first()->attributes.foreach_attribute(
+ [&](const AttributeIDRef &attribute_id, const AttributeMetaData &meta_data) {
+ attributes.point_attributes.add_new(
+ attribute_id,
+ create_attribute_and_retrieve_span(points, attribute_id, meta_data.data_type));
+ return true;
+ },
+ ATTR_DOMAIN_POINT);
+
+ attributes.tangents = create_attribute_and_retrieve_span<float3>(points, "tangent");
+ attributes.normals = create_attribute_and_retrieve_span<float3>(points, "normal");
+ attributes.rotations = create_attribute_and_retrieve_span<float3>(points, "rotation");
+
+ return attributes;
+}
+
+} // namespace blender::nodes
+
+namespace blender::nodes::node_geo_legacy_curve_to_points_cc {
+
+static void node_declare(NodeDeclarationBuilder &b)
{
b.add_input<decl::Geometry>(N_("Geometry"));
b.add_input<decl::Int>(N_("Count")).default_value(10).min(2).max(100000);
@@ -36,12 +88,12 @@ static void geo_node_curve_to_points_declare(NodeDeclarationBuilder &b)
b.add_output<decl::Geometry>(N_("Geometry"));
}
-static void geo_node_curve_to_points_layout(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
+static void node_layout(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
{
uiItemR(layout, ptr, "mode", 0, "", ICON_NONE);
}
-static void geo_node_curve_to_points_init(bNodeTree *UNUSED(tree), bNode *node)
+static void node_init(bNodeTree *UNUSED(tree), bNode *node)
{
NodeGeometryCurveToPoints *data = (NodeGeometryCurveToPoints *)MEM_callocN(
sizeof(NodeGeometryCurveToPoints), __func__);
@@ -50,7 +102,7 @@ static void geo_node_curve_to_points_init(bNodeTree *UNUSED(tree), bNode *node)
node->storage = data;
}
-static void geo_node_curve_to_points_update(bNodeTree *UNUSED(ntree), bNode *node)
+static void node_update(bNodeTree *ntree, bNode *node)
{
NodeGeometryCurveToPoints &node_storage = *(NodeGeometryCurveToPoints *)node->storage;
const GeometryNodeCurveResampleMode mode = (GeometryNodeCurveResampleMode)node_storage.mode;
@@ -58,8 +110,8 @@ static void geo_node_curve_to_points_update(bNodeTree *UNUSED(ntree), bNode *nod
bNodeSocket *count_socket = ((bNodeSocket *)node->inputs.first)->next;
bNodeSocket *length_socket = count_socket->next;
- nodeSetSocketAvailability(count_socket, mode == GEO_NODE_CURVE_RESAMPLE_COUNT);
- nodeSetSocketAvailability(length_socket, mode == GEO_NODE_CURVE_RESAMPLE_LENGTH);
+ nodeSetSocketAvailability(ntree, count_socket, mode == GEO_NODE_CURVE_RESAMPLE_COUNT);
+ nodeSetSocketAvailability(ntree, length_socket, mode == GEO_NODE_CURVE_RESAMPLE_LENGTH);
}
/**
@@ -114,54 +166,6 @@ static Array<int> calculate_spline_point_offsets(GeoNodeExecParams &params,
return {0};
}
-static GMutableSpan create_attribute_and_retrieve_span(PointCloudComponent &points,
- const AttributeIDRef &attribute_id,
- const CustomDataType data_type)
-{
- points.attribute_try_create(attribute_id, ATTR_DOMAIN_POINT, data_type, AttributeInitDefault());
- WriteAttributeLookup attribute = points.attribute_try_get_for_write(attribute_id);
- BLI_assert(attribute);
- return attribute.varray->get_internal_span();
-}
-
-template<typename T>
-static MutableSpan<T> create_attribute_and_retrieve_span(PointCloudComponent &points,
- const AttributeIDRef &attribute_id)
-{
- GMutableSpan attribute = create_attribute_and_retrieve_span(
- points, attribute_id, bke::cpp_type_to_custom_data_type(CPPType::get<T>()));
- return attribute.typed<T>();
-}
-
-CurveToPointsResults curve_to_points_create_result_attributes(PointCloudComponent &points,
- const CurveEval &curve)
-{
- CurveToPointsResults attributes;
-
- attributes.result_size = points.attribute_domain_size(ATTR_DOMAIN_POINT);
-
- attributes.positions = create_attribute_and_retrieve_span<float3>(points, "position");
- attributes.radii = create_attribute_and_retrieve_span<float>(points, "radius");
- attributes.tilts = create_attribute_and_retrieve_span<float>(points, "tilt");
-
- /* Because of the invariants of the curve component, we use the attributes of the
- * first spline as a representative for the attribute meta data all splines. */
- curve.splines().first()->attributes.foreach_attribute(
- [&](const AttributeIDRef &attribute_id, const AttributeMetaData &meta_data) {
- attributes.point_attributes.add_new(
- attribute_id,
- create_attribute_and_retrieve_span(points, attribute_id, meta_data.data_type));
- return true;
- },
- ATTR_DOMAIN_POINT);
-
- attributes.tangents = create_attribute_and_retrieve_span<float3>(points, "tangent");
- attributes.normals = create_attribute_and_retrieve_span<float3>(points, "normal");
- attributes.rotations = create_attribute_and_retrieve_span<float3>(points, "rotation");
-
- return attributes;
-}
-
/**
* TODO: For non-poly splines, this has double copies that could be avoided as part
* of a general look at optimizing uses of #Spline::interpolate_to_evaluated.
@@ -177,8 +181,8 @@ static void copy_evaluated_point_attributes(Span<SplinePtr> splines,
const int size = offsets[i + 1] - offsets[i];
data.positions.slice(offset, size).copy_from(spline.evaluated_positions());
- spline.interpolate_to_evaluated(spline.radii())->materialize(data.radii.slice(offset, size));
- spline.interpolate_to_evaluated(spline.tilts())->materialize(data.tilts.slice(offset, size));
+ spline.interpolate_to_evaluated(spline.radii()).materialize(data.radii.slice(offset, size));
+ spline.interpolate_to_evaluated(spline.tilts()).materialize(data.tilts.slice(offset, size));
for (const Map<AttributeIDRef, GMutableSpan>::Item item : data.point_attributes.items()) {
const AttributeIDRef attribute_id = item.key;
@@ -188,7 +192,7 @@ static void copy_evaluated_point_attributes(Span<SplinePtr> splines,
GSpan spline_span = *spline.attributes.get_for_read(attribute_id);
spline.interpolate_to_evaluated(spline_span)
- ->materialize(point_span.slice(offset, size).data());
+ .materialize(point_span.slice(offset, size).data());
}
data.tangents.slice(offset, size).copy_from(spline.evaluated_tangents());
@@ -230,7 +234,7 @@ static void copy_uniform_sample_point_attributes(Span<SplinePtr> splines,
BLI_assert(spline.attributes.get_for_read(attribute_id));
GSpan spline_span = *spline.attributes.get_for_read(attribute_id);
- spline.sample_with_index_factors(*spline.interpolate_to_evaluated(spline_span),
+ spline.sample_with_index_factors(spline.interpolate_to_evaluated(spline_span),
uniform_samples,
point_span.slice(offset, size));
}
@@ -263,20 +267,20 @@ static void copy_spline_domain_attributes(const CurveComponent &curve_component,
if (meta_data.domain != ATTR_DOMAIN_CURVE) {
return true;
}
- GVArrayPtr spline_attribute = curve_component.attribute_get_for_read(
+ GVArray spline_attribute = curve_component.attribute_get_for_read(
attribute_id, ATTR_DOMAIN_CURVE, meta_data.data_type);
- const CPPType &type = spline_attribute->type();
+ const CPPType &type = spline_attribute.type();
OutputAttribute result_attribute = points.attribute_try_get_for_output_only(
attribute_id, ATTR_DOMAIN_POINT, meta_data.data_type);
GMutableSpan result = result_attribute.as_span();
- for (const int i : IndexRange(spline_attribute->size())) {
+ for (const int i : spline_attribute.index_range()) {
const int offset = offsets[i];
const int size = offsets[i + 1] - offsets[i];
if (size != 0) {
BUFFER_FOR_CPP_TYPE_VALUE(type, buffer);
- spline_attribute->get(i, buffer);
+ spline_attribute.get(i, buffer);
type.fill_assign_n(buffer, result[offset], size);
}
}
@@ -286,7 +290,7 @@ static void copy_spline_domain_attributes(const CurveComponent &curve_component,
});
}
-static void geo_node_curve_to_points_exec(GeoNodeExecParams params)
+static void node_geo_exec(GeoNodeExecParams params)
{
NodeGeometryCurveToPoints &node_storage = *(NodeGeometryCurveToPoints *)params.node().storage;
const GeometryNodeCurveResampleMode mode = (GeometryNodeCurveResampleMode)node_storage.mode;
@@ -340,21 +344,23 @@ static void geo_node_curve_to_points_exec(GeoNodeExecParams params)
params.set_output("Geometry", std::move(result));
}
-} // namespace blender::nodes
+} // namespace blender::nodes::node_geo_legacy_curve_to_points_cc
void register_node_type_geo_legacy_curve_to_points()
{
+ namespace file_ns = blender::nodes::node_geo_legacy_curve_to_points_cc;
+
static bNodeType ntype;
geo_node_type_base(
&ntype, GEO_NODE_LEGACY_CURVE_TO_POINTS, "Curve to Points", NODE_CLASS_GEOMETRY, 0);
- ntype.declare = blender::nodes::geo_node_curve_to_points_declare;
- ntype.geometry_node_execute = blender::nodes::geo_node_curve_to_points_exec;
- ntype.draw_buttons = blender::nodes::geo_node_curve_to_points_layout;
+ ntype.declare = file_ns::node_declare;
+ ntype.geometry_node_execute = file_ns::node_geo_exec;
+ ntype.draw_buttons = file_ns::node_layout;
node_type_storage(
&ntype, "NodeGeometryCurveToPoints", node_free_standard_storage, node_copy_standard_storage);
- node_type_init(&ntype, blender::nodes::geo_node_curve_to_points_init);
- node_type_update(&ntype, blender::nodes::geo_node_curve_to_points_update);
+ node_type_init(&ntype, file_ns::node_init);
+ node_type_update(&ntype, file_ns::node_update);
nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/geometry/nodes/legacy/node_geo_delete_geometry.cc b/source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_delete_geometry.cc
index 1d76a0532a1..0ae5766a27d 100644
--- a/source/blender/nodes/geometry/nodes/legacy/node_geo_delete_geometry.cc
+++ b/source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_delete_geometry.cc
@@ -29,23 +29,23 @@
using blender::bke::CustomDataAttributes;
/* 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);
-
-namespace blender::nodes {
-
-static void geo_node_delete_geometry_declare(NodeDeclarationBuilder &b)
+void copy_masked_vertices_to_new_mesh(const Mesh &src_mesh,
+ Mesh &dst_mesh,
+ blender::Span<int> vertex_map);
+void copy_masked_edges_to_new_mesh(const Mesh &src_mesh,
+ Mesh &dst_mesh,
+ blender::Span<int> vertex_map,
+ blender::Span<int> edge_map);
+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);
+
+namespace blender::nodes::node_geo_legacy_delete_geometry_cc {
+
+static void node_declare(NodeDeclarationBuilder &b)
{
b.add_input<decl::Geometry>(N_("Geometry"));
b.add_input<decl::String>(N_("Selection"));
@@ -137,7 +137,7 @@ static std::unique_ptr<CurveEval> curve_delete(const CurveEval &input_curve,
Vector<int64_t> copied_splines;
if (input_curve.attributes.get_for_read(name)) {
- GVArray_Typed<bool> selection = input_curve.attributes.get_for_read<bool>(name, false);
+ VArray<bool> selection = input_curve.attributes.get_for_read<bool>(name, false);
for (const int i : input_splines.index_range()) {
if (selection[i] == invert) {
output_curve->add_spline(input_splines[i]->copy());
@@ -151,7 +151,7 @@ static std::unique_ptr<CurveEval> curve_delete(const CurveEval &input_curve,
for (const int i : input_splines.index_range()) {
const Spline &spline = *input_splines[i];
- GVArray_Typed<bool> selection = spline.attributes.get_for_read<bool>(name, false);
+ VArray<bool> selection = spline.attributes.get_for_read<bool>(name, false);
indices_to_copy.clear();
for (const int i_point : IndexRange(spline.size())) {
@@ -202,7 +202,7 @@ static void delete_point_cloud_selection(const PointCloudComponent &in_component
const StringRef selection_name,
const bool invert)
{
- const GVArray_Typed<bool> selection_attribute = in_component.attribute_get_for_read<bool>(
+ const VArray<bool> selection_attribute = in_component.attribute_get_for_read<bool>(
selection_name, ATTR_DOMAIN_POINT, false);
VArray_Span<bool> selection{selection_attribute};
@@ -590,7 +590,7 @@ static void delete_mesh_selection(MeshComponent &component,
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>(
+ VArray<bool> selection = component.attribute_get_for_read<bool>(
selection_name, selection_domain, false);
/* Check if there is anything to delete. */
@@ -627,7 +627,7 @@ static void delete_mesh_selection(MeshComponent &component,
component.replace(mesh_out);
}
-static void geo_node_delete_geometry_exec(GeoNodeExecParams params)
+static void node_geo_exec(GeoNodeExecParams params)
{
GeometrySet geometry_set = params.extract_input<GeometrySet>("Geometry");
geometry_set = bke::geometry_set_realize_instances(geometry_set);
@@ -662,16 +662,18 @@ static void geo_node_delete_geometry_exec(GeoNodeExecParams params)
params.set_output("Geometry", std::move(out_set));
}
-} // namespace blender::nodes
+} // namespace blender::nodes::node_geo_legacy_delete_geometry_cc
void register_node_type_geo_legacy_delete_geometry()
{
+ namespace file_ns = blender::nodes::node_geo_legacy_delete_geometry_cc;
+
static bNodeType ntype;
geo_node_type_base(
&ntype, GEO_NODE_LEGACY_DELETE_GEOMETRY, "Delete Geometry", NODE_CLASS_GEOMETRY, 0);
- ntype.declare = blender::nodes::geo_node_delete_geometry_declare;
- ntype.geometry_node_execute = blender::nodes::geo_node_delete_geometry_exec;
+ ntype.declare = file_ns::node_declare;
+ ntype.geometry_node_execute = file_ns::node_geo_exec;
nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/geometry/nodes/legacy/node_geo_edge_split.cc b/source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_edge_split.cc
index 8f2bf05d2b4..0a510105f5f 100644
--- a/source/blender/nodes/geometry/nodes/legacy/node_geo_edge_split.cc
+++ b/source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_edge_split.cc
@@ -22,9 +22,9 @@ extern "C" {
Mesh *doEdgeSplit(const Mesh *mesh, EdgeSplitModifierData *emd);
}
-namespace blender::nodes {
+namespace blender::nodes::node_geo_legacy_edge_split_cc {
-static void geo_node_edge_split_declare(NodeDeclarationBuilder &b)
+static void node_declare(NodeDeclarationBuilder &b)
{
b.add_input<decl::Geometry>(N_("Geometry"));
b.add_input<decl::Bool>(N_("Edge Angle")).default_value(true);
@@ -37,7 +37,7 @@ static void geo_node_edge_split_declare(NodeDeclarationBuilder &b)
b.add_output<decl::Geometry>(N_("Geometry"));
}
-static void geo_node_edge_split_exec(GeoNodeExecParams params)
+static void node_geo_exec(GeoNodeExecParams params)
{
GeometrySet geometry_set = params.extract_input<GeometrySet>("Geometry");
@@ -76,14 +76,16 @@ static void geo_node_edge_split_exec(GeoNodeExecParams params)
params.set_output("Geometry", std::move(geometry_set));
}
-} // namespace blender::nodes
+} // namespace blender::nodes::node_geo_legacy_edge_split_cc
void register_node_type_geo_legacy_edge_split()
{
+ namespace file_ns = blender::nodes::node_geo_legacy_edge_split_cc;
+
static bNodeType ntype;
geo_node_type_base(&ntype, GEO_NODE_LEGACY_EDGE_SPLIT, "Edge Split", NODE_CLASS_GEOMETRY, 0);
- ntype.geometry_node_execute = blender::nodes::geo_node_edge_split_exec;
- ntype.declare = blender::nodes::geo_node_edge_split_declare;
+ ntype.geometry_node_execute = file_ns::node_geo_exec;
+ ntype.declare = file_ns::node_declare;
nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/geometry/nodes/legacy/node_geo_material_assign.cc b/source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_material_assign.cc
index 333a17aa4e9..00833e81c29 100644
--- a/source/blender/nodes/geometry/nodes/legacy/node_geo_material_assign.cc
+++ b/source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_material_assign.cc
@@ -24,9 +24,9 @@
#include "BKE_material.h"
-namespace blender::nodes {
+namespace blender::nodes::node_geo_legacy_material_assign_cc {
-static void geo_node_legacy_material_assign_declare(NodeDeclarationBuilder &b)
+static void node_declare(NodeDeclarationBuilder &b)
{
b.add_input<decl::Geometry>(N_("Geometry"));
b.add_input<decl::Material>(N_("Material")).hide_label(true);
@@ -59,7 +59,7 @@ static void assign_material_to_faces(Mesh &mesh, const VArray<bool> &face_mask,
}
}
-static void geo_node_legacy_material_assign_exec(GeoNodeExecParams params)
+static void node_geo_exec(GeoNodeExecParams params)
{
Material *material = params.extract_input<Material *>("Material");
const std::string mask_name = params.extract_input<std::string>("Selection");
@@ -72,7 +72,7 @@ static void geo_node_legacy_material_assign_exec(GeoNodeExecParams params)
MeshComponent &mesh_component = geometry_set.get_component_for_write<MeshComponent>();
Mesh *mesh = mesh_component.get_for_write();
if (mesh != nullptr) {
- GVArray_Typed<bool> face_mask = mesh_component.attribute_get_for_read<bool>(
+ VArray<bool> face_mask = mesh_component.attribute_get_for_read<bool>(
mask_name, ATTR_DOMAIN_FACE, true);
assign_material_to_faces(*mesh, face_mask, material);
}
@@ -81,15 +81,17 @@ static void geo_node_legacy_material_assign_exec(GeoNodeExecParams params)
params.set_output("Geometry", std::move(geometry_set));
}
-} // namespace blender::nodes
+} // namespace blender::nodes::node_geo_legacy_material_assign_cc
void register_node_type_geo_legacy_material_assign()
{
+ namespace file_ns = blender::nodes::node_geo_legacy_material_assign_cc;
+
static bNodeType ntype;
geo_node_type_base(
&ntype, GEO_NODE_LEGACY_MATERIAL_ASSIGN, "Material Assign", NODE_CLASS_GEOMETRY, 0);
- ntype.declare = blender::nodes::geo_node_legacy_material_assign_declare;
- ntype.geometry_node_execute = blender::nodes::geo_node_legacy_material_assign_exec;
+ ntype.declare = file_ns::node_declare;
+ ntype.geometry_node_execute = file_ns::node_geo_exec;
nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/geometry/nodes/legacy/node_geo_mesh_to_curve.cc b/source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_mesh_to_curve.cc
index 9167096fd3d..e384124d3e1 100644
--- a/source/blender/nodes/geometry/nodes/legacy/node_geo_mesh_to_curve.cc
+++ b/source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_mesh_to_curve.cc
@@ -18,16 +18,16 @@
#include "node_geometry_util.hh"
-namespace blender::nodes {
+namespace blender::nodes::node_geo_legacy_mesh_to_curve_cc {
-static void geo_node_legacy_mesh_to_curve_declare(NodeDeclarationBuilder &b)
+static void node_declare(NodeDeclarationBuilder &b)
{
b.add_input<decl::Geometry>(N_("Mesh"));
b.add_input<decl::String>(N_("Selection"));
b.add_output<decl::Geometry>(N_("Curve"));
}
-static void geo_node_legacy_mesh_to_curve_exec(GeoNodeExecParams params)
+static void node_geo_exec(GeoNodeExecParams params)
{
GeometrySet geometry_set = params.extract_input<GeometrySet>("Mesh");
@@ -44,7 +44,7 @@ static void geo_node_legacy_mesh_to_curve_exec(GeoNodeExecParams params)
params.error_message_add(NodeWarningType::Error,
TIP_("No attribute with name \"") + selection_name + "\"");
}
- GVArray_Typed<bool> selection = component.attribute_get_for_read<bool>(
+ VArray<bool> selection = component.attribute_get_for_read<bool>(
selection_name, ATTR_DOMAIN_EDGE, true);
Vector<int64_t> selected_edge_indices;
@@ -65,15 +65,17 @@ static void geo_node_legacy_mesh_to_curve_exec(GeoNodeExecParams params)
params.set_output("Curve", GeometrySet::create_with_curve(curve.release()));
}
-} // namespace blender::nodes
+} // namespace blender::nodes::node_geo_legacy_mesh_to_curve_cc
void register_node_type_geo_legacy_mesh_to_curve()
{
+ namespace file_ns = blender::nodes::node_geo_legacy_mesh_to_curve_cc;
+
static bNodeType ntype;
geo_node_type_base(
&ntype, GEO_NODE_LEGACY_MESH_TO_CURVE, "Mesh to Curve", NODE_CLASS_GEOMETRY, 0);
- ntype.declare = blender::nodes::geo_node_legacy_mesh_to_curve_declare;
- ntype.geometry_node_execute = blender::nodes::geo_node_legacy_mesh_to_curve_exec;
+ ntype.declare = file_ns::node_declare;
+ ntype.geometry_node_execute = file_ns::node_geo_exec;
nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/geometry/nodes/legacy/node_geo_point_distribute.cc b/source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_point_distribute.cc
index 210757f986d..d62f3536680 100644
--- a/source/blender/nodes/geometry/nodes/legacy/node_geo_point_distribute.cc
+++ b/source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_point_distribute.cc
@@ -36,11 +36,11 @@
#include "node_geometry_util.hh"
-using blender::bke::GeometryInstanceGroup;
+namespace blender::nodes::node_geo_legacy_point_distribute_cc {
-namespace blender::nodes {
+using blender::bke::GeometryInstanceGroup;
-static void geo_node_point_distribute_declare(NodeDeclarationBuilder &b)
+static void node_declare(NodeDeclarationBuilder &b)
{
b.add_input<decl::Geometry>(N_("Geometry"));
b.add_input<decl::Float>(N_("Distance Min")).min(0.0f).max(100000.0f).subtype(PROP_DISTANCE);
@@ -54,18 +54,17 @@ static void geo_node_point_distribute_declare(NodeDeclarationBuilder &b)
b.add_output<decl::Geometry>(N_("Geometry"));
}
-static void geo_node_point_distribute_layout(uiLayout *layout,
- bContext *UNUSED(C),
- PointerRNA *ptr)
+static void node_layout(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
{
uiItemR(layout, ptr, "distribute_method", 0, "", ICON_NONE);
}
-static void node_point_distribute_update(bNodeTree *UNUSED(ntree), bNode *node)
+static void node_point_distribute_update(bNodeTree *ntree, bNode *node)
{
bNodeSocket *sock_min_dist = (bNodeSocket *)BLI_findlink(&node->inputs, 1);
- nodeSetSocketAvailability(sock_min_dist, ELEM(node->custom1, GEO_NODE_POINT_DISTRIBUTE_POISSON));
+ nodeSetSocketAvailability(
+ ntree, sock_min_dist, ELEM(node->custom1, GEO_NODE_POINT_DISTRIBUTE_POISSON));
}
/**
@@ -106,9 +105,9 @@ static void sample_mesh_surface(const Mesh &mesh,
float looptri_density_factor = 1.0f;
if (density_factors != nullptr) {
- const float v0_density_factor = std::max(0.0f, density_factors->get(v0_loop));
- const float v1_density_factor = std::max(0.0f, density_factors->get(v1_loop));
- const float v2_density_factor = std::max(0.0f, density_factors->get(v2_loop));
+ const float v0_density_factor = std::max(0.0f, (*density_factors)[v0_loop]);
+ const float v1_density_factor = std::max(0.0f, (*density_factors)[v1_loop]);
+ const float v2_density_factor = std::max(0.0f, (*density_factors)[v2_loop]);
looptri_density_factor = (v0_density_factor + v1_density_factor + v2_density_factor) / 3.0f;
}
const float area = area_tri_v3(v0_pos, v1_pos, v2_pos);
@@ -315,7 +314,7 @@ BLI_NOINLINE static void interpolate_existing_attributes(
}
const AttributeDomain source_domain = attribute_info->domain;
- GVArrayPtr source_attribute = source_component.attribute_get_for_read(
+ GVArray source_attribute = source_component.attribute_get_for_read(
attribute_id, source_domain, output_data_type, nullptr);
if (!source_attribute) {
i_instance += set_group.transforms.size();
@@ -329,7 +328,7 @@ BLI_NOINLINE static void interpolate_existing_attributes(
GMutableSpan instance_span = out_span.slice(offset, bary_coords.size());
interpolate_attribute(
- mesh, bary_coords, looptri_indices, source_domain, *source_attribute, instance_span);
+ mesh, bary_coords, looptri_indices, source_domain, source_attribute, instance_span);
i_instance++;
}
@@ -337,7 +336,7 @@ BLI_NOINLINE static void interpolate_existing_attributes(
attribute_math::convert_to_static_type(output_data_type, [&](auto dummy) {
using T = decltype(dummy);
- GVArray_Span<T> source_span{*source_attribute};
+ VArray_Span source_span{source_attribute.typed<T>()};
});
}
@@ -445,7 +444,7 @@ static void distribute_points_random(Span<GeometryInstanceGroup> set_groups,
for (const GeometryInstanceGroup &set_group : set_groups) {
const GeometrySet &set = set_group.geometry_set;
const MeshComponent &component = *set.get_component_for_read<MeshComponent>();
- GVArray_Typed<float> density_factors = component.attribute_get_for_read<float>(
+ VArray<float> density_factors = component.attribute_get_for_read<float>(
density_attribute_name, ATTR_DOMAIN_CORNER, use_one_default ? 1.0f : 0.0f);
const Mesh &mesh = *component.get_for_read();
for (const float4x4 &transform : set_group.transforms) {
@@ -455,7 +454,7 @@ static void distribute_points_random(Span<GeometryInstanceGroup> set_groups,
sample_mesh_surface(mesh,
transform,
density,
- &*density_factors,
+ &density_factors,
seed,
positions,
bary_coords,
@@ -514,7 +513,7 @@ static void distribute_points_poisson_disk(Span<GeometryInstanceGroup> set_group
const GeometrySet &set = set_group.geometry_set;
const MeshComponent &component = *set.get_component_for_read<MeshComponent>();
const Mesh &mesh = *component.get_for_read();
- const GVArray_Typed<float> density_factors = component.attribute_get_for_read<float>(
+ const VArray<float> density_factors = component.attribute_get_for_read<float>(
density_attribute_name, ATTR_DOMAIN_CORNER, use_one_default ? 1.0f : 0.0f);
for (const int UNUSED(i_set_instance) : set_group.transforms.index_range()) {
@@ -540,7 +539,7 @@ static void distribute_points_poisson_disk(Span<GeometryInstanceGroup> set_group
}
}
-static void geo_node_point_distribute_exec(GeoNodeExecParams params)
+static void node_geo_exec(GeoNodeExecParams params)
{
GeometrySet geometry_set = params.extract_input<GeometrySet>("Geometry");
@@ -654,17 +653,19 @@ static void geo_node_point_distribute_exec(GeoNodeExecParams params)
params.set_output("Geometry", std::move(geometry_set_out));
}
-} // namespace blender::nodes
+} // namespace blender::nodes::node_geo_legacy_point_distribute_cc
void register_node_type_geo_point_distribute()
{
+ namespace file_ns = blender::nodes::node_geo_legacy_point_distribute_cc;
+
static bNodeType ntype;
geo_node_type_base(
&ntype, GEO_NODE_LEGACY_POINT_DISTRIBUTE, "Point Distribute", NODE_CLASS_GEOMETRY, 0);
- node_type_update(&ntype, blender::nodes::node_point_distribute_update);
- ntype.declare = blender::nodes::geo_node_point_distribute_declare;
- ntype.geometry_node_execute = blender::nodes::geo_node_point_distribute_exec;
- ntype.draw_buttons = blender::nodes::geo_node_point_distribute_layout;
+ node_type_update(&ntype, file_ns::node_point_distribute_update);
+ ntype.declare = file_ns::node_declare;
+ ntype.geometry_node_execute = file_ns::node_geo_exec;
+ ntype.draw_buttons = file_ns::node_layout;
nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/geometry/nodes/legacy/node_geo_point_instance.cc b/source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_point_instance.cc
index ffb2a0dd7ac..be8294cda90 100644
--- a/source/blender/nodes/geometry/nodes/legacy/node_geo_point_instance.cc
+++ b/source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_point_instance.cc
@@ -24,9 +24,9 @@
#include "node_geometry_util.hh"
-namespace blender::nodes {
+namespace blender::nodes::node_geo_legacy_point_instance_cc {
-static void geo_node_point_instance_declare(NodeDeclarationBuilder &b)
+static void node_declare(NodeDeclarationBuilder &b)
{
b.add_input<decl::Geometry>(N_("Geometry"));
b.add_input<decl::Object>(N_("Object")).hide_label();
@@ -36,7 +36,7 @@ static void geo_node_point_instance_declare(NodeDeclarationBuilder &b)
b.add_output<decl::Geometry>(N_("Geometry"));
}
-static void geo_node_point_instance_layout(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
+static void node_layout(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
{
uiItemR(layout, ptr, "instance_type", 0, "", ICON_NONE);
if (RNA_enum_get(ptr, "instance_type") == GEO_NODE_POINT_INSTANCE_TYPE_COLLECTION) {
@@ -44,7 +44,7 @@ static void geo_node_point_instance_layout(uiLayout *layout, bContext *UNUSED(C)
}
}
-static void geo_node_point_instance_init(bNodeTree *UNUSED(tree), bNode *node)
+static void node_init(bNodeTree *UNUSED(tree), bNode *node)
{
NodeGeometryPointInstance *data = (NodeGeometryPointInstance *)MEM_callocN(
sizeof(NodeGeometryPointInstance), __func__);
@@ -53,7 +53,7 @@ static void geo_node_point_instance_init(bNodeTree *UNUSED(tree), bNode *node)
node->storage = data;
}
-static void geo_node_point_instance_update(bNodeTree *UNUSED(tree), bNode *node)
+static void node_update(bNodeTree *ntree, bNode *node)
{
bNodeSocket *object_socket = (bNodeSocket *)BLI_findlink(&node->inputs, 1);
bNodeSocket *collection_socket = object_socket->next;
@@ -65,12 +65,15 @@ static void geo_node_point_instance_update(bNodeTree *UNUSED(tree), bNode *node)
const bool use_whole_collection = (node_storage->flag &
GEO_NODE_POINT_INSTANCE_WHOLE_COLLECTION) != 0;
- nodeSetSocketAvailability(object_socket, type == GEO_NODE_POINT_INSTANCE_TYPE_OBJECT);
- nodeSetSocketAvailability(collection_socket, type == GEO_NODE_POINT_INSTANCE_TYPE_COLLECTION);
- nodeSetSocketAvailability(instance_geometry_socket,
- type == GEO_NODE_POINT_INSTANCE_TYPE_GEOMETRY);
+ nodeSetSocketAvailability(ntree, object_socket, type == GEO_NODE_POINT_INSTANCE_TYPE_OBJECT);
nodeSetSocketAvailability(
- seed_socket, type == GEO_NODE_POINT_INSTANCE_TYPE_COLLECTION && !use_whole_collection);
+ ntree, collection_socket, type == GEO_NODE_POINT_INSTANCE_TYPE_COLLECTION);
+ nodeSetSocketAvailability(
+ ntree, instance_geometry_socket, type == GEO_NODE_POINT_INSTANCE_TYPE_GEOMETRY);
+ nodeSetSocketAvailability(ntree,
+ seed_socket,
+ type == GEO_NODE_POINT_INSTANCE_TYPE_COLLECTION &&
+ !use_whole_collection);
}
static Vector<InstanceReference> get_instance_references__object(GeoNodeExecParams &params)
@@ -171,13 +174,12 @@ static void add_instances_from_component(InstancesComponent &instances,
const int domain_size = src_geometry.attribute_domain_size(domain);
- GVArray_Typed<float3> positions = src_geometry.attribute_get_for_read<float3>(
+ VArray<float3> positions = src_geometry.attribute_get_for_read<float3>(
"position", domain, {0, 0, 0});
- GVArray_Typed<float3> rotations = src_geometry.attribute_get_for_read<float3>(
+ VArray<float3> rotations = src_geometry.attribute_get_for_read<float3>(
"rotation", domain, {0, 0, 0});
- GVArray_Typed<float3> scales = src_geometry.attribute_get_for_read<float3>(
- "scale", domain, {1, 1, 1});
- GVArray_Typed<int> id_attribute = src_geometry.attribute_get_for_read<int>("id", domain, -1);
+ VArray<float3> scales = src_geometry.attribute_get_for_read<float3>("scale", domain, {1, 1, 1});
+ VArray<int> id_attribute = src_geometry.attribute_get_for_read<int>("id", domain, -1);
/* The initial size of the component might be non-zero if there are two component types. */
const int start_len = instances.instances_amount();
@@ -213,7 +215,7 @@ static void add_instances_from_component(InstancesComponent &instances,
}
}
-static void geo_node_point_instance_exec(GeoNodeExecParams params)
+static void node_geo_exec(GeoNodeExecParams params)
{
GeometrySet geometry_set = params.extract_input<GeometrySet>("Geometry");
GeometrySet geometry_set_out;
@@ -253,20 +255,22 @@ static void geo_node_point_instance_exec(GeoNodeExecParams params)
params.set_output("Geometry", std::move(geometry_set_out));
}
-} // namespace blender::nodes
+} // namespace blender::nodes::node_geo_legacy_point_instance_cc
void register_node_type_geo_point_instance()
{
+ namespace file_ns = blender::nodes::node_geo_legacy_point_instance_cc;
+
static bNodeType ntype;
geo_node_type_base(
&ntype, GEO_NODE_LEGACY_POINT_INSTANCE, "Point Instance", NODE_CLASS_GEOMETRY, 0);
- node_type_init(&ntype, blender::nodes::geo_node_point_instance_init);
+ node_type_init(&ntype, file_ns::node_init);
node_type_storage(
&ntype, "NodeGeometryPointInstance", node_free_standard_storage, node_copy_standard_storage);
- ntype.declare = blender::nodes::geo_node_point_instance_declare;
- ntype.draw_buttons = blender::nodes::geo_node_point_instance_layout;
- node_type_update(&ntype, blender::nodes::geo_node_point_instance_update);
- ntype.geometry_node_execute = blender::nodes::geo_node_point_instance_exec;
+ ntype.declare = file_ns::node_declare;
+ ntype.draw_buttons = file_ns::node_layout;
+ node_type_update(&ntype, file_ns::node_update);
+ ntype.geometry_node_execute = file_ns::node_geo_exec;
nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/geometry/nodes/legacy/node_geo_point_rotate.cc b/source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_point_rotate.cc
index 54d36dab98d..7cdd03baa02 100644
--- a/source/blender/nodes/geometry/nodes/legacy/node_geo_point_rotate.cc
+++ b/source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_point_rotate.cc
@@ -21,9 +21,9 @@
#include "node_geometry_util.hh"
-namespace blender::nodes {
+namespace blender::nodes::node_geo_legacy_point_rotate_cc {
-static void geo_node_point_rotate_declare(NodeDeclarationBuilder &b)
+static void node_declare(NodeDeclarationBuilder &b)
{
b.add_input<decl::Geometry>(N_("Geometry"));
b.add_input<decl::String>(N_("Axis"));
@@ -37,7 +37,7 @@ static void geo_node_point_rotate_declare(NodeDeclarationBuilder &b)
b.add_output<decl::Geometry>(N_("Geometry"));
}
-static void geo_node_point_rotate_layout(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
+static void node_layout(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
{
NodeGeometryRotatePoints *storage = (NodeGeometryRotatePoints *)((bNode *)ptr->data)->storage;
@@ -57,7 +57,7 @@ static void geo_node_point_rotate_layout(uiLayout *layout, bContext *UNUSED(C),
}
}
-static void geo_node_point_rotate_init(bNodeTree *UNUSED(ntree), bNode *node)
+static void node_init(bNodeTree *UNUSED(ntree), bNode *node)
{
NodeGeometryRotatePoints *node_storage = (NodeGeometryRotatePoints *)MEM_callocN(
sizeof(NodeGeometryRotatePoints), __func__);
@@ -71,20 +71,23 @@ static void geo_node_point_rotate_init(bNodeTree *UNUSED(ntree), bNode *node)
node->storage = node_storage;
}
-static void geo_node_point_rotate_update(bNodeTree *UNUSED(ntree), bNode *node)
+static void node_update(bNodeTree *ntree, bNode *node)
{
NodeGeometryRotatePoints *node_storage = (NodeGeometryRotatePoints *)node->storage;
update_attribute_input_socket_availabilities(
+ *ntree,
*node,
"Axis",
(GeometryNodeAttributeInputMode)node_storage->input_type_axis,
node_storage->type == GEO_NODE_POINT_ROTATE_TYPE_AXIS_ANGLE);
update_attribute_input_socket_availabilities(
+ *ntree,
*node,
"Angle",
(GeometryNodeAttributeInputMode)node_storage->input_type_angle,
node_storage->type == GEO_NODE_POINT_ROTATE_TYPE_AXIS_ANGLE);
update_attribute_input_socket_availabilities(
+ *ntree,
*node,
"Rotation",
(GeometryNodeAttributeInputMode)node_storage->input_type_rotation,
@@ -169,9 +172,9 @@ static void point_rotate_on_component(GeometryComponent &component,
const int domain_size = rotations.size();
if (storage.type == GEO_NODE_POINT_ROTATE_TYPE_AXIS_ANGLE) {
- GVArray_Typed<float3> axis = params.get_input_attribute<float3>(
+ VArray<float3> axis = params.get_input_attribute<float3>(
"Axis", component, ATTR_DOMAIN_POINT, {0, 0, 1});
- GVArray_Typed<float> angles = params.get_input_attribute<float>(
+ VArray<float> angles = params.get_input_attribute<float>(
"Angle", component, ATTR_DOMAIN_POINT, 0);
if (storage.space == GEO_NODE_POINT_ROTATE_SPACE_OBJECT) {
@@ -182,7 +185,7 @@ static void point_rotate_on_component(GeometryComponent &component,
}
}
else {
- GVArray_Typed<float3> eulers = params.get_input_attribute<float3>(
+ VArray<float3> eulers = params.get_input_attribute<float3>(
"Rotation", component, ATTR_DOMAIN_POINT, {0, 0, 0});
if (storage.space == GEO_NODE_POINT_ROTATE_SPACE_OBJECT) {
@@ -196,7 +199,7 @@ static void point_rotate_on_component(GeometryComponent &component,
rotation_attribute.save();
}
-static void geo_node_point_rotate_exec(GeoNodeExecParams params)
+static void node_geo_exec(GeoNodeExecParams params)
{
GeometrySet geometry_set = params.extract_input<GeometrySet>("Geometry");
@@ -215,19 +218,21 @@ static void geo_node_point_rotate_exec(GeoNodeExecParams params)
params.set_output("Geometry", geometry_set);
}
-} // namespace blender::nodes
+} // namespace blender::nodes::node_geo_legacy_point_rotate_cc
void register_node_type_geo_point_rotate()
{
+ namespace file_ns = blender::nodes::node_geo_legacy_point_rotate_cc;
+
static bNodeType ntype;
geo_node_type_base(&ntype, GEO_NODE_LEGACY_POINT_ROTATE, "Point Rotate", NODE_CLASS_GEOMETRY, 0);
- node_type_init(&ntype, blender::nodes::geo_node_point_rotate_init);
- node_type_update(&ntype, blender::nodes::geo_node_point_rotate_update);
+ node_type_init(&ntype, file_ns::node_init);
+ node_type_update(&ntype, file_ns::node_update);
node_type_storage(
&ntype, "NodeGeometryRotatePoints", node_free_standard_storage, node_copy_standard_storage);
- ntype.declare = blender::nodes::geo_node_point_rotate_declare;
- ntype.geometry_node_execute = blender::nodes::geo_node_point_rotate_exec;
- ntype.draw_buttons = blender::nodes::geo_node_point_rotate_layout;
+ ntype.declare = file_ns::node_declare;
+ ntype.geometry_node_execute = file_ns::node_geo_exec;
+ ntype.draw_buttons = file_ns::node_layout;
nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/geometry/nodes/legacy/node_geo_point_scale.cc b/source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_point_scale.cc
index 934442ee8a3..4a6f19b8ed2 100644
--- a/source/blender/nodes/geometry/nodes/legacy/node_geo_point_scale.cc
+++ b/source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_point_scale.cc
@@ -21,9 +21,9 @@
#include "node_geometry_util.hh"
-namespace blender::nodes {
+namespace blender::nodes::node_geo_legacy_point_scale_cc {
-static void geo_node_point_scale_declare(NodeDeclarationBuilder &b)
+static void node_declare(NodeDeclarationBuilder &b)
{
b.add_input<decl::Geometry>(N_("Geometry"));
b.add_input<decl::String>(N_("Factor"));
@@ -34,14 +34,14 @@ static void geo_node_point_scale_declare(NodeDeclarationBuilder &b)
b.add_output<decl::Geometry>(N_("Geometry"));
}
-static void geo_node_point_scale_layout(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
+static void node_layout(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
{
uiLayoutSetPropSep(layout, true);
uiLayoutSetPropDecorate(layout, false);
uiItemR(layout, ptr, "input_type", 0, IFACE_("Type"), ICON_NONE);
}
-static void geo_node_point_scale_init(bNodeTree *UNUSED(tree), bNode *node)
+static void node_init(bNodeTree *UNUSED(tree), bNode *node)
{
NodeGeometryPointScale *data = (NodeGeometryPointScale *)MEM_callocN(
sizeof(NodeGeometryPointScale), __func__);
@@ -50,12 +50,12 @@ static void geo_node_point_scale_init(bNodeTree *UNUSED(tree), bNode *node)
node->storage = data;
}
-static void geo_node_point_scale_update(bNodeTree *UNUSED(ntree), bNode *node)
+static void node_update(bNodeTree *ntree, bNode *node)
{
NodeGeometryPointScale &node_storage = *(NodeGeometryPointScale *)node->storage;
update_attribute_input_socket_availabilities(
- *node, "Factor", (GeometryNodeAttributeInputMode)node_storage.input_type);
+ *ntree, *node, "Factor", (GeometryNodeAttributeInputMode)node_storage.input_type);
}
static void execute_on_component(GeoNodeExecParams params, GeometryComponent &component)
@@ -78,7 +78,7 @@ static void execute_on_component(GeoNodeExecParams params, GeometryComponent &co
const CustomDataType data_type = (input_type == GEO_NODE_ATTRIBUTE_INPUT_FLOAT) ? CD_PROP_FLOAT :
CD_PROP_FLOAT3;
- GVArrayPtr attribute = params.get_input_attribute(
+ GVArray attribute = params.get_input_attribute(
"Factor", component, ATTR_DOMAIN_POINT, data_type, nullptr);
if (!attribute) {
return;
@@ -86,13 +86,13 @@ static void execute_on_component(GeoNodeExecParams params, GeometryComponent &co
MutableSpan<float3> scale_span = scale_attribute.as_span();
if (data_type == CD_PROP_FLOAT) {
- GVArray_Typed<float> factors{*attribute};
+ VArray<float> factors = attribute.typed<float>();
for (const int i : scale_span.index_range()) {
scale_span[i] = scale_span[i] * factors[i];
}
}
else if (data_type == CD_PROP_FLOAT3) {
- GVArray_Typed<float3> factors{*attribute};
+ VArray<float3> factors = attribute.typed<float3>();
for (const int i : scale_span.index_range()) {
scale_span[i] = scale_span[i] * factors[i];
}
@@ -101,7 +101,7 @@ static void execute_on_component(GeoNodeExecParams params, GeometryComponent &co
scale_attribute.save();
}
-static void geo_node_point_scale_exec(GeoNodeExecParams params)
+static void node_geo_exec(GeoNodeExecParams params)
{
GeometrySet geometry_set = params.extract_input<GeometrySet>("Geometry");
@@ -120,20 +120,22 @@ static void geo_node_point_scale_exec(GeoNodeExecParams params)
params.set_output("Geometry", std::move(geometry_set));
}
-} // namespace blender::nodes
+} // namespace blender::nodes::node_geo_legacy_point_scale_cc
void register_node_type_geo_point_scale()
{
+ namespace file_ns = blender::nodes::node_geo_legacy_point_scale_cc;
+
static bNodeType ntype;
geo_node_type_base(&ntype, GEO_NODE_LEGACY_POINT_SCALE, "Point Scale", NODE_CLASS_GEOMETRY, 0);
- ntype.declare = blender::nodes::geo_node_point_scale_declare;
- node_type_init(&ntype, blender::nodes::geo_node_point_scale_init);
- node_type_update(&ntype, blender::nodes::geo_node_point_scale_update);
+ ntype.declare = file_ns::node_declare;
+ node_type_init(&ntype, file_ns::node_init);
+ node_type_update(&ntype, file_ns::node_update);
node_type_storage(
&ntype, "NodeGeometryPointScale", node_free_standard_storage, node_copy_standard_storage);
- ntype.geometry_node_execute = blender::nodes::geo_node_point_scale_exec;
- ntype.draw_buttons = blender::nodes::geo_node_point_scale_layout;
+ ntype.geometry_node_execute = file_ns::node_geo_exec;
+ ntype.draw_buttons = file_ns::node_layout;
nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/geometry/nodes/legacy/node_geo_point_separate.cc b/source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_point_separate.cc
index accdaf78439..5d18abbc828 100644
--- a/source/blender/nodes/geometry/nodes/legacy/node_geo_point_separate.cc
+++ b/source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_point_separate.cc
@@ -25,14 +25,6 @@
namespace blender::nodes {
-static void geo_node_point_instance_declare(NodeDeclarationBuilder &b)
-{
- b.add_input<decl::Geometry>(N_("Geometry"));
- b.add_input<decl::String>(N_("Mask"));
- b.add_output<decl::Geometry>(N_("Geometry 1"));
- b.add_output<decl::Geometry>(N_("Geometry 2"));
-}
-
template<typename T>
static void copy_data_based_on_mask(Span<T> data,
Span<bool> masks,
@@ -55,7 +47,7 @@ void copy_point_attributes_based_on_mask(const GeometryComponent &in_component,
{
for (const AttributeIDRef &attribute_id : in_component.attribute_ids()) {
ReadAttributeLookup attribute = in_component.attribute_try_get_for_read(attribute_id);
- const CustomDataType data_type = bke::cpp_type_to_custom_data_type(attribute.varray->type());
+ const CustomDataType data_type = bke::cpp_type_to_custom_data_type(attribute.varray.type());
/* Only copy point attributes. Theoretically this could interpolate attributes on other
* domains to the point domain, but that would conflict with attributes that are built-in
@@ -69,7 +61,7 @@ void copy_point_attributes_based_on_mask(const GeometryComponent &in_component,
attribute_math::convert_to_static_type(data_type, [&](auto dummy) {
using T = decltype(dummy);
- GVArray_Span<T> span{*attribute.varray};
+ VArray_Span span{attribute.varray.typed<T>()};
MutableSpan<T> out_span = result_attribute.as_span<T>();
copy_data_based_on_mask(span, masks, invert, out_span);
});
@@ -78,6 +70,18 @@ void copy_point_attributes_based_on_mask(const GeometryComponent &in_component,
}
}
+} // namespace blender::nodes
+
+namespace blender::nodes::node_geo_legacy_point_separate_cc {
+
+static void node_declare(NodeDeclarationBuilder &b)
+{
+ b.add_input<decl::Geometry>(N_("Geometry"));
+ b.add_input<decl::String>(N_("Mask"));
+ b.add_output<decl::Geometry>(N_("Geometry 1"));
+ b.add_output<decl::Geometry>(N_("Geometry 2"));
+}
+
static void create_component_points(GeometryComponent &component, const int total)
{
switch (component.type()) {
@@ -103,7 +107,7 @@ static void separate_points_from_component(const GeometryComponent &in_component
return;
}
- const GVArray_Typed<bool> mask_attribute = in_component.attribute_get_for_read<bool>(
+ const VArray<bool> mask_attribute = in_component.attribute_get_for_read<bool>(
mask_name, ATTR_DOMAIN_POINT, false);
VArray_Span<bool> masks{mask_attribute};
@@ -133,7 +137,7 @@ static GeometrySet separate_geometry_set(const GeometrySet &set_in,
return set_out;
}
-static void geo_node_point_separate_exec(GeoNodeExecParams params)
+static void node_geo_exec(GeoNodeExecParams params)
{
bool wait_for_inputs = false;
wait_for_inputs |= params.lazy_require_input("Geometry");
@@ -158,16 +162,18 @@ static void geo_node_point_separate_exec(GeoNodeExecParams params)
}
}
-} // namespace blender::nodes
+} // namespace blender::nodes::node_geo_legacy_point_separate_cc
void register_node_type_geo_point_separate()
{
+ namespace file_ns = blender::nodes::node_geo_legacy_point_separate_cc;
+
static bNodeType ntype;
geo_node_type_base(
&ntype, GEO_NODE_LEGACY_POINT_SEPARATE, "Point Separate", NODE_CLASS_GEOMETRY, 0);
- ntype.declare = blender::nodes::geo_node_point_instance_declare;
- ntype.geometry_node_execute = blender::nodes::geo_node_point_separate_exec;
+ ntype.declare = file_ns::node_declare;
+ ntype.geometry_node_execute = file_ns::node_geo_exec;
ntype.geometry_node_execute_supports_laziness = true;
nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/geometry/nodes/legacy/node_geo_point_translate.cc b/source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_point_translate.cc
index 34f7641995f..4e18c650199 100644
--- a/source/blender/nodes/geometry/nodes/legacy/node_geo_point_translate.cc
+++ b/source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_point_translate.cc
@@ -19,9 +19,9 @@
#include "node_geometry_util.hh"
-namespace blender::nodes {
+namespace blender::nodes::node_geo_legacy_point_translate_cc {
-static void geo_node_point_translate_declare(NodeDeclarationBuilder &b)
+static void node_declare(NodeDeclarationBuilder &b)
{
b.add_input<decl::Geometry>(N_("Geometry"));
b.add_input<decl::String>(N_("Translation"));
@@ -29,7 +29,7 @@ static void geo_node_point_translate_declare(NodeDeclarationBuilder &b)
b.add_output<decl::Geometry>(N_("Geometry"));
}
-static void geo_node_point_translate_layout(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
+static void node_layout(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
{
uiLayoutSetPropSep(layout, true);
uiLayoutSetPropDecorate(layout, false);
@@ -43,17 +43,17 @@ static void execute_on_component(GeoNodeExecParams params, GeometryComponent &co
if (!position_attribute) {
return;
}
- GVArray_Typed<float3> attribute = params.get_input_attribute<float3>(
+ VArray<float3> attribute = params.get_input_attribute<float3>(
"Translation", component, ATTR_DOMAIN_POINT, {0, 0, 0});
- for (const int i : IndexRange(attribute.size())) {
+ for (const int i : attribute.index_range()) {
position_attribute->set(i, position_attribute->get(i) + attribute[i]);
}
position_attribute.save();
}
-static void geo_node_point_translate_exec(GeoNodeExecParams params)
+static void node_geo_exec(GeoNodeExecParams params)
{
GeometrySet geometry_set = params.extract_input<GeometrySet>("Geometry");
@@ -72,7 +72,7 @@ static void geo_node_point_translate_exec(GeoNodeExecParams params)
params.set_output("Geometry", std::move(geometry_set));
}
-static void geo_node_point_translate_init(bNodeTree *UNUSED(tree), bNode *node)
+static void node_init(bNodeTree *UNUSED(tree), bNode *node)
{
NodeGeometryPointTranslate *data = (NodeGeometryPointTranslate *)MEM_callocN(
sizeof(NodeGeometryPointTranslate), __func__);
@@ -81,30 +81,32 @@ static void geo_node_point_translate_init(bNodeTree *UNUSED(tree), bNode *node)
node->storage = data;
}
-static void geo_node_point_translate_update(bNodeTree *UNUSED(ntree), bNode *node)
+static void node_update(bNodeTree *ntree, bNode *node)
{
NodeGeometryPointTranslate &node_storage = *(NodeGeometryPointTranslate *)node->storage;
update_attribute_input_socket_availabilities(
- *node, "Translation", (GeometryNodeAttributeInputMode)node_storage.input_type);
+ *ntree, *node, "Translation", (GeometryNodeAttributeInputMode)node_storage.input_type);
}
-} // namespace blender::nodes
+} // namespace blender::nodes::node_geo_legacy_point_translate_cc
void register_node_type_geo_point_translate()
{
+ namespace file_ns = blender::nodes::node_geo_legacy_point_translate_cc;
+
static bNodeType ntype;
geo_node_type_base(
&ntype, GEO_NODE_LEGACY_POINT_TRANSLATE, "Point Translate", NODE_CLASS_GEOMETRY, 0);
- node_type_init(&ntype, blender::nodes::geo_node_point_translate_init);
- node_type_update(&ntype, blender::nodes::geo_node_point_translate_update);
+ node_type_init(&ntype, file_ns::node_init);
+ node_type_update(&ntype, file_ns::node_update);
node_type_storage(&ntype,
"NodeGeometryPointTranslate",
node_free_standard_storage,
node_copy_standard_storage);
- ntype.declare = blender::nodes::geo_node_point_translate_declare;
- ntype.geometry_node_execute = blender::nodes::geo_node_point_translate_exec;
- ntype.draw_buttons = blender::nodes::geo_node_point_translate_layout;
+ ntype.declare = file_ns::node_declare;
+ ntype.geometry_node_execute = file_ns::node_geo_exec;
+ ntype.draw_buttons = file_ns::node_layout;
nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/geometry/nodes/legacy/node_geo_points_to_volume.cc b/source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_points_to_volume.cc
index cf7f466c2a6..2c34d0d781e 100644
--- a/source/blender/nodes/geometry/nodes/legacy/node_geo_points_to_volume.cc
+++ b/source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_points_to_volume.cc
@@ -28,9 +28,9 @@
#include "UI_interface.h"
#include "UI_resources.h"
-namespace blender::nodes {
+namespace blender::nodes::node_geo_legacy_points_to_volume_cc {
-static void geo_node_points_to_volume_declare(NodeDeclarationBuilder &b)
+static void node_declare(NodeDeclarationBuilder &b)
{
b.add_input<decl::Geometry>(N_("Geometry"));
b.add_input<decl::Float>(N_("Density")).default_value(1.0f).min(0.0f);
@@ -41,9 +41,7 @@ static void geo_node_points_to_volume_declare(NodeDeclarationBuilder &b)
b.add_output<decl::Geometry>(N_("Geometry"));
}
-static void geo_node_points_to_volume_layout(uiLayout *layout,
- bContext *UNUSED(C),
- PointerRNA *ptr)
+static void node_layout(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
{
uiLayoutSetPropSep(layout, true);
uiLayoutSetPropDecorate(layout, false);
@@ -51,7 +49,7 @@ static void geo_node_points_to_volume_layout(uiLayout *layout,
uiItemR(layout, ptr, "input_type_radius", 0, IFACE_("Radius"), ICON_NONE);
}
-static void geo_node_points_to_volume_init(bNodeTree *UNUSED(ntree), bNode *node)
+static void node_init(bNodeTree *UNUSED(ntree), bNode *node)
{
NodeGeometryPointsToVolume *data = (NodeGeometryPointsToVolume *)MEM_callocN(
sizeof(NodeGeometryPointsToVolume), __func__);
@@ -65,19 +63,22 @@ static void geo_node_points_to_volume_init(bNodeTree *UNUSED(ntree), bNode *node
STRNCPY(radius_attribute_socket_value->value, "radius");
}
-static void geo_node_points_to_volume_update(bNodeTree *UNUSED(ntree), bNode *node)
+static void node_update(bNodeTree *ntree, bNode *node)
{
NodeGeometryPointsToVolume *data = (NodeGeometryPointsToVolume *)node->storage;
bNodeSocket *voxel_size_socket = nodeFindSocket(node, SOCK_IN, "Voxel Size");
bNodeSocket *voxel_amount_socket = nodeFindSocket(node, SOCK_IN, "Voxel Amount");
- nodeSetSocketAvailability(voxel_amount_socket,
+ nodeSetSocketAvailability(ntree,
+ voxel_amount_socket,
data->resolution_mode ==
GEO_NODE_POINTS_TO_VOLUME_RESOLUTION_MODE_AMOUNT);
- nodeSetSocketAvailability(
- voxel_size_socket, data->resolution_mode == GEO_NODE_POINTS_TO_VOLUME_RESOLUTION_MODE_SIZE);
+ nodeSetSocketAvailability(ntree,
+ voxel_size_socket,
+ data->resolution_mode ==
+ GEO_NODE_POINTS_TO_VOLUME_RESOLUTION_MODE_SIZE);
update_attribute_input_socket_availabilities(
- *node, "Radius", (GeometryNodeAttributeInputMode)data->input_type_radius);
+ *ntree, *node, "Radius", (GeometryNodeAttributeInputMode)data->input_type_radius);
}
#ifdef WITH_OPENVDB
@@ -172,12 +173,12 @@ static void gather_point_data_from_component(const GeoNodeExecParams &params,
Vector<float3> &r_positions,
Vector<float> &r_radii)
{
- GVArray_Typed<float3> positions = component.attribute_get_for_read<float3>(
+ VArray<float3> positions = component.attribute_get_for_read<float3>(
"position", ATTR_DOMAIN_POINT, {0, 0, 0});
- GVArray_Typed<float> radii = params.get_input_attribute<float>(
+ VArray<float> radii = params.get_input_attribute<float>(
"Radius", component, ATTR_DOMAIN_POINT, 0.0f);
- for (const int i : IndexRange(positions.size())) {
+ for (const int i : positions.index_range()) {
r_positions.append(positions[i]);
r_radii.append(radii[i]);
}
@@ -241,7 +242,7 @@ static void initialize_volume_component_from_points(const GeometrySet &geometry_
}
#endif
-static void geo_node_points_to_volume_exec(GeoNodeExecParams params)
+static void node_geo_exec(GeoNodeExecParams params)
{
GeometrySet geometry_set_in = params.extract_input<GeometrySet>("Geometry");
GeometrySet geometry_set_out;
@@ -256,10 +257,12 @@ static void geo_node_points_to_volume_exec(GeoNodeExecParams params)
params.set_output("Geometry", std::move(geometry_set_out));
}
-} // namespace blender::nodes
+} // namespace blender::nodes::node_geo_legacy_points_to_volume_cc
void register_node_type_geo_legacy_points_to_volume()
{
+ namespace file_ns = blender::nodes::node_geo_legacy_points_to_volume_cc;
+
static bNodeType ntype;
geo_node_type_base(
@@ -269,10 +272,10 @@ void register_node_type_geo_legacy_points_to_volume()
node_free_standard_storage,
node_copy_standard_storage);
node_type_size(&ntype, 170, 120, 700);
- node_type_init(&ntype, blender::nodes::geo_node_points_to_volume_init);
- node_type_update(&ntype, blender::nodes::geo_node_points_to_volume_update);
- ntype.declare = blender::nodes::geo_node_points_to_volume_declare;
- ntype.geometry_node_execute = blender::nodes::geo_node_points_to_volume_exec;
- ntype.draw_buttons = blender::nodes::geo_node_points_to_volume_layout;
+ node_type_init(&ntype, file_ns::node_init);
+ node_type_update(&ntype, file_ns::node_update);
+ ntype.declare = file_ns::node_declare;
+ ntype.geometry_node_execute = file_ns::node_geo_exec;
+ ntype.draw_buttons = file_ns::node_layout;
nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/geometry/nodes/legacy/node_geo_raycast.cc b/source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_raycast.cc
index e6a81fc9627..83081933c64 100644
--- a/source/blender/nodes/geometry/nodes/legacy/node_geo_raycast.cc
+++ b/source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_raycast.cc
@@ -24,9 +24,9 @@
#include "node_geometry_util.hh"
-namespace blender::nodes {
+namespace blender::nodes::node_geo_legacy_raycast_cc {
-static void geo_node_raycast_declare(NodeDeclarationBuilder &b)
+static void node_declare(NodeDeclarationBuilder &b)
{
b.add_input<decl::Geometry>(N_("Geometry"));
b.add_input<decl::Geometry>(N_("Target Geometry"));
@@ -47,7 +47,7 @@ static void geo_node_raycast_declare(NodeDeclarationBuilder &b)
b.add_output<decl::Geometry>(N_("Geometry"));
}
-static void geo_node_raycast_layout(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
+static void node_layout(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
{
uiLayoutSetPropSep(layout, true);
uiLayoutSetPropDecorate(layout, false);
@@ -56,7 +56,7 @@ static void geo_node_raycast_layout(uiLayout *layout, bContext *UNUSED(C), Point
uiItemR(layout, ptr, "input_type_ray_length", 0, IFACE_("Ray Length"), ICON_NONE);
}
-static void geo_node_raycast_init(bNodeTree *UNUSED(tree), bNode *node)
+static void node_init(bNodeTree *UNUSED(tree), bNode *node)
{
NodeGeometryRaycast *data = (NodeGeometryRaycast *)MEM_callocN(sizeof(NodeGeometryRaycast),
__func__);
@@ -65,15 +65,19 @@ static void geo_node_raycast_init(bNodeTree *UNUSED(tree), bNode *node)
node->storage = data;
}
-static void geo_node_raycast_update(bNodeTree *UNUSED(ntree), bNode *node)
+static void node_update(bNodeTree *ntree, bNode *node)
{
NodeGeometryRaycast *node_storage = (NodeGeometryRaycast *)node->storage;
update_attribute_input_socket_availabilities(
+ *ntree,
*node,
"Ray Direction",
(GeometryNodeAttributeInputMode)node_storage->input_type_ray_direction);
update_attribute_input_socket_availabilities(
- *node, "Ray Length", (GeometryNodeAttributeInputMode)node_storage->input_type_ray_length);
+ *ntree,
+ *node,
+ "Ray Length",
+ (GeometryNodeAttributeInputMode)node_storage->input_type_ray_length);
}
static void raycast_to_mesh(const Mesh &mesh,
@@ -197,11 +201,11 @@ static void raycast_from_points(const GeoNodeExecParams &params,
(GeometryNodeRaycastMapMode)storage.mapping);
const AttributeDomain result_domain = ATTR_DOMAIN_POINT;
- GVArray_Typed<float3> ray_origins = dst_component.attribute_get_for_read<float3>(
+ VArray<float3> ray_origins = dst_component.attribute_get_for_read<float3>(
"position", result_domain, {0, 0, 0});
- GVArray_Typed<float3> ray_directions = params.get_input_attribute<float3>(
+ VArray<float3> ray_directions = params.get_input_attribute<float3>(
"Ray Direction", dst_component, result_domain, {0, 0, 0});
- GVArray_Typed<float> ray_lengths = params.get_input_attribute<float>(
+ VArray<float> ray_lengths = params.get_input_attribute<float>(
"Ray Length", dst_component, result_domain, 0);
OutputAttribute_Typed<bool> hit_attribute =
@@ -218,10 +222,10 @@ static void raycast_from_points(const GeoNodeExecParams &params,
Array<int> hit_indices;
Array<float3> hit_positions_internal;
if (!hit_attribute_names.is_empty()) {
- hit_indices.reinitialize(ray_origins->size());
+ hit_indices.reinitialize(ray_origins.size());
if (!hit_position_attribute) {
- hit_positions_internal.reinitialize(ray_origins->size());
+ hit_positions_internal.reinitialize(ray_origins.size());
}
}
const MutableSpan<bool> is_hit = hit_attribute ? hit_attribute.as_span() : MutableSpan<bool>();
@@ -268,7 +272,7 @@ static void raycast_from_points(const GeoNodeExecParams &params,
}
}
-static void geo_node_raycast_exec(GeoNodeExecParams params)
+static void node_geo_exec(GeoNodeExecParams params)
{
GeometrySet geometry_set = params.extract_input<GeometrySet>("Geometry");
GeometrySet target_geometry_set = params.extract_input<GeometrySet>("Target Geometry");
@@ -303,20 +307,22 @@ static void geo_node_raycast_exec(GeoNodeExecParams params)
params.set_output("Geometry", geometry_set);
}
-} // namespace blender::nodes
+} // namespace blender::nodes::node_geo_legacy_raycast_cc
void register_node_type_geo_legacy_raycast()
{
+ namespace file_ns = blender::nodes::node_geo_legacy_raycast_cc;
+
static bNodeType ntype;
geo_node_type_base(&ntype, GEO_NODE_LEGACY_RAYCAST, "Raycast", NODE_CLASS_GEOMETRY, 0);
node_type_size_preset(&ntype, NODE_SIZE_LARGE);
- node_type_init(&ntype, blender::nodes::geo_node_raycast_init);
- node_type_update(&ntype, blender::nodes::geo_node_raycast_update);
+ node_type_init(&ntype, file_ns::node_init);
+ node_type_update(&ntype, file_ns::node_update);
node_type_storage(
&ntype, "NodeGeometryRaycast", node_free_standard_storage, node_copy_standard_storage);
- ntype.declare = blender::nodes::geo_node_raycast_declare;
- ntype.geometry_node_execute = blender::nodes::geo_node_raycast_exec;
- ntype.draw_buttons = blender::nodes::geo_node_raycast_layout;
+ ntype.declare = file_ns::node_declare;
+ ntype.geometry_node_execute = file_ns::node_geo_exec;
+ ntype.draw_buttons = file_ns::node_layout;
nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/geometry/nodes/legacy/node_geo_select_by_material.cc b/source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_select_by_material.cc
index a8d6f33a5fd..0119570b199 100644
--- a/source/blender/nodes/geometry/nodes/legacy/node_geo_select_by_material.cc
+++ b/source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_select_by_material.cc
@@ -26,9 +26,9 @@
#include "BKE_material.h"
-namespace blender::nodes {
+namespace blender::nodes::node_geo_legacy_select_by_material_cc {
-static void geo_node_legacy_select_by_material_declare(NodeDeclarationBuilder &b)
+static void node_declare(NodeDeclarationBuilder &b)
{
b.add_input<decl::Geometry>(N_("Geometry"));
b.add_input<decl::Material>(N_("Material")).hide_label();
@@ -54,7 +54,7 @@ static void select_mesh_by_material(const Mesh &mesh,
});
}
-static void geo_node_legacy_select_by_material_exec(GeoNodeExecParams params)
+static void node_geo_exec(GeoNodeExecParams params)
{
Material *material = params.extract_input<Material *>("Material");
const std::string selection_name = params.extract_input<std::string>("Selection");
@@ -78,15 +78,17 @@ static void geo_node_legacy_select_by_material_exec(GeoNodeExecParams params)
params.set_output("Geometry", std::move(geometry_set));
}
-} // namespace blender::nodes
+} // namespace blender::nodes::node_geo_legacy_select_by_material_cc
void register_node_type_geo_legacy_select_by_material()
{
+ namespace file_ns = blender::nodes::node_geo_legacy_select_by_material_cc;
+
static bNodeType ntype;
geo_node_type_base(
&ntype, GEO_NODE_LEGACY_SELECT_BY_MATERIAL, "Select by Material", NODE_CLASS_GEOMETRY, 0);
- ntype.declare = blender::nodes::geo_node_legacy_select_by_material_declare;
- ntype.geometry_node_execute = blender::nodes::geo_node_legacy_select_by_material_exec;
+ ntype.declare = file_ns::node_declare;
+ ntype.geometry_node_execute = file_ns::node_geo_exec;
nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/geometry/nodes/legacy/node_geo_subdivision_surface.cc b/source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_subdivision_surface.cc
index 295cd05fd01..dd9c26f3790 100644
--- a/source/blender/nodes/geometry/nodes/legacy/node_geo_subdivision_surface.cc
+++ b/source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_subdivision_surface.cc
@@ -23,9 +23,9 @@
#include "UI_resources.h"
#include "node_geometry_util.hh"
-namespace blender::nodes {
+namespace blender::nodes::node_geo_legacy_subdivision_surface_cc {
-static void geo_node_subdivision_surface_declare(NodeDeclarationBuilder &b)
+static void node_declare(NodeDeclarationBuilder &b)
{
b.add_input<decl::Geometry>(N_("Geometry"));
b.add_input<decl::Int>(N_("Level")).default_value(1).min(0).max(6);
@@ -33,9 +33,7 @@ static void geo_node_subdivision_surface_declare(NodeDeclarationBuilder &b)
b.add_output<decl::Geometry>(N_("Geometry"));
}
-static void geo_node_subdivision_surface_layout(uiLayout *layout,
- bContext *UNUSED(C),
- PointerRNA *ptr)
+static void node_layout(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
{
#ifdef WITH_OPENSUBDIV
uiLayoutSetPropSep(layout, true);
@@ -47,7 +45,7 @@ static void geo_node_subdivision_surface_layout(uiLayout *layout,
#endif
}
-static void geo_node_subdivision_surface_init(bNodeTree *UNUSED(ntree), bNode *node)
+static void node_init(bNodeTree *UNUSED(ntree), bNode *node)
{
NodeGeometrySubdivisionSurface *data = (NodeGeometrySubdivisionSurface *)MEM_callocN(
sizeof(NodeGeometrySubdivisionSurface), __func__);
@@ -56,7 +54,7 @@ static void geo_node_subdivision_surface_init(bNodeTree *UNUSED(ntree), bNode *n
node->storage = data;
}
-static void geo_node_subdivision_surface_exec(GeoNodeExecParams params)
+static void node_geo_exec(GeoNodeExecParams params)
{
GeometrySet geometry_set = params.extract_input<GeometrySet>("Geometry");
@@ -126,18 +124,20 @@ static void geo_node_subdivision_surface_exec(GeoNodeExecParams params)
params.set_output("Geometry", std::move(geometry_set));
}
-} // namespace blender::nodes
+} // namespace blender::nodes::node_geo_legacy_subdivision_surface_cc
void register_node_type_geo_legacy_subdivision_surface()
{
+ namespace file_ns = blender::nodes::node_geo_legacy_subdivision_surface_cc;
+
static bNodeType ntype;
geo_node_type_base(
&ntype, GEO_NODE_LEGACY_SUBDIVISION_SURFACE, "Subdivision Surface", NODE_CLASS_GEOMETRY, 0);
- ntype.declare = blender::nodes::geo_node_subdivision_surface_declare;
- ntype.geometry_node_execute = blender::nodes::geo_node_subdivision_surface_exec;
- ntype.draw_buttons = blender::nodes::geo_node_subdivision_surface_layout;
- node_type_init(&ntype, blender::nodes::geo_node_subdivision_surface_init);
+ ntype.declare = file_ns::node_declare;
+ ntype.geometry_node_execute = file_ns::node_geo_exec;
+ ntype.draw_buttons = file_ns::node_layout;
+ node_type_init(&ntype, file_ns::node_init);
node_type_size_preset(&ntype, NODE_SIZE_MIDDLE);
node_type_storage(&ntype,
"NodeGeometrySubdivisionSurface",
diff --git a/source/blender/nodes/geometry/nodes/legacy/node_geo_volume_to_mesh.cc b/source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_volume_to_mesh.cc
index 39af5bf1fd2..acff0be7126 100644
--- a/source/blender/nodes/geometry/nodes/legacy/node_geo_volume_to_mesh.cc
+++ b/source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_volume_to_mesh.cc
@@ -35,9 +35,9 @@
#include "UI_interface.h"
#include "UI_resources.h"
-namespace blender::nodes {
+namespace blender::nodes::node_geo_legacy_volume_to_mesh_cc {
-static void geo_node_volume_to_mesh_declare(NodeDeclarationBuilder &b)
+static void node_declare(NodeDeclarationBuilder &b)
{
b.add_input<decl::Geometry>(N_("Geometry"));
b.add_input<decl::String>(N_("Density"));
@@ -48,14 +48,14 @@ static void geo_node_volume_to_mesh_declare(NodeDeclarationBuilder &b)
b.add_output<decl::Geometry>(N_("Geometry"));
}
-static void geo_node_volume_to_mesh_layout(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
+static void node_layout(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
{
uiLayoutSetPropSep(layout, true);
uiLayoutSetPropDecorate(layout, false);
uiItemR(layout, ptr, "resolution_mode", 0, IFACE_("Resolution"), ICON_NONE);
}
-static void geo_node_volume_to_mesh_init(bNodeTree *UNUSED(ntree), bNode *node)
+static void node_init(bNodeTree *UNUSED(ntree), bNode *node)
{
NodeGeometryVolumeToMesh *data = (NodeGeometryVolumeToMesh *)MEM_callocN(
sizeof(NodeGeometryVolumeToMesh), __func__);
@@ -68,15 +68,17 @@ static void geo_node_volume_to_mesh_init(bNodeTree *UNUSED(ntree), bNode *node)
node->storage = data;
}
-static void geo_node_volume_to_mesh_update(bNodeTree *UNUSED(ntree), bNode *node)
+static void node_update(bNodeTree *ntree, bNode *node)
{
NodeGeometryVolumeToMesh *data = (NodeGeometryVolumeToMesh *)node->storage;
bNodeSocket *voxel_size_socket = nodeFindSocket(node, SOCK_IN, "Voxel Size");
bNodeSocket *voxel_amount_socket = nodeFindSocket(node, SOCK_IN, "Voxel Amount");
- nodeSetSocketAvailability(voxel_amount_socket,
+ nodeSetSocketAvailability(ntree,
+ voxel_amount_socket,
data->resolution_mode == VOLUME_TO_MESH_RESOLUTION_MODE_VOXEL_AMOUNT);
- nodeSetSocketAvailability(voxel_size_socket,
+ nodeSetSocketAvailability(ntree,
+ voxel_size_socket,
data->resolution_mode == VOLUME_TO_MESH_RESOLUTION_MODE_VOXEL_SIZE);
}
@@ -138,7 +140,7 @@ static void create_mesh_from_volume(GeometrySet &geometry_set_in,
#endif /* WITH_OPENVDB */
-static void geo_node_volume_to_mesh_exec(GeoNodeExecParams params)
+static void node_geo_exec(GeoNodeExecParams params)
{
GeometrySet geometry_set_in = params.extract_input<GeometrySet>("Geometry");
GeometrySet geometry_set_out;
@@ -153,21 +155,23 @@ static void geo_node_volume_to_mesh_exec(GeoNodeExecParams params)
params.set_output("Geometry", geometry_set_out);
}
-} // namespace blender::nodes
+} // namespace blender::nodes::node_geo_legacy_volume_to_mesh_cc
void register_node_type_geo_legacy_volume_to_mesh()
{
+ namespace file_ns = blender::nodes::node_geo_legacy_volume_to_mesh_cc;
+
static bNodeType ntype;
geo_node_type_base(
&ntype, GEO_NODE_LEGACY_VOLUME_TO_MESH, "Volume to Mesh", NODE_CLASS_GEOMETRY, 0);
- ntype.declare = blender::nodes::geo_node_volume_to_mesh_declare;
+ ntype.declare = file_ns::node_declare;
node_type_storage(
&ntype, "NodeGeometryVolumeToMesh", node_free_standard_storage, node_copy_standard_storage);
node_type_size(&ntype, 170, 120, 700);
- node_type_init(&ntype, blender::nodes::geo_node_volume_to_mesh_init);
- node_type_update(&ntype, blender::nodes::geo_node_volume_to_mesh_update);
- ntype.geometry_node_execute = blender::nodes::geo_node_volume_to_mesh_exec;
- ntype.draw_buttons = blender::nodes::geo_node_volume_to_mesh_layout;
+ node_type_init(&ntype, file_ns::node_init);
+ node_type_update(&ntype, file_ns::node_update);
+ ntype.geometry_node_execute = file_ns::node_geo_exec;
+ ntype.draw_buttons = file_ns::node_layout;
nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/geometry/nodes/node_geo_attribute_capture.cc b/source/blender/nodes/geometry/nodes/node_geo_attribute_capture.cc
index 5cc8f1476f8..7229fda7a5c 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_attribute_capture.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_attribute_capture.cc
@@ -21,9 +21,9 @@
#include "node_geometry_util.hh"
-namespace blender::nodes {
+namespace blender::nodes::node_geo_attribute_capture_cc {
-static void geo_node_attribute_capture_declare(NodeDeclarationBuilder &b)
+static void node_declare(NodeDeclarationBuilder &b)
{
b.add_input<decl::Geometry>(N_("Geometry"));
b.add_input<decl::Vector>(N_("Value")).supports_field();
@@ -40,9 +40,7 @@ static void geo_node_attribute_capture_declare(NodeDeclarationBuilder &b)
b.add_output<decl::Int>(N_("Attribute"), "Attribute_004").field_source();
}
-static void geo_node_attribute_capture_layout(uiLayout *layout,
- bContext *UNUSED(C),
- PointerRNA *ptr)
+static void node_layout(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
{
uiLayoutSetPropSep(layout, true);
uiLayoutSetPropDecorate(layout, false);
@@ -50,7 +48,7 @@ static void geo_node_attribute_capture_layout(uiLayout *layout,
uiItemR(layout, ptr, "data_type", 0, "", ICON_NONE);
}
-static void geo_node_attribute_capture_init(bNodeTree *UNUSED(tree), bNode *node)
+static void node_init(bNodeTree *UNUSED(tree), bNode *node)
{
NodeGeometryAttributeCapture *data = (NodeGeometryAttributeCapture *)MEM_callocN(
sizeof(NodeGeometryAttributeCapture), __func__);
@@ -60,7 +58,7 @@ static void geo_node_attribute_capture_init(bNodeTree *UNUSED(tree), bNode *node
node->storage = data;
}
-static void geo_node_attribute_capture_update(bNodeTree *UNUSED(ntree), bNode *node)
+static void node_update(bNodeTree *ntree, bNode *node)
{
const NodeGeometryAttributeCapture &storage = *(const NodeGeometryAttributeCapture *)
node->storage;
@@ -73,11 +71,11 @@ static void geo_node_attribute_capture_update(bNodeTree *UNUSED(ntree), bNode *n
bNodeSocket *socket_value_boolean = socket_value_color4f->next;
bNodeSocket *socket_value_int32 = socket_value_boolean->next;
- nodeSetSocketAvailability(socket_value_vector, data_type == CD_PROP_FLOAT3);
- nodeSetSocketAvailability(socket_value_float, data_type == CD_PROP_FLOAT);
- nodeSetSocketAvailability(socket_value_color4f, data_type == CD_PROP_COLOR);
- nodeSetSocketAvailability(socket_value_boolean, data_type == CD_PROP_BOOL);
- nodeSetSocketAvailability(socket_value_int32, data_type == CD_PROP_INT32);
+ nodeSetSocketAvailability(ntree, socket_value_vector, data_type == CD_PROP_FLOAT3);
+ nodeSetSocketAvailability(ntree, socket_value_float, data_type == CD_PROP_FLOAT);
+ nodeSetSocketAvailability(ntree, socket_value_color4f, data_type == CD_PROP_COLOR);
+ nodeSetSocketAvailability(ntree, socket_value_boolean, data_type == CD_PROP_BOOL);
+ nodeSetSocketAvailability(ntree, socket_value_int32, data_type == CD_PROP_INT32);
bNodeSocket *out_socket_value_geometry = (bNodeSocket *)node->outputs.first;
bNodeSocket *out_socket_value_vector = out_socket_value_geometry->next;
@@ -86,11 +84,11 @@ static void geo_node_attribute_capture_update(bNodeTree *UNUSED(ntree), bNode *n
bNodeSocket *out_socket_value_boolean = out_socket_value_color4f->next;
bNodeSocket *out_socket_value_int32 = out_socket_value_boolean->next;
- nodeSetSocketAvailability(out_socket_value_vector, data_type == CD_PROP_FLOAT3);
- nodeSetSocketAvailability(out_socket_value_float, data_type == CD_PROP_FLOAT);
- nodeSetSocketAvailability(out_socket_value_color4f, data_type == CD_PROP_COLOR);
- nodeSetSocketAvailability(out_socket_value_boolean, data_type == CD_PROP_BOOL);
- nodeSetSocketAvailability(out_socket_value_int32, data_type == CD_PROP_INT32);
+ nodeSetSocketAvailability(ntree, out_socket_value_vector, data_type == CD_PROP_FLOAT3);
+ nodeSetSocketAvailability(ntree, out_socket_value_float, data_type == CD_PROP_FLOAT);
+ nodeSetSocketAvailability(ntree, out_socket_value_color4f, data_type == CD_PROP_COLOR);
+ nodeSetSocketAvailability(ntree, out_socket_value_boolean, data_type == CD_PROP_BOOL);
+ nodeSetSocketAvailability(ntree, out_socket_value_int32, data_type == CD_PROP_INT32);
}
static void try_capture_field_on_geometry(GeometryComponent &component,
@@ -113,7 +111,7 @@ static void try_capture_field_on_geometry(GeometryComponent &component,
output_attribute.save();
}
-static void geo_node_attribute_capture_exec(GeoNodeExecParams params)
+static void node_geo_exec(GeoNodeExecParams params)
{
GeometrySet geometry_set = params.extract_input<GeometrySet>("Geometry");
@@ -147,16 +145,27 @@ static void geo_node_attribute_capture_exec(GeoNodeExecParams params)
WeakAnonymousAttributeID anonymous_id{"Attribute"};
const CPPType &type = field.cpp_type();
- static const Array<GeometryComponentType> types = {
- GEO_COMPONENT_TYPE_MESH, GEO_COMPONENT_TYPE_POINT_CLOUD, GEO_COMPONENT_TYPE_CURVE};
- geometry_set.modify_geometry_sets([&](GeometrySet &geometry_set) {
- for (const GeometryComponentType type : types) {
- if (geometry_set.has(type)) {
- GeometryComponent &component = geometry_set.get_component_for_write(type);
- try_capture_field_on_geometry(component, anonymous_id.get(), domain, field);
- }
+ /* Run on the instances component separately to only affect the top level of instances. */
+ if (domain == ATTR_DOMAIN_INSTANCE) {
+ if (geometry_set.has_instances()) {
+ GeometryComponent &component = geometry_set.get_component_for_write(
+ GEO_COMPONENT_TYPE_INSTANCES);
+ try_capture_field_on_geometry(component, anonymous_id.get(), domain, field);
}
- });
+ }
+ else {
+ static const Array<GeometryComponentType> types = {
+ GEO_COMPONENT_TYPE_MESH, GEO_COMPONENT_TYPE_POINT_CLOUD, GEO_COMPONENT_TYPE_CURVE};
+
+ geometry_set.modify_geometry_sets([&](GeometrySet &geometry_set) {
+ for (const GeometryComponentType type : types) {
+ if (geometry_set.has(type)) {
+ GeometryComponent &component = geometry_set.get_component_for_write(type);
+ try_capture_field_on_geometry(component, anonymous_id.get(), domain, field);
+ }
+ }
+ });
+ }
GField output_field{std::make_shared<bke::AnonymousAttributeFieldInput>(
std::move(anonymous_id), type, params.attribute_producer_name())};
@@ -189,10 +198,12 @@ static void geo_node_attribute_capture_exec(GeoNodeExecParams params)
params.set_output("Geometry", geometry_set);
}
-} // namespace blender::nodes
+} // namespace blender::nodes::node_geo_attribute_capture_cc
void register_node_type_geo_attribute_capture()
{
+ namespace file_ns = blender::nodes::node_geo_attribute_capture_cc;
+
static bNodeType ntype;
geo_node_type_base(
@@ -201,10 +212,10 @@ void register_node_type_geo_attribute_capture()
"NodeGeometryAttributeCapture",
node_free_standard_storage,
node_copy_standard_storage);
- node_type_init(&ntype, blender::nodes::geo_node_attribute_capture_init);
- node_type_update(&ntype, blender::nodes::geo_node_attribute_capture_update);
- ntype.declare = blender::nodes::geo_node_attribute_capture_declare;
- ntype.geometry_node_execute = blender::nodes::geo_node_attribute_capture_exec;
- ntype.draw_buttons = blender::nodes::geo_node_attribute_capture_layout;
+ node_type_init(&ntype, file_ns::node_init);
+ node_type_update(&ntype, file_ns::node_update);
+ ntype.declare = file_ns::node_declare;
+ ntype.geometry_node_execute = file_ns::node_geo_exec;
+ ntype.draw_buttons = file_ns::node_layout;
nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/geometry/nodes/node_geo_attribute_remove.cc b/source/blender/nodes/geometry/nodes/node_geo_attribute_remove.cc
index f80b8ccc971..6f26b2c756b 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_attribute_remove.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_attribute_remove.cc
@@ -16,9 +16,9 @@
#include "node_geometry_util.hh"
-namespace blender::nodes {
+namespace blender::nodes::node_geo_attribute_remove_cc {
-static void geo_node_attribute_remove_declare(NodeDeclarationBuilder &b)
+static void node_declare(NodeDeclarationBuilder &b)
{
b.add_input<decl::Geometry>(N_("Geometry"));
b.add_input<decl::String>(N_("Attribute")).multi_input();
@@ -42,7 +42,7 @@ static void remove_attribute(GeometryComponent &component,
}
}
-static void geo_node_attribute_remove_exec(GeoNodeExecParams params)
+static void node_geo_exec(GeoNodeExecParams params)
{
GeometrySet geometry_set = params.extract_input<GeometrySet>("Geometry");
Vector<std::string> attribute_names = params.extract_multi_input<std::string>("Attribute");
@@ -66,15 +66,17 @@ static void geo_node_attribute_remove_exec(GeoNodeExecParams params)
params.set_output("Geometry", geometry_set);
}
-} // namespace blender::nodes
+} // namespace blender::nodes::node_geo_attribute_remove_cc
void register_node_type_geo_attribute_remove()
{
+ namespace file_ns = blender::nodes::node_geo_attribute_remove_cc;
+
static bNodeType ntype;
geo_node_type_base(
&ntype, GEO_NODE_ATTRIBUTE_REMOVE, "Attribute Remove", NODE_CLASS_ATTRIBUTE, 0);
- ntype.geometry_node_execute = blender::nodes::geo_node_attribute_remove_exec;
- ntype.declare = blender::nodes::geo_node_attribute_remove_declare;
+ ntype.geometry_node_execute = file_ns::node_geo_exec;
+ ntype.declare = file_ns::node_declare;
nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/geometry/nodes/node_geo_attribute_statistic.cc b/source/blender/nodes/geometry/nodes/node_geo_attribute_statistic.cc
index 155bd8c8c28..c84031f4c6b 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_attribute_statistic.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_attribute_statistic.cc
@@ -24,9 +24,9 @@
#include "node_geometry_util.hh"
-namespace blender::nodes {
+namespace blender::nodes::node_geo_attribute_statistic_cc {
-static void geo_node_attribute_statistic_declare(NodeDeclarationBuilder &b)
+static void node_declare(NodeDeclarationBuilder &b)
{
b.add_input<decl::Geometry>(N_("Geometry"));
b.add_input<decl::Float>(N_("Attribute")).hide_value().supports_field();
@@ -51,21 +51,19 @@ static void geo_node_attribute_statistic_declare(NodeDeclarationBuilder &b)
b.add_output<decl::Vector>(N_("Variance"), "Variance_001");
}
-static void geo_node_attribute_statistic_layout(uiLayout *layout,
- bContext *UNUSED(C),
- PointerRNA *ptr)
+static void node_layout(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
{
uiItemR(layout, ptr, "data_type", 0, "", ICON_NONE);
uiItemR(layout, ptr, "domain", 0, "", ICON_NONE);
}
-static void geo_node_attribute_statistic_init(bNodeTree *UNUSED(tree), bNode *node)
+static void node_init(bNodeTree *UNUSED(tree), bNode *node)
{
node->custom1 = CD_PROP_FLOAT;
node->custom2 = ATTR_DOMAIN_POINT;
}
-static void geo_node_attribute_statistic_update(bNodeTree *UNUSED(ntree), bNode *node)
+static void node_update(bNodeTree *ntree, bNode *node)
{
bNodeSocket *socket_geo = (bNodeSocket *)node->inputs.first;
bNodeSocket *socket_float_attr = socket_geo->next;
@@ -91,25 +89,25 @@ static void geo_node_attribute_statistic_update(bNodeTree *UNUSED(ntree), bNode
const CustomDataType data_type = static_cast<CustomDataType>(node->custom1);
- nodeSetSocketAvailability(socket_float_attr, data_type == CD_PROP_FLOAT);
- nodeSetSocketAvailability(socket_float_mean, data_type == CD_PROP_FLOAT);
- nodeSetSocketAvailability(socket_float_median, data_type == CD_PROP_FLOAT);
- nodeSetSocketAvailability(socket_float_sum, data_type == CD_PROP_FLOAT);
- nodeSetSocketAvailability(socket_float_min, data_type == CD_PROP_FLOAT);
- nodeSetSocketAvailability(socket_float_max, data_type == CD_PROP_FLOAT);
- nodeSetSocketAvailability(socket_float_range, data_type == CD_PROP_FLOAT);
- nodeSetSocketAvailability(socket_float_std, data_type == CD_PROP_FLOAT);
- nodeSetSocketAvailability(socket_float_variance, data_type == CD_PROP_FLOAT);
-
- nodeSetSocketAvailability(socket_float3_attr, data_type == CD_PROP_FLOAT3);
- nodeSetSocketAvailability(socket_vector_mean, data_type == CD_PROP_FLOAT3);
- nodeSetSocketAvailability(socket_vector_median, data_type == CD_PROP_FLOAT3);
- nodeSetSocketAvailability(socket_vector_sum, data_type == CD_PROP_FLOAT3);
- nodeSetSocketAvailability(socket_vector_min, data_type == CD_PROP_FLOAT3);
- nodeSetSocketAvailability(socket_vector_max, data_type == CD_PROP_FLOAT3);
- nodeSetSocketAvailability(socket_vector_range, data_type == CD_PROP_FLOAT3);
- nodeSetSocketAvailability(socket_vector_std, data_type == CD_PROP_FLOAT3);
- nodeSetSocketAvailability(socket_vector_variance, data_type == CD_PROP_FLOAT3);
+ nodeSetSocketAvailability(ntree, socket_float_attr, data_type == CD_PROP_FLOAT);
+ nodeSetSocketAvailability(ntree, socket_float_mean, data_type == CD_PROP_FLOAT);
+ nodeSetSocketAvailability(ntree, socket_float_median, data_type == CD_PROP_FLOAT);
+ nodeSetSocketAvailability(ntree, socket_float_sum, data_type == CD_PROP_FLOAT);
+ nodeSetSocketAvailability(ntree, socket_float_min, data_type == CD_PROP_FLOAT);
+ nodeSetSocketAvailability(ntree, socket_float_max, data_type == CD_PROP_FLOAT);
+ nodeSetSocketAvailability(ntree, socket_float_range, data_type == CD_PROP_FLOAT);
+ nodeSetSocketAvailability(ntree, socket_float_std, data_type == CD_PROP_FLOAT);
+ nodeSetSocketAvailability(ntree, socket_float_variance, data_type == CD_PROP_FLOAT);
+
+ nodeSetSocketAvailability(ntree, socket_float3_attr, data_type == CD_PROP_FLOAT3);
+ nodeSetSocketAvailability(ntree, socket_vector_mean, data_type == CD_PROP_FLOAT3);
+ nodeSetSocketAvailability(ntree, socket_vector_median, data_type == CD_PROP_FLOAT3);
+ nodeSetSocketAvailability(ntree, socket_vector_sum, data_type == CD_PROP_FLOAT3);
+ nodeSetSocketAvailability(ntree, socket_vector_min, data_type == CD_PROP_FLOAT3);
+ nodeSetSocketAvailability(ntree, socket_vector_max, data_type == CD_PROP_FLOAT3);
+ nodeSetSocketAvailability(ntree, socket_vector_range, data_type == CD_PROP_FLOAT3);
+ nodeSetSocketAvailability(ntree, socket_vector_std, data_type == CD_PROP_FLOAT3);
+ nodeSetSocketAvailability(ntree, socket_vector_variance, data_type == CD_PROP_FLOAT3);
}
template<typename T> static T compute_sum(const Span<T> data)
@@ -170,7 +168,7 @@ static void set_empty(CustomDataType data_type, GeoNodeExecParams &params)
}
}
-static void geo_node_attribute_statistic_exec(GeoNodeExecParams params)
+static void node_geo_exec(GeoNodeExecParams params)
{
GeometrySet geometry_set = params.get_input<GeometrySet>("Geometry");
@@ -360,19 +358,21 @@ static void geo_node_attribute_statistic_exec(GeoNodeExecParams params)
}
}
-} // namespace blender::nodes
+} // namespace blender::nodes::node_geo_attribute_statistic_cc
void register_node_type_geo_attribute_statistic()
{
+ namespace file_ns = blender::nodes::node_geo_attribute_statistic_cc;
+
static bNodeType ntype;
geo_node_type_base(
&ntype, GEO_NODE_ATTRIBUTE_STATISTIC, "Attribute Statistic", NODE_CLASS_ATTRIBUTE, 0);
- ntype.declare = blender::nodes::geo_node_attribute_statistic_declare;
- node_type_init(&ntype, blender::nodes::geo_node_attribute_statistic_init);
- node_type_update(&ntype, blender::nodes::geo_node_attribute_statistic_update);
- ntype.geometry_node_execute = blender::nodes::geo_node_attribute_statistic_exec;
- ntype.draw_buttons = blender::nodes::geo_node_attribute_statistic_layout;
+ ntype.declare = file_ns::node_declare;
+ node_type_init(&ntype, file_ns::node_init);
+ node_type_update(&ntype, file_ns::node_update);
+ ntype.geometry_node_execute = file_ns::node_geo_exec;
+ ntype.draw_buttons = file_ns::node_layout;
nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/geometry/nodes/node_geo_boolean.cc b/source/blender/nodes/geometry/nodes/node_geo_boolean.cc
index 516f07b7ad3..0947632cc09 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_boolean.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_boolean.cc
@@ -23,9 +23,9 @@
#include "node_geometry_util.hh"
-namespace blender::nodes {
+namespace blender::nodes::node_geo_boolean_cc {
-static void geo_node_boolean_declare(NodeDeclarationBuilder &b)
+static void node_declare(NodeDeclarationBuilder &b)
{
b.add_input<decl::Geometry>(N_("Mesh 1"))
.only_realized_data()
@@ -36,12 +36,12 @@ static void geo_node_boolean_declare(NodeDeclarationBuilder &b)
b.add_output<decl::Geometry>(N_("Mesh"));
}
-static void geo_node_boolean_layout(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
+static void node_layout(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
{
uiItemR(layout, ptr, "operation", 0, "", ICON_NONE);
}
-static void geo_node_boolean_update(bNodeTree *UNUSED(ntree), bNode *node)
+static void node_update(bNodeTree *ntree, bNode *node)
{
GeometryNodeBooleanOperation operation = (GeometryNodeBooleanOperation)node->custom1;
@@ -51,24 +51,24 @@ static void geo_node_boolean_update(bNodeTree *UNUSED(ntree), bNode *node)
switch (operation) {
case GEO_NODE_BOOLEAN_INTERSECT:
case GEO_NODE_BOOLEAN_UNION:
- nodeSetSocketAvailability(geometry_1_socket, false);
- nodeSetSocketAvailability(geometry_2_socket, true);
+ nodeSetSocketAvailability(ntree, geometry_1_socket, false);
+ nodeSetSocketAvailability(ntree, geometry_2_socket, true);
node_sock_label(geometry_2_socket, N_("Mesh"));
break;
case GEO_NODE_BOOLEAN_DIFFERENCE:
- nodeSetSocketAvailability(geometry_1_socket, true);
- nodeSetSocketAvailability(geometry_2_socket, true);
+ nodeSetSocketAvailability(ntree, geometry_1_socket, true);
+ nodeSetSocketAvailability(ntree, geometry_2_socket, true);
node_sock_label(geometry_2_socket, N_("Mesh 2"));
break;
}
}
-static void geo_node_boolean_init(bNodeTree *UNUSED(tree), bNode *node)
+static void node_init(bNodeTree *UNUSED(tree), bNode *node)
{
node->custom1 = GEO_NODE_BOOLEAN_DIFFERENCE;
}
-static void geo_node_boolean_exec(GeoNodeExecParams params)
+static void node_geo_exec(GeoNodeExecParams params)
{
GeometryNodeBooleanOperation operation = (GeometryNodeBooleanOperation)params.node().custom1;
const bool use_self = params.get_input<bool>("Self Intersection");
@@ -119,17 +119,19 @@ static void geo_node_boolean_exec(GeoNodeExecParams params)
params.set_output("Mesh", GeometrySet::create_with_mesh(result));
}
-} // namespace blender::nodes
+} // namespace blender::nodes::node_geo_boolean_cc
void register_node_type_geo_boolean()
{
+ namespace file_ns = blender::nodes::node_geo_boolean_cc;
+
static bNodeType ntype;
geo_node_type_base(&ntype, GEO_NODE_MESH_BOOLEAN, "Mesh Boolean", NODE_CLASS_GEOMETRY, 0);
- ntype.declare = blender::nodes::geo_node_boolean_declare;
- ntype.draw_buttons = blender::nodes::geo_node_boolean_layout;
- ntype.updatefunc = blender::nodes::geo_node_boolean_update;
- node_type_init(&ntype, blender::nodes::geo_node_boolean_init);
- ntype.geometry_node_execute = blender::nodes::geo_node_boolean_exec;
+ ntype.declare = file_ns::node_declare;
+ ntype.draw_buttons = file_ns::node_layout;
+ ntype.updatefunc = file_ns::node_update;
+ node_type_init(&ntype, file_ns::node_init);
+ ntype.geometry_node_execute = file_ns::node_geo_exec;
nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/geometry/nodes/node_geo_bounding_box.cc b/source/blender/nodes/geometry/nodes/node_geo_bounding_box.cc
index e7c9715934a..da1f9a00c69 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_bounding_box.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_bounding_box.cc
@@ -16,9 +16,9 @@
#include "node_geometry_util.hh"
-namespace blender::nodes {
+namespace blender::nodes::node_geo_bounding_box_cc {
-static void geo_node_bounding_box_declare(NodeDeclarationBuilder &b)
+static void node_declare(NodeDeclarationBuilder &b)
{
b.add_input<decl::Geometry>(N_("Geometry"));
b.add_output<decl::Geometry>(N_("Bounding Box"));
@@ -26,7 +26,7 @@ static void geo_node_bounding_box_declare(NodeDeclarationBuilder &b)
b.add_output<decl::Vector>(N_("Max"));
}
-static void geo_node_bounding_box_exec(GeoNodeExecParams params)
+static void node_geo_exec(GeoNodeExecParams params)
{
GeometrySet geometry_set = params.extract_input<GeometrySet>("Geometry");
@@ -78,14 +78,16 @@ static void geo_node_bounding_box_exec(GeoNodeExecParams params)
}
}
-} // namespace blender::nodes
+} // namespace blender::nodes::node_geo_bounding_box_cc
void register_node_type_geo_bounding_box()
{
+ namespace file_ns = blender::nodes::node_geo_bounding_box_cc;
+
static bNodeType ntype;
geo_node_type_base(&ntype, GEO_NODE_BOUNDING_BOX, "Bounding Box", NODE_CLASS_GEOMETRY, 0);
- ntype.declare = blender::nodes::geo_node_bounding_box_declare;
- ntype.geometry_node_execute = blender::nodes::geo_node_bounding_box_exec;
+ ntype.declare = file_ns::node_declare;
+ ntype.geometry_node_execute = file_ns::node_geo_exec;
nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/geometry/nodes/node_geo_collection_info.cc b/source/blender/nodes/geometry/nodes/node_geo_collection_info.cc
index f068e621596..1cd5f396ee5 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_collection_info.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_collection_info.cc
@@ -27,9 +27,9 @@
#include <algorithm>
-namespace blender::nodes {
+namespace blender::nodes::node_geo_collection_info_cc {
-static void geo_node_collection_info_declare(NodeDeclarationBuilder &b)
+static void node_declare(NodeDeclarationBuilder &b)
{
b.add_input<decl::Collection>(N_("Collection")).hide_label();
b.add_input<decl::Bool>(N_("Separate Children"))
@@ -38,16 +38,16 @@ static void geo_node_collection_info_declare(NodeDeclarationBuilder &b)
b.add_input<decl::Bool>(N_("Reset Children"))
.description(
N_("Reset the transforms of every child instance in the output. Only used when Separate "
- "Children is enabled"));
+ "Children is enabled"));
b.add_output<decl::Geometry>(N_("Geometry"));
}
-static void geo_node_collection_info_layout(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
+static void node_layout(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
{
uiItemR(layout, ptr, "transform_space", UI_ITEM_R_EXPAND, nullptr, ICON_NONE);
}
-static void geo_node_collection_info_node_init(bNodeTree *UNUSED(tree), bNode *node)
+static void node_node_init(bNodeTree *UNUSED(tree), bNode *node)
{
NodeGeometryCollectionInfo *data = (NodeGeometryCollectionInfo *)MEM_callocN(
sizeof(NodeGeometryCollectionInfo), __func__);
@@ -61,7 +61,7 @@ struct InstanceListEntry {
float4x4 transform;
};
-static void geo_node_collection_info_exec(GeoNodeExecParams params)
+static void node_geo_exec(GeoNodeExecParams params)
{
Collection *collection = params.get_input<Collection *>("Collection");
@@ -155,20 +155,22 @@ static void geo_node_collection_info_exec(GeoNodeExecParams params)
params.set_output("Geometry", geometry_set_out);
}
-} // namespace blender::nodes
+} // namespace blender::nodes::node_geo_collection_info_cc
void register_node_type_geo_collection_info()
{
+ namespace file_ns = blender::nodes::node_geo_collection_info_cc;
+
static bNodeType ntype;
geo_node_type_base(&ntype, GEO_NODE_COLLECTION_INFO, "Collection Info", NODE_CLASS_INPUT, 0);
- ntype.declare = blender::nodes::geo_node_collection_info_declare;
- node_type_init(&ntype, blender::nodes::geo_node_collection_info_node_init);
+ ntype.declare = file_ns::node_declare;
+ node_type_init(&ntype, file_ns::node_node_init);
node_type_storage(&ntype,
"NodeGeometryCollectionInfo",
node_free_standard_storage,
node_copy_standard_storage);
- ntype.geometry_node_execute = blender::nodes::geo_node_collection_info_exec;
- ntype.draw_buttons = blender::nodes::geo_node_collection_info_layout;
+ ntype.geometry_node_execute = file_ns::node_geo_exec;
+ ntype.draw_buttons = file_ns::node_layout;
nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/geometry/nodes/node_geo_common.cc b/source/blender/nodes/geometry/nodes/node_geo_common.cc
index e2bb7e9f939..9ebbdd349de 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_common.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_common.cc
@@ -31,7 +31,6 @@ void register_node_type_geo_group(void)
ntype.poll = geo_node_poll_default;
ntype.poll_instance = node_group_poll_instance;
ntype.insert_link = node_insert_link_default;
- ntype.update_internal_links = node_update_internal_links_default;
ntype.rna_ext.srna = RNA_struct_find("GeometryNodeGroup");
BLI_assert(ntype.rna_ext.srna != nullptr);
RNA_struct_blender_type_set(ntype.rna_ext.srna, &ntype);
@@ -53,7 +52,4 @@ void register_node_type_geo_custom_group(bNodeType *ntype)
if (ntype->insert_link == nullptr) {
ntype->insert_link = node_insert_link_default;
}
- if (ntype->update_internal_links == nullptr) {
- ntype->update_internal_links = node_update_internal_links_default;
- }
}
diff --git a/source/blender/nodes/geometry/nodes/node_geo_convex_hull.cc b/source/blender/nodes/geometry/nodes/node_geo_convex_hull.cc
index 3cf682e161c..5222e2055b1 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_convex_hull.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_convex_hull.cc
@@ -28,9 +28,9 @@
# include "RBI_hull_api.h"
#endif
-namespace blender::nodes {
+namespace blender::nodes::node_geo_convex_hull_cc {
-static void geo_node_convex_hull_declare(NodeDeclarationBuilder &b)
+static void node_declare(NodeDeclarationBuilder &b)
{
b.add_input<decl::Geometry>(N_("Geometry"));
b.add_output<decl::Geometry>(N_("Convex Hull"));
@@ -169,10 +169,10 @@ static Mesh *compute_hull(const GeometrySet &geometry_set)
span_count++;
const PointCloudComponent *component =
geometry_set.get_component_for_read<PointCloudComponent>();
- GVArray_Typed<float3> varray = component->attribute_get_for_read<float3>(
+ VArray<float3> varray = component->attribute_get_for_read<float3>(
"position", ATTR_DOMAIN_POINT, {0, 0, 0});
- total_size += varray->size();
- positions_span = varray->get_internal_span();
+ total_size += varray.size();
+ positions_span = varray.get_internal_span();
}
if (geometry_set.has_curve()) {
@@ -200,18 +200,18 @@ static Mesh *compute_hull(const GeometrySet &geometry_set)
if (geometry_set.has_mesh()) {
const MeshComponent *component = geometry_set.get_component_for_read<MeshComponent>();
- GVArray_Typed<float3> varray = component->attribute_get_for_read<float3>(
+ VArray<float3> varray = component->attribute_get_for_read<float3>(
"position", ATTR_DOMAIN_POINT, {0, 0, 0});
- varray->materialize(positions.as_mutable_span().slice(offset, varray.size()));
+ varray.materialize(positions.as_mutable_span().slice(offset, varray.size()));
offset += varray.size();
}
if (geometry_set.has_pointcloud()) {
const PointCloudComponent *component =
geometry_set.get_component_for_read<PointCloudComponent>();
- GVArray_Typed<float3> varray = component->attribute_get_for_read<float3>(
+ VArray<float3> varray = component->attribute_get_for_read<float3>(
"position", ATTR_DOMAIN_POINT, {0, 0, 0});
- varray->materialize(positions.as_mutable_span().slice(offset, varray.size()));
+ varray.materialize(positions.as_mutable_span().slice(offset, varray.size()));
offset += varray.size();
}
@@ -235,16 +235,16 @@ static void read_positions(const GeometryComponent &component,
Span<float4x4> transforms,
Vector<float3> *r_coords)
{
- GVArray_Typed<float3> positions = component.attribute_get_for_read<float3>(
+ VArray<float3> positions = component.attribute_get_for_read<float3>(
"position", ATTR_DOMAIN_POINT, {0, 0, 0});
/* NOTE: could use convex hull operation here to
* cut out some vertices, before accumulating,
* but can also be done by the user beforehand. */
- r_coords->reserve(r_coords->size() + positions.size() * transforms.size());
+ r_coords->reserve(r_coords->size() + positions->size() * transforms.size());
for (const float4x4 &transform : transforms) {
- for (const int i : positions.index_range()) {
+ for (const int i : positions->index_range()) {
const float3 position = positions[i];
const float3 transformed_position = transform * position;
r_coords->append(transformed_position);
@@ -296,7 +296,7 @@ static Mesh *convex_hull_from_instances(const GeometrySet &geometry_set)
#endif /* WITH_BULLET */
-static void geo_node_convex_hull_exec(GeoNodeExecParams params)
+static void node_geo_exec(GeoNodeExecParams params)
{
GeometrySet geometry_set = params.extract_input<GeometrySet>("Geometry");
@@ -316,14 +316,16 @@ static void geo_node_convex_hull_exec(GeoNodeExecParams params)
#endif /* WITH_BULLET */
}
-} // namespace blender::nodes
+} // namespace blender::nodes::node_geo_convex_hull_cc
void register_node_type_geo_convex_hull()
{
+ namespace file_ns = blender::nodes::node_geo_convex_hull_cc;
+
static bNodeType ntype;
geo_node_type_base(&ntype, GEO_NODE_CONVEX_HULL, "Convex Hull", NODE_CLASS_GEOMETRY, 0);
- ntype.declare = blender::nodes::geo_node_convex_hull_declare;
- ntype.geometry_node_execute = blender::nodes::geo_node_convex_hull_exec;
+ ntype.declare = file_ns::node_declare;
+ ntype.geometry_node_execute = file_ns::node_geo_exec;
nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/geometry/nodes/node_geo_curve_endpoint_selection.cc b/source/blender/nodes/geometry/nodes/node_geo_curve_endpoint_selection.cc
index 42d88cdb1e7..c756185e4ed 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_curve_endpoint_selection.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_curve_endpoint_selection.cc
@@ -21,9 +21,9 @@
#include "node_geometry_util.hh"
-namespace blender::nodes {
+namespace blender::nodes::node_geo_curve_endpoint_select_cc {
-static void geo_node_curve_endpoint_selection_declare(NodeDeclarationBuilder &b)
+static void node_declare(NodeDeclarationBuilder &b)
{
b.add_input<decl::Int>(N_("Start Size"))
.min(0)
@@ -64,9 +64,9 @@ class EndpointFieldInput final : public fn::FieldInput {
category_ = Category::Generated;
}
- const GVArray *get_varray_for_context(const fn::FieldContext &context,
- IndexMask UNUSED(mask),
- ResourceScope &scope) const final
+ GVArray get_varray_for_context(const fn::FieldContext &context,
+ IndexMask UNUSED(mask),
+ ResourceScope &UNUSED(scope)) const final
{
if (const GeometryComponentFieldContext *geometry_context =
dynamic_cast<const GeometryComponentFieldContext *>(&context)) {
@@ -111,9 +111,9 @@ class EndpointFieldInput final : public fn::FieldInput {
}
current_point += spline->size();
}
- return &scope.construct<fn::GVArray_For_ArrayContainer<Array<bool>>>(std::move(selection));
+ return VArray<bool>::ForContainer(std::move(selection));
}
- return nullptr;
+ return {};
};
uint64_t hash() const override
@@ -131,23 +131,25 @@ class EndpointFieldInput final : public fn::FieldInput {
}
};
-static void geo_node_curve_endpoint_selection_exec(GeoNodeExecParams params)
+static void node_geo_exec(GeoNodeExecParams params)
{
Field<int> start_size = params.extract_input<Field<int>>("Start Size");
Field<int> end_size = params.extract_input<Field<int>>("End Size");
Field<bool> selection_field{std::make_shared<EndpointFieldInput>(start_size, end_size)};
params.set_output("Selection", std::move(selection_field));
}
-} // namespace blender::nodes
+} // namespace blender::nodes::node_geo_curve_endpoint_select_cc
void register_node_type_geo_curve_endpoint_selection()
{
+ namespace file_ns = blender::nodes::node_geo_curve_endpoint_select_cc;
+
static bNodeType ntype;
geo_node_type_base(
&ntype, GEO_NODE_CURVE_ENDPOINT_SELECTION, "Endpoint Selection", NODE_CLASS_INPUT, 0);
- ntype.declare = blender::nodes::geo_node_curve_endpoint_selection_declare;
- ntype.geometry_node_execute = blender::nodes::geo_node_curve_endpoint_selection_exec;
+ ntype.declare = file_ns::node_declare;
+ ntype.geometry_node_execute = file_ns::node_geo_exec;
nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/geometry/nodes/node_geo_curve_fill.cc b/source/blender/nodes/geometry/nodes/node_geo_curve_fill.cc
index 219effadec4..4130cf99516 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_curve_fill.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_curve_fill.cc
@@ -31,20 +31,20 @@
#include "node_geometry_util.hh"
-namespace blender::nodes {
+namespace blender::nodes::node_geo_curve_fill_cc {
-static void geo_node_curve_fill_declare(NodeDeclarationBuilder &b)
+static void node_declare(NodeDeclarationBuilder &b)
{
b.add_input<decl::Geometry>(N_("Curve")).supported_type(GEO_COMPONENT_TYPE_CURVE);
b.add_output<decl::Geometry>(N_("Mesh"));
}
-static void geo_node_curve_fill_layout(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
+static void node_layout(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
{
uiItemR(layout, ptr, "mode", UI_ITEM_R_EXPAND, nullptr, ICON_NONE);
}
-static void geo_node_curve_fill_init(bNodeTree *UNUSED(ntree), bNode *node)
+static void node_init(bNodeTree *UNUSED(ntree), bNode *node)
{
NodeGeometryCurveFill *data = (NodeGeometryCurveFill *)MEM_callocN(sizeof(NodeGeometryCurveFill),
__func__);
@@ -147,7 +147,7 @@ static void curve_fill_calculate(GeometrySet &geometry_set, const GeometryNodeCu
geometry_set.replace_curve(nullptr);
}
-static void geo_node_curve_fill_exec(GeoNodeExecParams params)
+static void node_geo_exec(GeoNodeExecParams params)
{
GeometrySet geometry_set = params.extract_input<GeometrySet>("Curve");
@@ -160,19 +160,21 @@ static void geo_node_curve_fill_exec(GeoNodeExecParams params)
params.set_output("Mesh", std::move(geometry_set));
}
-} // namespace blender::nodes
+} // namespace blender::nodes::node_geo_curve_fill_cc
void register_node_type_geo_curve_fill()
{
+ namespace file_ns = blender::nodes::node_geo_curve_fill_cc;
+
static bNodeType ntype;
geo_node_type_base(&ntype, GEO_NODE_FILL_CURVE, "Fill Curve", NODE_CLASS_GEOMETRY, 0);
- node_type_init(&ntype, blender::nodes::geo_node_curve_fill_init);
+ node_type_init(&ntype, file_ns::node_init);
node_type_storage(
&ntype, "NodeGeometryCurveFill", node_free_standard_storage, node_copy_standard_storage);
- ntype.declare = blender::nodes::geo_node_curve_fill_declare;
- ntype.geometry_node_execute = blender::nodes::geo_node_curve_fill_exec;
- ntype.draw_buttons = blender::nodes::geo_node_curve_fill_layout;
+ ntype.declare = file_ns::node_declare;
+ ntype.geometry_node_execute = file_ns::node_geo_exec;
+ ntype.draw_buttons = file_ns::node_layout;
nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/geometry/nodes/node_geo_curve_fillet.cc b/source/blender/nodes/geometry/nodes/node_geo_curve_fillet.cc
index 27d7d22b106..ed5c9e1bc98 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_curve_fillet.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_curve_fillet.cc
@@ -25,9 +25,9 @@
#include "BKE_spline.hh"
-namespace blender::nodes {
+namespace blender::nodes::node_geo_curve_fillet_cc {
-static void geo_node_curve_fillet_declare(NodeDeclarationBuilder &b)
+static void node_declare(NodeDeclarationBuilder &b)
{
b.add_input<decl::Geometry>(N_("Curve")).supported_type(GEO_COMPONENT_TYPE_CURVE);
b.add_input<decl::Int>(N_("Count")).default_value(1).min(1).max(1000).supports_field();
@@ -41,12 +41,12 @@ static void geo_node_curve_fillet_declare(NodeDeclarationBuilder &b)
b.add_output<decl::Geometry>(N_("Curve"));
}
-static void geo_node_curve_fillet_layout(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
+static void node_layout(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
{
uiItemR(layout, ptr, "mode", UI_ITEM_R_EXPAND, nullptr, ICON_NONE);
}
-static void geo_node_curve_fillet_init(bNodeTree *UNUSED(tree), bNode *node)
+static void node_init(bNodeTree *UNUSED(tree), bNode *node)
{
NodeGeometryCurveFillet *data = (NodeGeometryCurveFillet *)MEM_callocN(
sizeof(NodeGeometryCurveFillet), __func__);
@@ -59,10 +59,10 @@ struct FilletParam {
GeometryNodeCurveFilletMode mode;
/* Number of points to be added. */
- const VArray<int> *counts;
+ VArray<int> counts;
/* Radii for fillet arc at all vertices. */
- const VArray<float> *radii;
+ VArray<float> radii;
/* Whether or not fillets are allowed to overlap. */
bool limit_radius;
@@ -76,14 +76,14 @@ struct FilletData {
Array<int> counts;
};
-static void geo_node_curve_fillet_update(bNodeTree *UNUSED(ntree), bNode *node)
+static void node_update(bNodeTree *ntree, bNode *node)
{
NodeGeometryCurveFillet &node_storage = *(NodeGeometryCurveFillet *)node->storage;
const GeometryNodeCurveFilletMode mode = (GeometryNodeCurveFilletMode)node_storage.mode;
bNodeSocket *poly_socket = ((bNodeSocket *)node->inputs.first)->next;
- nodeSetSocketAvailability(poly_socket, mode == GEO_NODE_CURVE_FILLET_POLY);
+ nodeSetSocketAvailability(ntree, poly_socket, mode == GEO_NODE_CURVE_FILLET_POLY);
}
/* Function to get the center of a fillet. */
@@ -160,7 +160,7 @@ static Array<int> calculate_counts(const FilletParam &fillet_param,
Array<int> counts(size, 1);
if (fillet_param.mode == GEO_NODE_CURVE_FILLET_POLY) {
for (const int i : IndexRange(size)) {
- counts[i] = (*fillet_param.counts)[spline_offset + i];
+ counts[i] = fillet_param.counts[spline_offset + i];
}
}
if (!cyclic) {
@@ -178,12 +178,12 @@ static Array<float> calculate_radii(const FilletParam &fillet_param,
Array<float> radii(size, 0.0f);
if (fillet_param.limit_radius) {
for (const int i : IndexRange(size)) {
- radii[i] = std::max((*fillet_param.radii)[spline_offset + i], 0.0f);
+ radii[i] = std::max(fillet_param.radii[spline_offset + i], 0.0f);
}
}
else {
for (const int i : IndexRange(size)) {
- radii[i] = (*fillet_param.radii)[spline_offset + i];
+ radii[i] = fillet_param.radii[spline_offset + i];
}
}
@@ -590,13 +590,13 @@ static void calculate_curve_fillet(GeometrySet &geometry_set,
field_evaluator.evaluate();
- fillet_param.radii = &field_evaluator.get_evaluated<float>(0);
- if (fillet_param.radii->is_single() && fillet_param.radii->get_internal_single() < 0.0f) {
+ fillet_param.radii = field_evaluator.get_evaluated<float>(0);
+ if (fillet_param.radii.is_single() && fillet_param.radii.get_internal_single() < 0.0f) {
return;
}
if (mode == GEO_NODE_CURVE_FILLET_POLY) {
- fillet_param.counts = &field_evaluator.get_evaluated<int>(1);
+ fillet_param.counts = field_evaluator.get_evaluated<int>(1);
}
fillet_param.limit_radius = limit_radius;
@@ -607,7 +607,7 @@ static void calculate_curve_fillet(GeometrySet &geometry_set,
geometry_set.replace_curve(output_curve.release());
}
-static void geo_node_fillet_exec(GeoNodeExecParams params)
+static void node_geo_exec(GeoNodeExecParams params)
{
GeometrySet geometry_set = params.extract_input<GeometrySet>("Curve");
@@ -629,19 +629,21 @@ static void geo_node_fillet_exec(GeoNodeExecParams params)
params.set_output("Curve", std::move(geometry_set));
}
-} // namespace blender::nodes
+} // namespace blender::nodes::node_geo_curve_fillet_cc
void register_node_type_geo_curve_fillet()
{
+ namespace file_ns = blender::nodes::node_geo_curve_fillet_cc;
+
static bNodeType ntype;
geo_node_type_base(&ntype, GEO_NODE_FILLET_CURVE, "Fillet Curve", NODE_CLASS_GEOMETRY, 0);
- ntype.draw_buttons = blender::nodes::geo_node_curve_fillet_layout;
+ ntype.draw_buttons = file_ns::node_layout;
node_type_storage(
&ntype, "NodeGeometryCurveFillet", node_free_standard_storage, node_copy_standard_storage);
- ntype.declare = blender::nodes::geo_node_curve_fillet_declare;
- node_type_init(&ntype, blender::nodes::geo_node_curve_fillet_init);
- node_type_update(&ntype, blender::nodes::geo_node_curve_fillet_update);
- ntype.geometry_node_execute = blender::nodes::geo_node_fillet_exec;
+ ntype.declare = file_ns::node_declare;
+ node_type_init(&ntype, file_ns::node_init);
+ node_type_update(&ntype, file_ns::node_update);
+ ntype.geometry_node_execute = file_ns::node_geo_exec;
nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/geometry/nodes/node_geo_curve_handle_type_selection.cc b/source/blender/nodes/geometry/nodes/node_geo_curve_handle_type_selection.cc
index e48c72b68d9..2a53f7a3f82 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_curve_handle_type_selection.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_curve_handle_type_selection.cc
@@ -21,22 +21,20 @@
#include "node_geometry_util.hh"
-namespace blender::nodes {
+namespace blender::nodes::node_geo_curve_handle_type_selection_cc {
-static void geo_node_curve_handle_type_selection_declare(NodeDeclarationBuilder &b)
+static void node_declare(NodeDeclarationBuilder &b)
{
b.add_output<decl::Bool>(N_("Selection")).field_source();
}
-static void geo_node_curve_handle_type_selection_layout(uiLayout *layout,
- bContext *UNUSED(C),
- PointerRNA *ptr)
+static void node_layout(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
{
uiItemR(layout, ptr, "mode", UI_ITEM_R_EXPAND, nullptr, ICON_NONE);
uiItemR(layout, ptr, "handle_type", 0, "", ICON_NONE);
}
-static void geo_node_curve_handle_type_selection_init(bNodeTree *UNUSED(tree), bNode *node)
+static void node_init(bNodeTree *UNUSED(tree), bNode *node)
{
NodeGeometryCurveSelectHandles *data = (NodeGeometryCurveSelectHandles *)MEM_callocN(
sizeof(NodeGeometryCurveSelectHandles), __func__);
@@ -96,9 +94,9 @@ class HandleTypeFieldInput final : public fn::FieldInput {
category_ = Category::Generated;
}
- const GVArray *get_varray_for_context(const fn::FieldContext &context,
- IndexMask mask,
- ResourceScope &scope) const final
+ GVArray get_varray_for_context(const fn::FieldContext &context,
+ IndexMask mask,
+ ResourceScope &UNUSED(scope)) const final
{
if (const GeometryComponentFieldContext *geometry_context =
dynamic_cast<const GeometryComponentFieldContext *>(&context)) {
@@ -106,22 +104,22 @@ class HandleTypeFieldInput final : public fn::FieldInput {
const GeometryComponent &component = geometry_context->geometry_component();
const AttributeDomain domain = geometry_context->domain();
if (component.type() != GEO_COMPONENT_TYPE_CURVE) {
- return nullptr;
+ return {};
}
const CurveComponent &curve_component = static_cast<const CurveComponent &>(component);
const CurveEval *curve = curve_component.get_for_read();
if (curve == nullptr) {
- return nullptr;
+ return {};
}
if (domain == ATTR_DOMAIN_POINT) {
Array<bool> selection(mask.min_array_size());
select_by_handle_type(*curve, type_, mode_, selection);
- return &scope.construct<fn::GVArray_For_ArrayContainer<Array<bool>>>(std::move(selection));
+ return VArray<bool>::ForContainer(std::move(selection));
}
}
- return nullptr;
+ return {};
};
uint64_t hash() const override
@@ -140,7 +138,7 @@ class HandleTypeFieldInput final : public fn::FieldInput {
}
};
-static void geo_node_curve_handle_type_selection_exec(GeoNodeExecParams params)
+static void node_geo_exec(GeoNodeExecParams params)
{
const NodeGeometryCurveSelectHandles *storage =
(const NodeGeometryCurveSelectHandles *)params.node().storage;
@@ -152,22 +150,24 @@ static void geo_node_curve_handle_type_selection_exec(GeoNodeExecParams params)
params.set_output("Selection", std::move(selection_field));
}
-} // namespace blender::nodes
+} // namespace blender::nodes::node_geo_curve_handle_type_selection_cc
void register_node_type_geo_curve_handle_type_selection()
{
+ namespace file_ns = blender::nodes::node_geo_curve_handle_type_selection_cc;
+
static bNodeType ntype;
geo_node_type_base(
&ntype, GEO_NODE_CURVE_HANDLE_TYPE_SELECTION, "Handle Type Selection", NODE_CLASS_INPUT, 0);
- ntype.declare = blender::nodes::geo_node_curve_handle_type_selection_declare;
- ntype.geometry_node_execute = blender::nodes::geo_node_curve_handle_type_selection_exec;
- node_type_init(&ntype, blender::nodes::geo_node_curve_handle_type_selection_init);
+ ntype.declare = file_ns::node_declare;
+ ntype.geometry_node_execute = file_ns::node_geo_exec;
+ node_type_init(&ntype, file_ns::node_init);
node_type_storage(&ntype,
"NodeGeometryCurveSelectHandles",
node_free_standard_storage,
node_copy_standard_storage);
- ntype.draw_buttons = blender::nodes::geo_node_curve_handle_type_selection_layout;
+ ntype.draw_buttons = file_ns::node_layout;
nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/geometry/nodes/node_geo_curve_length.cc b/source/blender/nodes/geometry/nodes/node_geo_curve_length.cc
index 0d0dc0ec89c..33e9b11ec0c 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_curve_length.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_curve_length.cc
@@ -17,15 +17,15 @@
#include "BKE_spline.hh"
#include "node_geometry_util.hh"
-namespace blender::nodes {
+namespace blender::nodes::node_geo_curve_length_cc {
-static void geo_node_curve_length_declare(NodeDeclarationBuilder &b)
+static void node_declare(NodeDeclarationBuilder &b)
{
b.add_input<decl::Geometry>(N_("Curve")).supported_type(GEO_COMPONENT_TYPE_CURVE);
b.add_output<decl::Float>(N_("Length"));
}
-static void geo_node_curve_length_exec(GeoNodeExecParams params)
+static void node_geo_exec(GeoNodeExecParams params)
{
GeometrySet curve_set = params.extract_input<GeometrySet>("Curve");
if (!curve_set.has_curve()) {
@@ -40,14 +40,16 @@ static void geo_node_curve_length_exec(GeoNodeExecParams params)
params.set_output("Length", length);
}
-} // namespace blender::nodes
+} // namespace blender::nodes::node_geo_curve_length_cc
void register_node_type_geo_curve_length()
{
+ namespace file_ns = blender::nodes::node_geo_curve_length_cc;
+
static bNodeType ntype;
geo_node_type_base(&ntype, GEO_NODE_CURVE_LENGTH, "Curve Length", NODE_CLASS_GEOMETRY, 0);
- ntype.declare = blender::nodes::geo_node_curve_length_declare;
- ntype.geometry_node_execute = blender::nodes::geo_node_curve_length_exec;
+ ntype.declare = file_ns::node_declare;
+ ntype.geometry_node_execute = file_ns::node_geo_exec;
nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/geometry/nodes/node_geo_curve_parameter.cc b/source/blender/nodes/geometry/nodes/node_geo_curve_parameter.cc
index 4c89aba2e6d..27b2590546b 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_curve_parameter.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_curve_parameter.cc
@@ -20,11 +20,20 @@
#include "node_geometry_util.hh"
-namespace blender::nodes {
+namespace blender::nodes::node_geo_curve_parameter_cc {
-static void geo_node_curve_parameter_declare(NodeDeclarationBuilder &b)
+static void node_declare(NodeDeclarationBuilder &b)
{
- b.add_output<decl::Float>(N_("Factor")).field_source();
+ b.add_output<decl::Float>(N_("Factor"))
+ .field_source()
+ .description(
+ N_("For points, the portion of the spline's total length at the control point. For "
+ "Splines, the factor of that spline within the entire curve"));
+ b.add_output<decl::Float>(N_("Length"))
+ .field_source()
+ .description(
+ N_("For points, the distance along the control point's spline, For splines, the "
+ "distance along the entire curve"));
}
/**
@@ -32,47 +41,42 @@ static void geo_node_curve_parameter_declare(NodeDeclarationBuilder &b)
* average parameter for each spline would just be 0.5, or close to it. Instead, the parameter for
* each spline is the portion of the total length at the start of the spline.
*/
-static Array<float> curve_parameter_spline_domain(const CurveEval &curve, const IndexMask mask)
+static Array<float> curve_length_spline_domain(const CurveEval &curve,
+ const IndexMask UNUSED(mask))
{
Span<SplinePtr> splines = curve.splines();
float length = 0.0f;
- Array<float> parameters(splines.size());
+ Array<float> lengths(splines.size());
for (const int i : splines.index_range()) {
- parameters[i] = length;
+ lengths[i] = length;
length += splines[i]->length();
}
- const float total_length_inverse = length == 0.0f ? 0.0f : 1.0f / length;
- mask.foreach_index([&](const int64_t i) { parameters[i] *= total_length_inverse; });
-
- return parameters;
+ return lengths;
}
/**
* The parameter at each control point is the factor at the corresponding evaluated point.
*/
-static void calculate_bezier_parameters(const BezierSpline &spline, MutableSpan<float> parameters)
+static void calculate_bezier_lengths(const BezierSpline &spline, MutableSpan<float> lengths)
{
Span<int> offsets = spline.control_point_offsets();
- Span<float> lengths = spline.evaluated_lengths();
- const float total_length = spline.length();
- const float total_length_inverse = total_length == 0.0f ? 0.0f : 1.0f / total_length;
-
+ Span<float> lengths_eval = spline.evaluated_lengths();
for (const int i : IndexRange(1, spline.size() - 1)) {
- parameters[i] = lengths[offsets[i] - 1] * total_length_inverse;
+ lengths[i] = lengths_eval[offsets[i] - 1];
}
}
/**
* The parameter for poly splines is simply the evaluated lengths divided by the total length.
*/
-static void calculate_poly_parameters(const PolySpline &spline, MutableSpan<float> parameters)
+static void calculate_poly_length(const PolySpline &spline, MutableSpan<float> lengths)
{
- Span<float> lengths = spline.evaluated_lengths();
- const float total_length = spline.length();
- const float total_length_inverse = total_length == 0.0f ? 0.0f : 1.0f / total_length;
-
- for (const int i : IndexRange(1, spline.size() - 1)) {
- parameters[i] = lengths[i - 1] * total_length_inverse;
+ Span<float> lengths_eval = spline.evaluated_lengths();
+ if (spline.is_cyclic()) {
+ lengths.drop_front(1).copy_from(lengths_eval.drop_back(1));
+ }
+ else {
+ lengths.drop_front(1).copy_from(lengths_eval);
}
}
@@ -82,70 +86,100 @@ static void calculate_poly_parameters(const PolySpline &spline, MutableSpan<floa
* each point is not well defined. So instead, treat the control points as if they were a poly
* spline.
*/
-static void calculate_nurbs_parameters(const NURBSpline &spline, MutableSpan<float> parameters)
+static void calculate_nurbs_lengths(const NURBSpline &spline, MutableSpan<float> lengths)
{
Span<float3> positions = spline.positions();
Array<float> control_point_lengths(spline.size());
-
float length = 0.0f;
for (const int i : IndexRange(positions.size() - 1)) {
- parameters[i] = length;
+ lengths[i] = length;
length += float3::distance(positions[i], positions[i + 1]);
}
-
- const float total_length_inverse = length == 0.0f ? 0.0f : 1.0f / length;
- for (float &parameter : parameters) {
- parameter *= total_length_inverse;
- }
+ lengths.last() = length;
}
-static Array<float> curve_parameter_point_domain(const CurveEval &curve)
+static Array<float> curve_length_point_domain(const CurveEval &curve)
{
Span<SplinePtr> splines = curve.splines();
Array<int> offsets = curve.control_point_offsets();
const int total_size = offsets.last();
- Array<float> parameters(total_size);
+ Array<float> lengths(total_size);
threading::parallel_for(splines.index_range(), 128, [&](IndexRange range) {
for (const int i : range) {
const Spline &spline = *splines[i];
- MutableSpan spline_factors{parameters.as_mutable_span().slice(offsets[i], spline.size())};
+ MutableSpan spline_factors{lengths.as_mutable_span().slice(offsets[i], spline.size())};
spline_factors.first() = 0.0f;
switch (splines[i]->type()) {
case Spline::Type::Bezier: {
- calculate_bezier_parameters(static_cast<const BezierSpline &>(spline), spline_factors);
+ calculate_bezier_lengths(static_cast<const BezierSpline &>(spline), spline_factors);
break;
}
case Spline::Type::Poly: {
- calculate_poly_parameters(static_cast<const PolySpline &>(spline), spline_factors);
+ calculate_poly_length(static_cast<const PolySpline &>(spline), spline_factors);
break;
}
case Spline::Type::NURBS: {
- calculate_nurbs_parameters(static_cast<const NURBSpline &>(spline), spline_factors);
+ calculate_nurbs_lengths(static_cast<const NURBSpline &>(spline), spline_factors);
break;
}
}
}
});
- return parameters;
+ return lengths;
}
-static const GVArray *construct_curve_parameter_gvarray(const CurveEval &curve,
- const IndexMask mask,
- const AttributeDomain domain,
- ResourceScope &scope)
+static VArray<float> construct_curve_parameter_varray(const CurveEval &curve,
+ const IndexMask mask,
+ const AttributeDomain domain)
{
if (domain == ATTR_DOMAIN_POINT) {
- Array<float> parameters = curve_parameter_point_domain(curve);
- return &scope.construct<fn::GVArray_For_ArrayContainer<Array<float>>>(std::move(parameters));
+ Span<SplinePtr> splines = curve.splines();
+ Array<float> values = curve_length_point_domain(curve);
+
+ const Array<int> offsets = curve.control_point_offsets();
+ for (const int i_spline : curve.splines().index_range()) {
+ const Spline &spline = *splines[i_spline];
+ const float spline_length = spline.length();
+ const float spline_length_inv = spline_length == 0.0f ? 0.0f : 1.0f / spline_length;
+ for (const int i : IndexRange(spline.size())) {
+ values[offsets[i_spline] + i] *= spline_length_inv;
+ }
+ }
+ return VArray<float>::ForContainer(std::move(values));
}
if (domain == ATTR_DOMAIN_CURVE) {
- Array<float> parameters = curve_parameter_spline_domain(curve, mask);
- return &scope.construct<fn::GVArray_For_ArrayContainer<Array<float>>>(std::move(parameters));
+ Array<float> values = curve.accumulated_spline_lengths();
+ const float total_length_inv = values.last() == 0.0f ? 0.0f : 1.0f / values.last();
+ for (const int i : mask) {
+ values[i] *= total_length_inv;
+ }
+ return VArray<float>::ForContainer(std::move(values));
}
+ return {};
+}
- return nullptr;
+static VArray<float> construct_curve_length_varray(const CurveEval &curve,
+ const IndexMask mask,
+ const AttributeDomain domain)
+{
+ if (domain == ATTR_DOMAIN_POINT) {
+ Array<float> lengths = curve_length_point_domain(curve);
+ return VArray<float>::ForContainer(std::move(lengths));
+ }
+
+ if (domain == ATTR_DOMAIN_CURVE) {
+ if (curve.splines().size() == 1) {
+ Array<float> lengths(1, 0.0f);
+ return VArray<float>::ForContainer(std::move(lengths));
+ }
+
+ Array<float> lengths = curve_length_spline_domain(curve, mask);
+ return VArray<float>::ForContainer(std::move(lengths));
+ }
+
+ return {};
}
class CurveParameterFieldInput final : public fn::FieldInput {
@@ -155,9 +189,9 @@ class CurveParameterFieldInput final : public fn::FieldInput {
category_ = Category::Generated;
}
- const GVArray *get_varray_for_context(const fn::FieldContext &context,
- IndexMask mask,
- ResourceScope &scope) const final
+ GVArray get_varray_for_context(const fn::FieldContext &context,
+ IndexMask mask,
+ ResourceScope &UNUSED(scope)) const final
{
if (const GeometryComponentFieldContext *geometry_context =
dynamic_cast<const GeometryComponentFieldContext *>(&context)) {
@@ -169,11 +203,11 @@ class CurveParameterFieldInput final : public fn::FieldInput {
const CurveComponent &curve_component = static_cast<const CurveComponent &>(component);
const CurveEval *curve = curve_component.get_for_read();
if (curve) {
- return construct_curve_parameter_gvarray(*curve, mask, domain, scope);
+ return construct_curve_parameter_varray(*curve, mask, domain);
}
}
}
- return nullptr;
+ return {};
}
uint64_t hash() const override
@@ -188,20 +222,62 @@ class CurveParameterFieldInput final : public fn::FieldInput {
}
};
-static void geo_node_curve_parameter_exec(GeoNodeExecParams params)
+class CurveLengthFieldInput final : public fn::FieldInput {
+ public:
+ CurveLengthFieldInput() : fn::FieldInput(CPPType::get<float>(), "Curve Length node")
+ {
+ category_ = Category::Generated;
+ }
+
+ GVArray get_varray_for_context(const fn::FieldContext &context,
+ IndexMask mask,
+ ResourceScope &UNUSED(scope)) const final
+ {
+ if (const GeometryComponentFieldContext *geometry_context =
+ dynamic_cast<const GeometryComponentFieldContext *>(&context)) {
+
+ const GeometryComponent &component = geometry_context->geometry_component();
+ const AttributeDomain domain = geometry_context->domain();
+ if (component.type() == GEO_COMPONENT_TYPE_CURVE) {
+ const CurveComponent &curve_component = static_cast<const CurveComponent &>(component);
+ const CurveEval *curve = curve_component.get_for_read();
+ if (curve) {
+ return construct_curve_length_varray(*curve, mask, domain);
+ }
+ }
+ }
+ return {};
+ }
+
+ uint64_t hash() const override
+ {
+ /* Some random constant hash. */
+ return 345634563454;
+ }
+
+ bool is_equal_to(const fn::FieldNode &other) const override
+ {
+ return dynamic_cast<const CurveLengthFieldInput *>(&other) != nullptr;
+ }
+};
+
+static void node_geo_exec(GeoNodeExecParams params)
{
Field<float> parameter_field{std::make_shared<CurveParameterFieldInput>()};
+ Field<float> length_field{std::make_shared<CurveLengthFieldInput>()};
params.set_output("Factor", std::move(parameter_field));
+ params.set_output("Length", std::move(length_field));
}
-} // namespace blender::nodes
+} // namespace blender::nodes::node_geo_curve_parameter_cc
void register_node_type_geo_curve_parameter()
{
- static bNodeType ntype;
+ namespace file_ns = blender::nodes::node_geo_curve_parameter_cc;
+ static bNodeType ntype;
geo_node_type_base(&ntype, GEO_NODE_CURVE_PARAMETER, "Curve Parameter", NODE_CLASS_INPUT, 0);
- ntype.geometry_node_execute = blender::nodes::geo_node_curve_parameter_exec;
- ntype.declare = blender::nodes::geo_node_curve_parameter_declare;
+ ntype.geometry_node_execute = file_ns::node_geo_exec;
+ ntype.declare = file_ns::node_declare;
nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/geometry/nodes/node_geo_curve_primitive_bezier_segment.cc b/source/blender/nodes/geometry/nodes/node_geo_curve_primitive_bezier_segment.cc
index a755d47cc6a..a2ca41d8e19 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_curve_primitive_bezier_segment.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_curve_primitive_bezier_segment.cc
@@ -21,34 +21,44 @@
#include "node_geometry_util.hh"
-namespace blender::nodes {
+namespace blender::nodes::node_geo_curve_primitive_bezier_segment_cc {
-static void geo_node_curve_primitive_bezier_segment_declare(NodeDeclarationBuilder &b)
+static void node_declare(NodeDeclarationBuilder &b)
{
b.add_input<decl::Int>(N_("Resolution"))
.default_value(16)
.min(1)
.max(256)
- .subtype(PROP_UNSIGNED);
+ .subtype(PROP_UNSIGNED)
+ .description(N_("The number of evaluated points on the curve"));
b.add_input<decl::Vector>(N_("Start"))
.default_value({-1.0f, 0.0f, 0.0f})
- .subtype(PROP_TRANSLATION);
+ .subtype(PROP_TRANSLATION)
+ .description(N_("Position of the start control point of the curve"));
b.add_input<decl::Vector>(N_("Start Handle"))
.default_value({-0.5f, 0.5f, 0.0f})
- .subtype(PROP_TRANSLATION);
- b.add_input<decl::Vector>(N_("End Handle")).subtype(PROP_TRANSLATION);
- b.add_input<decl::Vector>(N_("End")).default_value({1.0f, 0.0f, 0.0f}).subtype(PROP_TRANSLATION);
+ .subtype(PROP_TRANSLATION)
+ .description(
+ N_("Position of the start handle used to define the shape of the curve. In Offset mode, "
+ "relative to Start point"));
+ b.add_input<decl::Vector>(N_("End Handle"))
+ .subtype(PROP_TRANSLATION)
+ .description(
+ N_("Position of the end handle used to define the shape of the curve. In Offset mode, "
+ "relative to End point"));
+ b.add_input<decl::Vector>(N_("End"))
+ .default_value({1.0f, 0.0f, 0.0f})
+ .subtype(PROP_TRANSLATION)
+ .description(N_("Position of the end control point of the curve"));
b.add_output<decl::Geometry>(N_("Curve"));
}
-static void geo_node_curve_primitive_bezier_segment_layout(uiLayout *layout,
- bContext *UNUSED(C),
- PointerRNA *ptr)
+static void node_layout(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
{
uiItemR(layout, ptr, "mode", UI_ITEM_R_EXPAND, nullptr, ICON_NONE);
}
-static void geo_node_curve_primitive_bezier_segment_init(bNodeTree *UNUSED(tree), bNode *node)
+static void node_init(bNodeTree *UNUSED(tree), bNode *node)
{
NodeGeometryCurvePrimitiveBezierSegment *data = (NodeGeometryCurvePrimitiveBezierSegment *)
MEM_callocN(sizeof(NodeGeometryCurvePrimitiveBezierSegment), __func__);
@@ -108,7 +118,7 @@ static std::unique_ptr<CurveEval> create_bezier_segment_curve(
return curve;
}
-static void geo_node_curve_primitive_bezier_segment_exec(GeoNodeExecParams params)
+static void node_geo_exec(GeoNodeExecParams params)
{
const NodeGeometryCurvePrimitiveBezierSegment *node_storage =
(NodeGeometryCurvePrimitiveBezierSegment *)params.node().storage;
@@ -125,20 +135,22 @@ static void geo_node_curve_primitive_bezier_segment_exec(GeoNodeExecParams param
params.set_output("Curve", GeometrySet::create_with_curve(curve.release()));
}
-} // namespace blender::nodes
+} // namespace blender::nodes::node_geo_curve_primitive_bezier_segment_cc
void register_node_type_geo_curve_primitive_bezier_segment()
{
+ namespace file_ns = blender::nodes::node_geo_curve_primitive_bezier_segment_cc;
+
static bNodeType ntype;
geo_node_type_base(
&ntype, GEO_NODE_CURVE_PRIMITIVE_BEZIER_SEGMENT, "Bezier Segment", NODE_CLASS_GEOMETRY, 0);
- node_type_init(&ntype, blender::nodes::geo_node_curve_primitive_bezier_segment_init);
+ node_type_init(&ntype, file_ns::node_init);
node_type_storage(&ntype,
"NodeGeometryCurvePrimitiveBezierSegment",
node_free_standard_storage,
node_copy_standard_storage);
- ntype.declare = blender::nodes::geo_node_curve_primitive_bezier_segment_declare;
- ntype.draw_buttons = blender::nodes::geo_node_curve_primitive_bezier_segment_layout;
- ntype.geometry_node_execute = blender::nodes::geo_node_curve_primitive_bezier_segment_exec;
+ ntype.declare = file_ns::node_declare;
+ ntype.draw_buttons = file_ns::node_layout;
+ ntype.geometry_node_execute = file_ns::node_geo_exec;
nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/geometry/nodes/node_geo_curve_primitive_circle.cc b/source/blender/nodes/geometry/nodes/node_geo_curve_primitive_circle.cc
index bf4f22d6578..f56571241f9 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_curve_primitive_circle.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_curve_primitive_circle.cc
@@ -21,33 +21,48 @@
#include "node_geometry_util.hh"
-namespace blender::nodes {
+namespace blender::nodes::node_geo_curve_primitive_circle_cc {
-static void geo_node_curve_primitive_circle_declare(NodeDeclarationBuilder &b)
+static void node_declare(NodeDeclarationBuilder &b)
{
- b.add_input<decl::Int>(N_("Resolution")).default_value(32).min(3).max(512);
+ b.add_input<decl::Int>(N_("Resolution"))
+ .default_value(32)
+ .min(3)
+ .max(512)
+ .description(N_("Number of points on the circle"));
b.add_input<decl::Vector>(N_("Point 1"))
.default_value({-1.0f, 0.0f, 0.0f})
- .subtype(PROP_TRANSLATION);
+ .subtype(PROP_TRANSLATION)
+ .description(
+ N_("One of the three points on the circle. The point order determines the circle's "
+ "direction"));
b.add_input<decl::Vector>(N_("Point 2"))
.default_value({0.0f, 1.0f, 0.0f})
- .subtype(PROP_TRANSLATION);
+ .subtype(PROP_TRANSLATION)
+ .description(
+ N_("One of the three points on the circle. The point order determines the circle's "
+ "direction"));
b.add_input<decl::Vector>(N_("Point 3"))
.default_value({1.0f, 0.0f, 0.0f})
- .subtype(PROP_TRANSLATION);
- b.add_input<decl::Float>(N_("Radius")).default_value(1.0f).min(0.0f).subtype(PROP_DISTANCE);
+ .subtype(PROP_TRANSLATION)
+ .description(
+ N_("One of the three points on the circle. The point order determines the circle's "
+ "direction"));
+ b.add_input<decl::Float>(N_("Radius"))
+ .default_value(1.0f)
+ .min(0.0f)
+ .subtype(PROP_DISTANCE)
+ .description(N_("Distance of the points from the origin"));
b.add_output<decl::Geometry>(N_("Curve"));
b.add_output<decl::Vector>(N_("Center"));
}
-static void geo_node_curve_primitive_circle_layout(uiLayout *layout,
- bContext *UNUSED(C),
- PointerRNA *ptr)
+static void node_layout(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
{
uiItemR(layout, ptr, "mode", UI_ITEM_R_EXPAND, nullptr, ICON_NONE);
}
-static void geo_node_curve_primitive_circle_init(bNodeTree *UNUSED(tree), bNode *node)
+static void node_init(bNodeTree *UNUSED(tree), bNode *node)
{
NodeGeometryCurvePrimitiveCircle *data = (NodeGeometryCurvePrimitiveCircle *)MEM_callocN(
sizeof(NodeGeometryCurvePrimitiveCircle), __func__);
@@ -56,7 +71,7 @@ static void geo_node_curve_primitive_circle_init(bNodeTree *UNUSED(tree), bNode
node->storage = data;
}
-static void geo_node_curve_primitive_circle_update(bNodeTree *UNUSED(ntree), bNode *node)
+static void node_update(bNodeTree *ntree, bNode *node)
{
const NodeGeometryCurvePrimitiveCircle *node_storage = (NodeGeometryCurvePrimitiveCircle *)
node->storage;
@@ -70,11 +85,16 @@ static void geo_node_curve_primitive_circle_update(bNodeTree *UNUSED(ntree), bNo
bNodeSocket *center_socket = ((bNodeSocket *)node->outputs.first)->next;
- nodeSetSocketAvailability(start_socket, mode == GEO_NODE_CURVE_PRIMITIVE_CIRCLE_TYPE_POINTS);
- nodeSetSocketAvailability(middle_socket, mode == GEO_NODE_CURVE_PRIMITIVE_CIRCLE_TYPE_POINTS);
- nodeSetSocketAvailability(end_socket, mode == GEO_NODE_CURVE_PRIMITIVE_CIRCLE_TYPE_POINTS);
- nodeSetSocketAvailability(center_socket, mode == GEO_NODE_CURVE_PRIMITIVE_CIRCLE_TYPE_POINTS);
- nodeSetSocketAvailability(radius_socket, mode == GEO_NODE_CURVE_PRIMITIVE_CIRCLE_TYPE_RADIUS);
+ nodeSetSocketAvailability(
+ ntree, start_socket, mode == GEO_NODE_CURVE_PRIMITIVE_CIRCLE_TYPE_POINTS);
+ nodeSetSocketAvailability(
+ ntree, middle_socket, mode == GEO_NODE_CURVE_PRIMITIVE_CIRCLE_TYPE_POINTS);
+ nodeSetSocketAvailability(
+ ntree, end_socket, mode == GEO_NODE_CURVE_PRIMITIVE_CIRCLE_TYPE_POINTS);
+ nodeSetSocketAvailability(
+ ntree, center_socket, mode == GEO_NODE_CURVE_PRIMITIVE_CIRCLE_TYPE_POINTS);
+ nodeSetSocketAvailability(
+ ntree, radius_socket, mode == GEO_NODE_CURVE_PRIMITIVE_CIRCLE_TYPE_RADIUS);
}
static bool colinear_f3_f3_f3(const float3 p1, const float3 p2, const float3 p3)
@@ -173,7 +193,7 @@ static std::unique_ptr<CurveEval> create_radius_circle_curve(const int resolutio
return curve;
}
-static void geo_node_curve_primitive_circle_exec(GeoNodeExecParams params)
+static void node_geo_exec(GeoNodeExecParams params)
{
const NodeGeometryCurvePrimitiveCircle *node_storage =
(NodeGeometryCurvePrimitiveCircle *)params.node().storage;
@@ -204,22 +224,24 @@ static void geo_node_curve_primitive_circle_exec(GeoNodeExecParams params)
}
}
-} // namespace blender::nodes
+} // namespace blender::nodes::node_geo_curve_primitive_circle_cc
void register_node_type_geo_curve_primitive_circle()
{
+ namespace file_ns = blender::nodes::node_geo_curve_primitive_circle_cc;
+
static bNodeType ntype;
geo_node_type_base(
&ntype, GEO_NODE_CURVE_PRIMITIVE_CIRCLE, "Curve Circle", NODE_CLASS_GEOMETRY, 0);
- node_type_init(&ntype, blender::nodes::geo_node_curve_primitive_circle_init);
- node_type_update(&ntype, blender::nodes::geo_node_curve_primitive_circle_update);
+ node_type_init(&ntype, file_ns::node_init);
+ node_type_update(&ntype, file_ns::node_update);
node_type_storage(&ntype,
"NodeGeometryCurvePrimitiveCircle",
node_free_standard_storage,
node_copy_standard_storage);
- ntype.declare = blender::nodes::geo_node_curve_primitive_circle_declare;
- ntype.geometry_node_execute = blender::nodes::geo_node_curve_primitive_circle_exec;
- ntype.draw_buttons = blender::nodes::geo_node_curve_primitive_circle_layout;
+ ntype.declare = file_ns::node_declare;
+ ntype.geometry_node_execute = file_ns::node_geo_exec;
+ ntype.draw_buttons = file_ns::node_layout;
nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/geometry/nodes/node_geo_curve_primitive_line.cc b/source/blender/nodes/geometry/nodes/node_geo_curve_primitive_line.cc
index 5b215797052..321fe6f2a9e 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_curve_primitive_line.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_curve_primitive_line.cc
@@ -21,25 +21,34 @@
#include "node_geometry_util.hh"
-namespace blender::nodes {
+namespace blender::nodes::node_geo_curve_primitive_line_cc {
-static void geo_node_curve_primitive_line_declare(NodeDeclarationBuilder &b)
+static void node_declare(NodeDeclarationBuilder &b)
{
- b.add_input<decl::Vector>(N_("Start")).subtype(PROP_TRANSLATION);
- b.add_input<decl::Vector>(N_("End")).default_value({0.0f, 0.0f, 1.0f}).subtype(PROP_TRANSLATION);
- b.add_input<decl::Vector>(N_("Direction")).default_value({0.0f, 0.0f, 1.0f});
- b.add_input<decl::Float>(N_("Length")).default_value(1.0f).subtype(PROP_DISTANCE);
+ b.add_input<decl::Vector>(N_("Start"))
+ .subtype(PROP_TRANSLATION)
+ .description(N_("Position of the first control point"));
+ b.add_input<decl::Vector>(N_("End"))
+ .default_value({0.0f, 0.0f, 1.0f})
+ .subtype(PROP_TRANSLATION)
+ .description(N_("Position of the second control point"));
+ b.add_input<decl::Vector>(N_("Direction"))
+ .default_value({0.0f, 0.0f, 1.0f})
+ .description(
+ N_("Direction the line is going in. The length of this vector does not matter"));
+ b.add_input<decl::Float>(N_("Length"))
+ .default_value(1.0f)
+ .subtype(PROP_DISTANCE)
+ .description(N_("Distance between the two points"));
b.add_output<decl::Geometry>(N_("Curve"));
}
-static void geo_node_curve_primitive_line_layout(uiLayout *layout,
- bContext *UNUSED(C),
- PointerRNA *ptr)
+static void node_layout(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
{
uiItemR(layout, ptr, "mode", UI_ITEM_R_EXPAND, nullptr, ICON_NONE);
}
-static void geo_node_curve_primitive_line_init(bNodeTree *UNUSED(tree), bNode *node)
+static void node_init(bNodeTree *UNUSED(tree), bNode *node)
{
NodeGeometryCurvePrimitiveLine *data = (NodeGeometryCurvePrimitiveLine *)MEM_callocN(
sizeof(NodeGeometryCurvePrimitiveLine), __func__);
@@ -48,7 +57,7 @@ static void geo_node_curve_primitive_line_init(bNodeTree *UNUSED(tree), bNode *n
node->storage = data;
}
-static void geo_node_curve_primitive_line_update(bNodeTree *UNUSED(ntree), bNode *node)
+static void node_update(bNodeTree *ntree, bNode *node)
{
const NodeGeometryCurvePrimitiveLine *node_storage = (NodeGeometryCurvePrimitiveLine *)
node->storage;
@@ -59,10 +68,11 @@ static void geo_node_curve_primitive_line_update(bNodeTree *UNUSED(ntree), bNode
bNodeSocket *direction_socket = p2_socket->next;
bNodeSocket *length_socket = direction_socket->next;
- nodeSetSocketAvailability(p2_socket, mode == GEO_NODE_CURVE_PRIMITIVE_LINE_MODE_POINTS);
- nodeSetSocketAvailability(direction_socket,
- mode == GEO_NODE_CURVE_PRIMITIVE_LINE_MODE_DIRECTION);
- nodeSetSocketAvailability(length_socket, mode == GEO_NODE_CURVE_PRIMITIVE_LINE_MODE_DIRECTION);
+ nodeSetSocketAvailability(ntree, p2_socket, mode == GEO_NODE_CURVE_PRIMITIVE_LINE_MODE_POINTS);
+ nodeSetSocketAvailability(
+ ntree, direction_socket, mode == GEO_NODE_CURVE_PRIMITIVE_LINE_MODE_DIRECTION);
+ nodeSetSocketAvailability(
+ ntree, length_socket, mode == GEO_NODE_CURVE_PRIMITIVE_LINE_MODE_DIRECTION);
}
static std::unique_ptr<CurveEval> create_point_line_curve(const float3 start, const float3 end)
@@ -100,7 +110,7 @@ static std::unique_ptr<CurveEval> create_direction_line_curve(const float3 start
return curve;
}
-static void geo_node_curve_primitive_line_exec(GeoNodeExecParams params)
+static void node_geo_exec(GeoNodeExecParams params)
{
const NodeGeometryCurvePrimitiveLine *node_storage =
@@ -122,20 +132,22 @@ static void geo_node_curve_primitive_line_exec(GeoNodeExecParams params)
params.set_output("Curve", GeometrySet::create_with_curve(curve.release()));
}
-} // namespace blender::nodes
+} // namespace blender::nodes::node_geo_curve_primitive_line_cc
void register_node_type_geo_curve_primitive_line()
{
+ namespace file_ns = blender::nodes::node_geo_curve_primitive_line_cc;
+
static bNodeType ntype;
geo_node_type_base(&ntype, GEO_NODE_CURVE_PRIMITIVE_LINE, "Curve Line", NODE_CLASS_GEOMETRY, 0);
- node_type_init(&ntype, blender::nodes::geo_node_curve_primitive_line_init);
- node_type_update(&ntype, blender::nodes::geo_node_curve_primitive_line_update);
+ node_type_init(&ntype, file_ns::node_init);
+ node_type_update(&ntype, file_ns::node_update);
node_type_storage(&ntype,
"NodeGeometryCurvePrimitiveLine",
node_free_standard_storage,
node_copy_standard_storage);
- ntype.declare = blender::nodes::geo_node_curve_primitive_line_declare;
- ntype.geometry_node_execute = blender::nodes::geo_node_curve_primitive_line_exec;
- ntype.draw_buttons = blender::nodes::geo_node_curve_primitive_line_layout;
+ ntype.declare = file_ns::node_declare;
+ ntype.geometry_node_execute = file_ns::node_geo_exec;
+ ntype.draw_buttons = file_ns::node_layout;
nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/geometry/nodes/node_geo_curve_primitive_quadratic_bezier.cc b/source/blender/nodes/geometry/nodes/node_geo_curve_primitive_quadratic_bezier.cc
index 6041ddee02d..92a9b1b4966 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_curve_primitive_quadratic_bezier.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_curve_primitive_quadratic_bezier.cc
@@ -17,22 +17,28 @@
#include "BKE_spline.hh"
#include "node_geometry_util.hh"
-namespace blender::nodes {
+namespace blender::nodes::node_geo_curve_primitive_quadratic_bezier_cc {
-static void geo_node_curve_primitive_quadratic_bezier_declare(NodeDeclarationBuilder &b)
+static void node_declare(NodeDeclarationBuilder &b)
{
b.add_input<decl::Int>(N_("Resolution"))
.default_value(16)
.min(3)
.max(256)
- .subtype(PROP_UNSIGNED);
+ .subtype(PROP_UNSIGNED)
+ .description(N_("The number of edges on the curve"));
b.add_input<decl::Vector>(N_("Start"))
.default_value({-1.0f, 0.0f, 0.0f})
- .subtype(PROP_TRANSLATION);
+ .subtype(PROP_TRANSLATION)
+ .description(N_("Position of the first control point"));
b.add_input<decl::Vector>(N_("Middle"))
.default_value({0.0f, 2.0f, 0.0f})
- .subtype(PROP_TRANSLATION);
- b.add_input<decl::Vector>(N_("End")).default_value({1.0f, 0.0f, 0.0f}).subtype(PROP_TRANSLATION);
+ .subtype(PROP_TRANSLATION)
+ .description(N_("Position of the middle control point"));
+ b.add_input<decl::Vector>(N_("End"))
+ .default_value({1.0f, 0.0f, 0.0f})
+ .subtype(PROP_TRANSLATION)
+ .description(N_("Position of the last control point"));
b.add_output<decl::Geometry>(N_("Curve"));
}
@@ -58,7 +64,7 @@ static std::unique_ptr<CurveEval> create_quadratic_bezier_curve(const float3 p1,
return curve;
}
-static void geo_node_curve_primitive_quadratic_bezier_exec(GeoNodeExecParams params)
+static void node_geo_exec(GeoNodeExecParams params)
{
std::unique_ptr<CurveEval> curve = create_quadratic_bezier_curve(
params.extract_input<float3>("Start"),
@@ -68,17 +74,19 @@ static void geo_node_curve_primitive_quadratic_bezier_exec(GeoNodeExecParams par
params.set_output("Curve", GeometrySet::create_with_curve(curve.release()));
}
-} // namespace blender::nodes
+} // namespace blender::nodes::node_geo_curve_primitive_quadratic_bezier_cc
void register_node_type_geo_curve_primitive_quadratic_bezier()
{
+ namespace file_ns = blender::nodes::node_geo_curve_primitive_quadratic_bezier_cc;
+
static bNodeType ntype;
geo_node_type_base(&ntype,
GEO_NODE_CURVE_PRIMITIVE_QUADRATIC_BEZIER,
"Quadratic Bezier",
NODE_CLASS_GEOMETRY,
0);
- ntype.declare = blender::nodes::geo_node_curve_primitive_quadratic_bezier_declare;
- ntype.geometry_node_execute = blender::nodes::geo_node_curve_primitive_quadratic_bezier_exec;
+ ntype.declare = file_ns::node_declare;
+ ntype.geometry_node_execute = file_ns::node_geo_exec;
nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/geometry/nodes/node_geo_curve_primitive_quadrilateral.cc b/source/blender/nodes/geometry/nodes/node_geo_curve_primitive_quadrilateral.cc
index 7260da05a8d..53e301ecad7 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_curve_primitive_quadrilateral.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_curve_primitive_quadrilateral.cc
@@ -19,46 +19,70 @@
#include "UI_resources.h"
#include "node_geometry_util.hh"
-namespace blender::nodes {
+namespace blender::nodes::node_geo_curve_primitive_quadrilaterial_cc {
-static void geo_node_curve_primitive_quadrilateral_declare(NodeDeclarationBuilder &b)
+static void node_declare(NodeDeclarationBuilder &b)
{
- b.add_input<decl::Float>(N_("Width")).default_value(2.0f).min(0.0f).subtype(PROP_DISTANCE);
- b.add_input<decl::Float>(N_("Height")).default_value(2.0f).min(0.0f).subtype(PROP_DISTANCE);
+ b.add_input<decl::Float>(N_("Width"))
+ .default_value(2.0f)
+ .min(0.0f)
+ .subtype(PROP_DISTANCE)
+ .description(N_("The X axis size of the shape"));
+ b.add_input<decl::Float>(N_("Height"))
+ .default_value(2.0f)
+ .min(0.0f)
+ .subtype(PROP_DISTANCE)
+ .description(N_("The Y axis size of the shape"));
b.add_input<decl::Float>(N_("Bottom Width"))
.default_value(4.0f)
.min(0.0f)
- .subtype(PROP_DISTANCE);
- b.add_input<decl::Float>(N_("Top Width")).default_value(2.0f).min(0.0f).subtype(PROP_DISTANCE);
- b.add_input<decl::Float>(N_("Offset")).default_value(1.0f).subtype(PROP_DISTANCE);
+ .subtype(PROP_DISTANCE)
+ .description(N_("The X axis size of the shape"));
+ b.add_input<decl::Float>(N_("Top Width"))
+ .default_value(2.0f)
+ .min(0.0f)
+ .subtype(PROP_DISTANCE)
+ .description(N_("The X axis size of the shape"));
+ b.add_input<decl::Float>(N_("Offset"))
+ .default_value(1.0f)
+ .subtype(PROP_DISTANCE)
+ .description(
+ N_("For Parallelogram, the relative X difference between the top and bottom edges. For "
+ "Trapezoid, the amount to move the top edge in the positive X axis"));
b.add_input<decl::Float>(N_("Bottom Height"))
.default_value(3.0f)
.min(0.0f)
- .subtype(PROP_DISTANCE);
- b.add_input<decl::Float>(N_("Top Height")).default_value(1.0f).subtype(PROP_DISTANCE);
+ .subtype(PROP_DISTANCE)
+ .description(N_("The distance between the bottom point and the X axis"));
+ b.add_input<decl::Float>(N_("Top Height"))
+ .default_value(1.0f)
+ .subtype(PROP_DISTANCE)
+ .description(N_("The distance between the top point and the X axis"));
b.add_input<decl::Vector>(N_("Point 1"))
.default_value({-1.0f, -1.0f, 0.0f})
- .subtype(PROP_DISTANCE);
+ .subtype(PROP_DISTANCE)
+ .description(N_("The exact location of the point to use"));
b.add_input<decl::Vector>(N_("Point 2"))
.default_value({1.0f, -1.0f, 0.0f})
- .subtype(PROP_DISTANCE);
+ .subtype(PROP_DISTANCE)
+ .description(N_("The exact location of the point to use"));
b.add_input<decl::Vector>(N_("Point 3"))
.default_value({1.0f, 1.0f, 0.0f})
- .subtype(PROP_DISTANCE);
+ .subtype(PROP_DISTANCE)
+ .description(N_("The exact location of the point to use"));
b.add_input<decl::Vector>(N_("Point 4"))
.default_value({-1.0f, 1.0f, 0.0f})
- .subtype(PROP_DISTANCE);
+ .subtype(PROP_DISTANCE)
+ .description(N_("The exact location of the point to use"));
b.add_output<decl::Geometry>(N_("Curve"));
}
-static void geo_node_curve_primitive_quadrilateral_layout(uiLayout *layout,
- bContext *UNUSED(C),
- PointerRNA *ptr)
+static void node_layout(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
{
uiItemR(layout, ptr, "mode", 0, "", ICON_NONE);
}
-static void geo_node_curve_primitive_quadrilateral_init(bNodeTree *UNUSED(tree), bNode *node)
+static void node_init(bNodeTree *UNUSED(tree), bNode *node)
{
NodeGeometryCurvePrimitiveQuad *data = (NodeGeometryCurvePrimitiveQuad *)MEM_callocN(
sizeof(NodeGeometryCurvePrimitiveQuad), __func__);
@@ -66,7 +90,7 @@ static void geo_node_curve_primitive_quadrilateral_init(bNodeTree *UNUSED(tree),
node->storage = data;
}
-static void geo_node_curve_primitive_quadrilateral_update(bNodeTree *UNUSED(ntree), bNode *node)
+static void node_update(bNodeTree *ntree, bNode *node)
{
NodeGeometryCurvePrimitiveQuad &node_storage = *(NodeGeometryCurvePrimitiveQuad *)node->storage;
GeometryNodeCurvePrimitiveQuadMode mode = static_cast<GeometryNodeCurvePrimitiveQuadMode>(
@@ -85,34 +109,34 @@ static void geo_node_curve_primitive_quadrilateral_update(bNodeTree *UNUSED(ntre
bNodeSocket *p4 = p3->next;
LISTBASE_FOREACH (bNodeSocket *, sock, &node->inputs) {
- nodeSetSocketAvailability(sock, false);
+ nodeSetSocketAvailability(ntree, sock, false);
}
if (mode == GEO_NODE_CURVE_PRIMITIVE_QUAD_MODE_RECTANGLE) {
- nodeSetSocketAvailability(width, true);
- nodeSetSocketAvailability(height, true);
+ nodeSetSocketAvailability(ntree, width, true);
+ nodeSetSocketAvailability(ntree, height, true);
}
else if (mode == GEO_NODE_CURVE_PRIMITIVE_QUAD_MODE_PARALLELOGRAM) {
- nodeSetSocketAvailability(width, true);
- nodeSetSocketAvailability(height, true);
- nodeSetSocketAvailability(offset, true);
+ nodeSetSocketAvailability(ntree, width, true);
+ nodeSetSocketAvailability(ntree, height, true);
+ nodeSetSocketAvailability(ntree, offset, true);
}
else if (mode == GEO_NODE_CURVE_PRIMITIVE_QUAD_MODE_TRAPEZOID) {
- nodeSetSocketAvailability(bottom, true);
- nodeSetSocketAvailability(top, true);
- nodeSetSocketAvailability(offset, true);
- nodeSetSocketAvailability(height, true);
+ nodeSetSocketAvailability(ntree, bottom, true);
+ nodeSetSocketAvailability(ntree, top, true);
+ nodeSetSocketAvailability(ntree, offset, true);
+ nodeSetSocketAvailability(ntree, height, true);
}
else if (mode == GEO_NODE_CURVE_PRIMITIVE_QUAD_MODE_KITE) {
- nodeSetSocketAvailability(width, true);
- nodeSetSocketAvailability(bottom_height, true);
- nodeSetSocketAvailability(top_height, true);
+ nodeSetSocketAvailability(ntree, width, true);
+ nodeSetSocketAvailability(ntree, bottom_height, true);
+ nodeSetSocketAvailability(ntree, top_height, true);
}
else if (mode == GEO_NODE_CURVE_PRIMITIVE_QUAD_MODE_POINTS) {
- nodeSetSocketAvailability(p1, true);
- nodeSetSocketAvailability(p2, true);
- nodeSetSocketAvailability(p3, true);
- nodeSetSocketAvailability(p4, true);
+ nodeSetSocketAvailability(ntree, p1, true);
+ nodeSetSocketAvailability(ntree, p2, true);
+ nodeSetSocketAvailability(ntree, p3, true);
+ nodeSetSocketAvailability(ntree, p4, true);
}
}
@@ -171,7 +195,7 @@ static void create_kite_curve(MutableSpan<float3> positions,
positions[3] = float3(-width / 2.0f, 0, 0);
}
-static void geo_node_curve_primitive_quadrilateral_exec(GeoNodeExecParams params)
+static void node_geo_exec(GeoNodeExecParams params)
{
const NodeGeometryCurvePrimitiveQuad &node_storage =
*(NodeGeometryCurvePrimitiveQuad *)(params.node()).storage;
@@ -229,18 +253,20 @@ static void geo_node_curve_primitive_quadrilateral_exec(GeoNodeExecParams params
params.set_output("Curve", GeometrySet::create_with_curve(curve.release()));
}
-} // namespace blender::nodes
+} // namespace blender::nodes::node_geo_curve_primitive_quadrilaterial_cc
void register_node_type_geo_curve_primitive_quadrilateral()
{
+ namespace file_ns = blender::nodes::node_geo_curve_primitive_quadrilaterial_cc;
+
static bNodeType ntype;
geo_node_type_base(
&ntype, GEO_NODE_CURVE_PRIMITIVE_QUADRILATERAL, "Quadrilateral", NODE_CLASS_GEOMETRY, 0);
- ntype.declare = blender::nodes::geo_node_curve_primitive_quadrilateral_declare;
- ntype.geometry_node_execute = blender::nodes::geo_node_curve_primitive_quadrilateral_exec;
- ntype.draw_buttons = blender::nodes::geo_node_curve_primitive_quadrilateral_layout;
- node_type_update(&ntype, blender::nodes::geo_node_curve_primitive_quadrilateral_update);
- node_type_init(&ntype, blender::nodes::geo_node_curve_primitive_quadrilateral_init);
+ ntype.declare = file_ns::node_declare;
+ ntype.geometry_node_execute = file_ns::node_geo_exec;
+ ntype.draw_buttons = file_ns::node_layout;
+ node_type_update(&ntype, file_ns::node_update);
+ node_type_init(&ntype, file_ns::node_init);
node_type_storage(&ntype,
"NodeGeometryCurvePrimitiveQuad",
node_free_standard_storage,
diff --git a/source/blender/nodes/geometry/nodes/node_geo_curve_primitive_spiral.cc b/source/blender/nodes/geometry/nodes/node_geo_curve_primitive_spiral.cc
index 1dc9cd7f107..3be119a073f 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_curve_primitive_spiral.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_curve_primitive_spiral.cc
@@ -18,20 +18,34 @@
#include "node_geometry_util.hh"
-namespace blender::nodes {
+namespace blender::nodes::node_geo_curve_primitive_spiral_cc {
-static void geo_node_curve_primitive_spiral_declare(NodeDeclarationBuilder &b)
+static void node_declare(NodeDeclarationBuilder &b)
{
b.add_input<decl::Int>(N_("Resolution"))
.default_value(32)
.min(1)
.max(1024)
- .subtype(PROP_UNSIGNED);
- b.add_input<decl::Float>(N_("Rotations")).default_value(2.0f).min(0.0f);
- b.add_input<decl::Float>(N_("Start Radius")).default_value(1.0f).subtype(PROP_DISTANCE);
- b.add_input<decl::Float>(N_("End Radius")).default_value(2.0f).subtype(PROP_DISTANCE);
- b.add_input<decl::Float>(N_("Height")).default_value(2.0f).subtype(PROP_DISTANCE);
- b.add_input<decl::Bool>(N_("Reverse"));
+ .subtype(PROP_UNSIGNED)
+ .description(N_("Number of points in one rotation of the spiral"));
+ b.add_input<decl::Float>(N_("Rotations"))
+ .default_value(2.0f)
+ .min(0.0f)
+ .description(N_("Number of times the spiral makes a full rotation"));
+ b.add_input<decl::Float>(N_("Start Radius"))
+ .default_value(1.0f)
+ .subtype(PROP_DISTANCE)
+ .description(N_("Horizontal Distance from the Z axis at the start of the spiral"));
+ b.add_input<decl::Float>(N_("End Radius"))
+ .default_value(2.0f)
+ .subtype(PROP_DISTANCE)
+ .description(N_("Horizontal Distance from the Z axis at the end of the spiral"));
+ b.add_input<decl::Float>(N_("Height"))
+ .default_value(2.0f)
+ .subtype(PROP_DISTANCE)
+ .description(N_("The height perpendicular to the base of the spiral"));
+ b.add_input<decl::Bool>(N_("Reverse"))
+ .description(N_("Switch the direction from clockwise to counterclockwise"));
b.add_output<decl::Geometry>(N_("Curve"));
}
@@ -67,7 +81,7 @@ static std::unique_ptr<CurveEval> create_spiral_curve(const float rotations,
return curve;
}
-static void geo_node_curve_primitive_spiral_exec(GeoNodeExecParams params)
+static void node_geo_exec(GeoNodeExecParams params)
{
const float rotations = std::max(params.extract_input<float>("Rotations"), 0.0f);
if (rotations == 0.0f) {
@@ -85,14 +99,16 @@ static void geo_node_curve_primitive_spiral_exec(GeoNodeExecParams params)
params.set_output("Curve", GeometrySet::create_with_curve(curve.release()));
}
-} // namespace blender::nodes
+} // namespace blender::nodes::node_geo_curve_primitive_spiral_cc
void register_node_type_geo_curve_primitive_spiral()
{
+ namespace file_ns = blender::nodes::node_geo_curve_primitive_spiral_cc;
+
static bNodeType ntype;
geo_node_type_base(&ntype, GEO_NODE_CURVE_PRIMITIVE_SPIRAL, "Spiral", NODE_CLASS_GEOMETRY, 0);
- ntype.declare = blender::nodes::geo_node_curve_primitive_spiral_declare;
- ntype.geometry_node_execute = blender::nodes::geo_node_curve_primitive_spiral_exec;
+ ntype.declare = file_ns::node_declare;
+ ntype.geometry_node_execute = file_ns::node_geo_exec;
nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/geometry/nodes/node_geo_curve_primitive_star.cc b/source/blender/nodes/geometry/nodes/node_geo_curve_primitive_star.cc
index b5bafce17c6..731be0f0f49 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_curve_primitive_star.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_curve_primitive_star.cc
@@ -18,21 +18,33 @@
#include "node_geometry_util.hh"
-namespace blender::nodes {
+namespace blender::nodes::node_geo_curve_primitive_star_cc {
-static void geo_node_curve_primitive_star_declare(NodeDeclarationBuilder &b)
+static void node_declare(NodeDeclarationBuilder &b)
{
- b.add_input<decl::Int>(N_("Points")).default_value(8).min(3).max(256).subtype(PROP_UNSIGNED);
+ b.add_input<decl::Int>(N_("Points"))
+ .default_value(8)
+ .min(3)
+ .max(256)
+ .subtype(PROP_UNSIGNED)
+ .description(N_("Number of points on each of the circles"));
b.add_input<decl::Float>(N_("Inner Radius"))
.default_value(1.0f)
.min(0.0f)
- .subtype(PROP_DISTANCE);
+ .subtype(PROP_DISTANCE)
+ .description(N_("Radius of the inner circle; can be larger than outer radius"));
b.add_input<decl::Float>(N_("Outer Radius"))
.default_value(2.0f)
.min(0.0f)
- .subtype(PROP_DISTANCE);
- b.add_input<decl::Float>(N_("Twist")).subtype(PROP_ANGLE);
+ .subtype(PROP_DISTANCE)
+ .description(N_("Radius of the outer circle; can be smaller than inner radius"));
+ b.add_input<decl::Float>(N_("Twist"))
+ .subtype(PROP_ANGLE)
+ .description(N_("The counterclockwise rotation of the inner set of points"));
b.add_output<decl::Geometry>(N_("Curve"));
+ b.add_output<decl::Bool>(N_("Outer Points"))
+ .field_source()
+ .description(N_("An attribute field with a selection of the outer points"));
}
static std::unique_ptr<CurveEval> create_star_curve(const float inner_radius,
@@ -57,26 +69,49 @@ static std::unique_ptr<CurveEval> create_star_curve(const float inner_radius,
spline->attributes.reallocate(spline->size());
curve->add_spline(std::move(spline));
curve->attributes.reallocate(curve->splines().size());
+
return curve;
}
-static void geo_node_curve_primitive_star_exec(GeoNodeExecParams params)
+static void create_selection_output(CurveComponent &component,
+ StrongAnonymousAttributeID &r_attribute)
+{
+ OutputAttribute_Typed<bool> attribute = component.attribute_try_get_for_output_only<bool>(
+ r_attribute.get(), ATTR_DOMAIN_POINT);
+ MutableSpan<bool> selection = attribute.as_span();
+ for (int i : selection.index_range()) {
+ selection[i] = i % 2 == 0;
+ }
+ attribute.save();
+}
+
+static void node_geo_exec(GeoNodeExecParams params)
{
std::unique_ptr<CurveEval> curve = create_star_curve(
std::max(params.extract_input<float>("Inner Radius"), 0.0f),
std::max(params.extract_input<float>("Outer Radius"), 0.0f),
params.extract_input<float>("Twist"),
std::max(params.extract_input<int>("Points"), 3));
- params.set_output("Curve", GeometrySet::create_with_curve(curve.release()));
-}
+ GeometrySet output = GeometrySet::create_with_curve(curve.release());
-} // namespace blender::nodes
+ if (params.output_is_required("Outer Points")) {
+ StrongAnonymousAttributeID attribute_output("Outer Points");
+ create_selection_output(output.get_component_for_write<CurveComponent>(), attribute_output);
+ params.set_output("Outer Points",
+ AnonymousAttributeFieldInput::Create<bool>(
+ std::move(attribute_output), params.attribute_producer_name()));
+ }
+ params.set_output("Curve", std::move(output));
+}
+} // namespace blender::nodes::node_geo_curve_primitive_star_cc
void register_node_type_geo_curve_primitive_star()
{
+ namespace file_ns = blender::nodes::node_geo_curve_primitive_star_cc;
+
static bNodeType ntype;
geo_node_type_base(&ntype, GEO_NODE_CURVE_PRIMITIVE_STAR, "Star", NODE_CLASS_GEOMETRY, 0);
- ntype.declare = blender::nodes::geo_node_curve_primitive_star_declare;
- ntype.geometry_node_execute = blender::nodes::geo_node_curve_primitive_star_exec;
+ ntype.declare = file_ns::node_declare;
+ ntype.geometry_node_execute = file_ns::node_geo_exec;
nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/geometry/nodes/node_geo_curve_resample.cc b/source/blender/nodes/geometry/nodes/node_geo_curve_resample.cc
index 945dac5650b..dec72eb61bb 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_curve_resample.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_curve_resample.cc
@@ -26,15 +26,12 @@
#include "node_geometry_util.hh"
-using blender::fn::GVArray_For_GSpan;
-using blender::fn::GVArray_For_Span;
-using blender::fn::GVArray_Typed;
+namespace blender::nodes::node_geo_curve_resample_cc {
-namespace blender::nodes {
-
-static void geo_node_curve_resample_declare(NodeDeclarationBuilder &b)
+static void node_declare(NodeDeclarationBuilder &b)
{
b.add_input<decl::Geometry>(N_("Curve")).supported_type(GEO_COMPONENT_TYPE_CURVE);
+ b.add_input<decl::Bool>(N_("Selection")).default_value(true).supports_field().hide_value();
b.add_input<decl::Int>(N_("Count")).default_value(10).min(1).max(100000).supports_field();
b.add_input<decl::Float>(N_("Length"))
.default_value(0.1f)
@@ -44,12 +41,12 @@ static void geo_node_curve_resample_declare(NodeDeclarationBuilder &b)
b.add_output<decl::Geometry>(N_("Curve"));
}
-static void geo_node_curve_resample_layout(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
+static void node_layout(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
{
uiItemR(layout, ptr, "mode", 0, "", ICON_NONE);
}
-static void geo_node_curve_resample_init(bNodeTree *UNUSED(tree), bNode *node)
+static void node_init(bNodeTree *UNUSED(tree), bNode *node)
{
NodeGeometryCurveResample *data = (NodeGeometryCurveResample *)MEM_callocN(
sizeof(NodeGeometryCurveResample), __func__);
@@ -58,22 +55,23 @@ static void geo_node_curve_resample_init(bNodeTree *UNUSED(tree), bNode *node)
node->storage = data;
}
-static void geo_node_curve_resample_update(bNodeTree *UNUSED(ntree), bNode *node)
+static void node_update(bNodeTree *ntree, bNode *node)
{
NodeGeometryCurveResample &node_storage = *(NodeGeometryCurveResample *)node->storage;
const GeometryNodeCurveResampleMode mode = (GeometryNodeCurveResampleMode)node_storage.mode;
- bNodeSocket *count_socket = ((bNodeSocket *)node->inputs.first)->next;
+ bNodeSocket *count_socket = ((bNodeSocket *)node->inputs.first)->next->next;
bNodeSocket *length_socket = count_socket->next;
- nodeSetSocketAvailability(count_socket, mode == GEO_NODE_CURVE_RESAMPLE_COUNT);
- nodeSetSocketAvailability(length_socket, mode == GEO_NODE_CURVE_RESAMPLE_LENGTH);
+ nodeSetSocketAvailability(ntree, count_socket, mode == GEO_NODE_CURVE_RESAMPLE_COUNT);
+ nodeSetSocketAvailability(ntree, length_socket, mode == GEO_NODE_CURVE_RESAMPLE_LENGTH);
}
struct SampleModeParam {
GeometryNodeCurveResampleMode mode;
std::optional<Field<float>> length;
std::optional<Field<int>> count;
+ Field<bool> selection;
};
static SplinePtr resample_spline(const Spline &src, const int count)
@@ -122,7 +120,7 @@ static SplinePtr resample_spline(const Spline &src, const int count)
std::optional<GMutableSpan> output_attribute = dst->attributes.get_for_write(
attribute_id);
if (output_attribute) {
- src.sample_with_index_factors(*src.interpolate_to_evaluated(*input_attribute),
+ src.sample_with_index_factors(src.interpolate_to_evaluated(*input_attribute),
uniform_samples,
*output_attribute);
return true;
@@ -145,8 +143,8 @@ static SplinePtr resample_spline_evaluated(const Spline &src)
dst->positions().copy_from(src.evaluated_positions());
dst->positions().copy_from(src.evaluated_positions());
- src.interpolate_to_evaluated(src.radii())->materialize(dst->radii());
- src.interpolate_to_evaluated(src.tilts())->materialize(dst->tilts());
+ src.interpolate_to_evaluated(src.radii()).materialize(dst->radii());
+ src.interpolate_to_evaluated(src.tilts()).materialize(dst->tilts());
src.attributes.foreach_attribute(
[&](const AttributeIDRef &attribute_id, const AttributeMetaData &meta_data) {
@@ -154,7 +152,7 @@ static SplinePtr resample_spline_evaluated(const Spline &src)
if (dst->attributes.create(attribute_id, meta_data.data_type)) {
std::optional<GMutableSpan> dst_attribute = dst->attributes.get_for_write(attribute_id);
if (dst_attribute) {
- src.interpolate_to_evaluated(*src_attribute)->materialize(dst_attribute->data());
+ src.interpolate_to_evaluated(*src_attribute).materialize(dst_attribute->data());
return true;
}
}
@@ -183,42 +181,64 @@ static std::unique_ptr<CurveEval> resample_curve(const CurveComponent *component
if (mode_param.mode == GEO_NODE_CURVE_RESAMPLE_COUNT) {
fn::FieldEvaluator evaluator{field_context, domain_size};
evaluator.add(*mode_param.count);
+ evaluator.add(mode_param.selection);
evaluator.evaluate();
const VArray<int> &cuts = evaluator.get_evaluated<int>(0);
+ const VArray<bool> &selections = evaluator.get_evaluated<bool>(1);
threading::parallel_for(input_splines.index_range(), 128, [&](IndexRange range) {
for (const int i : range) {
BLI_assert(mode_param.count);
- output_splines[i] = resample_spline(*input_splines[i], std::max(cuts[i], 1));
+ if (selections[i]) {
+ output_splines[i] = resample_spline(*input_splines[i], std::max(cuts[i], 1));
+ }
+ else {
+ output_splines[i] = input_splines[i]->copy();
+ }
}
});
}
else if (mode_param.mode == GEO_NODE_CURVE_RESAMPLE_LENGTH) {
fn::FieldEvaluator evaluator{field_context, domain_size};
evaluator.add(*mode_param.length);
+ evaluator.add(mode_param.selection);
evaluator.evaluate();
const VArray<float> &lengths = evaluator.get_evaluated<float>(0);
+ const VArray<bool> &selections = evaluator.get_evaluated<bool>(1);
threading::parallel_for(input_splines.index_range(), 128, [&](IndexRange range) {
for (const int i : range) {
- /* Don't allow asymptotic count increase for low resolution values. */
- const float divide_length = std::max(lengths[i], 0.0001f);
- const float spline_length = input_splines[i]->length();
- const int count = std::max(int(spline_length / divide_length) + 1, 1);
- output_splines[i] = resample_spline(*input_splines[i], count);
+ if (selections[i]) {
+ /* Don't allow asymptotic count increase for low resolution values. */
+ const float divide_length = std::max(lengths[i], 0.0001f);
+ const float spline_length = input_splines[i]->length();
+ const int count = std::max(int(spline_length / divide_length) + 1, 1);
+ output_splines[i] = resample_spline(*input_splines[i], count);
+ }
+ else {
+ output_splines[i] = input_splines[i]->copy();
+ }
}
});
}
else if (mode_param.mode == GEO_NODE_CURVE_RESAMPLE_EVALUATED) {
+ fn::FieldEvaluator evaluator{field_context, domain_size};
+ evaluator.add(mode_param.selection);
+ evaluator.evaluate();
+ const VArray<bool> &selections = evaluator.get_evaluated<bool>(0);
+
threading::parallel_for(input_splines.index_range(), 128, [&](IndexRange range) {
for (const int i : range) {
- output_splines[i] = resample_spline_evaluated(*input_splines[i]);
+ if (selections[i]) {
+ output_splines[i] = resample_spline_evaluated(*input_splines[i]);
+ }
+ else {
+ output_splines[i] = input_splines[i]->copy();
+ }
}
});
}
-
output_curve->attributes = input_curve->attributes;
-
return output_curve;
}
@@ -235,7 +255,7 @@ static void geometry_set_curve_resample(GeometrySet &geometry_set,
geometry_set.replace_curve(output_curve.release());
}
-static void geo_node_resample_exec(GeoNodeExecParams params)
+static void node_geo_exec(GeoNodeExecParams params)
{
GeometrySet geometry_set = params.extract_input<GeometrySet>("Curve");
@@ -244,6 +264,8 @@ static void geo_node_resample_exec(GeoNodeExecParams params)
SampleModeParam mode_param;
mode_param.mode = mode;
+ mode_param.selection = params.extract_input<Field<bool>>("Selection");
+
if (mode == GEO_NODE_CURVE_RESAMPLE_COUNT) {
Field<int> count = params.extract_input<Field<int>>("Count");
if (count < 1) {
@@ -263,19 +285,21 @@ static void geo_node_resample_exec(GeoNodeExecParams params)
params.set_output("Curve", std::move(geometry_set));
}
-} // namespace blender::nodes
+} // namespace blender::nodes::node_geo_curve_resample_cc
void register_node_type_geo_curve_resample()
{
+ namespace file_ns = blender::nodes::node_geo_curve_resample_cc;
+
static bNodeType ntype;
geo_node_type_base(&ntype, GEO_NODE_RESAMPLE_CURVE, "Resample Curve", NODE_CLASS_GEOMETRY, 0);
- ntype.declare = blender::nodes::geo_node_curve_resample_declare;
- ntype.draw_buttons = blender::nodes::geo_node_curve_resample_layout;
+ ntype.declare = file_ns::node_declare;
+ ntype.draw_buttons = file_ns::node_layout;
node_type_storage(
&ntype, "NodeGeometryCurveResample", node_free_standard_storage, node_copy_standard_storage);
- node_type_init(&ntype, blender::nodes::geo_node_curve_resample_init);
- node_type_update(&ntype, blender::nodes::geo_node_curve_resample_update);
- ntype.geometry_node_execute = blender::nodes::geo_node_resample_exec;
+ node_type_init(&ntype, file_ns::node_init);
+ node_type_update(&ntype, file_ns::node_update);
+ ntype.geometry_node_execute = file_ns::node_geo_exec;
nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/geometry/nodes/node_geo_curve_reverse.cc b/source/blender/nodes/geometry/nodes/node_geo_curve_reverse.cc
index b1dc45a426a..d07e89ec7f2 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_curve_reverse.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_curve_reverse.cc
@@ -20,16 +20,16 @@
#include "node_geometry_util.hh"
-namespace blender::nodes {
+namespace blender::nodes::node_geo_curve_reverse_cc {
-static void geo_node_curve_reverse_declare(NodeDeclarationBuilder &b)
+static void node_declare(NodeDeclarationBuilder &b)
{
b.add_input<decl::Geometry>(N_("Curve")).supported_type(GEO_COMPONENT_TYPE_CURVE);
b.add_input<decl::Bool>(N_("Selection")).default_value(true).hide_value().supports_field();
b.add_output<decl::Geometry>(N_("Curve"));
}
-static void geo_node_curve_reverse_exec(GeoNodeExecParams params)
+static void node_geo_exec(GeoNodeExecParams params)
{
GeometrySet geometry_set = params.extract_input<GeometrySet>("Curve");
@@ -60,13 +60,15 @@ static void geo_node_curve_reverse_exec(GeoNodeExecParams params)
params.set_output("Curve", std::move(geometry_set));
}
-} // namespace blender::nodes
+} // namespace blender::nodes::node_geo_curve_reverse_cc
void register_node_type_geo_curve_reverse()
{
+ namespace file_ns = blender::nodes::node_geo_curve_reverse_cc;
+
static bNodeType ntype;
geo_node_type_base(&ntype, GEO_NODE_REVERSE_CURVE, "Reverse Curve", NODE_CLASS_GEOMETRY, 0);
- ntype.declare = blender::nodes::geo_node_curve_reverse_declare;
- ntype.geometry_node_execute = blender::nodes::geo_node_curve_reverse_exec;
+ ntype.declare = file_ns::node_declare;
+ ntype.geometry_node_execute = file_ns::node_geo_exec;
nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/geometry/nodes/node_geo_curve_sample.cc b/source/blender/nodes/geometry/nodes/node_geo_curve_sample.cc
index 31b38c0dce7..b81860ca9b3 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_curve_sample.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_curve_sample.cc
@@ -23,9 +23,9 @@
#include "node_geometry_util.hh"
-namespace blender::nodes {
+namespace blender::nodes::node_geo_curve_sample_cc {
-static void geo_node_curve_sample_declare(NodeDeclarationBuilder &b)
+static void node_declare(NodeDeclarationBuilder &b)
{
b.add_input<decl::Geometry>(N_("Curve"))
.only_realized_data()
@@ -38,12 +38,12 @@ static void geo_node_curve_sample_declare(NodeDeclarationBuilder &b)
b.add_output<decl::Vector>(N_("Normal")).dependent_field();
}
-static void geo_node_curve_sample_layout(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
+static void node_layout(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
{
uiItemR(layout, ptr, "mode", UI_ITEM_R_EXPAND, nullptr, ICON_NONE);
}
-static void geo_node_curve_sample_type_init(bNodeTree *UNUSED(tree), bNode *node)
+static void node_type_init(bNodeTree *UNUSED(tree), bNode *node)
{
NodeGeometryCurveSample *data = (NodeGeometryCurveSample *)MEM_callocN(
sizeof(NodeGeometryCurveSample), __func__);
@@ -51,7 +51,7 @@ static void geo_node_curve_sample_type_init(bNodeTree *UNUSED(tree), bNode *node
node->storage = data;
}
-static void geo_node_curve_sample_update(bNodeTree *UNUSED(ntree), bNode *node)
+static void node_update(bNodeTree *ntree, bNode *node)
{
const NodeGeometryCurveSample &node_storage = *(NodeGeometryCurveSample *)node->storage;
const GeometryNodeCurveSampleMode mode = (GeometryNodeCurveSampleMode)node_storage.mode;
@@ -59,8 +59,8 @@ static void geo_node_curve_sample_update(bNodeTree *UNUSED(ntree), bNode *node)
bNodeSocket *factor = ((bNodeSocket *)node->inputs.first)->next;
bNodeSocket *length = factor->next;
- nodeSetSocketAvailability(factor, mode == GEO_NODE_CURVE_SAMPLE_FACTOR);
- nodeSetSocketAvailability(length, mode == GEO_NODE_CURVE_SAMPLE_LENGTH);
+ nodeSetSocketAvailability(ntree, factor, mode == GEO_NODE_CURVE_SAMPLE_FACTOR);
+ nodeSetSocketAvailability(ntree, length, mode == GEO_NODE_CURVE_SAMPLE_LENGTH);
}
template<typename T> static T sample_with_lookup(const Spline::LookupResult lookup, Span<T> data)
@@ -229,7 +229,7 @@ static Field<float> get_length_input_field(const GeoNodeExecParams &params,
return Field<float>(std::move(process_op), 0);
}
-static void geo_node_curve_sample_exec(GeoNodeExecParams params)
+static void node_geo_exec(GeoNodeExecParams params)
{
GeometrySet geometry_set = params.extract_input<GeometrySet>("Curve");
@@ -271,20 +271,22 @@ static void geo_node_curve_sample_exec(GeoNodeExecParams params)
params.set_output("Normal", Field<float3>(sample_op, 2));
}
-} // namespace blender::nodes
+} // namespace blender::nodes::node_geo_curve_sample_cc
void register_node_type_geo_curve_sample()
{
+ namespace file_ns = blender::nodes::node_geo_curve_sample_cc;
+
static bNodeType ntype;
geo_node_type_base(&ntype, GEO_NODE_SAMPLE_CURVE, " Sample Curve", NODE_CLASS_GEOMETRY, 0);
- ntype.geometry_node_execute = blender::nodes::geo_node_curve_sample_exec;
- ntype.declare = blender::nodes::geo_node_curve_sample_declare;
- node_type_init(&ntype, blender::nodes::geo_node_curve_sample_type_init);
- node_type_update(&ntype, blender::nodes::geo_node_curve_sample_update);
+ ntype.geometry_node_execute = file_ns::node_geo_exec;
+ ntype.declare = file_ns::node_declare;
+ node_type_init(&ntype, file_ns::node_type_init);
+ node_type_update(&ntype, file_ns::node_update);
node_type_storage(
&ntype, "NodeGeometryCurveSample", node_free_standard_storage, node_copy_standard_storage);
- ntype.draw_buttons = blender::nodes::geo_node_curve_sample_layout;
+ ntype.draw_buttons = file_ns::node_layout;
nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/geometry/nodes/node_geo_curve_set_handles.cc b/source/blender/nodes/geometry/nodes/node_geo_curve_set_handles.cc
index 8b0a6ca840c..d769228f9e7 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_curve_set_handles.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_curve_set_handles.cc
@@ -21,24 +21,22 @@
#include "node_geometry_util.hh"
-namespace blender::nodes {
+namespace blender::nodes::node_geo_curve_set_handles_cc {
-static void geo_node_curve_set_handles_declare(NodeDeclarationBuilder &b)
+static void node_declare(NodeDeclarationBuilder &b)
{
b.add_input<decl::Geometry>(N_("Curve")).supported_type(GEO_COMPONENT_TYPE_CURVE);
b.add_input<decl::Bool>(N_("Selection")).default_value(true).hide_value().supports_field();
b.add_output<decl::Geometry>(N_("Curve"));
}
-static void geo_node_curve_set_handles_layout(uiLayout *layout,
- bContext *UNUSED(C),
- PointerRNA *ptr)
+static void node_layout(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
{
uiItemR(layout, ptr, "mode", UI_ITEM_R_EXPAND, nullptr, ICON_NONE);
uiItemR(layout, ptr, "handle_type", 0, "", ICON_NONE);
}
-static void geo_node_curve_set_handles_init(bNodeTree *UNUSED(tree), bNode *node)
+static void node_init(bNodeTree *UNUSED(tree), bNode *node)
{
NodeGeometryCurveSetHandles *data = (NodeGeometryCurveSetHandles *)MEM_callocN(
sizeof(NodeGeometryCurveSetHandles), __func__);
@@ -64,7 +62,7 @@ static BezierSpline::HandleType handle_type_from_input_type(GeometryNodeCurveHan
return BezierSpline::HandleType::Auto;
}
-static void geo_node_curve_set_handles_exec(GeoNodeExecParams params)
+static void node_geo_exec(GeoNodeExecParams params)
{
const NodeGeometryCurveSetHandles *node_storage =
(NodeGeometryCurveSetHandles *)params.node().storage;
@@ -130,21 +128,23 @@ static void geo_node_curve_set_handles_exec(GeoNodeExecParams params)
}
params.set_output("Curve", std::move(geometry_set));
}
-} // namespace blender::nodes
+} // namespace blender::nodes::node_geo_curve_set_handles_cc
void register_node_type_geo_curve_set_handles()
{
+ namespace file_ns = blender::nodes::node_geo_curve_set_handles_cc;
+
static bNodeType ntype;
geo_node_type_base(
&ntype, GEO_NODE_CURVE_SET_HANDLES, "Set Handle Type", NODE_CLASS_GEOMETRY, 0);
- ntype.declare = blender::nodes::geo_node_curve_set_handles_declare;
- ntype.geometry_node_execute = blender::nodes::geo_node_curve_set_handles_exec;
- node_type_init(&ntype, blender::nodes::geo_node_curve_set_handles_init);
+ ntype.declare = file_ns::node_declare;
+ ntype.geometry_node_execute = file_ns::node_geo_exec;
+ node_type_init(&ntype, file_ns::node_init);
node_type_storage(&ntype,
"NodeGeometryCurveSetHandles",
node_free_standard_storage,
node_copy_standard_storage);
- ntype.draw_buttons = blender::nodes::geo_node_curve_set_handles_layout;
+ ntype.draw_buttons = file_ns::node_layout;
nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/geometry/nodes/node_geo_curve_spline_type.cc b/source/blender/nodes/geometry/nodes/node_geo_curve_spline_type.cc
index ae4453929ac..1d859c8555f 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_curve_spline_type.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_curve_spline_type.cc
@@ -23,23 +23,21 @@
#include "node_geometry_util.hh"
-namespace blender::nodes {
+namespace blender::nodes::node_geo_curve_spline_type_cc {
-static void geo_node_curve_spline_type_declare(NodeDeclarationBuilder &b)
+static void node_declare(NodeDeclarationBuilder &b)
{
b.add_input<decl::Geometry>(N_("Curve")).supported_type(GEO_COMPONENT_TYPE_CURVE);
b.add_input<decl::Bool>(N_("Selection")).default_value(true).hide_value().supports_field();
b.add_output<decl::Geometry>(N_("Curve"));
}
-static void geo_node_curve_spline_type_layout(uiLayout *layout,
- bContext *UNUSED(C),
- PointerRNA *ptr)
+static void node_layout(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
{
uiItemR(layout, ptr, "spline_type", 0, "", ICON_NONE);
}
-static void geo_node_curve_spline_type_init(bNodeTree *UNUSED(tree), bNode *node)
+static void node_init(bNodeTree *UNUSED(tree), bNode *node)
{
NodeGeometryCurveSplineType *data = (NodeGeometryCurveSplineType *)MEM_callocN(
sizeof(NodeGeometryCurveSplineType), __func__);
@@ -238,7 +236,7 @@ static SplinePtr convert_to_nurbs(const Spline &input)
return {};
}
-static void geo_node_curve_spline_type_exec(GeoNodeExecParams params)
+static void node_geo_exec(GeoNodeExecParams params)
{
const NodeGeometryCurveSplineType *storage =
(const NodeGeometryCurveSplineType *)params.node().storage;
@@ -288,21 +286,23 @@ static void geo_node_curve_spline_type_exec(GeoNodeExecParams params)
params.set_output("Curve", std::move(geometry_set));
}
-} // namespace blender::nodes
+} // namespace blender::nodes::node_geo_curve_spline_type_cc
void register_node_type_geo_curve_spline_type()
{
+ namespace file_ns = blender::nodes::node_geo_curve_spline_type_cc;
+
static bNodeType ntype;
geo_node_type_base(
&ntype, GEO_NODE_CURVE_SPLINE_TYPE, "Set Spline Type", NODE_CLASS_GEOMETRY, 0);
- ntype.declare = blender::nodes::geo_node_curve_spline_type_declare;
- ntype.geometry_node_execute = blender::nodes::geo_node_curve_spline_type_exec;
- node_type_init(&ntype, blender::nodes::geo_node_curve_spline_type_init);
+ ntype.declare = file_ns::node_declare;
+ ntype.geometry_node_execute = file_ns::node_geo_exec;
+ node_type_init(&ntype, file_ns::node_init);
node_type_storage(&ntype,
"NodeGeometryCurveSplineType",
node_free_standard_storage,
node_copy_standard_storage);
- ntype.draw_buttons = blender::nodes::geo_node_curve_spline_type_layout;
+ ntype.draw_buttons = file_ns::node_layout;
nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/geometry/nodes/node_geo_curve_subdivide.cc b/source/blender/nodes/geometry/nodes/node_geo_curve_subdivide.cc
index b52de822c22..6de188fc1c4 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_curve_subdivide.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_curve_subdivide.cc
@@ -25,13 +25,9 @@
#include "node_geometry_util.hh"
-using blender::fn::GVArray_For_GSpan;
-using blender::fn::GVArray_For_Span;
-using blender::fn::GVArray_Typed;
+namespace blender::nodes::node_geo_curve_subdivide_cc {
-namespace blender::nodes {
-
-static void geo_node_curve_subdivide_declare(NodeDeclarationBuilder &b)
+static void node_declare(NodeDeclarationBuilder &b)
{
b.add_input<decl::Geometry>(N_("Curve")).supported_type(GEO_COMPONENT_TYPE_CURVE);
b.add_input<decl::Int>(N_("Cuts")).default_value(1).min(0).max(1000).supports_field();
@@ -326,7 +322,7 @@ static std::unique_ptr<CurveEval> subdivide_curve(const CurveEval &input_curve,
return output_curve;
}
-static void geo_node_subdivide_exec(GeoNodeExecParams params)
+static void node_geo_exec(GeoNodeExecParams params)
{
GeometrySet geometry_set = params.extract_input<GeometrySet>("Curve");
Field<int> cuts_field = params.extract_input<Field<int>>("Cuts");
@@ -355,14 +351,16 @@ static void geo_node_subdivide_exec(GeoNodeExecParams params)
params.set_output("Curve", geometry_set);
}
-} // namespace blender::nodes
+} // namespace blender::nodes::node_geo_curve_subdivide_cc
void register_node_type_geo_curve_subdivide()
{
+ namespace file_ns = blender::nodes::node_geo_curve_subdivide_cc;
+
static bNodeType ntype;
geo_node_type_base(&ntype, GEO_NODE_SUBDIVIDE_CURVE, "Subdivide Curve", NODE_CLASS_GEOMETRY, 0);
- ntype.declare = blender::nodes::geo_node_curve_subdivide_declare;
- ntype.geometry_node_execute = blender::nodes::geo_node_subdivide_exec;
+ ntype.declare = file_ns::node_declare;
+ ntype.geometry_node_execute = file_ns::node_geo_exec;
nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/geometry/nodes/node_geo_curve_to_mesh.cc b/source/blender/nodes/geometry/nodes/node_geo_curve_to_mesh.cc
index 1977b465de4..ff3e85cb6b7 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_curve_to_mesh.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_curve_to_mesh.cc
@@ -23,9 +23,9 @@
#include "node_geometry_util.hh"
-namespace blender::nodes {
+namespace blender::nodes::node_geo_curve_to_mesh_cc {
-static void geo_node_curve_to_mesh_declare(NodeDeclarationBuilder &b)
+static void node_declare(NodeDeclarationBuilder &b)
{
b.add_input<decl::Geometry>(N_("Curve")).supported_type(GEO_COMPONENT_TYPE_CURVE);
b.add_input<decl::Geometry>(N_("Profile Curve"))
@@ -54,7 +54,7 @@ static void geometry_set_curve_to_mesh(GeometrySet &geometry_set,
}
}
-static void geo_node_curve_to_mesh_exec(GeoNodeExecParams params)
+static void node_geo_exec(GeoNodeExecParams params)
{
GeometrySet curve_set = params.extract_input<GeometrySet>("Curve");
GeometrySet profile_set = params.extract_input<GeometrySet>("Profile Curve");
@@ -72,14 +72,16 @@ static void geo_node_curve_to_mesh_exec(GeoNodeExecParams params)
params.set_output("Mesh", std::move(curve_set));
}
-} // namespace blender::nodes
+} // namespace blender::nodes::node_geo_curve_to_mesh_cc
void register_node_type_geo_curve_to_mesh()
{
+ namespace file_ns = blender::nodes::node_geo_curve_to_mesh_cc;
+
static bNodeType ntype;
geo_node_type_base(&ntype, GEO_NODE_CURVE_TO_MESH, "Curve to Mesh", NODE_CLASS_GEOMETRY, 0);
- ntype.declare = blender::nodes::geo_node_curve_to_mesh_declare;
- ntype.geometry_node_execute = blender::nodes::geo_node_curve_to_mesh_exec;
+ ntype.declare = file_ns::node_declare;
+ ntype.geometry_node_execute = file_ns::node_geo_exec;
nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/geometry/nodes/node_geo_curve_to_points.cc b/source/blender/nodes/geometry/nodes/node_geo_curve_to_points.cc
index 38d7fb99e87..1901097c369 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_curve_to_points.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_curve_to_points.cc
@@ -27,8 +27,22 @@
#include "node_geometry_util.hh"
namespace blender::nodes {
+void curve_create_default_rotation_attribute(Span<float3> tangents,
+ Span<float3> normals,
+ MutableSpan<float3> rotations)
+{
+ threading::parallel_for(IndexRange(rotations.size()), 512, [&](IndexRange range) {
+ for (const int i : range) {
+ rotations[i] =
+ float4x4::from_normalized_axis_data({0, 0, 0}, normals[i], tangents[i]).to_euler();
+ }
+ });
+}
+} // namespace blender::nodes
+
+namespace blender::nodes::node_geo_curve_to_points_cc {
-static void geo_node_curve_to_points_declare(NodeDeclarationBuilder &b)
+static void node_declare(NodeDeclarationBuilder &b)
{
b.add_input<decl::Geometry>(N_("Curve")).supported_type(GEO_COMPONENT_TYPE_CURVE);
b.add_input<decl::Int>(N_("Count")).default_value(10).min(2).max(100000);
@@ -39,12 +53,12 @@ static void geo_node_curve_to_points_declare(NodeDeclarationBuilder &b)
b.add_output<decl::Vector>(N_("Rotation")).field_source();
}
-static void geo_node_curve_to_points_layout(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
+static void node_layout(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
{
uiItemR(layout, ptr, "mode", 0, "", ICON_NONE);
}
-static void geo_node_curve_to_points_init(bNodeTree *UNUSED(tree), bNode *node)
+static void node_init(bNodeTree *UNUSED(tree), bNode *node)
{
NodeGeometryCurveToPoints *data = (NodeGeometryCurveToPoints *)MEM_callocN(
sizeof(NodeGeometryCurveToPoints), __func__);
@@ -53,7 +67,7 @@ static void geo_node_curve_to_points_init(bNodeTree *UNUSED(tree), bNode *node)
node->storage = data;
}
-static void geo_node_curve_to_points_update(bNodeTree *UNUSED(ntree), bNode *node)
+static void node_update(bNodeTree *ntree, bNode *node)
{
NodeGeometryCurveToPoints &node_storage = *(NodeGeometryCurveToPoints *)node->storage;
const GeometryNodeCurveResampleMode mode = (GeometryNodeCurveResampleMode)node_storage.mode;
@@ -61,8 +75,8 @@ static void geo_node_curve_to_points_update(bNodeTree *UNUSED(ntree), bNode *nod
bNodeSocket *count_socket = ((bNodeSocket *)node->inputs.first)->next;
bNodeSocket *length_socket = count_socket->next;
- nodeSetSocketAvailability(count_socket, mode == GEO_NODE_CURVE_RESAMPLE_COUNT);
- nodeSetSocketAvailability(length_socket, mode == GEO_NODE_CURVE_RESAMPLE_LENGTH);
+ nodeSetSocketAvailability(ntree, count_socket, mode == GEO_NODE_CURVE_RESAMPLE_COUNT);
+ nodeSetSocketAvailability(ntree, length_socket, mode == GEO_NODE_CURVE_RESAMPLE_LENGTH);
}
static Array<int> calculate_spline_point_offsets(GeoNodeExecParams &params,
@@ -113,7 +127,7 @@ static GMutableSpan ensure_point_attribute(PointCloudComponent &points,
points.attribute_try_create(attribute_id, ATTR_DOMAIN_POINT, data_type, AttributeInitDefault());
WriteAttributeLookup attribute = points.attribute_try_get_for_write(attribute_id);
BLI_assert(attribute);
- return attribute.varray->get_internal_span();
+ return attribute.varray.get_internal_span();
}
template<typename T>
@@ -194,7 +208,7 @@ static void copy_evaluated_point_attributes(const Span<SplinePtr> splines,
const int size = offsets[i + 1] - offsets[i];
data.positions.slice(offset, size).copy_from(spline.evaluated_positions());
- spline.interpolate_to_evaluated(spline.radii())->materialize(data.radii.slice(offset, size));
+ spline.interpolate_to_evaluated(spline.radii()).materialize(data.radii.slice(offset, size));
for (const Map<AttributeIDRef, GMutableSpan>::Item item : data.point_attributes.items()) {
const AttributeIDRef attribute_id = item.key;
@@ -203,7 +217,7 @@ static void copy_evaluated_point_attributes(const Span<SplinePtr> splines,
BLI_assert(spline.attributes.get_for_read(attribute_id));
GSpan spline_span = *spline.attributes.get_for_read(attribute_id);
- spline.interpolate_to_evaluated(spline_span)->materialize(dst.slice(offset, size).data());
+ spline.interpolate_to_evaluated(spline_span).materialize(dst.slice(offset, size).data());
}
if (!data.tangents.is_empty()) {
@@ -233,7 +247,7 @@ static void copy_uniform_sample_point_attributes(const Span<SplinePtr> splines,
spline.sample_with_index_factors<float3>(
spline.evaluated_positions(), uniform_samples, data.positions.slice(offset, size));
- spline.sample_with_index_factors<float>(*spline.interpolate_to_evaluated(spline.radii()),
+ spline.sample_with_index_factors<float>(spline.interpolate_to_evaluated(spline.radii()),
uniform_samples,
data.radii.slice(offset, size));
@@ -244,7 +258,7 @@ static void copy_uniform_sample_point_attributes(const Span<SplinePtr> splines,
BLI_assert(spline.attributes.get_for_read(attribute_id));
GSpan spline_span = *spline.attributes.get_for_read(attribute_id);
- spline.sample_with_index_factors(*spline.interpolate_to_evaluated(spline_span),
+ spline.sample_with_index_factors(spline.interpolate_to_evaluated(spline_span),
uniform_samples,
dst.slice(offset, size));
}
@@ -289,19 +303,7 @@ static void copy_spline_domain_attributes(const CurveEval &curve,
ATTR_DOMAIN_CURVE);
}
-void curve_create_default_rotation_attribute(Span<float3> tangents,
- Span<float3> normals,
- MutableSpan<float3> rotations)
-{
- threading::parallel_for(IndexRange(rotations.size()), 512, [&](IndexRange range) {
- for (const int i : range) {
- rotations[i] =
- float4x4::from_normalized_axis_data({0, 0, 0}, normals[i], tangents[i]).to_euler();
- }
- });
-}
-
-static void geo_node_curve_to_points_exec(GeoNodeExecParams params)
+static void node_geo_exec(GeoNodeExecParams params)
{
NodeGeometryCurveToPoints &node_storage = *(NodeGeometryCurveToPoints *)params.node().storage;
const GeometryNodeCurveResampleMode mode = (GeometryNodeCurveResampleMode)node_storage.mode;
@@ -374,20 +376,22 @@ static void geo_node_curve_to_points_exec(GeoNodeExecParams params)
}
}
-} // namespace blender::nodes
+} // namespace blender::nodes::node_geo_curve_to_points_cc
void register_node_type_geo_curve_to_points()
{
+ namespace file_ns = blender::nodes::node_geo_curve_to_points_cc;
+
static bNodeType ntype;
geo_node_type_base(&ntype, GEO_NODE_CURVE_TO_POINTS, "Curve to Points", NODE_CLASS_GEOMETRY, 0);
- ntype.declare = blender::nodes::geo_node_curve_to_points_declare;
- ntype.geometry_node_execute = blender::nodes::geo_node_curve_to_points_exec;
- ntype.draw_buttons = blender::nodes::geo_node_curve_to_points_layout;
+ ntype.declare = file_ns::node_declare;
+ ntype.geometry_node_execute = file_ns::node_geo_exec;
+ ntype.draw_buttons = file_ns::node_layout;
node_type_storage(
&ntype, "NodeGeometryCurveToPoints", node_free_standard_storage, node_copy_standard_storage);
- node_type_init(&ntype, blender::nodes::geo_node_curve_to_points_init);
- node_type_update(&ntype, blender::nodes::geo_node_curve_to_points_update);
+ node_type_init(&ntype, file_ns::node_init);
+ node_type_update(&ntype, file_ns::node_update);
nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/geometry/nodes/node_geo_curve_trim.cc b/source/blender/nodes/geometry/nodes/node_geo_curve_trim.cc
index 4e1a2910c7c..127164b0ab0 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_curve_trim.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_curve_trim.cc
@@ -22,11 +22,11 @@
#include "node_geometry_util.hh"
-using blender::attribute_math::mix2;
+namespace blender::nodes::node_geo_curve_trim_cc {
-namespace blender::nodes {
+using blender::attribute_math::mix2;
-static void geo_node_curve_trim_declare(NodeDeclarationBuilder &b)
+static void node_declare(NodeDeclarationBuilder &b)
{
b.add_input<decl::Geometry>(N_("Curve")).supported_type(GEO_COMPONENT_TYPE_CURVE);
b.add_input<decl::Float>(N_("Start")).min(0.0f).max(1.0f).subtype(PROP_FACTOR).supports_field();
@@ -48,12 +48,12 @@ static void geo_node_curve_trim_declare(NodeDeclarationBuilder &b)
b.add_output<decl::Geometry>(N_("Curve"));
}
-static void geo_node_curve_trim_layout(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
+static void node_layout(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
{
uiItemR(layout, ptr, "mode", UI_ITEM_R_EXPAND, nullptr, ICON_NONE);
}
-static void geo_node_curve_trim_init(bNodeTree *UNUSED(tree), bNode *node)
+static void node_init(bNodeTree *UNUSED(tree), bNode *node)
{
NodeGeometryCurveTrim *data = (NodeGeometryCurveTrim *)MEM_callocN(sizeof(NodeGeometryCurveTrim),
__func__);
@@ -62,7 +62,7 @@ static void geo_node_curve_trim_init(bNodeTree *UNUSED(tree), bNode *node)
node->storage = data;
}
-static void geo_node_curve_trim_update(bNodeTree *UNUSED(ntree), bNode *node)
+static void node_update(bNodeTree *ntree, bNode *node)
{
const NodeGeometryCurveTrim &node_storage = *(NodeGeometryCurveTrim *)node->storage;
const GeometryNodeCurveSampleMode mode = (GeometryNodeCurveSampleMode)node_storage.mode;
@@ -72,10 +72,10 @@ static void geo_node_curve_trim_update(bNodeTree *UNUSED(ntree), bNode *node)
bNodeSocket *start_len = end_fac->next;
bNodeSocket *end_len = start_len->next;
- nodeSetSocketAvailability(start_fac, mode == GEO_NODE_CURVE_SAMPLE_FACTOR);
- nodeSetSocketAvailability(end_fac, mode == GEO_NODE_CURVE_SAMPLE_FACTOR);
- nodeSetSocketAvailability(start_len, mode == GEO_NODE_CURVE_SAMPLE_LENGTH);
- nodeSetSocketAvailability(end_len, mode == GEO_NODE_CURVE_SAMPLE_LENGTH);
+ nodeSetSocketAvailability(ntree, start_fac, mode == GEO_NODE_CURVE_SAMPLE_FACTOR);
+ nodeSetSocketAvailability(ntree, end_fac, mode == GEO_NODE_CURVE_SAMPLE_FACTOR);
+ nodeSetSocketAvailability(ntree, start_len, mode == GEO_NODE_CURVE_SAMPLE_LENGTH);
+ nodeSetSocketAvailability(ntree, end_len, mode == GEO_NODE_CURVE_SAMPLE_LENGTH);
}
struct TrimLocation {
@@ -216,9 +216,9 @@ static PolySpline trim_nurbs_spline(const Spline &spline,
attribute_math::convert_to_static_type(src->type(), [&](auto dummy) {
using T = decltype(dummy);
- GVArray_Typed<T> eval_data = spline.interpolate_to_evaluated<T>(src->typed<T>());
+ VArray<T> eval_data = spline.interpolate_to_evaluated<T>(src->typed<T>());
linear_trim_to_output_data<T>(
- start, end, eval_data->get_internal_span(), dst->typed<T>());
+ start, end, eval_data.get_internal_span(), dst->typed<T>());
});
return true;
},
@@ -227,13 +227,13 @@ static PolySpline trim_nurbs_spline(const Spline &spline,
linear_trim_to_output_data<float3>(
start, end, spline.evaluated_positions(), new_spline.positions());
- GVArray_Typed<float> evaluated_radii = spline.interpolate_to_evaluated(spline.radii());
+ VArray<float> evaluated_radii = spline.interpolate_to_evaluated(spline.radii());
linear_trim_to_output_data<float>(
- start, end, evaluated_radii->get_internal_span(), new_spline.radii());
+ start, end, evaluated_radii.get_internal_span(), new_spline.radii());
- GVArray_Typed<float> evaluated_tilts = spline.interpolate_to_evaluated(spline.tilts());
+ VArray<float> evaluated_tilts = spline.interpolate_to_evaluated(spline.tilts());
linear_trim_to_output_data<float>(
- start, end, evaluated_tilts->get_internal_span(), new_spline.tilts());
+ start, end, evaluated_tilts.get_internal_span(), new_spline.tilts());
return new_spline;
}
@@ -427,8 +427,8 @@ static PolySpline to_single_point_nurbs(const Spline &spline, const Spline::Look
std::optional<GMutableSpan> dst = new_spline.attributes.get_for_write(attribute_id);
attribute_math::convert_to_static_type(src->type(), [&](auto dummy) {
using T = decltype(dummy);
- GVArray_Typed<T> eval_data = spline.interpolate_to_evaluated<T>(src->typed<T>());
- to_single_point_data<T>(trim, eval_data->get_internal_span(), dst->typed<T>());
+ VArray<T> eval_data = spline.interpolate_to_evaluated<T>(src->typed<T>());
+ to_single_point_data<T>(trim, eval_data.get_internal_span(), dst->typed<T>());
});
return true;
},
@@ -436,11 +436,11 @@ static PolySpline to_single_point_nurbs(const Spline &spline, const Spline::Look
to_single_point_data<float3>(trim, spline.evaluated_positions(), new_spline.positions());
- GVArray_Typed<float> evaluated_radii = spline.interpolate_to_evaluated(spline.radii());
- to_single_point_data<float>(trim, evaluated_radii->get_internal_span(), new_spline.radii());
+ VArray<float> evaluated_radii = spline.interpolate_to_evaluated(spline.radii());
+ to_single_point_data<float>(trim, evaluated_radii.get_internal_span(), new_spline.radii());
- GVArray_Typed<float> evaluated_tilts = spline.interpolate_to_evaluated(spline.tilts());
- to_single_point_data<float>(trim, evaluated_tilts->get_internal_span(), new_spline.tilts());
+ VArray<float> evaluated_tilts = spline.interpolate_to_evaluated(spline.tilts());
+ to_single_point_data<float>(trim, evaluated_tilts.get_internal_span(), new_spline.tilts());
return new_spline;
}
@@ -532,7 +532,7 @@ static void geometry_set_curve_trim(GeometrySet &geometry_set,
});
}
-static void geo_node_curve_trim_exec(GeoNodeExecParams params)
+static void node_geo_exec(GeoNodeExecParams params)
{
const NodeGeometryCurveTrim &node_storage = *(NodeGeometryCurveTrim *)params.node().storage;
const GeometryNodeCurveSampleMode mode = (GeometryNodeCurveSampleMode)node_storage.mode;
@@ -557,18 +557,20 @@ static void geo_node_curve_trim_exec(GeoNodeExecParams params)
params.set_output("Curve", std::move(geometry_set));
}
-} // namespace blender::nodes
+} // namespace blender::nodes::node_geo_curve_trim_cc
void register_node_type_geo_curve_trim()
{
+ namespace file_ns = blender::nodes::node_geo_curve_trim_cc;
+
static bNodeType ntype;
geo_node_type_base(&ntype, GEO_NODE_TRIM_CURVE, "Trim Curve", NODE_CLASS_GEOMETRY, 0);
- ntype.geometry_node_execute = blender::nodes::geo_node_curve_trim_exec;
- ntype.draw_buttons = blender::nodes::geo_node_curve_trim_layout;
- ntype.declare = blender::nodes::geo_node_curve_trim_declare;
+ ntype.geometry_node_execute = file_ns::node_geo_exec;
+ ntype.draw_buttons = file_ns::node_layout;
+ ntype.declare = file_ns::node_declare;
node_type_storage(
&ntype, "NodeGeometryCurveTrim", node_free_standard_storage, node_copy_standard_storage);
- node_type_init(&ntype, blender::nodes::geo_node_curve_trim_init);
- node_type_update(&ntype, blender::nodes::geo_node_curve_trim_update);
+ node_type_init(&ntype, file_ns::node_init);
+ node_type_update(&ntype, file_ns::node_update);
nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/geometry/nodes/node_geo_delete_geometry.cc b/source/blender/nodes/geometry/nodes/node_geo_delete_geometry.cc
index b0df6428a06..055e44998cb 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_delete_geometry.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_delete_geometry.cc
@@ -29,58 +29,24 @@
#include "node_geometry_util.hh"
-using blender::bke::CustomDataAttributes;
-
/* 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);
+void copy_masked_vertices_to_new_mesh(const Mesh &src_mesh,
+ Mesh &dst_mesh,
+ blender::Span<int> vertex_map);
+void copy_masked_edges_to_new_mesh(const Mesh &src_mesh,
+ Mesh &dst_mesh,
+ blender::Span<int> vertex_map,
+ blender::Span<int> edge_map);
+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);
namespace blender::nodes {
-static void geo_node_delete_geometry_declare(NodeDeclarationBuilder &b)
-{
- b.add_input<decl::Geometry>(N_("Geometry"));
- b.add_input<decl::Bool>(N_("Selection"))
- .default_value(true)
- .hide_value()
- .supports_field()
- .description(N_("The parts of the geometry to be deleted"));
- b.add_output<decl::Geometry>(N_("Geometry"));
-}
-
-static void geo_node_delete_geometry_layout(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
-{
- const bNode *node = static_cast<bNode *>(ptr->data);
- const NodeGeometryDeleteGeometry &storage = *(const NodeGeometryDeleteGeometry *)node->storage;
- const AttributeDomain domain = static_cast<AttributeDomain>(storage.domain);
-
- uiItemR(layout, ptr, "domain", 0, "", ICON_NONE);
- /* Only show the mode when it is relevant. */
- if (ELEM(domain, ATTR_DOMAIN_POINT, ATTR_DOMAIN_EDGE, ATTR_DOMAIN_FACE)) {
- uiItemR(layout, ptr, "mode", 0, "", ICON_NONE);
- }
-}
-
-static void geo_node_delete_geometry_init(bNodeTree *UNUSED(tree), bNode *node)
-{
- NodeGeometryDeleteGeometry *data = (NodeGeometryDeleteGeometry *)MEM_callocN(
- sizeof(NodeGeometryDeleteGeometry), __func__);
- data->domain = ATTR_DOMAIN_POINT;
- data->mode = GEO_NODE_DELETE_GEOMETRY_MODE_ALL;
-
- node->storage = data;
-}
+using blender::bke::CustomDataAttributes;
template<typename T> static void copy_data(Span<T> data, MutableSpan<T> r_data, IndexMask mask)
{
@@ -138,7 +104,7 @@ static void copy_attributes(const Map<AttributeIDRef, AttributeKind> &attributes
if (!domains.contains(attribute.domain)) {
continue;
}
- const CustomDataType data_type = bke::cpp_type_to_custom_data_type(attribute.varray->type());
+ const CustomDataType data_type = bke::cpp_type_to_custom_data_type(attribute.varray.type());
OutputAttribute result_attribute = result_component.attribute_try_get_for_output_only(
attribute_id, attribute.domain, data_type);
@@ -149,7 +115,7 @@ static void copy_attributes(const Map<AttributeIDRef, AttributeKind> &attributes
attribute_math::convert_to_static_type(data_type, [&](auto dummy) {
using T = decltype(dummy);
- GVArray_Span<T> span{*attribute.varray};
+ VArray_Span<T> span{attribute.varray.typed<T>()};
MutableSpan<T> out_span = result_attribute.as_span<T>();
out_span.copy_from(span);
});
@@ -178,7 +144,7 @@ static void copy_attributes_based_on_mask(const Map<AttributeIDRef, AttributeKin
if (domain != attribute.domain) {
continue;
}
- const CustomDataType data_type = bke::cpp_type_to_custom_data_type(attribute.varray->type());
+ const CustomDataType data_type = bke::cpp_type_to_custom_data_type(attribute.varray.type());
OutputAttribute result_attribute = result_component.attribute_try_get_for_output_only(
attribute_id, attribute.domain, data_type);
@@ -189,7 +155,7 @@ static void copy_attributes_based_on_mask(const Map<AttributeIDRef, AttributeKin
attribute_math::convert_to_static_type(data_type, [&](auto dummy) {
using T = decltype(dummy);
- GVArray_Span<T> span{*attribute.varray};
+ VArray_Span<T> span{attribute.varray.typed<T>()};
MutableSpan<T> out_span = result_attribute.as_span<T>();
copy_data(span, out_span, mask);
});
@@ -1209,7 +1175,45 @@ void separate_geometry(GeometrySet &geometry_set,
r_is_error = !some_valid_domain && geometry_set.has_realized_data();
}
-static void geo_node_delete_geometry_exec(GeoNodeExecParams params)
+} // namespace blender::nodes
+
+namespace blender::nodes::node_geo_delete_geometry_cc {
+
+static void node_declare(NodeDeclarationBuilder &b)
+{
+ b.add_input<decl::Geometry>(N_("Geometry"));
+ b.add_input<decl::Bool>(N_("Selection"))
+ .default_value(true)
+ .hide_value()
+ .supports_field()
+ .description(N_("The parts of the geometry to be deleted"));
+ b.add_output<decl::Geometry>(N_("Geometry"));
+}
+
+static void node_layout(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
+{
+ const bNode *node = static_cast<bNode *>(ptr->data);
+ const NodeGeometryDeleteGeometry &storage = *(const NodeGeometryDeleteGeometry *)node->storage;
+ const AttributeDomain domain = static_cast<AttributeDomain>(storage.domain);
+
+ uiItemR(layout, ptr, "domain", 0, "", ICON_NONE);
+ /* Only show the mode when it is relevant. */
+ if (ELEM(domain, ATTR_DOMAIN_POINT, ATTR_DOMAIN_EDGE, ATTR_DOMAIN_FACE)) {
+ uiItemR(layout, ptr, "mode", 0, "", ICON_NONE);
+ }
+}
+
+static void node_init(bNodeTree *UNUSED(tree), bNode *node)
+{
+ NodeGeometryDeleteGeometry *data = (NodeGeometryDeleteGeometry *)MEM_callocN(
+ sizeof(NodeGeometryDeleteGeometry), __func__);
+ data->domain = ATTR_DOMAIN_POINT;
+ data->mode = GEO_NODE_DELETE_GEOMETRY_MODE_ALL;
+
+ node->storage = data;
+}
+
+static void node_geo_exec(GeoNodeExecParams params)
{
GeometrySet geometry_set = params.extract_input<GeometrySet>("Geometry");
@@ -1236,10 +1240,12 @@ static void geo_node_delete_geometry_exec(GeoNodeExecParams params)
params.set_output("Geometry", std::move(geometry_set));
}
-} // namespace blender::nodes
+} // namespace blender::nodes::node_geo_delete_geometry_cc
void register_node_type_geo_delete_geometry()
{
+ namespace file_ns = blender::nodes::node_geo_delete_geometry_cc;
+
static bNodeType ntype;
geo_node_type_base(&ntype, GEO_NODE_DELETE_GEOMETRY, "Delete Geometry", NODE_CLASS_GEOMETRY, 0);
@@ -1249,10 +1255,10 @@ void register_node_type_geo_delete_geometry()
node_free_standard_storage,
node_copy_standard_storage);
- node_type_init(&ntype, blender::nodes::geo_node_delete_geometry_init);
+ node_type_init(&ntype, file_ns::node_init);
- ntype.declare = blender::nodes::geo_node_delete_geometry_declare;
- ntype.geometry_node_execute = blender::nodes::geo_node_delete_geometry_exec;
- ntype.draw_buttons = blender::nodes::geo_node_delete_geometry_layout;
+ ntype.declare = file_ns::node_declare;
+ ntype.geometry_node_execute = file_ns::node_geo_exec;
+ ntype.draw_buttons = file_ns::node_layout;
nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/geometry/nodes/node_geo_distribute_points_on_faces.cc b/source/blender/nodes/geometry/nodes/node_geo_distribute_points_on_faces.cc
index 115ad09a9e6..adb698b8f7a 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_distribute_points_on_faces.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_distribute_points_on_faces.cc
@@ -36,11 +36,9 @@
#include "node_geometry_util.hh"
-using blender::bke::GeometryInstanceGroup;
+namespace blender::nodes::node_geo_distribute_points_on_faces_cc {
-namespace blender::nodes {
-
-static void geo_node_point_distribute_points_on_faces_declare(NodeDeclarationBuilder &b)
+static void node_declare(NodeDeclarationBuilder &b)
{
b.add_input<decl::Geometry>(N_("Mesh")).supported_type(GEO_COMPONENT_TYPE_MESH);
b.add_input<decl::Bool>(N_("Selection")).default_value(true).hide_value().supports_field();
@@ -60,26 +58,26 @@ static void geo_node_point_distribute_points_on_faces_declare(NodeDeclarationBui
b.add_output<decl::Vector>(N_("Rotation")).subtype(PROP_EULER).field_source();
}
-static void geo_node_point_distribute_points_on_faces_layout(uiLayout *layout,
- bContext *UNUSED(C),
- PointerRNA *ptr)
+static void node_layout(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
{
uiItemR(layout, ptr, "distribute_method", 0, "", ICON_NONE);
}
-static void node_point_distribute_points_on_faces_update(bNodeTree *UNUSED(ntree), bNode *node)
+static void node_point_distribute_points_on_faces_update(bNodeTree *ntree, bNode *node)
{
bNodeSocket *sock_distance_min = (bNodeSocket *)BLI_findlink(&node->inputs, 2);
bNodeSocket *sock_density_max = (bNodeSocket *)sock_distance_min->next;
bNodeSocket *sock_density = sock_density_max->next;
bNodeSocket *sock_density_factor = sock_density->next;
- nodeSetSocketAvailability(sock_distance_min,
- node->custom1 == GEO_NODE_POINT_DISTRIBUTE_POINTS_ON_FACES_POISSON);
- nodeSetSocketAvailability(sock_density_max,
+ nodeSetSocketAvailability(ntree,
+ sock_distance_min,
node->custom1 == GEO_NODE_POINT_DISTRIBUTE_POINTS_ON_FACES_POISSON);
- nodeSetSocketAvailability(sock_density,
- node->custom1 == GEO_NODE_POINT_DISTRIBUTE_POINTS_ON_FACES_RANDOM);
- nodeSetSocketAvailability(sock_density_factor,
+ nodeSetSocketAvailability(
+ ntree, sock_density_max, node->custom1 == GEO_NODE_POINT_DISTRIBUTE_POINTS_ON_FACES_POISSON);
+ nodeSetSocketAvailability(
+ ntree, sock_density, node->custom1 == GEO_NODE_POINT_DISTRIBUTE_POINTS_ON_FACES_RANDOM);
+ nodeSetSocketAvailability(ntree,
+ sock_density_factor,
node->custom1 == GEO_NODE_POINT_DISTRIBUTE_POINTS_ON_FACES_POISSON);
}
@@ -313,7 +311,7 @@ BLI_NOINLINE static void propagate_existing_attributes(
bary_coords,
looptri_indices,
source_attribute.domain,
- *source_attribute.varray,
+ source_attribute.varray,
out_span);
attribute_out.save();
}
@@ -526,7 +524,7 @@ static void point_distribution_calculate(GeometrySet &geometry_set,
mesh_component, point_component, bary_coords, looptri_indices, attribute_outputs);
}
-static void geo_node_point_distribute_points_on_faces_exec(GeoNodeExecParams params)
+static void node_geo_exec(GeoNodeExecParams params)
{
GeometrySet geometry_set = params.extract_input<GeometrySet>("Mesh");
@@ -568,10 +566,12 @@ static void geo_node_point_distribute_points_on_faces_exec(GeoNodeExecParams par
}
}
-} // namespace blender::nodes
+} // namespace blender::nodes::node_geo_distribute_points_on_faces_cc
void register_node_type_geo_distribute_points_on_faces()
{
+ namespace file_ns = blender::nodes::node_geo_distribute_points_on_faces_cc;
+
static bNodeType ntype;
geo_node_type_base(&ntype,
@@ -579,10 +579,10 @@ void register_node_type_geo_distribute_points_on_faces()
"Distribute Points on Faces",
NODE_CLASS_GEOMETRY,
0);
- node_type_update(&ntype, blender::nodes::node_point_distribute_points_on_faces_update);
+ node_type_update(&ntype, file_ns::node_point_distribute_points_on_faces_update);
node_type_size(&ntype, 170, 100, 320);
- ntype.declare = blender::nodes::geo_node_point_distribute_points_on_faces_declare;
- ntype.geometry_node_execute = blender::nodes::geo_node_point_distribute_points_on_faces_exec;
- ntype.draw_buttons = blender::nodes::geo_node_point_distribute_points_on_faces_layout;
+ ntype.declare = file_ns::node_declare;
+ ntype.geometry_node_execute = file_ns::node_geo_exec;
+ ntype.draw_buttons = file_ns::node_layout;
nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/geometry/nodes/node_geo_edge_split.cc b/source/blender/nodes/geometry/nodes/node_geo_edge_split.cc
index f562fb29e90..d23a18ba37b 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_edge_split.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_edge_split.cc
@@ -22,9 +22,9 @@
#include "node_geometry_util.hh"
-namespace blender::nodes {
+namespace blender::nodes::node_geo_edge_split_cc {
-static void geo_node_edge_split_declare(NodeDeclarationBuilder &b)
+static void node_declare(NodeDeclarationBuilder &b)
{
b.add_input<decl::Geometry>(N_("Mesh")).supported_type(GEO_COMPONENT_TYPE_MESH);
b.add_input<decl::Bool>(N_("Selection")).default_value(true).hide_value().supports_field();
@@ -33,12 +33,13 @@ static void geo_node_edge_split_declare(NodeDeclarationBuilder &b)
static Mesh *mesh_edge_split(const Mesh &mesh, const IndexMask selection)
{
- const BMeshCreateParams bmcp = {true};
+ BMeshCreateParams bmesh_create_params{};
+ bmesh_create_params.use_toolflags = true;
const BMAllocTemplate allocsize = {0, 0, 0, 0};
- BMesh *bm = BM_mesh_create(&allocsize, &bmcp);
+ BMesh *bm = BM_mesh_create(&allocsize, &bmesh_create_params);
- BMeshFromMeshParams params{};
- BM_mesh_bm_from_me(bm, &mesh, &params);
+ BMeshFromMeshParams bmesh_from_mesh_params{};
+ BM_mesh_bm_from_me(bm, &mesh, &bmesh_from_mesh_params);
BM_mesh_elem_table_ensure(bm, BM_EDGE);
for (const int i : selection) {
@@ -56,7 +57,7 @@ static Mesh *mesh_edge_split(const Mesh &mesh, const IndexMask selection)
return result;
}
-static void geo_node_edge_split_exec(GeoNodeExecParams params)
+static void node_geo_exec(GeoNodeExecParams params)
{
GeometrySet geometry_set = params.extract_input<GeometrySet>("Mesh");
@@ -81,14 +82,16 @@ static void geo_node_edge_split_exec(GeoNodeExecParams params)
params.set_output("Mesh", std::move(geometry_set));
}
-} // namespace blender::nodes
+} // namespace blender::nodes::node_geo_edge_split_cc
void register_node_type_geo_edge_split()
{
+ namespace file_ns = blender::nodes::node_geo_edge_split_cc;
+
static bNodeType ntype;
geo_node_type_base(&ntype, GEO_NODE_SPLIT_EDGES, "Split Edges", NODE_CLASS_GEOMETRY, 0);
- ntype.geometry_node_execute = blender::nodes::geo_node_edge_split_exec;
- ntype.declare = blender::nodes::geo_node_edge_split_declare;
+ ntype.geometry_node_execute = file_ns::node_geo_exec;
+ ntype.declare = file_ns::node_declare;
nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/geometry/nodes/node_geo_image_texture.cc b/source/blender/nodes/geometry/nodes/node_geo_image_texture.cc
index e1c72fbd438..c56d920fac5 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_image_texture.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_image_texture.cc
@@ -32,9 +32,9 @@
#include "UI_interface.h"
#include "UI_resources.h"
-namespace blender::nodes {
+namespace blender::nodes::node_geo_image_texture_cc {
-static void geo_node_image_texture_declare(NodeDeclarationBuilder &b)
+static void node_declare(NodeDeclarationBuilder &b)
{
b.add_input<decl::Image>(N_("Image")).hide_label();
b.add_input<decl::Vector>(N_("Vector"))
@@ -45,13 +45,13 @@ static void geo_node_image_texture_declare(NodeDeclarationBuilder &b)
b.add_output<decl::Float>(N_("Alpha")).no_muted_links().dependent_field();
}
-static void geo_node_image_texture_layout(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
+static void node_layout(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
{
uiItemR(layout, ptr, "interpolation", UI_ITEM_R_SPLIT_EMPTY_NAME, "", ICON_NONE);
uiItemR(layout, ptr, "extension", UI_ITEM_R_SPLIT_EMPTY_NAME, "", ICON_NONE);
}
-static void geo_node_image_texture_init(bNodeTree *UNUSED(ntree), bNode *node)
+static void node_init(bNodeTree *UNUSED(ntree), bNode *node)
{
NodeGeometryImageTexture *tex = (NodeGeometryImageTexture *)MEM_callocN(
sizeof(NodeGeometryImageTexture), __func__);
@@ -82,7 +82,7 @@ class ImageFieldsFunction : public fn::MultiFunction {
image_buffer_ = BKE_image_acquire_ibuf(&image_, &image_user_, &image_lock_);
if (image_buffer_ == nullptr) {
- throw std::runtime_error("cannot aquire image buffer");
+ throw std::runtime_error("cannot acquire image buffer");
}
if (image_buffer_->rect_float == nullptr) {
@@ -370,7 +370,7 @@ class ImageFieldsFunction : public fn::MultiFunction {
}
};
-static void geo_node_image_texture_exec(GeoNodeExecParams params)
+static void node_geo_exec(GeoNodeExecParams params)
{
auto return_default = [&]() {
params.set_output("Color", ColorGeometry4f(0.0f, 0.0f, 0.0f, 1.0f));
@@ -410,20 +410,22 @@ static void geo_node_image_texture_exec(GeoNodeExecParams params)
params.set_output("Alpha", Field<float>(image_op, 1));
}
-} // namespace blender::nodes
+} // namespace blender::nodes::node_geo_image_texture_cc
void register_node_type_geo_image_texture(void)
{
+ namespace file_ns = blender::nodes::node_geo_image_texture_cc;
+
static bNodeType ntype;
geo_node_type_base(&ntype, GEO_NODE_IMAGE_TEXTURE, "Image Texture", NODE_CLASS_TEXTURE, 0);
- ntype.declare = blender::nodes::geo_node_image_texture_declare;
- ntype.draw_buttons = blender::nodes::geo_node_image_texture_layout;
- node_type_init(&ntype, blender::nodes::geo_node_image_texture_init);
+ ntype.declare = file_ns::node_declare;
+ ntype.draw_buttons = file_ns::node_layout;
+ node_type_init(&ntype, file_ns::node_init);
node_type_storage(
&ntype, "NodeGeometryImageTexture", node_free_standard_storage, node_copy_standard_storage);
node_type_size_preset(&ntype, NODE_SIZE_LARGE);
- ntype.geometry_node_execute = blender::nodes::geo_node_image_texture_exec;
+ ntype.geometry_node_execute = file_ns::node_geo_exec;
nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/geometry/nodes/node_geo_input_curve_handles.cc b/source/blender/nodes/geometry/nodes/node_geo_input_curve_handles.cc
index b8df545d073..dae8fda2099 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_input_curve_handles.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_input_curve_handles.cc
@@ -16,15 +16,15 @@
#include "node_geometry_util.hh"
-namespace blender::nodes {
+namespace blender::nodes::node_geo_input_curve_handles_cc {
-static void geo_node_input_curve_handles_declare(NodeDeclarationBuilder &b)
+static void node_declare(NodeDeclarationBuilder &b)
{
b.add_output<decl::Vector>(N_("Left")).field_source();
b.add_output<decl::Vector>(N_("Right")).field_source();
}
-static void geo_node_input_curve_handles_exec(GeoNodeExecParams params)
+static void node_geo_exec(GeoNodeExecParams params)
{
Field<float3> left_field = AttributeFieldInput::Create<float3>("handle_left");
Field<float3> right_field = AttributeFieldInput::Create<float3>("handle_right");
@@ -32,15 +32,17 @@ static void geo_node_input_curve_handles_exec(GeoNodeExecParams params)
params.set_output("Right", std::move(right_field));
}
-} // namespace blender::nodes
+} // namespace blender::nodes::node_geo_input_curve_handles_cc
void register_node_type_geo_input_curve_handles()
{
+ namespace file_ns = blender::nodes::node_geo_input_curve_handles_cc;
+
static bNodeType ntype;
geo_node_type_base(
&ntype, GEO_NODE_INPUT_CURVE_HANDLES, "Curve Handle Positions", NODE_CLASS_INPUT, 0);
node_type_size_preset(&ntype, NODE_SIZE_MIDDLE);
- ntype.geometry_node_execute = blender::nodes::geo_node_input_curve_handles_exec;
- ntype.declare = blender::nodes::geo_node_input_curve_handles_declare;
+ ntype.geometry_node_execute = file_ns::node_geo_exec;
+ ntype.declare = file_ns::node_declare;
nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/geometry/nodes/node_geo_input_curve_tilt.cc b/source/blender/nodes/geometry/nodes/node_geo_input_curve_tilt.cc
index f32db3842db..5ba85b6f34e 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_input_curve_tilt.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_input_curve_tilt.cc
@@ -16,27 +16,29 @@
#include "node_geometry_util.hh"
-namespace blender::nodes {
+namespace blender::nodes::node_geo_input_curve_tilt_cc {
-static void geo_node_input_curve_tilt_declare(NodeDeclarationBuilder &b)
+static void node_declare(NodeDeclarationBuilder &b)
{
b.add_output<decl::Float>(N_("Tilt")).field_source();
}
-static void geo_node_input_curve_tilt_exec(GeoNodeExecParams params)
+static void node_geo_exec(GeoNodeExecParams params)
{
Field<float> tilt_field = AttributeFieldInput::Create<float>("tilt");
params.set_output("Tilt", std::move(tilt_field));
}
-} // namespace blender::nodes
+} // namespace blender::nodes::node_geo_input_curve_tilt_cc
void register_node_type_geo_input_curve_tilt()
{
+ namespace file_ns = blender::nodes::node_geo_input_curve_tilt_cc;
+
static bNodeType ntype;
geo_node_type_base(&ntype, GEO_NODE_INPUT_CURVE_TILT, "Curve Tilt", NODE_CLASS_INPUT, 0);
- ntype.geometry_node_execute = blender::nodes::geo_node_input_curve_tilt_exec;
- ntype.declare = blender::nodes::geo_node_input_curve_tilt_declare;
+ ntype.geometry_node_execute = file_ns::node_geo_exec;
+ ntype.declare = file_ns::node_declare;
nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/geometry/nodes/node_geo_input_id.cc b/source/blender/nodes/geometry/nodes/node_geo_input_id.cc
index 37d5bac0325..d2e103a093a 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_input_id.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_input_id.cc
@@ -16,27 +16,29 @@
#include "node_geometry_util.hh"
-namespace blender::nodes {
+namespace blender::nodes::node_geo_input_id_cc {
-static void geo_node_input_id_declare(NodeDeclarationBuilder &b)
+static void node_declare(NodeDeclarationBuilder &b)
{
b.add_output<decl::Int>(N_("ID")).field_source();
}
-static void geo_node_input_id_exec(GeoNodeExecParams params)
+static void node_geo_exec(GeoNodeExecParams params)
{
Field<int> position_field{std::make_shared<bke::IDAttributeFieldInput>()};
params.set_output("ID", std::move(position_field));
}
-} // namespace blender::nodes
+} // namespace blender::nodes::node_geo_input_id_cc
void register_node_type_geo_input_id()
{
+ namespace file_ns = blender::nodes::node_geo_input_id_cc;
+
static bNodeType ntype;
geo_node_type_base(&ntype, GEO_NODE_INPUT_ID, "ID", NODE_CLASS_INPUT, 0);
- ntype.geometry_node_execute = blender::nodes::geo_node_input_id_exec;
- ntype.declare = blender::nodes::geo_node_input_id_declare;
+ ntype.geometry_node_execute = file_ns::node_geo_exec;
+ ntype.declare = file_ns::node_declare;
nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/geometry/nodes/node_geo_input_index.cc b/source/blender/nodes/geometry/nodes/node_geo_input_index.cc
index 6200ac5e7a8..74cddfc6a4a 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_input_index.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_input_index.cc
@@ -16,27 +16,29 @@
#include "node_geometry_util.hh"
-namespace blender::nodes {
+namespace blender::nodes::node_geo_input_index_cc {
-static void geo_node_input_index_declare(NodeDeclarationBuilder &b)
+static void node_declare(NodeDeclarationBuilder &b)
{
b.add_output<decl::Int>(N_("Index")).field_source();
}
-static void geo_node_input_index_exec(GeoNodeExecParams params)
+static void node_geo_exec(GeoNodeExecParams params)
{
Field<int> index_field{std::make_shared<fn::IndexFieldInput>()};
params.set_output("Index", std::move(index_field));
}
-} // namespace blender::nodes
+} // namespace blender::nodes::node_geo_input_index_cc
void register_node_type_geo_input_index()
{
+ namespace file_ns = blender::nodes::node_geo_input_index_cc;
+
static bNodeType ntype;
geo_node_type_base(&ntype, GEO_NODE_INPUT_INDEX, "Index", NODE_CLASS_INPUT, 0);
- ntype.geometry_node_execute = blender::nodes::geo_node_input_index_exec;
- ntype.declare = blender::nodes::geo_node_input_index_declare;
+ ntype.geometry_node_execute = file_ns::node_geo_exec;
+ ntype.declare = file_ns::node_declare;
nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/geometry/nodes/node_geo_input_material.cc b/source/blender/nodes/geometry/nodes/node_geo_input_material.cc
index fc41188dee5..1b6e3c8fc68 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_input_material.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_input_material.cc
@@ -19,33 +19,35 @@
#include "node_geometry_util.hh"
-namespace blender::nodes {
+namespace blender::nodes::node_geo_input_material_cc {
-static void geo_node_input_material_declare(NodeDeclarationBuilder &b)
+static void node_declare(NodeDeclarationBuilder &b)
{
b.add_output<decl::Material>(N_("Material"));
}
-static void geo_node_input_material_layout(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
+static void node_layout(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
{
uiItemR(layout, ptr, "material", 0, "", ICON_NONE);
}
-static void geo_node_input_material_exec(GeoNodeExecParams params)
+static void node_geo_exec(GeoNodeExecParams params)
{
Material *material = (Material *)params.node().id;
params.set_output("Material", material);
}
-} // namespace blender::nodes
+} // namespace blender::nodes::node_geo_input_material_cc
void register_node_type_geo_input_material()
{
+ namespace file_ns = blender::nodes::node_geo_input_material_cc;
+
static bNodeType ntype;
geo_node_type_base(&ntype, GEO_NODE_INPUT_MATERIAL, "Material", NODE_CLASS_INPUT, 0);
- ntype.draw_buttons = blender::nodes::geo_node_input_material_layout;
- ntype.declare = blender::nodes::geo_node_input_material_declare;
- ntype.geometry_node_execute = blender::nodes::geo_node_input_material_exec;
+ ntype.draw_buttons = file_ns::node_layout;
+ ntype.declare = file_ns::node_declare;
+ ntype.geometry_node_execute = file_ns::node_geo_exec;
nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/geometry/nodes/node_geo_input_material_index.cc b/source/blender/nodes/geometry/nodes/node_geo_input_material_index.cc
index 5d5d9e40032..4df218eb669 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_input_material_index.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_input_material_index.cc
@@ -16,27 +16,29 @@
#include "node_geometry_util.hh"
-namespace blender::nodes {
+namespace blender::nodes::node_geo_input_material_index_cc {
-static void geo_node_input_material_index_declare(NodeDeclarationBuilder &b)
+static void node_declare(NodeDeclarationBuilder &b)
{
b.add_output<decl::Int>(N_("Material Index")).field_source();
}
-static void geo_node_input_material_index_exec(GeoNodeExecParams params)
+static void node_geo_exec(GeoNodeExecParams params)
{
Field<int> material_index_field = AttributeFieldInput::Create<int>("material_index");
params.set_output("Material Index", std::move(material_index_field));
}
-} // namespace blender::nodes
+} // namespace blender::nodes::node_geo_input_material_index_cc
void register_node_type_geo_input_material_index()
{
+ namespace file_ns = blender::nodes::node_geo_input_material_index_cc;
+
static bNodeType ntype;
geo_node_type_base(&ntype, GEO_NODE_INPUT_MATERIAL_INDEX, "Material Index", NODE_CLASS_INPUT, 0);
- ntype.geometry_node_execute = blender::nodes::geo_node_input_material_index_exec;
- ntype.declare = blender::nodes::geo_node_input_material_index_declare;
+ ntype.geometry_node_execute = file_ns::node_geo_exec;
+ ntype.declare = file_ns::node_declare;
nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/geometry/nodes/node_geo_input_normal.cc b/source/blender/nodes/geometry/nodes/node_geo_input_normal.cc
index 92b89313d23..6e63354a31a 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_input_normal.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_input_normal.cc
@@ -24,26 +24,25 @@
#include "node_geometry_util.hh"
-namespace blender::nodes {
+namespace blender::nodes::node_geo_input_normal_cc {
-static void geo_node_input_normal_declare(NodeDeclarationBuilder &b)
+static void node_declare(NodeDeclarationBuilder &b)
{
b.add_output<decl::Vector>(N_("Normal")).field_source();
}
-static GVArrayPtr mesh_face_normals(const Mesh &mesh,
- const Span<MVert> verts,
- const Span<MPoly> polys,
- const Span<MLoop> loops,
- const IndexMask mask)
+static VArray<float3> mesh_face_normals(const Mesh &mesh,
+ const Span<MVert> verts,
+ const Span<MPoly> polys,
+ const Span<MLoop> loops,
+ const IndexMask mask)
{
/* Use existing normals to avoid unnecessarily recalculating them, if possible. */
if (!(mesh.runtime.cd_dirty_poly & CD_MASK_NORMAL) &&
CustomData_has_layer(&mesh.pdata, CD_NORMAL)) {
const void *data = CustomData_get_layer(&mesh.pdata, CD_NORMAL);
- return std::make_unique<fn::GVArray_For_Span<float3>>(
- Span<float3>((const float3 *)data, polys.size()));
+ return VArray<float3>::ForSpan({(const float3 *)data, polys.size()});
}
auto normal_fn = [verts, polys, loops](const int i) -> float3 {
@@ -53,24 +52,21 @@ static GVArrayPtr mesh_face_normals(const Mesh &mesh,
return normal;
};
- return std::make_unique<
- fn::GVArray_For_EmbeddedVArray<float3, VArray_For_Func<float3, decltype(normal_fn)>>>(
- mask.min_array_size(), mask.min_array_size(), normal_fn);
+ return VArray<float3>::ForFunc(mask.min_array_size(), normal_fn);
}
-static GVArrayPtr mesh_vertex_normals(const Mesh &mesh,
- const Span<MVert> verts,
- const Span<MPoly> polys,
- const Span<MLoop> loops,
- const IndexMask mask)
+static VArray<float3> mesh_vertex_normals(const Mesh &mesh,
+ const Span<MVert> verts,
+ const Span<MPoly> polys,
+ const Span<MLoop> loops,
+ const IndexMask mask)
{
/* Use existing normals to avoid unnecessarily recalculating them, if possible. */
if (!(mesh.runtime.cd_dirty_vert & CD_MASK_NORMAL) &&
CustomData_has_layer(&mesh.vdata, CD_NORMAL)) {
const void *data = CustomData_get_layer(&mesh.pdata, CD_NORMAL);
- return std::make_unique<fn::GVArray_For_Span<float3>>(
- Span<float3>((const float3 *)data, mesh.totvert));
+ return VArray<float3>::ForSpan({(const float3 *)data, mesh.totvert});
}
/* If the normals are dirty, they must be recalculated for the output of this node's field
@@ -91,14 +87,14 @@ static GVArrayPtr mesh_vertex_normals(const Mesh &mesh,
nullptr,
(float(*)[3])normals.data());
- return std::make_unique<fn::GVArray_For_ArrayContainer<Array<float3>>>(std::move(normals));
+ return VArray<float3>::ForContainer(std::move(normals));
}
-static const GVArray *construct_mesh_normals_gvarray(const MeshComponent &mesh_component,
+static VArray<float3> construct_mesh_normals_gvarray(const MeshComponent &mesh_component,
const Mesh &mesh,
const IndexMask mask,
const AttributeDomain domain,
- ResourceScope &scope)
+ ResourceScope &UNUSED(scope))
{
Span<MVert> verts{mesh.mvert, mesh.totvert};
Span<MEdge> edges{mesh.medge, mesh.totedge};
@@ -107,18 +103,18 @@ static const GVArray *construct_mesh_normals_gvarray(const MeshComponent &mesh_c
switch (domain) {
case ATTR_DOMAIN_FACE: {
- return scope.add_value(mesh_face_normals(mesh, verts, polys, loops, mask)).get();
+ return mesh_face_normals(mesh, verts, polys, loops, mask);
}
case ATTR_DOMAIN_POINT: {
- return scope.add_value(mesh_vertex_normals(mesh, verts, polys, loops, mask)).get();
+ return mesh_vertex_normals(mesh, verts, polys, loops, mask);
}
case ATTR_DOMAIN_EDGE: {
/* In this case, start with vertex normals and convert to the edge domain, since the
* conversion from edges to vertices is very simple. Use the full mask since the edges
* might use the vertex normal from any index. */
- GVArrayPtr vert_normals = mesh_vertex_normals(
+ GVArray vert_normals = mesh_vertex_normals(
mesh, verts, polys, loops, IndexRange(verts.size()));
- Span<float3> vert_normals_span = vert_normals->get_internal_span().typed<float3>();
+ Span<float3> vert_normals_span = vert_normals.get_internal_span().typed<float3>();
Array<float3> edge_normals(mask.min_array_size());
/* Use "manual" domain interpolation instead of the GeometryComponent API to avoid
@@ -130,23 +126,21 @@ static const GVArray *construct_mesh_normals_gvarray(const MeshComponent &mesh_c
.normalized();
}
- return &scope.construct<fn::GVArray_For_ArrayContainer<Array<float3>>>(
- std::move(edge_normals));
+ return VArray<float3>::ForContainer(std::move(edge_normals));
}
case ATTR_DOMAIN_CORNER: {
/* The normals on corners are just the mesh's face normals, so start with the face normal
* array and copy the face normal for each of its corners. */
- GVArrayPtr face_normals = mesh_face_normals(
+ VArray<float3> face_normals = mesh_face_normals(
mesh, verts, polys, loops, IndexRange(polys.size()));
/* In this case using the mesh component's generic domain interpolation is fine, the data
* will still be normalized, since the face normal is just copied to every corner. */
- GVArrayPtr loop_normals = mesh_component.attribute_try_adapt_domain(
+ return mesh_component.attribute_try_adapt_domain<float3>(
std::move(face_normals), ATTR_DOMAIN_FACE, ATTR_DOMAIN_CORNER);
- return scope.add_value(std::move(loop_normals)).get();
}
default:
- return nullptr;
+ return {};
}
}
@@ -204,9 +198,9 @@ static Array<float3> curve_normal_point_domain(const CurveEval &curve)
return normals;
}
-static const GVArray *construct_curve_normal_gvarray(const CurveComponent &component,
+static VArray<float3> construct_curve_normal_gvarray(const CurveComponent &component,
const AttributeDomain domain,
- ResourceScope &scope)
+ ResourceScope &UNUSED(scope))
{
const CurveEval *curve = component.get_for_read();
if (curve == nullptr) {
@@ -220,20 +214,18 @@ static const GVArray *construct_curve_normal_gvarray(const CurveComponent &compo
* This is only possible when there is only one poly spline. */
if (splines.size() == 1 && splines.first()->type() == Spline::Type::Poly) {
const PolySpline &spline = static_cast<PolySpline &>(*splines.first());
- return &scope.construct<fn::GVArray_For_Span<float3>>(spline.evaluated_normals());
+ return VArray<float3>::ForSpan(spline.evaluated_normals());
}
Array<float3> normals = curve_normal_point_domain(*curve);
- return &scope.construct<fn::GVArray_For_ArrayContainer<Array<float3>>>(std::move(normals));
+ return VArray<float3>::ForContainer(std::move(normals));
}
if (domain == ATTR_DOMAIN_CURVE) {
Array<float3> point_normals = curve_normal_point_domain(*curve);
- GVArrayPtr gvarray = std::make_unique<fn::GVArray_For_ArrayContainer<Array<float3>>>(
- std::move(point_normals));
- GVArrayPtr spline_normals = component.attribute_try_adapt_domain(
- std::move(gvarray), ATTR_DOMAIN_POINT, ATTR_DOMAIN_CURVE);
- return scope.add_value(std::move(spline_normals)).get();
+ VArray<float3> varray = VArray<float3>::ForContainer(std::move(point_normals));
+ return component.attribute_try_adapt_domain<float3>(
+ std::move(varray), ATTR_DOMAIN_POINT, ATTR_DOMAIN_CURVE);
}
return nullptr;
@@ -246,9 +238,9 @@ class NormalFieldInput final : public fn::FieldInput {
category_ = Category::Generated;
}
- const GVArray *get_varray_for_context(const fn::FieldContext &context,
- IndexMask mask,
- ResourceScope &scope) const final
+ GVArray get_varray_for_context(const fn::FieldContext &context,
+ IndexMask mask,
+ ResourceScope &scope) const final
{
if (const GeometryComponentFieldContext *geometry_context =
dynamic_cast<const GeometryComponentFieldContext *>(&context)) {
@@ -260,7 +252,7 @@ class NormalFieldInput final : public fn::FieldInput {
const MeshComponent &mesh_component = static_cast<const MeshComponent &>(component);
const Mesh *mesh = mesh_component.get_for_read();
if (mesh == nullptr) {
- return nullptr;
+ return {};
}
return construct_mesh_normals_gvarray(mesh_component, *mesh, mask, domain, scope);
@@ -270,7 +262,7 @@ class NormalFieldInput final : public fn::FieldInput {
return construct_curve_normal_gvarray(curve_component, domain, scope);
}
}
- return nullptr;
+ return {};
}
uint64_t hash() const override
@@ -285,20 +277,22 @@ class NormalFieldInput final : public fn::FieldInput {
}
};
-static void geo_node_input_normal_exec(GeoNodeExecParams params)
+static void node_geo_exec(GeoNodeExecParams params)
{
Field<float3> normal_field{std::make_shared<NormalFieldInput>()};
params.set_output("Normal", std::move(normal_field));
}
-} // namespace blender::nodes
+} // namespace blender::nodes::node_geo_input_normal_cc
void register_node_type_geo_input_normal()
{
+ namespace file_ns = blender::nodes::node_geo_input_normal_cc;
+
static bNodeType ntype;
geo_node_type_base(&ntype, GEO_NODE_INPUT_NORMAL, "Normal", NODE_CLASS_INPUT, 0);
- ntype.geometry_node_execute = blender::nodes::geo_node_input_normal_exec;
- ntype.declare = blender::nodes::geo_node_input_normal_declare;
+ ntype.geometry_node_execute = file_ns::node_geo_exec;
+ ntype.declare = file_ns::node_declare;
nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/geometry/nodes/node_geo_input_position.cc b/source/blender/nodes/geometry/nodes/node_geo_input_position.cc
index a8477d4bc4f..8322831a871 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_input_position.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_input_position.cc
@@ -16,27 +16,29 @@
#include "node_geometry_util.hh"
-namespace blender::nodes {
+namespace blender::nodes::node_geo_input_position_cc {
-static void geo_node_input_position_declare(NodeDeclarationBuilder &b)
+static void node_declare(NodeDeclarationBuilder &b)
{
b.add_output<decl::Vector>(N_("Position")).field_source();
}
-static void geo_node_input_position_exec(GeoNodeExecParams params)
+static void node_geo_exec(GeoNodeExecParams params)
{
Field<float3> position_field{AttributeFieldInput::Create<float3>("position")};
params.set_output("Position", std::move(position_field));
}
-} // namespace blender::nodes
+} // namespace blender::nodes::node_geo_input_position_cc
void register_node_type_geo_input_position()
{
+ namespace file_ns = blender::nodes::node_geo_input_position_cc;
+
static bNodeType ntype;
geo_node_type_base(&ntype, GEO_NODE_INPUT_POSITION, "Position", NODE_CLASS_INPUT, 0);
- ntype.geometry_node_execute = blender::nodes::geo_node_input_position_exec;
- ntype.declare = blender::nodes::geo_node_input_position_declare;
+ ntype.geometry_node_execute = file_ns::node_geo_exec;
+ ntype.declare = file_ns::node_declare;
nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/geometry/nodes/node_geo_input_radius.cc b/source/blender/nodes/geometry/nodes/node_geo_input_radius.cc
index 6d2c4c38cbe..26fb74f5a5b 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_input_radius.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_input_radius.cc
@@ -16,27 +16,29 @@
#include "node_geometry_util.hh"
-namespace blender::nodes {
+namespace blender::nodes::node_geo_input_radius_cc {
-static void geo_node_input_radius_declare(NodeDeclarationBuilder &b)
+static void node_declare(NodeDeclarationBuilder &b)
{
b.add_output<decl::Float>(N_("Radius")).default_value(1.0f).min(0.0f).field_source();
}
-static void geo_node_input_radius_exec(GeoNodeExecParams params)
+static void node_geo_exec(GeoNodeExecParams params)
{
Field<float> radius_field = AttributeFieldInput::Create<float>("radius");
params.set_output("Radius", std::move(radius_field));
}
-} // namespace blender::nodes
+} // namespace blender::nodes::node_geo_input_radius_cc
void register_node_type_geo_input_radius()
{
+ namespace file_ns = blender::nodes::node_geo_input_radius_cc;
+
static bNodeType ntype;
geo_node_type_base(&ntype, GEO_NODE_INPUT_RADIUS, "Radius", NODE_CLASS_INPUT, 0);
- ntype.geometry_node_execute = blender::nodes::geo_node_input_radius_exec;
- ntype.declare = blender::nodes::geo_node_input_radius_declare;
+ ntype.geometry_node_execute = file_ns::node_geo_exec;
+ ntype.declare = file_ns::node_declare;
nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/geometry/nodes/node_geo_input_shade_smooth.cc b/source/blender/nodes/geometry/nodes/node_geo_input_shade_smooth.cc
index dcd14b1c054..3efe8577e51 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_input_shade_smooth.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_input_shade_smooth.cc
@@ -16,27 +16,29 @@
#include "node_geometry_util.hh"
-namespace blender::nodes {
+namespace blender::nodes::node_geo_input_shade_smooth_cc {
-static void geo_node_input_shade_smooth_declare(NodeDeclarationBuilder &b)
+static void node_declare(NodeDeclarationBuilder &b)
{
b.add_output<decl::Bool>(N_("Smooth")).field_source();
}
-static void geo_node_input_shade_smooth_exec(GeoNodeExecParams params)
+static void node_geo_exec(GeoNodeExecParams params)
{
Field<bool> shade_smooth_field = AttributeFieldInput::Create<bool>("shade_smooth");
params.set_output("Smooth", std::move(shade_smooth_field));
}
-} // namespace blender::nodes
+} // namespace blender::nodes::node_geo_input_shade_smooth_cc
void register_node_type_geo_input_shade_smooth()
{
+ namespace file_ns = blender::nodes::node_geo_input_shade_smooth_cc;
+
static bNodeType ntype;
geo_node_type_base(&ntype, GEO_NODE_INPUT_SHADE_SMOOTH, "Is Shade Smooth", NODE_CLASS_INPUT, 0);
- ntype.geometry_node_execute = blender::nodes::geo_node_input_shade_smooth_exec;
- ntype.declare = blender::nodes::geo_node_input_shade_smooth_declare;
+ ntype.geometry_node_execute = file_ns::node_geo_exec;
+ ntype.declare = file_ns::node_declare;
nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/geometry/nodes/node_geo_input_spline_cyclic.cc b/source/blender/nodes/geometry/nodes/node_geo_input_spline_cyclic.cc
index a8ee6dd8b12..5f833445a76 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_input_spline_cyclic.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_input_spline_cyclic.cc
@@ -16,28 +16,30 @@
#include "node_geometry_util.hh"
-namespace blender::nodes {
+namespace blender::nodes::node_geo_input_spline_cyclic_cc {
-static void geo_node_input_spline_cyclic_declare(NodeDeclarationBuilder &b)
+static void node_declare(NodeDeclarationBuilder &b)
{
b.add_output<decl::Bool>(N_("Cyclic")).field_source();
}
-static void geo_node_input_spline_cyclic_exec(GeoNodeExecParams params)
+static void node_geo_exec(GeoNodeExecParams params)
{
Field<bool> cyclic_field = AttributeFieldInput::Create<bool>("cyclic");
params.set_output("Cyclic", std::move(cyclic_field));
}
-} // namespace blender::nodes
+} // namespace blender::nodes::node_geo_input_spline_cyclic_cc
void register_node_type_geo_input_spline_cyclic()
{
+ namespace file_ns = blender::nodes::node_geo_input_spline_cyclic_cc;
+
static bNodeType ntype;
geo_node_type_base(
&ntype, GEO_NODE_INPUT_SPLINE_CYCLIC, "Is Spline Cyclic", NODE_CLASS_INPUT, 0);
- ntype.geometry_node_execute = blender::nodes::geo_node_input_spline_cyclic_exec;
- ntype.declare = blender::nodes::geo_node_input_spline_cyclic_declare;
+ ntype.geometry_node_execute = file_ns::node_geo_exec;
+ ntype.declare = file_ns::node_declare;
nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/geometry/nodes/node_geo_input_spline_length.cc b/source/blender/nodes/geometry/nodes/node_geo_input_spline_length.cc
index 895efa6f0ed..998fce5841b 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_input_spline_length.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_input_spline_length.cc
@@ -18,38 +18,32 @@
#include "BKE_spline.hh"
-namespace blender::nodes {
+namespace blender::nodes::node_geo_input_spline_length_cc {
-static void geo_node_input_spline_length_declare(NodeDeclarationBuilder &b)
+static void node_declare(NodeDeclarationBuilder &b)
{
b.add_output<decl::Float>(N_("Length")).field_source();
}
-static const GVArray *construct_spline_length_gvarray(const CurveComponent &component,
- const AttributeDomain domain,
- ResourceScope &scope)
+static VArray<float> construct_spline_length_gvarray(const CurveComponent &component,
+ const AttributeDomain domain,
+ ResourceScope &UNUSED(scope))
{
const CurveEval *curve = component.get_for_read();
if (curve == nullptr) {
- return nullptr;
+ return {};
}
Span<SplinePtr> splines = curve->splines();
auto length_fn = [splines](int i) { return splines[i]->length(); };
if (domain == ATTR_DOMAIN_CURVE) {
- return &scope.construct<
- fn::GVArray_For_EmbeddedVArray<float, VArray_For_Func<float, decltype(length_fn)>>>(
- splines.size(), splines.size(), length_fn);
+ return VArray<float>::ForFunc(splines.size(), length_fn);
}
if (domain == ATTR_DOMAIN_POINT) {
- GVArrayPtr length = std::make_unique<
- fn::GVArray_For_EmbeddedVArray<float, VArray_For_Func<float, decltype(length_fn)>>>(
- splines.size(), splines.size(), length_fn);
- return scope
- .add_value(component.attribute_try_adapt_domain(
- std::move(length), ATTR_DOMAIN_CURVE, ATTR_DOMAIN_POINT))
- .get();
+ VArray<float> length = VArray<float>::ForFunc(splines.size(), length_fn);
+ return component.attribute_try_adapt_domain<float>(
+ std::move(length), ATTR_DOMAIN_CURVE, ATTR_DOMAIN_POINT);
}
return nullptr;
@@ -62,9 +56,9 @@ class SplineLengthFieldInput final : public fn::FieldInput {
category_ = Category::Generated;
}
- const GVArray *get_varray_for_context(const fn::FieldContext &context,
- IndexMask UNUSED(mask),
- ResourceScope &scope) const final
+ GVArray get_varray_for_context(const fn::FieldContext &context,
+ IndexMask UNUSED(mask),
+ ResourceScope &scope) const final
{
if (const GeometryComponentFieldContext *geometry_context =
dynamic_cast<const GeometryComponentFieldContext *>(&context)) {
@@ -76,7 +70,7 @@ class SplineLengthFieldInput final : public fn::FieldInput {
return construct_spline_length_gvarray(curve_component, domain, scope);
}
}
- return nullptr;
+ return {};
}
uint64_t hash() const override
@@ -91,20 +85,22 @@ class SplineLengthFieldInput final : public fn::FieldInput {
}
};
-static void geo_node_input_spline_length_exec(GeoNodeExecParams params)
+static void node_geo_exec(GeoNodeExecParams params)
{
Field<float> length_field{std::make_shared<SplineLengthFieldInput>()};
params.set_output("Length", std::move(length_field));
}
-} // namespace blender::nodes
+} // namespace blender::nodes::node_geo_input_spline_length_cc
void register_node_type_geo_input_spline_length()
{
+ namespace file_ns = blender::nodes::node_geo_input_spline_length_cc;
+
static bNodeType ntype;
geo_node_type_base(&ntype, GEO_NODE_INPUT_SPLINE_LENGTH, "Spline Length", NODE_CLASS_INPUT, 0);
- ntype.geometry_node_execute = blender::nodes::geo_node_input_spline_length_exec;
- ntype.declare = blender::nodes::geo_node_input_spline_length_declare;
+ ntype.geometry_node_execute = file_ns::node_geo_exec;
+ ntype.declare = file_ns::node_declare;
nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/geometry/nodes/node_geo_input_spline_resolution.cc b/source/blender/nodes/geometry/nodes/node_geo_input_spline_resolution.cc
index 75fb8a13d38..77b6e27e6a2 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_input_spline_resolution.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_input_spline_resolution.cc
@@ -16,28 +16,30 @@
#include "node_geometry_util.hh"
-namespace blender::nodes {
+namespace blender::nodes::node_geo_input_spline_resolution_cc {
-static void geo_node_input_spline_resolution_declare(NodeDeclarationBuilder &b)
+static void node_declare(NodeDeclarationBuilder &b)
{
b.add_output<decl::Int>(N_("Resolution")).field_source();
}
-static void geo_node_input_spline_resolution_exec(GeoNodeExecParams params)
+static void node_geo_exec(GeoNodeExecParams params)
{
Field<int> resolution_field = AttributeFieldInput::Create<int>("resolution");
params.set_output("Resolution", std::move(resolution_field));
}
-} // namespace blender::nodes
+} // namespace blender::nodes::node_geo_input_spline_resolution_cc
void register_node_type_geo_input_spline_resolution()
{
+ namespace file_ns = blender::nodes::node_geo_input_spline_resolution_cc;
+
static bNodeType ntype;
geo_node_type_base(
&ntype, GEO_NODE_INPUT_SPLINE_RESOLUTION, "Spline Resolution", NODE_CLASS_INPUT, 0);
- ntype.geometry_node_execute = blender::nodes::geo_node_input_spline_resolution_exec;
- ntype.declare = blender::nodes::geo_node_input_spline_resolution_declare;
+ ntype.geometry_node_execute = file_ns::node_geo_exec;
+ ntype.declare = file_ns::node_declare;
nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/geometry/nodes/node_geo_input_tangent.cc b/source/blender/nodes/geometry/nodes/node_geo_input_tangent.cc
index 6b1736fe2ac..0502f64ecb7 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_input_tangent.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_input_tangent.cc
@@ -20,9 +20,9 @@
#include "node_geometry_util.hh"
-namespace blender::nodes {
+namespace blender::nodes::node_geo_input_tangent_cc {
-static void geo_node_input_tangent_declare(NodeDeclarationBuilder &b)
+static void node_declare(NodeDeclarationBuilder &b)
{
b.add_output<decl::Vector>(N_("Tangent")).field_source();
}
@@ -84,9 +84,9 @@ static Array<float3> curve_tangent_point_domain(const CurveEval &curve)
return tangents;
}
-static const GVArray *construct_curve_tangent_gvarray(const CurveComponent &component,
+static VArray<float3> construct_curve_tangent_gvarray(const CurveComponent &component,
const AttributeDomain domain,
- ResourceScope &scope)
+ ResourceScope &UNUSED(scope))
{
const CurveEval *curve = component.get_for_read();
if (curve == nullptr) {
@@ -100,20 +100,19 @@ static const GVArray *construct_curve_tangent_gvarray(const CurveComponent &comp
* This is only possible when there is only one poly spline. */
if (splines.size() == 1 && splines.first()->type() == Spline::Type::Poly) {
const PolySpline &spline = static_cast<PolySpline &>(*splines.first());
- return &scope.construct<fn::GVArray_For_Span<float3>>(spline.evaluated_tangents());
+ return VArray<float3>::ForSpan(spline.evaluated_tangents());
}
Array<float3> tangents = curve_tangent_point_domain(*curve);
- return &scope.construct<fn::GVArray_For_ArrayContainer<Array<float3>>>(std::move(tangents));
+ return VArray<float3>::ForContainer(std::move(tangents));
}
if (domain == ATTR_DOMAIN_CURVE) {
Array<float3> point_tangents = curve_tangent_point_domain(*curve);
- GVArrayPtr gvarray = std::make_unique<fn::GVArray_For_ArrayContainer<Array<float3>>>(
- std::move(point_tangents));
- GVArrayPtr spline_tangents = component.attribute_try_adapt_domain(
- std::move(gvarray), ATTR_DOMAIN_POINT, ATTR_DOMAIN_CURVE);
- return scope.add_value(std::move(spline_tangents)).get();
+ return component.attribute_try_adapt_domain<float3>(
+ VArray<float3>::ForContainer(std::move(point_tangents)),
+ ATTR_DOMAIN_POINT,
+ ATTR_DOMAIN_CURVE);
}
return nullptr;
@@ -126,9 +125,9 @@ class TangentFieldInput final : public fn::FieldInput {
category_ = Category::Generated;
}
- const GVArray *get_varray_for_context(const fn::FieldContext &context,
- IndexMask UNUSED(mask),
- ResourceScope &scope) const final
+ GVArray get_varray_for_context(const fn::FieldContext &context,
+ IndexMask UNUSED(mask),
+ ResourceScope &scope) const final
{
if (const GeometryComponentFieldContext *geometry_context =
dynamic_cast<const GeometryComponentFieldContext *>(&context)) {
@@ -141,7 +140,7 @@ class TangentFieldInput final : public fn::FieldInput {
return construct_curve_tangent_gvarray(curve_component, domain, scope);
}
}
- return nullptr;
+ return {};
}
uint64_t hash() const override
@@ -156,20 +155,22 @@ class TangentFieldInput final : public fn::FieldInput {
}
};
-static void geo_node_input_tangent_exec(GeoNodeExecParams params)
+static void node_geo_exec(GeoNodeExecParams params)
{
Field<float3> tangent_field{std::make_shared<TangentFieldInput>()};
params.set_output("Tangent", std::move(tangent_field));
}
-} // namespace blender::nodes
+} // namespace blender::nodes::node_geo_input_tangent_cc
void register_node_type_geo_input_tangent()
{
+ namespace file_ns = blender::nodes::node_geo_input_tangent_cc;
+
static bNodeType ntype;
geo_node_type_base(&ntype, GEO_NODE_INPUT_TANGENT, "Curve Tangent", NODE_CLASS_INPUT, 0);
- ntype.geometry_node_execute = blender::nodes::geo_node_input_tangent_exec;
- ntype.declare = blender::nodes::geo_node_input_tangent_declare;
+ ntype.geometry_node_execute = file_ns::node_geo_exec;
+ ntype.declare = file_ns::node_declare;
nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/geometry/nodes/node_geo_instance_on_points.cc b/source/blender/nodes/geometry/nodes/node_geo_instance_on_points.cc
index aff29d973d4..d859289fc59 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_instance_on_points.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_instance_on_points.cc
@@ -24,9 +24,9 @@
#include "node_geometry_util.hh"
-namespace blender::nodes {
+namespace blender::nodes::node_geo_instance_on_points_cc {
-static void geo_node_instance_on_points_declare(NodeDeclarationBuilder &b)
+static void node_declare(NodeDeclarationBuilder &b)
{
b.add_input<decl::Geometry>(N_("Points")).description(N_("Points to instance on"));
b.add_input<decl::Bool>(N_("Selection")).default_value(true).supports_field().hide_value();
@@ -80,10 +80,10 @@ static void add_instances_from_component(InstancesComponent &dst_component,
select_len);
FieldEvaluator field_evaluator{field_context, domain_size};
- const VArray<bool> *pick_instance = nullptr;
- const VArray<int> *indices = nullptr;
- const VArray<float3> *rotations = nullptr;
- const VArray<float3> *scales = nullptr;
+ VArray<bool> pick_instance;
+ VArray<int> indices;
+ VArray<float3> rotations;
+ VArray<float3> scales;
/* The evaluator could use the component's stable IDs as a destination directly, but only the
* selected indices should be copied. */
field_evaluator.add(params.get_input<Field<bool>>("Pick Instance"), &pick_instance);
@@ -92,7 +92,7 @@ static void add_instances_from_component(InstancesComponent &dst_component,
field_evaluator.add(params.get_input<Field<float3>>("Scale"), &scales);
field_evaluator.evaluate();
- GVArray_Typed<float3> positions = src_component.attribute_get_for_read<float3>(
+ VArray<float3> positions = src_component.attribute_get_for_read<float3>(
"position", domain, {0, 0, 0});
const InstancesComponent *src_instances = instance.get_component_for_read<InstancesComponent>();
@@ -101,7 +101,7 @@ static void add_instances_from_component(InstancesComponent &dst_component,
Array<int> handle_mapping;
/* Only fill #handle_mapping when it may be used below. */
if (src_instances != nullptr &&
- (!pick_instance->is_single() || pick_instance->get_internal_single())) {
+ (!pick_instance.is_single() || pick_instance.get_internal_single())) {
Span<InstanceReference> src_references = src_instances->references();
handle_mapping.reinitialize(src_references.size());
for (const int src_instance_handle : src_references.index_range()) {
@@ -121,17 +121,16 @@ static void add_instances_from_component(InstancesComponent &dst_component,
/* Compute base transform for every instances. */
float4x4 &dst_transform = dst_transforms[range_i];
- dst_transform = float4x4::from_loc_eul_scale(
- positions[i], rotations->get(i), scales->get(i));
+ dst_transform = float4x4::from_loc_eul_scale(positions[i], rotations[i], scales[i]);
/* Reference that will be used by this new instance. */
int dst_handle = empty_reference_handle;
- const bool use_individual_instance = pick_instance->get(i);
+ const bool use_individual_instance = pick_instance[i];
if (use_individual_instance) {
if (src_instances != nullptr) {
const int src_instances_amount = src_instances->instances_amount();
- const int original_index = indices->get(i);
+ const int original_index = indices[i];
/* Use #mod_i instead of `%` to get the desirable wrap around behavior where -1
* refers to the last element. */
const int index = mod_i(original_index, std::max(src_instances_amount, 1));
@@ -155,10 +154,10 @@ static void add_instances_from_component(InstancesComponent &dst_component,
}
});
- GVArrayPtr id_attribute = src_component.attribute_try_get_for_read(
- "id", ATTR_DOMAIN_POINT, CD_PROP_INT32);
- if (id_attribute) {
- GVArray_Typed<int> ids{*id_attribute};
+ VArray<int> ids = src_component
+ .attribute_try_get_for_read("id", ATTR_DOMAIN_POINT, CD_PROP_INT32)
+ .typed<int>();
+ if (ids) {
VArray_Span<int> ids_span{ids};
MutableSpan<int> dst_ids = dst_component.instance_ids_ensure();
for (const int64_t i : selection.index_range()) {
@@ -166,8 +165,8 @@ static void add_instances_from_component(InstancesComponent &dst_component,
}
}
- if (pick_instance->is_single()) {
- if (pick_instance->get_internal_single()) {
+ if (pick_instance.is_single()) {
+ if (pick_instance.get_internal_single()) {
if (instance.has_realized_data()) {
params.error_message_add(
NodeWarningType::Info,
@@ -177,7 +176,7 @@ static void add_instances_from_component(InstancesComponent &dst_component,
}
}
-static void geo_node_instance_on_points_exec(GeoNodeExecParams params)
+static void node_geo_exec(GeoNodeExecParams params)
{
GeometrySet geometry_set = params.extract_input<GeometrySet>("Points");
GeometrySet instance = params.get_input<GeometrySet>("Instance");
@@ -215,15 +214,17 @@ static void geo_node_instance_on_points_exec(GeoNodeExecParams params)
params.set_output("Instances", std::move(geometry_set));
}
-} // namespace blender::nodes
+} // namespace blender::nodes::node_geo_instance_on_points_cc
void register_node_type_geo_instance_on_points()
{
+ namespace file_ns = blender::nodes::node_geo_instance_on_points_cc;
+
static bNodeType ntype;
geo_node_type_base(
&ntype, GEO_NODE_INSTANCE_ON_POINTS, "Instance on Points", NODE_CLASS_GEOMETRY, 0);
- ntype.declare = blender::nodes::geo_node_instance_on_points_declare;
- ntype.geometry_node_execute = blender::nodes::geo_node_instance_on_points_exec;
+ ntype.declare = file_ns::node_declare;
+ ntype.geometry_node_execute = file_ns::node_geo_exec;
nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/geometry/nodes/node_geo_instances_to_points.cc b/source/blender/nodes/geometry/nodes/node_geo_instances_to_points.cc
index c3955426e69..71e4a69911c 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_instances_to_points.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_instances_to_points.cc
@@ -19,9 +19,9 @@
#include "node_geometry_util.hh"
-namespace blender::nodes {
+namespace blender::nodes::node_geo_instances_to_points_cc {
-static void geo_node_instances_to_points_declare(NodeDeclarationBuilder &b)
+static void node_declare(NodeDeclarationBuilder &b)
{
b.add_input<decl::Geometry>(N_("Instances")).only_instances();
b.add_input<decl::Bool>(N_("Selection")).default_value(true).hide_value().supports_field();
@@ -51,9 +51,8 @@ static void convert_instances_to_points(GeometrySet &geometry_set,
{
const InstancesComponent &instances = *geometry_set.get_component_for_read<InstancesComponent>();
- const AttributeDomain attribute_domain = ATTR_DOMAIN_POINT;
- GeometryComponentFieldContext field_context{instances, attribute_domain};
- const int domain_size = instances.attribute_domain_size(attribute_domain);
+ GeometryComponentFieldContext field_context{instances, ATTR_DOMAIN_INSTANCE};
+ const int domain_size = instances.attribute_domain_size(ATTR_DOMAIN_INSTANCE);
fn::FieldEvaluator selection_evaluator{field_context, domain_size};
selection_evaluator.add(std::move(selection_field));
@@ -88,7 +87,7 @@ static void convert_instances_to_points(GeometrySet &geometry_set,
}
}
-static void geo_node_instances_to_points_exec(GeoNodeExecParams params)
+static void node_geo_exec(GeoNodeExecParams params)
{
GeometrySet geometry_set = params.extract_input<GeometrySet>("Instances");
@@ -105,15 +104,17 @@ static void geo_node_instances_to_points_exec(GeoNodeExecParams params)
}
}
-} // namespace blender::nodes
+} // namespace blender::nodes::node_geo_instances_to_points_cc
void register_node_type_geo_instances_to_points()
{
+ namespace file_ns = blender::nodes::node_geo_instances_to_points_cc;
+
static bNodeType ntype;
geo_node_type_base(
&ntype, GEO_NODE_INSTANCES_TO_POINTS, "Instances to Points", NODE_CLASS_GEOMETRY, 0);
- ntype.declare = blender::nodes::geo_node_instances_to_points_declare;
- ntype.geometry_node_execute = blender::nodes::geo_node_instances_to_points_exec;
+ ntype.declare = file_ns::node_declare;
+ ntype.geometry_node_execute = file_ns::node_geo_exec;
nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/geometry/nodes/node_geo_is_viewport.cc b/source/blender/nodes/geometry/nodes/node_geo_is_viewport.cc
index 8e0e98f7bd5..5925d440317 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_is_viewport.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_is_viewport.cc
@@ -18,14 +18,14 @@
#include "node_geometry_util.hh"
-namespace blender::nodes {
+namespace blender::nodes::node_geo_is_viewport_cc {
-static void geo_node_is_viewport_declare(NodeDeclarationBuilder &b)
+static void node_declare(NodeDeclarationBuilder &b)
{
b.add_output<decl::Bool>(N_("Is Viewport"));
}
-static void geo_node_is_viewport_exec(GeoNodeExecParams params)
+static void node_geo_exec(GeoNodeExecParams params)
{
const Depsgraph *depsgraph = params.depsgraph();
const eEvaluationMode mode = DEG_get_mode(depsgraph);
@@ -34,14 +34,16 @@ static void geo_node_is_viewport_exec(GeoNodeExecParams params)
params.set_output("Is Viewport", is_viewport);
}
-} // namespace blender::nodes
+} // namespace blender::nodes::node_geo_is_viewport_cc
void register_node_type_geo_is_viewport()
{
+ namespace file_ns = blender::nodes::node_geo_is_viewport_cc;
+
static bNodeType ntype;
geo_node_type_base(&ntype, GEO_NODE_IS_VIEWPORT, "Is Viewport", NODE_CLASS_INPUT, 0);
- ntype.geometry_node_execute = blender::nodes::geo_node_is_viewport_exec;
- ntype.declare = blender::nodes::geo_node_is_viewport_declare;
+ ntype.geometry_node_execute = file_ns::node_geo_exec;
+ ntype.declare = file_ns::node_declare;
nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/geometry/nodes/node_geo_join_geometry.cc b/source/blender/nodes/geometry/nodes/node_geo_join_geometry.cc
index 9d363bd1af4..53f7d968644 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_join_geometry.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_join_geometry.cc
@@ -27,11 +27,9 @@
#include "node_geometry_util.hh"
-using blender::fn::GVArray_For_GSpan;
+namespace blender::nodes::node_geo_join_geometry_cc {
-namespace blender::nodes {
-
-static void geo_node_join_geometry_declare(NodeDeclarationBuilder &b)
+static void node_declare(NodeDeclarationBuilder &b)
{
b.add_input<decl::Geometry>(N_("Geometry")).multi_input();
b.add_output<decl::Geometry>(N_("Geometry"));
@@ -190,10 +188,10 @@ static void fill_new_attribute(Span<const GeometryComponent *> src_components,
if (domain_size == 0) {
continue;
}
- GVArrayPtr read_attribute = component->attribute_get_for_read(
+ GVArray read_attribute = component->attribute_get_for_read(
attribute_id, domain, data_type, nullptr);
- GVArray_GSpan src_span{*read_attribute};
+ GVArray_GSpan src_span{read_attribute};
const void *src_buffer = src_span.data();
void *dst_buffer = dst_span[offset];
cpp_type->copy_assign_n(src_buffer, dst_buffer, domain_size);
@@ -319,8 +317,7 @@ static void ensure_control_point_attribute(const AttributeIDRef &attribute_id,
spline->size() * type.size(), type.alignment(), __func__);
const DataTypeConversions &conversions = blender::nodes::get_implicit_type_conversions();
- conversions.try_convert(std::make_unique<GVArray_For_GSpan>(*attribute), type)
- ->materialize(converted_buffer);
+ conversions.try_convert(GVArray::ForSpan(*attribute), type).materialize(converted_buffer);
spline->attributes.remove(attribute_id);
spline->attributes.create_by_move(attribute_id, data_type, converted_buffer);
@@ -333,14 +330,14 @@ static void ensure_control_point_attribute(const AttributeIDRef &attribute_id,
/* In this case the attribute did not exist, but there is a spline domain attribute
* we can retrieve a value from, as a spline to point domain conversion. So fill the
* new attribute with the value for this spline. */
- GVArrayPtr current_curve_attribute = current_curve->attributes.get_for_read(
+ GVArray current_curve_attribute = current_curve->attributes.get_for_read(
attribute_id, data_type, nullptr);
BLI_assert(spline->attributes.get_for_read(attribute_id));
std::optional<GMutableSpan> new_attribute = spline->attributes.get_for_write(attribute_id);
BUFFER_FOR_CPP_TYPE_VALUE(type, buffer);
- current_curve_attribute->get(spline_index_in_component, buffer);
+ current_curve_attribute.get(spline_index_in_component, buffer);
type.fill_assign_n(buffer, new_attribute->data(), new_attribute->size());
}
}
@@ -397,8 +394,8 @@ static void ensure_spline_attribute(const AttributeIDRef &attribute_id,
if (size == 0) {
continue;
}
- GVArrayPtr read_attribute = curve.attributes.get_for_read(attribute_id, data_type, nullptr);
- GVArray_GSpan src_span{*read_attribute};
+ GVArray read_attribute = curve.attributes.get_for_read(attribute_id, data_type, nullptr);
+ GVArray_GSpan src_span{read_attribute};
const void *src_buffer = src_span.data();
type.copy_assign_n(src_buffer, result_attribute[offset], size);
@@ -498,7 +495,7 @@ static void join_component_type(Span<GeometrySet> src_geometry_sets, GeometrySet
join_components(components, result);
}
-static void geo_node_join_geometry_exec(GeoNodeExecParams params)
+static void node_geo_exec(GeoNodeExecParams params)
{
Vector<GeometrySet> geometry_sets = params.extract_multi_input<GeometrySet>("Geometry");
@@ -511,14 +508,16 @@ static void geo_node_join_geometry_exec(GeoNodeExecParams params)
params.set_output("Geometry", std::move(geometry_set_result));
}
-} // namespace blender::nodes
+} // namespace blender::nodes::node_geo_join_geometry_cc
void register_node_type_geo_join_geometry()
{
+ namespace file_ns = blender::nodes::node_geo_join_geometry_cc;
+
static bNodeType ntype;
geo_node_type_base(&ntype, GEO_NODE_JOIN_GEOMETRY, "Join Geometry", NODE_CLASS_GEOMETRY, 0);
- ntype.geometry_node_execute = blender::nodes::geo_node_join_geometry_exec;
- ntype.declare = blender::nodes::geo_node_join_geometry_declare;
+ ntype.geometry_node_execute = file_ns::node_geo_exec;
+ ntype.declare = file_ns::node_declare;
nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/geometry/nodes/node_geo_material_replace.cc b/source/blender/nodes/geometry/nodes/node_geo_material_replace.cc
index e4a62bd5267..5a334126350 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_material_replace.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_material_replace.cc
@@ -24,9 +24,9 @@
#include "BKE_material.h"
-namespace blender::nodes {
+namespace blender::nodes::node_geo_material_replace_cc {
-static void geo_node_material_replace_declare(NodeDeclarationBuilder &b)
+static void node_declare(NodeDeclarationBuilder &b)
{
b.add_input<decl::Geometry>(N_("Geometry")).supported_type(GEO_COMPONENT_TYPE_MESH);
b.add_input<decl::Material>(N_("Old"));
@@ -34,7 +34,7 @@ static void geo_node_material_replace_declare(NodeDeclarationBuilder &b)
b.add_output<decl::Geometry>(N_("Geometry"));
}
-static void geo_node_material_replace_exec(GeoNodeExecParams params)
+static void node_geo_exec(GeoNodeExecParams params)
{
Material *old_material = params.extract_input<Material *>("Old");
Material *new_material = params.extract_input<Material *>("New");
@@ -55,15 +55,17 @@ static void geo_node_material_replace_exec(GeoNodeExecParams params)
params.set_output("Geometry", std::move(geometry_set));
}
-} // namespace blender::nodes
+} // namespace blender::nodes::node_geo_material_replace_cc
void register_node_type_geo_material_replace()
{
+ namespace file_ns = blender::nodes::node_geo_material_replace_cc;
+
static bNodeType ntype;
geo_node_type_base(
&ntype, GEO_NODE_REPLACE_MATERIAL, "Replace Material", NODE_CLASS_GEOMETRY, 0);
- ntype.declare = blender::nodes::geo_node_material_replace_declare;
- ntype.geometry_node_execute = blender::nodes::geo_node_material_replace_exec;
+ ntype.declare = file_ns::node_declare;
+ ntype.geometry_node_execute = file_ns::node_geo_exec;
nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/geometry/nodes/node_geo_material_selection.cc b/source/blender/nodes/geometry/nodes/node_geo_material_selection.cc
index 06c770820ee..948565b62f0 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_material_selection.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_material_selection.cc
@@ -26,9 +26,9 @@
#include "BKE_material.h"
-namespace blender::nodes {
+namespace blender::nodes::node_geo_material_selection_cc {
-static void geo_node_material_selection_declare(NodeDeclarationBuilder &b)
+static void node_declare(NodeDeclarationBuilder &b)
{
b.add_input<decl::Material>(N_("Material")).hide_label(true);
b.add_output<decl::Bool>(N_("Selection")).field_source();
@@ -64,36 +64,33 @@ class MaterialSelectionFieldInput final : public fn::FieldInput {
category_ = Category::Generated;
}
- const GVArray *get_varray_for_context(const fn::FieldContext &context,
- IndexMask mask,
- ResourceScope &scope) const final
+ GVArray get_varray_for_context(const fn::FieldContext &context,
+ IndexMask mask,
+ ResourceScope &UNUSED(scope)) const final
{
if (const GeometryComponentFieldContext *geometry_context =
dynamic_cast<const GeometryComponentFieldContext *>(&context)) {
const GeometryComponent &component = geometry_context->geometry_component();
const AttributeDomain domain = geometry_context->domain();
if (component.type() != GEO_COMPONENT_TYPE_MESH) {
- return nullptr;
+ return {};
}
const MeshComponent &mesh_component = static_cast<const MeshComponent &>(component);
const Mesh *mesh = mesh_component.get_for_read();
if (mesh == nullptr) {
- return nullptr;
+ return {};
}
if (domain == ATTR_DOMAIN_FACE) {
Array<bool> selection(mask.min_array_size());
select_mesh_by_material(*mesh, material_, mask, selection);
- return &scope.construct<fn::GVArray_For_ArrayContainer<Array<bool>>>(std::move(selection));
+ return VArray<bool>::ForContainer(std::move(selection));
}
Array<bool> selection(mesh->totpoly);
select_mesh_by_material(*mesh, material_, IndexMask(mesh->totpoly), selection);
- GVArrayPtr face_selection = std::make_unique<fn::GVArray_For_ArrayContainer<Array<bool>>>(
- std::move(selection));
- GVArrayPtr final_selection = mesh_component.attribute_try_adapt_domain(
- std::move(face_selection), ATTR_DOMAIN_FACE, domain);
- return scope.add_value(std::move(final_selection)).get();
+ return mesh_component.attribute_try_adapt_domain<bool>(
+ VArray<bool>::ForContainer(std::move(selection)), ATTR_DOMAIN_FACE, domain);
}
return nullptr;
@@ -114,22 +111,24 @@ class MaterialSelectionFieldInput final : public fn::FieldInput {
}
};
-static void geo_node_material_selection_exec(GeoNodeExecParams params)
+static void node_geo_exec(GeoNodeExecParams params)
{
Material *material = params.extract_input<Material *>("Material");
Field<bool> material_field{std::make_shared<MaterialSelectionFieldInput>(material)};
params.set_output("Selection", std::move(material_field));
}
-} // namespace blender::nodes
+} // namespace blender::nodes::node_geo_material_selection_cc
void register_node_type_geo_material_selection()
{
+ namespace file_ns = blender::nodes::node_geo_material_selection_cc;
+
static bNodeType ntype;
geo_node_type_base(
&ntype, GEO_NODE_MATERIAL_SELECTION, "Material Selection", NODE_CLASS_GEOMETRY, 0);
- ntype.declare = blender::nodes::geo_node_material_selection_declare;
- ntype.geometry_node_execute = blender::nodes::geo_node_material_selection_exec;
+ ntype.declare = file_ns::node_declare;
+ ntype.geometry_node_execute = file_ns::node_geo_exec;
nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_circle.cc b/source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_circle.cc
index 685a8faff5c..ec06bdc0455 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_circle.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_circle.cc
@@ -25,25 +25,30 @@
#include "node_geometry_util.hh"
-namespace blender::nodes {
+namespace blender::nodes::node_geo_mesh_primitive_circle_cc {
-static void geo_node_mesh_primitive_circle_declare(NodeDeclarationBuilder &b)
+static void node_declare(NodeDeclarationBuilder &b)
{
- b.add_input<decl::Int>(N_("Vertices")).default_value(32).min(3);
- b.add_input<decl::Float>(N_("Radius")).default_value(1.0f).min(0.0f).subtype(PROP_DISTANCE);
+ b.add_input<decl::Int>(N_("Vertices"))
+ .default_value(32)
+ .min(3)
+ .description(N_("Number of vertices on the circle"));
+ b.add_input<decl::Float>(N_("Radius"))
+ .default_value(1.0f)
+ .min(0.0f)
+ .subtype(PROP_DISTANCE)
+ .description(N_("Distance of the vertices from the origin"));
b.add_output<decl::Geometry>(N_("Mesh"));
}
-static void geo_node_mesh_primitive_circle_layout(uiLayout *layout,
- bContext *UNUSED(C),
- PointerRNA *ptr)
+static void node_layout(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
{
uiLayoutSetPropSep(layout, true);
uiLayoutSetPropDecorate(layout, false);
uiItemR(layout, ptr, "fill_type", 0, nullptr, ICON_NONE);
}
-static void geo_node_mesh_primitive_circle_init(bNodeTree *UNUSED(ntree), bNode *node)
+static void node_init(bNodeTree *UNUSED(ntree), bNode *node)
{
NodeGeometryMeshCircle *node_storage = (NodeGeometryMeshCircle *)MEM_callocN(
sizeof(NodeGeometryMeshCircle), __func__);
@@ -192,7 +197,7 @@ static Mesh *create_circle_mesh(const float radius,
return mesh;
}
-static void geo_node_mesh_primitive_circle_exec(GeoNodeExecParams params)
+static void node_geo_exec(GeoNodeExecParams params)
{
const bNode &node = params.node();
const NodeGeometryMeshCircle &storage = *(const NodeGeometryMeshCircle *)node.storage;
@@ -215,19 +220,21 @@ static void geo_node_mesh_primitive_circle_exec(GeoNodeExecParams params)
params.set_output("Mesh", GeometrySet::create_with_mesh(mesh));
}
-} // namespace blender::nodes
+} // namespace blender::nodes::node_geo_mesh_primitive_circle_cc
void register_node_type_geo_mesh_primitive_circle()
{
+ namespace file_ns = blender::nodes::node_geo_mesh_primitive_circle_cc;
+
static bNodeType ntype;
geo_node_type_base(
&ntype, GEO_NODE_MESH_PRIMITIVE_CIRCLE, "Mesh Circle", NODE_CLASS_GEOMETRY, 0);
- node_type_init(&ntype, blender::nodes::geo_node_mesh_primitive_circle_init);
+ node_type_init(&ntype, file_ns::node_init);
node_type_storage(
&ntype, "NodeGeometryMeshCircle", node_free_standard_storage, node_copy_standard_storage);
- ntype.geometry_node_execute = blender::nodes::geo_node_mesh_primitive_circle_exec;
- ntype.draw_buttons = blender::nodes::geo_node_mesh_primitive_circle_layout;
- ntype.declare = blender::nodes::geo_node_mesh_primitive_circle_declare;
+ ntype.geometry_node_execute = file_ns::node_geo_exec;
+ ntype.draw_buttons = file_ns::node_layout;
+ ntype.declare = file_ns::node_declare;
nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_cone.cc b/source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_cone.cc
index 206d48d40c8..d2739e7e3ad 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_cone.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_cone.cc
@@ -25,53 +25,9 @@
#include "node_geometry_util.hh"
-namespace blender::nodes {
-
-static void geo_node_mesh_primitive_cone_declare(NodeDeclarationBuilder &b)
-{
- b.add_input<decl::Int>(N_("Vertices")).default_value(32).min(3).max(512);
- b.add_input<decl::Int>(N_("Side Segments")).default_value(1).min(1).max(512);
- b.add_input<decl::Int>(N_("Fill Segments")).default_value(1).min(1).max(512);
- b.add_input<decl::Float>(N_("Radius Top")).min(0.0f).subtype(PROP_DISTANCE);
- b.add_input<decl::Float>(N_("Radius Bottom"))
- .default_value(1.0f)
- .min(0.0f)
- .subtype(PROP_DISTANCE);
- b.add_input<decl::Float>(N_("Depth")).default_value(2.0f).min(0.0f).subtype(PROP_DISTANCE);
- b.add_output<decl::Geometry>(N_("Mesh"));
-}
-
-static void geo_node_mesh_primitive_cone_init(bNodeTree *UNUSED(ntree), bNode *node)
-{
- NodeGeometryMeshCone *node_storage = (NodeGeometryMeshCone *)MEM_callocN(
- sizeof(NodeGeometryMeshCone), __func__);
-
- node_storage->fill_type = GEO_NODE_MESH_CIRCLE_FILL_NGON;
-
- node->storage = node_storage;
-}
+#include <cmath>
-static void geo_node_mesh_primitive_cone_update(bNodeTree *UNUSED(ntree), bNode *node)
-{
- bNodeSocket *vertices_socket = (bNodeSocket *)node->inputs.first;
- bNodeSocket *rings_socket = vertices_socket->next;
- bNodeSocket *fill_subdiv_socket = rings_socket->next;
-
- const NodeGeometryMeshCone &storage = *(const NodeGeometryMeshCone *)node->storage;
- const GeometryNodeMeshCircleFillType fill_type =
- static_cast<const GeometryNodeMeshCircleFillType>(storage.fill_type);
- const bool has_fill = fill_type != GEO_NODE_MESH_CIRCLE_FILL_NONE;
- nodeSetSocketAvailability(fill_subdiv_socket, has_fill);
-}
-
-static void geo_node_mesh_primitive_cone_layout(uiLayout *layout,
- bContext *UNUSED(C),
- PointerRNA *ptr)
-{
- uiLayoutSetPropSep(layout, true);
- uiLayoutSetPropDecorate(layout, false);
- uiItemR(layout, ptr, "fill_type", 0, nullptr, ICON_NONE);
-}
+namespace blender::nodes {
struct ConeConfig {
float radius_top;
@@ -94,6 +50,8 @@ struct ConeConfig {
int tot_edge_rings;
int tot_verts;
int tot_edges;
+ int tot_corners;
+ int tot_faces;
/* Helpful vertex indices. */
int first_vert;
@@ -107,6 +65,14 @@ struct ConeConfig {
int last_fan_edges_start;
int last_edge;
+ /* Helpful face indices. */
+ int top_faces_start;
+ int top_faces_len;
+ int side_faces_start;
+ int side_faces_len;
+ int bottom_faces_start;
+ int bottom_faces_len;
+
ConeConfig(float radius_top,
float radius_bottom,
float depth,
@@ -133,6 +99,7 @@ struct ConeConfig {
this->tot_edge_rings = this->calculate_total_edge_rings();
this->tot_verts = this->calculate_total_verts();
this->tot_edges = this->calculate_total_edges();
+ this->tot_corners = this->calculate_total_corners();
this->first_vert = 0;
this->first_ring_verts_start = this->top_has_center_vert ? 1 : first_vert;
@@ -144,6 +111,36 @@ struct ConeConfig {
this->tot_quad_rings * this->circle_segments * 2;
this->last_fan_edges_start = this->tot_edges - this->circle_segments;
this->last_edge = this->tot_edges - 1;
+
+ this->top_faces_start = 0;
+ if (!this->top_is_point) {
+ this->top_faces_len = (fill_segments - 1) * circle_segments;
+ this->top_faces_len += this->top_has_center_vert ? circle_segments : 0;
+ this->top_faces_len += this->fill_type == GEO_NODE_MESH_CIRCLE_FILL_NGON ? 1 : 0;
+ }
+ else {
+ this->top_faces_len = 0;
+ }
+
+ this->side_faces_start = this->top_faces_len;
+ if (this->top_is_point && this->bottom_is_point) {
+ this->side_faces_len = 0;
+ }
+ else {
+ this->side_faces_len = side_segments * circle_segments;
+ }
+
+ if (!this->bottom_is_point) {
+ this->bottom_faces_len = (fill_segments - 1) * circle_segments;
+ this->bottom_faces_len += this->bottom_has_center_vert ? circle_segments : 0;
+ this->bottom_faces_len += this->fill_type == GEO_NODE_MESH_CIRCLE_FILL_NGON ? 1 : 0;
+ }
+ else {
+ this->bottom_faces_len = 0;
+ }
+ this->bottom_faces_start = this->side_faces_start + this->side_faces_len;
+
+ this->tot_faces = this->top_faces_len + this->side_faces_len + this->bottom_faces_len;
}
private:
@@ -151,10 +148,7 @@ struct ConeConfig {
int calculate_total_edge_rings();
int calculate_total_verts();
int calculate_total_edges();
-
- public:
- int get_tot_corners() const;
- int get_tot_faces() const;
+ int calculate_total_corners();
};
int ConeConfig::calculate_total_quad_rings()
@@ -248,7 +242,7 @@ int ConeConfig::calculate_total_edges()
return edge_total;
}
-int ConeConfig::get_tot_corners() const
+int ConeConfig::calculate_total_corners()
{
if (top_is_point && bottom_is_point) {
return 0;
@@ -275,32 +269,6 @@ int ConeConfig::get_tot_corners() const
return corner_total;
}
-int ConeConfig::get_tot_faces() const
-{
- if (top_is_point && bottom_is_point) {
- return 0;
- }
-
- int face_total = 0;
- if (top_has_center_vert) {
- face_total += circle_segments;
- }
- else if (!top_is_point && fill_type == GEO_NODE_MESH_CIRCLE_FILL_NGON) {
- face_total++;
- }
-
- face_total += tot_quad_rings * circle_segments;
-
- if (bottom_has_center_vert) {
- face_total += circle_segments;
- }
- else if (!bottom_is_point && fill_type == GEO_NODE_MESH_CIRCLE_FILL_NGON) {
- face_total++;
- }
-
- return face_total;
-}
-
static void calculate_cone_vertices(const MutableSpan<MVert> &verts, const ConeConfig &config)
{
Array<float2> circle(config.circle_segments);
@@ -522,6 +490,60 @@ static void calculate_cone_faces(const MutableSpan<MLoop> &loops,
}
}
+static void calculate_selection_outputs(Mesh *mesh,
+ const ConeConfig &config,
+ ConeAttributeOutputs &attribute_outputs)
+{
+ MeshComponent mesh_component;
+ mesh_component.replace(mesh, GeometryOwnershipType::Editable);
+
+ /* Populate "Top" selection output. */
+ if (attribute_outputs.top_id) {
+ const bool face = !config.top_is_point && config.fill_type != GEO_NODE_MESH_CIRCLE_FILL_NONE;
+ OutputAttribute_Typed<bool> attribute = mesh_component.attribute_try_get_for_output_only<bool>(
+ attribute_outputs.top_id.get(), face ? ATTR_DOMAIN_FACE : ATTR_DOMAIN_POINT);
+ MutableSpan<bool> selection = attribute.as_span();
+
+ if (config.top_is_point) {
+ selection[config.first_vert] = true;
+ }
+ else {
+ selection.slice(0, face ? config.top_faces_len : config.circle_segments).fill(true);
+ }
+ attribute.save();
+ }
+
+ /* Populate "Bottom" selection output. */
+ if (attribute_outputs.bottom_id) {
+ const bool face = !config.bottom_is_point &&
+ config.fill_type != GEO_NODE_MESH_CIRCLE_FILL_NONE;
+ OutputAttribute_Typed<bool> attribute = mesh_component.attribute_try_get_for_output_only<bool>(
+ attribute_outputs.bottom_id.get(), face ? ATTR_DOMAIN_FACE : ATTR_DOMAIN_POINT);
+ MutableSpan<bool> selection = attribute.as_span();
+
+ if (config.bottom_is_point) {
+ selection[config.last_vert] = true;
+ }
+ else {
+ selection
+ .slice(config.bottom_faces_start,
+ face ? config.bottom_faces_len : config.circle_segments)
+ .fill(true);
+ }
+ attribute.save();
+ }
+
+ /* Populate "Side" selection output. */
+ if (attribute_outputs.side_id) {
+ OutputAttribute_Typed<bool> attribute = mesh_component.attribute_try_get_for_output_only<bool>(
+ attribute_outputs.side_id.get(), ATTR_DOMAIN_FACE);
+ MutableSpan<bool> selection = attribute.as_span();
+
+ selection.slice(config.side_faces_start, config.side_faces_len).fill(true);
+ attribute.save();
+ }
+}
+
/**
* If the top is the cone tip or has a fill, it is unwrapped into a circle in the
* lower left quadrant of the UV.
@@ -665,7 +687,8 @@ Mesh *create_cylinder_or_cone_mesh(const float radius_top,
const int circle_segments,
const int side_segments,
const int fill_segments,
- const GeometryNodeMeshCircleFillType fill_type)
+ const GeometryNodeMeshCircleFillType fill_type,
+ ConeAttributeOutputs &attribute_outputs)
{
const ConeConfig config(
radius_top, radius_bottom, depth, circle_segments, side_segments, fill_segments, fill_type);
@@ -683,7 +706,7 @@ Mesh *create_cylinder_or_cone_mesh(const float radius_top,
}
Mesh *mesh = BKE_mesh_new_nomain(
- config.tot_verts, config.tot_edges, 0, config.get_tot_corners(), config.get_tot_faces());
+ config.tot_verts, config.tot_edges, 0, config.tot_corners, config.tot_faces);
BKE_id_material_eval_ensure_default_slot(&mesh->id);
MutableSpan<MVert> verts{mesh->mvert, mesh->totvert};
@@ -695,67 +718,179 @@ Mesh *create_cylinder_or_cone_mesh(const float radius_top,
calculate_cone_edges(edges, config);
calculate_cone_faces(loops, polys, config);
calculate_cone_uvs(mesh, config);
+ calculate_selection_outputs(mesh, config, attribute_outputs);
BKE_mesh_normals_tag_dirty(mesh);
return mesh;
}
-static void geo_node_mesh_primitive_cone_exec(GeoNodeExecParams params)
+} // namespace blender::nodes
+
+namespace blender::nodes::node_geo_mesh_primitive_cone_cc {
+
+static void node_declare(NodeDeclarationBuilder &b)
+{
+ b.add_input<decl::Int>(N_("Vertices"))
+ .default_value(32)
+ .min(3)
+ .max(512)
+ .description(N_("Number of points on the circle at the top and bottom"));
+ b.add_input<decl::Int>(N_("Side Segments"))
+ .default_value(1)
+ .min(1)
+ .max(512)
+ .description(N_("The number of edges running vertically along the side of the cone"));
+ b.add_input<decl::Int>(N_("Fill Segments"))
+ .default_value(1)
+ .min(1)
+ .max(512)
+ .description(N_("Number of concentric rings used to fill the round face"));
+ b.add_input<decl::Float>(N_("Radius Top"))
+ .min(0.0f)
+ .subtype(PROP_DISTANCE)
+ .description(N_("Radius of the top circle of the cone"));
+ b.add_input<decl::Float>(N_("Radius Bottom"))
+ .default_value(1.0f)
+ .min(0.0f)
+ .subtype(PROP_DISTANCE)
+ .description(N_("Radius of the bottom circle of the cone"));
+ b.add_input<decl::Float>(N_("Depth"))
+ .default_value(2.0f)
+ .min(0.0f)
+ .subtype(PROP_DISTANCE)
+ .description(N_("Height of the generated cone"));
+ b.add_output<decl::Geometry>(N_("Mesh"));
+ b.add_output<decl::Bool>(N_("Top")).field_source();
+ b.add_output<decl::Bool>(N_("Bottom")).field_source();
+ b.add_output<decl::Bool>(N_("Side")).field_source();
+}
+
+static void node_init(bNodeTree *UNUSED(ntree), bNode *node)
+{
+ NodeGeometryMeshCone *node_storage = (NodeGeometryMeshCone *)MEM_callocN(
+ sizeof(NodeGeometryMeshCone), __func__);
+
+ node_storage->fill_type = GEO_NODE_MESH_CIRCLE_FILL_NGON;
+
+ node->storage = node_storage;
+}
+
+static void node_update(bNodeTree *ntree, bNode *node)
+{
+ bNodeSocket *vertices_socket = (bNodeSocket *)node->inputs.first;
+ bNodeSocket *rings_socket = vertices_socket->next;
+ bNodeSocket *fill_subdiv_socket = rings_socket->next;
+
+ const NodeGeometryMeshCone &storage = *(const NodeGeometryMeshCone *)node->storage;
+ const GeometryNodeMeshCircleFillType fill_type =
+ static_cast<const GeometryNodeMeshCircleFillType>(storage.fill_type);
+ const bool has_fill = fill_type != GEO_NODE_MESH_CIRCLE_FILL_NONE;
+ nodeSetSocketAvailability(ntree, fill_subdiv_socket, has_fill);
+}
+
+static void node_layout(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
+{
+ uiLayoutSetPropSep(layout, true);
+ uiLayoutSetPropDecorate(layout, false);
+ uiItemR(layout, ptr, "fill_type", 0, nullptr, ICON_NONE);
+}
+
+static void node_geo_exec(GeoNodeExecParams params)
{
const bNode &node = params.node();
const NodeGeometryMeshCone &storage = *(const NodeGeometryMeshCone *)node.storage;
const GeometryNodeMeshCircleFillType fill_type = (const GeometryNodeMeshCircleFillType)
storage.fill_type;
+ auto return_default = [&]() {
+ params.set_output("Top", fn::make_constant_field<bool>(false));
+ params.set_output("Bottom", fn::make_constant_field<bool>(false));
+ params.set_output("Side", fn::make_constant_field<bool>(false));
+ params.set_output("Mesh", GeometrySet());
+ };
+
const int circle_segments = params.extract_input<int>("Vertices");
if (circle_segments < 3) {
params.error_message_add(NodeWarningType::Info, TIP_("Vertices must be at least 3"));
- params.set_output("Mesh", GeometrySet());
- return;
+ return return_default();
}
const int side_segments = params.extract_input<int>("Side Segments");
if (side_segments < 1) {
params.error_message_add(NodeWarningType::Info, TIP_("Side Segments must be at least 1"));
- params.set_output("Mesh", GeometrySet());
- return;
+ return return_default();
}
const bool no_fill = fill_type == GEO_NODE_MESH_CIRCLE_FILL_NONE;
const int fill_segments = no_fill ? 1 : params.extract_input<int>("Fill Segments");
if (fill_segments < 1) {
params.error_message_add(NodeWarningType::Info, TIP_("Fill Segments must be at least 1"));
- params.set_output("Mesh", GeometrySet());
- return;
+ return return_default();
}
const float radius_top = params.extract_input<float>("Radius Top");
const float radius_bottom = params.extract_input<float>("Radius Bottom");
const float depth = params.extract_input<float>("Depth");
- Mesh *mesh = create_cylinder_or_cone_mesh(
- radius_top, radius_bottom, depth, circle_segments, side_segments, fill_segments, fill_type);
+ ConeAttributeOutputs attribute_outputs;
+ if (params.output_is_required("Top")) {
+ attribute_outputs.top_id = StrongAnonymousAttributeID("top_selection");
+ }
+ if (params.output_is_required("Bottom")) {
+ attribute_outputs.bottom_id = StrongAnonymousAttributeID("bottom_selection");
+ }
+ if (params.output_is_required("Side")) {
+ attribute_outputs.side_id = StrongAnonymousAttributeID("side_selection");
+ }
+
+ Mesh *mesh = create_cylinder_or_cone_mesh(radius_top,
+ radius_bottom,
+ depth,
+ circle_segments,
+ side_segments,
+ fill_segments,
+ fill_type,
+ attribute_outputs);
/* Transform the mesh so that the base of the cone is at the origin. */
BKE_mesh_translate(mesh, float3(0.0f, 0.0f, depth * 0.5f), false);
+ if (attribute_outputs.top_id) {
+ params.set_output("Top",
+ AnonymousAttributeFieldInput::Create<bool>(
+ std::move(attribute_outputs.top_id), params.attribute_producer_name()));
+ }
+ if (attribute_outputs.bottom_id) {
+ params.set_output(
+ "Bottom",
+ AnonymousAttributeFieldInput::Create<bool>(std::move(attribute_outputs.bottom_id),
+ params.attribute_producer_name()));
+ }
+ if (attribute_outputs.side_id) {
+ params.set_output("Side",
+ AnonymousAttributeFieldInput::Create<bool>(
+ std::move(attribute_outputs.side_id), params.attribute_producer_name()));
+ }
+
params.set_output("Mesh", GeometrySet::create_with_mesh(mesh));
}
-} // namespace blender::nodes
+} // namespace blender::nodes::node_geo_mesh_primitive_cone_cc
void register_node_type_geo_mesh_primitive_cone()
{
+ namespace file_ns = blender::nodes::node_geo_mesh_primitive_cone_cc;
+
static bNodeType ntype;
geo_node_type_base(&ntype, GEO_NODE_MESH_PRIMITIVE_CONE, "Cone", NODE_CLASS_GEOMETRY, 0);
- node_type_init(&ntype, blender::nodes::geo_node_mesh_primitive_cone_init);
- node_type_update(&ntype, blender::nodes::geo_node_mesh_primitive_cone_update);
+ node_type_init(&ntype, file_ns::node_init);
+ node_type_update(&ntype, file_ns::node_update);
node_type_storage(
&ntype, "NodeGeometryMeshCone", node_free_standard_storage, node_copy_standard_storage);
- ntype.geometry_node_execute = blender::nodes::geo_node_mesh_primitive_cone_exec;
- ntype.draw_buttons = blender::nodes::geo_node_mesh_primitive_cone_layout;
- ntype.declare = blender::nodes::geo_node_mesh_primitive_cone_declare;
+ ntype.geometry_node_execute = file_ns::node_geo_exec;
+ ntype.draw_buttons = file_ns::node_layout;
+ ntype.declare = file_ns::node_declare;
nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_cube.cc b/source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_cube.cc
index 3a211993bdc..682efcc81bd 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_cube.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_cube.cc
@@ -24,18 +24,6 @@
namespace blender::nodes {
-static void geo_node_mesh_primitive_cube_declare(NodeDeclarationBuilder &b)
-{
- b.add_input<decl::Vector>(N_("Size"))
- .default_value(float3(1))
- .min(0.0f)
- .subtype(PROP_TRANSLATION);
- b.add_input<decl::Int>(N_("Vertices X")).default_value(2).min(2).max(1000);
- b.add_input<decl::Int>(N_("Vertices Y")).default_value(2).min(2).max(1000);
- b.add_input<decl::Int>(N_("Vertices Z")).default_value(2).min(2).max(1000);
- b.add_output<decl::Geometry>(N_("Mesh"));
-}
-
struct CuboidConfig {
float3 size;
int verts_x;
@@ -426,6 +414,35 @@ Mesh *create_cuboid_mesh(const float3 size,
return mesh;
}
+} // namespace blender::nodes
+
+namespace blender::nodes::node_geo_mesh_primitive_cube_cc {
+
+static void node_declare(NodeDeclarationBuilder &b)
+{
+ b.add_input<decl::Vector>(N_("Size"))
+ .default_value(float3(1))
+ .min(0.0f)
+ .subtype(PROP_TRANSLATION)
+ .description(N_("Side length along each axis"));
+ b.add_input<decl::Int>(N_("Vertices X"))
+ .default_value(2)
+ .min(2)
+ .max(1000)
+ .description(N_("Number of vertices for the X side of the shape"));
+ b.add_input<decl::Int>(N_("Vertices Y"))
+ .default_value(2)
+ .min(2)
+ .max(1000)
+ .description(N_("Number of vertices for the Y side of the shape"));
+ b.add_input<decl::Int>(N_("Vertices Z"))
+ .default_value(2)
+ .min(2)
+ .max(1000)
+ .description(N_("Number of vertices for the Z side of the shape"));
+ b.add_output<decl::Geometry>(N_("Mesh"));
+}
+
static Mesh *create_cube_mesh(const float3 size,
const int verts_x,
const int verts_y,
@@ -471,7 +488,7 @@ static Mesh *create_cube_mesh(const float3 size,
return create_cuboid_mesh(size, verts_x, verts_y, verts_z);
}
-static void geo_node_mesh_primitive_cube_exec(GeoNodeExecParams params)
+static void node_geo_exec(GeoNodeExecParams params)
{
const float3 size = params.extract_input<float3>("Size");
const int verts_x = params.extract_input<int>("Vertices X");
@@ -488,14 +505,16 @@ static void geo_node_mesh_primitive_cube_exec(GeoNodeExecParams params)
params.set_output("Mesh", GeometrySet::create_with_mesh(mesh));
}
-} // namespace blender::nodes
+} // namespace blender::nodes::node_geo_mesh_primitive_cube_cc
void register_node_type_geo_mesh_primitive_cube()
{
+ namespace file_ns = blender::nodes::node_geo_mesh_primitive_cube_cc;
+
static bNodeType ntype;
geo_node_type_base(&ntype, GEO_NODE_MESH_PRIMITIVE_CUBE, "Cube", NODE_CLASS_GEOMETRY, 0);
- ntype.declare = blender::nodes::geo_node_mesh_primitive_cube_declare;
- ntype.geometry_node_execute = blender::nodes::geo_node_mesh_primitive_cube_exec;
+ ntype.declare = file_ns::node_declare;
+ ntype.geometry_node_execute = file_ns::node_geo_exec;
nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_cylinder.cc b/source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_cylinder.cc
index 3bcf42b40b1..f5ef277de03 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_cylinder.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_cylinder.cc
@@ -25,25 +25,25 @@
#include "node_geometry_util.hh"
-namespace blender::nodes {
+namespace blender::nodes::node_geo_mesh_primitive_cylinder_cc {
-static void geo_node_mesh_primitive_cylinder_declare(NodeDeclarationBuilder &b)
+static void node_declare(NodeDeclarationBuilder &b)
{
b.add_input<decl::Int>(N_("Vertices"))
.default_value(32)
.min(3)
.max(512)
- .description(N_("The number of vertices around the circumference"));
+ .description(N_("The number of vertices on the top and bottom circles"));
b.add_input<decl::Int>(N_("Side Segments"))
.default_value(1)
.min(1)
.max(512)
- .description(N_("The number of segments along the side"));
+ .description(N_("The number of rectangular segments along each side"));
b.add_input<decl::Int>(N_("Fill Segments"))
.default_value(1)
.min(1)
.max(512)
- .description(N_("The number of concentric segments of the fill"));
+ .description(N_("The number of concentric rings used to fill the round faces"));
b.add_input<decl::Float>(N_("Radius"))
.default_value(1.0f)
.min(0.0f)
@@ -53,20 +53,21 @@ static void geo_node_mesh_primitive_cylinder_declare(NodeDeclarationBuilder &b)
.default_value(2.0f)
.min(0.0f)
.subtype(PROP_DISTANCE)
- .description(N_("The height of the cylinder on the Z axis"));
+ .description(N_("The height of the cylinder"));
b.add_output<decl::Geometry>(N_("Mesh"));
+ b.add_output<decl::Bool>(N_("Top")).field_source();
+ b.add_output<decl::Bool>(N_("Side")).field_source();
+ b.add_output<decl::Bool>(N_("Bottom")).field_source();
}
-static void geo_node_mesh_primitive_cylinder_layout(uiLayout *layout,
- bContext *UNUSED(C),
- PointerRNA *ptr)
+static void node_layout(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
{
uiLayoutSetPropSep(layout, true);
uiLayoutSetPropDecorate(layout, false);
uiItemR(layout, ptr, "fill_type", 0, nullptr, ICON_NONE);
}
-static void geo_node_mesh_primitive_cylinder_init(bNodeTree *UNUSED(ntree), bNode *node)
+static void node_init(bNodeTree *UNUSED(ntree), bNode *node)
{
NodeGeometryMeshCylinder *node_storage = (NodeGeometryMeshCylinder *)MEM_callocN(
sizeof(NodeGeometryMeshCylinder), __func__);
@@ -76,7 +77,7 @@ static void geo_node_mesh_primitive_cylinder_init(bNodeTree *UNUSED(ntree), bNod
node->storage = node_storage;
}
-static void geo_node_mesh_primitive_cylinder_update(bNodeTree *UNUSED(ntree), bNode *node)
+static void node_update(bNodeTree *ntree, bNode *node)
{
bNodeSocket *vertices_socket = (bNodeSocket *)node->inputs.first;
bNodeSocket *rings_socket = vertices_socket->next;
@@ -86,10 +87,10 @@ static void geo_node_mesh_primitive_cylinder_update(bNodeTree *UNUSED(ntree), bN
const GeometryNodeMeshCircleFillType fill_type =
static_cast<const GeometryNodeMeshCircleFillType>(storage.fill_type);
const bool has_fill = fill_type != GEO_NODE_MESH_CIRCLE_FILL_NONE;
- nodeSetSocketAvailability(fill_subdiv_socket, has_fill);
+ nodeSetSocketAvailability(ntree, fill_subdiv_socket, has_fill);
}
-static void geo_node_mesh_primitive_cylinder_exec(GeoNodeExecParams params)
+static void node_geo_exec(GeoNodeExecParams params)
{
const bNode &node = params.node();
const NodeGeometryMeshCylinder &storage = *(const NodeGeometryMeshCylinder *)node.storage;
@@ -97,49 +98,89 @@ static void geo_node_mesh_primitive_cylinder_exec(GeoNodeExecParams params)
const GeometryNodeMeshCircleFillType fill_type = (const GeometryNodeMeshCircleFillType)
storage.fill_type;
+ auto return_default = [&]() {
+ params.set_output("Top", fn::make_constant_field<bool>(false));
+ params.set_output("Bottom", fn::make_constant_field<bool>(false));
+ params.set_output("Side", fn::make_constant_field<bool>(false));
+ params.set_output("Mesh", GeometrySet());
+ };
+
const float radius = params.extract_input<float>("Radius");
const float depth = params.extract_input<float>("Depth");
const int circle_segments = params.extract_input<int>("Vertices");
if (circle_segments < 3) {
params.error_message_add(NodeWarningType::Info, TIP_("Vertices must be at least 3"));
- params.set_output("Mesh", GeometrySet());
- return;
+ return return_default();
}
const int side_segments = params.extract_input<int>("Side Segments");
if (side_segments < 1) {
params.error_message_add(NodeWarningType::Info, TIP_("Side Segments must be at least 1"));
- params.set_output("Mesh", GeometrySet());
- return;
+ return return_default();
}
const bool no_fill = fill_type == GEO_NODE_MESH_CIRCLE_FILL_NONE;
const int fill_segments = no_fill ? 1 : params.extract_input<int>("Fill Segments");
if (fill_segments < 1) {
params.error_message_add(NodeWarningType::Info, TIP_("Fill Segments must be at least 1"));
- params.set_output("Mesh", GeometrySet());
- return;
+ return return_default();
+ }
+
+ ConeAttributeOutputs attribute_outputs;
+ if (params.output_is_required("Top")) {
+ attribute_outputs.top_id = StrongAnonymousAttributeID("top_selection");
+ }
+ if (params.output_is_required("Bottom")) {
+ attribute_outputs.bottom_id = StrongAnonymousAttributeID("bottom_selection");
+ }
+ if (params.output_is_required("Side")) {
+ attribute_outputs.side_id = StrongAnonymousAttributeID("side_selection");
}
/* The cylinder is a special case of the cone mesh where the top and bottom radius are equal. */
- Mesh *mesh = create_cylinder_or_cone_mesh(
- radius, radius, depth, circle_segments, side_segments, fill_segments, fill_type);
+ Mesh *mesh = create_cylinder_or_cone_mesh(radius,
+ radius,
+ depth,
+ circle_segments,
+ side_segments,
+ fill_segments,
+ fill_type,
+ attribute_outputs);
+
+ if (attribute_outputs.top_id) {
+ params.set_output("Top",
+ AnonymousAttributeFieldInput::Create<bool>(
+ std::move(attribute_outputs.top_id), params.attribute_producer_name()));
+ }
+ if (attribute_outputs.bottom_id) {
+ params.set_output(
+ "Bottom",
+ AnonymousAttributeFieldInput::Create<bool>(std::move(attribute_outputs.bottom_id),
+ params.attribute_producer_name()));
+ }
+ if (attribute_outputs.side_id) {
+ params.set_output("Side",
+ AnonymousAttributeFieldInput::Create<bool>(
+ std::move(attribute_outputs.side_id), params.attribute_producer_name()));
+ }
params.set_output("Mesh", GeometrySet::create_with_mesh(mesh));
}
-} // namespace blender::nodes
+} // namespace blender::nodes::node_geo_mesh_primitive_cylinder_cc
void register_node_type_geo_mesh_primitive_cylinder()
{
+ namespace file_ns = blender::nodes::node_geo_mesh_primitive_cylinder_cc;
+
static bNodeType ntype;
geo_node_type_base(&ntype, GEO_NODE_MESH_PRIMITIVE_CYLINDER, "Cylinder", NODE_CLASS_GEOMETRY, 0);
- node_type_init(&ntype, blender::nodes::geo_node_mesh_primitive_cylinder_init);
- node_type_update(&ntype, blender::nodes::geo_node_mesh_primitive_cylinder_update);
+ node_type_init(&ntype, file_ns::node_init);
+ node_type_update(&ntype, file_ns::node_update);
node_type_storage(
&ntype, "NodeGeometryMeshCylinder", node_free_standard_storage, node_copy_standard_storage);
- ntype.declare = blender::nodes::geo_node_mesh_primitive_cylinder_declare;
- ntype.geometry_node_execute = blender::nodes::geo_node_mesh_primitive_cylinder_exec;
- ntype.draw_buttons = blender::nodes::geo_node_mesh_primitive_cylinder_layout;
+ ntype.declare = file_ns::node_declare;
+ ntype.geometry_node_execute = file_ns::node_geo_exec;
+ ntype.draw_buttons = file_ns::node_layout;
nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_grid.cc b/source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_grid.cc
index c4e476981c1..c761380645d 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_grid.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_grid.cc
@@ -27,15 +27,6 @@
namespace blender::nodes {
-static void geo_node_mesh_primitive_grid_declare(NodeDeclarationBuilder &b)
-{
- b.add_input<decl::Float>(N_("Size X")).default_value(1.0f).min(0.0f).subtype(PROP_DISTANCE);
- b.add_input<decl::Float>(N_("Size Y")).default_value(1.0f).min(0.0f).subtype(PROP_DISTANCE);
- b.add_input<decl::Int>(N_("Vertices X")).default_value(3).min(2).max(1000);
- b.add_input<decl::Int>(N_("Vertices Y")).default_value(3).min(2).max(1000);
- b.add_output<decl::Geometry>(N_("Mesh"));
-}
-
static void calculate_uvs(
Mesh *mesh, Span<MVert> verts, Span<MLoop> loops, const float size_x, const float size_y)
{
@@ -153,7 +144,36 @@ Mesh *create_grid_mesh(const int verts_x,
return mesh;
}
-static void geo_node_mesh_primitive_grid_exec(GeoNodeExecParams params)
+} // namespace blender::nodes
+
+namespace blender::nodes::node_geo_mesh_primitive_grid_cc {
+
+static void node_declare(NodeDeclarationBuilder &b)
+{
+ b.add_input<decl::Float>(N_("Size X"))
+ .default_value(1.0f)
+ .min(0.0f)
+ .subtype(PROP_DISTANCE)
+ .description(N_("Side length of the plane in the X direction"));
+ b.add_input<decl::Float>(N_("Size Y"))
+ .default_value(1.0f)
+ .min(0.0f)
+ .subtype(PROP_DISTANCE)
+ .description(N_("Side length of the plane in the Y direction"));
+ b.add_input<decl::Int>(N_("Vertices X"))
+ .default_value(3)
+ .min(2)
+ .max(1000)
+ .description(N_("Number of vertices in the X direction"));
+ b.add_input<decl::Int>(N_("Vertices Y"))
+ .default_value(3)
+ .min(2)
+ .max(1000)
+ .description(N_("Number of vertices in the Y direction"));
+ b.add_output<decl::Geometry>(N_("Mesh"));
+}
+
+static void node_geo_exec(GeoNodeExecParams params)
{
const float size_x = params.extract_input<float>("Size X");
const float size_y = params.extract_input<float>("Size Y");
@@ -171,14 +191,16 @@ static void geo_node_mesh_primitive_grid_exec(GeoNodeExecParams params)
params.set_output("Mesh", GeometrySet::create_with_mesh(mesh));
}
-} // namespace blender::nodes
+} // namespace blender::nodes::node_geo_mesh_primitive_grid_cc
void register_node_type_geo_mesh_primitive_grid()
{
+ namespace file_ns = blender::nodes::node_geo_mesh_primitive_grid_cc;
+
static bNodeType ntype;
geo_node_type_base(&ntype, GEO_NODE_MESH_PRIMITIVE_GRID, "Grid", NODE_CLASS_GEOMETRY, 0);
- ntype.declare = blender::nodes::geo_node_mesh_primitive_grid_declare;
- ntype.geometry_node_execute = blender::nodes::geo_node_mesh_primitive_grid_exec;
+ ntype.declare = file_ns::node_declare;
+ ntype.geometry_node_execute = file_ns::node_geo_exec;
nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_ico_sphere.cc b/source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_ico_sphere.cc
index da3dfef3aea..5f483a95063 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_ico_sphere.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_ico_sphere.cc
@@ -24,12 +24,20 @@
#include "node_geometry_util.hh"
-namespace blender::nodes {
+namespace blender::nodes::node_geo_mesh_primitive_ico_sphere_cc {
-static void geo_node_mesh_primitive_ico_sphere_declare(NodeDeclarationBuilder &b)
+static void node_declare(NodeDeclarationBuilder &b)
{
- b.add_input<decl::Float>(N_("Radius")).default_value(1.0f).min(0.0f).subtype(PROP_DISTANCE);
- b.add_input<decl::Int>(N_("Subdivisions")).default_value(1).min(1).max(7);
+ b.add_input<decl::Float>(N_("Radius"))
+ .default_value(1.0f)
+ .min(0.0f)
+ .subtype(PROP_DISTANCE)
+ .description(N_("Distance from the generated points to the origin"));
+ b.add_input<decl::Int>(N_("Subdivisions"))
+ .default_value(1)
+ .min(1)
+ .max(7)
+ .description(N_("Number of subdivisions on top of the basic icosahedron"));
b.add_output<decl::Geometry>(N_("Mesh"));
}
@@ -37,9 +45,10 @@ static Mesh *create_ico_sphere_mesh(const int subdivisions, const float radius)
{
const float4x4 transform = float4x4::identity();
- const BMeshCreateParams bmcp = {true};
+ BMeshCreateParams bmesh_create_params{};
+ bmesh_create_params.use_toolflags = true;
const BMAllocTemplate allocsize = {0, 0, 0, 0};
- BMesh *bm = BM_mesh_create(&allocsize, &bmcp);
+ BMesh *bm = BM_mesh_create(&allocsize, &bmesh_create_params);
BM_data_layer_add_named(bm, &bm->ldata, CD_MLOOPUV, nullptr);
BMO_op_callf(bm,
@@ -60,7 +69,7 @@ static Mesh *create_ico_sphere_mesh(const int subdivisions, const float radius)
return mesh;
}
-static void geo_node_mesh_primitive_ico_sphere_exec(GeoNodeExecParams params)
+static void node_geo_exec(GeoNodeExecParams params)
{
const int subdivisions = std::min(params.extract_input<int>("Subdivisions"), 10);
const float radius = params.extract_input<float>("Radius");
@@ -69,15 +78,17 @@ static void geo_node_mesh_primitive_ico_sphere_exec(GeoNodeExecParams params)
params.set_output("Mesh", GeometrySet::create_with_mesh(mesh));
}
-} // namespace blender::nodes
+} // namespace blender::nodes::node_geo_mesh_primitive_ico_sphere_cc
void register_node_type_geo_mesh_primitive_ico_sphere()
{
+ namespace file_ns = blender::nodes::node_geo_mesh_primitive_ico_sphere_cc;
+
static bNodeType ntype;
geo_node_type_base(
&ntype, GEO_NODE_MESH_PRIMITIVE_ICO_SPHERE, "Ico Sphere", NODE_CLASS_GEOMETRY, 0);
- ntype.declare = blender::nodes::geo_node_mesh_primitive_ico_sphere_declare;
- ntype.geometry_node_execute = blender::nodes::geo_node_mesh_primitive_ico_sphere_exec;
+ ntype.declare = file_ns::node_declare;
+ ntype.geometry_node_execute = file_ns::node_geo_exec;
nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_line.cc b/source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_line.cc
index 6515afe5966..cda55eadaf6 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_line.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_line.cc
@@ -25,22 +25,33 @@
#include "node_geometry_util.hh"
-namespace blender::nodes {
+namespace blender::nodes::node_geo_mesh_primitive_line_cc {
-static void geo_node_mesh_primitive_line_declare(NodeDeclarationBuilder &b)
+static void node_declare(NodeDeclarationBuilder &b)
{
- b.add_input<decl::Int>(N_("Count")).default_value(10).min(1).max(10000);
- b.add_input<decl::Float>(N_("Resolution")).default_value(1.0f).min(0.1f).subtype(PROP_DISTANCE);
- b.add_input<decl::Vector>(N_("Start Location")).subtype(PROP_TRANSLATION);
+ b.add_input<decl::Int>(N_("Count"))
+ .default_value(10)
+ .min(1)
+ .max(10000)
+ .description(N_("Number of vertices on the line"));
+ b.add_input<decl::Float>(N_("Resolution"))
+ .default_value(1.0f)
+ .min(0.1f)
+ .subtype(PROP_DISTANCE)
+ .description(N_("Length of each individual edge"));
+ b.add_input<decl::Vector>(N_("Start Location"))
+ .subtype(PROP_TRANSLATION)
+ .description(N_("Position of the first vertex"));
b.add_input<decl::Vector>(N_("Offset"))
.default_value({0.0f, 0.0f, 1.0f})
- .subtype(PROP_TRANSLATION);
+ .subtype(PROP_TRANSLATION)
+ .description(N_(
+ "In offset mode, the distance between each socket on each axis. In end points mode, the "
+ "position of the final vertex"));
b.add_output<decl::Geometry>(N_("Mesh"));
}
-static void geo_node_mesh_primitive_line_layout(uiLayout *layout,
- bContext *UNUSED(C),
- PointerRNA *ptr)
+static void node_layout(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
{
uiLayoutSetPropSep(layout, true);
uiLayoutSetPropDecorate(layout, false);
@@ -50,7 +61,7 @@ static void geo_node_mesh_primitive_line_layout(uiLayout *layout,
}
}
-static void geo_node_mesh_primitive_line_init(bNodeTree *UNUSED(ntree), bNode *node)
+static void node_init(bNodeTree *UNUSED(ntree), bNode *node)
{
NodeGeometryMeshLine *node_storage = (NodeGeometryMeshLine *)MEM_callocN(
sizeof(NodeGeometryMeshLine), __func__);
@@ -61,7 +72,7 @@ static void geo_node_mesh_primitive_line_init(bNodeTree *UNUSED(ntree), bNode *n
node->storage = node_storage;
}
-static void geo_node_mesh_primitive_line_update(bNodeTree *UNUSED(tree), bNode *node)
+static void node_update(bNodeTree *ntree, bNode *node)
{
bNodeSocket *count_socket = (bNodeSocket *)node->inputs.first;
bNodeSocket *resolution_socket = count_socket->next;
@@ -77,48 +88,17 @@ static void geo_node_mesh_primitive_line_update(bNodeTree *UNUSED(tree), bNode *
(mode == GEO_NODE_MESH_LINE_MODE_END_POINTS) ? N_("End Location") :
N_("Offset"));
- nodeSetSocketAvailability(resolution_socket,
+ nodeSetSocketAvailability(ntree,
+ resolution_socket,
mode == GEO_NODE_MESH_LINE_MODE_END_POINTS &&
count_mode == GEO_NODE_MESH_LINE_COUNT_RESOLUTION);
- nodeSetSocketAvailability(count_socket,
+ nodeSetSocketAvailability(ntree,
+ count_socket,
mode == GEO_NODE_MESH_LINE_MODE_OFFSET ||
count_mode == GEO_NODE_MESH_LINE_COUNT_TOTAL);
}
-static void fill_edge_data(MutableSpan<MEdge> edges)
-{
- for (const int i : edges.index_range()) {
- edges[i].v1 = i;
- edges[i].v2 = i + 1;
- edges[i].flag |= ME_LOOSEEDGE;
- }
-}
-
-Mesh *create_line_mesh(const float3 start, const float3 delta, const int count)
-{
- if (count < 1) {
- return nullptr;
- }
-
- Mesh *mesh = BKE_mesh_new_nomain(count, count - 1, 0, 0, 0);
- BKE_id_material_eval_ensure_default_slot(&mesh->id);
- MutableSpan<MVert> verts{mesh->mvert, mesh->totvert};
- MutableSpan<MEdge> edges{mesh->medge, mesh->totedge};
-
- short normal[3];
- normal_float_to_short_v3(normal, delta.normalized());
-
- for (const int i : verts.index_range()) {
- copy_v3_v3(verts[i].co, start + delta * i);
- copy_v3_v3_short(verts[i].no, normal);
- }
-
- fill_edge_data(edges);
-
- return mesh;
-}
-
-static void geo_node_mesh_primitive_line_exec(GeoNodeExecParams params)
+static void node_geo_exec(GeoNodeExecParams params)
{
const NodeGeometryMeshLine &storage = *(const NodeGeometryMeshLine *)params.node().storage;
const GeometryNodeMeshLineMode mode = (const GeometryNodeMeshLineMode)storage.mode;
@@ -159,19 +139,58 @@ static void geo_node_mesh_primitive_line_exec(GeoNodeExecParams params)
params.set_output("Mesh", GeometrySet::create_with_mesh(mesh));
}
+} // namespace blender::nodes::node_geo_mesh_primitive_line_cc
+
+namespace blender::nodes {
+
+static void fill_edge_data(MutableSpan<MEdge> edges)
+{
+ for (const int i : edges.index_range()) {
+ edges[i].v1 = i;
+ edges[i].v2 = i + 1;
+ edges[i].flag |= ME_LOOSEEDGE;
+ }
+}
+
+Mesh *create_line_mesh(const float3 start, const float3 delta, const int count)
+{
+ if (count < 1) {
+ return nullptr;
+ }
+
+ Mesh *mesh = BKE_mesh_new_nomain(count, count - 1, 0, 0, 0);
+ BKE_id_material_eval_ensure_default_slot(&mesh->id);
+ MutableSpan<MVert> verts{mesh->mvert, mesh->totvert};
+ MutableSpan<MEdge> edges{mesh->medge, mesh->totedge};
+
+ short normal[3];
+ normal_float_to_short_v3(normal, delta.normalized());
+
+ for (const int i : verts.index_range()) {
+ copy_v3_v3(verts[i].co, start + delta * i);
+ copy_v3_v3_short(verts[i].no, normal);
+ }
+
+ fill_edge_data(edges);
+
+ return mesh;
+}
+
} // namespace blender::nodes
void register_node_type_geo_mesh_primitive_line()
{
+ namespace file_ns = blender::nodes::node_geo_mesh_primitive_line_cc;
+
static bNodeType ntype;
geo_node_type_base(&ntype, GEO_NODE_MESH_PRIMITIVE_LINE, "Mesh Line", NODE_CLASS_GEOMETRY, 0);
- ntype.declare = blender::nodes::geo_node_mesh_primitive_line_declare;
- node_type_init(&ntype, blender::nodes::geo_node_mesh_primitive_line_init);
- node_type_update(&ntype, blender::nodes::geo_node_mesh_primitive_line_update);
+ ntype.declare = file_ns::node_declare;
+ node_type_init(&ntype, file_ns::node_init);
+ node_type_update(&ntype, file_ns::node_update);
node_type_storage(
&ntype, "NodeGeometryMeshLine", node_free_standard_storage, node_copy_standard_storage);
- ntype.geometry_node_execute = blender::nodes::geo_node_mesh_primitive_line_exec;
- ntype.draw_buttons = blender::nodes::geo_node_mesh_primitive_line_layout;
+ ntype.geometry_node_execute = file_ns::node_geo_exec;
+ ntype.draw_buttons = file_ns::node_layout;
nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_uv_sphere.cc b/source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_uv_sphere.cc
index 54a762fc15d..c109596c1c6 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_uv_sphere.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_uv_sphere.cc
@@ -25,13 +25,25 @@
#include "node_geometry_util.hh"
-namespace blender::nodes {
+namespace blender::nodes::node_geo_mesh_primitive_uv_sphere_cc {
-static void geo_node_mesh_primitive_uv_shpere_declare(NodeDeclarationBuilder &b)
+static void node_declare(NodeDeclarationBuilder &b)
{
- b.add_input<decl::Int>(N_("Segments")).default_value(32).min(3).max(1024);
- b.add_input<decl::Int>(N_("Rings")).default_value(16).min(2).max(1024);
- b.add_input<decl::Float>(N_("Radius")).default_value(1.0f).min(0.0f).subtype(PROP_DISTANCE);
+ b.add_input<decl::Int>(N_("Segments"))
+ .default_value(32)
+ .min(3)
+ .max(1024)
+ .description(N_("Horizontal resolution of the sphere"));
+ b.add_input<decl::Int>(N_("Rings"))
+ .default_value(16)
+ .min(2)
+ .max(1024)
+ .description(N_("The number of horizontal rings"));
+ b.add_input<decl::Float>(N_("Radius"))
+ .default_value(1.0f)
+ .min(0.0f)
+ .subtype(PROP_DISTANCE)
+ .description(N_("Distance from the generated points to the origin"));
b.add_output<decl::Geometry>(N_("Mesh"));
}
@@ -280,7 +292,7 @@ static Mesh *create_uv_sphere_mesh(const float radius, const int segments, const
return mesh;
}
-static void geo_node_mesh_primitive_uv_sphere_exec(GeoNodeExecParams params)
+static void node_geo_exec(GeoNodeExecParams params)
{
const int segments_num = params.extract_input<int>("Segments");
const int rings_num = params.extract_input<int>("Rings");
@@ -301,15 +313,17 @@ static void geo_node_mesh_primitive_uv_sphere_exec(GeoNodeExecParams params)
params.set_output("Mesh", GeometrySet::create_with_mesh(mesh));
}
-} // namespace blender::nodes
+} // namespace blender::nodes::node_geo_mesh_primitive_uv_sphere_cc
void register_node_type_geo_mesh_primitive_uv_sphere()
{
+ namespace file_ns = blender::nodes::node_geo_mesh_primitive_uv_sphere_cc;
+
static bNodeType ntype;
geo_node_type_base(
&ntype, GEO_NODE_MESH_PRIMITIVE_UV_SPHERE, "UV Sphere", NODE_CLASS_GEOMETRY, 0);
- ntype.declare = blender::nodes::geo_node_mesh_primitive_uv_shpere_declare;
- ntype.geometry_node_execute = blender::nodes::geo_node_mesh_primitive_uv_sphere_exec;
+ ntype.declare = file_ns::node_declare;
+ ntype.geometry_node_execute = file_ns::node_geo_exec;
nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/geometry/nodes/node_geo_mesh_subdivide.cc b/source/blender/nodes/geometry/nodes/node_geo_mesh_subdivide.cc
index d99c0c851a8..6206b51b6a8 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_mesh_subdivide.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_mesh_subdivide.cc
@@ -23,9 +23,9 @@
#include "node_geometry_util.hh"
-namespace blender::nodes {
+namespace blender::nodes::node_geo_mesh_subdivide_cc {
-static void geo_node_mesh_subdivide_declare(NodeDeclarationBuilder &b)
+static void node_declare(NodeDeclarationBuilder &b)
{
b.add_input<decl::Geometry>(N_("Mesh")).supported_type(GEO_COMPONENT_TYPE_MESH);
b.add_input<decl::Int>(N_("Level")).default_value(1).min(0).max(6);
@@ -72,7 +72,7 @@ static void geometry_set_mesh_subdivide(GeometrySet &geometry_set, const int lev
BKE_subdiv_free(subdiv);
}
-static void geo_node_mesh_subdivide_exec(GeoNodeExecParams params)
+static void node_geo_exec(GeoNodeExecParams params)
{
GeometrySet geometry_set = params.extract_input<GeometrySet>("Mesh");
@@ -97,14 +97,16 @@ static void geo_node_mesh_subdivide_exec(GeoNodeExecParams params)
params.set_output("Mesh", std::move(geometry_set));
}
-} // namespace blender::nodes
+} // namespace blender::nodes::node_geo_mesh_subdivide_cc
void register_node_type_geo_mesh_subdivide()
{
+ namespace file_ns = blender::nodes::node_geo_mesh_subdivide_cc;
+
static bNodeType ntype;
geo_node_type_base(&ntype, GEO_NODE_SUBDIVIDE_MESH, "Subdivide Mesh", NODE_CLASS_GEOMETRY, 0);
- ntype.declare = blender::nodes::geo_node_mesh_subdivide_declare;
- ntype.geometry_node_execute = blender::nodes::geo_node_mesh_subdivide_exec;
+ ntype.declare = file_ns::node_declare;
+ ntype.geometry_node_execute = file_ns::node_geo_exec;
nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/geometry/nodes/node_geo_mesh_to_curve.cc b/source/blender/nodes/geometry/nodes/node_geo_mesh_to_curve.cc
index 11865c635b8..90f0af75788 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_mesh_to_curve.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_mesh_to_curve.cc
@@ -18,16 +18,16 @@
#include "node_geometry_util.hh"
-namespace blender::nodes {
+namespace blender::nodes::node_geo_mesh_to_curve_cc {
-static void geo_node_legacy_mesh_to_curve_declare(NodeDeclarationBuilder &b)
+static void node_declare(NodeDeclarationBuilder &b)
{
b.add_input<decl::Geometry>(N_("Mesh")).supported_type(GEO_COMPONENT_TYPE_MESH);
b.add_input<decl::Bool>(N_("Selection")).default_value(true).hide_value().supports_field();
b.add_output<decl::Geometry>(N_("Curve"));
}
-static void geo_node_legacy_mesh_to_curve_exec(GeoNodeExecParams params)
+static void node_geo_exec(GeoNodeExecParams params)
{
GeometrySet geometry_set = params.extract_input<GeometrySet>("Mesh");
@@ -56,14 +56,16 @@ static void geo_node_legacy_mesh_to_curve_exec(GeoNodeExecParams params)
params.set_output("Curve", std::move(geometry_set));
}
-} // namespace blender::nodes
+} // namespace blender::nodes::node_geo_mesh_to_curve_cc
void register_node_type_geo_mesh_to_curve()
{
+ namespace file_ns = blender::nodes::node_geo_mesh_to_curve_cc;
+
static bNodeType ntype;
geo_node_type_base(&ntype, GEO_NODE_MESH_TO_CURVE, "Mesh to Curve", NODE_CLASS_GEOMETRY, 0);
- ntype.declare = blender::nodes::geo_node_legacy_mesh_to_curve_declare;
- ntype.geometry_node_execute = blender::nodes::geo_node_legacy_mesh_to_curve_exec;
+ ntype.declare = file_ns::node_declare;
+ ntype.geometry_node_execute = file_ns::node_geo_exec;
nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/geometry/nodes/node_geo_mesh_to_points.cc b/source/blender/nodes/geometry/nodes/node_geo_mesh_to_points.cc
index 92911e89f59..d3c4aa87547 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_mesh_to_points.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_mesh_to_points.cc
@@ -26,9 +26,9 @@
using blender::Array;
-namespace blender::nodes {
+namespace blender::nodes::node_geo_mesh_to_points_cc {
-static void geo_node_mesh_to_points_declare(NodeDeclarationBuilder &b)
+static void node_declare(NodeDeclarationBuilder &b)
{
b.add_input<decl::Geometry>(N_("Mesh")).supported_type(GEO_COMPONENT_TYPE_MESH);
b.add_input<decl::Bool>(N_("Selection")).default_value(true).supports_field().hide_value();
@@ -41,12 +41,12 @@ static void geo_node_mesh_to_points_declare(NodeDeclarationBuilder &b)
b.add_output<decl::Geometry>(N_("Points"));
}
-static void geo_node_mesh_to_points_layout(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
+static void node_layout(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
{
uiItemR(layout, ptr, "mode", 0, "", ICON_NONE);
}
-static void geo_node_mesh_to_points_init(bNodeTree *UNUSED(tree), bNode *node)
+static void node_init(bNodeTree *UNUSED(tree), bNode *node)
{
NodeGeometryMeshToPoints *data = (NodeGeometryMeshToPoints *)MEM_callocN(
sizeof(NodeGeometryMeshToPoints), __func__);
@@ -113,14 +113,14 @@ static void geometry_set_mesh_to_points(GeometrySet &geometry_set,
for (Map<AttributeIDRef, AttributeKind>::Item entry : attributes.items()) {
const AttributeIDRef attribute_id = entry.key;
const CustomDataType data_type = entry.value.data_type;
- GVArrayPtr src = mesh_component->attribute_get_for_read(attribute_id, domain, data_type);
+ GVArray src = mesh_component->attribute_get_for_read(attribute_id, domain, data_type);
OutputAttribute dst = point_component.attribute_try_get_for_output_only(
attribute_id, ATTR_DOMAIN_POINT, data_type);
if (dst && src) {
attribute_math::convert_to_static_type(data_type, [&](auto dummy) {
using T = decltype(dummy);
- GVArray_Typed<T> src_typed{*src};
- copy_attribute_to_points(*src_typed, selection, dst.as_span().typed<T>());
+ VArray<T> src_typed = src.typed<T>();
+ copy_attribute_to_points(src_typed, selection, dst.as_span().typed<T>());
});
dst.save();
}
@@ -129,7 +129,7 @@ static void geometry_set_mesh_to_points(GeometrySet &geometry_set,
geometry_set.keep_only({GEO_COMPONENT_TYPE_POINT_CLOUD, GEO_COMPONENT_TYPE_INSTANCES});
}
-static void geo_node_mesh_to_points_exec(GeoNodeExecParams params)
+static void node_geo_exec(GeoNodeExecParams params)
{
GeometrySet geometry_set = params.extract_input<GeometrySet>("Mesh");
Field<float3> position = params.extract_input<Field<float3>>("Position");
@@ -172,17 +172,19 @@ static void geo_node_mesh_to_points_exec(GeoNodeExecParams params)
params.set_output("Points", std::move(geometry_set));
}
-} // namespace blender::nodes
+} // namespace blender::nodes::node_geo_mesh_to_points_cc
void register_node_type_geo_mesh_to_points()
{
+ namespace file_ns = blender::nodes::node_geo_mesh_to_points_cc;
+
static bNodeType ntype;
geo_node_type_base(&ntype, GEO_NODE_MESH_TO_POINTS, "Mesh to Points", NODE_CLASS_GEOMETRY, 0);
- ntype.declare = blender::nodes::geo_node_mesh_to_points_declare;
- ntype.geometry_node_execute = blender::nodes::geo_node_mesh_to_points_exec;
- node_type_init(&ntype, blender::nodes::geo_node_mesh_to_points_init);
- ntype.draw_buttons = blender::nodes::geo_node_mesh_to_points_layout;
+ ntype.declare = file_ns::node_declare;
+ ntype.geometry_node_execute = file_ns::node_geo_exec;
+ node_type_init(&ntype, file_ns::node_init);
+ ntype.draw_buttons = file_ns::node_layout;
node_type_storage(
&ntype, "NodeGeometryMeshToPoints", node_free_standard_storage, node_copy_standard_storage);
nodeRegisterType(&ntype);
diff --git a/source/blender/nodes/geometry/nodes/node_geo_object_info.cc b/source/blender/nodes/geometry/nodes/node_geo_object_info.cc
index 3ba32c4b674..ff71bf973b2 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_object_info.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_object_info.cc
@@ -21,83 +21,93 @@
#include "node_geometry_util.hh"
-namespace blender::nodes {
+namespace blender::nodes::node_geo_object_info_cc {
-static void geo_node_object_info_declare(NodeDeclarationBuilder &b)
+static void node_declare(NodeDeclarationBuilder &b)
{
b.add_input<decl::Object>(N_("Object")).hide_label();
b.add_input<decl::Bool>(N_("As Instance"))
- .description(
- N_("Output the entire object as single instance. "
- "This allows instancing non-geometry object types"));
+ .description(N_("Output the entire object as single instance. "
+ "This allows instancing non-geometry object types"));
b.add_output<decl::Vector>(N_("Location"));
b.add_output<decl::Vector>(N_("Rotation"));
b.add_output<decl::Vector>(N_("Scale"));
b.add_output<decl::Geometry>(N_("Geometry"));
}
-static void geo_node_object_info_layout(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
+static void node_layout(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
{
uiItemR(layout, ptr, "transform_space", UI_ITEM_R_EXPAND, nullptr, ICON_NONE);
}
-static void geo_node_object_info_exec(GeoNodeExecParams params)
+static void node_geo_exec(GeoNodeExecParams params)
{
const bNode &bnode = params.node();
NodeGeometryObjectInfo *node_storage = (NodeGeometryObjectInfo *)bnode.storage;
const bool transform_space_relative = (node_storage->transform_space ==
GEO_NODE_TRANSFORM_SPACE_RELATIVE);
- Object *object = params.get_input<Object *>("Object");
+ auto default_transform = [&]() {
+ params.set_output("Location", float3(0));
+ params.set_output("Rotation", float3(0));
+ params.set_output("Scale", float3(0));
+ };
+ auto default_geometry = [&]() { params.set_output("Geometry", GeometrySet()); };
- float3 location = {0, 0, 0};
- float3 rotation = {0, 0, 0};
- float3 scale = {0, 0, 0};
- GeometrySet geometry_set;
+ Object *object = params.get_input<Object *>("Object");
const Object *self_object = params.self_object();
+ if (object == nullptr) {
+ default_transform();
+ default_geometry();
+ return;
+ }
- if (object != nullptr) {
- const float4x4 transform = float4x4(self_object->imat) * float4x4(object->obmat);
+ const float4x4 &object_matrix = object->obmat;
+ const float4x4 transform = float4x4(self_object->imat) * object_matrix;
- float quaternion[4];
- if (transform_space_relative) {
- mat4_decompose(location, quaternion, scale, transform.values);
- }
- else {
- mat4_decompose(location, quaternion, scale, object->obmat);
+ if (transform_space_relative) {
+ params.set_output("Location", transform.translation());
+ params.set_output("Rotation", transform.to_euler());
+ params.set_output("Scale", transform.scale());
+ }
+ else {
+ params.set_output("Location", object_matrix.translation());
+ params.set_output("Rotation", object_matrix.to_euler());
+ params.set_output("Scale", object_matrix.scale());
+ }
+
+ if (params.output_is_required("Geometry")) {
+ if (object == self_object) {
+ params.error_message_add(NodeWarningType::Error,
+ TIP_("Geometry cannot be retrieved from the modifier object"));
+ default_geometry();
+ return;
}
- quat_to_eul(rotation, quaternion);
-
- if (object != self_object) {
- if (params.get_input<bool>("As Instance")) {
- InstancesComponent &instances = geometry_set.get_component_for_write<InstancesComponent>();
- const int handle = instances.add_reference(*object);
- if (transform_space_relative) {
- instances.add_instance(handle, transform);
- }
- else {
- float unit_transform[4][4];
- unit_m4(unit_transform);
- instances.add_instance(handle, unit_transform);
- }
+
+ GeometrySet geometry_set;
+ if (params.get_input<bool>("As Instance")) {
+ InstancesComponent &instances = geometry_set.get_component_for_write<InstancesComponent>();
+ const int handle = instances.add_reference(*object);
+ if (transform_space_relative) {
+ instances.add_instance(handle, transform);
}
else {
- geometry_set = bke::object_get_evaluated_geometry_set(*object);
- if (transform_space_relative) {
- transform_geometry_set(geometry_set, transform, *params.depsgraph());
- }
+ instances.add_instance(handle, float4x4::identity());
+ }
+ }
+ else {
+ geometry_set = bke::object_get_evaluated_geometry_set(*object);
+ if (transform_space_relative) {
+ transform_geometry_set(geometry_set, transform, *params.depsgraph());
}
}
- }
- params.set_output("Location", location);
- params.set_output("Rotation", rotation);
- params.set_output("Scale", scale);
- params.set_output("Geometry", geometry_set);
+ params.set_output("Geometry", geometry_set);
+ }
}
-static void geo_node_object_info_node_init(bNodeTree *UNUSED(tree), bNode *node)
+static void node_node_init(bNodeTree *UNUSED(tree), bNode *node)
{
NodeGeometryObjectInfo *data = (NodeGeometryObjectInfo *)MEM_callocN(
sizeof(NodeGeometryObjectInfo), __func__);
@@ -105,18 +115,20 @@ static void geo_node_object_info_node_init(bNodeTree *UNUSED(tree), bNode *node)
node->storage = data;
}
-} // namespace blender::nodes
+} // namespace blender::nodes::node_geo_object_info_cc
void register_node_type_geo_object_info()
{
+ namespace file_ns = blender::nodes::node_geo_object_info_cc;
+
static bNodeType ntype;
geo_node_type_base(&ntype, GEO_NODE_OBJECT_INFO, "Object Info", NODE_CLASS_INPUT, 0);
- node_type_init(&ntype, blender::nodes::geo_node_object_info_node_init);
+ node_type_init(&ntype, file_ns::node_node_init);
node_type_storage(
&ntype, "NodeGeometryObjectInfo", node_free_standard_storage, node_copy_standard_storage);
- ntype.geometry_node_execute = blender::nodes::geo_node_object_info_exec;
- ntype.draw_buttons = blender::nodes::geo_node_object_info_layout;
- ntype.declare = blender::nodes::geo_node_object_info_declare;
+ ntype.geometry_node_execute = file_ns::node_geo_exec;
+ ntype.draw_buttons = file_ns::node_layout;
+ ntype.declare = file_ns::node_declare;
nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/geometry/nodes/node_geo_points_to_vertices.cc b/source/blender/nodes/geometry/nodes/node_geo_points_to_vertices.cc
index 3e0096824d3..5510773eabd 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_points_to_vertices.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_points_to_vertices.cc
@@ -21,11 +21,11 @@
#include "node_geometry_util.hh"
-using blender::Array;
+namespace blender::nodes::node_geo_points_to_vertices_cc {
-namespace blender::nodes {
+using blender::Array;
-static void geo_node_points_to_vertices_declare(NodeDeclarationBuilder &b)
+static void node_declare(NodeDeclarationBuilder &b)
{
b.add_input<decl::Geometry>(N_("Points")).supported_type(GEO_COMPONENT_TYPE_POINT_CLOUD);
b.add_input<decl::Bool>(N_("Selection")).default_value(true).supports_field().hide_value();
@@ -74,15 +74,15 @@ static void geometry_set_points_to_vertices(GeometrySet &geometry_set,
for (Map<AttributeIDRef, AttributeKind>::Item entry : attributes.items()) {
const AttributeIDRef attribute_id = entry.key;
const CustomDataType data_type = entry.value.data_type;
- GVArrayPtr src = point_component->attribute_get_for_read(
+ GVArray src = point_component->attribute_get_for_read(
attribute_id, ATTR_DOMAIN_POINT, data_type);
OutputAttribute dst = mesh_component.attribute_try_get_for_output_only(
attribute_id, ATTR_DOMAIN_POINT, data_type);
if (dst && src) {
attribute_math::convert_to_static_type(data_type, [&](auto dummy) {
using T = decltype(dummy);
- GVArray_Typed<T> src_typed{*src};
- VArray_Span<T> src_typed_span{*src_typed};
+ VArray<T> src_typed = src.typed<T>();
+ VArray_Span<T> src_typed_span{src_typed};
copy_attribute_to_vertices(src_typed_span, selection, dst.as_span().typed<T>());
});
dst.save();
@@ -92,7 +92,7 @@ static void geometry_set_points_to_vertices(GeometrySet &geometry_set,
geometry_set.keep_only({GEO_COMPONENT_TYPE_MESH, GEO_COMPONENT_TYPE_INSTANCES});
}
-static void geo_node_points_to_vertices_exec(GeoNodeExecParams params)
+static void node_geo_exec(GeoNodeExecParams params)
{
GeometrySet geometry_set = params.extract_input<GeometrySet>("Points");
Field<bool> selection_field = params.extract_input<Field<bool>>("Selection");
@@ -104,15 +104,17 @@ static void geo_node_points_to_vertices_exec(GeoNodeExecParams params)
params.set_output("Mesh", std::move(geometry_set));
}
-} // namespace blender::nodes
+} // namespace blender::nodes::node_geo_points_to_vertices_cc
void register_node_type_geo_points_to_vertices()
{
+ namespace file_ns = blender::nodes::node_geo_points_to_vertices_cc;
+
static bNodeType ntype;
geo_node_type_base(
&ntype, GEO_NODE_POINTS_TO_VERTICES, "Points to Vertices", NODE_CLASS_GEOMETRY, 0);
- ntype.declare = blender::nodes::geo_node_points_to_vertices_declare;
- ntype.geometry_node_execute = blender::nodes::geo_node_points_to_vertices_exec;
+ ntype.declare = file_ns::node_declare;
+ ntype.geometry_node_execute = file_ns::node_geo_exec;
nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/geometry/nodes/node_geo_points_to_volume.cc b/source/blender/nodes/geometry/nodes/node_geo_points_to_volume.cc
index 312ea7df919..a064dca3a3f 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_points_to_volume.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_points_to_volume.cc
@@ -28,9 +28,9 @@
#include "UI_interface.h"
#include "UI_resources.h"
-namespace blender::nodes {
+namespace blender::nodes::node_geo_points_to_volume_cc {
-static void geo_node_points_to_volume_declare(NodeDeclarationBuilder &b)
+static void node_declare(NodeDeclarationBuilder &b)
{
b.add_input<decl::Geometry>(N_("Points"));
b.add_input<decl::Float>(N_("Density")).default_value(1.0f).min(0.0f);
@@ -44,16 +44,14 @@ static void geo_node_points_to_volume_declare(NodeDeclarationBuilder &b)
b.add_output<decl::Geometry>(N_("Volume"));
}
-static void geo_node_points_to_volume_layout(uiLayout *layout,
- bContext *UNUSED(C),
- PointerRNA *ptr)
+static void node_layout(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
{
uiLayoutSetPropSep(layout, true);
uiLayoutSetPropDecorate(layout, false);
uiItemR(layout, ptr, "resolution_mode", 0, IFACE_("Resolution"), ICON_NONE);
}
-static void geo_node_points_to_volume_init(bNodeTree *UNUSED(ntree), bNode *node)
+static void node_init(bNodeTree *UNUSED(ntree), bNode *node)
{
NodeGeometryPointsToVolume *data = (NodeGeometryPointsToVolume *)MEM_callocN(
sizeof(NodeGeometryPointsToVolume), __func__);
@@ -61,16 +59,19 @@ static void geo_node_points_to_volume_init(bNodeTree *UNUSED(ntree), bNode *node
node->storage = data;
}
-static void geo_node_points_to_volume_update(bNodeTree *UNUSED(ntree), bNode *node)
+static void node_update(bNodeTree *ntree, bNode *node)
{
NodeGeometryPointsToVolume *data = (NodeGeometryPointsToVolume *)node->storage;
bNodeSocket *voxel_size_socket = nodeFindSocket(node, SOCK_IN, "Voxel Size");
bNodeSocket *voxel_amount_socket = nodeFindSocket(node, SOCK_IN, "Voxel Amount");
- nodeSetSocketAvailability(voxel_amount_socket,
+ nodeSetSocketAvailability(ntree,
+ voxel_amount_socket,
data->resolution_mode ==
GEO_NODE_POINTS_TO_VOLUME_RESOLUTION_MODE_AMOUNT);
- nodeSetSocketAvailability(
- voxel_size_socket, data->resolution_mode == GEO_NODE_POINTS_TO_VOLUME_RESOLUTION_MODE_SIZE);
+ nodeSetSocketAvailability(ntree,
+ voxel_size_socket,
+ data->resolution_mode ==
+ GEO_NODE_POINTS_TO_VOLUME_RESOLUTION_MODE_SIZE);
}
#ifdef WITH_OPENVDB
@@ -165,7 +166,7 @@ static void gather_point_data_from_component(GeoNodeExecParams &params,
Vector<float3> &r_positions,
Vector<float> &r_radii)
{
- GVArray_Typed<float3> positions = component.attribute_get_for_read<float3>(
+ VArray<float3> positions = component.attribute_get_for_read<float3>(
"position", ATTR_DOMAIN_POINT, {0, 0, 0});
Field<float> radius_field = params.get_input<Field<float>>("Radius");
@@ -173,7 +174,7 @@ static void gather_point_data_from_component(GeoNodeExecParams &params,
const int domain_size = component.attribute_domain_size(ATTR_DOMAIN_POINT);
r_positions.resize(r_positions.size() + domain_size);
- positions->materialize(r_positions.as_mutable_span().take_back(domain_size));
+ positions.materialize(r_positions.as_mutable_span().take_back(domain_size));
r_radii.resize(r_radii.size() + domain_size);
fn::FieldEvaluator evaluator{field_context, domain_size};
@@ -222,22 +223,18 @@ static void initialize_volume_component_from_points(GeoNodeExecParams &params,
Volume *volume = (Volume *)BKE_id_new_nomain(ID_VO, nullptr);
BKE_volume_init_grids(volume);
- VolumeGrid *c_density_grid = BKE_volume_grid_add(volume, "density", VOLUME_GRID_FLOAT);
- openvdb::FloatGrid::Ptr density_grid = openvdb::gridPtrCast<openvdb::FloatGrid>(
- BKE_volume_grid_openvdb_for_write(volume, c_density_grid, false));
-
const float density = params.get_input<float>("Density");
convert_to_grid_index_space(voxel_size, positions, radii);
openvdb::FloatGrid::Ptr new_grid = generate_volume_from_points(positions, radii, density);
- /* This merge is cheap, because the #density_grid is empty. */
- density_grid->merge(*new_grid);
- density_grid->transform().postScale(voxel_size);
+ new_grid->transform().postScale(voxel_size);
+ BKE_volume_grid_add_vdb(*volume, "density", std::move(new_grid));
+
r_geometry_set.keep_only({GEO_COMPONENT_TYPE_VOLUME, GEO_COMPONENT_TYPE_INSTANCES});
r_geometry_set.replace_volume(volume);
}
#endif
-static void geo_node_points_to_volume_exec(GeoNodeExecParams params)
+static void node_geo_exec(GeoNodeExecParams params)
{
GeometrySet geometry_set = params.extract_input<GeometrySet>("Points");
@@ -253,10 +250,12 @@ static void geo_node_points_to_volume_exec(GeoNodeExecParams params)
#endif
}
-} // namespace blender::nodes
+} // namespace blender::nodes::node_geo_points_to_volume_cc
void register_node_type_geo_points_to_volume()
{
+ namespace file_ns = blender::nodes::node_geo_points_to_volume_cc;
+
static bNodeType ntype;
geo_node_type_base(
@@ -266,10 +265,10 @@ void register_node_type_geo_points_to_volume()
node_free_standard_storage,
node_copy_standard_storage);
node_type_size(&ntype, 170, 120, 700);
- node_type_init(&ntype, blender::nodes::geo_node_points_to_volume_init);
- node_type_update(&ntype, blender::nodes::geo_node_points_to_volume_update);
- ntype.declare = blender::nodes::geo_node_points_to_volume_declare;
- ntype.geometry_node_execute = blender::nodes::geo_node_points_to_volume_exec;
- ntype.draw_buttons = blender::nodes::geo_node_points_to_volume_layout;
+ node_type_init(&ntype, file_ns::node_init);
+ node_type_update(&ntype, file_ns::node_update);
+ ntype.declare = file_ns::node_declare;
+ ntype.geometry_node_execute = file_ns::node_geo_exec;
+ ntype.draw_buttons = file_ns::node_layout;
nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/geometry/nodes/node_geo_proximity.cc b/source/blender/nodes/geometry/nodes/node_geo_proximity.cc
index c05476b982b..4431ccd5459 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_proximity.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_proximity.cc
@@ -27,9 +27,9 @@
#include "node_geometry_util.hh"
-namespace blender::nodes {
+namespace blender::nodes::node_geo_proximity_cc {
-static void geo_node_proximity_declare(NodeDeclarationBuilder &b)
+static void node_declare(NodeDeclarationBuilder &b)
{
b.add_input<decl::Geometry>(N_("Target"))
.only_realized_data()
@@ -39,7 +39,7 @@ static void geo_node_proximity_declare(NodeDeclarationBuilder &b)
b.add_output<decl::Float>(N_("Distance")).dependent_field();
}
-static void geo_node_proximity_layout(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
+static void node_layout(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
{
uiItemR(layout, ptr, "target_element", 0, "", ICON_NONE);
}
@@ -206,7 +206,7 @@ class ProximityFunction : public fn::MultiFunction {
}
};
-static void geo_node_proximity_exec(GeoNodeExecParams params)
+static void node_geo_exec(GeoNodeExecParams params)
{
GeometrySet geometry_set_target = params.extract_input<GeometrySet>("Target");
geometry_set_target.ensure_owns_direct_data();
@@ -233,18 +233,20 @@ static void geo_node_proximity_exec(GeoNodeExecParams params)
params.set_output("Distance", Field<float>(proximity_op, 1));
}
-} // namespace blender::nodes
+} // namespace blender::nodes::node_geo_proximity_cc
void register_node_type_geo_proximity()
{
+ namespace file_ns = blender::nodes::node_geo_proximity_cc;
+
static bNodeType ntype;
geo_node_type_base(&ntype, GEO_NODE_PROXIMITY, "Geometry Proximity", NODE_CLASS_GEOMETRY, 0);
- node_type_init(&ntype, blender::nodes::geo_proximity_init);
+ node_type_init(&ntype, file_ns::geo_proximity_init);
node_type_storage(
&ntype, "NodeGeometryProximity", node_free_standard_storage, node_copy_standard_storage);
- ntype.declare = blender::nodes::geo_node_proximity_declare;
- ntype.geometry_node_execute = blender::nodes::geo_node_proximity_exec;
- ntype.draw_buttons = blender::nodes::geo_node_proximity_layout;
+ ntype.declare = file_ns::node_declare;
+ ntype.geometry_node_execute = file_ns::node_geo_exec;
+ ntype.draw_buttons = file_ns::node_layout;
nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/geometry/nodes/node_geo_raycast.cc b/source/blender/nodes/geometry/nodes/node_geo_raycast.cc
index 42924a46667..c1f5b0c6706 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_raycast.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_raycast.cc
@@ -25,11 +25,11 @@
#include "node_geometry_util.hh"
-using namespace blender::bke::mesh_surface_sample;
+namespace blender::nodes::node_geo_raycast_cc {
-namespace blender::nodes {
+using namespace blender::bke::mesh_surface_sample;
-static void geo_node_raycast_declare(NodeDeclarationBuilder &b)
+static void node_declare(NodeDeclarationBuilder &b)
{
b.add_input<decl::Geometry>(N_("Target Geometry"))
.only_realized_data()
@@ -63,13 +63,13 @@ static void geo_node_raycast_declare(NodeDeclarationBuilder &b)
b.add_output<decl::Int>(N_("Attribute"), "Attribute_004").dependent_field({1, 2, 3, 4, 5, 6});
}
-static void geo_node_raycast_layout(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
+static void node_layout(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
{
uiItemR(layout, ptr, "data_type", 0, "", ICON_NONE);
uiItemR(layout, ptr, "mapping", 0, "", ICON_NONE);
}
-static void geo_node_raycast_init(bNodeTree *UNUSED(tree), bNode *node)
+static void node_init(bNodeTree *UNUSED(tree), bNode *node)
{
NodeGeometryRaycast *data = (NodeGeometryRaycast *)MEM_callocN(sizeof(NodeGeometryRaycast),
__func__);
@@ -78,7 +78,7 @@ static void geo_node_raycast_init(bNodeTree *UNUSED(tree), bNode *node)
node->storage = data;
}
-static void geo_node_raycast_update(bNodeTree *UNUSED(ntree), bNode *node)
+static void node_update(bNodeTree *ntree, bNode *node)
{
const NodeGeometryRaycast &data = *(const NodeGeometryRaycast *)node->storage;
const CustomDataType data_type = static_cast<CustomDataType>(data.data_type);
@@ -89,11 +89,11 @@ static void geo_node_raycast_update(bNodeTree *UNUSED(ntree), bNode *node)
bNodeSocket *socket_boolean = socket_color4f->next;
bNodeSocket *socket_int32 = socket_boolean->next;
- nodeSetSocketAvailability(socket_vector, data_type == CD_PROP_FLOAT3);
- nodeSetSocketAvailability(socket_float, data_type == CD_PROP_FLOAT);
- nodeSetSocketAvailability(socket_color4f, data_type == CD_PROP_COLOR);
- nodeSetSocketAvailability(socket_boolean, data_type == CD_PROP_BOOL);
- nodeSetSocketAvailability(socket_int32, data_type == CD_PROP_INT32);
+ nodeSetSocketAvailability(ntree, socket_vector, data_type == CD_PROP_FLOAT3);
+ nodeSetSocketAvailability(ntree, socket_float, data_type == CD_PROP_FLOAT);
+ nodeSetSocketAvailability(ntree, socket_color4f, data_type == CD_PROP_COLOR);
+ nodeSetSocketAvailability(ntree, socket_boolean, data_type == CD_PROP_BOOL);
+ nodeSetSocketAvailability(ntree, socket_int32, data_type == CD_PROP_INT32);
bNodeSocket *out_socket_vector = (bNodeSocket *)BLI_findlink(&node->outputs, 4);
bNodeSocket *out_socket_float = out_socket_vector->next;
@@ -101,11 +101,11 @@ static void geo_node_raycast_update(bNodeTree *UNUSED(ntree), bNode *node)
bNodeSocket *out_socket_boolean = out_socket_color4f->next;
bNodeSocket *out_socket_int32 = out_socket_boolean->next;
- nodeSetSocketAvailability(out_socket_vector, data_type == CD_PROP_FLOAT3);
- nodeSetSocketAvailability(out_socket_float, data_type == CD_PROP_FLOAT);
- nodeSetSocketAvailability(out_socket_color4f, data_type == CD_PROP_COLOR);
- nodeSetSocketAvailability(out_socket_boolean, data_type == CD_PROP_BOOL);
- nodeSetSocketAvailability(out_socket_int32, data_type == CD_PROP_INT32);
+ nodeSetSocketAvailability(ntree, out_socket_vector, data_type == CD_PROP_FLOAT3);
+ nodeSetSocketAvailability(ntree, out_socket_float, data_type == CD_PROP_FLOAT);
+ nodeSetSocketAvailability(ntree, out_socket_color4f, data_type == CD_PROP_COLOR);
+ nodeSetSocketAvailability(ntree, out_socket_boolean, data_type == CD_PROP_BOOL);
+ nodeSetSocketAvailability(ntree, out_socket_int32, data_type == CD_PROP_INT32);
}
static eAttributeMapMode get_map_mode(GeometryNodeRaycastMapMode map_mode)
@@ -375,7 +375,7 @@ static void output_attribute_field(GeoNodeExecParams &params, GField field)
}
}
-static void geo_node_raycast_exec(GeoNodeExecParams params)
+static void node_geo_exec(GeoNodeExecParams params)
{
GeometrySet target = params.extract_input<GeometrySet>("Target Geometry");
const NodeGeometryRaycast &data = *(const NodeGeometryRaycast *)params.node().storage;
@@ -426,20 +426,22 @@ static void geo_node_raycast_exec(GeoNodeExecParams params)
}
}
-} // namespace blender::nodes
+} // namespace blender::nodes::node_geo_raycast_cc
void register_node_type_geo_raycast()
{
+ namespace file_ns = blender::nodes::node_geo_raycast_cc;
+
static bNodeType ntype;
geo_node_type_base(&ntype, GEO_NODE_RAYCAST, "Raycast", NODE_CLASS_GEOMETRY, 0);
node_type_size_preset(&ntype, NODE_SIZE_MIDDLE);
- node_type_init(&ntype, blender::nodes::geo_node_raycast_init);
- node_type_update(&ntype, blender::nodes::geo_node_raycast_update);
+ node_type_init(&ntype, file_ns::node_init);
+ node_type_update(&ntype, file_ns::node_update);
node_type_storage(
&ntype, "NodeGeometryRaycast", node_free_standard_storage, node_copy_standard_storage);
- ntype.declare = blender::nodes::geo_node_raycast_declare;
- ntype.geometry_node_execute = blender::nodes::geo_node_raycast_exec;
- ntype.draw_buttons = blender::nodes::geo_node_raycast_layout;
+ ntype.declare = file_ns::node_declare;
+ ntype.geometry_node_execute = file_ns::node_geo_exec;
+ ntype.draw_buttons = file_ns::node_layout;
nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/geometry/nodes/node_geo_realize_instances.cc b/source/blender/nodes/geometry/nodes/node_geo_realize_instances.cc
index 6c51c1f738f..5b161e66d97 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_realize_instances.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_realize_instances.cc
@@ -19,30 +19,32 @@
#include "UI_interface.h"
#include "UI_resources.h"
-namespace blender::nodes {
+namespace blender::nodes::node_geo_realize_instances_cc {
-static void geo_node_realize_instances_declare(NodeDeclarationBuilder &b)
+static void node_declare(NodeDeclarationBuilder &b)
{
b.add_input<decl::Geometry>(N_("Geometry"));
b.add_output<decl::Geometry>(N_("Geometry"));
}
-static void geo_node_realize_instances_exec(GeoNodeExecParams params)
+static void node_geo_exec(GeoNodeExecParams params)
{
GeometrySet geometry_set = params.extract_input<GeometrySet>("Geometry");
geometry_set = bke::geometry_set_realize_instances(geometry_set);
params.set_output("Geometry", std::move(geometry_set));
}
-} // namespace blender::nodes
+} // namespace blender::nodes::node_geo_realize_instances_cc
void register_node_type_geo_realize_instances()
{
+ namespace file_ns = blender::nodes::node_geo_realize_instances_cc;
+
static bNodeType ntype;
geo_node_type_base(
&ntype, GEO_NODE_REALIZE_INSTANCES, "Realize Instances", NODE_CLASS_GEOMETRY, 0);
- ntype.declare = blender::nodes::geo_node_realize_instances_declare;
- ntype.geometry_node_execute = blender::nodes::geo_node_realize_instances_exec;
+ ntype.declare = file_ns::node_declare;
+ ntype.geometry_node_execute = file_ns::node_geo_exec;
nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/geometry/nodes/node_geo_rotate_instances.cc b/source/blender/nodes/geometry/nodes/node_geo_rotate_instances.cc
index abf44b1aaf8..0508ff7a215 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_rotate_instances.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_rotate_instances.cc
@@ -18,9 +18,9 @@
#include "node_geometry_util.hh"
-namespace blender::nodes {
+namespace blender::nodes::node_geo_rotate_instances_cc {
-static void geo_node_rotate_instances_declare(NodeDeclarationBuilder &b)
+static void node_declare(NodeDeclarationBuilder &b)
{
b.add_input<decl::Geometry>(N_("Instances")).only_instances();
b.add_input<decl::Bool>(N_("Selection")).default_value(true).hide_value().supports_field();
@@ -32,7 +32,7 @@ static void geo_node_rotate_instances_declare(NodeDeclarationBuilder &b)
static void rotate_instances(GeoNodeExecParams &params, InstancesComponent &instances_component)
{
- GeometryComponentFieldContext field_context{instances_component, ATTR_DOMAIN_POINT};
+ GeometryComponentFieldContext field_context{instances_component, ATTR_DOMAIN_INSTANCE};
const int domain_size = instances_component.instances_amount();
fn::FieldEvaluator selection_evaluator{field_context, domain_size};
@@ -96,7 +96,7 @@ static void rotate_instances(GeoNodeExecParams &params, InstancesComponent &inst
});
}
-static void geo_node_rotate_instances_exec(GeoNodeExecParams params)
+static void node_geo_exec(GeoNodeExecParams params)
{
GeometrySet geometry_set = params.extract_input<GeometrySet>("Instances");
if (geometry_set.has_instances()) {
@@ -106,15 +106,17 @@ static void geo_node_rotate_instances_exec(GeoNodeExecParams params)
params.set_output("Instances", std::move(geometry_set));
}
-} // namespace blender::nodes
+} // namespace blender::nodes::node_geo_rotate_instances_cc
void register_node_type_geo_rotate_instances()
{
+ namespace file_ns = blender::nodes::node_geo_rotate_instances_cc;
+
static bNodeType ntype;
geo_node_type_base(
&ntype, GEO_NODE_ROTATE_INSTANCES, "Rotate Instances", NODE_CLASS_GEOMETRY, 0);
- ntype.geometry_node_execute = blender::nodes::geo_node_rotate_instances_exec;
- ntype.declare = blender::nodes::geo_node_rotate_instances_declare;
+ ntype.geometry_node_execute = file_ns::node_geo_exec;
+ ntype.declare = file_ns::node_declare;
nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/geometry/nodes/node_geo_scale_instances.cc b/source/blender/nodes/geometry/nodes/node_geo_scale_instances.cc
index ea2b458410e..3e0f3160f89 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_scale_instances.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_scale_instances.cc
@@ -18,9 +18,9 @@
#include "node_geometry_util.hh"
-namespace blender::nodes {
+namespace blender::nodes::node_geo_scale_instances_cc {
-static void geo_node_scale_instances_declare(NodeDeclarationBuilder &b)
+static void node_declare(NodeDeclarationBuilder &b)
{
b.add_input<decl::Geometry>(N_("Instances")).only_instances();
b.add_input<decl::Bool>(N_("Selection")).default_value(true).hide_value().supports_field();
@@ -35,7 +35,7 @@ static void geo_node_scale_instances_declare(NodeDeclarationBuilder &b)
static void scale_instances(GeoNodeExecParams &params, InstancesComponent &instances_component)
{
- GeometryComponentFieldContext field_context{instances_component, ATTR_DOMAIN_POINT};
+ GeometryComponentFieldContext field_context{instances_component, ATTR_DOMAIN_INSTANCE};
fn::FieldEvaluator selection_evaluator{field_context, instances_component.instances_amount()};
selection_evaluator.add(params.extract_input<Field<bool>>("Selection"));
@@ -75,7 +75,7 @@ static void scale_instances(GeoNodeExecParams &params, InstancesComponent &insta
});
}
-static void geo_node_scale_instances_exec(GeoNodeExecParams params)
+static void node_geo_exec(GeoNodeExecParams params)
{
GeometrySet geometry_set = params.extract_input<GeometrySet>("Instances");
if (geometry_set.has_instances()) {
@@ -85,14 +85,16 @@ static void geo_node_scale_instances_exec(GeoNodeExecParams params)
params.set_output("Instances", std::move(geometry_set));
}
-} // namespace blender::nodes
+} // namespace blender::nodes::node_geo_scale_instances_cc
void register_node_type_geo_scale_instances()
{
+ namespace file_ns = blender::nodes::node_geo_scale_instances_cc;
+
static bNodeType ntype;
geo_node_type_base(&ntype, GEO_NODE_SCALE_INSTANCES, "Scale Instances", NODE_CLASS_GEOMETRY, 0);
- ntype.geometry_node_execute = blender::nodes::geo_node_scale_instances_exec;
- ntype.declare = blender::nodes::geo_node_scale_instances_declare;
+ ntype.geometry_node_execute = file_ns::node_geo_exec;
+ ntype.declare = file_ns::node_declare;
nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/geometry/nodes/node_geo_separate_components.cc b/source/blender/nodes/geometry/nodes/node_geo_separate_components.cc
index a16fb712b13..e4adfe6587d 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_separate_components.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_separate_components.cc
@@ -16,9 +16,9 @@
#include "node_geometry_util.hh"
-namespace blender::nodes {
+namespace blender::nodes::node_geo_separate_components_cc {
-static void geo_node_join_geometry_declare(NodeDeclarationBuilder &b)
+static void node_declare(NodeDeclarationBuilder &b)
{
b.add_input<decl::Geometry>(N_("Geometry"));
b.add_output<decl::Geometry>(N_("Mesh"));
@@ -28,7 +28,7 @@ static void geo_node_join_geometry_declare(NodeDeclarationBuilder &b)
b.add_output<decl::Geometry>(N_("Instances"));
}
-static void geo_node_separate_components_exec(GeoNodeExecParams params)
+static void node_geo_exec(GeoNodeExecParams params)
{
GeometrySet geometry_set = params.extract_input<GeometrySet>("Geometry");
@@ -61,15 +61,17 @@ static void geo_node_separate_components_exec(GeoNodeExecParams params)
params.set_output("Instances", instances);
}
-} // namespace blender::nodes
+} // namespace blender::nodes::node_geo_separate_components_cc
void register_node_type_geo_separate_components()
{
+ namespace file_ns = blender::nodes::node_geo_separate_components_cc;
+
static bNodeType ntype;
geo_node_type_base(
&ntype, GEO_NODE_SEPARATE_COMPONENTS, "Separate Components", NODE_CLASS_GEOMETRY, 0);
- ntype.declare = blender::nodes::geo_node_join_geometry_declare;
- ntype.geometry_node_execute = blender::nodes::geo_node_separate_components_exec;
+ ntype.declare = file_ns::node_declare;
+ ntype.geometry_node_execute = file_ns::node_geo_exec;
nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/geometry/nodes/node_geo_separate_geometry.cc b/source/blender/nodes/geometry/nodes/node_geo_separate_geometry.cc
index 28e214c0ccc..220aa07faa6 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_separate_geometry.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_separate_geometry.cc
@@ -19,9 +19,9 @@
#include "node_geometry_util.hh"
-namespace blender::nodes {
+namespace blender::nodes::node_geo_separate_geometry_cc {
-static void geo_node_separate_geometry_declare(NodeDeclarationBuilder &b)
+static void node_declare(NodeDeclarationBuilder &b)
{
b.add_input<decl::Geometry>(N_("Geometry"));
b.add_input<decl::Bool>(N_("Selection"))
@@ -35,14 +35,12 @@ static void geo_node_separate_geometry_declare(NodeDeclarationBuilder &b)
.description(N_("The parts of the geometry not in the selection"));
}
-static void geo_node_separate_geometry_layout(uiLayout *layout,
- bContext *UNUSED(C),
- PointerRNA *ptr)
+static void node_layout(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
{
uiItemR(layout, ptr, "domain", 0, "", ICON_NONE);
}
-static void geo_node_separate_geometry_init(bNodeTree *UNUSED(tree), bNode *node)
+static void node_init(bNodeTree *UNUSED(tree), bNode *node)
{
NodeGeometrySeparateGeometry *data = (NodeGeometrySeparateGeometry *)MEM_callocN(
sizeof(NodeGeometrySeparateGeometry), __func__);
@@ -51,7 +49,7 @@ static void geo_node_separate_geometry_init(bNodeTree *UNUSED(tree), bNode *node
node->storage = data;
}
-static void geo_node_separate_geometry_exec(GeoNodeExecParams params)
+static void node_geo_exec(GeoNodeExecParams params)
{
GeometrySet geometry_set = params.extract_input<GeometrySet>("Geometry");
@@ -95,10 +93,12 @@ static void geo_node_separate_geometry_exec(GeoNodeExecParams params)
}
}
-} // namespace blender::nodes
+} // namespace blender::nodes::node_geo_separate_geometry_cc
void register_node_type_geo_separate_geometry()
{
+ namespace file_ns = blender::nodes::node_geo_separate_geometry_cc;
+
static bNodeType ntype;
geo_node_type_base(
@@ -109,10 +109,10 @@ void register_node_type_geo_separate_geometry()
node_free_standard_storage,
node_copy_standard_storage);
- node_type_init(&ntype, blender::nodes::geo_node_separate_geometry_init);
+ node_type_init(&ntype, file_ns::node_init);
- ntype.declare = blender::nodes::geo_node_separate_geometry_declare;
- ntype.geometry_node_execute = blender::nodes::geo_node_separate_geometry_exec;
- ntype.draw_buttons = blender::nodes::geo_node_separate_geometry_layout;
+ ntype.declare = file_ns::node_declare;
+ ntype.geometry_node_execute = file_ns::node_geo_exec;
+ ntype.draw_buttons = file_ns::node_layout;
nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/geometry/nodes/node_geo_set_curve_handles.cc b/source/blender/nodes/geometry/nodes/node_geo_set_curve_handles.cc
index b64aa266330..f0b8579ae7d 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_set_curve_handles.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_set_curve_handles.cc
@@ -21,24 +21,23 @@
#include "node_geometry_util.hh"
-namespace blender::nodes {
+namespace blender::nodes::node_geo_set_curve_handles_cc {
-static void geo_node_set_curve_handles_declare(NodeDeclarationBuilder &b)
+static void node_declare(NodeDeclarationBuilder &b)
{
b.add_input<decl::Geometry>(N_("Curve")).supported_type(GEO_COMPONENT_TYPE_CURVE);
b.add_input<decl::Bool>(N_("Selection")).default_value(true).hide_value().supports_field();
b.add_input<decl::Vector>(N_("Position")).implicit_field();
+ b.add_input<decl::Vector>(N_("Offset")).default_value(float3(0.0f, 0.0f, 0.0f)).supports_field();
b.add_output<decl::Geometry>(N_("Curve"));
}
-static void geo_node_set_curve_handles_layout(uiLayout *layout,
- bContext *UNUSED(C),
- PointerRNA *ptr)
+static void node_layout(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
{
uiItemR(layout, ptr, "mode", UI_ITEM_R_EXPAND, nullptr, ICON_NONE);
}
-static void geo_node_set_curve_handles_init(bNodeTree *UNUSED(tree), bNode *node)
+static void node_init(bNodeTree *UNUSED(tree), bNode *node)
{
NodeGeometrySetCurveHandlePositions *data = (NodeGeometrySetCurveHandlePositions *)MEM_callocN(
sizeof(NodeGeometrySetCurveHandlePositions), __func__);
@@ -50,7 +49,8 @@ static void geo_node_set_curve_handles_init(bNodeTree *UNUSED(tree), bNode *node
static void set_position_in_component(const GeometryNodeCurveHandleMode mode,
GeometryComponent &component,
const Field<bool> &selection_field,
- const Field<float3> &position_field)
+ const Field<float3> &position_field,
+ const Field<float3> &offset_field)
{
GeometryComponentFieldContext field_context{component, ATTR_DOMAIN_POINT};
const int domain_size = component.attribute_domain_size(ATTR_DOMAIN_POINT);
@@ -111,15 +111,26 @@ static void set_position_in_component(const GeometryNodeCurveHandleMode mode,
}
}
- OutputAttribute_Typed<float3> positions = component.attribute_try_get_for_output_only<float3>(
- side, ATTR_DOMAIN_POINT);
fn::FieldEvaluator position_evaluator{field_context, &selection};
- position_evaluator.add_with_destination(position_field, positions.varray());
+ position_evaluator.add(position_field);
+ position_evaluator.add(offset_field);
position_evaluator.evaluate();
+
+ const VArray<float3> &positions_input = position_evaluator.get_evaluated<float3>(0);
+ const VArray<float3> &offsets_input = position_evaluator.get_evaluated<float3>(1);
+
+ OutputAttribute_Typed<float3> positions = component.attribute_try_get_for_output<float3>(
+ side, ATTR_DOMAIN_POINT, {0, 0, 0});
+ MutableSpan<float3> position_mutable = positions.as_span();
+
+ for (int i : selection) {
+ position_mutable[i] = positions_input[i] + offsets_input[i];
+ }
+
positions.save();
}
-static void geo_node_set_curve_handles_exec(GeoNodeExecParams params)
+static void node_geo_exec(GeoNodeExecParams params)
{
const NodeGeometrySetCurveHandlePositions *node_storage =
(NodeGeometrySetCurveHandlePositions *)params.node().storage;
@@ -128,6 +139,7 @@ static void geo_node_set_curve_handles_exec(GeoNodeExecParams params)
GeometrySet geometry_set = params.extract_input<GeometrySet>("Curve");
Field<bool> selection_field = params.extract_input<Field<bool>>("Selection");
Field<float3> position_field = params.extract_input<Field<float3>>("Position");
+ Field<float3> offset_field = params.extract_input<Field<float3>>("Offset");
bool has_bezier = false;
geometry_set.modify_geometry_sets([&](GeometrySet &geometry_set) {
@@ -137,7 +149,8 @@ static void geo_node_set_curve_handles_exec(GeoNodeExecParams params)
set_position_in_component(mode,
geometry_set.get_component_for_write<CurveComponent>(),
selection_field,
- position_field);
+ position_field,
+ offset_field);
}
});
if (!has_bezier) {
@@ -147,22 +160,24 @@ static void geo_node_set_curve_handles_exec(GeoNodeExecParams params)
params.set_output("Curve", std::move(geometry_set));
}
-} // namespace blender::nodes
+} // namespace blender::nodes::node_geo_set_curve_handles_cc
void register_node_type_geo_set_curve_handles()
{
+ namespace file_ns = blender::nodes::node_geo_set_curve_handles_cc;
+
static bNodeType ntype;
geo_node_type_base(
&ntype, GEO_NODE_SET_CURVE_HANDLES, "Set Handle Positions", NODE_CLASS_GEOMETRY, 0);
- ntype.geometry_node_execute = blender::nodes::geo_node_set_curve_handles_exec;
- ntype.declare = blender::nodes::geo_node_set_curve_handles_declare;
+ ntype.geometry_node_execute = file_ns::node_geo_exec;
+ ntype.declare = file_ns::node_declare;
ntype.minwidth = 100.0f;
- node_type_init(&ntype, blender::nodes::geo_node_set_curve_handles_init);
+ node_type_init(&ntype, file_ns::node_init);
node_type_storage(&ntype,
"NodeGeometrySetCurveHandlePositions",
node_free_standard_storage,
node_copy_standard_storage);
- ntype.draw_buttons = blender::nodes::geo_node_set_curve_handles_layout;
+ ntype.draw_buttons = file_ns::node_layout;
nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/geometry/nodes/node_geo_set_curve_radius.cc b/source/blender/nodes/geometry/nodes/node_geo_set_curve_radius.cc
index e47ce7dea30..fd486f07e69 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_set_curve_radius.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_set_curve_radius.cc
@@ -16,9 +16,9 @@
#include "node_geometry_util.hh"
-namespace blender::nodes {
+namespace blender::nodes::node_geo_set_curve_radius_cc {
-static void geo_node_set_curve_radius_declare(NodeDeclarationBuilder &b)
+static void node_declare(NodeDeclarationBuilder &b)
{
b.add_input<decl::Geometry>(N_("Curve")).supported_type(GEO_COMPONENT_TYPE_CURVE);
b.add_input<decl::Bool>(N_("Selection")).default_value(true).hide_value().supports_field();
@@ -53,7 +53,7 @@ static void set_radius_in_component(GeometryComponent &component,
radii.save();
}
-static void geo_node_set_curve_radius_exec(GeoNodeExecParams params)
+static void node_geo_exec(GeoNodeExecParams params)
{
GeometrySet geometry_set = params.extract_input<GeometrySet>("Curve");
Field<bool> selection_field = params.extract_input<Field<bool>>("Selection");
@@ -69,15 +69,17 @@ static void geo_node_set_curve_radius_exec(GeoNodeExecParams params)
params.set_output("Curve", std::move(geometry_set));
}
-} // namespace blender::nodes
+} // namespace blender::nodes::node_geo_set_curve_radius_cc
void register_node_type_geo_set_curve_radius()
{
+ namespace file_ns = blender::nodes::node_geo_set_curve_radius_cc;
+
static bNodeType ntype;
geo_node_type_base(
&ntype, GEO_NODE_SET_CURVE_RADIUS, "Set Curve Radius", NODE_CLASS_GEOMETRY, 0);
- ntype.geometry_node_execute = blender::nodes::geo_node_set_curve_radius_exec;
- ntype.declare = blender::nodes::geo_node_set_curve_radius_declare;
+ ntype.geometry_node_execute = file_ns::node_geo_exec;
+ ntype.declare = file_ns::node_declare;
nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/geometry/nodes/node_geo_set_curve_tilt.cc b/source/blender/nodes/geometry/nodes/node_geo_set_curve_tilt.cc
index a861c35f738..653ae39b4fa 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_set_curve_tilt.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_set_curve_tilt.cc
@@ -16,9 +16,9 @@
#include "node_geometry_util.hh"
-namespace blender::nodes {
+namespace blender::nodes::node_geo_set_curve_tilt_cc {
-static void geo_node_set_curve_tilt_declare(NodeDeclarationBuilder &b)
+static void node_declare(NodeDeclarationBuilder &b)
{
b.add_input<decl::Geometry>(N_("Curve")).supported_type(GEO_COMPONENT_TYPE_CURVE);
b.add_input<decl::Bool>(N_("Selection")).default_value(true).hide_value().supports_field();
@@ -49,7 +49,7 @@ static void set_tilt_in_component(GeometryComponent &component,
tilts.save();
}
-static void geo_node_set_curve_tilt_exec(GeoNodeExecParams params)
+static void node_geo_exec(GeoNodeExecParams params)
{
GeometrySet geometry_set = params.extract_input<GeometrySet>("Curve");
Field<bool> selection_field = params.extract_input<Field<bool>>("Selection");
@@ -65,14 +65,16 @@ static void geo_node_set_curve_tilt_exec(GeoNodeExecParams params)
params.set_output("Curve", std::move(geometry_set));
}
-} // namespace blender::nodes
+} // namespace blender::nodes::node_geo_set_curve_tilt_cc
void register_node_type_geo_set_curve_tilt()
{
+ namespace file_ns = blender::nodes::node_geo_set_curve_tilt_cc;
+
static bNodeType ntype;
geo_node_type_base(&ntype, GEO_NODE_SET_CURVE_TILT, "Set Curve Tilt", NODE_CLASS_GEOMETRY, 0);
- ntype.geometry_node_execute = blender::nodes::geo_node_set_curve_tilt_exec;
- ntype.declare = blender::nodes::geo_node_set_curve_tilt_declare;
+ ntype.geometry_node_execute = file_ns::node_geo_exec;
+ ntype.declare = file_ns::node_declare;
nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/geometry/nodes/node_geo_set_id.cc b/source/blender/nodes/geometry/nodes/node_geo_set_id.cc
index 77d8e786501..e2f48edc72d 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_set_id.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_set_id.cc
@@ -16,9 +16,9 @@
#include "node_geometry_util.hh"
-namespace blender::nodes {
+namespace blender::nodes::node_geo_set_id_cc {
-static void geo_node_set_id_declare(NodeDeclarationBuilder &b)
+static void node_declare(NodeDeclarationBuilder &b)
{
b.add_input<decl::Geometry>(N_("Geometry"));
b.add_input<decl::Bool>(N_("Selection")).default_value(true).hide_value().supports_field();
@@ -63,7 +63,7 @@ static void set_id_in_component(GeometryComponent &component,
}
}
-static void geo_node_set_id_exec(GeoNodeExecParams params)
+static void node_geo_exec(GeoNodeExecParams params)
{
GeometrySet geometry_set = params.extract_input<GeometrySet>("Geometry");
Field<bool> selection_field = params.extract_input<Field<bool>>("Selection");
@@ -81,14 +81,16 @@ static void geo_node_set_id_exec(GeoNodeExecParams params)
params.set_output("Geometry", std::move(geometry_set));
}
-} // namespace blender::nodes
+} // namespace blender::nodes::node_geo_set_id_cc
void register_node_type_geo_set_id()
{
+ namespace file_ns = blender::nodes::node_geo_set_id_cc;
+
static bNodeType ntype;
geo_node_type_base(&ntype, GEO_NODE_SET_ID, "Set ID", NODE_CLASS_GEOMETRY, 0);
- ntype.geometry_node_execute = blender::nodes::geo_node_set_id_exec;
- ntype.declare = blender::nodes::geo_node_set_id_declare;
+ ntype.geometry_node_execute = file_ns::node_geo_exec;
+ ntype.declare = file_ns::node_declare;
nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/geometry/nodes/node_geo_set_material.cc b/source/blender/nodes/geometry/nodes/node_geo_set_material.cc
index 3817de02a38..fd65bcc235a 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_set_material.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_set_material.cc
@@ -25,9 +25,9 @@
#include "BKE_material.h"
-namespace blender::nodes {
+namespace blender::nodes::node_geo_set_material_cc {
-static void geo_node_set_material_declare(NodeDeclarationBuilder &b)
+static void node_declare(NodeDeclarationBuilder &b)
{
b.add_input<decl::Geometry>(N_("Geometry"))
.supported_type({GEO_COMPONENT_TYPE_MESH, GEO_COMPONENT_TYPE_VOLUME});
@@ -59,7 +59,7 @@ static void assign_material_to_faces(Mesh &mesh, const IndexMask selection, Mate
}
}
-static void geo_node_set_material_exec(GeoNodeExecParams params)
+static void node_geo_exec(GeoNodeExecParams params)
{
Material *material = params.extract_input<Material *>("Material");
const Field<bool> selection_field = params.extract_input<Field<bool>>("Selection");
@@ -103,14 +103,16 @@ static void geo_node_set_material_exec(GeoNodeExecParams params)
params.set_output("Geometry", std::move(geometry_set));
}
-} // namespace blender::nodes
+} // namespace blender::nodes::node_geo_set_material_cc
void register_node_type_geo_set_material()
{
+ namespace file_ns = blender::nodes::node_geo_set_material_cc;
+
static bNodeType ntype;
geo_node_type_base(&ntype, GEO_NODE_SET_MATERIAL, "Set Material", NODE_CLASS_GEOMETRY, 0);
- ntype.declare = blender::nodes::geo_node_set_material_declare;
- ntype.geometry_node_execute = blender::nodes::geo_node_set_material_exec;
+ ntype.declare = file_ns::node_declare;
+ ntype.geometry_node_execute = file_ns::node_geo_exec;
nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/geometry/nodes/node_geo_set_material_index.cc b/source/blender/nodes/geometry/nodes/node_geo_set_material_index.cc
index a8bb1bd8644..25634311225 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_set_material_index.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_set_material_index.cc
@@ -16,9 +16,9 @@
#include "node_geometry_util.hh"
-namespace blender::nodes {
+namespace blender::nodes::node_geo_set_material_index_cc {
-static void geo_node_set_material_index_declare(NodeDeclarationBuilder &b)
+static void node_declare(NodeDeclarationBuilder &b)
{
b.add_input<decl::Geometry>(N_("Geometry")).supported_type(GEO_COMPONENT_TYPE_MESH);
b.add_input<decl::Bool>(N_("Selection")).default_value(true).hide_value().supports_field();
@@ -49,7 +49,7 @@ static void set_material_index_in_component(GeometryComponent &component,
indices.save();
}
-static void geo_node_set_material_index_exec(GeoNodeExecParams params)
+static void node_geo_exec(GeoNodeExecParams params)
{
GeometrySet geometry_set = params.extract_input<GeometrySet>("Geometry");
Field<bool> selection_field = params.extract_input<Field<bool>>("Selection");
@@ -64,15 +64,17 @@ static void geo_node_set_material_index_exec(GeoNodeExecParams params)
params.set_output("Geometry", std::move(geometry_set));
}
-} // namespace blender::nodes
+} // namespace blender::nodes::node_geo_set_material_index_cc
void register_node_type_geo_set_material_index()
{
+ namespace file_ns = blender::nodes::node_geo_set_material_index_cc;
+
static bNodeType ntype;
geo_node_type_base(
&ntype, GEO_NODE_SET_MATERIAL_INDEX, "Set Material Index", NODE_CLASS_GEOMETRY, 0);
- ntype.geometry_node_execute = blender::nodes::geo_node_set_material_index_exec;
- ntype.declare = blender::nodes::geo_node_set_material_index_declare;
+ ntype.geometry_node_execute = file_ns::node_geo_exec;
+ ntype.declare = file_ns::node_declare;
nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/geometry/nodes/node_geo_set_point_radius.cc b/source/blender/nodes/geometry/nodes/node_geo_set_point_radius.cc
index 9ff299542b4..bc7c59f75be 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_set_point_radius.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_set_point_radius.cc
@@ -16,9 +16,9 @@
#include "node_geometry_util.hh"
-namespace blender::nodes {
+namespace blender::nodes::node_geo_set_point_radius_cc {
-static void geo_node_set_point_radius_declare(NodeDeclarationBuilder &b)
+static void node_declare(NodeDeclarationBuilder &b)
{
b.add_input<decl::Geometry>(N_("Points")).supported_type(GEO_COMPONENT_TYPE_POINT_CLOUD);
b.add_input<decl::Bool>(N_("Selection")).default_value(true).hide_value().supports_field();
@@ -53,7 +53,7 @@ static void set_radius_in_component(GeometryComponent &component,
radii.save();
}
-static void geo_node_set_point_radius_exec(GeoNodeExecParams params)
+static void node_geo_exec(GeoNodeExecParams params)
{
GeometrySet geometry_set = params.extract_input<GeometrySet>("Points");
Field<bool> selection_field = params.extract_input<Field<bool>>("Selection");
@@ -70,15 +70,17 @@ static void geo_node_set_point_radius_exec(GeoNodeExecParams params)
params.set_output("Points", std::move(geometry_set));
}
-} // namespace blender::nodes
+} // namespace blender::nodes::node_geo_set_point_radius_cc
void register_node_type_geo_set_point_radius()
{
+ namespace file_ns = blender::nodes::node_geo_set_point_radius_cc;
+
static bNodeType ntype;
geo_node_type_base(
&ntype, GEO_NODE_SET_POINT_RADIUS, "Set Point Radius", NODE_CLASS_GEOMETRY, 0);
- ntype.geometry_node_execute = blender::nodes::geo_node_set_point_radius_exec;
- ntype.declare = blender::nodes::geo_node_set_point_radius_declare;
+ ntype.geometry_node_execute = file_ns::node_geo_exec;
+ ntype.declare = file_ns::node_declare;
nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/geometry/nodes/node_geo_set_position.cc b/source/blender/nodes/geometry/nodes/node_geo_set_position.cc
index 4e564386a28..a8e59a807e7 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_set_position.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_set_position.cc
@@ -18,9 +18,9 @@
#include "node_geometry_util.hh"
-namespace blender::nodes {
+namespace blender::nodes::node_geo_set_position_cc {
-static void geo_node_set_position_declare(NodeDeclarationBuilder &b)
+static void node_declare(NodeDeclarationBuilder &b)
{
b.add_input<decl::Geometry>(N_("Geometry"));
b.add_input<decl::Bool>(N_("Selection")).default_value(true).hide_value().supports_field();
@@ -34,8 +34,11 @@ static void set_position_in_component(GeometryComponent &component,
const Field<float3> &position_field,
const Field<float3> &offset_field)
{
- GeometryComponentFieldContext field_context{component, ATTR_DOMAIN_POINT};
- const int domain_size = component.attribute_domain_size(ATTR_DOMAIN_POINT);
+ AttributeDomain domain = component.type() == GEO_COMPONENT_TYPE_INSTANCES ?
+ ATTR_DOMAIN_INSTANCE :
+ ATTR_DOMAIN_POINT;
+ GeometryComponentFieldContext field_context{component, domain};
+ const int domain_size = component.attribute_domain_size(domain);
if (domain_size == 0) {
return;
}
@@ -57,7 +60,7 @@ static void set_position_in_component(GeometryComponent &component,
const VArray<float3> &offsets_input = position_evaluator.get_evaluated<float3>(1);
OutputAttribute_Typed<float3> positions = component.attribute_try_get_for_output<float3>(
- "position", ATTR_DOMAIN_POINT, {0, 0, 0});
+ "position", domain, {0, 0, 0});
MutableSpan<float3> position_mutable = positions.as_span();
for (int i : selection) {
@@ -66,7 +69,7 @@ static void set_position_in_component(GeometryComponent &component,
positions.save();
}
-static void geo_node_set_position_exec(GeoNodeExecParams params)
+static void node_geo_exec(GeoNodeExecParams params)
{
GeometrySet geometry = params.extract_input<GeometrySet>("Geometry");
Field<bool> selection_field = params.extract_input<Field<bool>>("Selection");
@@ -86,14 +89,16 @@ static void geo_node_set_position_exec(GeoNodeExecParams params)
params.set_output("Geometry", std::move(geometry));
}
-} // namespace blender::nodes
+} // namespace blender::nodes::node_geo_set_position_cc
void register_node_type_geo_set_position()
{
+ namespace file_ns = blender::nodes::node_geo_set_position_cc;
+
static bNodeType ntype;
geo_node_type_base(&ntype, GEO_NODE_SET_POSITION, "Set Position", NODE_CLASS_GEOMETRY, 0);
- ntype.geometry_node_execute = blender::nodes::geo_node_set_position_exec;
- ntype.declare = blender::nodes::geo_node_set_position_declare;
+ ntype.geometry_node_execute = file_ns::node_geo_exec;
+ ntype.declare = file_ns::node_declare;
nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/geometry/nodes/node_geo_set_shade_smooth.cc b/source/blender/nodes/geometry/nodes/node_geo_set_shade_smooth.cc
index 06e25c2ed55..a8831130453 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_set_shade_smooth.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_set_shade_smooth.cc
@@ -16,9 +16,9 @@
#include "node_geometry_util.hh"
-namespace blender::nodes {
+namespace blender::nodes::node_geo_set_shade_smooth_cc {
-static void geo_node_set_shade_smooth_declare(NodeDeclarationBuilder &b)
+static void node_declare(NodeDeclarationBuilder &b)
{
b.add_input<decl::Geometry>(N_("Geometry")).supported_type(GEO_COMPONENT_TYPE_MESH);
b.add_input<decl::Bool>(N_("Selection")).default_value(true).hide_value().supports_field();
@@ -49,7 +49,7 @@ static void set_smooth_in_component(GeometryComponent &component,
shades.save();
}
-static void geo_node_set_shade_smooth_exec(GeoNodeExecParams params)
+static void node_geo_exec(GeoNodeExecParams params)
{
GeometrySet geometry_set = params.extract_input<GeometrySet>("Geometry");
Field<bool> selection_field = params.extract_input<Field<bool>>("Selection");
@@ -64,15 +64,17 @@ static void geo_node_set_shade_smooth_exec(GeoNodeExecParams params)
params.set_output("Geometry", std::move(geometry_set));
}
-} // namespace blender::nodes
+} // namespace blender::nodes::node_geo_set_shade_smooth_cc
void register_node_type_geo_set_shade_smooth()
{
+ namespace file_ns = blender::nodes::node_geo_set_shade_smooth_cc;
+
static bNodeType ntype;
geo_node_type_base(
&ntype, GEO_NODE_SET_SHADE_SMOOTH, "Set Shade Smooth", NODE_CLASS_GEOMETRY, 0);
- ntype.geometry_node_execute = blender::nodes::geo_node_set_shade_smooth_exec;
- ntype.declare = blender::nodes::geo_node_set_shade_smooth_declare;
+ ntype.geometry_node_execute = file_ns::node_geo_exec;
+ ntype.declare = file_ns::node_declare;
nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/geometry/nodes/node_geo_set_spline_cyclic.cc b/source/blender/nodes/geometry/nodes/node_geo_set_spline_cyclic.cc
index ec751ae1d2b..7ffda8787e6 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_set_spline_cyclic.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_set_spline_cyclic.cc
@@ -16,9 +16,9 @@
#include "node_geometry_util.hh"
-namespace blender::nodes {
+namespace blender::nodes::node_geo_set_spline_cyclic_cc {
-static void geo_node_set_spline_cyclic_declare(NodeDeclarationBuilder &b)
+static void node_declare(NodeDeclarationBuilder &b)
{
b.add_input<decl::Geometry>(N_("Geometry")).supported_type(GEO_COMPONENT_TYPE_CURVE);
b.add_input<decl::Bool>(N_("Selection")).default_value(true).hide_value().supports_field();
@@ -49,7 +49,7 @@ static void set_cyclic_in_component(GeometryComponent &component,
cyclics.save();
}
-static void geo_node_set_spline_cyclic_exec(GeoNodeExecParams params)
+static void node_geo_exec(GeoNodeExecParams params)
{
GeometrySet geometry_set = params.extract_input<GeometrySet>("Geometry");
Field<bool> selection_field = params.extract_input<Field<bool>>("Selection");
@@ -65,15 +65,17 @@ static void geo_node_set_spline_cyclic_exec(GeoNodeExecParams params)
params.set_output("Geometry", std::move(geometry_set));
}
-} // namespace blender::nodes
+} // namespace blender::nodes::node_geo_set_spline_cyclic_cc
void register_node_type_geo_set_spline_cyclic()
{
+ namespace file_ns = blender::nodes::node_geo_set_spline_cyclic_cc;
+
static bNodeType ntype;
geo_node_type_base(
&ntype, GEO_NODE_SET_SPLINE_CYCLIC, "Set Spline Cyclic", NODE_CLASS_GEOMETRY, 0);
- ntype.geometry_node_execute = blender::nodes::geo_node_set_spline_cyclic_exec;
- ntype.declare = blender::nodes::geo_node_set_spline_cyclic_declare;
+ ntype.geometry_node_execute = file_ns::node_geo_exec;
+ ntype.declare = file_ns::node_declare;
nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/geometry/nodes/node_geo_set_spline_resolution.cc b/source/blender/nodes/geometry/nodes/node_geo_set_spline_resolution.cc
index ccf419975ca..4280372faa6 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_set_spline_resolution.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_set_spline_resolution.cc
@@ -18,9 +18,9 @@
#include "node_geometry_util.hh"
-namespace blender::nodes {
+namespace blender::nodes::node_geo_set_spline_resolution_cc {
-static void geo_node_set_spline_resolution_declare(NodeDeclarationBuilder &b)
+static void node_declare(NodeDeclarationBuilder &b)
{
b.add_input<decl::Geometry>(N_("Geometry")).supported_type(GEO_COMPONENT_TYPE_CURVE);
b.add_input<decl::Bool>(N_("Selection")).default_value(true).hide_value().supports_field();
@@ -51,7 +51,7 @@ static void set_resolution_in_component(GeometryComponent &component,
resolutions.save();
}
-static void geo_node_set_spline_resolution_exec(GeoNodeExecParams params)
+static void node_geo_exec(GeoNodeExecParams params)
{
GeometrySet geometry_set = params.extract_input<GeometrySet>("Geometry");
Field<bool> selection_field = params.extract_input<Field<bool>>("Selection");
@@ -81,15 +81,17 @@ static void geo_node_set_spline_resolution_exec(GeoNodeExecParams params)
params.set_output("Geometry", std::move(geometry_set));
}
-} // namespace blender::nodes
+} // namespace blender::nodes::node_geo_set_spline_resolution_cc
void register_node_type_geo_set_spline_resolution()
{
+ namespace file_ns = blender::nodes::node_geo_set_spline_resolution_cc;
+
static bNodeType ntype;
geo_node_type_base(
&ntype, GEO_NODE_SET_SPLINE_RESOLUTION, "Set Spline Resolution", NODE_CLASS_GEOMETRY, 0);
- ntype.geometry_node_execute = blender::nodes::geo_node_set_spline_resolution_exec;
- ntype.declare = blender::nodes::geo_node_set_spline_resolution_declare;
+ ntype.geometry_node_execute = file_ns::node_geo_exec;
+ ntype.declare = file_ns::node_declare;
nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/geometry/nodes/node_geo_string_join.cc b/source/blender/nodes/geometry/nodes/node_geo_string_join.cc
index 98d0aca084a..5308b43afb2 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_string_join.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_string_join.cc
@@ -16,16 +16,16 @@
#include "node_geometry_util.hh"
-namespace blender::nodes {
+namespace blender::nodes::node_geo_string_join_cc {
-static void geo_node_string_join_declare(NodeDeclarationBuilder &b)
+static void node_declare(NodeDeclarationBuilder &b)
{
b.add_input<decl::String>(N_("Delimiter"));
b.add_input<decl::String>(N_("Strings")).multi_input().hide_value();
b.add_output<decl::String>(N_("String"));
};
-static void geo_node_string_join_exec(GeoNodeExecParams params)
+static void node_geo_exec(GeoNodeExecParams params)
{
Vector<std::string> strings = params.extract_multi_input<std::string>("Strings");
const std::string delim = params.extract_input<std::string>("Delimiter");
@@ -40,14 +40,16 @@ static void geo_node_string_join_exec(GeoNodeExecParams params)
params.set_output("String", std::move(output));
}
-} // namespace blender::nodes
+} // namespace blender::nodes::node_geo_string_join_cc
void register_node_type_geo_string_join()
{
+ namespace file_ns = blender::nodes::node_geo_string_join_cc;
+
static bNodeType ntype;
geo_node_type_base(&ntype, GEO_NODE_STRING_JOIN, "Join Strings", NODE_CLASS_CONVERTER, 0);
- ntype.geometry_node_execute = blender::nodes::geo_node_string_join_exec;
- ntype.declare = blender::nodes::geo_node_string_join_declare;
+ ntype.geometry_node_execute = file_ns::node_geo_exec;
+ ntype.declare = file_ns::node_declare;
nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/geometry/nodes/node_geo_string_to_curves.cc b/source/blender/nodes/geometry/nodes/node_geo_string_to_curves.cc
index 95e94a22d81..6a793e12f82 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_string_to_curves.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_string_to_curves.cc
@@ -30,9 +30,9 @@
#include "node_geometry_util.hh"
-namespace blender::nodes {
+namespace blender::nodes::node_geo_string_to_curves_cc {
-static void geo_node_string_to_curves_declare(NodeDeclarationBuilder &b)
+static void node_declare(NodeDeclarationBuilder &b)
{
b.add_input<decl::String>(N_("String"));
b.add_input<decl::Float>(N_("Size")).default_value(1.0f).min(0.0f).subtype(PROP_DISTANCE);
@@ -60,7 +60,7 @@ static void geo_node_string_to_curves_declare(NodeDeclarationBuilder &b)
b.add_output<decl::String>(N_("Remainder"));
}
-static void geo_node_string_to_curves_layout(uiLayout *layout, struct bContext *C, PointerRNA *ptr)
+static void node_layout(uiLayout *layout, struct bContext *C, PointerRNA *ptr)
{
uiLayoutSetPropSep(layout, true);
uiLayoutSetPropDecorate(layout, false);
@@ -79,7 +79,7 @@ static void geo_node_string_to_curves_layout(uiLayout *layout, struct bContext *
uiItemR(layout, ptr, "align_y", 0, "", ICON_NONE);
}
-static void geo_node_string_to_curves_init(bNodeTree *UNUSED(ntree), bNode *node)
+static void node_init(bNodeTree *UNUSED(ntree), bNode *node)
{
NodeGeometryStringToCurves *data = (NodeGeometryStringToCurves *)MEM_callocN(
sizeof(NodeGeometryStringToCurves), __func__);
@@ -91,17 +91,19 @@ static void geo_node_string_to_curves_init(bNodeTree *UNUSED(ntree), bNode *node
node->id = (ID *)BKE_vfont_builtin_get();
}
-static void geo_node_string_to_curves_update(bNodeTree *UNUSED(ntree), bNode *node)
+static void node_update(bNodeTree *ntree, bNode *node)
{
const NodeGeometryStringToCurves *storage = (const NodeGeometryStringToCurves *)node->storage;
const GeometryNodeStringToCurvesOverflowMode overflow = (GeometryNodeStringToCurvesOverflowMode)
storage->overflow;
bNodeSocket *socket_remainder = ((bNodeSocket *)node->outputs.first)->next;
- nodeSetSocketAvailability(socket_remainder, overflow == GEO_NODE_STRING_TO_CURVES_MODE_TRUNCATE);
+ nodeSetSocketAvailability(
+ ntree, socket_remainder, overflow == GEO_NODE_STRING_TO_CURVES_MODE_TRUNCATE);
bNodeSocket *height_socket = (bNodeSocket *)node->inputs.last;
bNodeSocket *width_socket = height_socket->prev;
- nodeSetSocketAvailability(height_socket, overflow != GEO_NODE_STRING_TO_CURVES_MODE_OVERFLOW);
+ nodeSetSocketAvailability(
+ ntree, height_socket, overflow != GEO_NODE_STRING_TO_CURVES_MODE_OVERFLOW);
node_sock_label(width_socket,
overflow == GEO_NODE_STRING_TO_CURVES_MODE_OVERFLOW ? N_("Max Width") :
N_("Text Box Width"));
@@ -263,7 +265,7 @@ static void add_instances_from_handles(InstancesComponent &instances,
});
}
-static void geo_node_string_to_curves_exec(GeoNodeExecParams params)
+static void node_geo_exec(GeoNodeExecParams params)
{
TextLayout layout = get_text_layout(params);
@@ -295,23 +297,25 @@ static void geo_node_string_to_curves_exec(GeoNodeExecParams params)
params.set_output("Curves", std::move(geometry_set_out));
}
-} // namespace blender::nodes
+} // namespace blender::nodes::node_geo_string_to_curves_cc
void register_node_type_geo_string_to_curves()
{
+ namespace file_ns = blender::nodes::node_geo_string_to_curves_cc;
+
static bNodeType ntype;
geo_node_type_base(
&ntype, GEO_NODE_STRING_TO_CURVES, "String to Curves", NODE_CLASS_GEOMETRY, 0);
- ntype.declare = blender::nodes::geo_node_string_to_curves_declare;
- ntype.geometry_node_execute = blender::nodes::geo_node_string_to_curves_exec;
- node_type_init(&ntype, blender::nodes::geo_node_string_to_curves_init);
- node_type_update(&ntype, blender::nodes::geo_node_string_to_curves_update);
+ ntype.declare = file_ns::node_declare;
+ ntype.geometry_node_execute = file_ns::node_geo_exec;
+ node_type_init(&ntype, file_ns::node_init);
+ node_type_update(&ntype, file_ns::node_update);
node_type_size(&ntype, 190, 120, 700);
node_type_storage(&ntype,
"NodeGeometryStringToCurves",
node_free_standard_storage,
node_copy_standard_storage);
- ntype.draw_buttons = blender::nodes::geo_node_string_to_curves_layout;
+ ntype.draw_buttons = file_ns::node_layout;
nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/geometry/nodes/node_geo_subdivision_surface.cc b/source/blender/nodes/geometry/nodes/node_geo_subdivision_surface.cc
index 2b3430a5ed0..011d1e2af82 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_subdivision_surface.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_subdivision_surface.cc
@@ -27,9 +27,9 @@
#include "node_geometry_util.hh"
-namespace blender::nodes {
+namespace blender::nodes::node_geo_subdivision_surface_cc {
-static void geo_node_subdivision_surface_declare(NodeDeclarationBuilder &b)
+static void node_declare(NodeDeclarationBuilder &b)
{
b.add_input<decl::Geometry>(N_("Mesh")).supported_type(GEO_COMPONENT_TYPE_MESH);
b.add_input<decl::Int>(N_("Level")).default_value(1).min(0).max(6);
@@ -42,15 +42,13 @@ static void geo_node_subdivision_surface_declare(NodeDeclarationBuilder &b)
b.add_output<decl::Geometry>(N_("Mesh"));
}
-static void geo_node_subdivision_surface_layout(uiLayout *layout,
- bContext *UNUSED(C),
- PointerRNA *ptr)
+static void node_layout(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
{
uiItemR(layout, ptr, "uv_smooth", 0, "", ICON_NONE);
uiItemR(layout, ptr, "boundary_smooth", 0, "", ICON_NONE);
}
-static void geo_node_subdivision_surface_init(bNodeTree *UNUSED(ntree), bNode *node)
+static void node_init(bNodeTree *UNUSED(ntree), bNode *node)
{
NodeGeometrySubdivisionSurface *data = (NodeGeometrySubdivisionSurface *)MEM_callocN(
sizeof(NodeGeometrySubdivisionSurface), __func__);
@@ -59,7 +57,7 @@ static void geo_node_subdivision_surface_init(bNodeTree *UNUSED(ntree), bNode *n
node->storage = data;
}
-static void geo_node_subdivision_surface_exec(GeoNodeExecParams params)
+static void node_geo_exec(GeoNodeExecParams params)
{
GeometrySet geometry_set = params.extract_input<GeometrySet>("Mesh");
#ifndef WITH_OPENSUBDIV
@@ -145,18 +143,20 @@ static void geo_node_subdivision_surface_exec(GeoNodeExecParams params)
params.set_output("Mesh", std::move(geometry_set));
}
-} // namespace blender::nodes
+} // namespace blender::nodes::node_geo_subdivision_surface_cc
void register_node_type_geo_subdivision_surface()
{
+ namespace file_ns = blender::nodes::node_geo_subdivision_surface_cc;
+
static bNodeType ntype;
geo_node_type_base(
&ntype, GEO_NODE_SUBDIVISION_SURFACE, "Subdivision Surface", NODE_CLASS_GEOMETRY, 0);
- ntype.declare = blender::nodes::geo_node_subdivision_surface_declare;
- ntype.geometry_node_execute = blender::nodes::geo_node_subdivision_surface_exec;
- ntype.draw_buttons = blender::nodes::geo_node_subdivision_surface_layout;
- node_type_init(&ntype, blender::nodes::geo_node_subdivision_surface_init);
+ ntype.declare = file_ns::node_declare;
+ ntype.geometry_node_execute = file_ns::node_geo_exec;
+ ntype.draw_buttons = file_ns::node_layout;
+ node_type_init(&ntype, file_ns::node_init);
node_type_size_preset(&ntype, NODE_SIZE_MIDDLE);
node_type_storage(&ntype,
"NodeGeometrySubdivisionSurface",
diff --git a/source/blender/nodes/geometry/nodes/node_geo_switch.cc b/source/blender/nodes/geometry/nodes/node_geo_switch.cc
index 7e07a552650..3a07af30e19 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_switch.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_switch.cc
@@ -26,9 +26,9 @@
#include "FN_multi_function_signature.hh"
-namespace blender::nodes {
+namespace blender::nodes::node_geo_switch_cc {
-static void geo_node_switch_declare(NodeDeclarationBuilder &b)
+static void node_declare(NodeDeclarationBuilder &b)
{
b.add_input<decl::Bool>(N_("Switch")).default_value(false).supports_field();
b.add_input<decl::Bool>(N_("Switch"), "Switch_001").default_value(false);
@@ -83,19 +83,19 @@ static void geo_node_switch_declare(NodeDeclarationBuilder &b)
b.add_output<decl::Image>(N_("Output"), "Output_011");
}
-static void geo_node_switch_layout(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
+static void node_layout(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
{
uiItemR(layout, ptr, "input_type", 0, "", ICON_NONE);
}
-static void geo_node_switch_init(bNodeTree *UNUSED(tree), bNode *node)
+static void node_init(bNodeTree *UNUSED(tree), bNode *node)
{
NodeSwitch *data = (NodeSwitch *)MEM_callocN(sizeof(NodeSwitch), __func__);
data->input_type = SOCK_GEOMETRY;
node->storage = data;
}
-static void geo_node_switch_update(bNodeTree *UNUSED(ntree), bNode *node)
+static void node_update(bNodeTree *ntree, bNode *node)
{
NodeSwitch *node_storage = (NodeSwitch *)node->storage;
int index = 0;
@@ -110,20 +110,20 @@ static void geo_node_switch_update(bNodeTree *UNUSED(ntree), bNode *node)
SOCK_RGBA,
SOCK_STRING);
- nodeSetSocketAvailability(field_switch, fields_type);
- nodeSetSocketAvailability(non_field_switch, !fields_type);
+ nodeSetSocketAvailability(ntree, field_switch, fields_type);
+ nodeSetSocketAvailability(ntree, non_field_switch, !fields_type);
LISTBASE_FOREACH_INDEX (bNodeSocket *, socket, &node->inputs, index) {
if (index <= 1) {
continue;
}
- nodeSetSocketAvailability(socket,
- socket->type == (eNodeSocketDatatype)node_storage->input_type);
+ nodeSetSocketAvailability(
+ ntree, socket, socket->type == (eNodeSocketDatatype)node_storage->input_type);
}
LISTBASE_FOREACH (bNodeSocket *, socket, &node->outputs) {
- nodeSetSocketAvailability(socket,
- socket->type == (eNodeSocketDatatype)node_storage->input_type);
+ nodeSetSocketAvailability(
+ ntree, socket, socket->type == (eNodeSocketDatatype)node_storage->input_type);
}
}
@@ -232,7 +232,7 @@ template<typename T> void switch_no_fields(GeoNodeExecParams &params, const Stri
}
}
-static void geo_node_switch_exec(GeoNodeExecParams params)
+static void node_geo_exec(GeoNodeExecParams params)
{
const NodeSwitch &storage = *(const NodeSwitch *)params.node().storage;
const eNodeSocketDatatype data_type = static_cast<eNodeSocketDatatype>(storage.input_type);
@@ -293,19 +293,21 @@ static void geo_node_switch_exec(GeoNodeExecParams params)
}
}
-} // namespace blender::nodes
+} // namespace blender::nodes::node_geo_switch_cc
void register_node_type_geo_switch()
{
+ namespace file_ns = blender::nodes::node_geo_switch_cc;
+
static bNodeType ntype;
geo_node_type_base(&ntype, GEO_NODE_SWITCH, "Switch", NODE_CLASS_CONVERTER, 0);
- ntype.declare = blender::nodes::geo_node_switch_declare;
- node_type_init(&ntype, blender::nodes::geo_node_switch_init);
- node_type_update(&ntype, blender::nodes::geo_node_switch_update);
+ ntype.declare = file_ns::node_declare;
+ node_type_init(&ntype, file_ns::node_init);
+ node_type_update(&ntype, file_ns::node_update);
node_type_storage(&ntype, "NodeSwitch", node_free_standard_storage, node_copy_standard_storage);
- ntype.geometry_node_execute = blender::nodes::geo_node_switch_exec;
+ ntype.geometry_node_execute = file_ns::node_geo_exec;
ntype.geometry_node_execute_supports_laziness = true;
- ntype.draw_buttons = blender::nodes::geo_node_switch_layout;
+ ntype.draw_buttons = file_ns::node_layout;
nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/geometry/nodes/node_geo_transfer_attribute.cc b/source/blender/nodes/geometry/nodes/node_geo_transfer_attribute.cc
index 9754b3f81a0..acd8e6cad25 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_transfer_attribute.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_transfer_attribute.cc
@@ -33,17 +33,18 @@
#include "node_geometry_util.hh"
+namespace blender::nodes::node_geo_transfer_attribute_cc {
+
using namespace blender::bke::mesh_surface_sample;
using blender::fn::GArray;
-namespace blender::nodes {
-
-static void geo_node_transfer_attribute_declare(NodeDeclarationBuilder &b)
+static void node_declare(NodeDeclarationBuilder &b)
{
b.add_input<decl::Geometry>(N_("Target"))
- .only_realized_data()
- .supported_type(
- {GEO_COMPONENT_TYPE_MESH, GEO_COMPONENT_TYPE_POINT_CLOUD, GEO_COMPONENT_TYPE_CURVE});
+ .supported_type({GEO_COMPONENT_TYPE_MESH,
+ GEO_COMPONENT_TYPE_POINT_CLOUD,
+ GEO_COMPONENT_TYPE_CURVE,
+ GEO_COMPONENT_TYPE_INSTANCES});
b.add_input<decl::Vector>(N_("Attribute")).hide_value().supports_field();
b.add_input<decl::Float>(N_("Attribute"), "Attribute_001").hide_value().supports_field();
@@ -61,9 +62,7 @@ static void geo_node_transfer_attribute_declare(NodeDeclarationBuilder &b)
b.add_output<decl::Int>(N_("Attribute"), "Attribute_004").dependent_field({6, 7});
}
-static void geo_node_transfer_attribute_layout(uiLayout *layout,
- bContext *UNUSED(C),
- PointerRNA *ptr)
+static void node_layout(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
{
const bNode &node = *static_cast<const bNode *>(ptr->data);
const NodeGeometryTransferAttribute &data = *static_cast<const NodeGeometryTransferAttribute *>(
@@ -77,7 +76,7 @@ static void geo_node_transfer_attribute_layout(uiLayout *layout,
}
}
-static void geo_node_transfer_attribute_init(bNodeTree *UNUSED(tree), bNode *node)
+static void node_init(bNodeTree *UNUSED(tree), bNode *node)
{
NodeGeometryTransferAttribute *data = (NodeGeometryTransferAttribute *)MEM_callocN(
sizeof(NodeGeometryTransferAttribute), __func__);
@@ -86,7 +85,7 @@ static void geo_node_transfer_attribute_init(bNodeTree *UNUSED(tree), bNode *nod
node->storage = data;
}
-static void geo_node_transfer_attribute_update(bNodeTree *UNUSED(ntree), bNode *node)
+static void node_update(bNodeTree *ntree, bNode *node)
{
const NodeGeometryTransferAttribute &data = *(const NodeGeometryTransferAttribute *)
node->storage;
@@ -103,14 +102,14 @@ static void geo_node_transfer_attribute_update(bNodeTree *UNUSED(ntree), bNode *
bNodeSocket *socket_positions = socket_int32->next;
bNodeSocket *socket_indices = socket_positions->next;
- nodeSetSocketAvailability(socket_vector, data_type == CD_PROP_FLOAT3);
- nodeSetSocketAvailability(socket_float, data_type == CD_PROP_FLOAT);
- nodeSetSocketAvailability(socket_color4f, data_type == CD_PROP_COLOR);
- nodeSetSocketAvailability(socket_boolean, data_type == CD_PROP_BOOL);
- nodeSetSocketAvailability(socket_int32, data_type == CD_PROP_INT32);
+ nodeSetSocketAvailability(ntree, socket_vector, data_type == CD_PROP_FLOAT3);
+ nodeSetSocketAvailability(ntree, socket_float, data_type == CD_PROP_FLOAT);
+ nodeSetSocketAvailability(ntree, socket_color4f, data_type == CD_PROP_COLOR);
+ nodeSetSocketAvailability(ntree, socket_boolean, data_type == CD_PROP_BOOL);
+ nodeSetSocketAvailability(ntree, socket_int32, data_type == CD_PROP_INT32);
- nodeSetSocketAvailability(socket_positions, mapping != GEO_NODE_ATTRIBUTE_TRANSFER_INDEX);
- nodeSetSocketAvailability(socket_indices, mapping == GEO_NODE_ATTRIBUTE_TRANSFER_INDEX);
+ nodeSetSocketAvailability(ntree, socket_positions, mapping != GEO_NODE_ATTRIBUTE_TRANSFER_INDEX);
+ nodeSetSocketAvailability(ntree, socket_indices, mapping == GEO_NODE_ATTRIBUTE_TRANSFER_INDEX);
bNodeSocket *out_socket_vector = (bNodeSocket *)node->outputs.first;
bNodeSocket *out_socket_float = out_socket_vector->next;
@@ -118,11 +117,11 @@ static void geo_node_transfer_attribute_update(bNodeTree *UNUSED(ntree), bNode *
bNodeSocket *out_socket_boolean = out_socket_color4f->next;
bNodeSocket *out_socket_int32 = out_socket_boolean->next;
- nodeSetSocketAvailability(out_socket_vector, data_type == CD_PROP_FLOAT3);
- nodeSetSocketAvailability(out_socket_float, data_type == CD_PROP_FLOAT);
- nodeSetSocketAvailability(out_socket_color4f, data_type == CD_PROP_COLOR);
- nodeSetSocketAvailability(out_socket_boolean, data_type == CD_PROP_BOOL);
- nodeSetSocketAvailability(out_socket_int32, data_type == CD_PROP_INT32);
+ nodeSetSocketAvailability(ntree, out_socket_vector, data_type == CD_PROP_FLOAT3);
+ nodeSetSocketAvailability(ntree, out_socket_float, data_type == CD_PROP_FLOAT);
+ nodeSetSocketAvailability(ntree, out_socket_color4f, data_type == CD_PROP_COLOR);
+ nodeSetSocketAvailability(ntree, out_socket_boolean, data_type == CD_PROP_BOOL);
+ nodeSetSocketAvailability(ntree, out_socket_int32, data_type == CD_PROP_INT32);
}
static void get_closest_in_bvhtree(BVHTreeFromMesh &tree_data,
@@ -541,10 +540,10 @@ class NearestTransferFunction : public fn::MultiFunction {
attribute_math::convert_to_static_type(dst.type(), [&](auto dummy) {
using T = decltype(dummy);
if (use_mesh_ && use_points_) {
- GVArray_Typed<T> src_mesh{*mesh_data_};
- GVArray_Typed<T> src_point{*point_data_};
- copy_with_indices_and_comparison(*src_mesh,
- *src_point,
+ VArray<T> src_mesh = mesh_data_->typed<T>();
+ VArray<T> src_point = point_data_->typed<T>();
+ copy_with_indices_and_comparison(src_mesh,
+ src_point,
mesh_distances,
point_distances,
mask,
@@ -553,12 +552,12 @@ class NearestTransferFunction : public fn::MultiFunction {
dst.typed<T>());
}
else if (use_points_) {
- GVArray_Typed<T> src_point{*point_data_};
- copy_with_indices(*src_point, mask, point_indices, dst.typed<T>());
+ VArray<T> src_point = point_data_->typed<T>();
+ copy_with_indices(src_point, mask, point_indices, dst.typed<T>());
}
else if (use_mesh_) {
- GVArray_Typed<T> src_mesh{*mesh_data_};
- copy_with_indices(*src_mesh, mask, mesh_indices, dst.typed<T>());
+ VArray<T> src_mesh = mesh_data_->typed<T>();
+ copy_with_indices(src_mesh, mask, mesh_indices, dst.typed<T>());
}
});
}
@@ -593,8 +592,10 @@ static const GeometryComponent *find_target_component(const GeometrySet &geometr
{
/* Choose the other component based on a consistent order, rather than some more complicated
* heuristic. This is the same order visible in the spreadsheet and used in the ray-cast node. */
- static const Array<GeometryComponentType> supported_types = {
- GEO_COMPONENT_TYPE_MESH, GEO_COMPONENT_TYPE_POINT_CLOUD, GEO_COMPONENT_TYPE_CURVE};
+ static const Array<GeometryComponentType> supported_types = {GEO_COMPONENT_TYPE_MESH,
+ GEO_COMPONENT_TYPE_POINT_CLOUD,
+ GEO_COMPONENT_TYPE_CURVE,
+ GEO_COMPONENT_TYPE_INSTANCES};
for (const GeometryComponentType src_type : supported_types) {
if (component_is_available(geometry, src_type, domain)) {
return geometry.get_component_for_read(src_type);
@@ -667,8 +668,7 @@ class IndexTransferFunction : public fn::MultiFunction {
attribute_math::convert_to_static_type(type, [&](auto dummy) {
using T = decltype(dummy);
- GVArray_Typed<T> src{*src_data_};
- copy_with_indices_clamped(*src, mask, indices, dst.typed<T>());
+ copy_with_indices_clamped(src_data_->typed<T>(), mask, indices, dst.typed<T>());
});
}
};
@@ -720,7 +720,7 @@ static void output_attribute_field(GeoNodeExecParams &params, GField field)
}
}
-static void geo_node_transfer_attribute_exec(GeoNodeExecParams params)
+static void node_geo_exec(GeoNodeExecParams params)
{
GeometrySet geometry = params.extract_input<GeometrySet>("Target");
const bNode &node = params.node();
@@ -738,10 +738,6 @@ static void geo_node_transfer_attribute_exec(GeoNodeExecParams params)
});
};
- /* Since the instances are not used, there is no point in keeping
- * a reference to them while the field is passed around. */
- geometry.remove(GEO_COMPONENT_TYPE_INSTANCES);
-
GField output_field;
switch (mapping) {
case GEO_NODE_ATTRIBUTE_TRANSFER_NEAREST_FACE_INTERPOLATED: {
@@ -795,22 +791,24 @@ static void geo_node_transfer_attribute_exec(GeoNodeExecParams params)
output_attribute_field(params, std::move(output_field));
}
-} // namespace blender::nodes
+} // namespace blender::nodes::node_geo_transfer_attribute_cc
void register_node_type_geo_transfer_attribute()
{
+ namespace file_ns = blender::nodes::node_geo_transfer_attribute_cc;
+
static bNodeType ntype;
geo_node_type_base(
&ntype, GEO_NODE_TRANSFER_ATTRIBUTE, "Transfer Attribute", NODE_CLASS_ATTRIBUTE, 0);
- node_type_init(&ntype, blender::nodes::geo_node_transfer_attribute_init);
- node_type_update(&ntype, blender::nodes::geo_node_transfer_attribute_update);
+ node_type_init(&ntype, file_ns::node_init);
+ node_type_update(&ntype, file_ns::node_update);
node_type_storage(&ntype,
"NodeGeometryTransferAttribute",
node_free_standard_storage,
node_copy_standard_storage);
- ntype.declare = blender::nodes::geo_node_transfer_attribute_declare;
- ntype.geometry_node_execute = blender::nodes::geo_node_transfer_attribute_exec;
- ntype.draw_buttons = blender::nodes::geo_node_transfer_attribute_layout;
+ ntype.declare = file_ns::node_declare;
+ ntype.geometry_node_execute = file_ns::node_geo_exec;
+ ntype.draw_buttons = file_ns::node_layout;
nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/geometry/nodes/node_geo_transform.cc b/source/blender/nodes/geometry/nodes/node_geo_transform.cc
index 2c55a255b5d..8322de20d20 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_transform.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_transform.cc
@@ -35,15 +35,6 @@
namespace blender::nodes {
-static void geo_node_transform_declare(NodeDeclarationBuilder &b)
-{
- b.add_input<decl::Geometry>(N_("Geometry"));
- b.add_input<decl::Vector>(N_("Translation")).subtype(PROP_TRANSLATION);
- b.add_input<decl::Vector>(N_("Rotation")).subtype(PROP_EULER);
- b.add_input<decl::Vector>(N_("Scale")).default_value({1, 1, 1}).subtype(PROP_XYZ);
- b.add_output<decl::Geometry>(N_("Geometry"));
-}
-
static bool use_translate(const float3 rotation, const float3 scale)
{
if (compare_ff(rotation.length_squared(), 0.0f, 1e-9f) != 1) {
@@ -69,15 +60,6 @@ static void transform_mesh(Mesh &mesh, const float4x4 &transform)
BKE_mesh_normals_tag_dirty(&mesh);
}
-void transform_mesh(Mesh &mesh,
- const float3 translation,
- const float3 rotation,
- const float3 scale)
-{
- const float4x4 matrix = float4x4::from_loc_eul_scale(translation, rotation, scale);
- transform_mesh(mesh, matrix);
-}
-
static void translate_pointcloud(PointCloud &pointcloud, const float3 translation)
{
CustomData_duplicate_referenced_layer(&pointcloud.pdata, CD_PROP_FLOAT3, pointcloud.totpoint);
@@ -153,49 +135,71 @@ static void translate_volume(Volume &volume, const float3 translation, const Dep
transform_volume(volume, float4x4::from_location(translation), depsgraph);
}
-void transform_geometry_set(GeometrySet &geometry,
- const float4x4 &transform,
- const Depsgraph &depsgraph)
+static void translate_geometry_set(GeometrySet &geometry,
+ const float3 translation,
+ const Depsgraph &depsgraph)
{
if (CurveEval *curve = geometry.get_curve_for_write()) {
- curve->transform(transform);
+ curve->translate(translation);
}
if (Mesh *mesh = geometry.get_mesh_for_write()) {
- transform_mesh(*mesh, transform);
+ translate_mesh(*mesh, translation);
}
if (PointCloud *pointcloud = geometry.get_pointcloud_for_write()) {
- transform_pointcloud(*pointcloud, transform);
+ translate_pointcloud(*pointcloud, translation);
}
if (Volume *volume = geometry.get_volume_for_write()) {
- transform_volume(*volume, transform, depsgraph);
+ translate_volume(*volume, translation, depsgraph);
}
if (geometry.has_instances()) {
- transform_instances(geometry.get_component_for_write<InstancesComponent>(), transform);
+ translate_instances(geometry.get_component_for_write<InstancesComponent>(), translation);
}
}
-static void translate_geometry_set(GeometrySet &geometry,
- const float3 translation,
- const Depsgraph &depsgraph)
+void transform_geometry_set(GeometrySet &geometry,
+ const float4x4 &transform,
+ const Depsgraph &depsgraph)
{
if (CurveEval *curve = geometry.get_curve_for_write()) {
- curve->translate(translation);
+ curve->transform(transform);
}
if (Mesh *mesh = geometry.get_mesh_for_write()) {
- translate_mesh(*mesh, translation);
+ transform_mesh(*mesh, transform);
}
if (PointCloud *pointcloud = geometry.get_pointcloud_for_write()) {
- translate_pointcloud(*pointcloud, translation);
+ transform_pointcloud(*pointcloud, transform);
}
if (Volume *volume = geometry.get_volume_for_write()) {
- translate_volume(*volume, translation, depsgraph);
+ transform_volume(*volume, transform, depsgraph);
}
if (geometry.has_instances()) {
- translate_instances(geometry.get_component_for_write<InstancesComponent>(), translation);
+ transform_instances(geometry.get_component_for_write<InstancesComponent>(), transform);
}
}
-static void geo_node_transform_exec(GeoNodeExecParams params)
+void transform_mesh(Mesh &mesh,
+ const float3 translation,
+ const float3 rotation,
+ const float3 scale)
+{
+ const float4x4 matrix = float4x4::from_loc_eul_scale(translation, rotation, scale);
+ transform_mesh(mesh, matrix);
+}
+
+} // namespace blender::nodes
+
+namespace blender::nodes::node_geo_transform_cc {
+
+static void node_declare(NodeDeclarationBuilder &b)
+{
+ b.add_input<decl::Geometry>(N_("Geometry"));
+ b.add_input<decl::Vector>(N_("Translation")).subtype(PROP_TRANSLATION);
+ b.add_input<decl::Vector>(N_("Rotation")).subtype(PROP_EULER);
+ b.add_input<decl::Vector>(N_("Scale")).default_value({1, 1, 1}).subtype(PROP_XYZ);
+ b.add_output<decl::Geometry>(N_("Geometry"));
+}
+
+static void node_geo_exec(GeoNodeExecParams params)
{
GeometrySet geometry_set = params.extract_input<GeometrySet>("Geometry");
const float3 translation = params.extract_input<float3>("Translation");
@@ -214,14 +218,16 @@ static void geo_node_transform_exec(GeoNodeExecParams params)
params.set_output("Geometry", std::move(geometry_set));
}
-} // namespace blender::nodes
+} // namespace blender::nodes::node_geo_transform_cc
void register_node_type_geo_transform()
{
+ namespace file_ns = blender::nodes::node_geo_transform_cc;
+
static bNodeType ntype;
geo_node_type_base(&ntype, GEO_NODE_TRANSFORM, "Transform", NODE_CLASS_GEOMETRY, 0);
- ntype.declare = blender::nodes::geo_node_transform_declare;
- ntype.geometry_node_execute = blender::nodes::geo_node_transform_exec;
+ ntype.declare = file_ns::node_declare;
+ ntype.geometry_node_execute = file_ns::node_geo_exec;
nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/geometry/nodes/node_geo_translate_instances.cc b/source/blender/nodes/geometry/nodes/node_geo_translate_instances.cc
index fa05d858a07..8ef80323f99 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_translate_instances.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_translate_instances.cc
@@ -18,9 +18,9 @@
#include "node_geometry_util.hh"
-namespace blender::nodes {
+namespace blender::nodes::node_geo_translate_instances_cc {
-static void geo_node_translate_instances_declare(NodeDeclarationBuilder &b)
+static void node_declare(NodeDeclarationBuilder &b)
{
b.add_input<decl::Geometry>(N_("Instances")).only_instances();
b.add_input<decl::Bool>(N_("Selection")).default_value(true).hide_value().supports_field();
@@ -31,7 +31,7 @@ static void geo_node_translate_instances_declare(NodeDeclarationBuilder &b)
static void translate_instances(GeoNodeExecParams &params, InstancesComponent &instances_component)
{
- GeometryComponentFieldContext field_context{instances_component, ATTR_DOMAIN_POINT};
+ GeometryComponentFieldContext field_context{instances_component, ATTR_DOMAIN_INSTANCE};
fn::FieldEvaluator selection_evaluator{field_context, instances_component.instances_amount()};
selection_evaluator.add(params.extract_input<Field<bool>>("Selection"));
@@ -60,7 +60,7 @@ static void translate_instances(GeoNodeExecParams &params, InstancesComponent &i
});
}
-static void geo_node_translate_instances_exec(GeoNodeExecParams params)
+static void node_geo_exec(GeoNodeExecParams params)
{
GeometrySet geometry_set = params.extract_input<GeometrySet>("Instances");
if (geometry_set.has_instances()) {
@@ -70,15 +70,17 @@ static void geo_node_translate_instances_exec(GeoNodeExecParams params)
params.set_output("Instances", std::move(geometry_set));
}
-} // namespace blender::nodes
+} // namespace blender::nodes::node_geo_translate_instances_cc
void register_node_type_geo_translate_instances()
{
+ namespace file_ns = blender::nodes::node_geo_translate_instances_cc;
+
static bNodeType ntype;
geo_node_type_base(
&ntype, GEO_NODE_TRANSLATE_INSTANCES, "Translate Instances", NODE_CLASS_GEOMETRY, 0);
- ntype.geometry_node_execute = blender::nodes::geo_node_translate_instances_exec;
- ntype.declare = blender::nodes::geo_node_translate_instances_declare;
+ ntype.geometry_node_execute = file_ns::node_geo_exec;
+ ntype.declare = file_ns::node_declare;
nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/geometry/nodes/node_geo_triangulate.cc b/source/blender/nodes/geometry/nodes/node_geo_triangulate.cc
index c869846e1f8..f8deaaa4a14 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_triangulate.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_triangulate.cc
@@ -27,16 +27,16 @@ Mesh *triangulate_mesh(Mesh *mesh,
const int flag);
}
-namespace blender::nodes {
+namespace blender::nodes::node_geo_triangulate_cc {
-static void geo_node_triangulate_declare(NodeDeclarationBuilder &b)
+static void node_declare(NodeDeclarationBuilder &b)
{
b.add_input<decl::Geometry>(N_("Mesh")).supported_type(GEO_COMPONENT_TYPE_MESH);
b.add_input<decl::Int>(N_("Minimum Vertices")).default_value(4).min(4).max(10000);
b.add_output<decl::Geometry>(N_("Mesh"));
}
-static void geo_node_triangulate_layout(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
+static void node_layout(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
{
uiItemR(layout, ptr, "quad_method", 0, "", ICON_NONE);
uiItemR(layout, ptr, "ngon_method", 0, "", ICON_NONE);
@@ -48,7 +48,7 @@ static void geo_triangulate_init(bNodeTree *UNUSED(ntree), bNode *node)
node->custom2 = GEO_NODE_TRIANGULATE_NGON_BEAUTY;
}
-static void geo_node_triangulate_exec(GeoNodeExecParams params)
+static void node_geo_exec(GeoNodeExecParams params)
{
GeometrySet geometry_set = params.extract_input<GeometrySet>("Mesh");
const int min_vertices = std::max(params.extract_input<int>("Minimum Vertices"), 4);
@@ -69,16 +69,18 @@ static void geo_node_triangulate_exec(GeoNodeExecParams params)
params.set_output("Mesh", std::move(geometry_set));
}
-} // namespace blender::nodes
+} // namespace blender::nodes::node_geo_triangulate_cc
void register_node_type_geo_triangulate()
{
+ namespace file_ns = blender::nodes::node_geo_triangulate_cc;
+
static bNodeType ntype;
geo_node_type_base(&ntype, GEO_NODE_TRIANGULATE, "Triangulate", NODE_CLASS_GEOMETRY, 0);
- ntype.declare = blender::nodes::geo_node_triangulate_declare;
- node_type_init(&ntype, blender::nodes::geo_triangulate_init);
- ntype.geometry_node_execute = blender::nodes::geo_node_triangulate_exec;
- ntype.draw_buttons = blender::nodes::geo_node_triangulate_layout;
+ ntype.declare = file_ns::node_declare;
+ node_type_init(&ntype, file_ns::geo_triangulate_init);
+ ntype.geometry_node_execute = file_ns::node_geo_exec;
+ ntype.draw_buttons = file_ns::node_layout;
nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/geometry/nodes/node_geo_viewer.cc b/source/blender/nodes/geometry/nodes/node_geo_viewer.cc
index 194d1a751ed..accbcc74174 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_viewer.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_viewer.cc
@@ -19,8 +19,9 @@
#include "node_geometry_util.hh"
-namespace blender::nodes {
-static void geo_node_viewer_declare(NodeDeclarationBuilder &b)
+namespace blender::nodes::node_geo_viewer_cc {
+
+static void node_declare(NodeDeclarationBuilder &b)
{
b.add_input<decl::Geometry>(N_("Geometry"));
b.add_input<decl::Float>(N_("Value")).supports_field().hide_value();
@@ -30,7 +31,7 @@ static void geo_node_viewer_declare(NodeDeclarationBuilder &b)
b.add_input<decl::Bool>(N_("Value"), "Value_004").supports_field().hide_value();
}
-static void geo_node_viewer_init(bNodeTree *UNUSED(tree), bNode *node)
+static void node_init(bNodeTree *UNUSED(tree), bNode *node)
{
NodeGeometryViewer *data = (NodeGeometryViewer *)MEM_callocN(sizeof(NodeGeometryViewer),
__func__);
@@ -39,7 +40,7 @@ static void geo_node_viewer_init(bNodeTree *UNUSED(tree), bNode *node)
node->storage = data;
}
-static void geo_node_viewer_layout(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
+static void node_layout(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
{
uiItemR(layout, ptr, "data_type", 0, "", ICON_NONE);
}
@@ -63,7 +64,7 @@ static eNodeSocketDatatype custom_data_type_to_socket_type(const CustomDataType
}
}
-static void geo_node_viewer_update(bNodeTree *UNUSED(ntree), bNode *node)
+static void node_update(bNodeTree *ntree, bNode *node)
{
const NodeGeometryViewer &storage = *(const NodeGeometryViewer *)node->storage;
const CustomDataType data_type = static_cast<CustomDataType>(storage.data_type);
@@ -73,22 +74,24 @@ static void geo_node_viewer_update(bNodeTree *UNUSED(ntree), bNode *node)
if (socket->type == SOCK_GEOMETRY) {
continue;
}
- nodeSetSocketAvailability(socket, socket->type == socket_type);
+ nodeSetSocketAvailability(ntree, socket, socket->type == socket_type);
}
}
-} // namespace blender::nodes
+} // namespace blender::nodes::node_geo_viewer_cc
void register_node_type_geo_viewer()
{
+ namespace file_ns = blender::nodes::node_geo_viewer_cc;
+
static bNodeType ntype;
geo_node_type_base(&ntype, GEO_NODE_VIEWER, "Viewer", NODE_CLASS_OUTPUT, 0);
node_type_storage(
&ntype, "NodeGeometryViewer", node_free_standard_storage, node_copy_standard_storage);
- node_type_update(&ntype, blender::nodes::geo_node_viewer_update);
- node_type_init(&ntype, blender::nodes::geo_node_viewer_init);
- ntype.declare = blender::nodes::geo_node_viewer_declare;
- ntype.draw_buttons_ex = blender::nodes::geo_node_viewer_layout;
+ node_type_update(&ntype, file_ns::node_update);
+ node_type_init(&ntype, file_ns::node_init);
+ ntype.declare = file_ns::node_declare;
+ ntype.draw_buttons_ex = file_ns::node_layout;
nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/geometry/nodes/node_geo_volume_to_mesh.cc b/source/blender/nodes/geometry/nodes/node_geo_volume_to_mesh.cc
index 416d502dc59..12a7435d8be 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_volume_to_mesh.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_volume_to_mesh.cc
@@ -35,9 +35,9 @@
#include "UI_interface.h"
#include "UI_resources.h"
-namespace blender::nodes {
+namespace blender::nodes::node_geo_volume_to_mesh_cc {
-static void geo_node_volume_to_mesh_declare(NodeDeclarationBuilder &b)
+static void node_declare(NodeDeclarationBuilder &b)
{
b.add_input<decl::Geometry>(N_("Volume")).supported_type(GEO_COMPONENT_TYPE_VOLUME);
b.add_input<decl::Float>(N_("Voxel Size")).default_value(0.3f).min(0.01f).subtype(PROP_DISTANCE);
@@ -47,14 +47,14 @@ static void geo_node_volume_to_mesh_declare(NodeDeclarationBuilder &b)
b.add_output<decl::Geometry>(N_("Mesh"));
}
-static void geo_node_volume_to_mesh_layout(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
+static void node_layout(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
{
uiLayoutSetPropSep(layout, true);
uiLayoutSetPropDecorate(layout, false);
uiItemR(layout, ptr, "resolution_mode", 0, IFACE_("Resolution"), ICON_NONE);
}
-static void geo_node_volume_to_mesh_init(bNodeTree *UNUSED(ntree), bNode *node)
+static void node_init(bNodeTree *UNUSED(ntree), bNode *node)
{
NodeGeometryVolumeToMesh *data = (NodeGeometryVolumeToMesh *)MEM_callocN(
sizeof(NodeGeometryVolumeToMesh), __func__);
@@ -62,15 +62,17 @@ static void geo_node_volume_to_mesh_init(bNodeTree *UNUSED(ntree), bNode *node)
node->storage = data;
}
-static void geo_node_volume_to_mesh_update(bNodeTree *UNUSED(ntree), bNode *node)
+static void node_update(bNodeTree *ntree, bNode *node)
{
NodeGeometryVolumeToMesh *data = (NodeGeometryVolumeToMesh *)node->storage;
bNodeSocket *voxel_size_socket = nodeFindSocket(node, SOCK_IN, "Voxel Size");
bNodeSocket *voxel_amount_socket = nodeFindSocket(node, SOCK_IN, "Voxel Amount");
- nodeSetSocketAvailability(voxel_amount_socket,
+ nodeSetSocketAvailability(ntree,
+ voxel_amount_socket,
data->resolution_mode == VOLUME_TO_MESH_RESOLUTION_MODE_VOXEL_AMOUNT);
- nodeSetSocketAvailability(voxel_size_socket,
+ nodeSetSocketAvailability(ntree,
+ voxel_size_socket,
data->resolution_mode == VOLUME_TO_MESH_RESOLUTION_MODE_VOXEL_SIZE);
}
@@ -174,7 +176,7 @@ static Mesh *create_mesh_from_volume(GeometrySet &geometry_set, GeoNodeExecParam
#endif /* WITH_OPENVDB */
-static void geo_node_volume_to_mesh_exec(GeoNodeExecParams params)
+static void node_geo_exec(GeoNodeExecParams params)
{
GeometrySet geometry_set = params.extract_input<GeometrySet>("Volume");
@@ -192,20 +194,22 @@ static void geo_node_volume_to_mesh_exec(GeoNodeExecParams params)
params.set_output("Mesh", std::move(geometry_set));
}
-} // namespace blender::nodes
+} // namespace blender::nodes::node_geo_volume_to_mesh_cc
void register_node_type_geo_volume_to_mesh()
{
+ namespace file_ns = blender::nodes::node_geo_volume_to_mesh_cc;
+
static bNodeType ntype;
geo_node_type_base(&ntype, GEO_NODE_VOLUME_TO_MESH, "Volume to Mesh", NODE_CLASS_GEOMETRY, 0);
- ntype.declare = blender::nodes::geo_node_volume_to_mesh_declare;
+ ntype.declare = file_ns::node_declare;
node_type_storage(
&ntype, "NodeGeometryVolumeToMesh", node_free_standard_storage, node_copy_standard_storage);
node_type_size(&ntype, 170, 120, 700);
- node_type_init(&ntype, blender::nodes::geo_node_volume_to_mesh_init);
- node_type_update(&ntype, blender::nodes::geo_node_volume_to_mesh_update);
- ntype.geometry_node_execute = blender::nodes::geo_node_volume_to_mesh_exec;
- ntype.draw_buttons = blender::nodes::geo_node_volume_to_mesh_layout;
+ node_type_init(&ntype, file_ns::node_init);
+ node_type_update(&ntype, file_ns::node_update);
+ ntype.geometry_node_execute = file_ns::node_geo_exec;
+ ntype.draw_buttons = file_ns::node_layout;
nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/intern/geometry_nodes_eval_log.cc b/source/blender/nodes/intern/geometry_nodes_eval_log.cc
index ddd3c991518..4cba9669647 100644
--- a/source/blender/nodes/intern/geometry_nodes_eval_log.cc
+++ b/source/blender/nodes/intern/geometry_nodes_eval_log.cc
@@ -25,12 +25,15 @@
#include "BLT_translation.h"
+#include <chrono>
+
namespace blender::nodes::geometry_nodes_eval_log {
using fn::CPPType;
using fn::FieldCPPType;
using fn::FieldInput;
using fn::GField;
+using fn::ValueOrFieldCPPType;
ModifierLog::ModifierLog(GeoLogger &logger)
: input_geometry_log_(std::move(logger.input_geometry_log_)),
@@ -63,6 +66,12 @@ ModifierLog::ModifierLog(GeoLogger &logger)
node_with_warning.node);
node_log.warnings_.append(node_with_warning.warning);
}
+
+ for (NodeWithExecutionTime &node_with_exec_time : local_logger.node_exec_times_) {
+ NodeLog &node_log = this->lookup_or_add_node_log(log_by_tree_context,
+ node_with_exec_time.node);
+ node_log.exec_time_ = node_with_exec_time.exec_time;
+ }
}
}
@@ -417,25 +426,38 @@ void LocalGeoLogger::log_value_for_sockets(Span<DSocket> sockets, GPointer value
geometry_set, log_full_geometry);
values_.append({copied_sockets, std::move(value_log)});
}
- else if (const FieldCPPType *field_type = dynamic_cast<const FieldCPPType *>(&type)) {
- GField field = field_type->get_gfield(value.get());
- bool log_full_field = false;
- if (!field.node().depends_on_input()) {
- /* Always log constant fields so that their value can be shown in socket inspection.
- * In the future we can also evaluate the field here and only store the value. */
- log_full_field = true;
- }
- if (!log_full_field) {
- for (const DSocket &socket : sockets) {
- if (main_logger_->log_full_sockets_.contains(socket)) {
- log_full_field = true;
- break;
+ else if (const ValueOrFieldCPPType *value_or_field_type =
+ dynamic_cast<const ValueOrFieldCPPType *>(&type)) {
+ const void *value_or_field = value.get();
+ if (value_or_field_type->is_field(value_or_field)) {
+ GField field = *value_or_field_type->get_field_ptr(value_or_field);
+ bool log_full_field = false;
+ if (!field.node().depends_on_input()) {
+ /* Always log constant fields so that their value can be shown in socket inspection.
+ * In the future we can also evaluate the field here and only store the value. */
+ log_full_field = true;
+ }
+ if (!log_full_field) {
+ for (const DSocket &socket : sockets) {
+ if (main_logger_->log_full_sockets_.contains(socket)) {
+ log_full_field = true;
+ break;
+ }
}
}
+ destruct_ptr<GFieldValueLog> value_log = allocator_->construct<GFieldValueLog>(
+ std::move(field), log_full_field);
+ values_.append({copied_sockets, std::move(value_log)});
+ }
+ else {
+ const CPPType &base_type = value_or_field_type->base_type();
+ const void *value = value_or_field_type->get_value_ptr(value_or_field);
+ void *buffer = allocator_->allocate(base_type.size(), base_type.alignment());
+ base_type.copy_construct(value, buffer);
+ destruct_ptr<GenericValueLog> value_log = allocator_->construct<GenericValueLog>(
+ GMutablePointer{base_type, buffer});
+ values_.append({copied_sockets, std::move(value_log)});
}
- destruct_ptr<GFieldValueLog> value_log = allocator_->construct<GFieldValueLog>(
- std::move(field), log_full_field);
- values_.append({copied_sockets, std::move(value_log)});
}
else {
void *buffer = allocator_->allocate(type.size(), type.alignment());
@@ -457,4 +479,9 @@ void LocalGeoLogger::log_node_warning(DNode node, NodeWarningType type, std::str
node_warnings_.append({node, {type, std::move(message)}});
}
+void LocalGeoLogger::log_execution_time(DNode node, std::chrono::microseconds exec_time)
+{
+ node_exec_times_.append({node, exec_time});
+}
+
} // namespace blender::nodes::geometry_nodes_eval_log
diff --git a/source/blender/nodes/intern/node_common.cc b/source/blender/nodes/intern/node_common.cc
index e5ec50858d9..b80cedc9352 100644
--- a/source/blender/nodes/intern/node_common.cc
+++ b/source/blender/nodes/intern/node_common.cc
@@ -251,26 +251,6 @@ void register_node_type_frame(void)
/** \name Node Re-Route
* \{ */
-/* simple, only a single input and output here */
-static void node_reroute_update_internal_links(bNodeTree *ntree, bNode *node)
-{
- bNodeLink *link;
-
- /* Security check! */
- if (!ntree) {
- return;
- }
-
- link = (bNodeLink *)MEM_callocN(sizeof(bNodeLink), "internal node link");
- link->fromnode = node;
- link->fromsock = (bNodeSocket *)node->inputs.first;
- link->tonode = node;
- link->tosock = (bNodeSocket *)node->outputs.first;
- /* internal link is always valid */
- link->flag |= NODE_LINK_VALID;
- BLI_addtail(&node->internal_links, link);
-}
-
static void node_reroute_init(bNodeTree *ntree, bNode *node)
{
/* NOTE: Cannot use socket templates for this, since it would reset the socket type
@@ -288,7 +268,6 @@ void register_node_type_reroute(void)
node_type_base(ntype, NODE_REROUTE, "Reroute", NODE_CLASS_LAYOUT, 0);
node_type_init(ntype, node_reroute_init);
- node_type_internal_links(ntype, node_reroute_update_internal_links);
nodeRegisterType(ntype);
}
diff --git a/source/blender/nodes/intern/node_declaration.cc b/source/blender/nodes/intern/node_declaration.cc
index 8a38b68ec59..e804d10ad75 100644
--- a/source/blender/nodes/intern/node_declaration.cc
+++ b/source/blender/nodes/intern/node_declaration.cc
@@ -20,16 +20,6 @@
namespace blender::nodes {
-void NodeDeclaration::build(bNodeTree &ntree, bNode &node) const
-{
- for (const SocketDeclarationPtr &decl : inputs_) {
- decl->build(ntree, node, SOCK_IN);
- }
- for (const SocketDeclarationPtr &decl : outputs_) {
- decl->build(ntree, node, SOCK_OUT);
- }
-}
-
bool NodeDeclaration::matches(const bNode &node) const
{
auto check_sockets = [&](ListBase sockets, Span<SocketDeclarationPtr> socket_decls) {
diff --git a/source/blender/nodes/intern/node_geometry_exec.cc b/source/blender/nodes/intern/node_geometry_exec.cc
index c7a3e795c33..f54ef25d4d6 100644
--- a/source/blender/nodes/intern/node_geometry_exec.cc
+++ b/source/blender/nodes/intern/node_geometry_exec.cc
@@ -39,8 +39,8 @@ void GeoNodeExecParams::error_message_add(const NodeWarningType type, std::strin
void GeoNodeExecParams::check_input_geometry_set(StringRef identifier,
const GeometrySet &geometry_set) const
{
- const int input_index = provider_->dnode->input_by_identifier(identifier).index();
- const SocketDeclaration &decl = *provider_->dnode->declaration()->inputs()[input_index];
+ const SocketDeclaration &decl =
+ *provider_->dnode->input_by_identifier(identifier).bsocket()->declaration;
const decl::Geometry *geo_decl = dynamic_cast<const decl::Geometry *>(&decl);
if (geo_decl == nullptr) {
return;
@@ -113,11 +113,11 @@ const bNodeSocket *GeoNodeExecParams::find_available_socket(const StringRef name
return nullptr;
}
-GVArrayPtr GeoNodeExecParams::get_input_attribute(const StringRef name,
- const GeometryComponent &component,
- const AttributeDomain domain,
- const CustomDataType type,
- const void *default_value) const
+GVArray GeoNodeExecParams::get_input_attribute(const StringRef name,
+ const GeometryComponent &component,
+ const AttributeDomain domain,
+ const CustomDataType type,
+ const void *default_value) const
{
const bNodeSocket *found_socket = this->find_available_socket(name);
BLI_assert(found_socket != nullptr); /* There should always be available socket for the name. */
@@ -129,13 +129,13 @@ GVArrayPtr GeoNodeExecParams::get_input_attribute(const StringRef name,
}
if (found_socket == nullptr) {
- return std::make_unique<fn::GVArray_For_SingleValue>(*cpp_type, domain_size, default_value);
+ return GVArray::ForSingle(*cpp_type, domain_size, default_value);
}
if (found_socket->type == SOCK_STRING) {
const std::string name = this->get_input<std::string>(found_socket->identifier);
/* Try getting the attribute without the default value. */
- GVArrayPtr attribute = component.attribute_try_get_for_read(name, domain, type);
+ GVArray attribute = component.attribute_try_get_for_read(name, domain, type);
if (attribute) {
return attribute;
}
@@ -147,36 +147,36 @@ GVArrayPtr GeoNodeExecParams::get_input_attribute(const StringRef name,
this->error_message_add(NodeWarningType::Error,
TIP_("No attribute with name \"") + name + "\"");
}
- return std::make_unique<fn::GVArray_For_SingleValue>(*cpp_type, domain_size, default_value);
+ return GVArray::ForSingle(*cpp_type, domain_size, default_value);
}
const DataTypeConversions &conversions = get_implicit_type_conversions();
if (found_socket->type == SOCK_FLOAT) {
const float value = this->get_input<float>(found_socket->identifier);
BUFFER_FOR_CPP_TYPE_VALUE(*cpp_type, buffer);
conversions.convert_to_uninitialized(CPPType::get<float>(), *cpp_type, &value, buffer);
- return std::make_unique<fn::GVArray_For_SingleValue>(*cpp_type, domain_size, buffer);
+ return GVArray::ForSingle(*cpp_type, domain_size, buffer);
}
if (found_socket->type == SOCK_INT) {
const int value = this->get_input<int>(found_socket->identifier);
BUFFER_FOR_CPP_TYPE_VALUE(*cpp_type, buffer);
conversions.convert_to_uninitialized(CPPType::get<int>(), *cpp_type, &value, buffer);
- return std::make_unique<fn::GVArray_For_SingleValue>(*cpp_type, domain_size, buffer);
+ return GVArray::ForSingle(*cpp_type, domain_size, buffer);
}
if (found_socket->type == SOCK_VECTOR) {
const float3 value = this->get_input<float3>(found_socket->identifier);
BUFFER_FOR_CPP_TYPE_VALUE(*cpp_type, buffer);
conversions.convert_to_uninitialized(CPPType::get<float3>(), *cpp_type, &value, buffer);
- return std::make_unique<fn::GVArray_For_SingleValue>(*cpp_type, domain_size, buffer);
+ return GVArray::ForSingle(*cpp_type, domain_size, buffer);
}
if (found_socket->type == SOCK_RGBA) {
const ColorGeometry4f value = this->get_input<ColorGeometry4f>(found_socket->identifier);
BUFFER_FOR_CPP_TYPE_VALUE(*cpp_type, buffer);
conversions.convert_to_uninitialized(
CPPType::get<ColorGeometry4f>(), *cpp_type, &value, buffer);
- return std::make_unique<fn::GVArray_For_SingleValue>(*cpp_type, domain_size, buffer);
+ return GVArray::ForSingle(*cpp_type, domain_size, buffer);
}
BLI_assert(false);
- return std::make_unique<fn::GVArray_For_SingleValue>(*cpp_type, domain_size, default_value);
+ return GVArray::ForSingle(*cpp_type, domain_size, default_value);
}
CustomDataType GeoNodeExecParams::get_input_attribute_data_type(
@@ -288,7 +288,7 @@ void GeoNodeExecParams::check_input_access(StringRef identifier,
BLI_assert_unreachable();
}
else if (requested_type != nullptr) {
- const CPPType &expected_type = *found_socket->typeinfo->get_geometry_nodes_cpp_type();
+ const CPPType &expected_type = *found_socket->typeinfo->geometry_nodes_cpp_type;
if (*requested_type != expected_type) {
std::cout << "The requested type '" << requested_type->name() << "' is incorrect. Expected '"
<< expected_type.name() << "'.\n";
@@ -328,7 +328,7 @@ void GeoNodeExecParams::check_output_access(StringRef identifier, const CPPType
BLI_assert_unreachable();
}
else {
- const CPPType &expected_type = *found_socket->typeinfo->get_geometry_nodes_cpp_type();
+ const CPPType &expected_type = *found_socket->typeinfo->geometry_nodes_cpp_type;
if (value_type != expected_type) {
std::cout << "The value type '" << value_type.name() << "' is incorrect. Expected '"
<< expected_type.name() << "'.\n";
diff --git a/source/blender/nodes/intern/node_socket.cc b/source/blender/nodes/intern/node_socket.cc
index 11356178d87..68e8f6421bd 100644
--- a/source/blender/nodes/intern/node_socket.cc
+++ b/source/blender/nodes/intern/node_socket.cc
@@ -51,6 +51,7 @@
#include "FN_field.hh"
using namespace blender;
+using blender::fn::ValueOrField;
using blender::nodes::SocketDeclarationPtr;
struct bNodeSocket *node_add_socket_from_template(struct bNodeTree *ntree,
@@ -269,10 +270,11 @@ void node_verify_sockets(bNodeTree *ntree, bNode *node, bool do_id_user)
return;
}
if (ntype->declare != nullptr) {
- nodeDeclarationEnsure(ntree, node);
+ nodeDeclarationEnsureOnOutdatedNode(ntree, node);
if (!node->declaration->matches(*node)) {
refresh_node(*ntree, *node, *node->declaration, do_id_user);
}
+ nodeSocketDeclarationsUpdate(node);
return;
}
/* Don't try to match socket lists when there are no templates.
@@ -696,17 +698,15 @@ static bNodeSocketType *make_socket_type_virtual()
static bNodeSocketType *make_socket_type_bool()
{
bNodeSocketType *socktype = make_standard_socket_type(SOCK_BOOLEAN, PROP_NONE);
- socktype->get_base_cpp_type = []() { return &blender::fn::CPPType::get<bool>(); };
+ socktype->base_cpp_type = &blender::fn::CPPType::get<bool>();
socktype->get_base_cpp_value = [](const bNodeSocket &socket, void *r_value) {
*(bool *)r_value = ((bNodeSocketValueBoolean *)socket.default_value)->value;
};
- socktype->get_geometry_nodes_cpp_type = []() {
- return &blender::fn::CPPType::get<blender::fn::Field<bool>>();
- };
+ socktype->geometry_nodes_cpp_type = &blender::fn::CPPType::get<ValueOrField<bool>>();
socktype->get_geometry_nodes_cpp_value = [](const bNodeSocket &socket, void *r_value) {
bool value;
socket.typeinfo->get_base_cpp_value(socket, &value);
- new (r_value) blender::fn::Field<bool>(blender::fn::make_constant_field(value));
+ new (r_value) ValueOrField<bool>(value);
};
return socktype;
}
@@ -714,17 +714,15 @@ static bNodeSocketType *make_socket_type_bool()
static bNodeSocketType *make_socket_type_float(PropertySubType subtype)
{
bNodeSocketType *socktype = make_standard_socket_type(SOCK_FLOAT, subtype);
- socktype->get_base_cpp_type = []() { return &blender::fn::CPPType::get<float>(); };
+ socktype->base_cpp_type = &blender::fn::CPPType::get<float>();
socktype->get_base_cpp_value = [](const bNodeSocket &socket, void *r_value) {
*(float *)r_value = ((bNodeSocketValueFloat *)socket.default_value)->value;
};
- socktype->get_geometry_nodes_cpp_type = []() {
- return &blender::fn::CPPType::get<blender::fn::Field<float>>();
- };
+ socktype->geometry_nodes_cpp_type = &blender::fn::CPPType::get<ValueOrField<float>>();
socktype->get_geometry_nodes_cpp_value = [](const bNodeSocket &socket, void *r_value) {
float value;
socket.typeinfo->get_base_cpp_value(socket, &value);
- new (r_value) blender::fn::Field<float>(blender::fn::make_constant_field(value));
+ new (r_value) ValueOrField<float>(value);
};
return socktype;
}
@@ -732,17 +730,15 @@ static bNodeSocketType *make_socket_type_float(PropertySubType subtype)
static bNodeSocketType *make_socket_type_int(PropertySubType subtype)
{
bNodeSocketType *socktype = make_standard_socket_type(SOCK_INT, subtype);
- socktype->get_base_cpp_type = []() { return &blender::fn::CPPType::get<int>(); };
+ socktype->base_cpp_type = &blender::fn::CPPType::get<int>();
socktype->get_base_cpp_value = [](const bNodeSocket &socket, void *r_value) {
*(int *)r_value = ((bNodeSocketValueInt *)socket.default_value)->value;
};
- socktype->get_geometry_nodes_cpp_type = []() {
- return &blender::fn::CPPType::get<blender::fn::Field<int>>();
- };
+ socktype->geometry_nodes_cpp_type = &blender::fn::CPPType::get<ValueOrField<int>>();
socktype->get_geometry_nodes_cpp_value = [](const bNodeSocket &socket, void *r_value) {
int value;
socket.typeinfo->get_base_cpp_value(socket, &value);
- new (r_value) blender::fn::Field<int>(blender::fn::make_constant_field(value));
+ new (r_value) ValueOrField<int>(value);
};
return socktype;
}
@@ -750,17 +746,15 @@ static bNodeSocketType *make_socket_type_int(PropertySubType subtype)
static bNodeSocketType *make_socket_type_vector(PropertySubType subtype)
{
bNodeSocketType *socktype = make_standard_socket_type(SOCK_VECTOR, subtype);
- socktype->get_base_cpp_type = []() { return &blender::fn::CPPType::get<blender::float3>(); };
+ socktype->base_cpp_type = &blender::fn::CPPType::get<blender::float3>();
socktype->get_base_cpp_value = [](const bNodeSocket &socket, void *r_value) {
*(blender::float3 *)r_value = ((bNodeSocketValueVector *)socket.default_value)->value;
};
- socktype->get_geometry_nodes_cpp_type = []() {
- return &blender::fn::CPPType::get<blender::fn::Field<blender::float3>>();
- };
+ socktype->geometry_nodes_cpp_type = &blender::fn::CPPType::get<ValueOrField<blender::float3>>();
socktype->get_geometry_nodes_cpp_value = [](const bNodeSocket &socket, void *r_value) {
blender::float3 value;
socket.typeinfo->get_base_cpp_value(socket, &value);
- new (r_value) blender::fn::Field<blender::float3>(blender::fn::make_constant_field(value));
+ new (r_value) ValueOrField<blender::float3>(value);
};
return socktype;
}
@@ -768,20 +762,16 @@ static bNodeSocketType *make_socket_type_vector(PropertySubType subtype)
static bNodeSocketType *make_socket_type_rgba()
{
bNodeSocketType *socktype = make_standard_socket_type(SOCK_RGBA, PROP_NONE);
- socktype->get_base_cpp_type = []() {
- return &blender::fn::CPPType::get<blender::ColorGeometry4f>();
- };
+ socktype->base_cpp_type = &blender::fn::CPPType::get<blender::ColorGeometry4f>();
socktype->get_base_cpp_value = [](const bNodeSocket &socket, void *r_value) {
*(blender::ColorGeometry4f *)r_value = ((bNodeSocketValueRGBA *)socket.default_value)->value;
};
- socktype->get_geometry_nodes_cpp_type = []() {
- return &blender::fn::CPPType::get<blender::fn::Field<blender::ColorGeometry4f>>();
- };
+ socktype->geometry_nodes_cpp_type =
+ &blender::fn::CPPType::get<ValueOrField<blender::ColorGeometry4f>>();
socktype->get_geometry_nodes_cpp_value = [](const bNodeSocket &socket, void *r_value) {
blender::ColorGeometry4f value;
socket.typeinfo->get_base_cpp_value(socket, &value);
- new (r_value)
- blender::fn::Field<blender::ColorGeometry4f>(blender::fn::make_constant_field(value));
+ new (r_value) ValueOrField<blender::ColorGeometry4f>(value);
};
return socktype;
}
@@ -789,18 +779,16 @@ static bNodeSocketType *make_socket_type_rgba()
static bNodeSocketType *make_socket_type_string()
{
bNodeSocketType *socktype = make_standard_socket_type(SOCK_STRING, PROP_NONE);
- socktype->get_base_cpp_type = []() { return &blender::fn::CPPType::get<std::string>(); };
+ socktype->base_cpp_type = &blender::fn::CPPType::get<std::string>();
socktype->get_base_cpp_value = [](const bNodeSocket &socket, void *r_value) {
new (r_value) std::string(((bNodeSocketValueString *)socket.default_value)->value);
};
- socktype->get_geometry_nodes_cpp_type = []() {
- return &blender::fn::CPPType::get<blender::fn::Field<std::string>>();
- };
+ socktype->geometry_nodes_cpp_type = &blender::fn::CPPType::get<ValueOrField<std::string>>();
socktype->get_geometry_nodes_cpp_value = [](const bNodeSocket &socket, void *r_value) {
std::string value;
value.~basic_string();
socket.typeinfo->get_base_cpp_value(socket, &value);
- new (r_value) blender::fn::Field<std::string>(blender::fn::make_constant_field(value));
+ new (r_value) ValueOrField<std::string>(value);
};
return socktype;
}
@@ -814,11 +802,11 @@ MAKE_CPP_TYPE(Material, Material *, CPPTypeFlags::BasicType)
static bNodeSocketType *make_socket_type_object()
{
bNodeSocketType *socktype = make_standard_socket_type(SOCK_OBJECT, PROP_NONE);
- socktype->get_base_cpp_type = []() { return &blender::fn::CPPType::get<Object *>(); };
+ socktype->base_cpp_type = &blender::fn::CPPType::get<Object *>();
socktype->get_base_cpp_value = [](const bNodeSocket &socket, void *r_value) {
*(Object **)r_value = ((bNodeSocketValueObject *)socket.default_value)->value;
};
- socktype->get_geometry_nodes_cpp_type = socktype->get_base_cpp_type;
+ socktype->geometry_nodes_cpp_type = socktype->base_cpp_type;
socktype->get_geometry_nodes_cpp_value = socktype->get_base_cpp_value;
return socktype;
}
@@ -826,11 +814,11 @@ static bNodeSocketType *make_socket_type_object()
static bNodeSocketType *make_socket_type_geometry()
{
bNodeSocketType *socktype = make_standard_socket_type(SOCK_GEOMETRY, PROP_NONE);
- socktype->get_base_cpp_type = []() { return &blender::fn::CPPType::get<GeometrySet>(); };
+ socktype->base_cpp_type = &blender::fn::CPPType::get<GeometrySet>();
socktype->get_base_cpp_value = [](const bNodeSocket &UNUSED(socket), void *r_value) {
new (r_value) GeometrySet();
};
- socktype->get_geometry_nodes_cpp_type = socktype->get_base_cpp_type;
+ socktype->geometry_nodes_cpp_type = socktype->base_cpp_type;
socktype->get_geometry_nodes_cpp_value = socktype->get_base_cpp_value;
return socktype;
}
@@ -838,11 +826,11 @@ static bNodeSocketType *make_socket_type_geometry()
static bNodeSocketType *make_socket_type_collection()
{
bNodeSocketType *socktype = make_standard_socket_type(SOCK_COLLECTION, PROP_NONE);
- socktype->get_base_cpp_type = []() { return &blender::fn::CPPType::get<Collection *>(); };
+ socktype->base_cpp_type = &blender::fn::CPPType::get<Collection *>();
socktype->get_base_cpp_value = [](const bNodeSocket &socket, void *r_value) {
*(Collection **)r_value = ((bNodeSocketValueCollection *)socket.default_value)->value;
};
- socktype->get_geometry_nodes_cpp_type = socktype->get_base_cpp_type;
+ socktype->geometry_nodes_cpp_type = socktype->base_cpp_type;
socktype->get_geometry_nodes_cpp_value = socktype->get_base_cpp_value;
return socktype;
}
@@ -850,11 +838,11 @@ static bNodeSocketType *make_socket_type_collection()
static bNodeSocketType *make_socket_type_texture()
{
bNodeSocketType *socktype = make_standard_socket_type(SOCK_TEXTURE, PROP_NONE);
- socktype->get_base_cpp_type = []() { return &blender::fn::CPPType::get<Tex *>(); };
+ socktype->base_cpp_type = &blender::fn::CPPType::get<Tex *>();
socktype->get_base_cpp_value = [](const bNodeSocket &socket, void *r_value) {
*(Tex **)r_value = ((bNodeSocketValueTexture *)socket.default_value)->value;
};
- socktype->get_geometry_nodes_cpp_type = socktype->get_base_cpp_type;
+ socktype->geometry_nodes_cpp_type = socktype->base_cpp_type;
socktype->get_geometry_nodes_cpp_value = socktype->get_base_cpp_value;
return socktype;
}
@@ -862,11 +850,11 @@ static bNodeSocketType *make_socket_type_texture()
static bNodeSocketType *make_socket_type_image()
{
bNodeSocketType *socktype = make_standard_socket_type(SOCK_IMAGE, PROP_NONE);
- socktype->get_base_cpp_type = []() { return &blender::fn::CPPType::get<Image *>(); };
+ socktype->base_cpp_type = &blender::fn::CPPType::get<Image *>();
socktype->get_base_cpp_value = [](const bNodeSocket &socket, void *r_value) {
*(Image **)r_value = ((bNodeSocketValueImage *)socket.default_value)->value;
};
- socktype->get_geometry_nodes_cpp_type = socktype->get_base_cpp_type;
+ socktype->geometry_nodes_cpp_type = socktype->base_cpp_type;
socktype->get_geometry_nodes_cpp_value = socktype->get_base_cpp_value;
return socktype;
}
@@ -874,11 +862,11 @@ static bNodeSocketType *make_socket_type_image()
static bNodeSocketType *make_socket_type_material()
{
bNodeSocketType *socktype = make_standard_socket_type(SOCK_MATERIAL, PROP_NONE);
- socktype->get_base_cpp_type = []() { return &blender::fn::CPPType::get<Material *>(); };
+ socktype->base_cpp_type = &blender::fn::CPPType::get<Material *>();
socktype->get_base_cpp_value = [](const bNodeSocket &socket, void *r_value) {
*(Material **)r_value = ((bNodeSocketValueMaterial *)socket.default_value)->value;
};
- socktype->get_geometry_nodes_cpp_type = socktype->get_base_cpp_type;
+ socktype->geometry_nodes_cpp_type = socktype->base_cpp_type;
socktype->get_geometry_nodes_cpp_value = socktype->get_base_cpp_value;
return socktype;
}
diff --git a/source/blender/nodes/intern/node_util.c b/source/blender/nodes/intern/node_util.c
index ba0cfeacb83..231030030eb 100644
--- a/source/blender/nodes/intern/node_util.c
+++ b/source/blender/nodes/intern/node_util.c
@@ -41,6 +41,8 @@
#include "MEM_guardedalloc.h"
+#include "NOD_common.h"
+
#include "node_util.h"
/* -------------------------------------------------------------------- */
@@ -97,12 +99,13 @@ void node_sock_label_clear(bNodeSocket *sock)
}
}
-void node_math_update(bNodeTree *UNUSED(ntree), bNode *node)
+void node_math_update(bNodeTree *ntree, bNode *node)
{
bNodeSocket *sock1 = BLI_findlink(&node->inputs, 0);
bNodeSocket *sock2 = BLI_findlink(&node->inputs, 1);
bNodeSocket *sock3 = BLI_findlink(&node->inputs, 2);
- nodeSetSocketAvailability(sock2,
+ nodeSetSocketAvailability(ntree,
+ sock2,
!ELEM(node->custom1,
NODE_MATH_SQRT,
NODE_MATH_SIGN,
@@ -126,7 +129,8 @@ void node_math_update(bNodeTree *UNUSED(ntree), bNode *node)
NODE_MATH_COSH,
NODE_MATH_SINH,
NODE_MATH_TANH));
- nodeSetSocketAvailability(sock3,
+ nodeSetSocketAvailability(ntree,
+ sock3,
ELEM(node->custom1,
NODE_MATH_COMPARE,
NODE_MATH_MULTIPLY_ADD,
@@ -491,6 +495,10 @@ static int node_datatype_priority(eNodeSocketDatatype from, eNodeSocketDatatype
/* select a suitable input socket for an output */
static bNodeSocket *select_internal_link_input(bNode *node, bNodeSocket *output)
{
+ if (node->type == NODE_REROUTE) {
+ return node->inputs.first;
+ }
+
bNodeSocket *selected = NULL, *input;
int i;
int sel_priority = -1;
@@ -524,7 +532,7 @@ static bNodeSocket *select_internal_link_input(bNode *node, bNodeSocket *output)
return selected;
}
-void node_update_internal_links_default(bNodeTree *ntree, bNode *node)
+void node_internal_links_create(bNodeTree *ntree, bNode *node)
{
bNodeLink *link;
bNodeSocket *output, *input;
diff --git a/source/blender/nodes/intern/node_util.h b/source/blender/nodes/intern/node_util.h
index 9cbb21e02f7..c064ef4ab36 100644
--- a/source/blender/nodes/intern/node_util.h
+++ b/source/blender/nodes/intern/node_util.h
@@ -83,7 +83,6 @@ void node_filter_label(struct bNodeTree *ntree, struct bNode *node, char *label,
/*** Link Handling */
void node_insert_link_default(struct bNodeTree *ntree, struct bNode *node, struct bNodeLink *link);
-void node_update_internal_links_default(struct bNodeTree *ntree, struct bNode *node);
float node_socket_get_float(struct bNodeTree *ntree, struct bNode *node, struct bNodeSocket *sock);
void node_socket_set_float(struct bNodeTree *ntree,
diff --git a/source/blender/nodes/intern/type_conversions.cc b/source/blender/nodes/intern/type_conversions.cc
index 1a71a3418a5..d4cd7dc6bfe 100644
--- a/source/blender/nodes/intern/type_conversions.cc
+++ b/source/blender/nodes/intern/type_conversions.cc
@@ -24,19 +24,16 @@
namespace blender::nodes {
-using fn::GVArrayPtr;
-using fn::GVMutableArray;
-using fn::GVMutableArrayPtr;
using fn::MFDataType;
template<typename From, typename To, To (*ConversionF)(const From &)>
static void add_implicit_conversion(DataTypeConversions &conversions)
{
- const CPPType &from_type = CPPType::get<From>();
- const CPPType &to_type = CPPType::get<To>();
- const std::string conversion_name = from_type.name() + " to " + to_type.name();
+ static const CPPType &from_type = CPPType::get<From>();
+ static const CPPType &to_type = CPPType::get<To>();
+ static const std::string conversion_name = from_type.name() + " to " + to_type.name();
- static fn::CustomMF_SI_SO<From, To> multi_function{conversion_name, ConversionF};
+ static fn::CustomMF_SI_SO<From, To> multi_function{conversion_name.c_str(), ConversionF};
static auto convert_single_to_initialized = [](const void *src, void *dst) {
*(To *)dst = ConversionF(*(const From *)src);
};
@@ -242,107 +239,108 @@ void DataTypeConversions::convert_to_uninitialized(const CPPType &from_type,
functions->convert_single_to_uninitialized(from_value, to_value);
}
-class GVArray_For_ConvertedGVArray : public GVArray {
+class GVArray_For_ConvertedGVArray : public fn::GVArrayImpl {
private:
- GVArrayPtr varray_;
+ fn::GVArray varray_;
const CPPType &from_type_;
ConversionFunctions old_to_new_conversions_;
public:
- GVArray_For_ConvertedGVArray(GVArrayPtr varray,
+ GVArray_For_ConvertedGVArray(fn::GVArray varray,
const CPPType &to_type,
const DataTypeConversions &conversions)
- : GVArray(to_type, varray->size()), varray_(std::move(varray)), from_type_(varray_->type())
+ : fn::GVArrayImpl(to_type, varray.size()),
+ varray_(std::move(varray)),
+ from_type_(varray_.type())
{
old_to_new_conversions_ = *conversions.get_conversion_functions(from_type_, to_type);
}
private:
- void get_impl(const int64_t index, void *r_value) const override
+ void get(const int64_t index, void *r_value) const override
{
BUFFER_FOR_CPP_TYPE_VALUE(from_type_, buffer);
- varray_->get(index, buffer);
+ varray_.get(index, buffer);
old_to_new_conversions_.convert_single_to_initialized(buffer, r_value);
from_type_.destruct(buffer);
}
- void get_to_uninitialized_impl(const int64_t index, void *r_value) const override
+ void get_to_uninitialized(const int64_t index, void *r_value) const override
{
BUFFER_FOR_CPP_TYPE_VALUE(from_type_, buffer);
- varray_->get(index, buffer);
+ varray_.get(index, buffer);
old_to_new_conversions_.convert_single_to_uninitialized(buffer, r_value);
from_type_.destruct(buffer);
}
};
-class GVMutableArray_For_ConvertedGVMutableArray : public GVMutableArray {
+class GVMutableArray_For_ConvertedGVMutableArray : public fn::GVMutableArrayImpl {
private:
- GVMutableArrayPtr varray_;
+ fn::GVMutableArray varray_;
const CPPType &from_type_;
ConversionFunctions old_to_new_conversions_;
ConversionFunctions new_to_old_conversions_;
public:
- GVMutableArray_For_ConvertedGVMutableArray(GVMutableArrayPtr varray,
+ GVMutableArray_For_ConvertedGVMutableArray(fn::GVMutableArray varray,
const CPPType &to_type,
const DataTypeConversions &conversions)
- : GVMutableArray(to_type, varray->size()),
+ : fn::GVMutableArrayImpl(to_type, varray.size()),
varray_(std::move(varray)),
- from_type_(varray_->type())
+ from_type_(varray_.type())
{
old_to_new_conversions_ = *conversions.get_conversion_functions(from_type_, to_type);
new_to_old_conversions_ = *conversions.get_conversion_functions(to_type, from_type_);
}
private:
- void get_impl(const int64_t index, void *r_value) const override
+ void get(const int64_t index, void *r_value) const override
{
BUFFER_FOR_CPP_TYPE_VALUE(from_type_, buffer);
- varray_->get(index, buffer);
+ varray_.get(index, buffer);
old_to_new_conversions_.convert_single_to_initialized(buffer, r_value);
from_type_.destruct(buffer);
}
- void get_to_uninitialized_impl(const int64_t index, void *r_value) const override
+ void get_to_uninitialized(const int64_t index, void *r_value) const override
{
BUFFER_FOR_CPP_TYPE_VALUE(from_type_, buffer);
- varray_->get(index, buffer);
+ varray_.get(index, buffer);
old_to_new_conversions_.convert_single_to_uninitialized(buffer, r_value);
from_type_.destruct(buffer);
}
- void set_by_move_impl(const int64_t index, void *value) override
+ void set_by_move(const int64_t index, void *value) override
{
BUFFER_FOR_CPP_TYPE_VALUE(from_type_, buffer);
new_to_old_conversions_.convert_single_to_uninitialized(value, buffer);
- varray_->set_by_relocate(index, buffer);
+ varray_.set_by_relocate(index, buffer);
}
};
-fn::GVArrayPtr DataTypeConversions::try_convert(fn::GVArrayPtr varray,
- const CPPType &to_type) const
+fn::GVArray DataTypeConversions::try_convert(fn::GVArray varray, const CPPType &to_type) const
{
- const CPPType &from_type = varray->type();
+ const CPPType &from_type = varray.type();
if (from_type == to_type) {
return varray;
}
if (!this->is_convertible(from_type, to_type)) {
return {};
}
- return std::make_unique<GVArray_For_ConvertedGVArray>(std::move(varray), to_type, *this);
+ return fn::GVArray::For<GVArray_For_ConvertedGVArray>(std::move(varray), to_type, *this);
}
-fn::GVMutableArrayPtr DataTypeConversions::try_convert(fn::GVMutableArrayPtr varray,
- const CPPType &to_type) const
+fn::GVMutableArray DataTypeConversions::try_convert(fn::GVMutableArray varray,
+ const CPPType &to_type) const
{
- const CPPType &from_type = varray->type();
+ const CPPType &from_type = varray.type();
if (from_type == to_type) {
return varray;
}
if (!this->is_convertible(from_type, to_type)) {
return {};
}
- return std::make_unique<GVMutableArray_For_ConvertedGVMutableArray>(
+ return fn::GVMutableArray::For<GVMutableArray_For_ConvertedGVMutableArray>(
std::move(varray), to_type, *this);
}
diff --git a/source/blender/nodes/shader/node_shader_util.c b/source/blender/nodes/shader/node_shader_util.c
index 97041b3fdfd..e1f6c135568 100644
--- a/source/blender/nodes/shader/node_shader_util.c
+++ b/source/blender/nodes/shader/node_shader_util.c
@@ -54,7 +54,6 @@ void sh_node_type_base(
ntype->poll = sh_node_poll_default;
ntype->insert_link = node_insert_link_default;
- ntype->update_internal_links = node_update_internal_links_default;
}
void sh_fn_node_type_base(bNodeType *ntype, int type, const char *name, short nclass, short flag)
diff --git a/source/blender/nodes/shader/nodes/node_shader_bsdf_hair_principled.c b/source/blender/nodes/shader/nodes/node_shader_bsdf_hair_principled.c
index e29b2ee1c5c..d2b40a7ec39 100644
--- a/source/blender/nodes/shader/nodes/node_shader_bsdf_hair_principled.c
+++ b/source/blender/nodes/shader/nodes/node_shader_bsdf_hair_principled.c
@@ -59,59 +59,34 @@ static void node_shader_init_hair_principled(bNodeTree *UNUSED(ntree), bNode *no
}
/* Triggers (in)visibility of some sockets when changing Parametrization. */
-static void node_shader_update_hair_principled(bNodeTree *UNUSED(ntree), bNode *node)
+static void node_shader_update_hair_principled(bNodeTree *ntree, bNode *node)
{
bNodeSocket *sock;
int parametrization = node->custom1;
for (sock = node->inputs.first; sock; sock = sock->next) {
if (STREQ(sock->name, "Color")) {
- if (parametrization == SHD_PRINCIPLED_HAIR_REFLECTANCE) {
- sock->flag &= ~SOCK_UNAVAIL;
- }
- else {
- sock->flag |= SOCK_UNAVAIL;
- }
+ nodeSetSocketAvailability(ntree, sock, parametrization == SHD_PRINCIPLED_HAIR_REFLECTANCE);
}
else if (STREQ(sock->name, "Melanin")) {
- if (parametrization == SHD_PRINCIPLED_HAIR_PIGMENT_CONCENTRATION) {
- sock->flag &= ~SOCK_UNAVAIL;
- }
- else {
- sock->flag |= SOCK_UNAVAIL;
- }
+ nodeSetSocketAvailability(
+ ntree, sock, parametrization == SHD_PRINCIPLED_HAIR_PIGMENT_CONCENTRATION);
}
else if (STREQ(sock->name, "Melanin Redness")) {
- if (parametrization == SHD_PRINCIPLED_HAIR_PIGMENT_CONCENTRATION) {
- sock->flag &= ~SOCK_UNAVAIL;
- }
- else {
- sock->flag |= SOCK_UNAVAIL;
- }
+ nodeSetSocketAvailability(
+ ntree, sock, parametrization == SHD_PRINCIPLED_HAIR_PIGMENT_CONCENTRATION);
}
else if (STREQ(sock->name, "Tint")) {
- if (parametrization == SHD_PRINCIPLED_HAIR_PIGMENT_CONCENTRATION) {
- sock->flag &= ~SOCK_UNAVAIL;
- }
- else {
- sock->flag |= SOCK_UNAVAIL;
- }
+ nodeSetSocketAvailability(
+ ntree, sock, parametrization == SHD_PRINCIPLED_HAIR_PIGMENT_CONCENTRATION);
}
else if (STREQ(sock->name, "Absorption Coefficient")) {
- if (parametrization == SHD_PRINCIPLED_HAIR_DIRECT_ABSORPTION) {
- sock->flag &= ~SOCK_UNAVAIL;
- }
- else {
- sock->flag |= SOCK_UNAVAIL;
- }
+ nodeSetSocketAvailability(
+ ntree, sock, parametrization == SHD_PRINCIPLED_HAIR_DIRECT_ABSORPTION);
}
else if (STREQ(sock->name, "Random Color")) {
- if (parametrization == SHD_PRINCIPLED_HAIR_PIGMENT_CONCENTRATION) {
- sock->flag &= ~SOCK_UNAVAIL;
- }
- else {
- sock->flag |= SOCK_UNAVAIL;
- }
+ nodeSetSocketAvailability(
+ ntree, sock, parametrization == SHD_PRINCIPLED_HAIR_PIGMENT_CONCENTRATION);
}
}
}
diff --git a/source/blender/nodes/shader/nodes/node_shader_bsdf_principled.c b/source/blender/nodes/shader/nodes/node_shader_bsdf_principled.c
index cb4f0594310..89b7164693f 100644
--- a/source/blender/nodes/shader/nodes/node_shader_bsdf_principled.c
+++ b/source/blender/nodes/shader/nodes/node_shader_bsdf_principled.c
@@ -167,7 +167,7 @@ static int node_shader_gpu_bsdf_principled(GPUMaterial *mat,
sss_scale);
}
-static void node_shader_update_principled(bNodeTree *UNUSED(ntree), bNode *node)
+static void node_shader_update_principled(bNodeTree *ntree, bNode *node)
{
bNodeSocket *sock;
int distribution = node->custom1;
@@ -175,21 +175,11 @@ static void node_shader_update_principled(bNodeTree *UNUSED(ntree), bNode *node)
for (sock = node->inputs.first; sock; sock = sock->next) {
if (STREQ(sock->name, "Transmission Roughness")) {
- if (distribution == SHD_GLOSSY_GGX) {
- sock->flag &= ~SOCK_UNAVAIL;
- }
- else {
- sock->flag |= SOCK_UNAVAIL;
- }
+ nodeSetSocketAvailability(ntree, sock, distribution == SHD_GLOSSY_GGX);
}
if (STR_ELEM(sock->name, "Subsurface IOR", "Subsurface Anisotropy")) {
- if (sss_method == SHD_SUBSURFACE_BURLEY) {
- sock->flag |= SOCK_UNAVAIL;
- }
- else {
- sock->flag &= ~SOCK_UNAVAIL;
- }
+ nodeSetSocketAvailability(ntree, sock, sss_method == SHD_SUBSURFACE_BURLEY);
}
}
}
diff --git a/source/blender/nodes/shader/nodes/node_shader_common.c b/source/blender/nodes/shader/nodes/node_shader_common.c
index 4df5add7151..a1dac05434e 100644
--- a/source/blender/nodes/shader/nodes/node_shader_common.c
+++ b/source/blender/nodes/shader/nodes/node_shader_common.c
@@ -237,7 +237,6 @@ void register_node_type_sh_group(void)
ntype.poll = sh_node_poll_default;
ntype.poll_instance = node_group_poll_instance;
ntype.insert_link = node_insert_link_default;
- ntype.update_internal_links = node_update_internal_links_default;
ntype.rna_ext.srna = RNA_struct_find("ShaderNodeGroup");
BLI_assert(ntype.rna_ext.srna != NULL);
RNA_struct_blender_type_set(ntype.rna_ext.srna, &ntype);
@@ -261,9 +260,6 @@ void register_node_type_sh_custom_group(bNodeType *ntype)
if (ntype->insert_link == NULL) {
ntype->insert_link = node_insert_link_default;
}
- if (ntype->update_internal_links == NULL) {
- ntype->update_internal_links = node_update_internal_links_default;
- }
node_type_exec(ntype, group_initexec, group_freeexec, group_execute);
node_type_gpu(ntype, gpu_group_execute);
diff --git a/source/blender/nodes/shader/nodes/node_shader_map_range.cc b/source/blender/nodes/shader/nodes/node_shader_map_range.cc
index c866a154e8c..e55963eb500 100644
--- a/source/blender/nodes/shader/nodes/node_shader_map_range.cc
+++ b/source/blender/nodes/shader/nodes/node_shader_map_range.cc
@@ -41,10 +41,10 @@ static void sh_node_map_range_declare(NodeDeclarationBuilder &b)
} // namespace blender::nodes
-static void node_shader_update_map_range(bNodeTree *UNUSED(ntree), bNode *node)
+static void node_shader_update_map_range(bNodeTree *ntree, bNode *node)
{
bNodeSocket *sockSteps = nodeFindSocket(node, SOCK_IN, "Steps");
- nodeSetSocketAvailability(sockSteps, node->custom2 == NODE_MAP_RANGE_STEPPED);
+ nodeSetSocketAvailability(ntree, sockSteps, node->custom2 == NODE_MAP_RANGE_STEPPED);
}
static void node_shader_init_map_range(bNodeTree *UNUSED(ntree), bNode *node)
diff --git a/source/blender/nodes/shader/nodes/node_shader_mapping.c b/source/blender/nodes/shader/nodes/node_shader_mapping.c
index 774e7fed029..cabfecdb6ee 100644
--- a/source/blender/nodes/shader/nodes/node_shader_mapping.c
+++ b/source/blender/nodes/shader/nodes/node_shader_mapping.c
@@ -57,11 +57,11 @@ static int gpu_shader_mapping(GPUMaterial *mat,
return 0;
}
-static void node_shader_update_mapping(bNodeTree *UNUSED(ntree), bNode *node)
+static void node_shader_update_mapping(bNodeTree *ntree, bNode *node)
{
bNodeSocket *sock = nodeFindSocket(node, SOCK_IN, "Location");
nodeSetSocketAvailability(
- sock, ELEM(node->custom1, NODE_MAPPING_TYPE_POINT, NODE_MAPPING_TYPE_TEXTURE));
+ ntree, sock, ELEM(node->custom1, NODE_MAPPING_TYPE_POINT, NODE_MAPPING_TYPE_TEXTURE));
}
void register_node_type_sh_mapping(void)
diff --git a/source/blender/nodes/shader/nodes/node_shader_math.cc b/source/blender/nodes/shader/nodes/node_shader_math.cc
index 284a5f1189f..1e94148c5c7 100644
--- a/source/blender/nodes/shader/nodes/node_shader_math.cc
+++ b/source/blender/nodes/shader/nodes/node_shader_math.cc
@@ -88,7 +88,8 @@ static const blender::fn::MultiFunction *get_base_multi_function(bNode &node)
blender::nodes::try_dispatch_float_math_fl_to_fl(
mode, [&](auto function, const blender::nodes::FloatMathOperationInfo &info) {
- static blender::fn::CustomMF_SI_SO<float, float> fn{info.title_case_name, function};
+ static blender::fn::CustomMF_SI_SO<float, float> fn{info.title_case_name.c_str(),
+ function};
base_fn = &fn;
});
if (base_fn != nullptr) {
@@ -97,7 +98,7 @@ static const blender::fn::MultiFunction *get_base_multi_function(bNode &node)
blender::nodes::try_dispatch_float_math_fl_fl_to_fl(
mode, [&](auto function, const blender::nodes::FloatMathOperationInfo &info) {
- static blender::fn::CustomMF_SI_SI_SO<float, float, float> fn{info.title_case_name,
+ static blender::fn::CustomMF_SI_SI_SO<float, float, float> fn{info.title_case_name.c_str(),
function};
base_fn = &fn;
});
@@ -108,7 +109,7 @@ static const blender::fn::MultiFunction *get_base_multi_function(bNode &node)
blender::nodes::try_dispatch_float_math_fl_fl_fl_to_fl(
mode, [&](auto function, const blender::nodes::FloatMathOperationInfo &info) {
static blender::fn::CustomMF_SI_SI_SI_SO<float, float, float, float> fn{
- info.title_case_name, function};
+ info.title_case_name.c_str(), function};
base_fn = &fn;
});
if (base_fn != nullptr) {
diff --git a/source/blender/nodes/shader/nodes/node_shader_output_aov.c b/source/blender/nodes/shader/nodes/node_shader_output_aov.c
index 7e7e1b703f1..32765b459ca 100644
--- a/source/blender/nodes/shader/nodes/node_shader_output_aov.c
+++ b/source/blender/nodes/shader/nodes/node_shader_output_aov.c
@@ -64,8 +64,7 @@ void register_node_type_sh_output_aov(void)
&ntype, "NodeShaderOutputAOV", node_free_standard_storage, node_copy_standard_storage);
node_type_gpu(&ntype, node_shader_gpu_output_aov);
- /* Do not allow muting output node. */
- node_type_internal_links(&ntype, NULL);
+ ntype.no_muting = true;
nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/shader/nodes/node_shader_output_light.c b/source/blender/nodes/shader/nodes/node_shader_output_light.c
index 722202bafdc..6c4837f3c6f 100644
--- a/source/blender/nodes/shader/nodes/node_shader_output_light.c
+++ b/source/blender/nodes/shader/nodes/node_shader_output_light.c
@@ -36,8 +36,7 @@ void register_node_type_sh_output_light(void)
node_type_init(&ntype, NULL);
node_type_storage(&ntype, "", NULL, NULL);
- /* Do not allow muting output node. */
- node_type_internal_links(&ntype, NULL);
+ ntype.no_muting = true;
nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/shader/nodes/node_shader_output_linestyle.c b/source/blender/nodes/shader/nodes/node_shader_output_linestyle.c
index 5b4ebf21f5f..07e253383e2 100644
--- a/source/blender/nodes/shader/nodes/node_shader_output_linestyle.c
+++ b/source/blender/nodes/shader/nodes/node_shader_output_linestyle.c
@@ -38,8 +38,7 @@ void register_node_type_sh_output_linestyle(void)
node_type_socket_templates(&ntype, sh_node_output_linestyle_in, NULL);
node_type_init(&ntype, NULL);
- /* Do not allow muting output node. */
- node_type_internal_links(&ntype, NULL);
+ ntype.no_muting = true;
nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/shader/nodes/node_shader_output_material.c b/source/blender/nodes/shader/nodes/node_shader_output_material.c
index fb0b6e7b263..41932cca6a3 100644
--- a/source/blender/nodes/shader/nodes/node_shader_output_material.c
+++ b/source/blender/nodes/shader/nodes/node_shader_output_material.c
@@ -84,8 +84,7 @@ void register_node_type_sh_output_material(void)
node_type_storage(&ntype, "", NULL, NULL);
node_type_gpu(&ntype, node_shader_gpu_output_material);
- /* Do not allow muting output node. */
- node_type_internal_links(&ntype, NULL);
+ ntype.no_muting = true;
nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/shader/nodes/node_shader_output_world.c b/source/blender/nodes/shader/nodes/node_shader_output_world.c
index 59c77e0b25c..09eca7f712e 100644
--- a/source/blender/nodes/shader/nodes/node_shader_output_world.c
+++ b/source/blender/nodes/shader/nodes/node_shader_output_world.c
@@ -52,8 +52,7 @@ void register_node_type_sh_output_world(void)
node_type_storage(&ntype, "", NULL, NULL);
node_type_gpu(&ntype, node_shader_gpu_output_world);
- /* Do not allow muting output node. */
- node_type_internal_links(&ntype, NULL);
+ ntype.no_muting = true;
nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/shader/nodes/node_shader_tex_musgrave.cc b/source/blender/nodes/shader/nodes/node_shader_tex_musgrave.cc
index 81f9cd735eb..e426d9cc49c 100644
--- a/source/blender/nodes/shader/nodes/node_shader_tex_musgrave.cc
+++ b/source/blender/nodes/shader/nodes/node_shader_tex_musgrave.cc
@@ -104,7 +104,7 @@ static int node_shader_gpu_tex_musgrave(GPUMaterial *mat,
return GPU_stack_link(mat, node, name, in, out);
}
-static void node_shader_update_tex_musgrave(bNodeTree *UNUSED(ntree), bNode *node)
+static void node_shader_update_tex_musgrave(bNodeTree *ntree, bNode *node)
{
NodeTexMusgrave *tex = (NodeTexMusgrave *)node->storage;
@@ -113,12 +113,14 @@ static void node_shader_update_tex_musgrave(bNodeTree *UNUSED(ntree), bNode *nod
bNodeSocket *inOffsetSock = nodeFindSocket(node, SOCK_IN, "Offset");
bNodeSocket *inGainSock = nodeFindSocket(node, SOCK_IN, "Gain");
- nodeSetSocketAvailability(inVectorSock, tex->dimensions != 1);
- nodeSetSocketAvailability(inWSock, tex->dimensions == 1 || tex->dimensions == 4);
- nodeSetSocketAvailability(inOffsetSock,
+ nodeSetSocketAvailability(ntree, inVectorSock, tex->dimensions != 1);
+ nodeSetSocketAvailability(ntree, inWSock, tex->dimensions == 1 || tex->dimensions == 4);
+ nodeSetSocketAvailability(ntree,
+ inOffsetSock,
tex->musgrave_type != SHD_MUSGRAVE_MULTIFRACTAL &&
tex->musgrave_type != SHD_MUSGRAVE_FBM);
- nodeSetSocketAvailability(inGainSock,
+ nodeSetSocketAvailability(ntree,
+ inGainSock,
tex->musgrave_type == SHD_MUSGRAVE_HYBRID_MULTIFRACTAL ||
tex->musgrave_type == SHD_MUSGRAVE_RIDGED_MULTIFRACTAL);
@@ -199,28 +201,28 @@ class MusgraveFunction : public fn::MultiFunction {
void call(IndexMask mask, fn::MFParams params, fn::MFContext UNUSED(context)) const override
{
- auto get_vector = [&](int param_index) -> const VArray<float3> & {
+ auto get_vector = [&](int param_index) -> VArray<float3> {
return params.readonly_single_input<float3>(param_index, "Vector");
};
- auto get_w = [&](int param_index) -> const VArray<float> & {
+ auto get_w = [&](int param_index) -> VArray<float> {
return params.readonly_single_input<float>(param_index, "W");
};
- auto get_scale = [&](int param_index) -> const VArray<float> & {
+ auto get_scale = [&](int param_index) -> VArray<float> {
return params.readonly_single_input<float>(param_index, "Scale");
};
- auto get_detail = [&](int param_index) -> const VArray<float> & {
+ auto get_detail = [&](int param_index) -> VArray<float> {
return params.readonly_single_input<float>(param_index, "Detail");
};
- auto get_dimension = [&](int param_index) -> const VArray<float> & {
+ auto get_dimension = [&](int param_index) -> VArray<float> {
return params.readonly_single_input<float>(param_index, "Dimension");
};
- auto get_lacunarity = [&](int param_index) -> const VArray<float> & {
+ auto get_lacunarity = [&](int param_index) -> VArray<float> {
return params.readonly_single_input<float>(param_index, "Lacunarity");
};
- auto get_offset = [&](int param_index) -> const VArray<float> & {
+ auto get_offset = [&](int param_index) -> VArray<float> {
return params.readonly_single_input<float>(param_index, "Offset");
};
- auto get_gain = [&](int param_index) -> const VArray<float> & {
+ auto get_gain = [&](int param_index) -> VArray<float> {
return params.readonly_single_input<float>(param_index, "Gain");
};
diff --git a/source/blender/nodes/shader/nodes/node_shader_tex_noise.cc b/source/blender/nodes/shader/nodes/node_shader_tex_noise.cc
index d28095edb96..7dd2695ecf7 100644
--- a/source/blender/nodes/shader/nodes/node_shader_tex_noise.cc
+++ b/source/blender/nodes/shader/nodes/node_shader_tex_noise.cc
@@ -76,14 +76,14 @@ static int node_shader_gpu_tex_noise(GPUMaterial *mat,
return GPU_stack_link(mat, node, name, in, out);
}
-static void node_shader_update_tex_noise(bNodeTree *UNUSED(ntree), bNode *node)
+static void node_shader_update_tex_noise(bNodeTree *ntree, bNode *node)
{
bNodeSocket *sockVector = nodeFindSocket(node, SOCK_IN, "Vector");
bNodeSocket *sockW = nodeFindSocket(node, SOCK_IN, "W");
NodeTexNoise *tex = (NodeTexNoise *)node->storage;
- nodeSetSocketAvailability(sockVector, tex->dimensions != 1);
- nodeSetSocketAvailability(sockW, tex->dimensions == 1 || tex->dimensions == 4);
+ nodeSetSocketAvailability(ntree, sockVector, tex->dimensions != 1);
+ nodeSetSocketAvailability(ntree, sockW, tex->dimensions == 1 || tex->dimensions == 4);
}
namespace blender::nodes {
diff --git a/source/blender/nodes/shader/nodes/node_shader_tex_sky.c b/source/blender/nodes/shader/nodes/node_shader_tex_sky.c
index 5dc11c4df00..5c581528c14 100644
--- a/source/blender/nodes/shader/nodes/node_shader_tex_sky.c
+++ b/source/blender/nodes/shader/nodes/node_shader_tex_sky.c
@@ -195,12 +195,12 @@ static int node_shader_gpu_tex_sky(GPUMaterial *mat,
return GPU_stack_link(mat, node, "node_tex_sky_nishita", in, out);
}
-static void node_shader_update_sky(bNodeTree *UNUSED(ntree), bNode *node)
+static void node_shader_update_sky(bNodeTree *ntree, bNode *node)
{
bNodeSocket *sockVector = nodeFindSocket(node, SOCK_IN, "Vector");
NodeTexSky *tex = (NodeTexSky *)node->storage;
- nodeSetSocketAvailability(sockVector, !(tex->sky_model == 2 && tex->sun_disc == 1));
+ nodeSetSocketAvailability(ntree, sockVector, !(tex->sky_model == 2 && tex->sun_disc == 1));
}
/* node type definition */
diff --git a/source/blender/nodes/shader/nodes/node_shader_tex_voronoi.cc b/source/blender/nodes/shader/nodes/node_shader_tex_voronoi.cc
index 422268b98c3..1bc3741d27c 100644
--- a/source/blender/nodes/shader/nodes/node_shader_tex_voronoi.cc
+++ b/source/blender/nodes/shader/nodes/node_shader_tex_voronoi.cc
@@ -123,7 +123,7 @@ static int node_shader_gpu_tex_voronoi(GPUMaterial *mat,
return GPU_stack_link(mat, node, name, in, out, GPU_constant(&metric));
}
-static void node_shader_update_tex_voronoi(bNodeTree *UNUSED(ntree), bNode *node)
+static void node_shader_update_tex_voronoi(bNodeTree *ntree, bNode *node)
{
bNodeSocket *inVectorSock = nodeFindSocket(node, SOCK_IN, "Vector");
bNodeSocket *inWSock = nodeFindSocket(node, SOCK_IN, "W");
@@ -138,27 +138,31 @@ static void node_shader_update_tex_voronoi(bNodeTree *UNUSED(ntree), bNode *node
NodeTexVoronoi *tex = (NodeTexVoronoi *)node->storage;
- nodeSetSocketAvailability(inWSock, tex->dimensions == 1 || tex->dimensions == 4);
- nodeSetSocketAvailability(inVectorSock, tex->dimensions != 1);
+ nodeSetSocketAvailability(ntree, inWSock, tex->dimensions == 1 || tex->dimensions == 4);
+ nodeSetSocketAvailability(ntree, inVectorSock, tex->dimensions != 1);
nodeSetSocketAvailability(
+ ntree,
inExponentSock,
tex->distance == SHD_VORONOI_MINKOWSKI && tex->dimensions != 1 &&
!ELEM(tex->feature, SHD_VORONOI_DISTANCE_TO_EDGE, SHD_VORONOI_N_SPHERE_RADIUS));
- nodeSetSocketAvailability(inSmoothnessSock, tex->feature == SHD_VORONOI_SMOOTH_F1);
+ nodeSetSocketAvailability(ntree, inSmoothnessSock, tex->feature == SHD_VORONOI_SMOOTH_F1);
- nodeSetSocketAvailability(outDistanceSock, tex->feature != SHD_VORONOI_N_SPHERE_RADIUS);
- nodeSetSocketAvailability(outColorSock,
+ nodeSetSocketAvailability(ntree, outDistanceSock, tex->feature != SHD_VORONOI_N_SPHERE_RADIUS);
+ nodeSetSocketAvailability(ntree,
+ outColorSock,
tex->feature != SHD_VORONOI_DISTANCE_TO_EDGE &&
tex->feature != SHD_VORONOI_N_SPHERE_RADIUS);
- nodeSetSocketAvailability(outPositionSock,
+ nodeSetSocketAvailability(ntree,
+ outPositionSock,
tex->feature != SHD_VORONOI_DISTANCE_TO_EDGE &&
tex->feature != SHD_VORONOI_N_SPHERE_RADIUS &&
tex->dimensions != 1);
- nodeSetSocketAvailability(outWSock,
+ nodeSetSocketAvailability(ntree,
+ outWSock,
tex->feature != SHD_VORONOI_DISTANCE_TO_EDGE &&
tex->feature != SHD_VORONOI_N_SPHERE_RADIUS &&
(ELEM(tex->dimensions, 1, 4)));
- nodeSetSocketAvailability(outRadiusSock, tex->feature == SHD_VORONOI_N_SPHERE_RADIUS);
+ nodeSetSocketAvailability(ntree, outRadiusSock, tex->feature == SHD_VORONOI_N_SPHERE_RADIUS);
}
namespace blender::nodes {
@@ -220,22 +224,22 @@ class VoronoiMinowskiFunction : public fn::MultiFunction {
void call(IndexMask mask, fn::MFParams params, fn::MFContext UNUSED(context)) const override
{
- auto get_vector = [&](int param_index) -> const VArray<float3> & {
+ auto get_vector = [&](int param_index) -> VArray<float3> {
return params.readonly_single_input<float3>(param_index, "Vector");
};
- auto get_w = [&](int param_index) -> const VArray<float> & {
+ auto get_w = [&](int param_index) -> VArray<float> {
return params.readonly_single_input<float>(param_index, "W");
};
- auto get_scale = [&](int param_index) -> const VArray<float> & {
+ auto get_scale = [&](int param_index) -> VArray<float> {
return params.readonly_single_input<float>(param_index, "Scale");
};
- auto get_smoothness = [&](int param_index) -> const VArray<float> & {
+ auto get_smoothness = [&](int param_index) -> VArray<float> {
return params.readonly_single_input<float>(param_index, "Smoothness");
};
- auto get_exponent = [&](int param_index) -> const VArray<float> & {
+ auto get_exponent = [&](int param_index) -> VArray<float> {
return params.readonly_single_input<float>(param_index, "Exponent");
};
- auto get_randomness = [&](int param_index) -> const VArray<float> & {
+ auto get_randomness = [&](int param_index) -> VArray<float> {
return params.readonly_single_input<float>(param_index, "Randomness");
};
auto get_r_distance = [&](int param_index) -> MutableSpan<float> {
@@ -651,19 +655,19 @@ class VoronoiMetricFunction : public fn::MultiFunction {
void call(IndexMask mask, fn::MFParams params, fn::MFContext UNUSED(context)) const override
{
- auto get_vector = [&](int param_index) -> const VArray<float3> & {
+ auto get_vector = [&](int param_index) -> VArray<float3> {
return params.readonly_single_input<float3>(param_index, "Vector");
};
- auto get_w = [&](int param_index) -> const VArray<float> & {
+ auto get_w = [&](int param_index) -> VArray<float> {
return params.readonly_single_input<float>(param_index, "W");
};
- auto get_scale = [&](int param_index) -> const VArray<float> & {
+ auto get_scale = [&](int param_index) -> VArray<float> {
return params.readonly_single_input<float>(param_index, "Scale");
};
- auto get_smoothness = [&](int param_index) -> const VArray<float> & {
+ auto get_smoothness = [&](int param_index) -> VArray<float> {
return params.readonly_single_input<float>(param_index, "Smoothness");
};
- auto get_randomness = [&](int param_index) -> const VArray<float> & {
+ auto get_randomness = [&](int param_index) -> VArray<float> {
return params.readonly_single_input<float>(param_index, "Randomness");
};
auto get_r_distance = [&](int param_index) -> MutableSpan<float> {
@@ -1153,16 +1157,16 @@ class VoronoiEdgeFunction : public fn::MultiFunction {
void call(IndexMask mask, fn::MFParams params, fn::MFContext UNUSED(context)) const override
{
- auto get_vector = [&](int param_index) -> const VArray<float3> & {
+ auto get_vector = [&](int param_index) -> VArray<float3> {
return params.readonly_single_input<float3>(param_index, "Vector");
};
- auto get_w = [&](int param_index) -> const VArray<float> & {
+ auto get_w = [&](int param_index) -> VArray<float> {
return params.readonly_single_input<float>(param_index, "W");
};
- auto get_scale = [&](int param_index) -> const VArray<float> & {
+ auto get_scale = [&](int param_index) -> VArray<float> {
return params.readonly_single_input<float>(param_index, "Scale");
};
- auto get_randomness = [&](int param_index) -> const VArray<float> & {
+ auto get_randomness = [&](int param_index) -> VArray<float> {
return params.readonly_single_input<float>(param_index, "Randomness");
};
auto get_r_distance = [&](int param_index) -> MutableSpan<float> {
diff --git a/source/blender/nodes/shader/nodes/node_shader_tex_white_noise.cc b/source/blender/nodes/shader/nodes/node_shader_tex_white_noise.cc
index 43ee9400551..7b4ff7fec5c 100644
--- a/source/blender/nodes/shader/nodes/node_shader_tex_white_noise.cc
+++ b/source/blender/nodes/shader/nodes/node_shader_tex_white_noise.cc
@@ -58,13 +58,13 @@ static int gpu_shader_tex_white_noise(GPUMaterial *mat,
return GPU_stack_link(mat, node, name, in, out);
}
-static void node_shader_update_tex_white_noise(bNodeTree *UNUSED(ntree), bNode *node)
+static void node_shader_update_tex_white_noise(bNodeTree *ntree, bNode *node)
{
bNodeSocket *sockVector = nodeFindSocket(node, SOCK_IN, "Vector");
bNodeSocket *sockW = nodeFindSocket(node, SOCK_IN, "W");
- nodeSetSocketAvailability(sockVector, node->custom1 != 1);
- nodeSetSocketAvailability(sockW, node->custom1 == 1 || node->custom1 == 4);
+ nodeSetSocketAvailability(ntree, sockVector, node->custom1 != 1);
+ nodeSetSocketAvailability(ntree, sockW, node->custom1 == 1 || node->custom1 == 4);
}
namespace blender::nodes {
diff --git a/source/blender/nodes/shader/nodes/node_shader_vector_math.cc b/source/blender/nodes/shader/nodes/node_shader_vector_math.cc
index ca5aeea9a7d..9b1b2467230 100644
--- a/source/blender/nodes/shader/nodes/node_shader_vector_math.cc
+++ b/source/blender/nodes/shader/nodes/node_shader_vector_math.cc
@@ -119,7 +119,7 @@ static int gpu_shader_vector_math(GPUMaterial *mat,
return 0;
}
-static void node_shader_update_vector_math(bNodeTree *UNUSED(ntree), bNode *node)
+static void node_shader_update_vector_math(bNodeTree *ntree, bNode *node)
{
bNodeSocket *sockB = (bNodeSocket *)BLI_findlink(&node->inputs, 1);
bNodeSocket *sockC = (bNodeSocket *)BLI_findlink(&node->inputs, 2);
@@ -128,7 +128,8 @@ static void node_shader_update_vector_math(bNodeTree *UNUSED(ntree), bNode *node
bNodeSocket *sockVector = nodeFindSocket(node, SOCK_OUT, "Vector");
bNodeSocket *sockValue = nodeFindSocket(node, SOCK_OUT, "Value");
- nodeSetSocketAvailability(sockB,
+ nodeSetSocketAvailability(ntree,
+ sockB,
!ELEM(node->custom1,
NODE_VECTOR_MATH_SINE,
NODE_VECTOR_MATH_COSINE,
@@ -140,19 +141,22 @@ static void node_shader_update_vector_math(bNodeTree *UNUSED(ntree), bNode *node
NODE_VECTOR_MATH_ABSOLUTE,
NODE_VECTOR_MATH_FRACTION,
NODE_VECTOR_MATH_NORMALIZE));
- nodeSetSocketAvailability(sockC,
+ nodeSetSocketAvailability(ntree,
+ sockC,
ELEM(node->custom1,
NODE_VECTOR_MATH_WRAP,
NODE_VECTOR_MATH_FACEFORWARD,
NODE_VECTOR_MATH_MULTIPLY_ADD));
- nodeSetSocketAvailability(sockScale,
- ELEM(node->custom1, NODE_VECTOR_MATH_SCALE, NODE_VECTOR_MATH_REFRACT));
- nodeSetSocketAvailability(sockVector,
+ nodeSetSocketAvailability(
+ ntree, sockScale, ELEM(node->custom1, NODE_VECTOR_MATH_SCALE, NODE_VECTOR_MATH_REFRACT));
+ nodeSetSocketAvailability(ntree,
+ sockVector,
!ELEM(node->custom1,
NODE_VECTOR_MATH_LENGTH,
NODE_VECTOR_MATH_DISTANCE,
NODE_VECTOR_MATH_DOT_PRODUCT));
- nodeSetSocketAvailability(sockValue,
+ nodeSetSocketAvailability(ntree,
+ sockValue,
ELEM(node->custom1,
NODE_VECTOR_MATH_LENGTH,
NODE_VECTOR_MATH_DISTANCE,
@@ -197,8 +201,8 @@ static const blender::fn::MultiFunction *get_multi_function(bNode &node)
blender::nodes::try_dispatch_float_math_fl3_fl3_to_fl3(
operation, [&](auto function, const blender::nodes::FloatMathOperationInfo &info) {
- static blender::fn::CustomMF_SI_SI_SO<float3, float3, float3> fn{info.title_case_name,
- function};
+ static blender::fn::CustomMF_SI_SI_SO<float3, float3, float3> fn{
+ info.title_case_name.c_str(), function};
multi_fn = &fn;
});
if (multi_fn != nullptr) {
@@ -208,7 +212,7 @@ static const blender::fn::MultiFunction *get_multi_function(bNode &node)
blender::nodes::try_dispatch_float_math_fl3_fl3_fl3_to_fl3(
operation, [&](auto function, const blender::nodes::FloatMathOperationInfo &info) {
static blender::fn::CustomMF_SI_SI_SI_SO<float3, float3, float3, float3> fn{
- info.title_case_name, function};
+ info.title_case_name.c_str(), function};
multi_fn = &fn;
});
if (multi_fn != nullptr) {
@@ -218,7 +222,7 @@ static const blender::fn::MultiFunction *get_multi_function(bNode &node)
blender::nodes::try_dispatch_float_math_fl3_fl3_fl_to_fl3(
operation, [&](auto function, const blender::nodes::FloatMathOperationInfo &info) {
static blender::fn::CustomMF_SI_SI_SI_SO<float3, float3, float, float3> fn{
- info.title_case_name, function};
+ info.title_case_name.c_str(), function};
multi_fn = &fn;
});
if (multi_fn != nullptr) {
@@ -227,8 +231,8 @@ static const blender::fn::MultiFunction *get_multi_function(bNode &node)
blender::nodes::try_dispatch_float_math_fl3_fl3_to_fl(
operation, [&](auto function, const blender::nodes::FloatMathOperationInfo &info) {
- static blender::fn::CustomMF_SI_SI_SO<float3, float3, float> fn{info.title_case_name,
- function};
+ static blender::fn::CustomMF_SI_SI_SO<float3, float3, float> fn{
+ info.title_case_name.c_str(), function};
multi_fn = &fn;
});
if (multi_fn != nullptr) {
@@ -237,8 +241,8 @@ static const blender::fn::MultiFunction *get_multi_function(bNode &node)
blender::nodes::try_dispatch_float_math_fl3_fl_to_fl3(
operation, [&](auto function, const blender::nodes::FloatMathOperationInfo &info) {
- static blender::fn::CustomMF_SI_SI_SO<float3, float, float3> fn{info.title_case_name,
- function};
+ static blender::fn::CustomMF_SI_SI_SO<float3, float, float3> fn{
+ info.title_case_name.c_str(), function};
multi_fn = &fn;
});
if (multi_fn != nullptr) {
@@ -247,7 +251,8 @@ static const blender::fn::MultiFunction *get_multi_function(bNode &node)
blender::nodes::try_dispatch_float_math_fl3_to_fl3(
operation, [&](auto function, const blender::nodes::FloatMathOperationInfo &info) {
- static blender::fn::CustomMF_SI_SO<float3, float3> fn{info.title_case_name, function};
+ static blender::fn::CustomMF_SI_SO<float3, float3> fn{info.title_case_name.c_str(),
+ function};
multi_fn = &fn;
});
if (multi_fn != nullptr) {
@@ -256,7 +261,8 @@ static const blender::fn::MultiFunction *get_multi_function(bNode &node)
blender::nodes::try_dispatch_float_math_fl3_to_fl(
operation, [&](auto function, const blender::nodes::FloatMathOperationInfo &info) {
- static blender::fn::CustomMF_SI_SO<float3, float> fn{info.title_case_name, function};
+ static blender::fn::CustomMF_SI_SO<float3, float> fn{info.title_case_name.c_str(),
+ function};
multi_fn = &fn;
});
if (multi_fn != nullptr) {
diff --git a/source/blender/nodes/shader/nodes/node_shader_vector_rotate.cc b/source/blender/nodes/shader/nodes/node_shader_vector_rotate.cc
index 1ab643bc3fa..3c1f1ed8d39 100644
--- a/source/blender/nodes/shader/nodes/node_shader_vector_rotate.cc
+++ b/source/blender/nodes/shader/nodes/node_shader_vector_rotate.cc
@@ -193,14 +193,16 @@ static void sh_node_vector_rotate_build_multi_function(
builder.set_matching_fn(fn);
}
-static void node_shader_update_vector_rotate(bNodeTree *UNUSED(ntree), bNode *node)
+static void node_shader_update_vector_rotate(bNodeTree *ntree, bNode *node)
{
bNodeSocket *sock_rotation = nodeFindSocket(node, SOCK_IN, "Rotation");
- nodeSetSocketAvailability(sock_rotation, ELEM(node->custom1, NODE_VECTOR_ROTATE_TYPE_EULER_XYZ));
+ nodeSetSocketAvailability(
+ ntree, sock_rotation, ELEM(node->custom1, NODE_VECTOR_ROTATE_TYPE_EULER_XYZ));
bNodeSocket *sock_axis = nodeFindSocket(node, SOCK_IN, "Axis");
- nodeSetSocketAvailability(sock_axis, ELEM(node->custom1, NODE_VECTOR_ROTATE_TYPE_AXIS));
+ nodeSetSocketAvailability(ntree, sock_axis, ELEM(node->custom1, NODE_VECTOR_ROTATE_TYPE_AXIS));
bNodeSocket *sock_angle = nodeFindSocket(node, SOCK_IN, "Angle");
- nodeSetSocketAvailability(sock_angle, !ELEM(node->custom1, NODE_VECTOR_ROTATE_TYPE_EULER_XYZ));
+ nodeSetSocketAvailability(
+ ntree, sock_angle, !ELEM(node->custom1, NODE_VECTOR_ROTATE_TYPE_EULER_XYZ));
}
void register_node_type_sh_vector_rotate(void)
diff --git a/source/blender/nodes/texture/node_texture_util.c b/source/blender/nodes/texture/node_texture_util.c
index 570b10d6e89..c968d0bae56 100644
--- a/source/blender/nodes/texture/node_texture_util.c
+++ b/source/blender/nodes/texture/node_texture_util.c
@@ -57,7 +57,6 @@ void tex_node_type_base(
ntype->poll = tex_node_poll_default;
ntype->insert_link = node_insert_link_default;
- ntype->update_internal_links = node_update_internal_links_default;
}
static void tex_call_delegate(TexDelegate *dg, float *out, TexParams *params, short thread)
diff --git a/source/blender/nodes/texture/nodes/node_texture_common.c b/source/blender/nodes/texture/nodes/node_texture_common.c
index 2de64779ea6..868c97e5850 100644
--- a/source/blender/nodes/texture/nodes/node_texture_common.c
+++ b/source/blender/nodes/texture/nodes/node_texture_common.c
@@ -166,7 +166,6 @@ void register_node_type_tex_group(void)
ntype.poll = tex_node_poll_default;
ntype.poll_instance = node_group_poll_instance;
ntype.insert_link = node_insert_link_default;
- ntype.update_internal_links = node_update_internal_links_default;
ntype.rna_ext.srna = RNA_struct_find("TextureNodeGroup");
BLI_assert(ntype.rna_ext.srna != NULL);
RNA_struct_blender_type_set(ntype.rna_ext.srna, &ntype);
diff --git a/source/blender/nodes/texture/nodes/node_texture_output.c b/source/blender/nodes/texture/nodes/node_texture_output.c
index b24781e032b..9145df0038b 100644
--- a/source/blender/nodes/texture/nodes/node_texture_output.c
+++ b/source/blender/nodes/texture/nodes/node_texture_output.c
@@ -172,8 +172,7 @@ void register_node_type_tex_output(void)
node_type_storage(&ntype, "TexNodeOutput", node_free_standard_storage, copy);
node_type_exec(&ntype, NULL, NULL, exec);
- /* Do not allow muting output. */
- node_type_internal_links(&ntype, NULL);
+ ntype.no_muting = true;
nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/texture/nodes/node_texture_viewer.c b/source/blender/nodes/texture/nodes/node_texture_viewer.c
index c96ff2062cb..18b11b86d6f 100644
--- a/source/blender/nodes/texture/nodes/node_texture_viewer.c
+++ b/source/blender/nodes/texture/nodes/node_texture_viewer.c
@@ -60,8 +60,7 @@ void register_node_type_tex_viewer(void)
node_type_socket_templates(&ntype, inputs, outputs);
node_type_exec(&ntype, NULL, NULL, exec);
- /* Do not allow muting viewer node. */
- node_type_internal_links(&ntype, NULL);
+ ntype.no_muting = true;
nodeRegisterType(&ntype);
}
diff --git a/source/blender/python/generic/blf_py_api.c b/source/blender/python/generic/blf_py_api.c
index 9e725730d40..a49c943df94 100644
--- a/source/blender/python/generic/blf_py_api.c
+++ b/source/blender/python/generic/blf_py_api.c
@@ -70,14 +70,15 @@ PyDoc_STRVAR(py_blf_size_doc,
"font use 0.\n"
" :type fontid: int\n"
" :arg size: Point size of the font.\n"
- " :type size: int\n"
+ " :type size: float\n"
" :arg dpi: dots per inch value to use for drawing.\n"
" :type dpi: int\n");
static PyObject *py_blf_size(PyObject *UNUSED(self), PyObject *args)
{
- int fontid, size, dpi;
+ int fontid, dpi;
+ float size;
- if (!PyArg_ParseTuple(args, "iii:blf.size", &fontid, &size, &dpi)) {
+ if (!PyArg_ParseTuple(args, "ifi:blf.size", &fontid, &size, &dpi)) {
return NULL;
}
diff --git a/source/blender/python/intern/bpy.c b/source/blender/python/intern/bpy.c
index 7646109c1b0..3377b2c283e 100644
--- a/source/blender/python/intern/bpy.c
+++ b/source/blender/python/intern/bpy.c
@@ -22,9 +22,13 @@
* A script writer should never directly access this module.
*/
+/* Future-proof, See https://docs.python.org/3/c-api/arg.html#strings-and-buffers */
+#define PY_SSIZE_T_CLEAN
+
#include <Python.h>
#include "BLI_string.h"
+#include "BLI_string_utils.h"
#include "BLI_utildefines.h"
#include "BKE_appdir.h"
@@ -149,6 +153,52 @@ static PyObject *bpy_blend_paths(PyObject *UNUSED(self), PyObject *args, PyObjec
return list;
}
+PyDoc_STRVAR(bpy_flip_name_doc,
+ ".. function:: flip_name(name, strip_digits=False)\n"
+ "\n"
+ " Flip a name between left/right sides, useful for \n"
+ " mirroring bone names.\n"
+ "\n"
+ " :arg name: Bone name to flip.\n"
+ " :type name: string\n"
+ " :arg strip_digits: Whether to remove ``.###`` suffix.\n"
+ " :type strip_digits: bool\n"
+ " :return: The flipped name.\n"
+ " :rtype: string\n");
+static PyObject *bpy_flip_name(PyObject *UNUSED(self), PyObject *args, PyObject *kw)
+{
+ const char *name_src = NULL;
+ Py_ssize_t name_src_len;
+ bool strip_digits = false;
+
+ static const char *_keywords[] = {"", "strip_digits", NULL};
+ static _PyArg_Parser _parser = {
+ "s#" /* `name` */
+ "|$" /* Optional, keyword only arguments. */
+ "O&" /* `strip_digits` */
+ /* Name to show in the case of an error. */
+ ":flip_name",
+ _keywords,
+ 0,
+ };
+ if (!_PyArg_ParseTupleAndKeywordsFast(
+ args, kw, &_parser, &name_src, &name_src_len, PyC_ParseBool, &strip_digits)) {
+ return NULL;
+ }
+
+ /* Worst case we gain one extra byte (besides null-terminator) by changing
+ "Left" to "Right", because only the first appearance of "Left" gets replaced. */
+ const size_t size = name_src_len + 2;
+ char *name_dst = PyMem_MALLOC(size);
+ const size_t name_dst_len = BLI_string_flip_side_name(name_dst, name_src, strip_digits, size);
+
+ PyObject *result = PyUnicode_FromStringAndSize(name_dst, name_dst_len);
+
+ PyMem_FREE(name_dst);
+
+ return result;
+}
+
// PyDoc_STRVAR(bpy_user_resource_doc[] = /* now in bpy/utils.py */
static PyObject *bpy_user_resource(PyObject *UNUSED(self), PyObject *args, PyObject *kw)
{
@@ -338,6 +388,12 @@ static PyMethodDef meth_bpy_blend_paths = {
METH_VARARGS | METH_KEYWORDS,
bpy_blend_paths_doc,
};
+static PyMethodDef meth_bpy_flip_name = {
+ "flip_name",
+ (PyCFunction)bpy_flip_name,
+ METH_VARARGS | METH_KEYWORDS,
+ bpy_flip_name_doc,
+};
static PyMethodDef meth_bpy_user_resource = {
"user_resource",
(PyCFunction)bpy_user_resource,
@@ -472,6 +528,8 @@ void BPy_init_modules(struct bContext *C)
PyModule_AddObject(mod,
meth_bpy_unescape_identifier.ml_name,
(PyObject *)PyCFunction_New(&meth_bpy_unescape_identifier, NULL));
+ PyModule_AddObject(
+ mod, meth_bpy_flip_name.ml_name, (PyObject *)PyCFunction_New(&meth_bpy_flip_name, NULL));
/* register funcs (bpy_rna.c) */
PyModule_AddObject(mod,
diff --git a/source/blender/python/intern/bpy_operator.c b/source/blender/python/intern/bpy_operator.c
index 5ae123f3254..ae42af7cd85 100644
--- a/source/blender/python/intern/bpy_operator.c
+++ b/source/blender/python/intern/bpy_operator.c
@@ -81,7 +81,7 @@ static PyObject *pyop_poll(PyObject *UNUSED(self), PyObject *args)
const char *context_str = NULL;
PyObject *ret;
- int context = WM_OP_EXEC_DEFAULT;
+ wmOperatorCallContext context = WM_OP_EXEC_DEFAULT;
/* XXX TODO: work out a better solution for passing on context,
* could make a tuple from self and pack the name and Context into it. */
@@ -107,7 +107,9 @@ static PyObject *pyop_poll(PyObject *UNUSED(self), PyObject *args)
}
if (context_str) {
- if (RNA_enum_value_from_id(rna_enum_operator_context_items, context_str, &context) == 0) {
+ int context_int = context;
+
+ if (RNA_enum_value_from_id(rna_enum_operator_context_items, context_str, &context_int) == 0) {
char *enum_str = pyrna_enum_repr(rna_enum_operator_context_items);
PyErr_Format(PyExc_TypeError,
"Calling operator \"bpy.ops.%s.poll\" error, "
@@ -117,6 +119,8 @@ static PyObject *pyop_poll(PyObject *UNUSED(self), PyObject *args)
MEM_freeN(enum_str);
return NULL;
}
+ /* Copy back to the properly typed enum. */
+ context = context_int;
}
if (ELEM(context_dict, NULL, Py_None)) {
@@ -166,8 +170,7 @@ static PyObject *pyop_call(PyObject *UNUSED(self), PyObject *args)
PyObject *kw = NULL; /* optional args */
PyObject *context_dict = NULL; /* optional args */
- /* note that context is an int, python does the conversion in this case */
- int context = WM_OP_EXEC_DEFAULT;
+ wmOperatorCallContext context = WM_OP_EXEC_DEFAULT;
int is_undo = false;
/* XXX TODO: work out a better solution for passing on context,
@@ -209,7 +212,9 @@ static PyObject *pyop_call(PyObject *UNUSED(self), PyObject *args)
}
if (context_str) {
- if (RNA_enum_value_from_id(rna_enum_operator_context_items, context_str, &context) == 0) {
+ int context_int = context;
+
+ if (RNA_enum_value_from_id(rna_enum_operator_context_items, context_str, &context_int) == 0) {
char *enum_str = pyrna_enum_repr(rna_enum_operator_context_items);
PyErr_Format(PyExc_TypeError,
"Calling operator \"bpy.ops.%s\" error, "
@@ -219,6 +224,8 @@ static PyObject *pyop_call(PyObject *UNUSED(self), PyObject *args)
MEM_freeN(enum_str);
return NULL;
}
+ /* Copy back to the properly typed enum. */
+ context = context_int;
}
if (ELEM(context_dict, NULL, Py_None)) {
diff --git a/source/blender/python/intern/bpy_props.c b/source/blender/python/intern/bpy_props.c
index 6d384ed9358..13c7d2947cf 100644
--- a/source/blender/python/intern/bpy_props.c
+++ b/source/blender/python/intern/bpy_props.c
@@ -366,7 +366,7 @@ static PyObject *bpy_prop_deferred_call(BPy_PropDeferred *UNUSED(self),
/**
* Expose the function in case scripts need to introspect this information
- * (not currently used by Blender it's self).
+ * (not currently used by Blender itself).
*/
static PyObject *bpy_prop_deferred_function_get(BPy_PropDeferred *self, void *UNUSED(closure))
{
@@ -377,7 +377,7 @@ static PyObject *bpy_prop_deferred_function_get(BPy_PropDeferred *self, void *UN
/**
* Expose keywords in case scripts need to introspect this information
- * (not currently used by Blender it's self).
+ * (not currently used by Blender itself).
*/
static PyObject *bpy_prop_deferred_keywords_get(BPy_PropDeferred *self, void *UNUSED(closure))
{
diff --git a/source/blender/python/intern/bpy_rna.c b/source/blender/python/intern/bpy_rna.c
index 7b1877f3191..707de1c2581 100644
--- a/source/blender/python/intern/bpy_rna.c
+++ b/source/blender/python/intern/bpy_rna.c
@@ -7693,7 +7693,7 @@ PyObject *BPY_rna_doc(void)
/**
* This could be a static variable as we only have one `bpy.types` module,
- * it just keeps the data isolated to store in the module it's self.
+ * it just keeps the data isolated to store in the module itself.
*
* This data doesn't change one initialized.
*/
diff --git a/source/blender/sequencer/SEQ_edit.h b/source/blender/sequencer/SEQ_edit.h
index fbbf4bc53ea..f3a64c9cd62 100644
--- a/source/blender/sequencer/SEQ_edit.h
+++ b/source/blender/sequencer/SEQ_edit.h
@@ -33,10 +33,15 @@ struct Scene;
struct Sequence;
int SEQ_edit_sequence_swap(struct Sequence *seq_a, struct Sequence *seq_b, const char **error_str);
+bool SEQ_edit_move_strip_to_seqbase(struct Scene *scene,
+ ListBase *seqbase,
+ struct Sequence *src_seq,
+ ListBase *dst_seqbase);
bool SEQ_edit_move_strip_to_meta(struct Scene *scene,
struct Sequence *src_seq,
struct Sequence *dst_seqm,
const char **error_str);
+bool SEQ_meta_separate(struct Scene *scene, struct Sequence *src_meta, const char **error_str);
void SEQ_edit_flag_for_removal(struct Scene *scene,
struct ListBase *seqbase,
struct Sequence *seq);
diff --git a/source/blender/sequencer/intern/effects.c b/source/blender/sequencer/intern/effects.c
index b9ee23a9186..6a6889c3679 100644
--- a/source/blender/sequencer/intern/effects.c
+++ b/source/blender/sequencer/intern/effects.c
@@ -2942,6 +2942,9 @@ static ImBuf *do_solid_color(const SeqRenderData *context,
}
}
}
+
+ out->planes = R_IMF_PLANES_RGB;
+
return out;
}
@@ -3741,7 +3744,7 @@ static void init_text_effect(Sequence *seq)
data = seq->effectdata = MEM_callocN(sizeof(TextVars), "textvars");
data->text_font = NULL;
data->text_blf_id = -1;
- data->text_size = 60;
+ data->text_size = 60.0f;
copy_v4_fl(data->color, 1.0f);
data->shadow_color[3] = 0.7f;
@@ -3842,7 +3845,7 @@ static int num_inputs_text(void)
static int early_out_text(Sequence *seq, float UNUSED(facf0), float UNUSED(facf1))
{
TextVars *data = seq->effectdata;
- if (data->text[0] == 0 || data->text_size < 1 ||
+ if (data->text[0] == 0 || data->text_size < 1.0f ||
((data->color[3] == 0.0f) &&
(data->shadow_color[3] == 0.0f || (data->flag & SEQ_TEXT_SHADOW) == 0))) {
return EARLY_USE_INPUT_1;
@@ -4024,6 +4027,14 @@ static int early_out_mul_input2(Sequence *UNUSED(seq), float facf0, float facf1)
return EARLY_DO_EFFECT;
}
+static int early_out_mul_input1(Sequence *UNUSED(seq), float facf0, float facf1)
+{
+ if (facf0 == 0.0f && facf1 == 0.0f) {
+ return EARLY_USE_INPUT_2;
+ }
+ return EARLY_DO_EFFECT;
+}
+
static void get_default_fac_noop(Sequence *UNUSED(seq),
float UNUSED(timeline_frame),
float *facf0,
@@ -4134,6 +4145,7 @@ static struct SeqEffectHandle get_sequence_effect_impl(int seq_type)
rval.multithreaded = true;
rval.init = init_alpha_over_or_under;
rval.execute_slice = do_alphaover_effect;
+ rval.early_out = early_out_mul_input1;
break;
case SEQ_TYPE_OVERDROP:
rval.multithreaded = true;
diff --git a/source/blender/sequencer/intern/render.c b/source/blender/sequencer/intern/render.c
index 8ce3398024d..6030b49537c 100644
--- a/source/blender/sequencer/intern/render.c
+++ b/source/blender/sequencer/intern/render.c
@@ -466,6 +466,45 @@ static void sequencer_thumbnail_transform(ImBuf *in, ImBuf *out)
IMB_transform(in, out, transform_matrix, &source_crop, IMB_FILTER_NEAREST);
}
+/* Check whether transform introduces transparent ares in the result (happens when the transformed
+ * image does not fully cover the render frame).
+ *
+ * The check is done by checking whether all corners of viewport fit inside of the transformed
+ * image. If they do not the image will have transparent areas. */
+static bool seq_image_transform_transparency_gained(const SeqRenderData *context, Sequence *seq)
+{
+ Scene *scene = context->scene;
+ const int x = context->rectx;
+ const int y = context->recty;
+
+ float seq_image_quad[4][2];
+ SEQ_image_transform_final_quad_get(scene, seq, seq_image_quad);
+ for (int i = 0; i < 4; i++) {
+ add_v2_v2(seq_image_quad[i], (float[]){x / 2, y / 2});
+ }
+
+ return !isect_point_quad_v2((float[]){x, y},
+ seq_image_quad[0],
+ seq_image_quad[1],
+ seq_image_quad[2],
+ seq_image_quad[3]) ||
+ !isect_point_quad_v2((float[]){0, y},
+ seq_image_quad[0],
+ seq_image_quad[1],
+ seq_image_quad[2],
+ seq_image_quad[3]) ||
+ !isect_point_quad_v2((float[]){x, 0},
+ seq_image_quad[0],
+ seq_image_quad[1],
+ seq_image_quad[2],
+ seq_image_quad[3]) ||
+ !isect_point_quad_v2((float[]){0, 0},
+ seq_image_quad[0],
+ seq_image_quad[1],
+ seq_image_quad[2],
+ seq_image_quad[3]);
+}
+
static void sequencer_preprocess_transform_crop(
ImBuf *in, ImBuf *out, const SeqRenderData *context, Sequence *seq, const bool is_proxy_image)
{
@@ -490,6 +529,13 @@ static void sequencer_preprocess_transform_crop(
const eIMBInterpolationFilterMode filter = context->for_render ? IMB_FILTER_BILINEAR :
IMB_FILTER_NEAREST;
IMB_transform(in, out, transform_matrix, &source_crop, filter);
+
+ if (!seq_image_transform_transparency_gained(context, seq)) {
+ out->planes = in->planes;
+ }
+ else {
+ out->planes = R_IMF_PLANES_RGBA;
+ }
}
static void multibuf(ImBuf *ibuf, const float fmul)
@@ -525,6 +571,10 @@ static void multibuf(ImBuf *ibuf, const float fmul)
rt_float += 4;
}
}
+
+ if (ELEM(ibuf->planes, R_IMF_PLANES_BW, R_IMF_PLANES_RGB) && fmul < 1.0f) {
+ ibuf->planes = R_IMF_PLANES_RGBA;
+ }
}
static ImBuf *input_preprocess(const SeqRenderData *context,
@@ -1804,6 +1854,20 @@ static ImBuf *seq_render_strip_stack(const SeqRenderData *context,
early_out = seq_get_early_out_for_blend_mode(seq);
+ /* Early out for alpha over. It requires image to be rendered, so it can't use
+ * `seq_get_early_out_for_blend_mode`. */
+ if (out == NULL && seq->blend_mode == SEQ_TYPE_ALPHAOVER && seq->blend_opacity == 100.0f) {
+ ImBuf *test = seq_render_strip(context, state, seq, timeline_frame);
+ if (ELEM(test->planes, R_IMF_PLANES_BW, R_IMF_PLANES_RGB)) {
+ early_out = EARLY_USE_INPUT_2;
+ }
+ else {
+ early_out = EARLY_DO_EFFECT;
+ }
+ /* Free the image. It is stored in cache, so this doesn't affect performance. */
+ IMB_freeImBuf(test);
+ }
+
switch (early_out) {
case EARLY_NO_INPUT:
case EARLY_USE_INPUT_2:
@@ -1828,6 +1892,7 @@ static ImBuf *seq_render_strip_stack(const SeqRenderData *context,
}
break;
}
+
if (out) {
break;
}
diff --git a/source/blender/sequencer/intern/strip_add.c b/source/blender/sequencer/intern/strip_add.c
index 70ac2620e20..382fdd4953f 100644
--- a/source/blender/sequencer/intern/strip_add.c
+++ b/source/blender/sequencer/intern/strip_add.c
@@ -159,7 +159,7 @@ Sequence *SEQ_add_scene_strip(Scene *scene, ListBase *seqbase, struct SeqLoadDat
{
Sequence *seq = SEQ_sequence_alloc(
seqbase, load_data->start_frame, load_data->channel, SEQ_TYPE_SCENE);
- seq->blend_mode = SEQ_TYPE_CROSS;
+ seq->blend_mode = SEQ_TYPE_ALPHAOVER;
seq->scene = load_data->scene;
seq->len = load_data->scene->r.efra - load_data->scene->r.sfra + 1;
id_us_ensure_real((ID *)load_data->scene);
@@ -180,7 +180,7 @@ Sequence *SEQ_add_movieclip_strip(Scene *scene, ListBase *seqbase, struct SeqLoa
{
Sequence *seq = SEQ_sequence_alloc(
seqbase, load_data->start_frame, load_data->channel, SEQ_TYPE_MOVIECLIP);
- seq->blend_mode = SEQ_TYPE_CROSS;
+ seq->blend_mode = SEQ_TYPE_ALPHAOVER;
seq->clip = load_data->clip;
seq->len = BKE_movieclip_get_duration(load_data->clip);
id_us_ensure_real((ID *)load_data->clip);
@@ -201,7 +201,7 @@ Sequence *SEQ_add_mask_strip(Scene *scene, ListBase *seqbase, struct SeqLoadData
{
Sequence *seq = SEQ_sequence_alloc(
seqbase, load_data->start_frame, load_data->channel, SEQ_TYPE_MASK);
- seq->blend_mode = SEQ_TYPE_CROSS;
+ seq->blend_mode = SEQ_TYPE_ALPHAOVER;
seq->mask = load_data->mask;
seq->len = BKE_mask_get_duration(load_data->mask);
id_us_ensure_real((ID *)load_data->mask);
@@ -230,18 +230,12 @@ Sequence *SEQ_add_effect_strip(Scene *scene, ListBase *seqbase, struct SeqLoadDa
seq->seq2 = load_data->effect.seq2;
seq->seq3 = load_data->effect.seq3;
- if (seq->type == SEQ_TYPE_COLOR) {
- seq->blend_mode = SEQ_TYPE_CROSS;
- }
- else if (seq->type == SEQ_TYPE_ADJUSTMENT) {
- seq->blend_mode = SEQ_TYPE_CROSS;
+ if (SEQ_effect_get_num_inputs(seq->type) == 1) {
+ seq->blend_mode = seq->seq1->blend_mode;
}
- else if (seq->type == SEQ_TYPE_TEXT) {
+ else {
seq->blend_mode = SEQ_TYPE_ALPHAOVER;
}
- else if (SEQ_effect_get_num_inputs(seq->type) == 1) {
- seq->blend_mode = seq->seq1->blend_mode;
- }
if (!load_data->effect.seq1) {
seq->len = 1; /* Effect is generator, set non zero length. */
@@ -326,7 +320,7 @@ Sequence *SEQ_add_image_strip(Main *bmain, Scene *scene, ListBase *seqbase, SeqL
{
Sequence *seq = SEQ_sequence_alloc(
seqbase, load_data->start_frame, load_data->channel, SEQ_TYPE_IMAGE);
- seq->blend_mode = SEQ_TYPE_CROSS; /* so alpha adjustment fade to the strip below */
+ seq->blend_mode = SEQ_TYPE_ALPHAOVER; /* so alpha adjustment fade to the strip below */
seq->len = load_data->image.len;
Strip *strip = seq->strip;
strip->stripdata = MEM_callocN(load_data->image.len * sizeof(StripElem), "stripelem");
@@ -587,7 +581,7 @@ Sequence *SEQ_add_movie_strip(
}
}
- seq->blend_mode = SEQ_TYPE_CROSS; /* so alpha adjustment fade to the strip below */
+ seq->blend_mode = SEQ_TYPE_ALPHAOVER; /* so alpha adjustment fade to the strip below */
if (anim_arr[0] != NULL) {
seq->len = IMB_anim_get_duration(anim_arr[0], IMB_TC_RECORD_RUN);
diff --git a/source/blender/sequencer/intern/strip_edit.c b/source/blender/sequencer/intern/strip_edit.c
index 747f0eb3deb..00b3da86306 100644
--- a/source/blender/sequencer/intern/strip_edit.c
+++ b/source/blender/sequencer/intern/strip_edit.c
@@ -221,6 +221,40 @@ static bool seq_exists_in_seqbase(Sequence *seq, ListBase *seqbase)
return false;
}
+/**
+ * Move sequence to seqbase.
+ *
+ * \param scene: Scene containing the editing
+ * \param dst_seqbase: seqbase where `seq` is located
+ * \param seq: Sequence to move
+ * \param dst_seqbase: Target seqbase
+ */
+bool SEQ_edit_move_strip_to_seqbase(Scene *scene,
+ ListBase *seqbase,
+ Sequence *seq,
+ ListBase *dst_seqbase)
+{
+ /* Move to meta. */
+ BLI_remlink(seqbase, seq);
+ BLI_addtail(dst_seqbase, seq);
+ SEQ_relations_invalidate_cache_preprocessed(scene, seq);
+
+ /* Update meta. */
+ if (SEQ_transform_test_overlap(dst_seqbase, seq)) {
+ SEQ_transform_seqbase_shuffle(dst_seqbase, seq, scene);
+ }
+
+ return true;
+}
+
+/**
+ * Move sequence to meta sequence.
+ *
+ * \param scene: Scene containing the editing
+ * \param src_seq: Sequence to move
+ * \param dst_seqm: Target Meta sequence
+ * \param error_str: Error message
+ */
bool SEQ_edit_move_strip_to_meta(Scene *scene,
Sequence *src_seq,
Sequence *dst_seqm,
@@ -262,17 +296,7 @@ bool SEQ_edit_move_strip_to_meta(Scene *scene,
Sequence *seq;
SEQ_ITERATOR_FOREACH (seq, collection) {
/* Move to meta. */
- BLI_remlink(seqbase, seq);
- BLI_addtail(&dst_seqm->seqbase, seq);
- SEQ_relations_invalidate_cache_preprocessed(scene, seq);
-
- /* Update meta. */
- ListBase *meta_seqbase = SEQ_get_seqbase_by_seq(&ed->seqbase, dst_seqm);
- SEQ_time_update_meta_strip_range(scene, dst_seqm);
- SEQ_time_update_sequence(scene, meta_seqbase, dst_seqm);
- if (SEQ_transform_test_overlap(&dst_seqm->seqbase, seq)) {
- SEQ_transform_seqbase_shuffle(&dst_seqm->seqbase, seq, scene);
- }
+ SEQ_edit_move_strip_to_seqbase(scene, seqbase, seq, &dst_seqm->seqbase);
}
SEQ_collection_free(collection);
diff --git a/source/blender/sequencer/intern/strip_transform.c b/source/blender/sequencer/intern/strip_transform.c
index becf44a7a8e..63ab4a30edc 100644
--- a/source/blender/sequencer/intern/strip_transform.c
+++ b/source/blender/sequencer/intern/strip_transform.c
@@ -520,10 +520,11 @@ static void seq_image_transform_quad_get_ex(const Scene *scene,
}
/**
- * Get 4 corner points of strip image, optionally without rotation component applied
+ * Get 4 corner points of strip image, optionally without rotation component applied.
+ * Corner vectors are in viewport space.
*
* \param scene: Scene in which strips are located
- * \param seq: Sequence to calculate image transform origin
+ * \param seq: Sequence to calculate transformed image quad
* \param apply_rotation: Apply sequence rotation transform to the quad
* \param r_quad: array of 4 2D vectors
*/
@@ -536,10 +537,10 @@ void SEQ_image_transform_quad_get(const Scene *scene,
}
/**
- * Get 4 corner points of strip image.
+ * Get 4 corner points of strip image. Corner vectors are in viewport space.
*
* \param scene: Scene in which strips are located
- * \param seq: Sequence to calculate image transform origin
+ * \param seq: Sequence to calculate transformed image quad
* \param r_quad: array of 4 2D vectors
*/
void SEQ_image_transform_final_quad_get(const Scene *scene,
diff --git a/source/blender/windowmanager/WM_api.h b/source/blender/windowmanager/WM_api.h
index ef81addbb4d..c41c328c006 100644
--- a/source/blender/windowmanager/WM_api.h
+++ b/source/blender/windowmanager/WM_api.h
@@ -413,7 +413,7 @@ int WM_generic_select_invoke(struct bContext *C,
const struct wmEvent *event);
void WM_operator_view3d_unit_defaults(struct bContext *C, struct wmOperator *op);
int WM_operator_smooth_viewtx_get(const struct wmOperator *op);
-int WM_menu_invoke_ex(struct bContext *C, struct wmOperator *op, int opcontext);
+int WM_menu_invoke_ex(struct bContext *C, struct wmOperator *op, wmOperatorCallContext opcontext);
int WM_menu_invoke(struct bContext *C, struct wmOperator *op, const struct wmEvent *event);
void WM_menu_name_call(struct bContext *C, const char *menu_name, short context);
int WM_enum_search_invoke_previews(struct bContext *C,
@@ -451,7 +451,7 @@ int WM_operator_confirm_message_ex(struct bContext *C,
const char *title,
const int icon,
const char *message,
- const short opcontext);
+ const wmOperatorCallContext opcontext);
int WM_operator_confirm_message(struct bContext *C, struct wmOperator *op, const char *message);
/* operator api */
@@ -474,26 +474,26 @@ bool WM_operator_is_repeat(const struct bContext *C, const struct wmOperator *op
bool WM_operator_name_poll(struct bContext *C, const char *opstring);
int WM_operator_name_call_ptr(struct bContext *C,
struct wmOperatorType *ot,
- short context,
+ wmOperatorCallContext context,
struct PointerRNA *properties);
int WM_operator_name_call(struct bContext *C,
const char *opstring,
- short context,
+ wmOperatorCallContext context,
struct PointerRNA *properties);
int WM_operator_name_call_with_properties(struct bContext *C,
const char *opstring,
- short context,
+ wmOperatorCallContext context,
struct IDProperty *properties);
int WM_operator_call_py(struct bContext *C,
struct wmOperatorType *ot,
- short context,
+ wmOperatorCallContext context,
struct PointerRNA *properties,
struct ReportList *reports,
const bool is_undo);
void WM_operator_name_call_ptr_with_depends_on_cursor(struct bContext *C,
wmOperatorType *ot,
- short opcontext,
+ wmOperatorCallContext opcontext,
PointerRNA *properties,
const char *drawstr);
diff --git a/source/blender/windowmanager/WM_keymap.h b/source/blender/windowmanager/WM_keymap.h
index 564afe084b9..0633ffe55ea 100644
--- a/source/blender/windowmanager/WM_keymap.h
+++ b/source/blender/windowmanager/WM_keymap.h
@@ -26,6 +26,7 @@
/* dna-savable wmStructs here */
#include "BLI_utildefines.h"
#include "DNA_windowmanager_types.h"
+#include "WM_types.h"
#ifdef __cplusplus
extern "C" {
@@ -169,14 +170,14 @@ int WM_keymap_item_raw_to_string(const short shift,
const int result_len);
wmKeyMapItem *WM_key_event_operator(const struct bContext *C,
const char *opname,
- int opcontext,
+ wmOperatorCallContext opcontext,
struct IDProperty *properties,
const short include_mask,
const short exclude_mask,
struct wmKeyMap **r_keymap);
char *WM_key_event_operator_string(const struct bContext *C,
const char *opname,
- int opcontext,
+ wmOperatorCallContext opcontext,
struct IDProperty *properties,
const bool is_strict,
char *result,
diff --git a/source/blender/windowmanager/WM_types.h b/source/blender/windowmanager/WM_types.h
index 27c8aa532f2..b8fe3786bde 100644
--- a/source/blender/windowmanager/WM_types.h
+++ b/source/blender/windowmanager/WM_types.h
@@ -211,7 +211,7 @@ enum {
* Context to call operator in for #WM_operator_name_call.
* rna_ui.c contains EnumPropertyItem's of these, keep in sync.
*/
-enum {
+typedef enum wmOperatorCallContext {
/* if there's invoke, call it, otherwise exec */
WM_OP_INVOKE_DEFAULT,
WM_OP_INVOKE_REGION_WIN,
@@ -226,9 +226,11 @@ enum {
WM_OP_EXEC_REGION_PREVIEW,
WM_OP_EXEC_AREA,
WM_OP_EXEC_SCREEN,
-};
+} wmOperatorCallContext;
-#define WM_OP_CONTEXT_HAS_AREA(type) (!ELEM(type, WM_OP_INVOKE_SCREEN, WM_OP_EXEC_SCREEN))
+#define WM_OP_CONTEXT_HAS_AREA(type) \
+ (CHECK_TYPE_INLINE(type, wmOperatorCallContext), \
+ !ELEM(type, WM_OP_INVOKE_SCREEN, WM_OP_EXEC_SCREEN))
#define WM_OP_CONTEXT_HAS_REGION(type) \
(WM_OP_CONTEXT_HAS_AREA(type) && !ELEM(type, WM_OP_INVOKE_AREA, WM_OP_EXEC_AREA))
@@ -923,7 +925,7 @@ typedef struct wmOperatorType {
typedef struct wmOperatorCallParams {
struct wmOperatorType *optype;
struct PointerRNA *opptr;
- short opcontext;
+ wmOperatorCallContext opcontext;
} wmOperatorCallParams;
#ifdef WITH_INPUT_IME
@@ -1079,6 +1081,10 @@ typedef struct wmDrag {
/**
* Dropboxes are like keymaps, part of the screen/area/region definition.
* Allocation and free is on startup and exit.
+ *
+ * The operator is polled and invoked with the current context (#WM_OP_INVOKE_DEFAULT), there is no
+ * way to override that (by design, since dropboxes should act on the exact mouse position). So the
+ * drop-boxes are supposed to check the required area and region context in their poll.
*/
typedef struct wmDropBox {
struct wmDropBox *next, *prev;
@@ -1120,10 +1126,6 @@ typedef struct wmDropBox {
struct IDProperty *properties;
/** RNA pointer to access properties. */
struct PointerRNA *ptr;
-
- /** Default invoke. */
- short opcontext;
-
} wmDropBox;
/**
diff --git a/source/blender/windowmanager/gizmo/WM_gizmo_types.h b/source/blender/windowmanager/gizmo/WM_gizmo_types.h
index ceaec94e70b..8bf82a41c91 100644
--- a/source/blender/windowmanager/gizmo/WM_gizmo_types.h
+++ b/source/blender/windowmanager/gizmo/WM_gizmo_types.h
@@ -29,6 +29,7 @@
#pragma once
#include "BLI_compiler_attrs.h"
+#include "BLI_utildefines.h"
struct wmGizmo;
struct wmGizmoGroup;
@@ -163,6 +164,8 @@ typedef enum eWM_GizmoFlagGroupTypeFlag {
WM_GIZMOGROUPTYPE_VR_REDRAWS = (1 << 10),
} eWM_GizmoFlagGroupTypeFlag;
+ENUM_OPERATORS(eWM_GizmoFlagGroupTypeFlag, WM_GIZMOGROUPTYPE_VR_REDRAWS);
+
/**
* #wmGizmoGroup.init_flag
*/
diff --git a/source/blender/windowmanager/intern/wm.c b/source/blender/windowmanager/intern/wm.c
index 4458b386ab6..47ee296823b 100644
--- a/source/blender/windowmanager/intern/wm.c
+++ b/source/blender/windowmanager/intern/wm.c
@@ -91,13 +91,18 @@ static void window_manager_foreach_id(ID *id, LibraryForeachIDData *data)
/* This pointer can be NULL during old files reading, better be safe than sorry. */
if (win->workspace_hook != NULL) {
ID *workspace = (ID *)BKE_workspace_active_get(win->workspace_hook);
- BKE_LIB_FOREACHID_PROCESS_ID(data, workspace, IDWALK_CB_NOP);
+ BKE_lib_query_foreachid_process(data, &workspace, IDWALK_CB_USER);
/* Allow callback to set a different workspace. */
BKE_workspace_active_set(win->workspace_hook, (WorkSpace *)workspace);
+ if (BKE_lib_query_foreachid_iter_stop(data)) {
+ return;
+ }
}
+
if (BKE_lib_query_foreachid_process_flags_get(data) & IDWALK_INCLUDE_UI) {
LISTBASE_FOREACH (ScrArea *, area, &win->global_areas.areabase) {
- BKE_screen_foreach_id_screen_area(data, area);
+ BKE_LIB_FOREACHID_PROCESS_FUNCTION_CALL(data,
+ BKE_screen_foreach_id_screen_area(data, area));
}
}
}
diff --git a/source/blender/windowmanager/intern/wm_dragdrop.c b/source/blender/windowmanager/intern/wm_dragdrop.c
index 49b84abf9a2..bc87347b2f3 100644
--- a/source/blender/windowmanager/intern/wm_dragdrop.c
+++ b/source/blender/windowmanager/intern/wm_dragdrop.c
@@ -122,7 +122,6 @@ wmDropBox *WM_dropbox_add(ListBase *lb,
drop->cancel = cancel;
drop->tooltip = tooltip;
drop->ot = WM_operatortype_find(idname, 0);
- drop->opcontext = WM_OP_INVOKE_DEFAULT;
if (drop->ot == NULL) {
MEM_freeN(drop);
@@ -324,7 +323,8 @@ static wmDropBox *dropbox_active(bContext *C,
continue;
}
- if (WM_operator_poll_context(C, drop->ot, drop->opcontext)) {
+ const wmOperatorCallContext opcontext = wm_drop_operator_context_get(drop);
+ if (WM_operator_poll_context(C, drop->ot, opcontext)) {
return drop;
}
@@ -392,10 +392,11 @@ static void wm_drop_update_active(bContext *C, wmDrag *drag, const wmEvent *even
void wm_drop_prepare(bContext *C, wmDrag *drag, wmDropBox *drop)
{
+ const wmOperatorCallContext opcontext = wm_drop_operator_context_get(drop);
/* Optionally copy drag information to operator properties. Don't call it if the
* operator fails anyway, it might do more than just set properties (e.g.
* typically import an asset). */
- if (drop->copy && WM_operator_poll_context(C, drop->ot, drop->opcontext)) {
+ if (drop->copy && WM_operator_poll_context(C, drop->ot, opcontext)) {
drop->copy(drag, drop);
}
@@ -423,6 +424,16 @@ void wm_drags_check_ops(bContext *C, const wmEvent *event)
}
}
+/**
+ * The operator of a dropbox should always be executed in the context determined by the mouse
+ * coordinates. The dropbox poll should check the context area and region as needed.
+ * So this always returns #WM_OP_INVOKE_DEFAULT.
+ */
+wmOperatorCallContext wm_drop_operator_context_get(const wmDropBox *UNUSED(drop))
+{
+ return WM_OP_INVOKE_DEFAULT;
+}
+
/* ************** IDs ***************** */
void WM_drag_add_local_ID(wmDrag *drag, ID *id, ID *from_parent)
diff --git a/source/blender/windowmanager/intern/wm_draw.c b/source/blender/windowmanager/intern/wm_draw.c
index 8acce240046..d8d57a9370c 100644
--- a/source/blender/windowmanager/intern/wm_draw.c
+++ b/source/blender/windowmanager/intern/wm_draw.c
@@ -108,6 +108,8 @@ static void wm_paintcursor_draw(bContext *C, ScrArea *area, ARegion *region)
}
if (pc->poll == NULL || pc->poll(C)) {
+ UI_SetTheme(area->spacetype, region->regiontype);
+
/* Prevent drawing outside region. */
GPU_scissor_test(true);
GPU_scissor(region->winrct.xmin,
@@ -839,6 +841,7 @@ static void wm_draw_window_onscreen(bContext *C, wmWindow *win, int view)
}
/* After area regions so we can do area 'overlay' drawing. */
+ UI_SetTheme(0, 0);
ED_screen_draw_edges(win);
wm_draw_callbacks(win);
wmWindowViewport(win);
diff --git a/source/blender/windowmanager/intern/wm_event_system.c b/source/blender/windowmanager/intern/wm_event_system.c
index b780fef289a..474d900a53d 100644
--- a/source/blender/windowmanager/intern/wm_event_system.c
+++ b/source/blender/windowmanager/intern/wm_event_system.c
@@ -108,7 +108,7 @@ static int wm_operator_call_internal(bContext *C,
wmOperatorType *ot,
PointerRNA *properties,
ReportList *reports,
- const short context,
+ const wmOperatorCallContext context,
const bool poll_only,
wmEvent *event);
@@ -1460,7 +1460,7 @@ static int wm_operator_call_internal(bContext *C,
wmOperatorType *ot,
PointerRNA *properties,
ReportList *reports,
- const short context,
+ const wmOperatorCallContext context,
const bool poll_only,
wmEvent *event)
{
@@ -1595,13 +1595,16 @@ static int wm_operator_call_internal(bContext *C,
/* Invokes operator in context. */
int WM_operator_name_call_ptr(bContext *C,
wmOperatorType *ot,
- short context,
+ wmOperatorCallContext context,
PointerRNA *properties)
{
BLI_assert(ot == WM_operatortype_find(ot->idname, true));
return wm_operator_call_internal(C, ot, properties, NULL, context, false, NULL);
}
-int WM_operator_name_call(bContext *C, const char *opstring, short context, PointerRNA *properties)
+int WM_operator_name_call(bContext *C,
+ const char *opstring,
+ wmOperatorCallContext context,
+ PointerRNA *properties)
{
wmOperatorType *ot = WM_operatortype_find(opstring, 0);
if (ot) {
@@ -1623,7 +1626,7 @@ bool WM_operator_name_poll(bContext *C, const char *opstring)
int WM_operator_name_call_with_properties(struct bContext *C,
const char *opstring,
- short context,
+ wmOperatorCallContext context,
struct IDProperty *properties)
{
PointerRNA props_ptr;
@@ -1654,7 +1657,7 @@ void WM_menu_name_call(bContext *C, const char *menu_name, short context)
*/
int WM_operator_call_py(bContext *C,
wmOperatorType *ot,
- short context,
+ wmOperatorCallContext context,
PointerRNA *properties,
ReportList *reports,
const bool is_undo)
@@ -1778,8 +1781,11 @@ static int ui_handler_wait_for_input(bContext *C, const wmEvent *event, void *us
return WM_UI_HANDLER_CONTINUE;
}
-void WM_operator_name_call_ptr_with_depends_on_cursor(
- bContext *C, wmOperatorType *ot, short opcontext, PointerRNA *properties, const char *drawstr)
+void WM_operator_name_call_ptr_with_depends_on_cursor(bContext *C,
+ wmOperatorType *ot,
+ wmOperatorCallContext opcontext,
+ PointerRNA *properties,
+ const char *drawstr)
{
int flag = ot->flag;
@@ -3073,8 +3079,9 @@ static int wm_handlers_do_intern(bContext *C, wmWindow *win, wmEvent *event, Lis
BLI_addtail(&single_lb, drag);
event->customdata = &single_lb;
+ const wmOperatorCallContext opcontext = wm_drop_operator_context_get(drop);
int op_retval = wm_operator_call_internal(
- C, drop->ot, drop->ptr, NULL, drop->opcontext, false, event);
+ C, drop->ot, drop->ptr, NULL, opcontext, false, event);
OPERATOR_RETVAL_CHECK(op_retval);
if ((op_retval & OPERATOR_CANCELLED) && drop->cancel) {
diff --git a/source/blender/windowmanager/intern/wm_files_link.c b/source/blender/windowmanager/intern/wm_files_link.c
index b45cf765a75..00ac1c2ffe6 100644
--- a/source/blender/windowmanager/intern/wm_files_link.c
+++ b/source/blender/windowmanager/intern/wm_files_link.c
@@ -53,6 +53,7 @@
#include "BLO_readfile.h"
#include "BKE_armature.h"
+#include "BKE_blendfile_link_append.h"
#include "BKE_context.h"
#include "BKE_global.h"
#include "BKE_key.h"
@@ -166,838 +167,6 @@ static int wm_link_append_flag(wmOperator *op)
return flag;
}
-typedef struct WMLinkAppendDataItem {
- char *name;
- BLI_bitmap
- *libraries; /* All libs (from WMLinkAppendData.libraries) to try to load this ID from. */
- short idcode;
-
- /** Type of action to do to append this item, and other append-specific information. */
- char append_action;
- char append_tag;
-
- ID *new_id;
- Library *source_library;
- void *customdata;
-} WMLinkAppendDataItem;
-
-typedef struct WMLinkAppendData {
- LinkNodePair libraries;
- LinkNodePair items;
- int num_libraries;
- int num_items;
- /**
- * Combines #eFileSel_Params_Flag from DNA_space_types.h & #eBLOLibLinkFlags from BLO_readfile.h
- */
- int flag;
-
- /** Allows to easily find an existing items from an ID pointer. Used by append code. */
- GHash *new_id_to_item;
-
- /** Runtime info used by append code to manage re-use of already appended matching IDs. */
- GHash *library_weak_reference_mapping;
-
- /* Internal 'private' data */
- MemArena *memarena;
-} WMLinkAppendData;
-
-typedef struct WMLinkAppendDataCallBack {
- WMLinkAppendData *lapp_data;
- WMLinkAppendDataItem *item;
- ReportList *reports;
-
-} WMLinkAppendDataCallBack;
-
-enum {
- WM_APPEND_ACT_UNSET = 0,
- WM_APPEND_ACT_KEEP_LINKED,
- WM_APPEND_ACT_REUSE_LOCAL,
- WM_APPEND_ACT_MAKE_LOCAL,
- WM_APPEND_ACT_COPY_LOCAL,
-};
-
-enum {
- WM_APPEND_TAG_INDIRECT = 1 << 0,
-};
-
-static WMLinkAppendData *wm_link_append_data_new(const int flag)
-{
- MemArena *ma = BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE, __func__);
- WMLinkAppendData *lapp_data = BLI_memarena_calloc(ma, sizeof(*lapp_data));
-
- lapp_data->flag = flag;
- lapp_data->memarena = ma;
-
- return lapp_data;
-}
-
-static void wm_link_append_data_free(WMLinkAppendData *lapp_data)
-{
- if (lapp_data->new_id_to_item != NULL) {
- BLI_ghash_free(lapp_data->new_id_to_item, NULL, NULL);
- }
-
- BLI_assert(lapp_data->library_weak_reference_mapping == NULL);
-
- BLI_memarena_free(lapp_data->memarena);
-}
-
-/* WARNING! *Never* call wm_link_append_data_library_add() after having added some items! */
-
-static void wm_link_append_data_library_add(WMLinkAppendData *lapp_data, const char *libname)
-{
- size_t len = strlen(libname) + 1;
- char *libpath = BLI_memarena_alloc(lapp_data->memarena, len);
-
- BLI_strncpy(libpath, libname, len);
- BLI_linklist_append_arena(&lapp_data->libraries, libpath, lapp_data->memarena);
- lapp_data->num_libraries++;
-}
-
-static WMLinkAppendDataItem *wm_link_append_data_item_add(WMLinkAppendData *lapp_data,
- const char *idname,
- const short idcode,
- void *customdata)
-{
- WMLinkAppendDataItem *item = BLI_memarena_calloc(lapp_data->memarena, sizeof(*item));
- size_t len = strlen(idname) + 1;
-
- item->name = BLI_memarena_alloc(lapp_data->memarena, len);
- BLI_strncpy(item->name, idname, len);
- item->idcode = idcode;
- item->libraries = BLI_BITMAP_NEW_MEMARENA(lapp_data->memarena, lapp_data->num_libraries);
-
- item->new_id = NULL;
- item->append_action = WM_APPEND_ACT_UNSET;
- item->customdata = customdata;
-
- BLI_linklist_append_arena(&lapp_data->items, item, lapp_data->memarena);
- lapp_data->num_items++;
-
- return item;
-}
-
-/* -------------------------------------------------------------------- */
-/** \name Library appending helper functions.
- *
- * FIXME: Deduplicate code with similar one in readfile.c
- * \{ */
-
-static bool object_in_any_scene(Main *bmain, Object *ob)
-{
- LISTBASE_FOREACH (Scene *, sce, &bmain->scenes) {
- if (BKE_scene_object_find(sce, ob)) {
- return true;
- }
- }
-
- return false;
-}
-
-static bool object_in_any_collection(Main *bmain, Object *ob)
-{
- LISTBASE_FOREACH (Collection *, collection, &bmain->collections) {
- if (BKE_collection_has_object(collection, ob)) {
- return true;
- }
- }
-
- LISTBASE_FOREACH (Scene *, scene, &bmain->scenes) {
- if (scene->master_collection != NULL &&
- BKE_collection_has_object(scene->master_collection, ob)) {
- return true;
- }
- }
-
- return false;
-}
-
-static ID *wm_append_loose_data_instantiate_process_check(WMLinkAppendDataItem *item)
-{
- /* We consider that if we either kept it linked, or re-used already local data, instantiation
- * status of those should not be modified. */
- if (!ELEM(item->append_action, WM_APPEND_ACT_COPY_LOCAL, WM_APPEND_ACT_MAKE_LOCAL)) {
- return NULL;
- }
-
- ID *id = item->new_id;
- if (id == NULL) {
- return NULL;
- }
-
- if (item->append_action == WM_APPEND_ACT_COPY_LOCAL) {
- BLI_assert(ID_IS_LINKED(id));
- id = id->newid;
- if (id == NULL) {
- return NULL;
- }
-
- BLI_assert(!ID_IS_LINKED(id));
- return id;
- }
-
- BLI_assert(!ID_IS_LINKED(id));
- return id;
-}
-
-static void wm_append_loose_data_instantiate_ensure_active_collection(
- WMLinkAppendData *lapp_data,
- Main *bmain,
- Scene *scene,
- ViewLayer *view_layer,
- Collection **r_active_collection)
-{
- /* Find or add collection as needed. */
- if (*r_active_collection == NULL) {
- if (lapp_data->flag & FILE_ACTIVE_COLLECTION) {
- LayerCollection *lc = BKE_layer_collection_get_active(view_layer);
- *r_active_collection = lc->collection;
- }
- else {
- *r_active_collection = BKE_collection_add(bmain, scene->master_collection, NULL);
- }
- }
-}
-
-/* TODO: De-duplicate this code with the one in readfile.c, think we need some utils code for that
- * in BKE. */
-static void wm_append_loose_data_instantiate(WMLinkAppendData *lapp_data,
- Main *bmain,
- Scene *scene,
- ViewLayer *view_layer,
- const View3D *v3d)
-{
- if (scene == NULL) {
- /* In some cases, like the asset drag&drop e.g., the caller code manages instantiation itself.
- */
- return;
- }
-
- LinkNode *itemlink;
- Collection *active_collection = NULL;
- const bool do_obdata = (lapp_data->flag & BLO_LIBLINK_OBDATA_INSTANCE) != 0;
-
- /* Do NOT make base active here! screws up GUI stuff,
- * if you want it do it at the editor level. */
- const bool object_set_active = false;
-
- /* First pass on obdata to enable their instantiation by default, then do a second pass on
- * objects to clear it for any obdata already in use. */
- if (do_obdata) {
- for (itemlink = lapp_data->items.list; itemlink; itemlink = itemlink->next) {
- WMLinkAppendDataItem *item = itemlink->link;
- ID *id = wm_append_loose_data_instantiate_process_check(item);
- if (id == NULL) {
- continue;
- }
- const ID_Type idcode = GS(id->name);
- if (!OB_DATA_SUPPORT_ID(idcode)) {
- continue;
- }
-
- id->tag |= LIB_TAG_DOIT;
- }
- for (itemlink = lapp_data->items.list; itemlink; itemlink = itemlink->next) {
- WMLinkAppendDataItem *item = itemlink->link;
- ID *id = item->new_id;
- if (id == NULL || GS(id->name) != ID_OB) {
- continue;
- }
-
- Object *ob = (Object *)id;
- Object *new_ob = (Object *)id->newid;
- if (ob->data != NULL) {
- ((ID *)(ob->data))->tag &= ~LIB_TAG_DOIT;
- }
- if (new_ob != NULL && new_ob->data != NULL) {
- ((ID *)(new_ob->data))->tag &= ~LIB_TAG_DOIT;
- }
- }
- }
-
- /* First do collections, then objects, then obdata. */
-
- /* NOTE: For collections we only view_layer-instantiate duplicated collections that have
- * non-instantiated objects in them. */
- for (itemlink = lapp_data->items.list; itemlink; itemlink = itemlink->next) {
- WMLinkAppendDataItem *item = itemlink->link;
- ID *id = wm_append_loose_data_instantiate_process_check(item);
- if (id == NULL || GS(id->name) != ID_GR) {
- continue;
- }
-
- /* We do not want to force instantiation of indirectly appended collections. Users can now
- * easily instantiate collections (and their objects) as needed by themselves. See T67032. */
- /* We need to check that objects in that collections are already instantiated in a scene.
- * Otherwise, it's better to add the collection to the scene's active collection, than to
- * instantiate its objects in active scene's collection directly. See T61141.
- *
- * NOTE: We only check object directly into that collection, not recursively into its
- * children.
- */
- Collection *collection = (Collection *)id;
- /* We always add collections directly selected by the user. */
- bool do_add_collection = (item->append_tag & WM_APPEND_TAG_INDIRECT) == 0;
- LISTBASE_FOREACH (CollectionObject *, coll_ob, &collection->gobject) {
- Object *ob = coll_ob->ob;
- if (!object_in_any_scene(bmain, ob)) {
- do_add_collection = true;
- break;
- }
- }
- if (do_add_collection) {
- wm_append_loose_data_instantiate_ensure_active_collection(
- lapp_data, bmain, scene, view_layer, &active_collection);
-
- /* In case user requested instantiation of collections as empties, we do so for the one they
- * explicitly selected (originally directly linked IDs). */
- if ((lapp_data->flag & BLO_LIBLINK_COLLECTION_INSTANCE) != 0 &&
- (item->append_tag & WM_APPEND_TAG_INDIRECT) == 0) {
- /* BKE_object_add(...) messes with the selection. */
- Object *ob = BKE_object_add_only_object(bmain, OB_EMPTY, collection->id.name + 2);
- ob->type = OB_EMPTY;
- ob->empty_drawsize = U.collection_instance_empty_size;
-
- const bool set_selected = (lapp_data->flag & FILE_AUTOSELECT) != 0;
- /* TODO: why is it OK to make this active here but not in other situations?
- * See other callers of #object_base_instance_init */
- const bool set_active = set_selected;
- BLO_object_instantiate_object_base_instance_init(
- bmain, active_collection, ob, view_layer, v3d, lapp_data->flag, set_active);
-
- /* Assign the collection. */
- ob->instance_collection = collection;
- id_us_plus(&collection->id);
- ob->transflag |= OB_DUPLICOLLECTION;
- copy_v3_v3(ob->loc, scene->cursor.location);
- }
- else {
- /* Add collection as child of active collection. */
- BKE_collection_child_add(bmain, active_collection, collection);
-
- if ((lapp_data->flag & FILE_AUTOSELECT) != 0) {
- LISTBASE_FOREACH (CollectionObject *, coll_ob, &collection->gobject) {
- Object *ob = coll_ob->ob;
- Base *base = BKE_view_layer_base_find(view_layer, ob);
- if (base) {
- base->flag |= BASE_SELECTED;
- BKE_scene_object_base_flag_sync_from_base(base);
- }
- }
- }
- }
- }
- }
-
- /* NOTE: For objects we only view_layer-instantiate duplicated objects that are not yet used
- * anywhere. */
- for (itemlink = lapp_data->items.list; itemlink; itemlink = itemlink->next) {
- WMLinkAppendDataItem *item = itemlink->link;
- ID *id = wm_append_loose_data_instantiate_process_check(item);
- if (id == NULL || GS(id->name) != ID_OB) {
- continue;
- }
-
- Object *ob = (Object *)id;
-
- if (object_in_any_collection(bmain, ob)) {
- continue;
- }
-
- wm_append_loose_data_instantiate_ensure_active_collection(
- lapp_data, bmain, scene, view_layer, &active_collection);
-
- CLAMP_MIN(ob->id.us, 0);
- ob->mode = OB_MODE_OBJECT;
-
- BLO_object_instantiate_object_base_instance_init(
- bmain, active_collection, ob, view_layer, v3d, lapp_data->flag, object_set_active);
- }
-
- if (!do_obdata) {
- return;
- }
-
- for (itemlink = lapp_data->items.list; itemlink; itemlink = itemlink->next) {
- WMLinkAppendDataItem *item = itemlink->link;
- ID *id = wm_append_loose_data_instantiate_process_check(item);
- if (id == NULL) {
- continue;
- }
- const ID_Type idcode = GS(id->name);
- if (!OB_DATA_SUPPORT_ID(idcode)) {
- continue;
- }
- if ((id->tag & LIB_TAG_DOIT) == 0) {
- continue;
- }
-
- wm_append_loose_data_instantiate_ensure_active_collection(
- lapp_data, bmain, scene, view_layer, &active_collection);
-
- const int type = BKE_object_obdata_to_type(id);
- BLI_assert(type != -1);
- Object *ob = BKE_object_add_only_object(bmain, type, id->name + 2);
- ob->data = id;
- id_us_plus(id);
- BKE_object_materials_test(bmain, ob, ob->data);
-
- BLO_object_instantiate_object_base_instance_init(
- bmain, active_collection, ob, view_layer, v3d, lapp_data->flag, object_set_active);
-
- copy_v3_v3(ob->loc, scene->cursor.location);
-
- id->tag &= ~LIB_TAG_DOIT;
- }
-
- /* Finally, add rigid body objects and constraints to current RB world(s). */
- for (itemlink = lapp_data->items.list; itemlink; itemlink = itemlink->next) {
- WMLinkAppendDataItem *item = itemlink->link;
- ID *id = wm_append_loose_data_instantiate_process_check(item);
- if (id == NULL || GS(id->name) != ID_OB) {
- continue;
- }
- BKE_rigidbody_ensure_local_object(bmain, (Object *)id);
- }
-}
-
-/** \} */
-
-static int foreach_libblock_append_callback(LibraryIDLinkCallbackData *cb_data)
-{
- /* NOTE: It is important to also skip liboverride references here, as those should never be made
- * local. */
- if (cb_data->cb_flag & (IDWALK_CB_EMBEDDED | IDWALK_CB_INTERNAL | IDWALK_CB_LOOPBACK |
- IDWALK_CB_OVERRIDE_LIBRARY_REFERENCE)) {
- return IDWALK_RET_NOP;
- }
-
- WMLinkAppendDataCallBack *data = cb_data->user_data;
- ID *id = *cb_data->id_pointer;
-
- if (id == NULL) {
- return IDWALK_RET_NOP;
- }
-
- if (!BKE_idtype_idcode_is_linkable(GS(id->name))) {
- /* While we do not want to add non-linkable ID (shape keys...) to the list of linked items,
- * unfortunately they can use fully linkable valid IDs too, like actions. Those need to be
- * processed, so we need to recursively deal with them here. */
- /* NOTE: Since we are by-passing checks in `BKE_library_foreach_ID_link` by manually calling it
- * recursively, we need to take care of potential recursion cases ourselves (e.g.animdata of
- * shapekey referencing the shapekey itself). */
- if (id != cb_data->id_self) {
- BKE_library_foreach_ID_link(
- cb_data->bmain, id, foreach_libblock_append_callback, data, IDWALK_NOP);
- }
- return IDWALK_RET_NOP;
- }
-
- const bool do_recursive = (data->lapp_data->flag & BLO_LIBLINK_APPEND_RECURSIVE) != 0;
- if (!do_recursive && cb_data->id_owner->lib != id->lib) {
- /* When `do_recursive` is false, we only make local IDs from same library(-ies) as the
- * initially directly linked ones. */
- return IDWALK_RET_NOP;
- }
-
- WMLinkAppendDataItem *item = BLI_ghash_lookup(data->lapp_data->new_id_to_item, id);
- if (item == NULL) {
- item = wm_link_append_data_item_add(data->lapp_data, id->name, GS(id->name), NULL);
- item->new_id = id;
- item->source_library = id->lib;
- /* Since we did not have an item for that ID yet, we know user did not selected it explicitly,
- * it was rather linked indirectly. This info is important for instantiation of collections. */
- item->append_tag |= WM_APPEND_TAG_INDIRECT;
- BLI_ghash_insert(data->lapp_data->new_id_to_item, id, item);
- }
-
- /* NOTE: currently there is no need to do anything else here, but in the future this would be
- * the place to add specific per-usage decisions on how to append an ID. */
-
- return IDWALK_RET_NOP;
-}
-
-/* Perform append operation, using modern ID usage looper to detect which ID should be kept linked,
- * made local, duplicated as local, re-used from local etc.
- *
- * TODO: Expose somehow this logic to the two other parts of code performing actual append
- * (i.e. copy/paste and `bpy` link/append API).
- * Then we can heavily simplify #BKE_library_make_local(). */
-static void wm_append_do(WMLinkAppendData *lapp_data,
- ReportList *reports,
- Main *bmain,
- Scene *scene,
- ViewLayer *view_layer,
- const View3D *v3d)
-{
- BLI_assert((lapp_data->flag & FILE_LINK) == 0);
-
- const bool set_fakeuser = (lapp_data->flag & BLO_LIBLINK_APPEND_SET_FAKEUSER) != 0;
- const bool do_reuse_local_id = (lapp_data->flag & BLO_LIBLINK_APPEND_LOCAL_ID_REUSE) != 0;
-
- const int make_local_common_flags = LIB_ID_MAKELOCAL_FULL_LIBRARY |
- ((lapp_data->flag & BLO_LIBLINK_APPEND_ASSET_DATA_CLEAR) !=
- 0 ?
- LIB_ID_MAKELOCAL_ASSET_DATA_CLEAR :
- 0);
-
- LinkNode *itemlink;
-
- /* Generate a mapping between newly linked IDs and their items, and tag linked IDs used as
- * liboverride references as already existing. */
- lapp_data->new_id_to_item = BLI_ghash_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp, __func__);
- for (itemlink = lapp_data->items.list; itemlink; itemlink = itemlink->next) {
- WMLinkAppendDataItem *item = itemlink->link;
- ID *id = item->new_id;
- if (id == NULL) {
- continue;
- }
- BLI_ghash_insert(lapp_data->new_id_to_item, id, item);
-
- /* This ensures that if a liboverride reference is also linked/used by some other appended
- * data, it gets a local copy instead of being made directly local, so that the liboverride
- * references remain valid (i.e. linked data). */
- if (ID_IS_OVERRIDE_LIBRARY_REAL(id)) {
- id->override_library->reference->tag |= LIB_TAG_PRE_EXISTING;
- }
- }
-
- lapp_data->library_weak_reference_mapping = BKE_main_library_weak_reference_create(bmain);
-
- /* NOTE: Since we append items for IDs not already listed (i.e. implicitly linked indirect
- * dependencies), this list will grow and we will process those IDs later, leading to a flatten
- * recursive processing of all the linked dependencies. */
- for (itemlink = lapp_data->items.list; itemlink; itemlink = itemlink->next) {
- WMLinkAppendDataItem *item = itemlink->link;
- ID *id = item->new_id;
- if (id == NULL) {
- continue;
- }
- BLI_assert(item->customdata == NULL);
-
- /* In Append case linked IDs should never be marked as needing post-processing (instantiation
- * of loose objects etc.). */
- BLI_assert((id->tag & LIB_TAG_DOIT) == 0);
-
- ID *existing_local_id = BKE_idtype_idcode_append_is_reusable(GS(id->name)) ?
- BKE_main_library_weak_reference_search_item(
- lapp_data->library_weak_reference_mapping,
- id->lib->filepath,
- id->name) :
- NULL;
-
- if (item->append_action != WM_APPEND_ACT_UNSET) {
- /* Already set, pass. */
- }
- if (GS(id->name) == ID_OB && ((Object *)id)->proxy_from != NULL) {
- CLOG_INFO(&LOG, 3, "Appended ID '%s' is proxified, keeping it linked...", id->name);
- item->append_action = WM_APPEND_ACT_KEEP_LINKED;
- }
- else if (do_reuse_local_id && existing_local_id != NULL) {
- CLOG_INFO(&LOG, 3, "Appended ID '%s' as a matching local one, re-using it...", id->name);
- item->append_action = WM_APPEND_ACT_REUSE_LOCAL;
- item->customdata = existing_local_id;
- }
- else if (id->tag & LIB_TAG_PRE_EXISTING) {
- CLOG_INFO(&LOG, 3, "Appended ID '%s' was already linked, need to copy it...", id->name);
- item->append_action = WM_APPEND_ACT_COPY_LOCAL;
- }
- else {
- CLOG_INFO(&LOG, 3, "Appended ID '%s' will be made local...", id->name);
- item->append_action = WM_APPEND_ACT_MAKE_LOCAL;
- }
-
- /* Only check dependencies if we are not keeping linked data, nor re-using existing local data.
- */
- if (!ELEM(item->append_action, WM_APPEND_ACT_KEEP_LINKED, WM_APPEND_ACT_REUSE_LOCAL)) {
- WMLinkAppendDataCallBack cb_data = {
- .lapp_data = lapp_data, .item = item, .reports = reports};
- BKE_library_foreach_ID_link(
- bmain, id, foreach_libblock_append_callback, &cb_data, IDWALK_NOP);
- }
-
- /* If we found a matching existing local id but are not re-using it, we need to properly clear
- * its weak reference to linked data. */
- if (existing_local_id != NULL &&
- !ELEM(item->append_action, WM_APPEND_ACT_KEEP_LINKED, WM_APPEND_ACT_REUSE_LOCAL)) {
- BKE_main_library_weak_reference_remove_item(lapp_data->library_weak_reference_mapping,
- id->lib->filepath,
- id->name,
- existing_local_id);
- }
- }
-
- /* Effectively perform required operation on every linked ID. */
- for (itemlink = lapp_data->items.list; itemlink; itemlink = itemlink->next) {
- WMLinkAppendDataItem *item = itemlink->link;
- ID *id = item->new_id;
- if (id == NULL) {
- continue;
- }
-
- ID *local_appended_new_id = NULL;
- char lib_filepath[FILE_MAX];
- BLI_strncpy(lib_filepath, id->lib->filepath, sizeof(lib_filepath));
- char lib_id_name[MAX_ID_NAME];
- BLI_strncpy(lib_id_name, id->name, sizeof(lib_id_name));
-
- switch (item->append_action) {
- case WM_APPEND_ACT_COPY_LOCAL:
- BKE_lib_id_make_local(bmain, id, make_local_common_flags | LIB_ID_MAKELOCAL_FORCE_COPY);
- local_appended_new_id = id->newid;
- break;
- case WM_APPEND_ACT_MAKE_LOCAL:
- BKE_lib_id_make_local(bmain,
- id,
- make_local_common_flags | LIB_ID_MAKELOCAL_FORCE_LOCAL |
- LIB_ID_MAKELOCAL_OBJECT_NO_PROXY_CLEARING);
- BLI_assert(id->newid == NULL);
- local_appended_new_id = id;
- break;
- case WM_APPEND_ACT_KEEP_LINKED:
- /* Nothing to do here. */
- break;
- case WM_APPEND_ACT_REUSE_LOCAL:
- /* We only need to set `newid` to ID found in previous loop, for proper remapping. */
- ID_NEW_SET(id, item->customdata);
- /* This is not a 'new' local appended id, do not set `local_appended_new_id` here. */
- break;
- case WM_APPEND_ACT_UNSET:
- CLOG_ERROR(
- &LOG, "Unexpected unset append action for '%s' ID, assuming 'keep link'", id->name);
- break;
- default:
- BLI_assert(0);
- }
-
- if (local_appended_new_id != NULL) {
- if (BKE_idtype_idcode_append_is_reusable(GS(local_appended_new_id->name))) {
- BKE_main_library_weak_reference_add_item(lapp_data->library_weak_reference_mapping,
- lib_filepath,
- lib_id_name,
- local_appended_new_id);
- }
-
- if (set_fakeuser) {
- if (!ELEM(GS(local_appended_new_id->name), ID_OB, ID_GR)) {
- /* Do not set fake user on objects nor collections (instancing). */
- id_fake_user_set(local_appended_new_id);
- }
- }
- }
- }
-
- BKE_main_library_weak_reference_destroy(lapp_data->library_weak_reference_mapping);
- lapp_data->library_weak_reference_mapping = NULL;
-
- /* Remap IDs as needed. */
- for (itemlink = lapp_data->items.list; itemlink; itemlink = itemlink->next) {
- WMLinkAppendDataItem *item = itemlink->link;
-
- if (item->append_action == WM_APPEND_ACT_KEEP_LINKED) {
- continue;
- }
-
- ID *id = item->new_id;
- if (id == NULL) {
- continue;
- }
- if (ELEM(item->append_action, WM_APPEND_ACT_COPY_LOCAL, WM_APPEND_ACT_REUSE_LOCAL)) {
- BLI_assert(ID_IS_LINKED(id));
- id = id->newid;
- if (id == NULL) {
- continue;
- }
- }
-
- BLI_assert(!ID_IS_LINKED(id));
-
- BKE_libblock_relink_to_newid_new(bmain, id);
- }
-
- /* Remove linked IDs when a local existing data has been reused instead. */
- BKE_main_id_tag_all(bmain, LIB_TAG_DOIT, false);
- for (itemlink = lapp_data->items.list; itemlink; itemlink = itemlink->next) {
- WMLinkAppendDataItem *item = itemlink->link;
-
- if (item->append_action != WM_APPEND_ACT_REUSE_LOCAL) {
- continue;
- }
-
- ID *id = item->new_id;
- if (id == NULL) {
- continue;
- }
- BLI_assert(ID_IS_LINKED(id));
- BLI_assert(id->newid != NULL);
-
- id->tag |= LIB_TAG_DOIT;
- item->new_id = id->newid;
- }
- BKE_id_multi_tagged_delete(bmain);
-
- /* Instantiate newly created (duplicated) IDs as needed. */
- wm_append_loose_data_instantiate(lapp_data, bmain, scene, view_layer, v3d);
-
- /* Attempt to deal with object proxies.
- *
- * NOTE: Copied from `BKE_library_make_local`, but this is not really working (as in, not
- * producing any useful result in any known use case), neither here nor in
- * `BKE_library_make_local` currently.
- * Proxies are end of life anyway, so not worth spending time on this. */
- for (itemlink = lapp_data->items.list; itemlink; itemlink = itemlink->next) {
- WMLinkAppendDataItem *item = itemlink->link;
-
- if (item->append_action != WM_APPEND_ACT_COPY_LOCAL) {
- continue;
- }
-
- ID *id = item->new_id;
- if (id == NULL) {
- continue;
- }
- BLI_assert(ID_IS_LINKED(id));
-
- /* Attempt to re-link copied proxy objects. This allows appending of an entire scene
- * from another blend file into this one, even when that blend file contains proxified
- * armatures that have local references. Since the proxified object needs to be linked
- * (not local), this will only work when the "Localize all" checkbox is disabled.
- * TL;DR: this is a dirty hack on top of an already weak feature (proxies). */
- if (GS(id->name) == ID_OB && ((Object *)id)->proxy != NULL) {
- Object *ob = (Object *)id;
- Object *ob_new = (Object *)id->newid;
- bool is_local = false, is_lib = false;
-
- /* Proxies only work when the proxified object is linked-in from a library. */
- if (!ID_IS_LINKED(ob->proxy)) {
- CLOG_WARN(&LOG,
- "Proxy object %s will lose its link to %s, because the "
- "proxified object is local",
- id->newid->name,
- ob->proxy->id.name);
- continue;
- }
-
- BKE_library_ID_test_usages(bmain, id, &is_local, &is_lib);
-
- /* We can only switch the proxy'ing to a made-local proxy if it is no longer
- * referred to from a library. Not checking for local use; if new local proxy
- * was not used locally would be a nasty bug! */
- if (is_local || is_lib) {
- CLOG_WARN(&LOG,
- "Made-local proxy object %s will lose its link to %s, "
- "because the linked-in proxy is referenced (is_local=%i, is_lib=%i)",
- id->newid->name,
- ob->proxy->id.name,
- is_local,
- is_lib);
- }
- else {
- /* we can switch the proxy'ing from the linked-in to the made-local proxy.
- * BKE_object_make_proxy() shouldn't be used here, as it allocates memory that
- * was already allocated by object_make_local() (which called BKE_object_copy). */
- ob_new->proxy = ob->proxy;
- ob_new->proxy_group = ob->proxy_group;
- ob_new->proxy_from = ob->proxy_from;
- ob_new->proxy->proxy_from = ob_new;
- ob->proxy = ob->proxy_from = ob->proxy_group = NULL;
- }
- }
- }
-
- BKE_main_id_newptr_and_tag_clear(bmain);
-}
-
-static void wm_link_do(WMLinkAppendData *lapp_data,
- ReportList *reports,
- Main *bmain,
- Scene *scene,
- ViewLayer *view_layer,
- const View3D *v3d)
-{
- Main *mainl;
- BlendHandle *bh;
- Library *lib;
-
- const int flag = lapp_data->flag;
- const int id_tag_extra = 0;
-
- LinkNode *liblink, *itemlink;
- int lib_idx, item_idx;
-
- BLI_assert(lapp_data->num_items && lapp_data->num_libraries);
-
- for (lib_idx = 0, liblink = lapp_data->libraries.list; liblink;
- lib_idx++, liblink = liblink->next) {
- char *libname = liblink->link;
- BlendFileReadReport bf_reports = {.reports = reports};
-
- if (STREQ(libname, BLO_EMBEDDED_STARTUP_BLEND)) {
- bh = BLO_blendhandle_from_memory(
- datatoc_startup_blend, datatoc_startup_blend_size, &bf_reports);
- }
- else {
- bh = BLO_blendhandle_from_file(libname, &bf_reports);
- }
-
- if (bh == NULL) {
- /* Unlikely since we just browsed it, but possible
- * Error reports will have been made by BLO_blendhandle_from_file() */
- continue;
- }
-
- /* here appending/linking starts */
- struct LibraryLink_Params liblink_params;
- BLO_library_link_params_init_with_context(
- &liblink_params, bmain, flag, id_tag_extra, scene, view_layer, v3d);
- /* In case of append, do not handle instantiation in linking process, but during append phase
- * (see #wm_append_loose_data_instantiate ). */
- if ((flag & FILE_LINK) == 0) {
- liblink_params.flag &= ~BLO_LIBLINK_NEEDS_ID_TAG_DOIT;
- }
-
- mainl = BLO_library_link_begin(&bh, libname, &liblink_params);
- lib = mainl->curlib;
- BLI_assert(lib);
- UNUSED_VARS_NDEBUG(lib);
-
- if (mainl->versionfile < 250) {
- BKE_reportf(reports,
- RPT_WARNING,
- "Linking or appending from a very old .blend file format (%d.%d), no animation "
- "conversion will "
- "be done! You may want to re-save your lib file with current Blender",
- mainl->versionfile,
- mainl->subversionfile);
- }
-
- /* For each lib file, we try to link all items belonging to that lib,
- * and tag those successful to not try to load them again with the other libs. */
- for (item_idx = 0, itemlink = lapp_data->items.list; itemlink;
- item_idx++, itemlink = itemlink->next) {
- WMLinkAppendDataItem *item = itemlink->link;
- ID *new_id;
-
- if (!BLI_BITMAP_TEST(item->libraries, lib_idx)) {
- continue;
- }
-
- new_id = BLO_library_link_named_part(mainl, &bh, item->idcode, item->name, &liblink_params);
-
- if (new_id) {
- /* If the link is successful, clear item's libs 'todo' flags.
- * This avoids trying to link same item with other libraries to come. */
- BLI_bitmap_set_all(item->libraries, false, lapp_data->num_libraries);
- item->new_id = new_id;
- item->source_library = new_id->lib;
- }
- }
-
- BLO_library_link_end(mainl, &bh, &liblink_params);
- BLO_blendhandle_close(bh);
- }
-}
-
/**
* Check if an item defined by \a name and \a group can be appended/linked.
*
@@ -1048,7 +217,7 @@ static int wm_link_append_exec(bContext *C, wmOperator *op)
Scene *scene = CTX_data_scene(C);
ViewLayer *view_layer = CTX_data_view_layer(C);
PropertyRNA *prop;
- WMLinkAppendData *lapp_data;
+ BlendfileLinkAppendContext *lapp_context;
char path[FILE_MAX_LIBEXTRA], root[FILE_MAXDIR], libname[FILE_MAX_LIBEXTRA], relname[FILE_MAX];
char *group, *name;
int totfiles = 0;
@@ -1115,7 +284,14 @@ static int wm_link_append_exec(bContext *C, wmOperator *op)
/* We define our working data...
* Note that here, each item 'uses' one library, and only one. */
- lapp_data = wm_link_append_data_new(flag);
+ LibraryLink_Params lapp_params;
+ BLO_library_link_params_init_with_context(
+ &lapp_params, bmain, flag, 0, scene, view_layer, CTX_wm_view3d(C));
+
+ lapp_context = BKE_blendfile_link_append_context_new(&lapp_params);
+ BKE_blendfile_link_append_context_embedded_blendfile_set(
+ lapp_context, datatoc_startup_blend, datatoc_startup_blend_size);
+
if (totfiles != 0) {
GHash *libraries = BLI_ghash_new(BLI_ghashutil_strhash_p, BLI_ghashutil_strcmp, __func__);
int lib_idx = 0;
@@ -1133,7 +309,7 @@ static int wm_link_append_exec(bContext *C, wmOperator *op)
if (!BLI_ghash_haskey(libraries, libname)) {
BLI_ghash_insert(libraries, BLI_strdup(libname), POINTER_FROM_INT(lib_idx));
lib_idx++;
- wm_link_append_data_library_add(lapp_data, libname);
+ BKE_blendfile_link_append_context_library_add(lapp_context, libname, NULL);
}
}
}
@@ -1145,7 +321,7 @@ static int wm_link_append_exec(bContext *C, wmOperator *op)
BLI_join_dirfile(path, sizeof(path), root, relname);
if (BLO_library_path_explode(path, libname, &group, &name)) {
- WMLinkAppendDataItem *item;
+ BlendfileLinkAppendContextItem *item;
if (!wm_link_append_item_poll(op->reports, path, group, name, do_append)) {
continue;
@@ -1153,9 +329,9 @@ static int wm_link_append_exec(bContext *C, wmOperator *op)
lib_idx = POINTER_AS_INT(BLI_ghash_lookup(libraries, libname));
- item = wm_link_append_data_item_add(
- lapp_data, name, BKE_idtype_idcode_from_name(group), NULL);
- BLI_BITMAP_ENABLE(item->libraries, lib_idx);
+ item = BKE_blendfile_link_append_context_item_add(
+ lapp_context, name, BKE_idtype_idcode_from_name(group), NULL);
+ BKE_blendfile_link_append_context_item_library_index_enable(lapp_context, item, lib_idx);
}
}
RNA_END;
@@ -1163,16 +339,17 @@ static int wm_link_append_exec(bContext *C, wmOperator *op)
BLI_ghash_free(libraries, MEM_freeN, NULL);
}
else {
- WMLinkAppendDataItem *item;
+ BlendfileLinkAppendContextItem *item;
- wm_link_append_data_library_add(lapp_data, libname);
- item = wm_link_append_data_item_add(lapp_data, name, BKE_idtype_idcode_from_name(group), NULL);
- BLI_BITMAP_ENABLE(item->libraries, 0);
+ BKE_blendfile_link_append_context_library_add(lapp_context, libname, NULL);
+ item = BKE_blendfile_link_append_context_item_add(
+ lapp_context, name, BKE_idtype_idcode_from_name(group), NULL);
+ BKE_blendfile_link_append_context_item_library_index_enable(lapp_context, item, 0);
}
- if (lapp_data->num_items == 0) {
+ if (BKE_blendfile_link_append_context_is_empty(lapp_context)) {
/* Early out in case there is nothing to link. */
- wm_link_append_data_free(lapp_data);
+ BKE_blendfile_link_append_context_free(lapp_context);
/* Clear pre existing tag. */
BKE_main_id_tag_all(bmain, LIB_TAG_PRE_EXISTING, false);
return OPERATOR_CANCELLED;
@@ -1181,7 +358,7 @@ static int wm_link_append_exec(bContext *C, wmOperator *op)
/* XXX We'd need re-entrant locking on Main for this to work... */
// BKE_main_lock(bmain);
- wm_link_do(lapp_data, op->reports, bmain, scene, view_layer, CTX_wm_view3d(C));
+ BKE_blendfile_link(lapp_context, op->reports);
// BKE_main_unlock(bmain);
@@ -1191,10 +368,10 @@ static int wm_link_append_exec(bContext *C, wmOperator *op)
/* append, rather than linking */
if (do_append) {
- wm_append_do(lapp_data, op->reports, bmain, scene, view_layer, CTX_wm_view3d(C));
+ BKE_blendfile_append(lapp_context, op->reports);
}
- wm_link_append_data_free(lapp_data);
+ BKE_blendfile_link_append_context_free(lapp_context);
/* important we unset, otherwise these object won't
* link into other scenes from this blend file */
@@ -1346,23 +523,29 @@ static ID *wm_file_link_append_datablock_ex(Main *bmain,
BKE_main_id_tag_all(bmain, LIB_TAG_PRE_EXISTING, true);
/* Define working data, with just the one item we want to link. */
- WMLinkAppendData *lapp_data = wm_link_append_data_new(flag);
+ LibraryLink_Params lapp_params;
+ BLO_library_link_params_init_with_context(&lapp_params, bmain, flag, 0, scene, view_layer, v3d);
+
+ BlendfileLinkAppendContext *lapp_context = BKE_blendfile_link_append_context_new(&lapp_params);
+ BKE_blendfile_link_append_context_embedded_blendfile_set(
+ lapp_context, datatoc_startup_blend, datatoc_startup_blend_size);
- wm_link_append_data_library_add(lapp_data, filepath);
- WMLinkAppendDataItem *item = wm_link_append_data_item_add(lapp_data, id_name, id_code, NULL);
- BLI_BITMAP_ENABLE(item->libraries, 0);
+ BKE_blendfile_link_append_context_library_add(lapp_context, filepath, NULL);
+ BlendfileLinkAppendContextItem *item = BKE_blendfile_link_append_context_item_add(
+ lapp_context, id_name, id_code, NULL);
+ BKE_blendfile_link_append_context_item_library_index_enable(lapp_context, item, 0);
/* Link datablock. */
- wm_link_do(lapp_data, NULL, bmain, scene, view_layer, v3d);
+ BKE_blendfile_link(lapp_context, NULL);
if (do_append) {
- wm_append_do(lapp_data, NULL, bmain, scene, view_layer, v3d);
+ BKE_blendfile_append(lapp_context, NULL);
}
/* Get linked datablock and free working data. */
- ID *id = item->new_id;
+ ID *id = BKE_blendfile_link_append_context_item_newid_get(lapp_context, item);
- wm_link_append_data_free(lapp_data);
+ BKE_blendfile_link_append_context_free(lapp_context);
BKE_main_id_tag_all(bmain, LIB_TAG_PRE_EXISTING, false);
@@ -1439,291 +622,6 @@ static int wm_lib_relocate_invoke(bContext *C, wmOperator *op, const wmEvent *UN
return OPERATOR_CANCELLED;
}
-static void lib_relocate_do_remap(Main *bmain,
- ID *old_id,
- ID *new_id,
- ReportList *reports,
- const bool do_reload,
- const short remap_flags)
-{
- BLI_assert(old_id);
- if (do_reload) {
- /* Since we asked for placeholders in case of missing IDs,
- * we expect to always get a valid one. */
- BLI_assert(new_id);
- }
- if (new_id) {
- CLOG_INFO(&LOG,
- 4,
- "Before remap of %s, old_id users: %d, new_id users: %d",
- old_id->name,
- old_id->us,
- new_id->us);
- BKE_libblock_remap_locked(bmain, old_id, new_id, remap_flags);
-
- if (old_id->flag & LIB_FAKEUSER) {
- id_fake_user_clear(old_id);
- id_fake_user_set(new_id);
- }
-
- CLOG_INFO(&LOG,
- 4,
- "After remap of %s, old_id users: %d, new_id users: %d",
- old_id->name,
- old_id->us,
- new_id->us);
-
- /* In some cases, new_id might become direct link, remove parent of library in this case. */
- if (new_id->lib->parent && (new_id->tag & LIB_TAG_INDIRECT) == 0) {
- if (do_reload) {
- BLI_assert_unreachable(); /* Should not happen in 'pure' reload case... */
- }
- new_id->lib->parent = NULL;
- }
- }
-
- if (old_id->us > 0 && new_id && old_id->lib == new_id->lib) {
- /* Note that this *should* not happen - but better be safe than sorry in this area,
- * at least until we are 100% sure this cannot ever happen.
- * Also, we can safely assume names were unique so far,
- * so just replacing '.' by '~' should work,
- * but this does not totally rules out the possibility of name collision. */
- size_t len = strlen(old_id->name);
- size_t dot_pos;
- bool has_num = false;
-
- for (dot_pos = len; dot_pos--;) {
- char c = old_id->name[dot_pos];
- if (c == '.') {
- break;
- }
- if (c < '0' || c > '9') {
- has_num = false;
- break;
- }
- has_num = true;
- }
-
- if (has_num) {
- old_id->name[dot_pos] = '~';
- }
- else {
- len = MIN2(len, MAX_ID_NAME - 7);
- BLI_strncpy(&old_id->name[len], "~000", 7);
- }
-
- id_sort_by_name(which_libbase(bmain, GS(old_id->name)), old_id, NULL);
-
- BKE_reportf(
- reports,
- RPT_WARNING,
- "Lib Reload: Replacing all references to old data-block '%s' by reloaded one failed, "
- "old one (%d remaining users) had to be kept and was renamed to '%s'",
- new_id->name,
- old_id->us,
- old_id->name);
- }
-}
-
-static void lib_relocate_do(bContext *C,
- Library *library,
- WMLinkAppendData *lapp_data,
- ReportList *reports,
- const bool do_reload)
-{
- ListBase *lbarray[INDEX_ID_MAX];
- int lba_idx;
-
- LinkNode *itemlink;
- int item_idx;
-
- Main *bmain = CTX_data_main(C);
- Scene *scene = CTX_data_scene(C);
- ViewLayer *view_layer = CTX_data_view_layer(C);
-
- /* Remove all IDs to be reloaded from Main. */
- lba_idx = set_listbasepointers(bmain, lbarray);
- while (lba_idx--) {
- ID *id = lbarray[lba_idx]->first;
- const short idcode = id ? GS(id->name) : 0;
-
- if (!id || !BKE_idtype_idcode_is_linkable(idcode)) {
- /* No need to reload non-linkable datatypes,
- * those will get relinked with their 'users ID'. */
- continue;
- }
-
- for (; id; id = id->next) {
- if (id->lib == library) {
- WMLinkAppendDataItem *item;
-
- /* We remove it from current Main, and add it to items to link... */
- /* Note that non-linkable IDs (like e.g. shapekeys) are also explicitly linked here... */
- BLI_remlink(lbarray[lba_idx], id);
- /* Usual special code for ShapeKeys snowflakes... */
- Key *old_key = BKE_key_from_id(id);
- if (old_key != NULL) {
- BLI_remlink(which_libbase(bmain, GS(old_key->id.name)), &old_key->id);
- }
-
- item = wm_link_append_data_item_add(lapp_data, id->name + 2, idcode, id);
- BLI_bitmap_set_all(item->libraries, true, lapp_data->num_libraries);
-
- CLOG_INFO(&LOG, 4, "Datablock to seek for: %s", id->name);
- }
- }
- }
-
- if (lapp_data->num_items == 0) {
- /* Early out in case there is nothing to do. */
- return;
- }
-
- BKE_main_id_tag_all(bmain, LIB_TAG_PRE_EXISTING, true);
-
- /* We do not want any instantiation here! */
- wm_link_do(lapp_data, reports, bmain, NULL, NULL, NULL);
-
- BKE_main_lock(bmain);
-
- /* We add back old id to bmain.
- * We need to do this in a first, separated loop, otherwise some of those may not be handled by
- * ID remapping, which means they would still reference old data to be deleted... */
- for (item_idx = 0, itemlink = lapp_data->items.list; itemlink;
- item_idx++, itemlink = itemlink->next) {
- WMLinkAppendDataItem *item = itemlink->link;
- ID *old_id = item->customdata;
-
- BLI_assert(old_id);
- BLI_addtail(which_libbase(bmain, GS(old_id->name)), old_id);
-
- /* Usual special code for ShapeKeys snowflakes... */
- Key *old_key = BKE_key_from_id(old_id);
- if (old_key != NULL) {
- BLI_addtail(which_libbase(bmain, GS(old_key->id.name)), &old_key->id);
- }
- }
-
- /* Since our (old) reloaded IDs were removed from main, the user count done for them in linking
- * code is wrong, we need to redo it here after adding them back to main. */
- BKE_main_id_refcount_recompute(bmain, false);
-
- /* Note that in reload case, we also want to replace indirect usages. */
- const short remap_flags = ID_REMAP_SKIP_NEVER_NULL_USAGE |
- ID_REMAP_NO_INDIRECT_PROXY_DATA_USAGE |
- (do_reload ? 0 : ID_REMAP_SKIP_INDIRECT_USAGE);
- for (item_idx = 0, itemlink = lapp_data->items.list; itemlink;
- item_idx++, itemlink = itemlink->next) {
- WMLinkAppendDataItem *item = itemlink->link;
- ID *old_id = item->customdata;
- ID *new_id = item->new_id;
-
- lib_relocate_do_remap(bmain, old_id, new_id, reports, do_reload, remap_flags);
- if (new_id == NULL) {
- continue;
- }
- /* Usual special code for ShapeKeys snowflakes... */
- Key **old_key_p = BKE_key_from_id_p(old_id);
- if (old_key_p == NULL) {
- continue;
- }
- Key *old_key = *old_key_p;
- Key *new_key = BKE_key_from_id(new_id);
- if (old_key != NULL) {
- *old_key_p = NULL;
- id_us_min(&old_key->id);
- lib_relocate_do_remap(bmain, &old_key->id, &new_key->id, reports, do_reload, remap_flags);
- *old_key_p = old_key;
- id_us_plus_no_lib(&old_key->id);
- }
- }
-
- BKE_main_unlock(bmain);
-
- for (item_idx = 0, itemlink = lapp_data->items.list; itemlink;
- item_idx++, itemlink = itemlink->next) {
- WMLinkAppendDataItem *item = itemlink->link;
- ID *old_id = item->customdata;
-
- if (old_id->us == 0) {
- BKE_id_free(bmain, old_id);
- }
- }
-
- /* Some datablocks can get reloaded/replaced 'silently' because they are not linkable
- * (shape keys e.g.), so we need another loop here to clear old ones if possible. */
- lba_idx = set_listbasepointers(bmain, lbarray);
- while (lba_idx--) {
- ID *id, *id_next;
- for (id = lbarray[lba_idx]->first; id; id = id_next) {
- id_next = id->next;
- /* XXX That check may be a bit to generic/permissive? */
- if (id->lib && (id->flag & LIB_TAG_PRE_EXISTING) && id->us == 0) {
- BKE_id_free(bmain, id);
- }
- }
- }
-
- /* Get rid of no more used libraries... */
- BKE_main_id_tag_idcode(bmain, ID_LI, LIB_TAG_DOIT, true);
- lba_idx = set_listbasepointers(bmain, lbarray);
- while (lba_idx--) {
- ID *id;
- for (id = lbarray[lba_idx]->first; id; id = id->next) {
- if (id->lib) {
- id->lib->id.tag &= ~LIB_TAG_DOIT;
- }
- }
- }
- Library *lib, *lib_next;
- for (lib = which_libbase(bmain, ID_LI)->first; lib; lib = lib_next) {
- lib_next = lib->id.next;
- if (lib->id.tag & LIB_TAG_DOIT) {
- id_us_clear_real(&lib->id);
- if (lib->id.us == 0) {
- BKE_id_free(bmain, (ID *)lib);
- }
- }
- }
-
- /* Update overrides of reloaded linked data-blocks. */
- ID *id;
- FOREACH_MAIN_ID_BEGIN (bmain, id) {
- if (ID_IS_LINKED(id) || !ID_IS_OVERRIDE_LIBRARY_REAL(id) ||
- (id->tag & LIB_TAG_PRE_EXISTING) == 0) {
- continue;
- }
- if ((id->override_library->reference->tag & LIB_TAG_PRE_EXISTING) == 0) {
- BKE_lib_override_library_update(bmain, id);
- }
- }
- FOREACH_MAIN_ID_END;
-
- /* Resync overrides if needed. */
- if (!USER_EXPERIMENTAL_TEST(&U, no_override_auto_resync)) {
- BKE_lib_override_library_main_resync(bmain,
- scene,
- view_layer,
- &(struct BlendFileReadReport){
- .reports = reports,
- });
- /* We need to rebuild some of the deleted override rules (for UI feedback purpose). */
- BKE_lib_override_library_main_operations_create(bmain, true);
- }
-
- BKE_main_collection_sync(bmain);
-
- BKE_main_lib_objects_recalc_all(bmain);
- IMB_colormanagement_check_file_config(bmain);
-
- /* important we unset, otherwise these object won't
- * link into other scenes from this blend file */
- BKE_main_id_tag_all(bmain, LIB_TAG_PRE_EXISTING, false);
-
- /* recreate dependency graph to include new objects */
- DEG_relations_tag_update(bmain);
-}
-
void WM_lib_reload(Library *lib, bContext *C, ReportList *reports)
{
if (!BLO_has_bfile_extension(lib->filepath_abs)) {
@@ -1740,14 +638,34 @@ void WM_lib_reload(Library *lib, bContext *C, ReportList *reports)
return;
}
- WMLinkAppendData *lapp_data = wm_link_append_data_new(BLO_LIBLINK_USE_PLACEHOLDERS |
- BLO_LIBLINK_FORCE_INDIRECT);
+ Main *bmain = CTX_data_main(C);
+ LibraryLink_Params lapp_params;
+ BLO_library_link_params_init_with_context(&lapp_params,
+ bmain,
+ BLO_LIBLINK_USE_PLACEHOLDERS |
+ BLO_LIBLINK_FORCE_INDIRECT,
+ 0,
+ CTX_data_scene(C),
+ CTX_data_view_layer(C),
+ NULL);
+
+ BlendfileLinkAppendContext *lapp_context = BKE_blendfile_link_append_context_new(&lapp_params);
- wm_link_append_data_library_add(lapp_data, lib->filepath_abs);
+ BKE_blendfile_link_append_context_library_add(lapp_context, lib->filepath_abs, NULL);
- lib_relocate_do(C, lib, lapp_data, reports, true);
+ BKE_blendfile_library_relocate(lapp_context, reports, lib, true);
- wm_link_append_data_free(lapp_data);
+ BKE_blendfile_link_append_context_free(lapp_context);
+
+ BKE_main_lib_objects_recalc_all(bmain);
+ IMB_colormanagement_check_file_config(bmain);
+
+ /* Important we unset, otherwise these object won't link into other scenes from this blend file.
+ */
+ BKE_main_id_tag_all(bmain, LIB_TAG_PRE_EXISTING, false);
+
+ /* Recreate dependency graph to include new IDs. */
+ DEG_relations_tag_update(bmain);
WM_event_add_notifier(C, NC_WINDOW, NULL);
}
@@ -1763,7 +681,7 @@ static int wm_lib_relocate_exec_do(bContext *C, wmOperator *op, bool do_reload)
if (lib) {
Main *bmain = CTX_data_main(C);
PropertyRNA *prop;
- WMLinkAppendData *lapp_data;
+ BlendfileLinkAppendContext *lapp_context;
char path[FILE_MAX], root[FILE_MAXDIR], libname[FILE_MAX], relname[FILE_MAX];
short flag = 0;
@@ -1808,13 +726,17 @@ static int wm_lib_relocate_exec_do(bContext *C, wmOperator *op, bool do_reload)
return OPERATOR_CANCELLED;
}
+ LibraryLink_Params lapp_params;
+ BLO_library_link_params_init_with_context(
+ &lapp_params, bmain, flag, 0, CTX_data_scene(C), CTX_data_view_layer(C), NULL);
+
if (BLI_path_cmp(lib->filepath_abs, path) == 0) {
CLOG_INFO(&LOG, 4, "We are supposed to reload '%s' lib (%d)", lib->filepath, lib->id.us);
do_reload = true;
- lapp_data = wm_link_append_data_new(flag);
- wm_link_append_data_library_add(lapp_data, path);
+ lapp_context = BKE_blendfile_link_append_context_new(&lapp_params);
+ BKE_blendfile_link_append_context_library_add(lapp_context, path, NULL);
}
else {
int totfiles = 0;
@@ -1834,7 +756,7 @@ static int wm_lib_relocate_exec_do(bContext *C, wmOperator *op, bool do_reload)
}
}
- lapp_data = wm_link_append_data_new(flag);
+ lapp_context = BKE_blendfile_link_append_context_new(&lapp_params);
if (totfiles) {
RNA_BEGIN (op->ptr, itemptr, "files") {
@@ -1847,27 +769,39 @@ static int wm_lib_relocate_exec_do(bContext *C, wmOperator *op, bool do_reload)
}
CLOG_INFO(&LOG, 4, "\tCandidate new lib to reload datablocks from: %s", path);
- wm_link_append_data_library_add(lapp_data, path);
+ BKE_blendfile_link_append_context_library_add(lapp_context, path, NULL);
}
RNA_END;
}
else {
CLOG_INFO(&LOG, 4, "\tCandidate new lib to reload datablocks from: %s", path);
- wm_link_append_data_library_add(lapp_data, path);
+ BKE_blendfile_link_append_context_library_add(lapp_context, path, NULL);
}
}
if (do_reload) {
- lapp_data->flag |= BLO_LIBLINK_USE_PLACEHOLDERS | BLO_LIBLINK_FORCE_INDIRECT;
+ BKE_blendfile_link_append_context_flag_set(
+ lapp_context, BLO_LIBLINK_USE_PLACEHOLDERS | BLO_LIBLINK_FORCE_INDIRECT, true);
}
- lib_relocate_do(C, lib, lapp_data, op->reports, do_reload);
+ BKE_blendfile_library_relocate(lapp_context, op->reports, lib, do_reload);
- wm_link_append_data_free(lapp_data);
+ BKE_blendfile_link_append_context_free(lapp_context);
/* XXX TODO: align G.lib with other directory storage (like last opened image etc...) */
BLI_strncpy(G.lib, root, FILE_MAX);
+ BKE_main_lib_objects_recalc_all(bmain);
+ IMB_colormanagement_check_file_config(bmain);
+
+ /* Important we unset, otherwise these object won't link into other scenes from this blend
+ * file.
+ */
+ BKE_main_id_tag_all(bmain, LIB_TAG_PRE_EXISTING, false);
+
+ /* Recreate dependency graph to include new IDs. */
+ DEG_relations_tag_update(bmain);
+
WM_event_add_notifier(C, NC_WINDOW, NULL);
return OPERATOR_FINISHED;
diff --git a/source/blender/windowmanager/intern/wm_keymap.c b/source/blender/windowmanager/intern/wm_keymap.c
index 658424b84a6..35f6ce40dba 100644
--- a/source/blender/windowmanager/intern/wm_keymap.c
+++ b/source/blender/windowmanager/intern/wm_keymap.c
@@ -1394,7 +1394,7 @@ static wmKeyMapItem *wm_keymap_item_find_handlers(const bContext *C,
wmWindow *win,
ListBase *handlers,
const char *opname,
- int UNUSED(opcontext),
+ wmOperatorCallContext UNUSED(opcontext),
IDProperty *properties,
const bool is_strict,
const struct wmKeyMapItemFind_Params *params,
@@ -1430,7 +1430,7 @@ static wmKeyMapItem *wm_keymap_item_find_handlers(const bContext *C,
static wmKeyMapItem *wm_keymap_item_find_props(const bContext *C,
const char *opname,
- int opcontext,
+ wmOperatorCallContext opcontext,
IDProperty *properties,
const bool is_strict,
const struct wmKeyMapItemFind_Params *params,
@@ -1543,7 +1543,7 @@ static wmKeyMapItem *wm_keymap_item_find_props(const bContext *C,
static wmKeyMapItem *wm_keymap_item_find(const bContext *C,
const char *opname,
- int opcontext,
+ wmOperatorCallContext opcontext,
IDProperty *properties,
bool is_strict,
const struct wmKeyMapItemFind_Params *params,
@@ -1642,7 +1642,7 @@ static bool kmi_filter_is_visible(const wmKeyMap *UNUSED(km),
char *WM_key_event_operator_string(const bContext *C,
const char *opname,
- int opcontext,
+ wmOperatorCallContext opcontext,
IDProperty *properties,
const bool is_strict,
char *result,
@@ -1682,7 +1682,7 @@ static bool kmi_filter_is_visible_type_mask(const wmKeyMap *km,
*/
wmKeyMapItem *WM_key_event_operator(const bContext *C,
const char *opname,
- int opcontext,
+ wmOperatorCallContext opcontext,
IDProperty *properties,
const short include_mask,
const short exclude_mask,
diff --git a/source/blender/windowmanager/intern/wm_operators.c b/source/blender/windowmanager/intern/wm_operators.c
index 1130ad9a558..ffdc99152b1 100644
--- a/source/blender/windowmanager/intern/wm_operators.c
+++ b/source/blender/windowmanager/intern/wm_operators.c
@@ -1064,7 +1064,7 @@ int WM_operator_smooth_viewtx_get(const wmOperator *op)
}
/* invoke callback, uses enum property named "type" */
-int WM_menu_invoke_ex(bContext *C, wmOperator *op, int opcontext)
+int WM_menu_invoke_ex(bContext *C, wmOperator *op, wmOperatorCallContext opcontext)
{
PropertyRNA *prop = op->type->prop;
@@ -1216,7 +1216,7 @@ int WM_operator_confirm_message_ex(bContext *C,
const char *title,
const int icon,
const char *message,
- const short opcontext)
+ const wmOperatorCallContext opcontext)
{
IDProperty *properties = op->ptr->data;
diff --git a/source/blender/windowmanager/intern/wm_playanim.c b/source/blender/windowmanager/intern/wm_playanim.c
index fa21dbcb4bb..640fef82085 100644
--- a/source/blender/windowmanager/intern/wm_playanim.c
+++ b/source/blender/windowmanager/intern/wm_playanim.c
@@ -1570,7 +1570,7 @@ static char *wm_main_playanim_intern(int argc, const char **argv)
/* initialize the font */
BLF_init();
ps.fontid = BLF_load_mono_default(false);
- BLF_size(ps.fontid, 11, 72);
+ BLF_size(ps.fontid, 11.0f, 72);
ps.ibufx = ibuf->x;
ps.ibufy = ibuf->y;
@@ -1845,7 +1845,6 @@ static char *wm_main_playanim_intern(int argc, const char **argv)
}
IMB_exit();
- BKE_images_exit();
DEG_free_node_types();
totblock = MEM_get_memory_blocks_in_use();
diff --git a/source/blender/windowmanager/wm_event_system.h b/source/blender/windowmanager/wm_event_system.h
index 40e4d905fcd..9b0f128d071 100644
--- a/source/blender/windowmanager/wm_event_system.h
+++ b/source/blender/windowmanager/wm_event_system.h
@@ -32,6 +32,7 @@
struct ARegion;
struct GHOST_TabletData;
struct ScrArea;
+enum wmOperatorCallContext;
#ifdef WITH_XR_OPENXR
struct wmXrActionData;
@@ -175,6 +176,7 @@ void wm_dropbox_free(void);
void wm_drags_exit(wmWindowManager *wm, wmWindow *win);
void wm_drop_prepare(bContext *C, wmDrag *drag, wmDropBox *drop);
void wm_drags_check_ops(bContext *C, const wmEvent *event);
+wmOperatorCallContext wm_drop_operator_context_get(const wmDropBox *drop);
void wm_drags_draw(bContext *C, wmWindow *win);
#ifdef __cplusplus
diff --git a/source/blender/windowmanager/xr/intern/wm_xr_operators.c b/source/blender/windowmanager/xr/intern/wm_xr_operators.c
index 112312bab7b..f3470edf2f7 100644
--- a/source/blender/windowmanager/xr/intern/wm_xr_operators.c
+++ b/source/blender/windowmanager/xr/intern/wm_xr_operators.c
@@ -432,10 +432,10 @@ static bool wm_xr_navigation_grab_can_do_bimanual(const wmXrActionData *actionda
const XrGrabData *data)
{
/* Returns true if: 1) Bimanual interaction is currently occurring (i.e. inputs on both
- controllers are pressed) and 2) bimanual interaction occurred on the last update. This second
- part is needed to avoid "jumpy" navigation changes when transitioning from one-handed to
- two-handed interaction (see #wm_xr_grab_compute/compute_bimanual() for how navigation deltas
- are calculated). */
+ * controllers are pressed) and 2) bimanual interaction occurred on the last update. This second
+ * part is needed to avoid "jumpy" navigation changes when transitioning from one-handed to
+ * two-handed interaction (see #wm_xr_grab_compute/compute_bimanual() for how navigation deltas
+ * are calculated). */
return (actiondata->bimanual && data->bimanual_prev);
}
@@ -545,7 +545,7 @@ static int wm_xr_navigation_grab_modal(bContext *C, wmOperator *op, const wmEven
/* Check if navigation is locked. */
if (!wm_xr_navigation_grab_is_locked(data, do_bimanual)) {
/* Prevent unwanted snapping (i.e. "jumpy" navigation changes when transitioning from
- two-handed to one-handed interaction) at the end of a bimanual interaction. */
+ * two-handed to one-handed interaction) at the end of a bimanual interaction. */
if (!wm_xr_navigation_grab_is_bimanual_ending(actiondata, data)) {
wm_xr_navigation_grab_apply(xr, actiondata, data, do_bimanual);
}
@@ -554,9 +554,9 @@ static int wm_xr_navigation_grab_modal(bContext *C, wmOperator *op, const wmEven
wm_xr_navigation_grab_bimanual_state_update(actiondata, data);
/* Note: KM_PRESS and KM_RELEASE are the only two values supported by XR events during event
- dispatching (see #wm_xr_session_action_states_interpret()). For modal XR operators, modal
- handling starts when an input is "pressed" (action state exceeds the action threshold) and
- ends when the input is "released" (state falls below the threshold). */
+ * dispatching (see #wm_xr_session_action_states_interpret()). For modal XR operators, modal
+ * handling starts when an input is "pressed" (action state exceeds the action threshold) and
+ * ends when the input is "released" (state falls below the threshold). */
switch (event->val) {
case KM_PRESS:
return OPERATOR_RUNNING_MODAL;
diff --git a/source/creator/creator.c b/source/creator/creator.c
index 7c99f954bfc..6daaea38c34 100644
--- a/source/creator/creator.c
+++ b/source/creator/creator.c
@@ -414,7 +414,6 @@ int main(int argc,
BKE_idtype_init();
BKE_cachefiles_init();
- BKE_images_init();
BKE_modifier_init();
BKE_gpencil_modifier_init();
BKE_shaderfx_init();
@@ -552,7 +551,8 @@ int main(int argc,
WM_exit(C);
}
else {
- if (!G.file_loaded) {
+ /* When no file is loaded, show the splash screen. */
+ if (!G.relbase_valid) {
WM_init_splash(C);
}
WM_main(C);
diff --git a/source/creator/creator_args.c b/source/creator/creator_args.c
index 943646daa81..896d29e0583 100644
--- a/source/creator/creator_args.c
+++ b/source/creator/creator_args.c
@@ -2008,8 +2008,6 @@ static int arg_handle_load_file(int UNUSED(argc), const char **argv, void *data)
}
}
- G.file_loaded = 1;
-
return 0;
}