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

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'source/blender')
-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.c254
-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_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_geometry_set.hh92
-rw-r--r--source/blender/blenkernel/BKE_global.h3
-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.h15
-rw-r--r--source/blender/blenkernel/BKE_spline.hh28
-rw-r--r--source/blender/blenkernel/CMakeLists.txt2
-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.cc136
-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/brush.c5
-rw-r--r--source/blender/blenkernel/intern/collection.c2
-rw-r--r--source/blender/blenkernel/intern/curve_to_mesh_convert.cc14
-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/geometry_component_curve.cc219
-rw-r--r--source/blender/blenkernel/intern/geometry_component_instances.cc26
-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_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.c5
-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/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/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/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_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/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/intern/readblenentry.c1
-rw-r--r--source/blender/blenloader/intern/versioning_300.c31
-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/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/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/tests/shaders_test.cc18
-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.cc7
-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_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.h33
-rw-r--r--source/blender/editors/interface/CMakeLists.txt2
-rw-r--r--source/blender/editors/interface/interface.c38
-rw-r--r--source/blender/editors/interface/interface_context_path.cc2
-rw-r--r--source/blender/editors/interface/interface_handlers.c6
-rw-r--r--source/blender/editors/interface/interface_icons_event.c26
-rw-r--r--source/blender/editors/interface/interface_intern.h9
-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_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_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.c2
-rw-r--r--source/blender/editors/interface/interface_templates.c2
-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_knife.c4
-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.c2
-rw-r--r--source/blender/editors/screen/screen_user_menu.c4
-rw-r--r--source/blender/editors/sculpt_paint/paint_image_2d.c33
-rw-r--r--source/blender/editors/sculpt_paint/paint_image_proj.c12
-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_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_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.cc6
-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.cc19
-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.hh (renamed from source/blender/editors/space_node/node_intern.h)26
-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.cc6
-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)139
-rw-r--r--source/blender/editors/space_outliner/outliner_edit.c6
-rw-r--r--source/blender/editors/space_spreadsheet/CMakeLists.txt10
-rw-r--r--source/blender/editors/space_spreadsheet/space_spreadsheet.cc2
-rw-r--r--source/blender/editors/space_spreadsheet/spreadsheet_cell_value.hh1
-rw-r--r--source/blender/editors/space_spreadsheet/spreadsheet_data_source_geometry.cc119
-rw-r--r--source/blender/editors/space_spreadsheet/spreadsheet_data_source_geometry.hh20
-rw-r--r--source/blender/editors/space_spreadsheet/spreadsheet_dataset_draw.cc19
-rw-r--r--source/blender/editors/space_spreadsheet/spreadsheet_dataset_layout.cc6
-rw-r--r--source/blender/editors/space_spreadsheet/spreadsheet_layout.cc17
-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_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/functions/FN_field.hh66
-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.hh2
-rw-r--r--source/blender/functions/FN_multi_function_params.hh26
-rw-r--r--source/blender/functions/intern/field.cc164
-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.cc24
-rw-r--r--source/blender/functions/intern/multi_function_parallel.cc4
-rw-r--r--source/blender/functions/intern/multi_function_procedure_executor.cc3
-rw-r--r--source/blender/functions/tests/FN_field_test.cc50
-rw-r--r--source/blender/functions/tests/FN_multi_function_procedure_test.cc37
-rw-r--r--source/blender/geometry/intern/mesh_to_curve_convert.cc16
-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/moviecache.c7
-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/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_image_types.h8
-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.h2
-rw-r--r--source/blender/makesdna/DNA_sequence_types.h2
-rw-r--r--source/blender/makesdna/DNA_space_types.h9
-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/rna_animviz.c2
-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_force.c3
-rw-r--r--source/blender/makesrna/intern/rna_sequencer.c6
-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_uvproject.c4
-rw-r--r--source/blender/nodes/CMakeLists.txt1
-rw-r--r--source/blender/nodes/NOD_common.h2
-rw-r--r--source/blender/nodes/NOD_geometry_exec.hh27
-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/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_align_rotation_to_vector.cc10
-rw-r--r--source/blender/nodes/geometry/nodes/legacy/node_geo_attribute_clamp.cc32
-rw-r--r--source/blender/nodes/geometry/nodes/legacy/node_geo_attribute_color_ramp.cc2
-rw-r--r--source/blender/nodes/geometry/nodes/legacy/node_geo_attribute_combine_xyz.cc14
-rw-r--r--source/blender/nodes/geometry/nodes/legacy/node_geo_attribute_compare.cc34
-rw-r--r--source/blender/nodes/geometry/nodes/legacy/node_geo_attribute_convert.cc4
-rw-r--r--source/blender/nodes/geometry/nodes/legacy/node_geo_attribute_curve_map.cc15
-rw-r--r--source/blender/nodes/geometry/nodes/legacy/node_geo_attribute_fill.cc12
-rw-r--r--source/blender/nodes/geometry/nodes/legacy/node_geo_attribute_map_range.cc33
-rw-r--r--source/blender/nodes/geometry/nodes/legacy/node_geo_attribute_math.cc12
-rw-r--r--source/blender/nodes/geometry/nodes/legacy/node_geo_attribute_mix.cc29
-rw-r--r--source/blender/nodes/geometry/nodes/legacy/node_geo_attribute_proximity.cc2
-rw-r--r--source/blender/nodes/geometry/nodes/legacy/node_geo_attribute_randomize.cc22
-rw-r--r--source/blender/nodes/geometry/nodes/legacy/node_geo_attribute_sample_texture.cc2
-rw-r--r--source/blender/nodes/geometry/nodes/legacy/node_geo_attribute_separate_xyz.cc8
-rw-r--r--source/blender/nodes/geometry/nodes/legacy/node_geo_attribute_transfer.cc10
-rw-r--r--source/blender/nodes/geometry/nodes/legacy/node_geo_attribute_vector_math.cc64
-rw-r--r--source/blender/nodes/geometry/nodes/legacy/node_geo_attribute_vector_rotate.cc51
-rw-r--r--source/blender/nodes/geometry/nodes/legacy/node_geo_curve_endpoints.cc8
-rw-r--r--source/blender/nodes/geometry/nodes/legacy/node_geo_curve_reverse.cc2
-rw-r--r--source/blender/nodes/geometry/nodes/legacy/node_geo_curve_set_handles.cc2
-rw-r--r--source/blender/nodes/geometry/nodes/legacy/node_geo_curve_spline_type.cc2
-rw-r--r--source/blender/nodes/geometry/nodes/legacy/node_geo_curve_subdivide.cc15
-rw-r--r--source/blender/nodes/geometry/nodes/legacy/node_geo_curve_to_points.cc24
-rw-r--r--source/blender/nodes/geometry/nodes/legacy/node_geo_delete_geometry.cc8
-rw-r--r--source/blender/nodes/geometry/nodes/legacy/node_geo_material_assign.cc2
-rw-r--r--source/blender/nodes/geometry/nodes/legacy/node_geo_mesh_to_curve.cc2
-rw-r--r--source/blender/nodes/geometry/nodes/legacy/node_geo_point_distribute.cc23
-rw-r--r--source/blender/nodes/geometry/nodes/legacy/node_geo_point_instance.cc24
-rw-r--r--source/blender/nodes/geometry/nodes/legacy/node_geo_point_rotate.cc11
-rw-r--r--source/blender/nodes/geometry/nodes/legacy/node_geo_point_scale.cc10
-rw-r--r--source/blender/nodes/geometry/nodes/legacy/node_geo_point_separate.cc6
-rw-r--r--source/blender/nodes/geometry/nodes/legacy/node_geo_point_translate.cc8
-rw-r--r--source/blender/nodes/geometry/nodes/legacy/node_geo_points_to_volume.cc19
-rw-r--r--source/blender/nodes/geometry/nodes/legacy/node_geo_raycast.cc18
-rw-r--r--source/blender/nodes/geometry/nodes/legacy/node_geo_volume_to_mesh.cc8
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_attribute_capture.cc22
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_attribute_statistic.cc40
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_boolean.cc10
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_collection_info.cc2
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_common.cc4
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_convex_hull.cc20
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_curve_endpoint_selection.cc10
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_curve_fillet.cc20
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_curve_handle_type_selection.cc14
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_curve_parameter.cc176
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_curve_primitive_bezier_segment.cc22
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_curve_primitive_circle.cc44
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_curve_primitive_line.cc30
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_curve_primitive_quadratic_bezier.cc14
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_curve_primitive_quadrilateral.cc84
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_curve_primitive_spiral.cc26
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_curve_primitive_star.cc45
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_curve_resample.cc64
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_curve_sample.cc6
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_curve_subdivide.cc4
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_curve_to_points.cc16
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_curve_trim.cc34
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_delete_geometry.cc8
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_distribute_points_on_faces.cc18
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_edge_split.cc9
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_input_normal.cc80
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_input_spline_length.cc30
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_input_tangent.cc25
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_instance_on_points.cc31
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_join_geometry.cc17
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_material_selection.cc19
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_circle.cc11
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_cone.cc229
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_cube.cc21
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_cylinder.cc69
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_grid.cc24
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_ico_sphere.cc17
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_line.cc29
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_uv_sphere.cc18
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_mesh_to_points.cc6
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_object_info.cc88
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_points_to_vertices.cc6
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_points_to_volume.cc25
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_raycast.cc22
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_set_curve_handles.cc25
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_string_to_curves.cc8
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_switch.cc14
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_transfer_attribute.cc45
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_viewer.cc4
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_volume_to_mesh.cc8
-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.cc30
-rw-r--r--source/blender/nodes/intern/node_socket.cc3
-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.cc58
-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_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.cc18
-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/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_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.c19
-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
431 files changed, 9058 insertions, 5827 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..959faca2f46 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) {
@@ -617,31 +589,22 @@ void blf_font_draw_buffer(FontBLF *font,
* - #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 766a3f34a66..3478eebbeb4 100644
--- a/source/blender/blenkernel/BKE_asset_catalog.hh
+++ b/source/blender/blenkernel/BKE_asset_catalog.hh
@@ -429,7 +429,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_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 6bdec0d70f3..43784b5a856 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 41
+#define BLENDER_FILE_SUBVERSION 2
/* 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_geometry_set.hh b/source/blender/blenkernel/BKE_geometry_set.hh
index 58a89d0207a..63ada807c55 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 {
@@ -759,9 +773,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 +790,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 +829,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..4f1da0a972f 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,7 +211,7 @@ 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.
*/
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 b38125b791d..4faf6d94df8 100644
--- a/source/blender/blenkernel/BKE_lib_id.h
+++ b/source/blender/blenkernel/BKE_lib_id.h
@@ -134,8 +134,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..bbeb01de0ff 100644
--- a/source/blender/blenkernel/BKE_node.h
+++ b/source/blender/blenkernel/BKE_node.h
@@ -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..c332e9a8dac 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;
diff --git a/source/blender/blenkernel/CMakeLists.txt b/source/blender/blenkernel/CMakeLists.txt
index d4ec7fd703d..b2418d0539c 100644
--- a/source/blender/blenkernel/CMakeLists.txt
+++ b/source/blender/blenkernel/CMakeLists.txt
@@ -192,7 +192,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
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 13f66445c46..03043f3b784 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..f3ece270618 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 {
@@ -207,7 +205,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 +255,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 +311,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 +343,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 +508,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 +538,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 +748,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 +919,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 +1107,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 +1125,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 +1135,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 +1145,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 +1173,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 +1181,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 +1195,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 +1208,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 +1234,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 +1263,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 +1306,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 +1323,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 +1344,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 +1360,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 +1379,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 +1407,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
@@ -1457,25 +1454,25 @@ static StringRef get_random_id_attribute_name(const AttributeDomain domain)
}
}
-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 +1492,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/brush.c b/source/blender/blenkernel/intern/brush.c
index 7d217d6907d..dc3c2a8e55e 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)
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/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/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/geometry_component_curve.cc b/source/blender/blenkernel/intern/geometry_component_curve.cc
index d3c3fcc1e67..0b80ff5acdf 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());
}
@@ -623,9 +615,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:
@@ -634,16 +626,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 {};
@@ -691,11 +682,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);
@@ -723,29 +714,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);
}
@@ -754,30 +745,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];
@@ -786,30 +777,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));
}
/**
@@ -820,24 +809,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];
@@ -852,7 +841,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];
@@ -885,21 +874,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_;
@@ -907,7 +895,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)
@@ -929,7 +917,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_);
}
@@ -976,19 +964,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_;
@@ -998,19 +985,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];
@@ -1026,7 +1013,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];
@@ -1049,13 +1036,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);
@@ -1097,7 +1083,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) {
@@ -1110,7 +1096,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();
@@ -1119,7 +1105,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
@@ -1144,8 +1130,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)};
}
@@ -1156,7 +1141,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
@@ -1248,10 +1233,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};
}
@@ -1273,7 +1256,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) {
@@ -1285,8 +1268,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
@@ -1303,12 +1286,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
@@ -1387,7 +1368,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 = {};
@@ -1399,7 +1380,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;
}
@@ -1440,7 +1421,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 = {};
@@ -1452,7 +1433,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..047bceda4fe 100644
--- a/source/blender/blenkernel/intern/geometry_component_instances.cc
+++ b/source/blender/blenkernel/intern/geometry_component_instances.cc
@@ -389,25 +389,22 @@ class InstancePositionAttributeProvider final : public BuiltinAttributeProvider
{
}
- 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
@@ -435,13 +432,13 @@ class InstanceIDAttributeProvider final : public BuiltinAttributeProvider {
{
}
- 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 +447,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 +473,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: {
diff --git a/source/blender/blenkernel/intern/geometry_component_mesh.cc b/source/blender/blenkernel/intern/geometry_component_mesh.cc
index c3e39c0b2cb..86a52b420b6 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
@@ -1184,7 +1177,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();
@@ -1197,8 +1190,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);
@@ -1207,7 +1199,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 f820b345c59..ffc39028400 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"
@@ -383,6 +384,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 311199f8833..c0efc246567 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. */
@@ -5101,11 +5120,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;
}
@@ -5124,9 +5143,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);
}
}
@@ -5140,7 +5159,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);
@@ -5148,7 +5167,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);
@@ -5168,6 +5187,7 @@ typedef struct ImagePoolItem {
typedef struct ImagePool {
ListBase image_buffers;
BLI_mempool *memory_pool;
+ ThreadMutex mutex;
} ImagePool;
ImagePool *BKE_image_pool_new(void)
@@ -5175,21 +5195,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);
}
@@ -5221,28 +5248,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;
@@ -5253,7 +5286,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;
}
@@ -5642,7 +5675,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);
@@ -5657,7 +5690,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;
@@ -5686,7 +5719,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);
@@ -5700,14 +5733,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);
@@ -5717,7 +5750,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;
}
@@ -5730,7 +5763,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);
@@ -5745,7 +5778,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;
}
@@ -5763,7 +5796,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);
@@ -5776,7 +5809,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_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..3a4e39812ab 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);
}
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 deef053b658..d650003afe2 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];
};
@@ -5400,7 +5409,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.
*
@@ -5426,7 +5435,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/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/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/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_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/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..7a548e7c434 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);
+ }
+ {
+ 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/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 9009eb36585..e0e59600704 100644
--- a/source/blender/blenloader/intern/versioning_300.c
+++ b/source/blender/blenloader/intern/versioning_300.c
@@ -1272,6 +1272,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);
+ }
+ }
+}
+
/* NOLINTNEXTLINE: readability-function-size */
void blo_do_versions_300(FileData *fd, Library *UNUSED(lib), Main *bmain)
{
@@ -2158,22 +2170,11 @@ void blo_do_versions_300(FileData *fd, Library *UNUSED(lib), Main *bmain)
* \note Keep this message at the bottom of the function.
*/
{
- /* Use consistent socket identifiers for the math node.
- * The code to make unique identifiers from the names was inconsistent. */
+ /* Keep this block, even when empty. */
+
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;
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/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/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/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_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..cac6e9965b6 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;
+ }
+ else 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 c57d121a18f..1a2d3f5837a 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 d2fd8ab88a4..f7c567c89f6 100644
--- a/source/blender/editors/asset/intern/asset_ops.cc
+++ b/source/blender/editors/asset/intern/asset_ops.cc
@@ -18,19 +18,13 @@
* \ingroup edasset
*/
-#include "BKE_asset.h"
-#include "BKE_asset_catalog.hh"
#include "BKE_asset_library.hh"
#include "BKE_context.h"
#include "BKE_lib_id.h"
#include "BKE_main.h"
#include "BKE_report.h"
-#include "BLI_string_ref.hh"
-#include "BLI_vector.hh"
-
#include "ED_asset.h"
-#include "ED_asset_catalog.hh"
/* XXX needs access to the file list, should all be done via the asset system in future. */
#include "ED_fileselect.h"
@@ -38,7 +32,6 @@
#include "RNA_define.h"
#include "WM_api.h"
-#include "WM_types.h"
using namespace blender;
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_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 725c9921d13..a244e77fcea 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
@@ -691,7 +692,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);
@@ -1002,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,
@@ -1012,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,
@@ -1185,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,
@@ -1195,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,
@@ -1381,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,
@@ -1392,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,
@@ -1723,7 +1724,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);
@@ -1963,7 +1964,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);
@@ -2391,7 +2392,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,
@@ -2399,7 +2400,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,
@@ -2407,7 +2408,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);
@@ -2487,14 +2488,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/interface/CMakeLists.txt b/source/blender/editors/interface/CMakeLists.txt
index 84172c7efce..2a8f40b2631 100644
--- a/source/blender/editors/interface/CMakeLists.txt
+++ b/source/blender/editors/interface/CMakeLists.txt
@@ -66,7 +66,7 @@ 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
diff --git a/source/blender/editors/interface/interface.c b/source/blender/editors/interface/interface.c
index 9f9324505ad..67ad4731b18 100644
--- a/source/blender/editors/interface/interface.c
+++ b/source/blender/editors/interface/interface.c
@@ -1638,7 +1638,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 +1678,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 +1881,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 +1993,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. */
@@ -4755,7 +4741,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 +5279,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 +5294,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 +5662,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 +5677,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 +6065,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 +6082,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,
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_handlers.c b/source/blender/editors/interface/interface_handlers.c
index 6d69724efef..8a744a1edbe 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);
}
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..8c33e2d1cc9 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;
@@ -609,7 +609,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 +882,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 +960,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 072362492d8..6acbaf03476 100644
--- a/source/blender/editors/interface/interface_panel.c
+++ b/source/blender/editors/interface/interface_panel.c
@@ -1348,7 +1348,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_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_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 d3ce7ebc3db..7b2fb8f784e 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.c
index 5877b4fe6d7..26250e105eb 100644
--- a/source/blender/editors/interface/interface_template_search_menu.c
+++ b/source/blender/editors/interface/interface_template_search_menu.c
@@ -115,7 +115,7 @@ struct MenuSearch_Item {
struct {
wmOperatorType *type;
PointerRNA *opptr;
- short opcontext;
+ wmOperatorCallContext opcontext;
bContextStore *context;
} op;
diff --git a/source/blender/editors/interface/interface_templates.c b/source/blender/editors/interface/interface_templates.c
index 1d349aa0596..b30a86c5fcf 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/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_knife.c b/source/blender/editors/mesh/editmesh_knife.c
index b712cfc24ed..cd04f40dedf 100644
--- a/source/blender/editors/mesh/editmesh_knife.c
+++ b/source/blender/editors/mesh/editmesh_knife.c
@@ -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. */
diff --git a/source/blender/editors/object/object_add.c b/source/blender/editors/object/object_add.c
index 90caeecd91f..8b5894923ad 100644
--- a/source/blender/editors/object/object_add.c
+++ b/source/blender/editors/object/object_add.c
@@ -2145,7 +2145,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;
@@ -2378,7 +2378,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);
@@ -3374,8 +3374,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..8523496bdbd 100644
--- a/source/blender/editors/screen/area.c
+++ b/source/blender/editors/screen/area.c
@@ -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.
*/
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/paint_image_2d.c b/source/blender/editors/sculpt_paint/paint_image_2d.c
index 63f61b6c5c1..318180e5eb4 100644
--- a/source/blender/editors/sculpt_paint/paint_image_2d.c
+++ b/source/blender/editors/sculpt_paint/paint_image_2d.c
@@ -381,18 +381,17 @@ static void brush_painter_mask_imbuf_partial_update(BrushPainter *painter,
}
/* create a mask with the falloff strength */
-static ushort *brush_painter_curve_mask_new(BrushPainter *painter,
- int diameter,
- float radius,
- const float pos[2])
+static ushort *brush_painter_curve_mask_init(
+ ushort *mask, BrushPainter *painter, int diameter, float radius, const float pos[2])
{
+ BLI_assert_msg(MEM_allocN_len(mask) == diameter * diameter * sizeof(ushort),
+ "Allocated size of mask doesn't match.");
+
Brush *brush = painter->brush;
int offset = (int)floorf(diameter / 2.0f);
- ushort *mask, *m;
-
- mask = MEM_mallocN(sizeof(ushort) * diameter * diameter, "brush_painter_mask");
+ ushort *m;
m = mask;
int aa_samples = 1.0f / (radius * 0.20f);
@@ -453,6 +452,20 @@ static ushort *brush_painter_curve_mask_new(BrushPainter *painter,
return mask;
}
+static void brush_painter_curve_mask_refresh(
+ BrushPainter *painter, ImagePaintTile *tile, int diameter, float radius, const float pos[2])
+{
+ BrushPainterCache *cache = &tile->cache;
+
+ if (diameter != cache->lastdiameter) {
+ if (cache->curve_mask != NULL) {
+ MEM_freeN(cache->curve_mask);
+ }
+ cache->curve_mask = MEM_mallocN(sizeof(ushort) * diameter * diameter, "brush_painter_mask");
+ }
+ brush_painter_curve_mask_init(cache->curve_mask, painter, diameter, radius, pos);
+}
+
/* create imbuf with brush color */
static ImBuf *brush_painter_imbuf_new(
BrushPainter *painter, ImagePaintTile *tile, const int size, float pressure, float distance)
@@ -858,10 +871,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. */
+ brush_painter_curve_mask_refresh(painter, tile, diameter, size, pos);
/* detect if we need to recreate image brush buffer */
if (diameter != cache->lastdiameter || (tex_rotation != cache->last_tex_rotation) || do_random ||
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_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_file/filelist.c b/source/blender/editors/space_file/filelist.c
index e6575316aec..d32e947d688 100644
--- a/source/blender/editors/space_file/filelist.c
+++ b/source/blender/editors/space_file/filelist.c
@@ -1731,7 +1731,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;
}
@@ -1762,6 +1762,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,
@@ -1917,6 +1918,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,
@@ -2016,7 +2018,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));
@@ -2680,24 +2681,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) {
+ entry->flags &= ~FILE_ENTRY_PREVIEW_LOADING;
+ 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;
}
}
- 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_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 d903e9ee984..63461056c8f 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
@@ -342,7 +342,7 @@ static void node_draw_frame_label(bNodeTree *ntree, bNode *node, const float asp
/* 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 +350,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);
diff --git a/source/blender/editors/space_node/node_add.cc b/source/blender/editors/space_node/node_add.cc
index cb66d0dbd2b..ea78ff36ab6 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..b2c16280c58 100644
--- a/source/blender/editors/space_node/node_draw.cc
+++ b/source/blender/editors/space_node/node_draw.cc
@@ -85,7 +85,7 @@
#include "FN_field_cpp_type.hh"
-#include "node_intern.h" /* own include */
+#include "node_intern.hh" /* own include */
#ifdef WITH_COMPOSITOR
# include "COM_compositor.h"
@@ -1107,21 +1107,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";
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.hh
index 383fe5afdf9..137b2a2a88a 100644
--- a/source/blender/editors/space_node/node_intern.h
+++ b/source/blender/editors/space_node/node_intern.hh
@@ -26,6 +26,10 @@
#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 */
@@ -43,10 +47,6 @@ 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;
@@ -265,11 +265,11 @@ 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);
+bool 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);
@@ -342,14 +342,6 @@ extern const char *node_context_dir[];
#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_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..ab20eaf131f 100644
--- a/source/blender/editors/space_node/node_relationships.cc
+++ b/source/blender/editors/space_node/node_relationships.cc
@@ -60,7 +60,7 @@
#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;
@@ -2369,8 +2369,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 0b5d7cdda82..a94deb97f42 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;
@@ -316,8 +311,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 +322,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 +332,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 +374,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 +399,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 +442,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 +452,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 +480,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 +489,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 +511,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 +521,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,12 +530,12 @@ 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);
+ if (snode->runtime != nullptr) {
+ snoden->runtime = (SpaceNode_Runtime *)MEM_dupallocN(snode->runtime);
BLI_listbase_clear(&snoden->runtime->linkdrag);
}
@@ -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_spreadsheet/CMakeLists.txt b/source/blender/editors/space_spreadsheet/CMakeLists.txt
index 91fe1bc01b7..192b80881ee 100644
--- a/source/blender/editors/space_spreadsheet/CMakeLists.txt
+++ b/source/blender/editors/space_spreadsheet/CMakeLists.txt
@@ -67,4 +67,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..50b67c55bd6 100644
--- a/source/blender/editors/space_spreadsheet/space_spreadsheet.cc
+++ b/source/blender/editors/space_spreadsheet/space_spreadsheet.cc
@@ -319,6 +319,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;
}
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..fef84719bc4 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,6 +496,91 @@ 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)
@@ -644,7 +738,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;
@@ -682,6 +776,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..25a9d0f0213 100644
--- a/source/blender/editors/space_spreadsheet/spreadsheet_dataset_draw.cc
+++ b/source/blender/editors/space_spreadsheet/spreadsheet_dataset_draw.cc
@@ -20,6 +20,7 @@
#include "DNA_windowmanager_types.h"
#include "BKE_context.h"
+#include "BKE_volume.h"
#include "BLF_api.h"
@@ -48,7 +49,7 @@ static int is_component_row_selected(struct uiBut *but, const void *arg)
const bool is_domain_selected = (AttributeDomain)sspreadsheet->attribute_domain == domain;
bool is_selected = is_component_selected && is_domain_selected;
- if (component == GEO_COMPONENT_TYPE_INSTANCES) {
+ if (ELEM(component, GEO_COMPONENT_TYPE_VOLUME, GEO_COMPONENT_TYPE_INSTANCES)) {
is_selected = is_component_selected;
}
@@ -141,6 +142,14 @@ static int element_count_from_instances(const GeometrySet &geometry_set)
return 0;
}
+static int element_count_from_volume(const GeometrySet &geometry_set)
+{
+ if (const Volume *volume = geometry_set.get_volume_for_read()) {
+ return BKE_volume_num_grids(volume);
+ }
+ return 0;
+}
+
static int element_count_from_component_domain(const GeometrySet &geometry_set,
GeometryComponentType component,
AttributeDomain domain)
@@ -191,6 +200,10 @@ void DatasetRegionDrawer::draw_dataset_row(const int indentation,
BLI_str_format_attribute_domain_size(
element_count, element_count_from_instances(draw_context.current_geometry_set));
}
+ else if (component == GEO_COMPONENT_TYPE_VOLUME) {
+ BLI_str_format_attribute_domain_size(
+ element_count, element_count_from_volume(draw_context.current_geometry_set));
+ }
else {
BLI_str_format_attribute_domain_size(
element_count,
@@ -206,7 +219,7 @@ void DatasetRegionDrawer::draw_dataset_row(const int indentation,
uiBut *bt = uiDefIconTextButO(&block,
UI_BTYPE_DATASETROW,
"SPREADSHEET_OT_change_spreadsheet_data_source",
- 0,
+ WM_OP_INVOKE_DEFAULT,
icon,
label,
rect.xmin,
@@ -237,7 +250,7 @@ void DatasetRegionDrawer::draw_dataset_row(const int indentation,
void DatasetRegionDrawer::draw_component_row(const DatasetComponentLayoutInfo &component_info)
{
- if (component_info.type == GEO_COMPONENT_TYPE_INSTANCES) {
+ if (ELEM(component_info.type, GEO_COMPONENT_TYPE_VOLUME, GEO_COMPONENT_TYPE_INSTANCES)) {
draw_dataset_row(
0, component_info.type, std::nullopt, component_info.icon, component_info.label, true);
}
diff --git a/source/blender/editors/space_spreadsheet/spreadsheet_dataset_layout.cc b/source/blender/editors/space_spreadsheet/spreadsheet_dataset_layout.cc
index abbad8c7088..f15af2e4d32 100644
--- a/source/blender/editors/space_spreadsheet/spreadsheet_dataset_layout.cc
+++ b/source/blender/editors/space_spreadsheet/spreadsheet_dataset_layout.cc
@@ -75,6 +75,12 @@ constexpr DatasetComponentLayoutInfo DATASET_layout_hierarchy[] = {
},
},
{
+ GEO_COMPONENT_TYPE_VOLUME,
+ N_("Volume Grids"),
+ ICON_VOLUME_DATA,
+ {},
+ },
+ {
GEO_COMPONENT_TYPE_INSTANCES,
N_("Instances"),
ICON_EMPTY_AXIS,
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_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 6acf51aec6e..3a9c9e27ef0 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_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/functions/FN_field.hh b/source/blender/functions/FN_field.hh
index 5e0302130af..fb488fdbfa9 100644
--- a/source/blender/functions/FN_field.hh
+++ b/source/blender/functions/FN_field.hh
@@ -248,9 +248,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 +268,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 +289,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 +317,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 +341,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 +352,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 +376,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 +392,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
@@ -429,11 +425,11 @@ 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;
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..c57f6cf574e 100644
--- a/source/blender/functions/FN_multi_function.hh
+++ b/source/blender/functions/FN_multi_function.hh
@@ -131,8 +131,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_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/intern/field.cc b/source/blender/functions/intern/field.cc
index 4de5e71c910..68a8446e6ae 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];
@@ -278,29 +277,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 +324,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 +337,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;
}
@@ -357,8 +369,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 +379,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 +391,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. */
@@ -404,15 +416,12 @@ Vector<const GVArray *> evaluate_fields(ResourceScope &scope,
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};
+ 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 +430,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 +491,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);
}
/**
@@ -512,9 +518,9 @@ GField make_field_constant_if_possible(GField field)
return GField{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 +532,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 +635,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 +679,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 +687,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..43eacdcd2a1 100644
--- a/source/blender/functions/intern/multi_function.cc
+++ b/source/blender/functions/intern/multi_function.cc
@@ -18,28 +18,4 @@
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_;
-
} // namespace blender::fn
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_executor.cc b/source/blender/functions/intern/multi_function_procedure_executor.cc
index 6d2d121bafd..85d0cf4909f 100644
--- a/source/blender/functions/intern/multi_function_procedure_executor.cc
+++ b/source/blender/functions/intern/multi_function_procedure_executor.cc
@@ -66,6 +66,7 @@ struct VariableValue_GVArray : public VariableValue {
VariableValue_GVArray(const GVArray &data) : VariableValue(static_type), data(data)
{
+ BLI_assert(data);
}
};
@@ -756,7 +757,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..16a6c73183d 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);
}
};
@@ -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..a0919d7926e 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{"My Procedure", 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)
{
/**
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/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/moviecache.c b/source/blender/imbuf/intern/moviecache.c
index 4f316150e10..8923ba98e08 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);
}
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/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_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_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 86fd6b9744a..03110f6e1be 100644
--- a/source/blender/makesdna/DNA_screen_types.h
+++ b/source/blender/makesdna/DNA_screen_types.h
@@ -667,7 +667,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..7fb15fc8508 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,
};
/** \} */
@@ -2006,6 +2010,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/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_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 c4efe5a0ea1..a62c27f5f4b 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_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..61b3f1d63d6 100644
--- a/source/blender/makesrna/intern/rna_sequencer.c
+++ b/source/blender/makesrna/intern/rna_sequencer.c
@@ -2980,11 +2980,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_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 32b3be9ee09..0e90372cd7b 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);
@@ -1128,39 +1136,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)
@@ -5016,6 +5025,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_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..0b4c34d6155 100644
--- a/source/blender/nodes/CMakeLists.txt
+++ b/source/blender/nodes/CMakeLists.txt
@@ -39,6 +39,7 @@ set(INC
../makesdna
../makesrna
../render
+ ../windowmanager
../../../intern/glew-mx
../../../intern/guardedalloc
../../../intern/sky/include
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..700f32ee414 100644
--- a/source/blender/nodes/NOD_geometry_exec.hh
+++ b/source/blender/nodes/NOD_geometry_exec.hh
@@ -57,13 +57,8 @@ 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 geometry_nodes_eval_log::NodeWarningType;
/**
@@ -316,21 +311,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_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/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_align_rotation_to_vector.cc
index b92d4704d63..dc7c251d034 100644
--- a/source/blender/nodes/geometry/nodes/legacy/node_geo_align_rotation_to_vector.cc
+++ b/source/blender/nodes/geometry/nodes/legacy/node_geo_align_rotation_to_vector.cc
@@ -65,14 +65,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 geo_node_align_rotation_to_vector_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 +179,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};
diff --git a/source/blender/nodes/geometry/nodes/legacy/node_geo_attribute_clamp.cc b/source/blender/nodes/geometry/nodes/legacy/node_geo_attribute_clamp.cc
index 91ff114a480..a11a1bd3825 100644
--- a/source/blender/nodes/geometry/nodes/legacy/node_geo_attribute_clamp.cc
+++ b/source/blender/nodes/geometry/nodes/legacy/node_geo_attribute_clamp.cc
@@ -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 geo_node_attribute_clamp_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: {
diff --git a/source/blender/nodes/geometry/nodes/legacy/node_geo_attribute_color_ramp.cc b/source/blender/nodes/geometry/nodes/legacy/node_geo_attribute_color_ramp.cc
index ab4b6aad545..061f5f3d7ee 100644
--- a/source/blender/nodes/geometry/nodes/legacy/node_geo_attribute_color_ramp.cc
+++ b/source/blender/nodes/geometry/nodes/legacy/node_geo_attribute_color_ramp.cc
@@ -85,7 +85,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();
diff --git a/source/blender/nodes/geometry/nodes/legacy/node_geo_attribute_combine_xyz.cc b/source/blender/nodes/geometry/nodes/legacy/node_geo_attribute_combine_xyz.cc
index d4c23380b4e..a610356955b 100644
--- a/source/blender/nodes/geometry/nodes/legacy/node_geo_attribute_combine_xyz.cc
+++ b/source/blender/nodes/geometry/nodes/legacy/node_geo_attribute_combine_xyz.cc
@@ -57,15 +57,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 geo_node_attribute_combine_xyz_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 +95,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())) {
diff --git a/source/blender/nodes/geometry/nodes/legacy/node_geo_attribute_compare.cc b/source/blender/nodes/geometry/nodes/legacy/node_geo_attribute_compare.cc
index e4e43a7b724..a4ffe884999 100644
--- a/source/blender/nodes/geometry/nodes/legacy/node_geo_attribute_compare.cc
+++ b/source/blender/nodes/geometry/nodes/legacy/node_geo_attribute_compare.cc
@@ -65,16 +65,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 geo_node_attribute_compare_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 +257,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,47 +276,47 @@ 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();
diff --git a/source/blender/nodes/geometry/nodes/legacy/node_geo_attribute_convert.cc b/source/blender/nodes/geometry/nodes/legacy/node_geo_attribute_convert.cc
index dc05fa2c125..13ba8d13618 100644
--- a/source/blender/nodes/geometry/nodes/legacy/node_geo_attribute_convert.cc
+++ b/source/blender/nodes/geometry/nodes/legacy/node_geo_attribute_convert.cc
@@ -104,7 +104,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 +118,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());
diff --git a/source/blender/nodes/geometry/nodes/legacy/node_geo_attribute_curve_map.cc b/source/blender/nodes/geometry/nodes/legacy/node_geo_attribute_curve_map.cc
index 669ac21436f..af56df0dc3f 100644
--- a/source/blender/nodes/geometry/nodes/legacy/node_geo_attribute_curve_map.cc
+++ b/source/blender/nodes/geometry/nodes/legacy/node_geo_attribute_curve_map.cc
@@ -136,10 +136,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 +148,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 +160,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]);
}
diff --git a/source/blender/nodes/geometry/nodes/legacy/node_geo_attribute_fill.cc b/source/blender/nodes/geometry/nodes/legacy/node_geo_attribute_fill.cc
index 5cb49dd83d0..a1b537e9657 100644
--- a/source/blender/nodes/geometry/nodes/legacy/node_geo_attribute_fill.cc
+++ b/source/blender/nodes/geometry/nodes/legacy/node_geo_attribute_fill.cc
@@ -47,7 +47,7 @@ static void geo_node_attribute_fill_init(bNodeTree *UNUSED(tree), bNode *node)
node->custom2 = ATTR_DOMAIN_AUTO;
}
-static void geo_node_attribute_fill_update(bNodeTree *UNUSED(ntree), bNode *node)
+static void geo_node_attribute_fill_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)
diff --git a/source/blender/nodes/geometry/nodes/legacy/node_geo_attribute_map_range.cc b/source/blender/nodes/geometry/nodes/legacy/node_geo_attribute_map_range.cc
index 978c75187fe..2c70157d586 100644
--- a/source/blender/nodes/geometry/nodes/legacy/node_geo_attribute_map_range.cc
+++ b/source/blender/nodes/geometry/nodes/legacy/node_geo_attribute_map_range.cc
@@ -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 geo_node_attribute_map_range_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:
diff --git a/source/blender/nodes/geometry/nodes/legacy/node_geo_attribute_math.cc b/source/blender/nodes/geometry/nodes/legacy/node_geo_attribute_math.cc
index 55d35f87cda..193db7355f9 100644
--- a/source/blender/nodes/geometry/nodes/legacy/node_geo_attribute_math.cc
+++ b/source/blender/nodes/geometry/nodes/legacy/node_geo_attribute_math.cc
@@ -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 geo_node_attribute_math_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);
}
diff --git a/source/blender/nodes/geometry/nodes/legacy/node_geo_attribute_mix.cc b/source/blender/nodes/geometry/nodes/legacy/node_geo_attribute_mix.cc
index b4205bc91b7..6c7f2313633 100644
--- a/source/blender/nodes/geometry/nodes/legacy/node_geo_attribute_mix.cc
+++ b/source/blender/nodes/geometry/nodes/legacy/node_geo_attribute_mix.cc
@@ -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 geo_node_attribute_mix_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,19 +206,19 @@ 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();
}
diff --git a/source/blender/nodes/geometry/nodes/legacy/node_geo_attribute_proximity.cc b/source/blender/nodes/geometry/nodes/legacy/node_geo_attribute_proximity.cc
index 9e3a7984c53..0122f9b7598 100644
--- a/source/blender/nodes/geometry/nodes/legacy/node_geo_attribute_proximity.cc
+++ b/source/blender/nodes/geometry/nodes/legacy/node_geo_attribute_proximity.cc
@@ -153,7 +153,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;
diff --git a/source/blender/nodes/geometry/nodes/legacy/node_geo_attribute_randomize.cc b/source/blender/nodes/geometry/nodes/legacy/node_geo_attribute_randomize.cc
index 2901472d661..f8d9dcdaf87 100644
--- a/source/blender/nodes/geometry/nodes/legacy/node_geo_attribute_randomize.cc
+++ b/source/blender/nodes/geometry/nodes/legacy/node_geo_attribute_randomize.cc
@@ -57,7 +57,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 geo_node_legacy_attribute_randomize_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 +68,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>
@@ -180,13 +180,13 @@ Array<uint32_t> get_geometry_element_ids_as_uints(const GeometryComponent &compo
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);
+ 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(hashes.size() == hash_attribute.size());
+ const CPPType &cpp_type = hash_attribute.type();
BLI_assert(cpp_type.is_hashable());
- GVArray_GSpan items{*hash_attribute};
+ 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]);
diff --git a/source/blender/nodes/geometry/nodes/legacy/node_geo_attribute_sample_texture.cc b/source/blender/nodes/geometry/nodes/legacy/node_geo_attribute_sample_texture.cc
index 19d6ced6eb6..9748ca3f2ad 100644
--- a/source/blender/nodes/geometry/nodes/legacy/node_geo_attribute_sample_texture.cc
+++ b/source/blender/nodes/geometry/nodes/legacy/node_geo_attribute_sample_texture.cc
@@ -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();
diff --git a/source/blender/nodes/geometry/nodes/legacy/node_geo_attribute_separate_xyz.cc b/source/blender/nodes/geometry/nodes/legacy/node_geo_attribute_separate_xyz.cc
index 809e75e73a3..bfc69780bf6 100644
--- a/source/blender/nodes/geometry/nodes/legacy/node_geo_attribute_separate_xyz.cc
+++ b/source/blender/nodes/geometry/nodes/legacy/node_geo_attribute_separate_xyz.cc
@@ -49,11 +49,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 geo_node_attribute_separate_xyz_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 +106,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);
diff --git a/source/blender/nodes/geometry/nodes/legacy/node_geo_attribute_transfer.cc b/source/blender/nodes/geometry/nodes/legacy/node_geo_attribute_transfer.cc
index 3a9cd52661a..b8827f82efc 100644
--- a/source/blender/nodes/geometry/nodes/legacy/node_geo_attribute_transfer.cc
+++ b/source/blender/nodes/geometry/nodes/legacy/node_geo_attribute_transfer.cc
@@ -407,13 +407,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 +424,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 +434,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 +460,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) {
diff --git a/source/blender/nodes/geometry/nodes/legacy/node_geo_attribute_vector_math.cc b/source/blender/nodes/geometry/nodes/legacy/node_geo_attribute_vector_math.cc
index 4c351846243..e7fdd0f2eef 100644
--- a/source/blender/nodes/geometry/nodes/legacy/node_geo_attribute_vector_math.cc
+++ b/source/blender/nodes/geometry/nodes/legacy/node_geo_attribute_vector_math.cc
@@ -166,19 +166,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 geo_node_attribute_vector_math_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 +189,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 +220,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 +253,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 +285,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 +315,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 +344,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 +371,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 +439,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 +478,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,22 +509,22 @@ 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;
}
diff --git a/source/blender/nodes/geometry/nodes/legacy/node_geo_attribute_vector_rotate.cc b/source/blender/nodes/geometry/nodes/legacy/node_geo_attribute_vector_rotate.cc
index 9ab8ec25fb6..a6cd24ed72d 100644
--- a/source/blender/nodes/geometry/nodes/legacy/node_geo_attribute_vector_rotate.cc
+++ b/source/blender/nodes/geometry/nodes/legacy/node_geo_attribute_vector_rotate.cc
@@ -70,27 +70,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 geo_node_attribute_vector_rotate_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,
@@ -220,12 +223,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 +241,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 +263,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);
diff --git a/source/blender/nodes/geometry/nodes/legacy/node_geo_curve_endpoints.cc b/source/blender/nodes/geometry/nodes/legacy/node_geo_curve_endpoints.cc
index 8b81008ff34..67c8200a9c2 100644
--- a/source/blender/nodes/geometry/nodes/legacy/node_geo_curve_endpoints.cc
+++ b/source/blender/nodes/geometry/nodes/legacy/node_geo_curve_endpoints.cc
@@ -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,7 +139,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(spline.size() - 1, point_span[i]);
+ spline_span.type().copy_assign(spline_span[spline.size() - 1], point_span[i]);
}
}
});
diff --git a/source/blender/nodes/geometry/nodes/legacy/node_geo_curve_reverse.cc b/source/blender/nodes/geometry/nodes/legacy/node_geo_curve_reverse.cc
index ba76fafe3e6..bc4612e2b8b 100644
--- a/source/blender/nodes/geometry/nodes/legacy/node_geo_curve_reverse.cc
+++ b/source/blender/nodes/geometry/nodes/legacy/node_geo_curve_reverse.cc
@@ -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) {
diff --git a/source/blender/nodes/geometry/nodes/legacy/node_geo_curve_set_handles.cc b/source/blender/nodes/geometry/nodes/legacy/node_geo_curve_set_handles.cc
index 4bac9cb976e..b92db315d94 100644
--- a/source/blender/nodes/geometry/nodes/legacy/node_geo_curve_set_handles.cc
+++ b/source/blender/nodes/geometry/nodes/legacy/node_geo_curve_set_handles.cc
@@ -84,7 +84,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);
diff --git a/source/blender/nodes/geometry/nodes/legacy/node_geo_curve_spline_type.cc b/source/blender/nodes/geometry/nodes/legacy/node_geo_curve_spline_type.cc
index df53c96e6ca..36d4519cac3 100644
--- a/source/blender/nodes/geometry/nodes/legacy/node_geo_curve_spline_type.cc
+++ b/source/blender/nodes/geometry/nodes/legacy/node_geo_curve_spline_type.cc
@@ -255,7 +255,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>();
diff --git a/source/blender/nodes/geometry/nodes/legacy/node_geo_curve_subdivide.cc b/source/blender/nodes/geometry/nodes/legacy/node_geo_curve_subdivide.cc
index f9b0a9d128e..603547a8e69 100644
--- a/source/blender/nodes/geometry/nodes/legacy/node_geo_curve_subdivide.cc
+++ b/source/blender/nodes/geometry/nodes/legacy/node_geo_curve_subdivide.cc
@@ -25,10 +25,6 @@
#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 {
static void geo_node_curve_subdivide_declare(NodeDeclarationBuilder &b)
@@ -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 geo_node_curve_subdivide_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,
@@ -363,14 +359,13 @@ 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()));
}
diff --git a/source/blender/nodes/geometry/nodes/legacy/node_geo_curve_to_points.cc b/source/blender/nodes/geometry/nodes/legacy/node_geo_curve_to_points.cc
index c171d485a6a..ab51258cc69 100644
--- a/source/blender/nodes/geometry/nodes/legacy/node_geo_curve_to_points.cc
+++ b/source/blender/nodes/geometry/nodes/legacy/node_geo_curve_to_points.cc
@@ -50,7 +50,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 geo_node_curve_to_points_update(bNodeTree *ntree, bNode *node)
{
NodeGeometryCurveToPoints &node_storage = *(NodeGeometryCurveToPoints *)node->storage;
const GeometryNodeCurveResampleMode mode = (GeometryNodeCurveResampleMode)node_storage.mode;
@@ -58,8 +58,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);
}
/**
@@ -121,7 +121,7 @@ static GMutableSpan create_attribute_and_retrieve_span(PointCloudComponent &poin
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>
@@ -177,8 +177,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 +188,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 +230,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 +263,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);
}
}
diff --git a/source/blender/nodes/geometry/nodes/legacy/node_geo_delete_geometry.cc b/source/blender/nodes/geometry/nodes/legacy/node_geo_delete_geometry.cc
index 1d76a0532a1..f62a22d7934 100644
--- a/source/blender/nodes/geometry/nodes/legacy/node_geo_delete_geometry.cc
+++ b/source/blender/nodes/geometry/nodes/legacy/node_geo_delete_geometry.cc
@@ -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. */
diff --git a/source/blender/nodes/geometry/nodes/legacy/node_geo_material_assign.cc b/source/blender/nodes/geometry/nodes/legacy/node_geo_material_assign.cc
index 333a17aa4e9..58374679a95 100644
--- a/source/blender/nodes/geometry/nodes/legacy/node_geo_material_assign.cc
+++ b/source/blender/nodes/geometry/nodes/legacy/node_geo_material_assign.cc
@@ -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);
}
diff --git a/source/blender/nodes/geometry/nodes/legacy/node_geo_mesh_to_curve.cc b/source/blender/nodes/geometry/nodes/legacy/node_geo_mesh_to_curve.cc
index 9167096fd3d..321de24a3dc 100644
--- a/source/blender/nodes/geometry/nodes/legacy/node_geo_mesh_to_curve.cc
+++ b/source/blender/nodes/geometry/nodes/legacy/node_geo_mesh_to_curve.cc
@@ -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;
diff --git a/source/blender/nodes/geometry/nodes/legacy/node_geo_point_distribute.cc b/source/blender/nodes/geometry/nodes/legacy/node_geo_point_distribute.cc
index 210757f986d..4e13a490d89 100644
--- a/source/blender/nodes/geometry/nodes/legacy/node_geo_point_distribute.cc
+++ b/source/blender/nodes/geometry/nodes/legacy/node_geo_point_distribute.cc
@@ -61,11 +61,12 @@ static void geo_node_point_distribute_layout(uiLayout *layout,
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 +107,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 +316,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 +330,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 +338,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 +446,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 +456,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 +515,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()) {
diff --git a/source/blender/nodes/geometry/nodes/legacy/node_geo_point_instance.cc b/source/blender/nodes/geometry/nodes/legacy/node_geo_point_instance.cc
index ffb2a0dd7ac..713971941ea 100644
--- a/source/blender/nodes/geometry/nodes/legacy/node_geo_point_instance.cc
+++ b/source/blender/nodes/geometry/nodes/legacy/node_geo_point_instance.cc
@@ -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 geo_node_point_instance_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();
diff --git a/source/blender/nodes/geometry/nodes/legacy/node_geo_point_rotate.cc b/source/blender/nodes/geometry/nodes/legacy/node_geo_point_rotate.cc
index 54d36dab98d..ab1d68bfe4f 100644
--- a/source/blender/nodes/geometry/nodes/legacy/node_geo_point_rotate.cc
+++ b/source/blender/nodes/geometry/nodes/legacy/node_geo_point_rotate.cc
@@ -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 geo_node_point_rotate_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) {
diff --git a/source/blender/nodes/geometry/nodes/legacy/node_geo_point_scale.cc b/source/blender/nodes/geometry/nodes/legacy/node_geo_point_scale.cc
index 934442ee8a3..8d6345ce6b1 100644
--- a/source/blender/nodes/geometry/nodes/legacy/node_geo_point_scale.cc
+++ b/source/blender/nodes/geometry/nodes/legacy/node_geo_point_scale.cc
@@ -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 geo_node_point_scale_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];
}
diff --git a/source/blender/nodes/geometry/nodes/legacy/node_geo_point_separate.cc b/source/blender/nodes/geometry/nodes/legacy/node_geo_point_separate.cc
index accdaf78439..3539fe2de64 100644
--- a/source/blender/nodes/geometry/nodes/legacy/node_geo_point_separate.cc
+++ b/source/blender/nodes/geometry/nodes/legacy/node_geo_point_separate.cc
@@ -55,7 +55,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 +69,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);
});
@@ -103,7 +103,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};
diff --git a/source/blender/nodes/geometry/nodes/legacy/node_geo_point_translate.cc b/source/blender/nodes/geometry/nodes/legacy/node_geo_point_translate.cc
index 34f7641995f..3b2959beb86 100644
--- a/source/blender/nodes/geometry/nodes/legacy/node_geo_point_translate.cc
+++ b/source/blender/nodes/geometry/nodes/legacy/node_geo_point_translate.cc
@@ -43,10 +43,10 @@ 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]);
}
@@ -81,12 +81,12 @@ 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 geo_node_point_translate_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
diff --git a/source/blender/nodes/geometry/nodes/legacy/node_geo_points_to_volume.cc b/source/blender/nodes/geometry/nodes/legacy/node_geo_points_to_volume.cc
index cf7f466c2a6..d465a9ab1a8 100644
--- a/source/blender/nodes/geometry/nodes/legacy/node_geo_points_to_volume.cc
+++ b/source/blender/nodes/geometry/nodes/legacy/node_geo_points_to_volume.cc
@@ -65,19 +65,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 geo_node_points_to_volume_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 +175,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]);
}
diff --git a/source/blender/nodes/geometry/nodes/legacy/node_geo_raycast.cc b/source/blender/nodes/geometry/nodes/legacy/node_geo_raycast.cc
index e6a81fc9627..5aa683ca232 100644
--- a/source/blender/nodes/geometry/nodes/legacy/node_geo_raycast.cc
+++ b/source/blender/nodes/geometry/nodes/legacy/node_geo_raycast.cc
@@ -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 geo_node_raycast_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>();
diff --git a/source/blender/nodes/geometry/nodes/legacy/node_geo_volume_to_mesh.cc b/source/blender/nodes/geometry/nodes/legacy/node_geo_volume_to_mesh.cc
index 39af5bf1fd2..6a52b943967 100644
--- a/source/blender/nodes/geometry/nodes/legacy/node_geo_volume_to_mesh.cc
+++ b/source/blender/nodes/geometry/nodes/legacy/node_geo_volume_to_mesh.cc
@@ -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 geo_node_volume_to_mesh_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);
}
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..19deb761948 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_attribute_capture.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_attribute_capture.cc
@@ -60,7 +60,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 geo_node_attribute_capture_update(bNodeTree *ntree, bNode *node)
{
const NodeGeometryAttributeCapture &storage = *(const NodeGeometryAttributeCapture *)
node->storage;
@@ -73,11 +73,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 +86,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,
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..d9513332078 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_attribute_statistic.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_attribute_statistic.cc
@@ -65,7 +65,7 @@ static void geo_node_attribute_statistic_init(bNodeTree *UNUSED(tree), bNode *no
node->custom2 = ATTR_DOMAIN_POINT;
}
-static void geo_node_attribute_statistic_update(bNodeTree *UNUSED(ntree), bNode *node)
+static void geo_node_attribute_statistic_update(bNodeTree *ntree, bNode *node)
{
bNodeSocket *socket_geo = (bNodeSocket *)node->inputs.first;
bNodeSocket *socket_float_attr = socket_geo->next;
@@ -91,25 +91,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)
diff --git a/source/blender/nodes/geometry/nodes/node_geo_boolean.cc b/source/blender/nodes/geometry/nodes/node_geo_boolean.cc
index 516f07b7ad3..dba051fe13d 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_boolean.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_boolean.cc
@@ -41,7 +41,7 @@ static void geo_node_boolean_layout(uiLayout *layout, bContext *UNUSED(C), Point
uiItemR(layout, ptr, "operation", 0, "", ICON_NONE);
}
-static void geo_node_boolean_update(bNodeTree *UNUSED(ntree), bNode *node)
+static void geo_node_boolean_update(bNodeTree *ntree, bNode *node)
{
GeometryNodeBooleanOperation operation = (GeometryNodeBooleanOperation)node->custom1;
@@ -51,13 +51,13 @@ 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;
}
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..503711fedfe 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_collection_info.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_collection_info.cc
@@ -38,7 +38,7 @@ 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"));
}
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..221fb421ab4 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_convex_hull.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_convex_hull.cc
@@ -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);
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..c41b76412e9 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
@@ -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
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..a320f35c539 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_curve_fillet.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_curve_fillet.cc
@@ -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 geo_node_curve_fillet_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;
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..5fb17270301 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
@@ -96,9 +96,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 +106,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
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..63518b38090 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_curve_parameter.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_curve_parameter.cc
@@ -24,7 +24,16 @@ namespace blender::nodes {
static void geo_node_curve_parameter_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,10 +222,51 @@ class CurveParameterFieldInput final : public fn::FieldInput {
}
};
+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 geo_node_curve_parameter_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
@@ -199,7 +274,6 @@ static void geo_node_curve_parameter_exec(GeoNodeExecParams params)
void register_node_type_geo_curve_parameter()
{
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;
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..673a5095044 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
@@ -29,15 +29,27 @@ static void geo_node_curve_primitive_bezier_segment_declare(NodeDeclarationBuild
.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"));
}
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..5d8beb9c9d8 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
@@ -25,17 +25,34 @@ namespace blender::nodes {
static void geo_node_curve_primitive_circle_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"));
}
@@ -56,7 +73,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 geo_node_curve_primitive_circle_update(bNodeTree *ntree, bNode *node)
{
const NodeGeometryCurvePrimitiveCircle *node_storage = (NodeGeometryCurvePrimitiveCircle *)
node->storage;
@@ -70,11 +87,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)
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..238fc77e1cc 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
@@ -25,10 +25,21 @@ namespace blender::nodes {
static void geo_node_curve_primitive_line_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"));
}
@@ -48,7 +59,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 geo_node_curve_primitive_line_update(bNodeTree *ntree, bNode *node)
{
const NodeGeometryCurvePrimitiveLine *node_storage = (NodeGeometryCurvePrimitiveLine *)
node->storage;
@@ -59,10 +70,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)
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..27bf4a310df 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
@@ -25,14 +25,20 @@ static void geo_node_curve_primitive_quadratic_bezier_declare(NodeDeclarationBui
.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"));
}
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..114ae441d99 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
@@ -23,31 +23,57 @@ namespace blender::nodes {
static void geo_node_curve_primitive_quadrilateral_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"));
}
@@ -66,7 +92,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 geo_node_curve_primitive_quadrilateral_update(bNodeTree *ntree, bNode *node)
{
NodeGeometryCurvePrimitiveQuad &node_storage = *(NodeGeometryCurvePrimitiveQuad *)node->storage;
GeometryNodeCurvePrimitiveQuadMode mode = static_cast<GeometryNodeCurvePrimitiveQuadMode>(
@@ -85,34 +111,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);
}
}
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..1384165e520 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
@@ -26,12 +26,26 @@ static void geo_node_curve_primitive_spiral_declare(NodeDeclarationBuilder &b)
.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"));
}
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..9004681c246 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
@@ -22,17 +22,29 @@ namespace blender::nodes {
static void geo_node_curve_primitive_star_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,9 +69,22 @@ 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 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 geo_node_curve_primitive_star_exec(GeoNodeExecParams params)
{
std::unique_ptr<CurveEval> curve = create_star_curve(
@@ -67,9 +92,17 @@ static void geo_node_curve_primitive_star_exec(GeoNodeExecParams params)
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());
+ 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
void register_node_type_geo_curve_primitive_star()
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..f72978bae50 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 {
static void geo_node_curve_resample_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)
@@ -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 geo_node_curve_resample_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;
}
@@ -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) {
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..8f42aacab43 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_curve_sample.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_curve_sample.cc
@@ -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 geo_node_curve_sample_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)
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..7c4c17e69e0 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_curve_subdivide.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_curve_subdivide.cc
@@ -25,10 +25,6 @@
#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 {
static void geo_node_curve_subdivide_declare(NodeDeclarationBuilder &b)
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..b9f129a5f75 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
@@ -53,7 +53,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 geo_node_curve_to_points_update(bNodeTree *ntree, bNode *node)
{
NodeGeometryCurveToPoints &node_storage = *(NodeGeometryCurveToPoints *)node->storage;
const GeometryNodeCurveResampleMode mode = (GeometryNodeCurveResampleMode)node_storage.mode;
@@ -61,8 +61,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 +113,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 +194,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 +203,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 +233,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 +244,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));
}
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..b281876d314 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_curve_trim.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_curve_trim.cc
@@ -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 geo_node_curve_trim_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;
}
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 e0a3faaefb0..d07644f8403 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_delete_geometry.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_delete_geometry.cc
@@ -138,7 +138,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 +149,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 +178,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 +189,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);
});
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..b2c76b76590 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
@@ -67,19 +67,21 @@ static void geo_node_point_distribute_points_on_faces_layout(uiLayout *layout,
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,
+ nodeSetSocketAvailability(ntree,
+ sock_distance_min,
node->custom1 == GEO_NODE_POINT_DISTRIBUTE_POINTS_ON_FACES_POISSON);
- nodeSetSocketAvailability(sock_density_max,
- 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 +315,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();
}
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..ca6254be182 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_edge_split.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_edge_split.cc
@@ -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) {
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..6c95ad73bf7 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_input_normal.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_input_normal.cc
@@ -31,19 +31,18 @@ static void geo_node_input_normal_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
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..a976e0b193f 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
@@ -25,31 +25,25 @@ static void geo_node_input_spline_length_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
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..49885f29d44 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_input_tangent.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_input_tangent.cc
@@ -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
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..2a68030aba7 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
@@ -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,
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..fcdf7c2da01 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_join_geometry.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_join_geometry.cc
@@ -27,8 +27,6 @@
#include "node_geometry_util.hh"
-using blender::fn::GVArray_For_GSpan;
-
namespace blender::nodes {
static void geo_node_join_geometry_declare(NodeDeclarationBuilder &b)
@@ -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);
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..12ffa21762e 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_material_selection.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_material_selection.cc
@@ -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;
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..f1f95be107a 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
@@ -29,8 +29,15 @@ namespace blender::nodes {
static void geo_node_mesh_primitive_circle_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"));
}
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..fc93f6e72b5 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,20 +25,45 @@
#include "node_geometry_util.hh"
+#include <cmath>
+
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::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);
- b.add_input<decl::Float>(N_("Depth")).default_value(2.0f).min(0.0f).subtype(PROP_DISTANCE);
+ .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 geo_node_mesh_primitive_cone_init(bNodeTree *UNUSED(ntree), bNode *node)
@@ -51,7 +76,7 @@ static void geo_node_mesh_primitive_cone_init(bNodeTree *UNUSED(ntree), bNode *n
node->storage = node_storage;
}
-static void geo_node_mesh_primitive_cone_update(bNodeTree *UNUSED(ntree), bNode *node)
+static void geo_node_mesh_primitive_cone_update(bNodeTree *ntree, bNode *node)
{
bNodeSocket *vertices_socket = (bNodeSocket *)node->inputs.first;
bNodeSocket *rings_socket = vertices_socket->next;
@@ -61,7 +86,7 @@ static void geo_node_mesh_primitive_cone_update(bNodeTree *UNUSED(ntree), bNode
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_cone_layout(uiLayout *layout,
@@ -94,6 +119,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 +134,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 +168,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 +180,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 +217,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 +311,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 +338,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 +559,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 +756,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 +775,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,6 +787,7 @@ 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);
@@ -708,38 +801,76 @@ static void geo_node_mesh_primitive_cone_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 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));
}
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..b5903f7b71e 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
@@ -29,10 +29,23 @@ 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);
+ .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"));
}
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..a2ac46190b3 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
@@ -33,17 +33,17 @@ static void geo_node_mesh_primitive_cylinder_declare(NodeDeclarationBuilder &b)
.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,8 +53,11 @@ 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,
@@ -76,7 +79,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 geo_node_mesh_primitive_cylinder_update(bNodeTree *ntree, bNode *node)
{
bNodeSocket *vertices_socket = (bNodeSocket *)node->inputs.first;
bNodeSocket *rings_socket = vertices_socket->next;
@@ -86,7 +89,7 @@ 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)
@@ -97,33 +100,71 @@ 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));
}
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..73c679e18f8 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
@@ -29,10 +29,26 @@ 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_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"));
}
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..e4bf5e31dbf 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
@@ -28,8 +28,16 @@ namespace blender::nodes {
static void geo_node_mesh_primitive_ico_sphere_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,
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..1a92be1c05d 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
@@ -29,12 +29,25 @@ namespace blender::nodes {
static void geo_node_mesh_primitive_line_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"));
}
@@ -61,7 +74,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 geo_node_mesh_primitive_line_update(bNodeTree *ntree, bNode *node)
{
bNodeSocket *count_socket = (bNodeSocket *)node->inputs.first;
bNodeSocket *resolution_socket = count_socket->next;
@@ -77,10 +90,12 @@ 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);
}
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..3197a94c27b 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
@@ -29,9 +29,21 @@ namespace blender::nodes {
static void geo_node_mesh_primitive_uv_shpere_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"));
}
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..a37e3e34777 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
@@ -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();
}
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..bb8e5f7e29b 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_object_info.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_object_info.cc
@@ -27,9 +27,8 @@ static void geo_node_object_info_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"));
@@ -48,53 +47,64 @@ static void geo_node_object_info_exec(GeoNodeExecParams params)
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)
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..5a6a3b25a45 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
@@ -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();
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..31c16cb95e0 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
@@ -61,16 +61,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 geo_node_points_to_volume_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 +168,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 +176,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,16 +225,12 @@ 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);
}
diff --git a/source/blender/nodes/geometry/nodes/node_geo_raycast.cc b/source/blender/nodes/geometry/nodes/node_geo_raycast.cc
index 34946b1115c..d422bf5a00a 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_raycast.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_raycast.cc
@@ -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 geo_node_raycast_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)
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..30b445da58c 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
@@ -28,6 +28,7 @@ static void geo_node_set_curve_handles_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"));
}
@@ -50,7 +51,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,11 +113,22 @@ 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();
}
@@ -128,6 +141,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 +151,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) {
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..9e3ff10a3c5 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
@@ -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 geo_node_string_to_curves_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"));
diff --git a/source/blender/nodes/geometry/nodes/node_geo_switch.cc b/source/blender/nodes/geometry/nodes/node_geo_switch.cc
index 7e07a552650..8d6f53ae375 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_switch.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_switch.cc
@@ -95,7 +95,7 @@ static void geo_node_switch_init(bNodeTree *UNUSED(tree), bNode *node)
node->storage = data;
}
-static void geo_node_switch_update(bNodeTree *UNUSED(ntree), bNode *node)
+static void geo_node_switch_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);
}
}
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..3b30806d8ae 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_transfer_attribute.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_transfer_attribute.cc
@@ -86,7 +86,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 geo_node_transfer_attribute_update(bNodeTree *ntree, bNode *node)
{
const NodeGeometryTransferAttribute &data = *(const NodeGeometryTransferAttribute *)
node->storage;
@@ -103,14 +103,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 +118,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 +541,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 +553,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>());
}
});
}
@@ -667,8 +667,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>());
});
}
};
diff --git a/source/blender/nodes/geometry/nodes/node_geo_viewer.cc b/source/blender/nodes/geometry/nodes/node_geo_viewer.cc
index 194d1a751ed..a46d7529124 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_viewer.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_viewer.cc
@@ -63,7 +63,7 @@ static eNodeSocketDatatype custom_data_type_to_socket_type(const CustomDataType
}
}
-static void geo_node_viewer_update(bNodeTree *UNUSED(ntree), bNode *node)
+static void geo_node_viewer_update(bNodeTree *ntree, bNode *node)
{
const NodeGeometryViewer &storage = *(const NodeGeometryViewer *)node->storage;
const CustomDataType data_type = static_cast<CustomDataType>(storage.data_type);
@@ -73,7 +73,7 @@ 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);
}
}
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..99eeae370fe 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
@@ -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 geo_node_volume_to_mesh_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);
}
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..faa4337ba7e 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(
diff --git a/source/blender/nodes/intern/node_socket.cc b/source/blender/nodes/intern/node_socket.cc
index 11356178d87..dce54d58dce 100644
--- a/source/blender/nodes/intern/node_socket.cc
+++ b/source/blender/nodes/intern/node_socket.cc
@@ -269,10 +269,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.
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..b1611679ced 100644
--- a/source/blender/nodes/intern/type_conversions.cc
+++ b/source/blender/nodes/intern/type_conversions.cc
@@ -24,9 +24,6 @@
namespace blender::nodes {
-using fn::GVArrayPtr;
-using fn::GVMutableArray;
-using fn::GVMutableArrayPtr;
using fn::MFDataType;
template<typename From, typename To, To (*ConversionF)(const From &)>
@@ -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_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..fad93962708 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,
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/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_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 112d76a3e65..8d25ece3753 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 */
@@ -472,26 +472,26 @@ bool WM_operator_repeat_check(const struct bContext *C, struct wmOperator *op);
bool WM_operator_is_repeat(const struct bContext *C, const struct wmOperator *op);
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 64aa55c058c..e3300a0f087 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 798f60fba3d..f51c8c48c48 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) {
@@ -1613,7 +1616,7 @@ int WM_operator_name_call(bContext *C, const char *opstring, short context, Poin
int WM_operator_name_call_with_properties(struct bContext *C,
const char *opstring,
- short context,
+ wmOperatorCallContext context,
struct IDProperty *properties)
{
PointerRNA props_ptr;
@@ -1644,7 +1647,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)
@@ -1768,8 +1771,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;
@@ -3063,8 +3069,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..d373ecdac77 100644
--- a/source/blender/windowmanager/intern/wm_files_link.c
+++ b/source/blender/windowmanager/intern/wm_files_link.c
@@ -52,6 +52,8 @@
#include "BLO_readfile.h"
+#include "BLT_translation.h"
+
#include "BKE_armature.h"
#include "BKE_context.h"
#include "BKE_global.h"
@@ -354,7 +356,8 @@ static void wm_append_loose_data_instantiate_ensure_active_collection(
*r_active_collection = lc->collection;
}
else {
- *r_active_collection = BKE_collection_add(bmain, scene->master_collection, NULL);
+ *r_active_collection = BKE_collection_add(
+ bmain, scene->master_collection, DATA_("Appended Data"));
}
}
}
@@ -438,11 +441,13 @@ static void wm_append_loose_data_instantiate(WMLinkAppendData *lapp_data,
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) {
+ 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) {
@@ -812,7 +817,7 @@ static void wm_append_do(WMLinkAppendData *lapp_data,
BLI_assert(!ID_IS_LINKED(id));
- BKE_libblock_relink_to_newid_new(bmain, id);
+ BKE_libblock_relink_to_newid(bmain, id, 0);
}
/* Remove linked IDs when a local existing data has been reused instead. */
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;