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:
-rw-r--r--build_files/cmake/macros.cmake2
-rw-r--r--build_files/cmake/platform/platform_win32_bundle_crt.cmake2
-rw-r--r--build_files/config/pipeline_config.yaml18
-rw-r--r--doc/doxygen/Doxyfile2
-rw-r--r--doc/python_api/examples/bpy.app.timers.5.py2
-rw-r--r--doc/python_api/rst/info_gotcha.rst2
-rw-r--r--doc/python_api/sphinx_doc_gen.py7
-rw-r--r--intern/cycles/CMakeLists.txt3
-rw-r--r--intern/cycles/blender/CMakeLists.txt5
-rw-r--r--intern/cycles/blender/addon/properties.py7
-rw-r--r--intern/cycles/blender/addon/ui.py3
-rw-r--r--intern/cycles/blender/sync.cpp11
-rw-r--r--intern/cycles/device/cpu/device.cpp1
-rw-r--r--intern/cycles/device/cpu/device_impl.cpp5
-rw-r--r--intern/cycles/device/cpu/device_impl.h2
-rw-r--r--intern/cycles/device/cuda/device.cpp1
-rw-r--r--intern/cycles/device/cuda/device_impl.cpp8
-rw-r--r--intern/cycles/device/cuda/device_impl.h2
-rw-r--r--intern/cycles/device/device.cpp2
-rw-r--r--intern/cycles/device/device.h6
-rw-r--r--intern/cycles/device/hip/device.cpp1
-rw-r--r--intern/cycles/device/hip/device_impl.cpp19
-rw-r--r--intern/cycles/device/hip/device_impl.h6
-rw-r--r--intern/cycles/device/hip/graphics_interop.h2
-rw-r--r--intern/cycles/device/multi/device.cpp8
-rw-r--r--intern/cycles/integrator/path_trace.cpp8
-rw-r--r--intern/cycles/integrator/path_trace_work.h5
-rw-r--r--intern/cycles/integrator/path_trace_work_cpu.cpp4
-rw-r--r--intern/cycles/integrator/path_trace_work_cpu.h3
-rw-r--r--intern/cycles/integrator/path_trace_work_gpu.cpp4
-rw-r--r--intern/cycles/integrator/path_trace_work_gpu.h3
-rw-r--r--intern/cycles/integrator/render_scheduler.cpp17
-rw-r--r--intern/cycles/integrator/render_scheduler.h8
-rw-r--r--intern/cycles/integrator/work_tile_scheduler.cpp3
-rw-r--r--intern/cycles/integrator/work_tile_scheduler.h2
-rw-r--r--intern/cycles/kernel/CMakeLists.txt16
-rw-r--r--intern/cycles/kernel/device/cuda/compat.h1
-rw-r--r--intern/cycles/kernel/device/cuda/config.h19
-rw-r--r--intern/cycles/kernel/device/gpu/image.h12
-rw-r--r--intern/cycles/kernel/device/gpu/kernel.h843
-rw-r--r--intern/cycles/kernel/device/gpu/parallel_active_index.h114
-rw-r--r--intern/cycles/kernel/device/gpu/parallel_prefix_sum.h8
-rw-r--r--intern/cycles/kernel/device/gpu/parallel_sorted_index.h14
-rw-r--r--intern/cycles/kernel/device/hip/compat.h1
-rw-r--r--intern/cycles/kernel/device/hip/config.h19
-rw-r--r--intern/cycles/kernel/device/metal/compat.h152
-rw-r--r--intern/cycles/kernel/device/metal/context_begin.h79
-rw-r--r--intern/cycles/kernel/device/metal/context_end.h23
-rw-r--r--intern/cycles/kernel/device/metal/globals.h51
-rw-r--r--intern/cycles/kernel/device/metal/kernel.metal25
-rw-r--r--intern/cycles/kernel/device/optix/compat.h1
-rw-r--r--intern/cycles/kernel/film/accumulate.h6
-rw-r--r--intern/cycles/kernel/integrator/init_from_bake.h3
-rw-r--r--intern/cycles/kernel/integrator/init_from_camera.h3
-rw-r--r--intern/cycles/kernel/integrator/shade_shadow.h4
-rw-r--r--intern/cycles/kernel/integrator/shade_volume.h14
-rw-r--r--intern/cycles/kernel/integrator/volume_stack.h28
-rw-r--r--intern/cycles/kernel/types.h8
-rw-r--r--intern/cycles/scene/image.cpp3
-rw-r--r--intern/cycles/scene/image.h1
-rw-r--r--intern/cycles/scene/image_oiio.cpp5
-rw-r--r--intern/cycles/session/session.cpp3
-rw-r--r--intern/cycles/session/session.h2
-rw-r--r--intern/ghost/GHOST_C-api.h7
-rw-r--r--intern/ghost/GHOST_Types.h4
-rw-r--r--intern/ghost/intern/GHOST_SystemCocoa.mm6
-rw-r--r--intern/ghost/intern/GHOST_XrAction.cpp5
-rw-r--r--intern/ghost/intern/GHOST_XrControllerModel.cpp14
-rw-r--r--intern/guardedalloc/MEM_guardedalloc.h3
-rw-r--r--intern/locale/boost_locale_wrapper.cpp21
-rw-r--r--release/datafiles/colormanagement/config.ocio2
-rw-r--r--release/datafiles/splash.pngbin609962 -> 737984 bytes
-rw-r--r--release/datafiles/userdef/userdef_default_theme.c2
-rw-r--r--release/freedesktop/snap/README.md2
-rwxr-xr-xrelease/lts/create_release_notes.py2
-rw-r--r--release/scripts/modules/bl_i18n_utils/bl_extract_messages.py2
-rw-r--r--release/scripts/modules/bl_i18n_utils/utils.py2
-rw-r--r--release/scripts/modules/bpy/utils/__init__.py4
-rw-r--r--release/scripts/modules/bpy_types.py2
-rw-r--r--release/scripts/presets/keyconfig/Blender.py2
-rw-r--r--release/scripts/presets/keyconfig/keymap_data/blender_default.py9
-rw-r--r--release/scripts/startup/bl_operators/userpref.py8
-rw-r--r--release/scripts/startup/bl_operators/wm.py4
-rw-r--r--release/scripts/startup/bl_ui/properties_data_gpencil.py3
-rw-r--r--release/scripts/startup/bl_ui/properties_physics_rigidbody.py2
-rw-r--r--release/scripts/startup/bl_ui/space_clip.py38
-rw-r--r--release/scripts/startup/bl_ui/space_dopesheet.py13
-rw-r--r--release/scripts/startup/bl_ui/space_graph.py13
-rw-r--r--release/scripts/startup/bl_ui/space_image.py26
-rw-r--r--release/scripts/startup/bl_ui/space_nla.py13
-rw-r--r--release/scripts/startup/bl_ui/space_node.py12
-rw-r--r--release/scripts/startup/bl_ui/space_outliner.py12
-rw-r--r--release/scripts/startup/bl_ui/space_sequencer.py27
-rw-r--r--release/scripts/startup/bl_ui/space_toolsystem_common.py4
-rw-r--r--release/scripts/startup/bl_ui/space_userpref.py11
-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
-rw-r--r--source/creator/creator.c4
-rw-r--r--source/creator/creator_args.c2
-rw-r--r--tests/gtests/runner/CMakeLists.txt2
-rwxr-xr-xtests/performance/benchmark16
-rw-r--r--tests/python/bl_blendfile_liblink.py100
531 files changed, 10417 insertions, 6509 deletions
diff --git a/build_files/cmake/macros.cmake b/build_files/cmake/macros.cmake
index 1471aa21505..34c2c9a684d 100644
--- a/build_files/cmake/macros.cmake
+++ b/build_files/cmake/macros.cmake
@@ -529,7 +529,7 @@ function(SETUP_LIBDIRS)
# NOTE: For all new libraries, use absolute library paths.
# This should eventually be phased out.
- # APPLE plaform uses full paths for linking libraries, and avoids link_directories.
+ # APPLE platform uses full paths for linking libraries, and avoids link_directories.
if(NOT MSVC AND NOT APPLE)
link_directories(${JPEG_LIBPATH} ${PNG_LIBPATH} ${ZLIB_LIBPATH} ${FREETYPE_LIBPATH})
diff --git a/build_files/cmake/platform/platform_win32_bundle_crt.cmake b/build_files/cmake/platform/platform_win32_bundle_crt.cmake
index 7b2e1edb1b3..699c89e29de 100644
--- a/build_files/cmake/platform/platform_win32_bundle_crt.cmake
+++ b/build_files/cmake/platform/platform_win32_bundle_crt.cmake
@@ -27,7 +27,7 @@ if(WITH_WINDOWS_BUNDLE_CRT)
# Install the CRT to the blender.crt Sub folder.
install(FILES ${CMAKE_INSTALL_SYSTEM_RUNTIME_LIBS} DESTINATION ./blender.crt COMPONENT Libraries)
- # Generating the manifest is a relativly expensive operation since
+ # Generating the manifest is a relatively expensive operation since
# it is collecting an sha1 hash for every file required. so only do
# this work when the libs have either changed or the manifest does
# not exist yet.
diff --git a/build_files/config/pipeline_config.yaml b/build_files/config/pipeline_config.yaml
index a56d7c4a85c..8222f2ff0b9 100644
--- a/build_files/config/pipeline_config.yaml
+++ b/build_files/config/pipeline_config.yaml
@@ -5,38 +5,38 @@
update-code:
git:
submodules:
- - branch: blender-v3.0-release
+ - branch: master
commit_id: HEAD
path: release/scripts/addons
- - branch: blender-v3.0-release
+ - branch: master
commit_id: HEAD
path: release/scripts/addons_contrib
- - branch: blender-v3.0-release
+ - branch: master
commit_id: HEAD
path: release/datafiles/locale
- - branch: blender-v3.0-release
+ - branch: master
commit_id: HEAD
path: source/tools
svn:
libraries:
darwin-arm64:
- branch: tags/blender-3.0-release
+ branch: trunk
commit_id: HEAD
path: lib/darwin_arm64
darwin-x86_64:
- branch: tags/blender-3.0-release
+ branch: trunk
commit_id: HEAD
path: lib/darwin
linux-x86_64:
- branch: tags/blender-3.0-release
+ branch: trunk
commit_id: HEAD
path: lib/linux_centos7_x86_64
windows-amd64:
- branch: tags/blender-3.0-release
+ branch: trunk
commit_id: HEAD
path: lib/win64_vc15
tests:
- branch: tags/blender-3.0-release
+ branch: trunk
commit_id: HEAD
path: lib/tests
benchmarks:
diff --git a/doc/doxygen/Doxyfile b/doc/doxygen/Doxyfile
index 96eb30a852e..89954d8a155 100644
--- a/doc/doxygen/Doxyfile
+++ b/doc/doxygen/Doxyfile
@@ -38,7 +38,7 @@ PROJECT_NAME = Blender
# could be handy for archiving the generated documentation or if some version
# control system is used.
-PROJECT_NUMBER = V3.0
+PROJECT_NUMBER = V3.1
# Using the PROJECT_BRIEF tag one can provide an optional one line description
# for a project that appears at the top of each page and should give viewer a
diff --git a/doc/python_api/examples/bpy.app.timers.5.py b/doc/python_api/examples/bpy.app.timers.5.py
index dda5ea12e73..ddda0576f05 100644
--- a/doc/python_api/examples/bpy.app.timers.5.py
+++ b/doc/python_api/examples/bpy.app.timers.5.py
@@ -11,7 +11,7 @@ import queue
execution_queue = queue.Queue()
-# This function can savely be called in another thread.
+# This function can safely be called in another thread.
# The function will be executed when the timer runs the next time.
def run_in_main_thread(function):
execution_queue.put(function)
diff --git a/doc/python_api/rst/info_gotcha.rst b/doc/python_api/rst/info_gotcha.rst
index df6e7297e26..7361f3e9ade 100644
--- a/doc/python_api/rst/info_gotcha.rst
+++ b/doc/python_api/rst/info_gotcha.rst
@@ -728,7 +728,7 @@ Abusing RNA property callbacks
------------------------------
Python-defined RNA properties can have custom callbacks. Trying to perform complex operations
-from there, like calling an operator, may work, but is not officialy recommended nor supported.
+from there, like calling an operator, may work, but is not officially recommended nor supported.
Main reason is that those callback should be very fast, but additionally, it may for example
create issues with undo/redo system (most operators store an history step, and editing an RNA
diff --git a/doc/python_api/sphinx_doc_gen.py b/doc/python_api/sphinx_doc_gen.py
index f8638b97270..7e2be8ddf75 100644
--- a/doc/python_api/sphinx_doc_gen.py
+++ b/doc/python_api/sphinx_doc_gen.py
@@ -1224,7 +1224,10 @@ def pycontext2sphinx(basepath):
while char_array[i] is not None:
member = ctypes.string_at(char_array[i]).decode(encoding="ascii")
fw(".. data:: %s\n\n" % member)
- member_type, is_seq = context_type_map[member]
+ try:
+ member_type, is_seq = context_type_map[member]
+ except KeyError:
+ raise SystemExit("Error: context key %r not found in context_type_map; update %s" % (member, __file__)) from None
fw(" :type: %s :class:`bpy.types.%s`\n\n" % ("sequence of " if is_seq else "", member_type))
unique.add(member)
i += 1
@@ -2251,7 +2254,7 @@ def main():
# First monkey patch to load in fake members.
setup_monkey_patch()
- # Perform changes to Blender it's self.
+ # Perform changes to Blender itself.
setup_data = setup_blender()
# eventually, create the dirs
diff --git a/intern/cycles/CMakeLists.txt b/intern/cycles/CMakeLists.txt
index 1500743763b..64fe70c886d 100644
--- a/intern/cycles/CMakeLists.txt
+++ b/intern/cycles/CMakeLists.txt
@@ -341,6 +341,9 @@ if(CMAKE_COMPILER_IS_GNUCXX)
unset(_has_cxxflag_float_conversion)
unset(_has_cxxflag_double_promotion)
unset(_has_no_error_unused_macros)
+elseif(CMAKE_C_COMPILER_ID MATCHES "Clang")
+ ADD_CHECK_CXX_COMPILER_FLAG(CMAKE_CXX_FLAGS _has_cxxflag_implicit_float_conversion "-Werror=implicit-float-conversion")
+ unset(_has_cxxflag_implicit_float_conversion)
endif()
if(WITH_CYCLES_CUDA_BINARIES AND (NOT WITH_CYCLES_CUBIN_COMPILER))
diff --git a/intern/cycles/blender/CMakeLists.txt b/intern/cycles/blender/CMakeLists.txt
index 149967ad331..f0540486656 100644
--- a/intern/cycles/blender/CMakeLists.txt
+++ b/intern/cycles/blender/CMakeLists.txt
@@ -138,11 +138,6 @@ endif()
blender_add_lib(bf_intern_cycles "${SRC}" "${INC}" "${INC_SYS}" "${LIB}")
-# avoid link failure with clang 3.4 debug
-if(CMAKE_C_COMPILER_ID MATCHES "Clang" AND NOT ${CMAKE_C_COMPILER_VERSION} VERSION_LESS '3.4')
- string(APPEND CMAKE_CXX_FLAGS_DEBUG " -gline-tables-only")
-endif()
-
add_dependencies(bf_intern_cycles bf_rna)
delayed_install(${CMAKE_CURRENT_SOURCE_DIR} "${ADDON_FILES}" ${CYCLES_INSTALL_PATH})
diff --git a/intern/cycles/blender/addon/properties.py b/intern/cycles/blender/addon/properties.py
index 64613216be0..986d5d972c1 100644
--- a/intern/cycles/blender/addon/properties.py
+++ b/intern/cycles/blender/addon/properties.py
@@ -325,6 +325,13 @@ class CyclesRenderSettings(bpy.types.PropertyGroup):
default=1024,
)
+ sample_offset: IntProperty(
+ name="Sample Offset",
+ description="Number of samples to skip when starting render",
+ min=0, max=(1 << 24),
+ default=0,
+ )
+
time_limit: FloatProperty(
name="Time Limit",
description="Limit the render time (excluding synchronization time)."
diff --git a/intern/cycles/blender/addon/ui.py b/intern/cycles/blender/addon/ui.py
index 428b9b25469..635d92c2629 100644
--- a/intern/cycles/blender/addon/ui.py
+++ b/intern/cycles/blender/addon/ui.py
@@ -290,6 +290,9 @@ class CYCLES_RENDER_PT_sampling_advanced(CyclesButtonsPanel, Panel):
col.active = not (cscene.use_adaptive_sampling and cscene.use_preview_adaptive_sampling)
col.prop(cscene, "sampling_pattern", text="Pattern")
+ col = layout.column(align=True)
+ col.prop(cscene, "sample_offset")
+
layout.separator()
col = layout.column(align=True)
diff --git a/intern/cycles/blender/sync.cpp b/intern/cycles/blender/sync.cpp
index 92662e37bc2..59d684dcf05 100644
--- a/intern/cycles/blender/sync.cpp
+++ b/intern/cycles/blender/sync.cpp
@@ -835,18 +835,25 @@ SessionParams BlenderSync::get_session_params(BL::RenderEngine &b_engine,
/* samples */
int samples = get_int(cscene, "samples");
int preview_samples = get_int(cscene, "preview_samples");
+ int sample_offset = get_int(cscene, "sample_offset");
if (background) {
params.samples = samples;
+ params.sample_offset = sample_offset;
}
else {
params.samples = preview_samples;
- if (params.samples == 0)
+ if (params.samples == 0) {
params.samples = INT_MAX;
+ }
+ params.sample_offset = 0;
}
+ /* Clamp sample offset. */
+ params.sample_offset = clamp(params.sample_offset, 0, Integrator::MAX_SAMPLES);
+
/* Clamp samples. */
- params.samples = min(params.samples, Integrator::MAX_SAMPLES);
+ params.samples = clamp(params.samples, 0, Integrator::MAX_SAMPLES - params.sample_offset);
/* Viewport Performance */
params.pixel_size = b_engine.get_preview_pixel_size(b_scene);
diff --git a/intern/cycles/device/cpu/device.cpp b/intern/cycles/device/cpu/device.cpp
index f11b49ef65f..5aabed8702a 100644
--- a/intern/cycles/device/cpu/device.cpp
+++ b/intern/cycles/device/cpu/device.cpp
@@ -38,7 +38,6 @@ void device_cpu_info(vector<DeviceInfo> &devices)
info.id = "CPU";
info.num = 0;
info.has_osl = true;
- info.has_half_images = true;
info.has_nanovdb = true;
info.has_profiling = true;
if (openimagedenoise_supported()) {
diff --git a/intern/cycles/device/cpu/device_impl.cpp b/intern/cycles/device/cpu/device_impl.cpp
index 68dec7f0af2..2ad76de70ca 100644
--- a/intern/cycles/device/cpu/device_impl.cpp
+++ b/intern/cycles/device/cpu/device_impl.cpp
@@ -93,11 +93,6 @@ CPUDevice::~CPUDevice()
texture_info.free();
}
-bool CPUDevice::show_samples() const
-{
- return (info.cpu_threads == 1);
-}
-
BVHLayoutMask CPUDevice::get_bvh_layout_mask() const
{
BVHLayoutMask bvh_layout_mask = BVH_LAYOUT_BVH2;
diff --git a/intern/cycles/device/cpu/device_impl.h b/intern/cycles/device/cpu/device_impl.h
index 90d217bb624..6f9452a6378 100644
--- a/intern/cycles/device/cpu/device_impl.h
+++ b/intern/cycles/device/cpu/device_impl.h
@@ -60,8 +60,6 @@ class CPUDevice : public Device {
CPUDevice(const DeviceInfo &info_, Stats &stats_, Profiler &profiler_);
~CPUDevice();
- virtual bool show_samples() const override;
-
virtual BVHLayoutMask get_bvh_layout_mask() const override;
/* Returns true if the texture info was copied to the device (meaning, some more
diff --git a/intern/cycles/device/cuda/device.cpp b/intern/cycles/device/cuda/device.cpp
index af2bdc6e29c..0d9e6c72466 100644
--- a/intern/cycles/device/cuda/device.cpp
+++ b/intern/cycles/device/cuda/device.cpp
@@ -144,7 +144,6 @@ void device_cuda_info(vector<DeviceInfo> &devices)
info.description = string(name);
info.num = num;
- info.has_half_images = (major >= 3);
info.has_nanovdb = true;
info.denoisers = 0;
diff --git a/intern/cycles/device/cuda/device_impl.cpp b/intern/cycles/device/cuda/device_impl.cpp
index 2bb0592bcc5..5ab73a6b9ef 100644
--- a/intern/cycles/device/cuda/device_impl.cpp
+++ b/intern/cycles/device/cuda/device_impl.cpp
@@ -46,12 +46,6 @@ bool CUDADevice::have_precompiled_kernels()
return path_exists(cubins_path);
}
-bool CUDADevice::show_samples() const
-{
- /* The CUDADevice only processes one tile at a time, so showing samples is fine. */
- return true;
-}
-
BVHLayoutMask CUDADevice::get_bvh_layout_mask() const
{
return BVH_LAYOUT_BVH2;
@@ -931,7 +925,6 @@ void CUDADevice::tex_alloc(device_texture &mem)
{
CUDAContextScope scope(this);
- /* General variables for both architectures */
string bind_name = mem.name;
size_t dsize = datatype_size(mem.data_type);
size_t size = mem.memory_size();
@@ -1094,7 +1087,6 @@ void CUDADevice::tex_alloc(device_texture &mem)
if (mem.info.data_type != IMAGE_DATA_TYPE_NANOVDB_FLOAT &&
mem.info.data_type != IMAGE_DATA_TYPE_NANOVDB_FLOAT3) {
- /* Kepler+, bindless textures. */
CUDA_RESOURCE_DESC resDesc;
memset(&resDesc, 0, sizeof(resDesc));
diff --git a/intern/cycles/device/cuda/device_impl.h b/intern/cycles/device/cuda/device_impl.h
index 72d4108d1bf..4c357d0b5ab 100644
--- a/intern/cycles/device/cuda/device_impl.h
+++ b/intern/cycles/device/cuda/device_impl.h
@@ -76,8 +76,6 @@ class CUDADevice : public Device {
static bool have_precompiled_kernels();
- virtual bool show_samples() const override;
-
virtual BVHLayoutMask get_bvh_layout_mask() const override;
void set_error(const string &error) override;
diff --git a/intern/cycles/device/device.cpp b/intern/cycles/device/device.cpp
index 63d0a49d3eb..bfbcdb20d5e 100644
--- a/intern/cycles/device/device.cpp
+++ b/intern/cycles/device/device.cpp
@@ -286,7 +286,6 @@ DeviceInfo Device::get_multi_device(const vector<DeviceInfo> &subdevices,
info.description = "Multi Device";
info.num = 0;
- info.has_half_images = true;
info.has_nanovdb = true;
info.has_osl = true;
info.has_profiling = true;
@@ -333,7 +332,6 @@ DeviceInfo Device::get_multi_device(const vector<DeviceInfo> &subdevices,
}
/* Accumulate device info. */
- info.has_half_images &= device.has_half_images;
info.has_nanovdb &= device.has_nanovdb;
info.has_osl &= device.has_osl;
info.has_profiling &= device.has_profiling;
diff --git a/intern/cycles/device/device.h b/intern/cycles/device/device.h
index 65188459c2c..346632de314 100644
--- a/intern/cycles/device/device.h
+++ b/intern/cycles/device/device.h
@@ -73,7 +73,6 @@ class DeviceInfo {
int num;
bool display_device; /* GPU is used as a display device. */
bool has_nanovdb; /* Support NanoVDB volumes. */
- bool has_half_images; /* Support half-float textures. */
bool has_osl; /* Support Open Shading Language. */
bool has_profiling; /* Supports runtime collection of profiling info. */
bool has_peer_memory; /* GPU has P2P access to memory of another GPU. */
@@ -90,7 +89,6 @@ class DeviceInfo {
num = 0;
cpu_threads = 0;
display_device = false;
- has_half_images = false;
has_nanovdb = false;
has_osl = false;
has_profiling = false;
@@ -151,10 +149,6 @@ class Device {
fprintf(stderr, "%s\n", error.c_str());
fflush(stderr);
}
- virtual bool show_samples() const
- {
- return false;
- }
virtual BVHLayoutMask get_bvh_layout_mask() const = 0;
/* statistics */
diff --git a/intern/cycles/device/hip/device.cpp b/intern/cycles/device/hip/device.cpp
index 29304e50247..25e932ef080 100644
--- a/intern/cycles/device/hip/device.cpp
+++ b/intern/cycles/device/hip/device.cpp
@@ -141,7 +141,6 @@ void device_hip_info(vector<DeviceInfo> &devices)
info.description = string(name);
info.num = num;
- info.has_half_images = true;
info.has_nanovdb = true;
info.denoisers = 0;
diff --git a/intern/cycles/device/hip/device_impl.cpp b/intern/cycles/device/hip/device_impl.cpp
index d7f68934b46..950fcaf1816 100644
--- a/intern/cycles/device/hip/device_impl.cpp
+++ b/intern/cycles/device/hip/device_impl.cpp
@@ -47,12 +47,6 @@ bool HIPDevice::have_precompiled_kernels()
return path_exists(fatbins_path);
}
-bool HIPDevice::show_samples() const
-{
- /* The HIPDevice only processes one tile at a time, so showing samples is fine. */
- return true;
-}
-
BVHLayoutMask HIPDevice::get_bvh_layout_mask() const
{
return BVH_LAYOUT_BVH2;
@@ -233,9 +227,7 @@ string HIPDevice::compile_kernel_get_common_cflags(const uint kernel_features)
return cflags;
}
-string HIPDevice::compile_kernel(const uint kernel_features,
- const char *name,
- const char *base)
+string HIPDevice::compile_kernel(const uint kernel_features, const char *name, const char *base)
{
/* Compute kernel name. */
int major, minor;
@@ -245,7 +237,7 @@ string HIPDevice::compile_kernel(const uint kernel_features,
hipGetDeviceProperties(&props, hipDevId);
/* gcnArchName can contain tokens after the arch name with features, ie.
- "gfx1010:sramecc-:xnack-" so we tokenize it to get the first part. */
+ * `gfx1010:sramecc-:xnack-` so we tokenize it to get the first part. */
char *arch = strtok(props.gcnArchName, ":");
if (arch == NULL) {
arch = props.gcnArchName;
@@ -376,10 +368,9 @@ string HIPDevice::compile_kernel(const uint kernel_features,
bool HIPDevice::load_kernels(const uint kernel_features)
{
- /* TODO(sergey): Support kernels re-load for CUDA devices adaptive compile.
+ /* TODO(sergey): Support kernels re-load for HIP devices adaptive compile.
*
- * Currently re-loading kernel will invalidate memory pointers,
- * causing problems in cuCtxSynchronize.
+ * Currently re-loading kernels will invalidate memory pointers.
*/
if (hipModule) {
if (use_adaptive_compilation()) {
@@ -900,7 +891,6 @@ void HIPDevice::tex_alloc(device_texture &mem)
{
HIPContextScope scope(this);
- /* General variables for both architectures */
string bind_name = mem.name;
size_t dsize = datatype_size(mem.data_type);
size_t size = mem.memory_size();
@@ -1065,7 +1055,6 @@ void HIPDevice::tex_alloc(device_texture &mem)
if (mem.info.data_type != IMAGE_DATA_TYPE_NANOVDB_FLOAT &&
mem.info.data_type != IMAGE_DATA_TYPE_NANOVDB_FLOAT3) {
- /* Kepler+, bindless textures. */
hipResourceDesc resDesc;
memset(&resDesc, 0, sizeof(resDesc));
diff --git a/intern/cycles/device/hip/device_impl.h b/intern/cycles/device/hip/device_impl.h
index eb832ad828c..08a7be57e9c 100644
--- a/intern/cycles/device/hip/device_impl.h
+++ b/intern/cycles/device/hip/device_impl.h
@@ -75,8 +75,6 @@ class HIPDevice : public Device {
static bool have_precompiled_kernels();
- virtual bool show_samples() const override;
-
virtual BVHLayoutMask get_bvh_layout_mask() const override;
void set_error(const string &error) override;
@@ -93,9 +91,7 @@ class HIPDevice : public Device {
virtual string compile_kernel_get_common_cflags(const uint kernel_features);
- string compile_kernel(const uint kernel_features,
- const char *name,
- const char *base = "hip");
+ string compile_kernel(const uint kernel_features, const char *name, const char *base = "hip");
virtual bool load_kernels(const uint kernel_features) override;
void reserve_local_memory(const uint kernel_features);
diff --git a/intern/cycles/device/hip/graphics_interop.h b/intern/cycles/device/hip/graphics_interop.h
index 8314405e670..71c6893edbd 100644
--- a/intern/cycles/device/hip/graphics_interop.h
+++ b/intern/cycles/device/hip/graphics_interop.h
@@ -48,7 +48,7 @@ class HIPDeviceGraphicsInterop : public DeviceGraphicsInterop {
HIPDeviceQueue *queue_ = nullptr;
HIPDevice *device_ = nullptr;
- /* OpenGL PBO which is currently registered as the destination for the CUDA buffer. */
+ /* OpenGL PBO which is currently registered as the destination for the HIP buffer. */
uint opengl_pbo_id_ = 0;
/* Buffer area in pixels of the corresponding PBO. */
int64_t buffer_area_ = 0;
diff --git a/intern/cycles/device/multi/device.cpp b/intern/cycles/device/multi/device.cpp
index 56efec3e131..e319246d4f4 100644
--- a/intern/cycles/device/multi/device.cpp
+++ b/intern/cycles/device/multi/device.cpp
@@ -109,14 +109,6 @@ class MultiDevice : public Device {
return error_msg;
}
- virtual bool show_samples() const override
- {
- if (devices.size() > 1) {
- return false;
- }
- return devices.front().device->show_samples();
- }
-
virtual BVHLayoutMask get_bvh_layout_mask() const override
{
BVHLayoutMask bvh_layout_mask = BVH_LAYOUT_ALL;
diff --git a/intern/cycles/integrator/path_trace.cpp b/intern/cycles/integrator/path_trace.cpp
index 92bf8e69d19..ec90681b78a 100644
--- a/intern/cycles/integrator/path_trace.cpp
+++ b/intern/cycles/integrator/path_trace.cpp
@@ -380,7 +380,10 @@ void PathTrace::path_trace(RenderWork &render_work)
PathTraceWork *path_trace_work = path_trace_works_[i].get();
PathTraceWork::RenderStatistics statistics;
- path_trace_work->render_samples(statistics, render_work.path_trace.start_sample, num_samples);
+ path_trace_work->render_samples(statistics,
+ render_work.path_trace.start_sample,
+ num_samples,
+ render_work.path_trace.sample_offset);
const double work_time = time_dt() - work_start_time;
work_balance_infos_[i].time_spent += work_time;
@@ -850,7 +853,8 @@ void PathTrace::progress_update_if_needed(const RenderWork &render_work)
const uint64_t num_samples_added = uint64_t(tile_size.x) * tile_size.y *
render_work.path_trace.num_samples;
const int current_sample = render_work.path_trace.start_sample +
- render_work.path_trace.num_samples;
+ render_work.path_trace.num_samples -
+ render_work.path_trace.sample_offset;
progress_->add_samples(num_samples_added, current_sample);
}
diff --git a/intern/cycles/integrator/path_trace_work.h b/intern/cycles/integrator/path_trace_work.h
index 0dc7cd2f896..2ebfc913580 100644
--- a/intern/cycles/integrator/path_trace_work.h
+++ b/intern/cycles/integrator/path_trace_work.h
@@ -75,7 +75,10 @@ class PathTraceWork {
/* Render given number of samples as a synchronous blocking call.
* The samples are added to the render buffer associated with this work. */
- virtual void render_samples(RenderStatistics &statistics, int start_sample, int samples_num) = 0;
+ virtual void render_samples(RenderStatistics &statistics,
+ int start_sample,
+ int samples_num,
+ int sample_offset) = 0;
/* Copy render result from this work to the corresponding place of the GPU display.
*
diff --git a/intern/cycles/integrator/path_trace_work_cpu.cpp b/intern/cycles/integrator/path_trace_work_cpu.cpp
index 12dcc899dbb..2f6c3cf5aca 100644
--- a/intern/cycles/integrator/path_trace_work_cpu.cpp
+++ b/intern/cycles/integrator/path_trace_work_cpu.cpp
@@ -71,7 +71,8 @@ void PathTraceWorkCPU::init_execution()
void PathTraceWorkCPU::render_samples(RenderStatistics &statistics,
int start_sample,
- int samples_num)
+ int samples_num,
+ int sample_offset)
{
const int64_t image_width = effective_buffer_params_.width;
const int64_t image_height = effective_buffer_params_.height;
@@ -99,6 +100,7 @@ void PathTraceWorkCPU::render_samples(RenderStatistics &statistics,
work_tile.w = 1;
work_tile.h = 1;
work_tile.start_sample = start_sample;
+ work_tile.sample_offset = sample_offset;
work_tile.num_samples = 1;
work_tile.offset = effective_buffer_params_.offset;
work_tile.stride = effective_buffer_params_.stride;
diff --git a/intern/cycles/integrator/path_trace_work_cpu.h b/intern/cycles/integrator/path_trace_work_cpu.h
index 6e734690811..63ab686588c 100644
--- a/intern/cycles/integrator/path_trace_work_cpu.h
+++ b/intern/cycles/integrator/path_trace_work_cpu.h
@@ -48,7 +48,8 @@ class PathTraceWorkCPU : public PathTraceWork {
virtual void render_samples(RenderStatistics &statistics,
int start_sample,
- int samples_num) override;
+ int samples_num,
+ int sample_offset) override;
virtual void copy_to_display(PathTraceDisplay *display,
PassMode pass_mode,
diff --git a/intern/cycles/integrator/path_trace_work_gpu.cpp b/intern/cycles/integrator/path_trace_work_gpu.cpp
index b9784f68f56..956aa6a8c90 100644
--- a/intern/cycles/integrator/path_trace_work_gpu.cpp
+++ b/intern/cycles/integrator/path_trace_work_gpu.cpp
@@ -250,7 +250,8 @@ void PathTraceWorkGPU::init_execution()
void PathTraceWorkGPU::render_samples(RenderStatistics &statistics,
int start_sample,
- int samples_num)
+ int samples_num,
+ int sample_offset)
{
/* Limit number of states for the tile and rely on a greedy scheduling of tiles. This allows to
* add more work (because tiles are smaller, so there is higher chance that more paths will
@@ -261,6 +262,7 @@ void PathTraceWorkGPU::render_samples(RenderStatistics &statistics,
work_tile_scheduler_.reset(effective_buffer_params_,
start_sample,
samples_num,
+ sample_offset,
device_scene_->data.integrator.scrambling_distance);
enqueue_reset();
diff --git a/intern/cycles/integrator/path_trace_work_gpu.h b/intern/cycles/integrator/path_trace_work_gpu.h
index c5e291e72db..5aa497c26e7 100644
--- a/intern/cycles/integrator/path_trace_work_gpu.h
+++ b/intern/cycles/integrator/path_trace_work_gpu.h
@@ -46,7 +46,8 @@ class PathTraceWorkGPU : public PathTraceWork {
virtual void render_samples(RenderStatistics &statistics,
int start_sample,
- int samples_num) override;
+ int samples_num,
+ int sample_offset) override;
virtual void copy_to_display(PathTraceDisplay *display,
PassMode pass_mode,
diff --git a/intern/cycles/integrator/render_scheduler.cpp b/intern/cycles/integrator/render_scheduler.cpp
index f776d01ef67..538d751e8b1 100644
--- a/intern/cycles/integrator/render_scheduler.cpp
+++ b/intern/cycles/integrator/render_scheduler.cpp
@@ -88,6 +88,16 @@ int RenderScheduler::get_num_samples() const
return num_samples_;
}
+void RenderScheduler::set_sample_offset(int sample_offset)
+{
+ sample_offset_ = sample_offset;
+}
+
+int RenderScheduler::get_sample_offset() const
+{
+ return sample_offset_;
+}
+
void RenderScheduler::set_time_limit(double time_limit)
{
time_limit_ = time_limit;
@@ -110,13 +120,15 @@ int RenderScheduler::get_num_rendered_samples() const
return state_.num_rendered_samples;
}
-void RenderScheduler::reset(const BufferParams &buffer_params, int num_samples)
+void RenderScheduler::reset(const BufferParams &buffer_params, int num_samples, int sample_offset)
{
buffer_params_ = buffer_params;
update_start_resolution_divider();
set_num_samples(num_samples);
+ set_start_sample(sample_offset);
+ set_sample_offset(sample_offset);
/* In background mode never do lower resolution render preview, as it is not really supported
* by the software. */
@@ -171,7 +183,7 @@ void RenderScheduler::reset(const BufferParams &buffer_params, int num_samples)
void RenderScheduler::reset_for_next_tile()
{
- reset(buffer_params_, num_samples_);
+ reset(buffer_params_, num_samples_, sample_offset_);
}
bool RenderScheduler::render_work_reschedule_on_converge(RenderWork &render_work)
@@ -317,6 +329,7 @@ RenderWork RenderScheduler::get_render_work()
render_work.path_trace.start_sample = get_start_sample_to_path_trace();
render_work.path_trace.num_samples = get_num_samples_to_path_trace();
+ render_work.path_trace.sample_offset = get_sample_offset();
render_work.init_render_buffers = (render_work.path_trace.start_sample == get_start_sample());
diff --git a/intern/cycles/integrator/render_scheduler.h b/intern/cycles/integrator/render_scheduler.h
index d7b7413ae31..28f563c46e3 100644
--- a/intern/cycles/integrator/render_scheduler.h
+++ b/intern/cycles/integrator/render_scheduler.h
@@ -39,6 +39,7 @@ class RenderWork {
struct {
int start_sample = 0;
int num_samples = 0;
+ int sample_offset = 0;
} path_trace;
struct {
@@ -125,6 +126,9 @@ class RenderScheduler {
void set_num_samples(int num_samples);
int get_num_samples() const;
+ void set_sample_offset(int sample_offset);
+ int get_sample_offset() const;
+
/* Time limit for the path tracing tasks, in minutes.
* Zero disables the limit. */
void set_time_limit(double time_limit);
@@ -150,7 +154,7 @@ class RenderScheduler {
/* Reset scheduler, indicating that rendering will happen from scratch.
* Resets current rendered state, as well as scheduling information. */
- void reset(const BufferParams &buffer_params, int num_samples);
+ void reset(const BufferParams &buffer_params, int num_samples, int sample_offset);
/* Reset scheduler upon switching to a next tile.
* Will keep the same number of samples and full-frame render parameters, but will reset progress
@@ -419,6 +423,8 @@ class RenderScheduler {
int start_sample_ = 0;
int num_samples_ = 0;
+ int sample_offset_ = 0;
+
/* Limit in seconds for how long path tracing is allowed to happen.
* Zero means no limit is applied. */
double time_limit_ = 0.0;
diff --git a/intern/cycles/integrator/work_tile_scheduler.cpp b/intern/cycles/integrator/work_tile_scheduler.cpp
index 2d1ac07db7f..d60f7149bf4 100644
--- a/intern/cycles/integrator/work_tile_scheduler.cpp
+++ b/intern/cycles/integrator/work_tile_scheduler.cpp
@@ -36,6 +36,7 @@ void WorkTileScheduler::set_max_num_path_states(int max_num_path_states)
void WorkTileScheduler::reset(const BufferParams &buffer_params,
int sample_start,
int samples_num,
+ int sample_offset,
float scrambling_distance)
{
/* Image buffer parameters. */
@@ -51,6 +52,7 @@ void WorkTileScheduler::reset(const BufferParams &buffer_params,
/* Samples parameters. */
sample_start_ = sample_start;
samples_num_ = samples_num;
+ sample_offset_ = sample_offset;
/* Initialize new scheduling. */
reset_scheduler_state();
@@ -111,6 +113,7 @@ bool WorkTileScheduler::get_work(KernelWorkTile *work_tile_, const int max_work_
work_tile.h = tile_size_.height;
work_tile.start_sample = sample_start_ + start_sample;
work_tile.num_samples = min(tile_size_.num_samples, samples_num_ - start_sample);
+ work_tile.sample_offset = sample_offset_;
work_tile.offset = offset_;
work_tile.stride = stride_;
diff --git a/intern/cycles/integrator/work_tile_scheduler.h b/intern/cycles/integrator/work_tile_scheduler.h
index d9fa7e84431..2d6395799f7 100644
--- a/intern/cycles/integrator/work_tile_scheduler.h
+++ b/intern/cycles/integrator/work_tile_scheduler.h
@@ -41,6 +41,7 @@ class WorkTileScheduler {
void reset(const BufferParams &buffer_params,
int sample_start,
int samples_num,
+ int sample_offset,
float scrambling_distance);
/* Get work for a device.
@@ -79,6 +80,7 @@ class WorkTileScheduler {
* (splitting into a smaller work tiles). */
int sample_start_ = 0;
int samples_num_ = 0;
+ int sample_offset_ = 0;
/* Tile size which be scheduled for rendering. */
TileSize tile_size_;
diff --git a/intern/cycles/kernel/CMakeLists.txt b/intern/cycles/kernel/CMakeLists.txt
index 29ff69df864..39cb886b16e 100644
--- a/intern/cycles/kernel/CMakeLists.txt
+++ b/intern/cycles/kernel/CMakeLists.txt
@@ -39,6 +39,10 @@ set(SRC_KERNEL_DEVICE_HIP
device/hip/kernel.cpp
)
+set(SRC_KERNEL_DEVICE_METAL
+ device/metal/kernel.metal
+)
+
set(SRC_KERNEL_DEVICE_OPTIX
device/optix/kernel.cu
device/optix/kernel_shader_raytrace.cu
@@ -79,6 +83,13 @@ set(SRC_KERNEL_DEVICE_OPTIX_HEADERS
device/optix/globals.h
)
+set(SRC_KERNEL_DEVICE_METAL_HEADERS
+ device/metal/compat.h
+ device/metal/context_begin.h
+ device/metal/context_end.h
+ device/metal/globals.h
+)
+
set(SRC_KERNEL_CLOSURE_HEADERS
closure/alloc.h
closure/bsdf.h
@@ -723,12 +734,14 @@ cycles_add_library(cycles_kernel "${LIB}"
${SRC_KERNEL_DEVICE_CUDA}
${SRC_KERNEL_DEVICE_HIP}
${SRC_KERNEL_DEVICE_OPTIX}
+ ${SRC_KERNEL_DEVICE_METAL}
${SRC_KERNEL_HEADERS}
${SRC_KERNEL_DEVICE_CPU_HEADERS}
${SRC_KERNEL_DEVICE_GPU_HEADERS}
${SRC_KERNEL_DEVICE_CUDA_HEADERS}
${SRC_KERNEL_DEVICE_HIP_HEADERS}
${SRC_KERNEL_DEVICE_OPTIX_HEADERS}
+ ${SRC_KERNEL_DEVICE_METAL_HEADERS}
)
source_group("bake" FILES ${SRC_KERNEL_BAKE_HEADERS})
@@ -740,6 +753,7 @@ source_group("device\\cuda" FILES ${SRC_KERNEL_DEVICE_CUDA} ${SRC_KERNEL_DEVICE_
source_group("device\\gpu" FILES ${SRC_KERNEL_DEVICE_GPU_HEADERS})
source_group("device\\hip" FILES ${SRC_KERNEL_DEVICE_HIP} ${SRC_KERNEL_DEVICE_HIP_HEADERS})
source_group("device\\optix" FILES ${SRC_KERNEL_DEVICE_OPTIX} ${SRC_KERNEL_DEVICE_OPTIX_HEADERS})
+source_group("device\\metal" FILES ${SRC_KERNEL_DEVICE_METAL} ${SRC_KERNEL_DEVICE_METAL_HEADERS})
source_group("film" FILES ${SRC_KERNEL_FILM_HEADERS})
source_group("geom" FILES ${SRC_KERNEL_GEOM_HEADERS})
source_group("integrator" FILES ${SRC_KERNEL_INTEGRATOR_HEADERS})
@@ -772,6 +786,8 @@ delayed_install(${CMAKE_CURRENT_SOURCE_DIR} "${SRC_KERNEL_DEVICE_HIP}" ${CYCLES_
delayed_install(${CMAKE_CURRENT_SOURCE_DIR} "${SRC_KERNEL_DEVICE_HIP_HEADERS}" ${CYCLES_INSTALL_PATH}/source/kernel/device/hip)
delayed_install(${CMAKE_CURRENT_SOURCE_DIR} "${SRC_KERNEL_DEVICE_OPTIX}" ${CYCLES_INSTALL_PATH}/source/kernel/device/optix)
delayed_install(${CMAKE_CURRENT_SOURCE_DIR} "${SRC_KERNEL_DEVICE_OPTIX_HEADERS}" ${CYCLES_INSTALL_PATH}/source/kernel/device/optix)
+delayed_install(${CMAKE_CURRENT_SOURCE_DIR} "${SRC_KERNEL_DEVICE_METAL}" ${CYCLES_INSTALL_PATH}/source/kernel/device/metal)
+delayed_install(${CMAKE_CURRENT_SOURCE_DIR} "${SRC_KERNEL_DEVICE_METAL_HEADERS}" ${CYCLES_INSTALL_PATH}/source/kernel/device/metal)
delayed_install(${CMAKE_CURRENT_SOURCE_DIR} "${SRC_KERNEL_FILM_HEADERS}" ${CYCLES_INSTALL_PATH}/source/kernel/film)
delayed_install(${CMAKE_CURRENT_SOURCE_DIR} "${SRC_KERNEL_GEOM_HEADERS}" ${CYCLES_INSTALL_PATH}/source/kernel/geom)
delayed_install(${CMAKE_CURRENT_SOURCE_DIR} "${SRC_KERNEL_INTEGRATOR_HEADERS}" ${CYCLES_INSTALL_PATH}/source/kernel/integrator)
diff --git a/intern/cycles/kernel/device/cuda/compat.h b/intern/cycles/kernel/device/cuda/compat.h
index 1ee82e6eb7c..2feebad074f 100644
--- a/intern/cycles/kernel/device/cuda/compat.h
+++ b/intern/cycles/kernel/device/cuda/compat.h
@@ -75,6 +75,7 @@ typedef unsigned long long uint64_t;
#define ccl_gpu_block_idx_x (blockIdx.x)
#define ccl_gpu_grid_dim_x (gridDim.x)
#define ccl_gpu_warp_size (warpSize)
+#define ccl_gpu_thread_mask(thread_warp) uint(0xFFFFFFFF >> (ccl_gpu_warp_size - thread_warp))
#define ccl_gpu_global_id_x() (ccl_gpu_block_idx_x * ccl_gpu_block_dim_x + ccl_gpu_thread_idx_x)
#define ccl_gpu_global_size_x() (ccl_gpu_grid_dim_x * ccl_gpu_block_dim_x)
diff --git a/intern/cycles/kernel/device/cuda/config.h b/intern/cycles/kernel/device/cuda/config.h
index 46196dcdb51..003881d7912 100644
--- a/intern/cycles/kernel/device/cuda/config.h
+++ b/intern/cycles/kernel/device/cuda/config.h
@@ -92,12 +92,29 @@
/* Compute number of threads per block and minimum blocks per multiprocessor
* given the maximum number of registers per thread. */
-
#define ccl_gpu_kernel(block_num_threads, thread_num_registers) \
extern "C" __global__ void __launch_bounds__(block_num_threads, \
GPU_MULTIPRESSOR_MAX_REGISTERS / \
(block_num_threads * thread_num_registers))
+#define ccl_gpu_kernel_threads(block_num_threads) \
+ extern "C" __global__ void __launch_bounds__(block_num_threads)
+
+#define ccl_gpu_kernel_signature(name, ...) kernel_gpu_##name(__VA_ARGS__)
+
+#define ccl_gpu_kernel_call(x) x
+
+/* Define a function object where "func" is the lambda body, and additional parameters are used to
+ * specify captured state */
+#define ccl_gpu_kernel_lambda(func, ...) \
+ struct KernelLambda { \
+ __VA_ARGS__; \
+ __device__ int operator()(const int state) \
+ { \
+ return (func); \
+ } \
+ } ccl_gpu_kernel_lambda_pass
+
/* sanity checks */
#if GPU_KERNEL_BLOCK_NUM_THREADS > GPU_BLOCK_MAX_THREADS
diff --git a/intern/cycles/kernel/device/gpu/image.h b/intern/cycles/kernel/device/gpu/image.h
index 95a37c693ae..0900a45c83d 100644
--- a/intern/cycles/kernel/device/gpu/image.h
+++ b/intern/cycles/kernel/device/gpu/image.h
@@ -65,7 +65,9 @@ ccl_device float cubic_h1(float a)
/* Fast bicubic texture lookup using 4 bilinear lookups, adapted from CUDA samples. */
template<typename T>
-ccl_device_noinline T kernel_tex_image_interp_bicubic(const TextureInfo &info, float x, float y)
+ccl_device_noinline T kernel_tex_image_interp_bicubic(ccl_global const TextureInfo &info,
+ float x,
+ float y)
{
ccl_gpu_tex_object tex = (ccl_gpu_tex_object)info.data;
@@ -94,7 +96,7 @@ ccl_device_noinline T kernel_tex_image_interp_bicubic(const TextureInfo &info, f
/* Fast tricubic texture lookup using 8 trilinear lookups. */
template<typename T>
ccl_device_noinline T
-kernel_tex_image_interp_tricubic(const TextureInfo &info, float x, float y, float z)
+kernel_tex_image_interp_tricubic(ccl_global const TextureInfo &info, float x, float y, float z)
{
ccl_gpu_tex_object tex = (ccl_gpu_tex_object)info.data;
@@ -169,7 +171,7 @@ ccl_device T kernel_tex_image_interp_tricubic_nanovdb(S &s, float x, float y, fl
template<typename T>
ccl_device_noinline T kernel_tex_image_interp_nanovdb(
- const TextureInfo &info, float x, float y, float z, uint interpolation)
+ ccl_global const TextureInfo &info, float x, float y, float z, uint interpolation)
{
using namespace nanovdb;
@@ -191,7 +193,7 @@ ccl_device_noinline T kernel_tex_image_interp_nanovdb(
ccl_device float4 kernel_tex_image_interp(KernelGlobals kg, int id, float x, float y)
{
- const TextureInfo &info = kernel_tex_fetch(__texture_info, id);
+ ccl_global const TextureInfo &info = kernel_tex_fetch(__texture_info, id);
/* float4, byte4, ushort4 and half4 */
const int texture_type = info.data_type;
@@ -226,7 +228,7 @@ ccl_device float4 kernel_tex_image_interp_3d(KernelGlobals kg,
float3 P,
InterpolationType interp)
{
- const TextureInfo &info = kernel_tex_fetch(__texture_info, id);
+ ccl_global const TextureInfo &info = kernel_tex_fetch(__texture_info, id);
if (info.use_transform_3d) {
P = transform_point(&info.transform_3d, P);
diff --git a/intern/cycles/kernel/device/gpu/kernel.h b/intern/cycles/kernel/device/gpu/kernel.h
index 56fcc38b907..dd0c6dd6893 100644
--- a/intern/cycles/kernel/device/gpu/kernel.h
+++ b/intern/cycles/kernel/device/gpu/kernel.h
@@ -21,6 +21,10 @@
#include "kernel/device/gpu/parallel_sorted_index.h"
#include "kernel/device/gpu/work_stealing.h"
+#ifdef __KERNEL_METAL__
+# include "kernel/device/metal/context_begin.h"
+#endif
+
#include "kernel/integrator/state.h"
#include "kernel/integrator/state_flow.h"
#include "kernel/integrator/state_util.h"
@@ -40,6 +44,11 @@
#include "kernel/bake/bake.h"
#include "kernel/film/adaptive_sampling.h"
+
+#ifdef __KERNEL_METAL__
+# include "kernel/device/metal/context_end.h"
+#endif
+
#include "kernel/film/read.h"
/* --------------------------------------------------------------------
@@ -47,7 +56,7 @@
*/
ccl_gpu_kernel(GPU_KERNEL_BLOCK_NUM_THREADS, GPU_KERNEL_MAX_REGISTERS)
- kernel_gpu_integrator_reset(int num_states)
+ ccl_gpu_kernel_signature(integrator_reset, int num_states)
{
const int state = ccl_gpu_global_id_x();
@@ -58,10 +67,11 @@ ccl_gpu_kernel(GPU_KERNEL_BLOCK_NUM_THREADS, GPU_KERNEL_MAX_REGISTERS)
}
ccl_gpu_kernel(GPU_KERNEL_BLOCK_NUM_THREADS, GPU_KERNEL_MAX_REGISTERS)
- kernel_gpu_integrator_init_from_camera(KernelWorkTile *tiles,
- const int num_tiles,
- float *render_buffer,
- const int max_tile_work_size)
+ ccl_gpu_kernel_signature(integrator_init_from_camera,
+ ccl_global KernelWorkTile *tiles,
+ const int num_tiles,
+ ccl_global float *render_buffer,
+ const int max_tile_work_size)
{
const int work_index = ccl_gpu_global_id_x();
@@ -72,7 +82,7 @@ ccl_gpu_kernel(GPU_KERNEL_BLOCK_NUM_THREADS, GPU_KERNEL_MAX_REGISTERS)
const int tile_index = work_index / max_tile_work_size;
const int tile_work_index = work_index - tile_index * max_tile_work_size;
- const KernelWorkTile *tile = &tiles[tile_index];
+ ccl_global const KernelWorkTile *tile = &tiles[tile_index];
if (tile_work_index >= tile->work_size) {
return;
@@ -83,14 +93,16 @@ ccl_gpu_kernel(GPU_KERNEL_BLOCK_NUM_THREADS, GPU_KERNEL_MAX_REGISTERS)
uint x, y, sample;
get_work_pixel(tile, tile_work_index, &x, &y, &sample);
- integrator_init_from_camera(nullptr, state, tile, render_buffer, x, y, sample);
+ ccl_gpu_kernel_call(
+ integrator_init_from_camera(nullptr, state, tile, render_buffer, x, y, sample));
}
ccl_gpu_kernel(GPU_KERNEL_BLOCK_NUM_THREADS, GPU_KERNEL_MAX_REGISTERS)
- kernel_gpu_integrator_init_from_bake(KernelWorkTile *tiles,
- const int num_tiles,
- float *render_buffer,
- const int max_tile_work_size)
+ ccl_gpu_kernel_signature(integrator_init_from_bake,
+ ccl_global KernelWorkTile *tiles,
+ const int num_tiles,
+ ccl_global float *render_buffer,
+ const int max_tile_work_size)
{
const int work_index = ccl_gpu_global_id_x();
@@ -101,7 +113,7 @@ ccl_gpu_kernel(GPU_KERNEL_BLOCK_NUM_THREADS, GPU_KERNEL_MAX_REGISTERS)
const int tile_index = work_index / max_tile_work_size;
const int tile_work_index = work_index - tile_index * max_tile_work_size;
- const KernelWorkTile *tile = &tiles[tile_index];
+ ccl_global const KernelWorkTile *tile = &tiles[tile_index];
if (tile_work_index >= tile->work_size) {
return;
@@ -112,230 +124,264 @@ ccl_gpu_kernel(GPU_KERNEL_BLOCK_NUM_THREADS, GPU_KERNEL_MAX_REGISTERS)
uint x, y, sample;
get_work_pixel(tile, tile_work_index, &x, &y, &sample);
- integrator_init_from_bake(nullptr, state, tile, render_buffer, x, y, sample);
+ ccl_gpu_kernel_call(
+ integrator_init_from_bake(nullptr, state, tile, render_buffer, x, y, sample));
}
ccl_gpu_kernel(GPU_KERNEL_BLOCK_NUM_THREADS, GPU_KERNEL_MAX_REGISTERS)
- kernel_gpu_integrator_intersect_closest(const int *path_index_array,
- ccl_global float *render_buffer,
- const int work_size)
+ ccl_gpu_kernel_signature(integrator_intersect_closest,
+ ccl_global const int *path_index_array,
+ ccl_global float *render_buffer,
+ const int work_size)
{
const int global_index = ccl_gpu_global_id_x();
if (global_index < work_size) {
const int state = (path_index_array) ? path_index_array[global_index] : global_index;
- integrator_intersect_closest(NULL, state, render_buffer);
+ ccl_gpu_kernel_call(integrator_intersect_closest(NULL, state, render_buffer));
}
}
ccl_gpu_kernel(GPU_KERNEL_BLOCK_NUM_THREADS, GPU_KERNEL_MAX_REGISTERS)
- kernel_gpu_integrator_intersect_shadow(const int *path_index_array, const int work_size)
+ ccl_gpu_kernel_signature(integrator_intersect_shadow,
+ ccl_global const int *path_index_array,
+ const int work_size)
{
const int global_index = ccl_gpu_global_id_x();
if (global_index < work_size) {
const int state = (path_index_array) ? path_index_array[global_index] : global_index;
- integrator_intersect_shadow(NULL, state);
+ ccl_gpu_kernel_call(integrator_intersect_shadow(NULL, state));
}
}
ccl_gpu_kernel(GPU_KERNEL_BLOCK_NUM_THREADS, GPU_KERNEL_MAX_REGISTERS)
- kernel_gpu_integrator_intersect_subsurface(const int *path_index_array, const int work_size)
+ ccl_gpu_kernel_signature(integrator_intersect_subsurface,
+ ccl_global const int *path_index_array,
+ const int work_size)
{
const int global_index = ccl_gpu_global_id_x();
if (global_index < work_size) {
const int state = (path_index_array) ? path_index_array[global_index] : global_index;
- integrator_intersect_subsurface(NULL, state);
+ ccl_gpu_kernel_call(integrator_intersect_subsurface(NULL, state));
}
}
ccl_gpu_kernel(GPU_KERNEL_BLOCK_NUM_THREADS, GPU_KERNEL_MAX_REGISTERS)
- kernel_gpu_integrator_intersect_volume_stack(const int *path_index_array, const int work_size)
+ ccl_gpu_kernel_signature(integrator_intersect_volume_stack,
+ ccl_global const int *path_index_array,
+ const int work_size)
{
const int global_index = ccl_gpu_global_id_x();
if (global_index < work_size) {
const int state = (path_index_array) ? path_index_array[global_index] : global_index;
- integrator_intersect_volume_stack(NULL, state);
+ ccl_gpu_kernel_call(integrator_intersect_volume_stack(NULL, state));
}
}
ccl_gpu_kernel(GPU_KERNEL_BLOCK_NUM_THREADS, GPU_KERNEL_MAX_REGISTERS)
- kernel_gpu_integrator_shade_background(const int *path_index_array,
- float *render_buffer,
- const int work_size)
+ ccl_gpu_kernel_signature(integrator_shade_background,
+ ccl_global const int *path_index_array,
+ ccl_global float *render_buffer,
+ const int work_size)
{
const int global_index = ccl_gpu_global_id_x();
if (global_index < work_size) {
const int state = (path_index_array) ? path_index_array[global_index] : global_index;
- integrator_shade_background(NULL, state, render_buffer);
+ ccl_gpu_kernel_call(integrator_shade_background(NULL, state, render_buffer));
}
}
ccl_gpu_kernel(GPU_KERNEL_BLOCK_NUM_THREADS, GPU_KERNEL_MAX_REGISTERS)
- kernel_gpu_integrator_shade_light(const int *path_index_array,
- float *render_buffer,
- const int work_size)
+ ccl_gpu_kernel_signature(integrator_shade_light,
+ ccl_global const int *path_index_array,
+ ccl_global float *render_buffer,
+ const int work_size)
{
const int global_index = ccl_gpu_global_id_x();
if (global_index < work_size) {
const int state = (path_index_array) ? path_index_array[global_index] : global_index;
- integrator_shade_light(NULL, state, render_buffer);
+ ccl_gpu_kernel_call(integrator_shade_light(NULL, state, render_buffer));
}
}
ccl_gpu_kernel(GPU_KERNEL_BLOCK_NUM_THREADS, GPU_KERNEL_MAX_REGISTERS)
- kernel_gpu_integrator_shade_shadow(const int *path_index_array,
- float *render_buffer,
- const int work_size)
+ ccl_gpu_kernel_signature(integrator_shade_shadow,
+ ccl_global const int *path_index_array,
+ ccl_global float *render_buffer,
+ const int work_size)
{
const int global_index = ccl_gpu_global_id_x();
if (global_index < work_size) {
const int state = (path_index_array) ? path_index_array[global_index] : global_index;
- integrator_shade_shadow(NULL, state, render_buffer);
+ ccl_gpu_kernel_call(integrator_shade_shadow(NULL, state, render_buffer));
}
}
ccl_gpu_kernel(GPU_KERNEL_BLOCK_NUM_THREADS, GPU_KERNEL_MAX_REGISTERS)
- kernel_gpu_integrator_shade_surface(const int *path_index_array,
- float *render_buffer,
- const int work_size)
+ ccl_gpu_kernel_signature(integrator_shade_surface,
+ ccl_global const int *path_index_array,
+ ccl_global float *render_buffer,
+ const int work_size)
{
const int global_index = ccl_gpu_global_id_x();
if (global_index < work_size) {
const int state = (path_index_array) ? path_index_array[global_index] : global_index;
- integrator_shade_surface(NULL, state, render_buffer);
+ ccl_gpu_kernel_call(integrator_shade_surface(NULL, state, render_buffer));
}
}
ccl_gpu_kernel(GPU_KERNEL_BLOCK_NUM_THREADS, GPU_KERNEL_MAX_REGISTERS)
- kernel_gpu_integrator_shade_surface_raytrace(const int *path_index_array,
- float *render_buffer,
- const int work_size)
+ ccl_gpu_kernel_signature(integrator_shade_surface_raytrace,
+ ccl_global const int *path_index_array,
+ ccl_global float *render_buffer,
+ const int work_size)
{
const int global_index = ccl_gpu_global_id_x();
if (global_index < work_size) {
const int state = (path_index_array) ? path_index_array[global_index] : global_index;
- integrator_shade_surface_raytrace(NULL, state, render_buffer);
+ ccl_gpu_kernel_call(integrator_shade_surface_raytrace(NULL, state, render_buffer));
}
}
ccl_gpu_kernel(GPU_KERNEL_BLOCK_NUM_THREADS, GPU_KERNEL_MAX_REGISTERS)
- kernel_gpu_integrator_shade_volume(const int *path_index_array,
- float *render_buffer,
- const int work_size)
+ ccl_gpu_kernel_signature(integrator_shade_volume,
+ ccl_global const int *path_index_array,
+ ccl_global float *render_buffer,
+ const int work_size)
{
const int global_index = ccl_gpu_global_id_x();
if (global_index < work_size) {
const int state = (path_index_array) ? path_index_array[global_index] : global_index;
- integrator_shade_volume(NULL, state, render_buffer);
+ ccl_gpu_kernel_call(integrator_shade_volume(NULL, state, render_buffer));
}
}
-extern "C" __global__ void __launch_bounds__(GPU_PARALLEL_ACTIVE_INDEX_DEFAULT_BLOCK_SIZE)
- kernel_gpu_integrator_queued_paths_array(int num_states,
- int *indices,
- int *num_indices,
- int kernel)
+ccl_gpu_kernel_threads(GPU_PARALLEL_ACTIVE_INDEX_DEFAULT_BLOCK_SIZE)
+ ccl_gpu_kernel_signature(integrator_queued_paths_array,
+ int num_states,
+ ccl_global int *indices,
+ ccl_global int *num_indices,
+ int kernel_index)
{
+ ccl_gpu_kernel_lambda(INTEGRATOR_STATE(state, path, queued_kernel) == kernel_index,
+ int kernel_index);
+ ccl_gpu_kernel_lambda_pass.kernel_index = kernel_index;
+
gpu_parallel_active_index_array<GPU_PARALLEL_ACTIVE_INDEX_DEFAULT_BLOCK_SIZE>(
- num_states, indices, num_indices, [kernel](const int state) {
- return (INTEGRATOR_STATE(state, path, queued_kernel) == kernel);
- });
+ num_states, indices, num_indices, ccl_gpu_kernel_lambda_pass);
}
-extern "C" __global__ void __launch_bounds__(GPU_PARALLEL_ACTIVE_INDEX_DEFAULT_BLOCK_SIZE)
- kernel_gpu_integrator_queued_shadow_paths_array(int num_states,
- int *indices,
- int *num_indices,
- int kernel)
+ccl_gpu_kernel_threads(GPU_PARALLEL_ACTIVE_INDEX_DEFAULT_BLOCK_SIZE)
+ ccl_gpu_kernel_signature(integrator_queued_shadow_paths_array,
+ int num_states,
+ ccl_global int *indices,
+ ccl_global int *num_indices,
+ int kernel_index)
{
+ ccl_gpu_kernel_lambda(INTEGRATOR_STATE(state, shadow_path, queued_kernel) == kernel_index,
+ int kernel_index);
+ ccl_gpu_kernel_lambda_pass.kernel_index = kernel_index;
+
gpu_parallel_active_index_array<GPU_PARALLEL_ACTIVE_INDEX_DEFAULT_BLOCK_SIZE>(
- num_states, indices, num_indices, [kernel](const int state) {
- return (INTEGRATOR_STATE(state, shadow_path, queued_kernel) == kernel);
- });
+ num_states, indices, num_indices, ccl_gpu_kernel_lambda_pass);
}
-extern "C" __global__ void __launch_bounds__(GPU_PARALLEL_ACTIVE_INDEX_DEFAULT_BLOCK_SIZE)
- kernel_gpu_integrator_active_paths_array(int num_states, int *indices, int *num_indices)
+ccl_gpu_kernel_threads(GPU_PARALLEL_ACTIVE_INDEX_DEFAULT_BLOCK_SIZE)
+ ccl_gpu_kernel_signature(integrator_active_paths_array,
+ int num_states,
+ ccl_global int *indices,
+ ccl_global int *num_indices)
{
+ ccl_gpu_kernel_lambda(INTEGRATOR_STATE(state, path, queued_kernel) != 0);
+
gpu_parallel_active_index_array<GPU_PARALLEL_ACTIVE_INDEX_DEFAULT_BLOCK_SIZE>(
- num_states, indices, num_indices, [](const int state) {
- return (INTEGRATOR_STATE(state, path, queued_kernel) != 0);
- });
+ num_states, indices, num_indices, ccl_gpu_kernel_lambda_pass);
}
-extern "C" __global__ void __launch_bounds__(GPU_PARALLEL_ACTIVE_INDEX_DEFAULT_BLOCK_SIZE)
- kernel_gpu_integrator_terminated_paths_array(int num_states,
- int *indices,
- int *num_indices,
- int indices_offset)
+ccl_gpu_kernel_threads(GPU_PARALLEL_ACTIVE_INDEX_DEFAULT_BLOCK_SIZE)
+ ccl_gpu_kernel_signature(integrator_terminated_paths_array,
+ int num_states,
+ ccl_global int *indices,
+ ccl_global int *num_indices,
+ int indices_offset)
{
+ ccl_gpu_kernel_lambda(INTEGRATOR_STATE(state, path, queued_kernel) == 0);
+
gpu_parallel_active_index_array<GPU_PARALLEL_ACTIVE_INDEX_DEFAULT_BLOCK_SIZE>(
- num_states, indices + indices_offset, num_indices, [](const int state) {
- return (INTEGRATOR_STATE(state, path, queued_kernel) == 0);
- });
+ num_states, indices + indices_offset, num_indices, ccl_gpu_kernel_lambda_pass);
}
-extern "C" __global__ void __launch_bounds__(GPU_PARALLEL_ACTIVE_INDEX_DEFAULT_BLOCK_SIZE)
- kernel_gpu_integrator_terminated_shadow_paths_array(int num_states,
- int *indices,
- int *num_indices,
- int indices_offset)
+ccl_gpu_kernel_threads(GPU_PARALLEL_ACTIVE_INDEX_DEFAULT_BLOCK_SIZE)
+ ccl_gpu_kernel_signature(integrator_terminated_shadow_paths_array,
+ int num_states,
+ ccl_global int *indices,
+ ccl_global int *num_indices,
+ int indices_offset)
{
+ ccl_gpu_kernel_lambda(INTEGRATOR_STATE(state, shadow_path, queued_kernel) == 0);
+
gpu_parallel_active_index_array<GPU_PARALLEL_ACTIVE_INDEX_DEFAULT_BLOCK_SIZE>(
- num_states, indices + indices_offset, num_indices, [](const int state) {
- return (INTEGRATOR_STATE(state, shadow_path, queued_kernel) == 0);
- });
-}
-
-extern "C" __global__ void __launch_bounds__(GPU_PARALLEL_SORTED_INDEX_DEFAULT_BLOCK_SIZE)
- kernel_gpu_integrator_sorted_paths_array(int num_states,
- int num_states_limit,
- int *indices,
- int *num_indices,
- int *key_counter,
- int *key_prefix_sum,
- int kernel)
-{
- gpu_parallel_sorted_index_array<GPU_PARALLEL_SORTED_INDEX_DEFAULT_BLOCK_SIZE>(
- num_states,
- num_states_limit,
- indices,
- num_indices,
- key_counter,
- key_prefix_sum,
- [kernel](const int state) {
- return (INTEGRATOR_STATE(state, path, queued_kernel) == kernel) ?
- INTEGRATOR_STATE(state, path, shader_sort_key) :
- GPU_PARALLEL_SORTED_INDEX_INACTIVE_KEY;
- });
-}
-
-extern "C" __global__ void __launch_bounds__(GPU_PARALLEL_ACTIVE_INDEX_DEFAULT_BLOCK_SIZE)
- kernel_gpu_integrator_compact_paths_array(int num_states,
- int *indices,
- int *num_indices,
- int num_active_paths)
-{
+ num_states, indices + indices_offset, num_indices, ccl_gpu_kernel_lambda_pass);
+}
+
+ccl_gpu_kernel_threads(GPU_PARALLEL_SORTED_INDEX_DEFAULT_BLOCK_SIZE)
+ ccl_gpu_kernel_signature(integrator_sorted_paths_array,
+ int num_states,
+ int num_states_limit,
+ ccl_global int *indices,
+ ccl_global int *num_indices,
+ ccl_global int *key_counter,
+ ccl_global int *key_prefix_sum,
+ int kernel_index)
+{
+ ccl_gpu_kernel_lambda((INTEGRATOR_STATE(state, path, queued_kernel) == kernel_index) ?
+ INTEGRATOR_STATE(state, path, shader_sort_key) :
+ GPU_PARALLEL_SORTED_INDEX_INACTIVE_KEY,
+ int kernel_index);
+ ccl_gpu_kernel_lambda_pass.kernel_index = kernel_index;
+
+ const uint state_index = ccl_gpu_global_id_x();
+ gpu_parallel_sorted_index_array(state_index,
+ num_states,
+ num_states_limit,
+ indices,
+ num_indices,
+ key_counter,
+ key_prefix_sum,
+ ccl_gpu_kernel_lambda_pass);
+}
+
+ccl_gpu_kernel_threads(GPU_PARALLEL_ACTIVE_INDEX_DEFAULT_BLOCK_SIZE)
+ ccl_gpu_kernel_signature(integrator_compact_paths_array,
+ int num_states,
+ ccl_global int *indices,
+ ccl_global int *num_indices,
+ int num_active_paths)
+{
+ ccl_gpu_kernel_lambda((state >= num_active_paths) &&
+ (INTEGRATOR_STATE(state, path, queued_kernel) != 0),
+ int num_active_paths);
+ ccl_gpu_kernel_lambda_pass.num_active_paths = num_active_paths;
+
gpu_parallel_active_index_array<GPU_PARALLEL_ACTIVE_INDEX_DEFAULT_BLOCK_SIZE>(
- num_states, indices, num_indices, [num_active_paths](const int state) {
- return (state >= num_active_paths) && (INTEGRATOR_STATE(state, path, queued_kernel) != 0);
- });
+ num_states, indices, num_indices, ccl_gpu_kernel_lambda_pass);
}
-extern "C" __global__ void __launch_bounds__(GPU_PARALLEL_SORTED_INDEX_DEFAULT_BLOCK_SIZE)
- kernel_gpu_integrator_compact_states(const int *active_terminated_states,
- const int active_states_offset,
- const int terminated_states_offset,
- const int work_size)
+ccl_gpu_kernel_threads(GPU_PARALLEL_SORTED_INDEX_DEFAULT_BLOCK_SIZE)
+ ccl_gpu_kernel_signature(integrator_compact_states,
+ ccl_global const int *active_terminated_states,
+ const int active_states_offset,
+ const int terminated_states_offset,
+ const int work_size)
{
const int global_index = ccl_gpu_global_id_x();
@@ -343,28 +389,32 @@ extern "C" __global__ void __launch_bounds__(GPU_PARALLEL_SORTED_INDEX_DEFAULT_B
const int from_state = active_terminated_states[active_states_offset + global_index];
const int to_state = active_terminated_states[terminated_states_offset + global_index];
- integrator_state_move(NULL, to_state, from_state);
+ ccl_gpu_kernel_call(integrator_state_move(NULL, to_state, from_state));
}
}
-extern "C" __global__ void __launch_bounds__(GPU_PARALLEL_ACTIVE_INDEX_DEFAULT_BLOCK_SIZE)
- kernel_gpu_integrator_compact_shadow_paths_array(int num_states,
- int *indices,
- int *num_indices,
- int num_active_paths)
+ccl_gpu_kernel_threads(GPU_PARALLEL_ACTIVE_INDEX_DEFAULT_BLOCK_SIZE)
+ ccl_gpu_kernel_signature(integrator_compact_shadow_paths_array,
+ int num_states,
+ ccl_global int *indices,
+ ccl_global int *num_indices,
+ int num_active_paths)
{
+ ccl_gpu_kernel_lambda((state >= num_active_paths) &&
+ (INTEGRATOR_STATE(state, shadow_path, queued_kernel) != 0),
+ int num_active_paths);
+ ccl_gpu_kernel_lambda_pass.num_active_paths = num_active_paths;
+
gpu_parallel_active_index_array<GPU_PARALLEL_ACTIVE_INDEX_DEFAULT_BLOCK_SIZE>(
- num_states, indices, num_indices, [num_active_paths](const int state) {
- return (state >= num_active_paths) &&
- (INTEGRATOR_STATE(state, shadow_path, queued_kernel) != 0);
- });
+ num_states, indices, num_indices, ccl_gpu_kernel_lambda_pass);
}
-extern "C" __global__ void __launch_bounds__(GPU_PARALLEL_SORTED_INDEX_DEFAULT_BLOCK_SIZE)
- kernel_gpu_integrator_compact_shadow_states(const int *active_terminated_states,
- const int active_states_offset,
- const int terminated_states_offset,
- const int work_size)
+ccl_gpu_kernel_threads(GPU_PARALLEL_SORTED_INDEX_DEFAULT_BLOCK_SIZE)
+ ccl_gpu_kernel_signature(integrator_compact_shadow_states,
+ ccl_global const int *active_terminated_states,
+ const int active_states_offset,
+ const int terminated_states_offset,
+ const int work_size)
{
const int global_index = ccl_gpu_global_id_x();
@@ -372,15 +422,14 @@ extern "C" __global__ void __launch_bounds__(GPU_PARALLEL_SORTED_INDEX_DEFAULT_B
const int from_state = active_terminated_states[active_states_offset + global_index];
const int to_state = active_terminated_states[terminated_states_offset + global_index];
- integrator_shadow_state_move(NULL, to_state, from_state);
+ ccl_gpu_kernel_call(integrator_shadow_state_move(NULL, to_state, from_state));
}
}
-extern "C" __global__ void __launch_bounds__(GPU_PARALLEL_PREFIX_SUM_DEFAULT_BLOCK_SIZE)
- kernel_gpu_prefix_sum(int *counter, int *prefix_sum, int num_values)
+ccl_gpu_kernel_threads(GPU_PARALLEL_PREFIX_SUM_DEFAULT_BLOCK_SIZE) ccl_gpu_kernel_signature(
+ prefix_sum, ccl_global int *counter, ccl_global int *prefix_sum, int num_values)
{
- gpu_parallel_prefix_sum<GPU_PARALLEL_PREFIX_SUM_DEFAULT_BLOCK_SIZE>(
- counter, prefix_sum, num_values);
+ gpu_parallel_prefix_sum(ccl_gpu_global_id_x(), counter, prefix_sum, num_values);
}
/* --------------------------------------------------------------------
@@ -388,16 +437,17 @@ extern "C" __global__ void __launch_bounds__(GPU_PARALLEL_PREFIX_SUM_DEFAULT_BLO
*/
ccl_gpu_kernel(GPU_KERNEL_BLOCK_NUM_THREADS, GPU_KERNEL_MAX_REGISTERS)
- kernel_gpu_adaptive_sampling_convergence_check(float *render_buffer,
- int sx,
- int sy,
- int sw,
- int sh,
- float threshold,
- bool reset,
- int offset,
- int stride,
- uint *num_active_pixels)
+ ccl_gpu_kernel_signature(adaptive_sampling_convergence_check,
+ ccl_global float *render_buffer,
+ int sx,
+ int sy,
+ int sw,
+ int sh,
+ float threshold,
+ bool reset,
+ int offset,
+ int stride,
+ ccl_global uint *num_active_pixels)
{
const int work_index = ccl_gpu_global_id_x();
const int y = work_index / sw;
@@ -406,37 +456,51 @@ ccl_gpu_kernel(GPU_KERNEL_BLOCK_NUM_THREADS, GPU_KERNEL_MAX_REGISTERS)
bool converged = true;
if (x < sw && y < sh) {
- converged = kernel_adaptive_sampling_convergence_check(
- nullptr, render_buffer, sx + x, sy + y, threshold, reset, offset, stride);
+ converged = ccl_gpu_kernel_call(kernel_adaptive_sampling_convergence_check(
+ nullptr, render_buffer, sx + x, sy + y, threshold, reset, offset, stride));
}
/* NOTE: All threads specified in the mask must execute the intrinsic. */
- const uint num_active_pixels_mask = ccl_gpu_ballot(!converged);
+ const auto num_active_pixels_mask = ccl_gpu_ballot(!converged);
const int lane_id = ccl_gpu_thread_idx_x % ccl_gpu_warp_size;
if (lane_id == 0) {
- atomic_fetch_and_add_uint32(num_active_pixels, __popc(num_active_pixels_mask));
+ atomic_fetch_and_add_uint32(num_active_pixels, ccl_gpu_popc(num_active_pixels_mask));
}
}
ccl_gpu_kernel(GPU_KERNEL_BLOCK_NUM_THREADS, GPU_KERNEL_MAX_REGISTERS)
- kernel_gpu_adaptive_sampling_filter_x(
- float *render_buffer, int sx, int sy, int sw, int sh, int offset, int stride)
+ ccl_gpu_kernel_signature(adaptive_sampling_filter_x,
+ ccl_global float *render_buffer,
+ int sx,
+ int sy,
+ int sw,
+ int sh,
+ int offset,
+ int stride)
{
const int y = ccl_gpu_global_id_x();
if (y < sh) {
- kernel_adaptive_sampling_filter_x(NULL, render_buffer, sy + y, sx, sw, offset, stride);
+ ccl_gpu_kernel_call(
+ kernel_adaptive_sampling_filter_x(NULL, render_buffer, sy + y, sx, sw, offset, stride));
}
}
ccl_gpu_kernel(GPU_KERNEL_BLOCK_NUM_THREADS, GPU_KERNEL_MAX_REGISTERS)
- kernel_gpu_adaptive_sampling_filter_y(
- float *render_buffer, int sx, int sy, int sw, int sh, int offset, int stride)
+ ccl_gpu_kernel_signature(adaptive_sampling_filter_y,
+ ccl_global float *render_buffer,
+ int sx,
+ int sy,
+ int sw,
+ int sh,
+ int offset,
+ int stride)
{
const int x = ccl_gpu_global_id_x();
if (x < sw) {
- kernel_adaptive_sampling_filter_y(NULL, render_buffer, sx + x, sy, sh, offset, stride);
+ ccl_gpu_kernel_call(
+ kernel_adaptive_sampling_filter_y(NULL, render_buffer, sx + x, sy, sh, offset, stride));
}
}
@@ -445,12 +509,14 @@ ccl_gpu_kernel(GPU_KERNEL_BLOCK_NUM_THREADS, GPU_KERNEL_MAX_REGISTERS)
*/
ccl_gpu_kernel(GPU_KERNEL_BLOCK_NUM_THREADS, GPU_KERNEL_MAX_REGISTERS)
- kernel_gpu_cryptomatte_postprocess(float *render_buffer, int num_pixels)
+ ccl_gpu_kernel_signature(cryptomatte_postprocess,
+ ccl_global float *render_buffer,
+ int num_pixels)
{
const int pixel_index = ccl_gpu_global_id_x();
if (pixel_index < num_pixels) {
- kernel_cryptomatte_post(nullptr, render_buffer, pixel_index);
+ ccl_gpu_kernel_call(kernel_cryptomatte_post(nullptr, render_buffer, pixel_index));
}
}
@@ -458,36 +524,6 @@ ccl_gpu_kernel(GPU_KERNEL_BLOCK_NUM_THREADS, GPU_KERNEL_MAX_REGISTERS)
* Film.
*/
-/* Common implementation for float destination. */
-template<typename Processor>
-ccl_device_inline void kernel_gpu_film_convert_common(const KernelFilmConvert *kfilm_convert,
- float *pixels,
- float *render_buffer,
- int num_pixels,
- int width,
- int offset,
- int stride,
- int dst_offset,
- int dst_stride,
- const Processor &processor)
-{
- const int render_pixel_index = ccl_gpu_global_id_x();
- if (render_pixel_index >= num_pixels) {
- return;
- }
-
- const int x = render_pixel_index % width;
- const int y = render_pixel_index / width;
-
- ccl_global const float *buffer = render_buffer + offset + x * kfilm_convert->pass_stride +
- y * stride * kfilm_convert->pass_stride;
-
- ccl_global float *pixel = pixels +
- (render_pixel_index + dst_offset) * kfilm_convert->pixel_stride;
-
- processor(kfilm_convert, buffer, pixel);
-}
-
ccl_device_inline void kernel_gpu_film_convert_half_write(ccl_global uchar4 *rgba,
const int rgba_offset,
const int rgba_stride,
@@ -508,177 +544,95 @@ ccl_device_inline void kernel_gpu_film_convert_half_write(ccl_global uchar4 *rgb
#endif
}
-/* Common implementation for half4 destination and 4-channel input pass. */
-template<typename Processor>
-ccl_device_inline void kernel_gpu_film_convert_half_rgba_common_rgba(
- const KernelFilmConvert *kfilm_convert,
- uchar4 *rgba,
- float *render_buffer,
- int num_pixels,
- int width,
- int offset,
- int stride,
- int rgba_offset,
- int rgba_stride,
- const Processor &processor)
-{
- const int render_pixel_index = ccl_gpu_global_id_x();
- if (render_pixel_index >= num_pixels) {
- return;
- }
-
- const int x = render_pixel_index % width;
- const int y = render_pixel_index / width;
-
- ccl_global const float *buffer = render_buffer + offset + x * kfilm_convert->pass_stride +
- y * stride * kfilm_convert->pass_stride;
-
- float pixel[4];
- processor(kfilm_convert, buffer, pixel);
-
- film_apply_pass_pixel_overlays_rgba(kfilm_convert, buffer, pixel);
-
- const half4 half_pixel = float4_to_half4_display(
- make_float4(pixel[0], pixel[1], pixel[2], pixel[3]));
- kernel_gpu_film_convert_half_write(rgba, rgba_offset, rgba_stride, x, y, half_pixel);
-}
-
-/* Common implementation for half4 destination and 3-channel input pass. */
-template<typename Processor>
-ccl_device_inline void kernel_gpu_film_convert_half_rgba_common_rgb(
- const KernelFilmConvert *kfilm_convert,
- uchar4 *rgba,
- float *render_buffer,
- int num_pixels,
- int width,
- int offset,
- int stride,
- int rgba_offset,
- int rgba_stride,
- const Processor &processor)
-{
- kernel_gpu_film_convert_half_rgba_common_rgba(
- kfilm_convert,
- rgba,
- render_buffer,
- num_pixels,
- width,
- offset,
- stride,
- rgba_offset,
- rgba_stride,
- [&processor](const KernelFilmConvert *kfilm_convert,
- ccl_global const float *buffer,
- float *pixel_rgba) {
- processor(kfilm_convert, buffer, pixel_rgba);
- pixel_rgba[3] = 1.0f;
- });
-}
-
-/* Common implementation for half4 destination and single channel input pass. */
-template<typename Processor>
-ccl_device_inline void kernel_gpu_film_convert_half_rgba_common_value(
- const KernelFilmConvert *kfilm_convert,
- uchar4 *rgba,
- float *render_buffer,
- int num_pixels,
- int width,
- int offset,
- int stride,
- int rgba_offset,
- int rgba_stride,
- const Processor &processor)
-{
- kernel_gpu_film_convert_half_rgba_common_rgba(
- kfilm_convert,
- rgba,
- render_buffer,
- num_pixels,
- width,
- offset,
- stride,
- rgba_offset,
- rgba_stride,
- [&processor](const KernelFilmConvert *kfilm_convert,
- ccl_global const float *buffer,
- float *pixel_rgba) {
- float value;
- processor(kfilm_convert, buffer, &value);
-
- pixel_rgba[0] = value;
- pixel_rgba[1] = value;
- pixel_rgba[2] = value;
- pixel_rgba[3] = 1.0f;
- });
-}
-
-#define KERNEL_FILM_CONVERT_PROC(name) \
- ccl_gpu_kernel(GPU_KERNEL_BLOCK_NUM_THREADS, GPU_KERNEL_MAX_REGISTERS) name
-
-#define KERNEL_FILM_CONVERT_DEFINE(variant, channels) \
- KERNEL_FILM_CONVERT_PROC(kernel_gpu_film_convert_##variant) \
- (const KernelFilmConvert kfilm_convert, \
- float *pixels, \
- float *render_buffer, \
- int num_pixels, \
- int width, \
- int offset, \
- int stride, \
- int rgba_offset, \
- int rgba_stride) \
+#define KERNEL_FILM_CONVERT_VARIANT(variant, input_channel_count) \
+ ccl_gpu_kernel(GPU_KERNEL_BLOCK_NUM_THREADS, GPU_KERNEL_MAX_REGISTERS) \
+ ccl_gpu_kernel_signature(film_convert_##variant, \
+ const KernelFilmConvert kfilm_convert, \
+ ccl_global float *pixels, \
+ ccl_global float *render_buffer, \
+ int num_pixels, \
+ int width, \
+ int offset, \
+ int stride, \
+ int rgba_offset, \
+ int rgba_stride) \
{ \
- kernel_gpu_film_convert_common(&kfilm_convert, \
- pixels, \
- render_buffer, \
- num_pixels, \
- width, \
- offset, \
- stride, \
- rgba_offset, \
- rgba_stride, \
- film_get_pass_pixel_##variant); \
+ const int render_pixel_index = ccl_gpu_global_id_x(); \
+ if (render_pixel_index >= num_pixels) { \
+ return; \
+ } \
+\
+ const int x = render_pixel_index % width; \
+ const int y = render_pixel_index / width; \
+\
+ ccl_global const float *buffer = render_buffer + offset + x * kfilm_convert.pass_stride + \
+ y * stride * kfilm_convert.pass_stride; \
+\
+ ccl_global float *pixel = pixels + \
+ (render_pixel_index + rgba_offset) * kfilm_convert.pixel_stride; \
+\
+ film_get_pass_pixel_##variant(&kfilm_convert, buffer, pixel); \
} \
- KERNEL_FILM_CONVERT_PROC(kernel_gpu_film_convert_##variant##_half_rgba) \
- (const KernelFilmConvert kfilm_convert, \
- uchar4 *rgba, \
- float *render_buffer, \
- int num_pixels, \
- int width, \
- int offset, \
- int stride, \
- int rgba_offset, \
- int rgba_stride) \
+\
+ ccl_gpu_kernel(GPU_KERNEL_BLOCK_NUM_THREADS, GPU_KERNEL_MAX_REGISTERS) \
+ ccl_gpu_kernel_signature(film_convert_##variant##_half_rgba, \
+ const KernelFilmConvert kfilm_convert, \
+ ccl_global uchar4 *rgba, \
+ ccl_global float *render_buffer, \
+ int num_pixels, \
+ int width, \
+ int offset, \
+ int stride, \
+ int rgba_offset, \
+ int rgba_stride) \
{ \
- kernel_gpu_film_convert_half_rgba_common_##channels(&kfilm_convert, \
- rgba, \
- render_buffer, \
- num_pixels, \
- width, \
- offset, \
- stride, \
- rgba_offset, \
- rgba_stride, \
- film_get_pass_pixel_##variant); \
- }
-
-KERNEL_FILM_CONVERT_DEFINE(depth, value)
-KERNEL_FILM_CONVERT_DEFINE(mist, value)
-KERNEL_FILM_CONVERT_DEFINE(sample_count, value)
-KERNEL_FILM_CONVERT_DEFINE(float, value)
-
-KERNEL_FILM_CONVERT_DEFINE(light_path, rgb)
-KERNEL_FILM_CONVERT_DEFINE(float3, rgb)
-
-KERNEL_FILM_CONVERT_DEFINE(motion, rgba)
-KERNEL_FILM_CONVERT_DEFINE(cryptomatte, rgba)
-KERNEL_FILM_CONVERT_DEFINE(shadow_catcher, rgba)
-KERNEL_FILM_CONVERT_DEFINE(shadow_catcher_matte_with_shadow, rgba)
-KERNEL_FILM_CONVERT_DEFINE(combined, rgba)
-KERNEL_FILM_CONVERT_DEFINE(float4, rgba)
-
-#undef KERNEL_FILM_CONVERT_DEFINE
-#undef KERNEL_FILM_CONVERT_HALF_RGBA_DEFINE
-#undef KERNEL_FILM_CONVERT_PROC
+ const int render_pixel_index = ccl_gpu_global_id_x(); \
+ if (render_pixel_index >= num_pixels) { \
+ return; \
+ } \
+\
+ const int x = render_pixel_index % width; \
+ const int y = render_pixel_index / width; \
+\
+ ccl_global const float *buffer = render_buffer + offset + x * kfilm_convert.pass_stride + \
+ y * stride * kfilm_convert.pass_stride; \
+\
+ float pixel[4]; \
+ film_get_pass_pixel_##variant(&kfilm_convert, buffer, pixel); \
+\
+ if (input_channel_count == 1) { \
+ pixel[1] = pixel[2] = pixel[0]; \
+ } \
+ if (input_channel_count <= 3) { \
+ pixel[3] = 1.0f; \
+ } \
+\
+ film_apply_pass_pixel_overlays_rgba(&kfilm_convert, buffer, pixel); \
+\
+ const half4 half_pixel = float4_to_half4_display( \
+ make_float4(pixel[0], pixel[1], pixel[2], pixel[3])); \
+ kernel_gpu_film_convert_half_write(rgba, rgba_offset, rgba_stride, x, y, half_pixel); \
+ }
+
+/* 1 channel inputs */
+KERNEL_FILM_CONVERT_VARIANT(depth, 1)
+KERNEL_FILM_CONVERT_VARIANT(mist, 1)
+KERNEL_FILM_CONVERT_VARIANT(sample_count, 1)
+KERNEL_FILM_CONVERT_VARIANT(float, 1)
+
+/* 3 channel inputs */
+KERNEL_FILM_CONVERT_VARIANT(light_path, 3)
+KERNEL_FILM_CONVERT_VARIANT(float3, 3)
+
+/* 4 channel inputs */
+KERNEL_FILM_CONVERT_VARIANT(motion, 4)
+KERNEL_FILM_CONVERT_VARIANT(cryptomatte, 4)
+KERNEL_FILM_CONVERT_VARIANT(shadow_catcher, 4)
+KERNEL_FILM_CONVERT_VARIANT(shadow_catcher_matte_with_shadow, 4)
+KERNEL_FILM_CONVERT_VARIANT(combined, 4)
+KERNEL_FILM_CONVERT_VARIANT(float4, 4)
+
+#undef KERNEL_FILM_CONVERT_VARIANT
/* --------------------------------------------------------------------
* Shader evaluation.
@@ -687,42 +641,46 @@ KERNEL_FILM_CONVERT_DEFINE(float4, rgba)
/* Displacement */
ccl_gpu_kernel(GPU_KERNEL_BLOCK_NUM_THREADS, GPU_KERNEL_MAX_REGISTERS)
- kernel_gpu_shader_eval_displace(KernelShaderEvalInput *input,
- float *output,
- const int offset,
- const int work_size)
+ ccl_gpu_kernel_signature(shader_eval_displace,
+ ccl_global KernelShaderEvalInput *input,
+ ccl_global float *output,
+ const int offset,
+ const int work_size)
{
int i = ccl_gpu_global_id_x();
if (i < work_size) {
- kernel_displace_evaluate(NULL, input, output, offset + i);
+ ccl_gpu_kernel_call(kernel_displace_evaluate(NULL, input, output, offset + i));
}
}
/* Background */
ccl_gpu_kernel(GPU_KERNEL_BLOCK_NUM_THREADS, GPU_KERNEL_MAX_REGISTERS)
- kernel_gpu_shader_eval_background(KernelShaderEvalInput *input,
- float *output,
- const int offset,
- const int work_size)
+ ccl_gpu_kernel_signature(shader_eval_background,
+ ccl_global KernelShaderEvalInput *input,
+ ccl_global float *output,
+ const int offset,
+ const int work_size)
{
int i = ccl_gpu_global_id_x();
if (i < work_size) {
- kernel_background_evaluate(NULL, input, output, offset + i);
+ ccl_gpu_kernel_call(kernel_background_evaluate(NULL, input, output, offset + i));
}
}
/* Curve Shadow Transparency */
ccl_gpu_kernel(GPU_KERNEL_BLOCK_NUM_THREADS, GPU_KERNEL_MAX_REGISTERS)
- kernel_gpu_shader_eval_curve_shadow_transparency(KernelShaderEvalInput *input,
- float *output,
- const int offset,
- const int work_size)
+ ccl_gpu_kernel_signature(shader_eval_curve_shadow_transparency,
+ ccl_global KernelShaderEvalInput *input,
+ ccl_global float *output,
+ const int offset,
+ const int work_size)
{
int i = ccl_gpu_global_id_x();
if (i < work_size) {
- kernel_curve_shadow_transparency_evaluate(NULL, input, output, offset + i);
+ ccl_gpu_kernel_call(
+ kernel_curve_shadow_transparency_evaluate(NULL, input, output, offset + i));
}
}
@@ -731,15 +689,16 @@ ccl_gpu_kernel(GPU_KERNEL_BLOCK_NUM_THREADS, GPU_KERNEL_MAX_REGISTERS)
*/
ccl_gpu_kernel(GPU_KERNEL_BLOCK_NUM_THREADS, GPU_KERNEL_MAX_REGISTERS)
- kernel_gpu_filter_color_preprocess(float *render_buffer,
- int full_x,
- int full_y,
- int width,
- int height,
- int offset,
- int stride,
- int pass_stride,
- int pass_denoised)
+ ccl_gpu_kernel_signature(filter_color_preprocess,
+ ccl_global float *render_buffer,
+ int full_x,
+ int full_y,
+ int width,
+ int height,
+ int offset,
+ int stride,
+ int pass_stride,
+ int pass_denoised)
{
const int work_index = ccl_gpu_global_id_x();
const int y = work_index / width;
@@ -750,31 +709,32 @@ ccl_gpu_kernel(GPU_KERNEL_BLOCK_NUM_THREADS, GPU_KERNEL_MAX_REGISTERS)
}
const uint64_t render_pixel_index = offset + (x + full_x) + (y + full_y) * stride;
- float *buffer = render_buffer + render_pixel_index * pass_stride;
+ ccl_global float *buffer = render_buffer + render_pixel_index * pass_stride;
- float *color_out = buffer + pass_denoised;
+ ccl_global float *color_out = buffer + pass_denoised;
color_out[0] = clamp(color_out[0], 0.0f, 10000.0f);
color_out[1] = clamp(color_out[1], 0.0f, 10000.0f);
color_out[2] = clamp(color_out[2], 0.0f, 10000.0f);
}
ccl_gpu_kernel(GPU_KERNEL_BLOCK_NUM_THREADS, GPU_KERNEL_MAX_REGISTERS)
- kernel_gpu_filter_guiding_preprocess(float *guiding_buffer,
- int guiding_pass_stride,
- int guiding_pass_albedo,
- int guiding_pass_normal,
- const float *render_buffer,
- int render_offset,
- int render_stride,
- int render_pass_stride,
- int render_pass_sample_count,
- int render_pass_denoising_albedo,
- int render_pass_denoising_normal,
- int full_x,
- int full_y,
- int width,
- int height,
- int num_samples)
+ ccl_gpu_kernel_signature(filter_guiding_preprocess,
+ ccl_global float *guiding_buffer,
+ int guiding_pass_stride,
+ int guiding_pass_albedo,
+ int guiding_pass_normal,
+ ccl_global const float *render_buffer,
+ int render_offset,
+ int render_stride,
+ int render_pass_stride,
+ int render_pass_sample_count,
+ int render_pass_denoising_albedo,
+ int render_pass_denoising_normal,
+ int full_x,
+ int full_y,
+ int width,
+ int height,
+ int num_samples)
{
const int work_index = ccl_gpu_global_id_x();
const int y = work_index / width;
@@ -785,10 +745,10 @@ ccl_gpu_kernel(GPU_KERNEL_BLOCK_NUM_THREADS, GPU_KERNEL_MAX_REGISTERS)
}
const uint64_t guiding_pixel_index = x + y * width;
- float *guiding_pixel = guiding_buffer + guiding_pixel_index * guiding_pass_stride;
+ ccl_global float *guiding_pixel = guiding_buffer + guiding_pixel_index * guiding_pass_stride;
const uint64_t render_pixel_index = render_offset + (x + full_x) + (y + full_y) * render_stride;
- const float *buffer = render_buffer + render_pixel_index * render_pass_stride;
+ ccl_global const float *buffer = render_buffer + render_pixel_index * render_pass_stride;
float pixel_scale;
if (render_pass_sample_count == PASS_UNUSED) {
@@ -802,8 +762,8 @@ ccl_gpu_kernel(GPU_KERNEL_BLOCK_NUM_THREADS, GPU_KERNEL_MAX_REGISTERS)
if (guiding_pass_albedo != PASS_UNUSED) {
kernel_assert(render_pass_denoising_albedo != PASS_UNUSED);
- const float *aledo_in = buffer + render_pass_denoising_albedo;
- float *albedo_out = guiding_pixel + guiding_pass_albedo;
+ ccl_global const float *aledo_in = buffer + render_pass_denoising_albedo;
+ ccl_global float *albedo_out = guiding_pixel + guiding_pass_albedo;
albedo_out[0] = aledo_in[0] * pixel_scale;
albedo_out[1] = aledo_in[1] * pixel_scale;
@@ -814,8 +774,8 @@ ccl_gpu_kernel(GPU_KERNEL_BLOCK_NUM_THREADS, GPU_KERNEL_MAX_REGISTERS)
if (guiding_pass_normal != PASS_UNUSED) {
kernel_assert(render_pass_denoising_normal != PASS_UNUSED);
- const float *normal_in = buffer + render_pass_denoising_normal;
- float *normal_out = guiding_pixel + guiding_pass_normal;
+ ccl_global const float *normal_in = buffer + render_pass_denoising_normal;
+ ccl_global float *normal_out = guiding_pixel + guiding_pass_normal;
normal_out[0] = normal_in[0] * pixel_scale;
normal_out[1] = normal_in[1] * pixel_scale;
@@ -824,11 +784,12 @@ ccl_gpu_kernel(GPU_KERNEL_BLOCK_NUM_THREADS, GPU_KERNEL_MAX_REGISTERS)
}
ccl_gpu_kernel(GPU_KERNEL_BLOCK_NUM_THREADS, GPU_KERNEL_MAX_REGISTERS)
- kernel_gpu_filter_guiding_set_fake_albedo(float *guiding_buffer,
- int guiding_pass_stride,
- int guiding_pass_albedo,
- int width,
- int height)
+ ccl_gpu_kernel_signature(filter_guiding_set_fake_albedo,
+ ccl_global float *guiding_buffer,
+ int guiding_pass_stride,
+ int guiding_pass_albedo,
+ int width,
+ int height)
{
kernel_assert(guiding_pass_albedo != PASS_UNUSED);
@@ -841,9 +802,9 @@ ccl_gpu_kernel(GPU_KERNEL_BLOCK_NUM_THREADS, GPU_KERNEL_MAX_REGISTERS)
}
const uint64_t guiding_pixel_index = x + y * width;
- float *guiding_pixel = guiding_buffer + guiding_pixel_index * guiding_pass_stride;
+ ccl_global float *guiding_pixel = guiding_buffer + guiding_pixel_index * guiding_pass_stride;
- float *albedo_out = guiding_pixel + guiding_pass_albedo;
+ ccl_global float *albedo_out = guiding_pixel + guiding_pass_albedo;
albedo_out[0] = 0.5f;
albedo_out[1] = 0.5f;
@@ -851,20 +812,21 @@ ccl_gpu_kernel(GPU_KERNEL_BLOCK_NUM_THREADS, GPU_KERNEL_MAX_REGISTERS)
}
ccl_gpu_kernel(GPU_KERNEL_BLOCK_NUM_THREADS, GPU_KERNEL_MAX_REGISTERS)
- kernel_gpu_filter_color_postprocess(float *render_buffer,
- int full_x,
- int full_y,
- int width,
- int height,
- int offset,
- int stride,
- int pass_stride,
- int num_samples,
- int pass_noisy,
- int pass_denoised,
- int pass_sample_count,
- int num_components,
- bool use_compositing)
+ ccl_gpu_kernel_signature(filter_color_postprocess,
+ ccl_global float *render_buffer,
+ int full_x,
+ int full_y,
+ int width,
+ int height,
+ int offset,
+ int stride,
+ int pass_stride,
+ int num_samples,
+ int pass_noisy,
+ int pass_denoised,
+ int pass_sample_count,
+ int num_components,
+ bool use_compositing)
{
const int work_index = ccl_gpu_global_id_x();
const int y = work_index / width;
@@ -875,7 +837,7 @@ ccl_gpu_kernel(GPU_KERNEL_BLOCK_NUM_THREADS, GPU_KERNEL_MAX_REGISTERS)
}
const uint64_t render_pixel_index = offset + (x + full_x) + (y + full_y) * stride;
- float *buffer = render_buffer + render_pixel_index * pass_stride;
+ ccl_global float *buffer = render_buffer + render_pixel_index * pass_stride;
float pixel_scale;
if (pass_sample_count == PASS_UNUSED) {
@@ -885,7 +847,7 @@ ccl_gpu_kernel(GPU_KERNEL_BLOCK_NUM_THREADS, GPU_KERNEL_MAX_REGISTERS)
pixel_scale = __float_as_uint(buffer[pass_sample_count]);
}
- float *denoised_pixel = buffer + pass_denoised;
+ ccl_global float *denoised_pixel = buffer + pass_denoised;
denoised_pixel[0] *= pixel_scale;
denoised_pixel[1] *= pixel_scale;
@@ -898,7 +860,7 @@ ccl_gpu_kernel(GPU_KERNEL_BLOCK_NUM_THREADS, GPU_KERNEL_MAX_REGISTERS)
/* Currently compositing passes are either 3-component (derived by dividing light passes)
* or do not have transparency (shadow catcher). Implicitly rely on this logic, as it
* simplifies logic and avoids extra memory allocation. */
- const float *noisy_pixel = buffer + pass_noisy;
+ ccl_global const float *noisy_pixel = buffer + pass_noisy;
denoised_pixel[3] = noisy_pixel[3];
}
else {
@@ -914,21 +876,22 @@ ccl_gpu_kernel(GPU_KERNEL_BLOCK_NUM_THREADS, GPU_KERNEL_MAX_REGISTERS)
*/
ccl_gpu_kernel(GPU_KERNEL_BLOCK_NUM_THREADS, GPU_KERNEL_MAX_REGISTERS)
- kernel_gpu_integrator_shadow_catcher_count_possible_splits(int num_states,
- uint *num_possible_splits)
+ ccl_gpu_kernel_signature(integrator_shadow_catcher_count_possible_splits,
+ int num_states,
+ ccl_global uint *num_possible_splits)
{
const int state = ccl_gpu_global_id_x();
bool can_split = false;
if (state < num_states) {
- can_split = kernel_shadow_catcher_path_can_split(nullptr, state);
+ can_split = ccl_gpu_kernel_call(kernel_shadow_catcher_path_can_split(nullptr, state));
}
/* NOTE: All threads specified in the mask must execute the intrinsic. */
- const uint can_split_mask = ccl_gpu_ballot(can_split);
+ const auto can_split_mask = ccl_gpu_ballot(can_split);
const int lane_id = ccl_gpu_thread_idx_x % ccl_gpu_warp_size;
if (lane_id == 0) {
- atomic_fetch_and_add_uint32(num_possible_splits, __popc(can_split_mask));
+ atomic_fetch_and_add_uint32(num_possible_splits, ccl_gpu_popc(can_split_mask));
}
}
diff --git a/intern/cycles/kernel/device/gpu/parallel_active_index.h b/intern/cycles/kernel/device/gpu/parallel_active_index.h
index d7416beb783..f667ede2712 100644
--- a/intern/cycles/kernel/device/gpu/parallel_active_index.h
+++ b/intern/cycles/kernel/device/gpu/parallel_active_index.h
@@ -31,10 +31,43 @@ CCL_NAMESPACE_BEGIN
# define GPU_PARALLEL_ACTIVE_INDEX_DEFAULT_BLOCK_SIZE 512
#endif
+#ifdef __KERNEL_METAL__
+struct ActiveIndexContext {
+ ActiveIndexContext(int _thread_index,
+ int _global_index,
+ int _threadgroup_size,
+ int _simdgroup_size,
+ int _simd_lane_index,
+ int _simd_group_index,
+ int _num_simd_groups,
+ threadgroup int *_simdgroup_offset)
+ : thread_index(_thread_index),
+ global_index(_global_index),
+ blocksize(_threadgroup_size),
+ ccl_gpu_warp_size(_simdgroup_size),
+ thread_warp(_simd_lane_index),
+ warp_index(_simd_group_index),
+ num_warps(_num_simd_groups),
+ warp_offset(_simdgroup_offset)
+ {
+ }
+
+ const int thread_index, global_index, blocksize, ccl_gpu_warp_size, thread_warp, warp_index,
+ num_warps;
+ threadgroup int *warp_offset;
+
+ template<uint blocksizeDummy, typename IsActiveOp>
+ void active_index_array(const uint num_states,
+ ccl_global int *indices,
+ ccl_global int *num_indices,
+ IsActiveOp is_active_op)
+ {
+ const uint state_index = global_index;
+#else
template<uint blocksize, typename IsActiveOp>
__device__ void gpu_parallel_active_index_array(const uint num_states,
- int *indices,
- int *num_indices,
+ ccl_global int *indices,
+ ccl_global int *num_indices,
IsActiveOp is_active_op)
{
extern ccl_gpu_shared int warp_offset[];
@@ -45,43 +78,62 @@ __device__ void gpu_parallel_active_index_array(const uint num_states,
const uint warp_index = thread_index / ccl_gpu_warp_size;
const uint num_warps = blocksize / ccl_gpu_warp_size;
- /* Test if state corresponding to this thread is active. */
const uint state_index = ccl_gpu_block_idx_x * blocksize + thread_index;
- const uint is_active = (state_index < num_states) ? is_active_op(state_index) : 0;
+#endif
- /* For each thread within a warp compute how many other active states precede it. */
- const uint thread_mask = 0xFFFFFFFF >> (ccl_gpu_warp_size - thread_warp);
- const uint thread_offset = ccl_gpu_popc(ccl_gpu_ballot(is_active) & thread_mask);
+ /* Test if state corresponding to this thread is active. */
+ const uint is_active = (state_index < num_states) ? is_active_op(state_index) : 0;
- /* Last thread in warp stores number of active states for each warp. */
- if (thread_warp == ccl_gpu_warp_size - 1) {
- warp_offset[warp_index] = thread_offset + is_active;
- }
+ /* For each thread within a warp compute how many other active states precede it. */
+ const uint thread_offset = ccl_gpu_popc(ccl_gpu_ballot(is_active) &
+ ccl_gpu_thread_mask(thread_warp));
- ccl_gpu_syncthreads();
-
- /* Last thread in block converts per-warp sizes to offsets, increments global size of
- * index array and gets offset to write to. */
- if (thread_index == blocksize - 1) {
- /* TODO: parallelize this. */
- int offset = 0;
- for (int i = 0; i < num_warps; i++) {
- int num_active = warp_offset[i];
- warp_offset[i] = offset;
- offset += num_active;
+ /* Last thread in warp stores number of active states for each warp. */
+ if (thread_warp == ccl_gpu_warp_size - 1) {
+ warp_offset[warp_index] = thread_offset + is_active;
}
- const uint block_num_active = warp_offset[warp_index] + thread_offset + is_active;
- warp_offset[num_warps] = atomic_fetch_and_add_uint32(num_indices, block_num_active);
- }
+ ccl_gpu_syncthreads();
+
+ /* Last thread in block converts per-warp sizes to offsets, increments global size of
+ * index array and gets offset to write to. */
+ if (thread_index == blocksize - 1) {
+ /* TODO: parallelize this. */
+ int offset = 0;
+ for (int i = 0; i < num_warps; i++) {
+ int num_active = warp_offset[i];
+ warp_offset[i] = offset;
+ offset += num_active;
+ }
+
+ const uint block_num_active = warp_offset[warp_index] + thread_offset + is_active;
+ warp_offset[num_warps] = atomic_fetch_and_add_uint32(num_indices, block_num_active);
+ }
- ccl_gpu_syncthreads();
+ ccl_gpu_syncthreads();
- /* Write to index array. */
- if (is_active) {
- const uint block_offset = warp_offset[num_warps];
- indices[block_offset + warp_offset[warp_index] + thread_offset] = state_index;
+ /* Write to index array. */
+ if (is_active) {
+ const uint block_offset = warp_offset[num_warps];
+ indices[block_offset + warp_offset[warp_index] + thread_offset] = state_index;
+ }
}
-}
+
+#ifdef __KERNEL_METAL__
+}; /* end class ActiveIndexContext */
+
+/* inject the required thread params into a struct, and redirect to its templated member function
+ */
+# define gpu_parallel_active_index_array \
+ ActiveIndexContext(metal_local_id, \
+ metal_global_id, \
+ metal_local_size, \
+ simdgroup_size, \
+ simd_lane_index, \
+ simd_group_index, \
+ num_simd_groups, \
+ simdgroup_offset) \
+ .active_index_array
+#endif
CCL_NAMESPACE_END
diff --git a/intern/cycles/kernel/device/gpu/parallel_prefix_sum.h b/intern/cycles/kernel/device/gpu/parallel_prefix_sum.h
index 6de3a022569..4bd002c27e4 100644
--- a/intern/cycles/kernel/device/gpu/parallel_prefix_sum.h
+++ b/intern/cycles/kernel/device/gpu/parallel_prefix_sum.h
@@ -33,10 +33,12 @@ CCL_NAMESPACE_BEGIN
# define GPU_PARALLEL_PREFIX_SUM_DEFAULT_BLOCK_SIZE 512
#endif
-template<uint blocksize>
-__device__ void gpu_parallel_prefix_sum(int *counter, int *prefix_sum, const int num_values)
+__device__ void gpu_parallel_prefix_sum(const int global_id,
+ ccl_global int *counter,
+ ccl_global int *prefix_sum,
+ const int num_values)
{
- if (!(ccl_gpu_block_idx_x == 0 && ccl_gpu_thread_idx_x == 0)) {
+ if (global_id != 0) {
return;
}
diff --git a/intern/cycles/kernel/device/gpu/parallel_sorted_index.h b/intern/cycles/kernel/device/gpu/parallel_sorted_index.h
index c06d7be444f..c092e2a21ee 100644
--- a/intern/cycles/kernel/device/gpu/parallel_sorted_index.h
+++ b/intern/cycles/kernel/device/gpu/parallel_sorted_index.h
@@ -33,16 +33,16 @@ CCL_NAMESPACE_BEGIN
#endif
#define GPU_PARALLEL_SORTED_INDEX_INACTIVE_KEY (~0)
-template<uint blocksize, typename GetKeyOp>
-__device__ void gpu_parallel_sorted_index_array(const uint num_states,
+template<typename GetKeyOp>
+__device__ void gpu_parallel_sorted_index_array(const uint state_index,
+ const uint num_states,
const int num_states_limit,
- int *indices,
- int *num_indices,
- int *key_counter,
- int *key_prefix_sum,
+ ccl_global int *indices,
+ ccl_global int *num_indices,
+ ccl_global int *key_counter,
+ ccl_global int *key_prefix_sum,
GetKeyOp get_key_op)
{
- const uint state_index = ccl_gpu_block_idx_x * blocksize + ccl_gpu_thread_idx_x;
const int key = (state_index < num_states) ? get_key_op(state_index) :
GPU_PARALLEL_SORTED_INDEX_INACTIVE_KEY;
diff --git a/intern/cycles/kernel/device/hip/compat.h b/intern/cycles/kernel/device/hip/compat.h
index 282c3eca641..fb07602539b 100644
--- a/intern/cycles/kernel/device/hip/compat.h
+++ b/intern/cycles/kernel/device/hip/compat.h
@@ -74,6 +74,7 @@ typedef unsigned long long uint64_t;
#define ccl_gpu_block_idx_x (blockIdx.x)
#define ccl_gpu_grid_dim_x (gridDim.x)
#define ccl_gpu_warp_size (warpSize)
+#define ccl_gpu_thread_mask(thread_warp) uint(0xFFFFFFFF >> (ccl_gpu_warp_size - thread_warp))
#define ccl_gpu_global_id_x() (ccl_gpu_block_idx_x * ccl_gpu_block_dim_x + ccl_gpu_thread_idx_x)
#define ccl_gpu_global_size_x() (ccl_gpu_grid_dim_x * ccl_gpu_block_dim_x)
diff --git a/intern/cycles/kernel/device/hip/config.h b/intern/cycles/kernel/device/hip/config.h
index 2fde0d46015..7ec744d8ad2 100644
--- a/intern/cycles/kernel/device/hip/config.h
+++ b/intern/cycles/kernel/device/hip/config.h
@@ -35,12 +35,29 @@
/* Compute number of threads per block and minimum blocks per multiprocessor
* given the maximum number of registers per thread. */
-
#define ccl_gpu_kernel(block_num_threads, thread_num_registers) \
extern "C" __global__ void __launch_bounds__(block_num_threads, \
GPU_MULTIPRESSOR_MAX_REGISTERS / \
(block_num_threads * thread_num_registers))
+#define ccl_gpu_kernel_threads(block_num_threads) \
+ extern "C" __global__ void __launch_bounds__(block_num_threads)
+
+#define ccl_gpu_kernel_signature(name, ...) kernel_gpu_##name(__VA_ARGS__)
+
+#define ccl_gpu_kernel_call(x) x
+
+/* Define a function object where "func" is the lambda body, and additional parameters are used to
+ * specify captured state */
+#define ccl_gpu_kernel_lambda(func, ...) \
+ struct KernelLambda { \
+ __VA_ARGS__; \
+ __device__ int operator()(const int state) \
+ { \
+ return (func); \
+ } \
+ } ccl_gpu_kernel_lambda_pass
+
/* sanity checks */
#if GPU_KERNEL_BLOCK_NUM_THREADS > GPU_BLOCK_MAX_THREADS
diff --git a/intern/cycles/kernel/device/metal/compat.h b/intern/cycles/kernel/device/metal/compat.h
index 77cea30914c..4a2c39d90fd 100644
--- a/intern/cycles/kernel/device/metal/compat.h
+++ b/intern/cycles/kernel/device/metal/compat.h
@@ -58,6 +58,123 @@ using namespace metal;
#define kernel_assert(cond)
+#define ccl_gpu_global_id_x() metal_global_id
+#define ccl_gpu_warp_size simdgroup_size
+#define ccl_gpu_thread_idx_x simd_group_index
+#define ccl_gpu_thread_mask(thread_warp) uint64_t((1ull << thread_warp) - 1)
+
+#define ccl_gpu_ballot(predicate) ((uint64_t)((simd_vote::vote_t)simd_ballot(predicate)))
+#define ccl_gpu_popc(x) popcount(x)
+
+// clang-format off
+
+/* kernel.h adapters */
+
+#define ccl_gpu_kernel(block_num_threads, thread_num_registers)
+#define ccl_gpu_kernel_threads(block_num_threads)
+
+/* Convert a comma-separated list into a semicolon-separated list
+ * (so that we can generate a struct based on kernel entry-point parameters). */
+#define FN0()
+#define FN1(p1) p1;
+#define FN2(p1, p2) p1; p2;
+#define FN3(p1, p2, p3) p1; p2; p3;
+#define FN4(p1, p2, p3, p4) p1; p2; p3; p4;
+#define FN5(p1, p2, p3, p4, p5) p1; p2; p3; p4; p5;
+#define FN6(p1, p2, p3, p4, p5, p6) p1; p2; p3; p4; p5; p6;
+#define FN7(p1, p2, p3, p4, p5, p6, p7) p1; p2; p3; p4; p5; p6; p7;
+#define FN8(p1, p2, p3, p4, p5, p6, p7, p8) p1; p2; p3; p4; p5; p6; p7; p8;
+#define FN9(p1, p2, p3, p4, p5, p6, p7, p8, p9) p1; p2; p3; p4; p5; p6; p7; p8; p9;
+#define FN10(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10) p1; p2; p3; p4; p5; p6; p7; p8; p9; p10;
+#define FN11(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11) p1; p2; p3; p4; p5; p6; p7; p8; p9; p10; p11;
+#define FN12(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12) p1; p2; p3; p4; p5; p6; p7; p8; p9; p10; p11; p12;
+#define FN13(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13) p1; p2; p3; p4; p5; p6; p7; p8; p9; p10; p11; p12; p13;
+#define FN14(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14) p1; p2; p3; p4; p5; p6; p7; p8; p9; p10; p11; p12; p13; p14;
+#define FN15(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15) p1; p2; p3; p4; p5; p6; p7; p8; p9; p10; p11; p12; p13; p14; p15;
+#define FN16(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16) p1; p2; p3; p4; p5; p6; p7; p8; p9; p10; p11; p12; p13; p14; p15; p16;
+#define GET_LAST_ARG(p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, ...) p16
+#define PARAMS_MAKER(...) GET_LAST_ARG(__VA_ARGS__, FN16, FN15, FN14, FN13, FN12, FN11, FN10, FN9, FN8, FN7, FN6, FN5, FN4, FN3, FN2, FN1, FN0)
+
+/* Generate a struct containing the entry-point parameters and a "run"
+ * method which can access them implicitly via this-> */
+#define ccl_gpu_kernel_signature(name, ...) \
+struct kernel_gpu_##name \
+{ \
+ PARAMS_MAKER(__VA_ARGS__)(__VA_ARGS__) \
+ void run(thread MetalKernelContext& context, \
+ threadgroup int *simdgroup_offset, \
+ const uint metal_global_id, \
+ const ushort metal_local_id, \
+ const ushort metal_local_size, \
+ uint simdgroup_size, \
+ uint simd_lane_index, \
+ uint simd_group_index, \
+ uint num_simd_groups) ccl_global const; \
+}; \
+kernel void kernel_metal_##name(device const kernel_gpu_##name *params_struct, \
+ constant KernelParamsMetal &ccl_restrict _launch_params_metal, \
+ constant MetalAncillaries *_metal_ancillaries, \
+ threadgroup int *simdgroup_offset[[ threadgroup(0) ]], \
+ const uint metal_global_id [[thread_position_in_grid]], \
+ const ushort metal_local_id [[thread_position_in_threadgroup]], \
+ const ushort metal_local_size [[threads_per_threadgroup]], \
+ uint simdgroup_size [[threads_per_simdgroup]], \
+ uint simd_lane_index [[thread_index_in_simdgroup]], \
+ uint simd_group_index [[simdgroup_index_in_threadgroup]], \
+ uint num_simd_groups [[simdgroups_per_threadgroup]]) { \
+ MetalKernelContext context(_launch_params_metal, _metal_ancillaries); \
+ INIT_DEBUG_BUFFER \
+ params_struct->run(context, simdgroup_offset, metal_global_id, metal_local_id, metal_local_size, simdgroup_size, simd_lane_index, simd_group_index, num_simd_groups); \
+} \
+void kernel_gpu_##name::run(thread MetalKernelContext& context, \
+ threadgroup int *simdgroup_offset, \
+ const uint metal_global_id, \
+ const ushort metal_local_id, \
+ const ushort metal_local_size, \
+ uint simdgroup_size, \
+ uint simd_lane_index, \
+ uint simd_group_index, \
+ uint num_simd_groups) ccl_global const
+
+#define ccl_gpu_kernel_call(x) context.x
+
+/* define a function object where "func" is the lambda body, and additional parameters are used to specify captured state */
+#define ccl_gpu_kernel_lambda(func, ...) \
+ struct KernelLambda \
+ { \
+ KernelLambda(ccl_private MetalKernelContext &_context) : context(_context) {} \
+ ccl_private MetalKernelContext &context; \
+ __VA_ARGS__; \
+ int operator()(const int state) const { return (func); } \
+ } ccl_gpu_kernel_lambda_pass(context)
+
+// clang-format on
+
+/* volumetric lambda functions - use function objects for lambda-like functionality */
+#define VOLUME_READ_LAMBDA(function_call) \
+ struct FnObjectRead { \
+ KernelGlobals kg; \
+ ccl_private MetalKernelContext *context; \
+ int state; \
+\
+ VolumeStack operator()(const int i) const \
+ { \
+ return context->function_call; \
+ } \
+ } volume_read_lambda_pass{kg, this, state};
+
+#define VOLUME_WRITE_LAMBDA(function_call) \
+ struct FnObjectWrite { \
+ KernelGlobals kg; \
+ ccl_private MetalKernelContext *context; \
+ int state; \
+\
+ void operator()(const int i, VolumeStack entry) const \
+ { \
+ context->function_call; \
+ } \
+ } volume_write_lambda_pass{kg, this, state};
+
/* make_type definitions with Metal style element initializers */
#ifdef make_float2
# undef make_float2
@@ -124,3 +241,38 @@ using namespace metal;
#define logf(x) trigmode::log(float(x))
#define NULL 0
+
+/* texture bindings and sampler setup */
+
+struct Texture2DParamsMetal {
+ texture2d<float, access::sample> tex;
+};
+struct Texture3DParamsMetal {
+ texture3d<float, access::sample> tex;
+};
+
+struct MetalAncillaries {
+ device Texture2DParamsMetal *textures_2d;
+ device Texture3DParamsMetal *textures_3d;
+};
+
+enum SamplerType {
+ SamplerFilterNearest_AddressRepeat,
+ SamplerFilterNearest_AddressClampEdge,
+ SamplerFilterNearest_AddressClampZero,
+
+ SamplerFilterLinear_AddressRepeat,
+ SamplerFilterLinear_AddressClampEdge,
+ SamplerFilterLinear_AddressClampZero,
+
+ SamplerCount
+};
+
+constant constexpr array<sampler, SamplerCount> metal_samplers = {
+ sampler(address::repeat, filter::nearest),
+ sampler(address::clamp_to_edge, filter::nearest),
+ sampler(address::clamp_to_zero, filter::nearest),
+ sampler(address::repeat, filter::linear),
+ sampler(address::clamp_to_edge, filter::linear),
+ sampler(address::clamp_to_zero, filter::linear),
+};
diff --git a/intern/cycles/kernel/device/metal/context_begin.h b/intern/cycles/kernel/device/metal/context_begin.h
new file mode 100644
index 00000000000..8c9e1c54077
--- /dev/null
+++ b/intern/cycles/kernel/device/metal/context_begin.h
@@ -0,0 +1,79 @@
+/*
+ * Copyright 2021 Blender Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// clang-format off
+
+/* Open the Metal kernel context class
+ * Necessary to access resource bindings */
+class MetalKernelContext {
+ public:
+ constant KernelParamsMetal &launch_params_metal;
+ constant MetalAncillaries *metal_ancillaries;
+
+ MetalKernelContext(constant KernelParamsMetal &_launch_params_metal, constant MetalAncillaries * _metal_ancillaries)
+ : launch_params_metal(_launch_params_metal), metal_ancillaries(_metal_ancillaries)
+ {}
+
+ /* texture fetch adapter functions */
+ typedef uint64_t ccl_gpu_tex_object;
+
+ template<typename T>
+ inline __attribute__((__always_inline__))
+ T ccl_gpu_tex_object_read_2D(ccl_gpu_tex_object tex, float x, float y) const {
+ kernel_assert(0);
+ return 0;
+ }
+ template<typename T>
+ inline __attribute__((__always_inline__))
+ T ccl_gpu_tex_object_read_3D(ccl_gpu_tex_object tex, float x, float y, float z) const {
+ kernel_assert(0);
+ return 0;
+ }
+
+ // texture2d
+ template<>
+ inline __attribute__((__always_inline__))
+ float4 ccl_gpu_tex_object_read_2D(ccl_gpu_tex_object tex, float x, float y) const {
+ const uint tid(tex);
+ const uint sid(tex >> 32);
+ return metal_ancillaries->textures_2d[tid].tex.sample(metal_samplers[sid], float2(x, y));
+ }
+ template<>
+ inline __attribute__((__always_inline__))
+ float ccl_gpu_tex_object_read_2D(ccl_gpu_tex_object tex, float x, float y) const {
+ const uint tid(tex);
+ const uint sid(tex >> 32);
+ return metal_ancillaries->textures_2d[tid].tex.sample(metal_samplers[sid], float2(x, y)).x;
+ }
+
+ // texture3d
+ template<>
+ inline __attribute__((__always_inline__))
+ float4 ccl_gpu_tex_object_read_3D(ccl_gpu_tex_object tex, float x, float y, float z) const {
+ const uint tid(tex);
+ const uint sid(tex >> 32);
+ return metal_ancillaries->textures_3d[tid].tex.sample(metal_samplers[sid], float3(x, y, z));
+ }
+ template<>
+ inline __attribute__((__always_inline__))
+ float ccl_gpu_tex_object_read_3D(ccl_gpu_tex_object tex, float x, float y, float z) const {
+ const uint tid(tex);
+ const uint sid(tex >> 32);
+ return metal_ancillaries->textures_3d[tid].tex.sample(metal_samplers[sid], float3(x, y, z)).x;
+ }
+# include "kernel/device/gpu/image.h"
+
+ // clang-format on
diff --git a/intern/cycles/kernel/device/metal/context_end.h b/intern/cycles/kernel/device/metal/context_end.h
new file mode 100644
index 00000000000..e700f294440
--- /dev/null
+++ b/intern/cycles/kernel/device/metal/context_end.h
@@ -0,0 +1,23 @@
+/*
+ * Copyright 2021 Blender Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+}
+; /* end of MetalKernelContext class definition */
+
+/* Silently redirect into the MetalKernelContext instance */
+/* NOTE: These macros will need maintaining as entry-points change. */
+
+#undef kernel_integrator_state
+#define kernel_integrator_state context.launch_params_metal.__integrator_state
diff --git a/intern/cycles/kernel/device/metal/globals.h b/intern/cycles/kernel/device/metal/globals.h
new file mode 100644
index 00000000000..b4963518b63
--- /dev/null
+++ b/intern/cycles/kernel/device/metal/globals.h
@@ -0,0 +1,51 @@
+/*
+ * Copyright 2021 Blender Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/* Constant Globals */
+
+#include "kernel/types.h"
+#include "kernel/util/profiling.h"
+
+#include "kernel/integrator/state.h"
+
+CCL_NAMESPACE_BEGIN
+
+typedef struct KernelParamsMetal {
+
+#define KERNEL_TEX(type, name) ccl_constant type *name;
+#include "kernel/textures.h"
+#undef KERNEL_TEX
+
+ const IntegratorStateGPU __integrator_state;
+ const KernelData data;
+
+} KernelParamsMetal;
+
+typedef struct KernelGlobalsGPU {
+ int unused[1];
+} KernelGlobalsGPU;
+
+typedef ccl_global const KernelGlobalsGPU *ccl_restrict KernelGlobals;
+
+#define kernel_data launch_params_metal.data
+#define kernel_integrator_state launch_params_metal.__integrator_state
+
+/* data lookup defines */
+
+#define kernel_tex_fetch(tex, index) launch_params_metal.tex[index]
+#define kernel_tex_array(tex) launch_params_metal.tex
+
+CCL_NAMESPACE_END
diff --git a/intern/cycles/kernel/device/metal/kernel.metal b/intern/cycles/kernel/device/metal/kernel.metal
new file mode 100644
index 00000000000..feca20ff475
--- /dev/null
+++ b/intern/cycles/kernel/device/metal/kernel.metal
@@ -0,0 +1,25 @@
+/*
+ * Copyright 2021 Blender Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/* Metal kernel entry points */
+
+// clang-format off
+
+#include "kernel/device/metal/compat.h"
+#include "kernel/device/metal/globals.h"
+#include "kernel/device/gpu/kernel.h"
+
+// clang-format on \ No newline at end of file
diff --git a/intern/cycles/kernel/device/optix/compat.h b/intern/cycles/kernel/device/optix/compat.h
index 835e4621d47..482b921a1a8 100644
--- a/intern/cycles/kernel/device/optix/compat.h
+++ b/intern/cycles/kernel/device/optix/compat.h
@@ -76,6 +76,7 @@ typedef unsigned long long uint64_t;
#define ccl_gpu_block_idx_x (blockIdx.x)
#define ccl_gpu_grid_dim_x (gridDim.x)
#define ccl_gpu_warp_size (warpSize)
+#define ccl_gpu_thread_mask(thread_warp) uint(0xFFFFFFFF >> (ccl_gpu_warp_size - thread_warp))
#define ccl_gpu_global_id_x() (ccl_gpu_block_idx_x * ccl_gpu_block_dim_x + ccl_gpu_thread_idx_x)
#define ccl_gpu_global_size_x() (ccl_gpu_grid_dim_x * ccl_gpu_block_dim_x)
diff --git a/intern/cycles/kernel/film/accumulate.h b/intern/cycles/kernel/film/accumulate.h
index ce338936376..6bdf1f2f3a1 100644
--- a/intern/cycles/kernel/film/accumulate.h
+++ b/intern/cycles/kernel/film/accumulate.h
@@ -151,7 +151,8 @@ ccl_device_forceinline ccl_global float *kernel_accum_pixel_render_buffer(
ccl_device_inline int kernel_accum_sample(KernelGlobals kg,
ConstIntegratorState state,
ccl_global float *ccl_restrict render_buffer,
- int sample)
+ int sample,
+ int sample_offset)
{
if (kernel_data.film.pass_sample_count == PASS_UNUSED) {
return sample;
@@ -159,7 +160,8 @@ ccl_device_inline int kernel_accum_sample(KernelGlobals kg,
ccl_global float *buffer = kernel_accum_pixel_render_buffer(kg, state, render_buffer);
- return atomic_fetch_and_add_uint32((uint *)(buffer) + kernel_data.film.pass_sample_count, 1);
+ return atomic_fetch_and_add_uint32((uint *)(buffer) + kernel_data.film.pass_sample_count, 1) +
+ sample_offset;
}
ccl_device void kernel_accum_adaptive_buffer(KernelGlobals kg,
diff --git a/intern/cycles/kernel/integrator/init_from_bake.h b/intern/cycles/kernel/integrator/init_from_bake.h
index 4e30563e21b..df1c7fd07e7 100644
--- a/intern/cycles/kernel/integrator/init_from_bake.h
+++ b/intern/cycles/kernel/integrator/init_from_bake.h
@@ -65,7 +65,8 @@ ccl_device bool integrator_init_from_bake(KernelGlobals kg,
}
/* Always count the sample, even if the camera sample will reject the ray. */
- const int sample = kernel_accum_sample(kg, state, render_buffer, scheduled_sample);
+ const int sample = kernel_accum_sample(
+ kg, state, render_buffer, scheduled_sample, tile->sample_offset);
/* Setup render buffers. */
const int index = INTEGRATOR_STATE(state, path, render_pixel_index);
diff --git a/intern/cycles/kernel/integrator/init_from_camera.h b/intern/cycles/kernel/integrator/init_from_camera.h
index f0ba77bd9a6..59dd1a9fa75 100644
--- a/intern/cycles/kernel/integrator/init_from_camera.h
+++ b/intern/cycles/kernel/integrator/init_from_camera.h
@@ -89,7 +89,8 @@ ccl_device bool integrator_init_from_camera(KernelGlobals kg,
* This logic allows to both count actual number of samples per pixel, and to add samples to this
* pixel after it was converged and samples were added somewhere else (in which case the
* `scheduled_sample` will be different from actual number of samples in this pixel). */
- const int sample = kernel_accum_sample(kg, state, render_buffer, scheduled_sample);
+ const int sample = kernel_accum_sample(
+ kg, state, render_buffer, scheduled_sample, tile->sample_offset);
/* Initialize random number seed for path. */
const uint rng_hash = path_rng_hash_init(kg, sample, x, y);
diff --git a/intern/cycles/kernel/integrator/shade_shadow.h b/intern/cycles/kernel/integrator/shade_shadow.h
index 1de890aae29..a68fcaa7a64 100644
--- a/intern/cycles/kernel/integrator/shade_shadow.h
+++ b/intern/cycles/kernel/integrator/shade_shadow.h
@@ -95,8 +95,8 @@ ccl_device_inline void integrate_transparent_volume_shadow(KernelGlobals kg,
shader_setup_from_volume(kg, shadow_sd, &ray);
- const float step_size = volume_stack_step_size(
- kg, [=](const int i) { return integrator_state_read_shadow_volume_stack(state, i); });
+ VOLUME_READ_LAMBDA(integrator_state_read_shadow_volume_stack(state, i));
+ const float step_size = volume_stack_step_size(kg, volume_read_lambda_pass);
volume_shadow_heterogeneous(kg, state, &ray, shadow_sd, throughput, step_size);
}
diff --git a/intern/cycles/kernel/integrator/shade_volume.h b/intern/cycles/kernel/integrator/shade_volume.h
index f42614cc87f..c5a80eb336f 100644
--- a/intern/cycles/kernel/integrator/shade_volume.h
+++ b/intern/cycles/kernel/integrator/shade_volume.h
@@ -78,9 +78,8 @@ ccl_device_inline bool shadow_volume_shader_sample(KernelGlobals kg,
ccl_private ShaderData *ccl_restrict sd,
ccl_private float3 *ccl_restrict extinction)
{
- shader_eval_volume<true>(kg, state, sd, PATH_RAY_SHADOW, [=](const int i) {
- return integrator_state_read_shadow_volume_stack(state, i);
- });
+ VOLUME_READ_LAMBDA(integrator_state_read_shadow_volume_stack(state, i))
+ shader_eval_volume<true>(kg, state, sd, PATH_RAY_SHADOW, volume_read_lambda_pass);
if (!(sd->flag & SD_EXTINCTION)) {
return false;
@@ -98,9 +97,8 @@ ccl_device_inline bool volume_shader_sample(KernelGlobals kg,
ccl_private VolumeShaderCoefficients *coeff)
{
const uint32_t path_flag = INTEGRATOR_STATE(state, path, flag);
- shader_eval_volume<false>(kg, state, sd, path_flag, [=](const int i) {
- return integrator_state_read_volume_stack(state, i);
- });
+ VOLUME_READ_LAMBDA(integrator_state_read_volume_stack(state, i))
+ shader_eval_volume<false>(kg, state, sd, path_flag, volume_read_lambda_pass);
if (!(sd->flag & (SD_EXTINCTION | SD_SCATTER | SD_EMISSION))) {
return false;
@@ -921,8 +919,8 @@ ccl_device VolumeIntegrateEvent volume_integrate(KernelGlobals kg,
VOLUME_SAMPLE_DISTANCE;
/* Step through volume. */
- const float step_size = volume_stack_step_size(
- kg, [=](const int i) { return integrator_state_read_volume_stack(state, i); });
+ VOLUME_READ_LAMBDA(integrator_state_read_volume_stack(state, i))
+ const float step_size = volume_stack_step_size(kg, volume_read_lambda_pass);
/* TODO: expensive to zero closures? */
VolumeIntegrateResult result = {};
diff --git a/intern/cycles/kernel/integrator/volume_stack.h b/intern/cycles/kernel/integrator/volume_stack.h
index cf69826ffff..ea3fa901e2d 100644
--- a/intern/cycles/kernel/integrator/volume_stack.h
+++ b/intern/cycles/kernel/integrator/volume_stack.h
@@ -18,6 +18,14 @@
CCL_NAMESPACE_BEGIN
+/* Volumetric read/write lambda functions - default implementations */
+#ifndef VOLUME_READ_LAMBDA
+# define VOLUME_READ_LAMBDA(function_call) \
+ auto volume_read_lambda_pass = [=](const int i) { return function_call; };
+# define VOLUME_WRITE_LAMBDA(function_call) \
+ auto volume_write_lambda_pass = [=](const int i, VolumeStack entry) { function_call; };
+#endif
+
/* Volume Stack
*
* This is an array of object/shared ID's that the current segment of the path
@@ -88,26 +96,18 @@ ccl_device void volume_stack_enter_exit(KernelGlobals kg,
IntegratorState state,
ccl_private const ShaderData *sd)
{
- volume_stack_enter_exit(
- kg,
- sd,
- [=](const int i) { return integrator_state_read_volume_stack(state, i); },
- [=](const int i, const VolumeStack entry) {
- integrator_state_write_volume_stack(state, i, entry);
- });
+ VOLUME_READ_LAMBDA(integrator_state_read_volume_stack(state, i))
+ VOLUME_WRITE_LAMBDA(integrator_state_write_volume_stack(state, i, entry))
+ volume_stack_enter_exit(kg, sd, volume_read_lambda_pass, volume_write_lambda_pass);
}
ccl_device void shadow_volume_stack_enter_exit(KernelGlobals kg,
IntegratorShadowState state,
ccl_private const ShaderData *sd)
{
- volume_stack_enter_exit(
- kg,
- sd,
- [=](const int i) { return integrator_state_read_shadow_volume_stack(state, i); },
- [=](const int i, const VolumeStack entry) {
- integrator_state_write_shadow_volume_stack(state, i, entry);
- });
+ VOLUME_READ_LAMBDA(integrator_state_read_shadow_volume_stack(state, i))
+ VOLUME_WRITE_LAMBDA(integrator_state_write_shadow_volume_stack(state, i, entry))
+ volume_stack_enter_exit(kg, sd, volume_read_lambda_pass, volume_write_lambda_pass);
}
/* Clean stack after the last bounce.
diff --git a/intern/cycles/kernel/types.h b/intern/cycles/kernel/types.h
index cae514d4dbd..74b34524786 100644
--- a/intern/cycles/kernel/types.h
+++ b/intern/cycles/kernel/types.h
@@ -36,13 +36,6 @@
# define __KERNEL_CPU__
#endif
-/* TODO(sergey): This is only to make it possible to include this header
- * from outside of the kernel. but this could be done somewhat cleaner?
- */
-#ifndef ccl_addr_space
-# define ccl_addr_space
-#endif
-
CCL_NAMESPACE_BEGIN
/* Constants */
@@ -1425,6 +1418,7 @@ typedef struct KernelWorkTile {
uint start_sample;
uint num_samples;
+ uint sample_offset;
int offset;
uint stride;
diff --git a/intern/cycles/scene/image.cpp b/intern/cycles/scene/image.cpp
index 80091e01b8c..8bb2d87fd1e 100644
--- a/intern/cycles/scene/image.cpp
+++ b/intern/cycles/scene/image.cpp
@@ -303,7 +303,6 @@ ImageManager::ImageManager(const DeviceInfo &info)
animation_frame = 0;
/* Set image limits */
- features.has_half_float = info.has_half_images;
features.has_nanovdb = info.has_nanovdb;
}
@@ -357,8 +356,6 @@ void ImageManager::load_image_metadata(Image *img)
metadata.detect_colorspace();
- assert(features.has_half_float ||
- (metadata.type != IMAGE_DATA_TYPE_HALF4 && metadata.type != IMAGE_DATA_TYPE_HALF));
assert(features.has_nanovdb || (metadata.type != IMAGE_DATA_TYPE_NANOVDB_FLOAT ||
metadata.type != IMAGE_DATA_TYPE_NANOVDB_FLOAT3));
diff --git a/intern/cycles/scene/image.h b/intern/cycles/scene/image.h
index 6447b028ebf..7cf09dd6d8f 100644
--- a/intern/cycles/scene/image.h
+++ b/intern/cycles/scene/image.h
@@ -100,7 +100,6 @@ class ImageMetaData {
/* Information about supported features that Image loaders can use. */
class ImageDeviceFeatures {
public:
- bool has_half_float;
bool has_nanovdb;
};
diff --git a/intern/cycles/scene/image_oiio.cpp b/intern/cycles/scene/image_oiio.cpp
index feafae035a1..4cea7fbfb01 100644
--- a/intern/cycles/scene/image_oiio.cpp
+++ b/intern/cycles/scene/image_oiio.cpp
@@ -30,7 +30,8 @@ OIIOImageLoader::~OIIOImageLoader()
{
}
-bool OIIOImageLoader::load_metadata(const ImageDeviceFeatures &features, ImageMetaData &metadata)
+bool OIIOImageLoader::load_metadata(const ImageDeviceFeatures & /*features*/,
+ ImageMetaData &metadata)
{
/* Perform preliminary checks, with meaningful logging. */
if (!path_exists(filepath.string())) {
@@ -76,7 +77,7 @@ bool OIIOImageLoader::load_metadata(const ImageDeviceFeatures &features, ImageMe
}
/* check if it's half float */
- if (spec.format == TypeDesc::HALF && features.has_half_float) {
+ if (spec.format == TypeDesc::HALF) {
is_half = true;
}
diff --git a/intern/cycles/session/session.cpp b/intern/cycles/session/session.cpp
index 65c46d0dd3c..aa58a039ed1 100644
--- a/intern/cycles/session/session.cpp
+++ b/intern/cycles/session/session.cpp
@@ -262,6 +262,7 @@ RenderWork Session::run_update_for_next_iteration()
}
render_scheduler_.set_num_samples(params.samples);
+ render_scheduler_.set_start_sample(params.sample_offset);
render_scheduler_.set_time_limit(params.time_limit);
while (have_tiles) {
@@ -397,7 +398,7 @@ void Session::do_delayed_reset()
/* Tile and work scheduling. */
tile_manager_.reset_scheduling(buffer_params_, get_effective_tile_size());
- render_scheduler_.reset(buffer_params_, params.samples);
+ render_scheduler_.reset(buffer_params_, params.samples, params.sample_offset);
/* Passes. */
/* When multiple tiles are used SAMPLE_COUNT pass is used to keep track of possible partial
diff --git a/intern/cycles/session/session.h b/intern/cycles/session/session.h
index 1ec0c6e9bb1..3f73593f008 100644
--- a/intern/cycles/session/session.h
+++ b/intern/cycles/session/session.h
@@ -54,6 +54,7 @@ class SessionParams {
bool experimental;
int samples;
+ int sample_offset;
int pixel_size;
int threads;
@@ -75,6 +76,7 @@ class SessionParams {
experimental = false;
samples = 1024;
+ sample_offset = 0;
pixel_size = 1;
threads = 0;
time_limit = 0.0;
diff --git a/intern/ghost/GHOST_C-api.h b/intern/ghost/GHOST_C-api.h
index 784febe8581..98094cc0669 100644
--- a/intern/ghost/GHOST_C-api.h
+++ b/intern/ghost/GHOST_C-api.h
@@ -729,13 +729,6 @@ extern GHOST_TSuccess GHOST_ReleaseOpenGLContext(GHOST_ContextHandle contexthand
extern unsigned int GHOST_GetContextDefaultOpenGLFramebuffer(GHOST_ContextHandle contexthandle);
/**
- * Returns whether a context is rendered upside down compared to OpenGL. This only needs to be
- * called if there's a non-OpenGL context, which is really the exception.
- * So generally, this does not need to be called.
- */
-extern int GHOST_isUpsideDownContext(GHOST_ContextHandle contexthandle);
-
-/**
* Get the OpenGL frame-buffer handle that serves as a default frame-buffer.
*/
extern unsigned int GHOST_GetDefaultOpenGLFramebuffer(GHOST_WindowHandle windwHandle);
diff --git a/intern/ghost/GHOST_Types.h b/intern/ghost/GHOST_Types.h
index 2c8014a08cc..ce0185bc7d0 100644
--- a/intern/ghost/GHOST_Types.h
+++ b/intern/ghost/GHOST_Types.h
@@ -654,8 +654,8 @@ enum {
GHOST_kXrContextDebug = (1 << 0),
GHOST_kXrContextDebugTime = (1 << 1),
# ifdef WIN32
- /* Needed to avoid issues with the SteamVR OpenGL graphics binding (use DirectX fallback
- instead). */
+ /* Needed to avoid issues with the SteamVR OpenGL graphics binding
+ * (use DirectX fallback instead). */
GHOST_kXrContextGpuNVIDIA = (1 << 2),
# endif
};
diff --git a/intern/ghost/intern/GHOST_SystemCocoa.mm b/intern/ghost/intern/GHOST_SystemCocoa.mm
index 204bbdaec50..b92c3e73a88 100644
--- a/intern/ghost/intern/GHOST_SystemCocoa.mm
+++ b/intern/ghost/intern/GHOST_SystemCocoa.mm
@@ -1245,7 +1245,7 @@ GHOST_TSuccess GHOST_SystemCocoa::handleDraggingEvent(GHOST_TEventType eventType
/* Convert the image in a RGBA 32bit format */
/* As Core Graphics does not support contexts with non premutliplied alpha,
- we need to get alpha key values in a separate batch */
+ * we need to get alpha key values in a separate batch */
/* First get RGB values w/o Alpha to avoid pre-multiplication,
* 32bit but last byte is unused */
@@ -1479,8 +1479,8 @@ GHOST_TSuccess GHOST_SystemCocoa::handleMouseEvent(void *eventPtr)
CocoaWindow *cocoawindow;
/* [event window] returns other windows if mouse-over, that's OSX input standard
- however, if mouse exits window(s), the windows become inactive, until you click.
- We then fall back to the active window from ghost */
+ * however, if mouse exits window(s), the windows become inactive, until you click.
+ * We then fall back to the active window from ghost. */
window = (GHOST_WindowCocoa *)m_windowManager->getWindowAssociatedWithOSWindow(
(void *)[event window]);
if (!window) {
diff --git a/intern/ghost/intern/GHOST_XrAction.cpp b/intern/ghost/intern/GHOST_XrAction.cpp
index 704b1ce9fac..f51f98c9b3d 100644
--- a/intern/ghost/intern/GHOST_XrAction.cpp
+++ b/intern/ghost/intern/GHOST_XrAction.cpp
@@ -216,8 +216,9 @@ GHOST_XrAction::GHOST_XrAction(XrInstance instance,
XrActionCreateInfo action_info{XR_TYPE_ACTION_CREATE_INFO};
strcpy(action_info.actionName, info.name);
- strcpy(action_info.localizedActionName, info.name); /* Just use same name for localized. This can
- be changed in the future if necessary. */
+
+ /* Just use same name for localized. This can be changed in the future if necessary. */
+ strcpy(action_info.localizedActionName, info.name);
switch (info.type) {
case GHOST_kXrActionTypeBooleanInput:
diff --git a/intern/ghost/intern/GHOST_XrControllerModel.cpp b/intern/ghost/intern/GHOST_XrControllerModel.cpp
index ae15bf11aa0..27f92ffe7c5 100644
--- a/intern/ghost/intern/GHOST_XrControllerModel.cpp
+++ b/intern/ghost/intern/GHOST_XrControllerModel.cpp
@@ -97,8 +97,8 @@ static void read_vertices(const tinygltf::Accessor &accessor,
validate_accessor(accessor, buffer_view, buffer, stride, packed_size);
/* Resize the vertices vector, if necessary, to include room for the attribute data.
- If there are multiple attributes for a primitive, the first one will resize, and the
- subsequent will not need to. */
+ * If there are multiple attributes for a primitive, the first one will resize, and the
+ * subsequent will not need to. */
primitive.vertices.resize(accessor.count);
/* Copy the attribute value over from the glTF buffer into the appropriate vertex field. */
@@ -147,9 +147,9 @@ static void read_indices(const tinygltf::Accessor &accessor,
const tinygltf::Buffer &buffer,
GHOST_XrPrimitive &primitive)
{
- if (buffer_view.target != TINYGLTF_TARGET_ELEMENT_ARRAY_BUFFER &&
- buffer_view.target != 0) { /* Allow 0 (not specified) even though spec doesn't seem to allow
- this (BoomBox GLB fails). */
+
+ /* Allow 0 (not specified) even though spec doesn't seem to allow this (BoomBox GLB fails). */
+ if (buffer_view.target != TINYGLTF_TARGET_ELEMENT_ARRAY_BUFFER && buffer_view.target != 0) {
throw GHOST_XrException(
"glTF: Accessor for indices uses bufferview with invalid 'target' type.");
}
@@ -164,8 +164,8 @@ static void read_indices(const tinygltf::Accessor &accessor,
validate_accessor(accessor, buffer_view, buffer, component_size_bytes, component_size_bytes);
- if ((accessor.count % 3) != 0) { /* Since only triangles are supported, enforce that the number
- of indices is divisible by 3. */
+ /* Since only triangles are supported, enforce that the number of indices is divisible by 3. */
+ if ((accessor.count % 3) != 0) {
throw GHOST_XrException("glTF: Unexpected number of indices for triangle primitive");
}
diff --git a/intern/guardedalloc/MEM_guardedalloc.h b/intern/guardedalloc/MEM_guardedalloc.h
index 713b1fac788..874abb88ff5 100644
--- a/intern/guardedalloc/MEM_guardedalloc.h
+++ b/intern/guardedalloc/MEM_guardedalloc.h
@@ -78,7 +78,8 @@ extern short (*MEM_testN)(void *vmemh);
/**
* Duplicates a block of memory, and returns a pointer to the
- * newly allocated block. */
+ * newly allocated block.
+ * NULL-safe; will return NULL when receiving a NULL pointer. */
extern void *(*MEM_dupallocN)(const void *vmemh) /* ATTR_MALLOC */ ATTR_WARN_UNUSED_RESULT;
/**
diff --git a/intern/locale/boost_locale_wrapper.cpp b/intern/locale/boost_locale_wrapper.cpp
index ede9377b38f..444b51b5e04 100644
--- a/intern/locale/boost_locale_wrapper.cpp
+++ b/intern/locale/boost_locale_wrapper.cpp
@@ -26,8 +26,8 @@ static std::string messages_path;
static std::string default_domain;
static std::string locale_str;
-/* Note: We cannot use short stuff like boost::locale::gettext, because those return
- * std::basic_string objects, which c_ptr()-returned char* is no more valid
+/* NOTE: We cannot use short stuff like `boost::locale::gettext`, because those return
+ * `std::basic_string` objects, which c_ptr()-returned char* is no more valid
* once deleted (which happens as soons they are out of scope of this func). */
typedef boost::locale::message_format<char> char_message_facet;
static std::locale locale_global;
@@ -63,7 +63,7 @@ static void bl_locale_global_cache()
void bl_locale_init(const char *_messages_path, const char *_default_domain)
{
- // Avoid using ICU backend, we do not need its power and it's rather heavy!
+ /* Avoid using ICU backend, we do not need its power and it's rather heavy! */
boost::locale::localization_backend_manager lman =
boost::locale::localization_backend_manager::global();
#if defined(_WIN32)
@@ -81,7 +81,7 @@ void bl_locale_set(const char *locale)
{
boost::locale::generator gen;
std::locale _locale;
- // Specify location of dictionaries.
+ /* Specify location of dictionaries. */
gen.add_messages_path(messages_path);
gen.add_messages_domain(default_domain);
// gen.set_default_messages_domain(default_domain);
@@ -99,12 +99,12 @@ void bl_locale_set(const char *locale)
#endif
}
std::locale::global(_locale);
- // Note: boost always uses "C" LC_NUMERIC by default!
+ /* NOTE: boost always uses "C" LC_NUMERIC by default! */
bl_locale_global_cache();
- // Generate the locale string
- // (useful to know which locale we are actually using in case of "default" one).
+ /* Generate the locale string
+ * (useful to know which locale we are actually using in case of "default" one). */
#define LOCALE_INFO std::use_facet<boost::locale::info>(_locale)
locale_str = LOCALE_INFO.language();
@@ -117,10 +117,9 @@ void bl_locale_set(const char *locale)
#undef LOCALE_INFO
}
- // Extra catch on `std::runtime_error` is needed for macOS/Clang as it seems that exceptions
- // like `boost::locale::conv::conversion_error` (which inherit from `std::runtime_error`) are
- // not caught by their ancestor `std::exception`. See
- // https://developer.blender.org/T88877#1177108 .
+ /* Extra catch on `std::runtime_error` is needed for macOS/Clang as it seems that exceptions
+ * like `boost::locale::conv::conversion_error` (which inherit from `std::runtime_error`) are
+ * not caught by their ancestor `std::exception`. See T88877#1177108 */
catch (std::runtime_error const &e) {
std::cout << "bl_locale_set(" << locale << "): " << e.what() << " \n";
}
diff --git a/release/datafiles/colormanagement/config.ocio b/release/datafiles/colormanagement/config.ocio
index bb9fd27fb84..bd342a0577e 100644
--- a/release/datafiles/colormanagement/config.ocio
+++ b/release/datafiles/colormanagement/config.ocio
@@ -42,7 +42,7 @@ roles:
# For interop between configs, and to determine XYZ for rendering
aces_interchange: Linear ACES
- # Specifed by OCIO, not used in Blender
+ # Specified by OCIO, not used in Blender
color_timing: Filmic Log
compositing_log: Filmic Log
default: Linear
diff --git a/release/datafiles/splash.png b/release/datafiles/splash.png
index 74e239b0f98..babb3e30c6d 100644
--- a/release/datafiles/splash.png
+++ b/release/datafiles/splash.png
Binary files differ
diff --git a/release/datafiles/userdef/userdef_default_theme.c b/release/datafiles/userdef/userdef_default_theme.c
index da01f65131c..055a2e37c6c 100644
--- a/release/datafiles/userdef/userdef_default_theme.c
+++ b/release/datafiles/userdef/userdef_default_theme.c
@@ -647,7 +647,7 @@ const bTheme U_theme_default = {
.facedot_size = 4,
.movie = RGBA(0x4d6890ff),
.movieclip = RGBA(0x8f4c4cff),
- .mask = RGBA(0x666666ff),
+ .mask = RGBA(0x8f5656ff),
.image = RGBA(0x8f744bff),
.scene = RGBA(0x808033ff),
.audio = RGBA(0x448080ff),
diff --git a/release/freedesktop/snap/README.md b/release/freedesktop/snap/README.md
index 742b265ada6..f6c662e9f1e 100644
--- a/release/freedesktop/snap/README.md
+++ b/release/freedesktop/snap/README.md
@@ -12,6 +12,6 @@ Build pipeline snap tracks and channels
- Test builds for the upcoming stable release - *not used for now*
<track>/beta
- Nightly automated builds provided by a release branch
- <track>/egde/<branch>
+ <track>/edge/<branch>
- Nightly or on demand builds - will also make use of branch
```
diff --git a/release/lts/create_release_notes.py b/release/lts/create_release_notes.py
index 2a396dca6b0..2d35a71c263 100755
--- a/release/lts/create_release_notes.py
+++ b/release/lts/create_release_notes.py
@@ -97,7 +97,7 @@ def extract_release_notes(version: str, task_id: int):
# Process
- 1. Retrieval of description of the gived `task_id`.
+ 1. Retrieval of description of the given `task_id`.
2. Find rows for the given `version` and convert to `ReleaseLogLine`.
3. based on the associated task or commit retrieves the title of the log
line.
diff --git a/release/scripts/modules/bl_i18n_utils/bl_extract_messages.py b/release/scripts/modules/bl_i18n_utils/bl_extract_messages.py
index 00edd7d523d..cf904a1a88b 100644
--- a/release/scripts/modules/bl_i18n_utils/bl_extract_messages.py
+++ b/release/scripts/modules/bl_i18n_utils/bl_extract_messages.py
@@ -877,7 +877,7 @@ def dump_messages(do_messages, do_checks, settings):
addons = utils.enable_addons(support={"OFFICIAL"})
# Note this is not needed if we have been started with factory settings, but just in case...
# XXX This is not working well, spent a whole day trying to understand *why* we still have references of
- # those removed calsses in things like `bpy.types.OperatorProperties.__subclasses__()`
+ # those removed classes in things like `bpy.types.OperatorProperties.__subclasses__()`
# (could not even reproduce it from regular py console in Blender with UI...).
# For some reasons, cleanup does not happen properly, *and* we have no way to tell which class is valid
# and which has been unregistered. So for now, just go for the dirty, easy way: do not disable add-ons. :(
diff --git a/release/scripts/modules/bl_i18n_utils/utils.py b/release/scripts/modules/bl_i18n_utils/utils.py
index 13fb87d386a..e13eb15dfd2 100644
--- a/release/scripts/modules/bl_i18n_utils/utils.py
+++ b/release/scripts/modules/bl_i18n_utils/utils.py
@@ -778,7 +778,7 @@ class I18nMessages:
try:
import bpy
except ModuleNotFoundError:
- print("Could not import bpy, find_best_messages_matches must be run from whithin Blender.")
+ print("Could not import bpy, find_best_messages_matches must be run from within Blender.")
return
# Build helper mappings.
diff --git a/release/scripts/modules/bpy/utils/__init__.py b/release/scripts/modules/bpy/utils/__init__.py
index 3f0248970c6..b009c38edb4 100644
--- a/release/scripts/modules/bpy/utils/__init__.py
+++ b/release/scripts/modules/bpy/utils/__init__.py
@@ -26,6 +26,7 @@ not associated with blenders internal data.
__all__ = (
"blend_paths",
"escape_identifier",
+ "flip_name",
"unescape_identifier",
"keyconfig_init",
"keyconfig_set",
@@ -61,6 +62,7 @@ from _bpy import (
_utils_units as units,
blend_paths,
escape_identifier,
+ flip_name,
unescape_identifier,
register_class,
resource_path,
@@ -106,7 +108,7 @@ def execfile(filepath, *, mod=None):
mod_orig = modules.get(mod_name, None)
modules[mod_name] = mod
- # No error supression, just ensure `sys.modules[mod_name]` is properly restored in the case of an error.
+ # No error suppression, just ensure `sys.modules[mod_name]` is properly restored in the case of an error.
try:
mod_spec.loader.exec_module(mod)
finally:
diff --git a/release/scripts/modules/bpy_types.py b/release/scripts/modules/bpy_types.py
index 26efb6e3307..b477f624b7b 100644
--- a/release/scripts/modules/bpy_types.py
+++ b/release/scripts/modules/bpy_types.py
@@ -720,7 +720,7 @@ class Gizmo(StructRNA):
# Dummy class to keep the reference in `bpy_types_dict` and avoid
-# erros like: "TypeError: expected GizmoGroup subclass of class ..."
+# errors like: "TypeError: expected GizmoGroup subclass of class ..."
class GizmoGroup(StructRNA):
__slots__ = ()
diff --git a/release/scripts/presets/keyconfig/Blender.py b/release/scripts/presets/keyconfig/Blender.py
index 35c920b3f40..1ac7626f926 100644
--- a/release/scripts/presets/keyconfig/Blender.py
+++ b/release/scripts/presets/keyconfig/Blender.py
@@ -202,7 +202,7 @@ class Prefs(bpy.types.KeyConfigPreferences):
update=update_fn,
)
- # Developer note, this is an experemental option.
+ # Developer note, this is an experimental option.
use_pie_click_drag: BoolProperty(
name="Pie Menu on Drag",
description=(
diff --git a/release/scripts/presets/keyconfig/keymap_data/blender_default.py b/release/scripts/presets/keyconfig/keymap_data/blender_default.py
index d6032a3ecce..dbc93cb6caa 100644
--- a/release/scripts/presets/keyconfig/keymap_data/blender_default.py
+++ b/release/scripts/presets/keyconfig/keymap_data/blender_default.py
@@ -1097,6 +1097,7 @@ def km_outliner(params):
# Fall through to generic context menu if the item(s) selected have no type specific actions.
("outliner.operation", {"type": 'RIGHTMOUSE', "value": 'PRESS'}, None),
op_menu("OUTLINER_MT_context_menu", {"type": 'RIGHTMOUSE', "value": 'PRESS'}),
+ op_menu_pie("OUTLINER_MT_view_pie", {"type": 'ACCENT_GRAVE', "value": 'PRESS'}),
("outliner.item_drag_drop", {"type": 'EVT_TWEAK_L', "value": 'ANY'}, None),
("outliner.item_drag_drop", {"type": 'EVT_TWEAK_L', "value": 'ANY', "shift": True}, None),
("outliner.show_hierarchy", {"type": 'HOME', "value": 'PRESS'}, None),
@@ -1748,6 +1749,7 @@ def km_graph_editor(params):
("graph.view_all", {"type": 'NDOF_BUTTON_FIT', "value": 'PRESS'}, None),
("graph.view_selected", {"type": 'NUMPAD_PERIOD', "value": 'PRESS'}, None),
("graph.view_frame", {"type": 'NUMPAD_0', "value": 'PRESS'}, None),
+ op_menu_pie("GRAPH_MT_view_pie", {"type": 'ACCENT_GRAVE', "value": 'PRESS'}),
("graph.fmodifier_add", {"type": 'M', "value": 'PRESS', "shift": True, "ctrl": True},
{"properties": [("only_active", False)]}),
("anim.channels_editable_toggle", {"type": 'TAB', "value": 'PRESS'}, None),
@@ -1815,6 +1817,7 @@ def km_image_generic(params):
("image.cycle_render_slot", {"type": 'J', "value": 'PRESS', "repeat": True}, None),
("image.cycle_render_slot", {"type": 'J', "value": 'PRESS', "alt": True, "repeat": True},
{"properties": [("reverse", True)]}),
+ op_menu_pie("IMAGE_MT_view_pie", {"type": 'ACCENT_GRAVE', "value": 'PRESS'}),
])
if not params.legacy:
@@ -2027,6 +2030,7 @@ def km_node_editor(params):
("node.view_all", {"type": 'HOME', "value": 'PRESS'}, None),
("node.view_all", {"type": 'NDOF_BUTTON_FIT', "value": 'PRESS'}, None),
("node.view_selected", {"type": 'NUMPAD_PERIOD', "value": 'PRESS'}, None),
+ op_menu_pie("NODE_MT_view_pie", {"type": 'ACCENT_GRAVE', "value": 'PRESS'}),
("node.delete", {"type": 'X', "value": 'PRESS'}, None),
("node.delete", {"type": 'DEL', "value": 'PRESS'}, None),
("node.delete_reconnect", {"type": 'X', "value": 'PRESS', "ctrl": True}, None),
@@ -2389,6 +2393,7 @@ def km_dopesheet(params):
("action.view_all", {"type": 'NDOF_BUTTON_FIT', "value": 'PRESS'}, None),
("action.view_selected", {"type": 'NUMPAD_PERIOD', "value": 'PRESS'}, None),
("action.view_frame", {"type": 'NUMPAD_0', "value": 'PRESS'}, None),
+ op_menu_pie("DOPESHEET_MT_view_pie", {"type": 'ACCENT_GRAVE', "value": 'PRESS'}),
("anim.channels_editable_toggle", {"type": 'TAB', "value": 'PRESS'}, None),
("anim.channels_select_filter", {"type": 'F', "value": 'PRESS', "ctrl": True}, None),
("transform.transform", {"type": 'G', "value": 'PRESS'},
@@ -2503,6 +2508,7 @@ def km_nla_editor(params):
("nla.view_all", {"type": 'NDOF_BUTTON_FIT', "value": 'PRESS'}, None),
("nla.view_selected", {"type": 'NUMPAD_PERIOD', "value": 'PRESS'}, None),
("nla.view_frame", {"type": 'NUMPAD_0', "value": 'PRESS'}, None),
+ op_menu_pie("NLA_MT_view_pie", {"type": 'ACCENT_GRAVE', "value": 'PRESS'}),
("nla.actionclip_add", {"type": 'A', "value": 'PRESS', "shift": True}, None),
("nla.transition_add", {"type": 'T', "value": 'PRESS', "shift": True}, None),
("nla.soundclip_add", {"type": 'K', "value": 'PRESS', "shift": True}, None),
@@ -2835,6 +2841,7 @@ def km_sequencer(params):
("sequencer.select_grouped", {"type": 'G', "value": 'PRESS', "shift": True}, None),
op_menu("SEQUENCER_MT_add", {"type": 'A', "value": 'PRESS', "shift": True}),
op_menu("SEQUENCER_MT_change", {"type": 'C', "value": 'PRESS'}),
+ op_menu_pie("SEQUENCER_MT_view_pie", {"type": 'ACCENT_GRAVE', "value": 'PRESS'}),
("sequencer.slip", {"type": 'S', "value": 'PRESS'}, None),
("wm.context_set_int", {"type": 'O', "value": 'PRESS'},
{"properties": [("data_path", 'scene.sequence_editor.overlay_frame'), ("value", 0)]}),
@@ -2892,6 +2899,7 @@ def km_sequencerpreview(params):
{"properties": [("ratio", 0.25)]}),
("sequencer.view_zoom_ratio", {"type": 'NUMPAD_8', "value": 'PRESS'},
{"properties": [("ratio", 0.125)]}),
+ op_menu_pie("SEQUENCER_MT_preview_view_pie", {"type": 'ACCENT_GRAVE', "value": 'PRESS'}),
# Edit.
("transform.translate", {"type": params.select_tweak, "value": 'ANY'}, None),
@@ -3042,6 +3050,7 @@ def km_clip(_params):
op_menu_pie("CLIP_MT_solving_pie", {"type": 'S', "value": 'PRESS', "shift": True}),
op_menu_pie("CLIP_MT_marker_pie", {"type": 'E', "value": 'PRESS', "shift": True}),
op_menu_pie("CLIP_MT_reconstruction_pie", {"type": 'W', "value": 'PRESS', "shift": True}),
+ op_menu_pie("CLIP_MT_view_pie", {"type": 'ACCENT_GRAVE', "value": 'PRESS'}),
])
return keymap
diff --git a/release/scripts/startup/bl_operators/userpref.py b/release/scripts/startup/bl_operators/userpref.py
index 67a02f6e1f4..1363bcf60e4 100644
--- a/release/scripts/startup/bl_operators/userpref.py
+++ b/release/scripts/startup/bl_operators/userpref.py
@@ -100,14 +100,6 @@ class PREFERENCES_OT_copy_prev(Operator):
version_new = ((version[0] * 100) + version[1])
version_old = ((version[0] * 100) + version[1]) - 1
- # Special case, remove when the version is > 3.0.
- if version_new == 300:
- version_new = 294
- version_old = 293
- else:
- print("TODO: remove exception!")
- # End special case.
-
# Ensure we only try to copy files from a point release.
# The check below ensures the second numbers match.
while (version_new % 100) // 10 == (version_old % 100) // 10:
diff --git a/release/scripts/startup/bl_operators/wm.py b/release/scripts/startup/bl_operators/wm.py
index 28bb0a58c02..d9ea991f976 100644
--- a/release/scripts/startup/bl_operators/wm.py
+++ b/release/scripts/startup/bl_operators/wm.py
@@ -1030,7 +1030,7 @@ class WM_OT_url_open_preset(Operator):
"Report a bug in an add-on"),
_url_from_bug_addon),
(('RELEASE_NOTES', "Release Notes",
- "Read about whats new in this version of Blender"),
+ "Read about what's new in this version of Blender"),
_url_from_release_notes),
(('MANUAL', "Manual",
"The reference manual for this version of Blender"),
@@ -1430,7 +1430,7 @@ class WM_OT_properties_edit(Operator):
type_items = rna_custom_property_type_items
subtype_items = rna_vector_subtype_items
- # Helper method to avoid repetative code to retrieve a single value from sequences and non-sequences.
+ # Helper method to avoid repetitive code to retrieve a single value from sequences and non-sequences.
@staticmethod
def _convert_new_value_single(old_value, new_type):
if hasattr(old_value, "__len__") and len(old_value) > 0:
diff --git a/release/scripts/startup/bl_ui/properties_data_gpencil.py b/release/scripts/startup/bl_ui/properties_data_gpencil.py
index 793c4a52350..34e83573bc9 100644
--- a/release/scripts/startup/bl_ui/properties_data_gpencil.py
+++ b/release/scripts/startup/bl_ui/properties_data_gpencil.py
@@ -110,7 +110,8 @@ class GPENCIL_MT_layer_context_menu(Menu):
layout.separator()
- layout.operator("gpencil.layer_merge", icon='SORT_ASC', text="Merge Down")
+ layout.operator("gpencil.layer_merge", icon='SORT_ASC', text="Merge Down").mode = 'ACTIVE'
+ layout.operator("gpencil.layer_merge", text="Merge All").mode = 'ALL'
layout.separator()
layout.operator("gpencil.layer_duplicate_object", text="Copy Layer to Selected").only_active = True
diff --git a/release/scripts/startup/bl_ui/properties_physics_rigidbody.py b/release/scripts/startup/bl_ui/properties_physics_rigidbody.py
index 26fe215b17d..9afe8415cf4 100644
--- a/release/scripts/startup/bl_ui/properties_physics_rigidbody.py
+++ b/release/scripts/startup/bl_ui/properties_physics_rigidbody.py
@@ -261,7 +261,7 @@ class PHYSICS_PT_rigid_body_dynamics(PHYSICS_PT_rigidbody_panel, Panel):
# col = layout.column(align=True)
# col.label(text="Activation:")
- # XXX: settings such as activate on collison/etc.
+ # XXX: settings such as activate on collision/etc.
col = flow.column()
col.prop(rbo, "linear_damping", text="Damping Translation")
diff --git a/release/scripts/startup/bl_ui/space_clip.py b/release/scripts/startup/bl_ui/space_clip.py
index c18d77987ad..86e9ef3d664 100644
--- a/release/scripts/startup/bl_ui/space_clip.py
+++ b/release/scripts/startup/bl_ui/space_clip.py
@@ -1858,6 +1858,43 @@ class CLIP_MT_reconstruction_pie(Menu):
pie.operator("clip.apply_solution_scale", icon='ARROW_LEFTRIGHT')
+class CLIP_MT_view_pie(Menu):
+ bl_label = "View"
+
+ @classmethod
+ def poll(cls, context):
+ space = context.space_data
+
+ # View operators are not yet implemented in Dopesheet mode.
+ return space.view != 'DOPESHEET'
+
+ def draw(self, context):
+ layout = self.layout
+ sc = context.space_data
+
+ pie = layout.menu_pie()
+
+ if sc.view == 'CLIP':
+ pie.operator("clip.view_all")
+ pie.operator("clip.view_selected", icon='ZOOM_SELECTED')
+
+ if sc.mode == 'MASK':
+ pie.operator("clip.view_center_cursor")
+ pie.separator()
+ else:
+ # Add spaces so items stay in the same position through all modes.
+ pie.separator()
+ pie.separator()
+
+ pie.operator("clip.view_all", text="Frame All Fit").fit_view = True
+
+ if sc.view == 'GRAPH':
+ pie.operator_context = 'INVOKE_REGION_PREVIEW'
+ pie.operator("clip.graph_view_all")
+ pie.separator()
+ pie.operator("clip.graph_center_current_frame")
+
+
classes = (
CLIP_UL_tracking_objects,
CLIP_HT_header,
@@ -1925,6 +1962,7 @@ classes = (
CLIP_MT_tracking_pie,
CLIP_MT_reconstruction_pie,
CLIP_MT_solving_pie,
+ CLIP_MT_view_pie,
)
if __name__ == "__main__": # only for live edit.
diff --git a/release/scripts/startup/bl_ui/space_dopesheet.py b/release/scripts/startup/bl_ui/space_dopesheet.py
index 781c430a752..9b8f1cfeb0d 100644
--- a/release/scripts/startup/bl_ui/space_dopesheet.py
+++ b/release/scripts/startup/bl_ui/space_dopesheet.py
@@ -379,6 +379,18 @@ class DOPESHEET_MT_view(Menu):
layout.menu("INFO_MT_area")
+class DOPESHEET_MT_view_pie(Menu):
+ bl_label = "View"
+
+ def draw(self, context):
+ layout = self.layout
+
+ pie = layout.menu_pie()
+ pie.operator("action.view_all")
+ pie.operator("action.view_selected", icon='ZOOM_SELECTED')
+ pie.operator("action.view_frame")
+
+
class DOPESHEET_MT_select(Menu):
bl_label = "Select"
@@ -778,6 +790,7 @@ classes = (
DOPESHEET_MT_context_menu,
DOPESHEET_MT_channel_context_menu,
DOPESHEET_MT_snap_pie,
+ DOPESHEET_MT_view_pie,
DOPESHEET_PT_filters,
DOPESHEET_PT_gpencil_mode,
DOPESHEET_PT_gpencil_layer_masks,
diff --git a/release/scripts/startup/bl_ui/space_graph.py b/release/scripts/startup/bl_ui/space_graph.py
index 612b7ba2b09..1562870d64f 100644
--- a/release/scripts/startup/bl_ui/space_graph.py
+++ b/release/scripts/startup/bl_ui/space_graph.py
@@ -338,6 +338,18 @@ class GRAPH_MT_key_snap(Menu):
layout.operator("graph.snap_cursor_value", text="Cursor Value to Selection")
+class GRAPH_MT_view_pie(Menu):
+ bl_label = "View"
+
+ def draw(self, context):
+ layout = self.layout
+
+ pie = layout.menu_pie()
+ pie.operator("graph.view_all")
+ pie.operator("graph.view_selected", icon='ZOOM_SELECTED')
+ pie.operator("graph.view_frame")
+
+
class GRAPH_MT_delete(Menu):
bl_label = "Delete"
@@ -468,6 +480,7 @@ classes = (
GRAPH_MT_channel_context_menu,
GRAPH_MT_pivot_pie,
GRAPH_MT_snap_pie,
+ GRAPH_MT_view_pie,
GRAPH_PT_filters,
)
diff --git a/release/scripts/startup/bl_ui/space_image.py b/release/scripts/startup/bl_ui/space_image.py
index 6a769b1aecc..8e82b07716c 100644
--- a/release/scripts/startup/bl_ui/space_image.py
+++ b/release/scripts/startup/bl_ui/space_image.py
@@ -591,6 +591,31 @@ class IMAGE_MT_uvs_snap_pie(Menu):
).target = 'ADJACENT_UNSELECTED'
+class IMAGE_MT_view_pie(Menu):
+ bl_label = "View"
+
+ def draw(self, context):
+ layout = self.layout
+
+ sima = context.space_data
+ show_uvedit = sima.show_uvedit
+ show_maskedit = sima.show_maskedit
+
+ pie = layout.menu_pie()
+ pie.operator("image.view_all")
+
+ if show_uvedit or show_maskedit:
+ pie.operator("image.view_selected", text="Frame Selected", icon='ZOOM_SELECTED')
+ pie.operator("image.view_center_cursor", text="Center View to Cursor")
+ else:
+ # Add spaces so items stay in the same position through all modes.
+ pie.separator()
+ pie.separator()
+
+ pie.operator("image.view_zoom_ratio", text="Zoom 1:1").ratio = 1
+ pie.operator("image.view_all", text="Frame All Fit").fit_view = True
+
+
class IMAGE_HT_tool_header(Header):
bl_space_type = 'IMAGE_EDITOR'
bl_region_type = 'TOOL_HEADER'
@@ -1633,6 +1658,7 @@ classes = (
IMAGE_MT_mask_context_menu,
IMAGE_MT_pivot_pie,
IMAGE_MT_uvs_snap_pie,
+ IMAGE_MT_view_pie,
IMAGE_HT_tool_header,
IMAGE_HT_header,
IMAGE_MT_editor_menus,
diff --git a/release/scripts/startup/bl_ui/space_nla.py b/release/scripts/startup/bl_ui/space_nla.py
index d472352084c..9507d8296a9 100644
--- a/release/scripts/startup/bl_ui/space_nla.py
+++ b/release/scripts/startup/bl_ui/space_nla.py
@@ -247,6 +247,18 @@ class NLA_MT_snap_pie(Menu):
pie.operator("nla.snap", text="Selection to Nearest Marker").type = 'NEAREST_MARKER'
+class NLA_MT_view_pie(Menu):
+ bl_label = "View"
+
+ def draw(self, context):
+ layout = self.layout
+
+ pie = layout.menu_pie()
+ pie.operator("nla.view_all")
+ pie.operator("nla.view_selected", icon='ZOOM_SELECTED')
+ pie.operator("nla.view_frame")
+
+
class NLA_MT_context_menu(Menu):
bl_label = "NLA Context Menu"
@@ -300,6 +312,7 @@ classes = (
NLA_MT_add,
NLA_MT_edit_transform,
NLA_MT_snap_pie,
+ NLA_MT_view_pie,
NLA_MT_context_menu,
NLA_MT_channel_context_menu,
NLA_PT_filters,
diff --git a/release/scripts/startup/bl_ui/space_node.py b/release/scripts/startup/bl_ui/space_node.py
index 2fda13184da..2b3f0cfbf7c 100644
--- a/release/scripts/startup/bl_ui/space_node.py
+++ b/release/scripts/startup/bl_ui/space_node.py
@@ -367,6 +367,17 @@ class NODE_MT_node(Menu):
layout.operator("node.read_viewlayers")
+class NODE_MT_view_pie(Menu):
+ bl_label = "View"
+
+ def draw(self, context):
+ layout = self.layout
+
+ pie = layout.menu_pie()
+ pie.operator("node.view_all")
+ pie.operator("node.view_selected", icon='ZOOM_SELECTED')
+
+
class NODE_PT_active_tool(ToolActivePanelHelper, Panel):
bl_space_type = 'NODE_EDITOR'
bl_region_type = 'UI'
@@ -877,6 +888,7 @@ classes = (
NODE_MT_node,
NODE_MT_node_color_context_menu,
NODE_MT_context_menu,
+ NODE_MT_view_pie,
NODE_PT_material_slots,
NODE_PT_node_color_presets,
NODE_PT_active_node_generic,
diff --git a/release/scripts/startup/bl_ui/space_outliner.py b/release/scripts/startup/bl_ui/space_outliner.py
index 07fa2220915..d85538a37e0 100644
--- a/release/scripts/startup/bl_ui/space_outliner.py
+++ b/release/scripts/startup/bl_ui/space_outliner.py
@@ -142,6 +142,17 @@ class OUTLINER_MT_context_menu_view(Menu):
layout.operator("outliner.show_one_level", text="Hide One Level").open = False
+class OUTLINER_MT_view_pie(Menu):
+ bl_label = "View"
+
+ def draw(self, context):
+ layout = self.layout
+
+ pie = layout.menu_pie()
+ pie.operator("outliner.show_hierarchy")
+ pie.operator("outliner.show_active", icon='ZOOM_SELECTED')
+
+
class OUTLINER_MT_edit_datablocks(Menu):
bl_label = "Edit"
@@ -471,6 +482,7 @@ classes = (
OUTLINER_MT_asset,
OUTLINER_MT_context_menu,
OUTLINER_MT_context_menu_view,
+ OUTLINER_MT_view_pie,
OUTLINER_PT_filter,
)
diff --git a/release/scripts/startup/bl_ui/space_sequencer.py b/release/scripts/startup/bl_ui/space_sequencer.py
index 7117f28c1a7..401ff9b64c2 100644
--- a/release/scripts/startup/bl_ui/space_sequencer.py
+++ b/release/scripts/startup/bl_ui/space_sequencer.py
@@ -1173,6 +1173,31 @@ class SEQUENCER_MT_pivot_pie(Menu):
pie.prop_enum(sequencer_tool_settings, "pivot_point", value='MEDIAN')
+class SEQUENCER_MT_view_pie(Menu):
+ bl_label = "View"
+
+ def draw(self, context):
+ layout = self.layout
+
+ pie = layout.menu_pie()
+ pie.operator("sequencer.view_all")
+ pie.operator("sequencer.view_selected", text="Frame Selected", icon='ZOOM_SELECTED')
+
+
+class SEQUENCER_MT_preview_view_pie(Menu):
+ bl_label = "View"
+
+ def draw(self, context):
+ layout = self.layout
+
+ pie = layout.menu_pie()
+ pie.operator_context = 'INVOKE_REGION_PREVIEW'
+ pie.operator("sequencer.view_all_preview")
+ pie.operator("sequencer.view_selected", text="Frame Selected", icon='ZOOM_SELECTED')
+ pie.separator()
+ pie.operator("sequencer.view_zoom_ratio", text="Zoom 1:1").ratio = 1
+
+
class SequencerButtonsPanel:
bl_space_type = 'SEQUENCE_EDITOR'
bl_region_type = 'UI'
@@ -2615,6 +2640,8 @@ classes = (
SEQUENCER_MT_context_menu,
SEQUENCER_MT_preview_context_menu,
SEQUENCER_MT_pivot_pie,
+ SEQUENCER_MT_view_pie,
+ SEQUENCER_MT_preview_view_pie,
SEQUENCER_PT_color_tag_picker,
diff --git a/release/scripts/startup/bl_ui/space_toolsystem_common.py b/release/scripts/startup/bl_ui/space_toolsystem_common.py
index 9d41a0fa02f..c4dabb5b5bc 100644
--- a/release/scripts/startup/bl_ui/space_toolsystem_common.py
+++ b/release/scripts/startup/bl_ui/space_toolsystem_common.py
@@ -64,7 +64,7 @@ from collections import namedtuple
ToolDef = namedtuple(
"ToolDef",
(
- # Unique tool name (withing space & mode context).
+ # Unique tool name (within space & mode context).
"idname",
# The name to display in the interface.
"label",
@@ -106,7 +106,7 @@ ToolDef = namedtuple(
# Keep this functionality since it's likely useful for add-on key-maps.
#
# Warning: currently 'from_dict' this is a list of one item,
- # so internally we can swap the key-map function for the key-map it's self.
+ # so internally we can swap the key-map function for the key-map itself.
# This isn't very nice and may change, tool definitions shouldn't care about this.
"keymap",
# Optional data-block associated with this tool.
diff --git a/release/scripts/startup/bl_ui/space_userpref.py b/release/scripts/startup/bl_ui/space_userpref.py
index 705f6fd788e..5032256e4d1 100644
--- a/release/scripts/startup/bl_ui/space_userpref.py
+++ b/release/scripts/startup/bl_ui/space_userpref.py
@@ -477,6 +477,16 @@ class USERPREF_PT_edit_weight_paint(EditingPanel, CenterAlignMixIn, Panel):
col.active = view.use_weight_color_range
col.template_color_ramp(view, "weight_color_range", expand=True)
+class USERPREF_PT_edit_text_editor(EditingPanel, CenterAlignMixIn, Panel):
+ bl_label = "Text Editor"
+ bl_options = {'DEFAULT_CLOSED'}
+
+ def draw_centered(self, context, layout):
+ prefs = context.preferences
+ edit = prefs.edit
+
+ layout.prop(edit, "use_text_edit_auto_close")
+
class USERPREF_PT_edit_misc(EditingPanel, CenterAlignMixIn, Panel):
bl_label = "Miscellaneous"
@@ -2358,6 +2368,7 @@ classes = (
USERPREF_PT_edit_annotations,
USERPREF_PT_edit_weight_paint,
USERPREF_PT_edit_gpencil,
+ USERPREF_PT_edit_text_editor,
USERPREF_PT_edit_misc,
USERPREF_PT_animation_timeline,
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 12d97d7e3e3..2246336369b 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;
diff --git a/source/creator/creator.c b/source/creator/creator.c
index 7c99f954bfc..6daaea38c34 100644
--- a/source/creator/creator.c
+++ b/source/creator/creator.c
@@ -414,7 +414,6 @@ int main(int argc,
BKE_idtype_init();
BKE_cachefiles_init();
- BKE_images_init();
BKE_modifier_init();
BKE_gpencil_modifier_init();
BKE_shaderfx_init();
@@ -552,7 +551,8 @@ int main(int argc,
WM_exit(C);
}
else {
- if (!G.file_loaded) {
+ /* When no file is loaded, show the splash screen. */
+ if (!G.relbase_valid) {
WM_init_splash(C);
}
WM_main(C);
diff --git a/source/creator/creator_args.c b/source/creator/creator_args.c
index 943646daa81..896d29e0583 100644
--- a/source/creator/creator_args.c
+++ b/source/creator/creator_args.c
@@ -2008,8 +2008,6 @@ static int arg_handle_load_file(int UNUSED(argc), const char **argv, void *data)
}
}
- G.file_loaded = 1;
-
return 0;
}
diff --git a/tests/gtests/runner/CMakeLists.txt b/tests/gtests/runner/CMakeLists.txt
index b18eff59016..4500aa7b30f 100644
--- a/tests/gtests/runner/CMakeLists.txt
+++ b/tests/gtests/runner/CMakeLists.txt
@@ -56,7 +56,7 @@ setup_platform_linker_libs(blender_test)
if(WIN32)
foreach(_lib ${_test_libs})
# Both target_link_libraries and target_link_options are required here
- # target_link_libraries will add any dependend libraries, while just setting
+ # target_link_libraries will add any dependent libraries, while just setting
# the wholearchive flag in target link options will not.
target_link_libraries(blender_test ${_lib})
target_link_options(blender_test PRIVATE /wholearchive:$<TARGET_FILE:${_lib}>)
diff --git a/tests/performance/benchmark b/tests/performance/benchmark
index a58c339e9f8..80556674dcc 100755
--- a/tests/performance/benchmark
+++ b/tests/performance/benchmark
@@ -4,6 +4,7 @@
import api
import argparse
import fnmatch
+import glob
import pathlib
import shutil
import sys
@@ -228,6 +229,9 @@ def cmd_reset(env: api.TestEnvironment, argv: List):
config.queue.write()
+ if args.test == '*':
+ shutil.rmtree(config.logs_dir)
+
def cmd_run(env: api.TestEnvironment, argv: List, update_only: bool):
# Run tests.
parser = argparse.ArgumentParser()
@@ -274,7 +278,17 @@ def cmd_graph(argv: List):
parser.add_argument('-o', '--output', type=str, required=True)
args = parser.parse_args(argv)
- graph = api.TestGraph([pathlib.Path(path) for path in args.json_file])
+ # For directories, use all json files in the directory.
+ json_files = []
+ for path in args.json_file:
+ path = pathlib.Path(path)
+ if path.is_dir():
+ for filepath in glob.iglob(str(path / '*.json')):
+ json_files.append(pathlib.Path(filepath))
+ else:
+ json_files.append(path)
+
+ graph = api.TestGraph(json_files)
graph.write(pathlib.Path(args.output))
def main():
diff --git a/tests/python/bl_blendfile_liblink.py b/tests/python/bl_blendfile_liblink.py
index ab26059e944..f7bd2308061 100644
--- a/tests/python/bl_blendfile_liblink.py
+++ b/tests/python/bl_blendfile_liblink.py
@@ -370,10 +370,110 @@ class TestBlendLibAppendReuseID(TestBlendLibLinkHelper):
assert(len(bpy.data.collections) == 0) # Scene's master collection is not listed here
+class TestBlendLibLibraryReload(TestBlendLibLinkHelper):
+
+ def __init__(self, args):
+ self.args = args
+
+ def test_link_reload(self):
+ output_dir = self.args.output_dir
+ output_lib_path = self.init_lib_data_basic()
+
+ # Simple link of a single Object, and reload.
+ self.reset_blender()
+
+ link_dir = os.path.join(output_lib_path, "Object")
+ bpy.ops.wm.link(directory=link_dir, filename="LibMesh")
+
+ assert(len(bpy.data.meshes) == 1)
+ assert(len(bpy.data.objects) == 1)
+ assert(len(bpy.data.collections) == 0) # Scene's master collection is not listed here
+
+ orig_data = self.blender_data_to_tuple(bpy.data, "orig_data")
+
+ bpy.ops.wm.lib_reload(library=bpy.data.objects[0].name)
+
+ reload_data = self.blender_data_to_tuple(bpy.data, "reload_data")
+
+ print(orig_data)
+ print(reload_data)
+ assert(orig_data == reload_data)
+
+
+
+class TestBlendLibLibraryRelocate(TestBlendLibLinkHelper):
+
+ def __init__(self, args):
+ self.args = args
+
+ def test_link_relocate(self):
+ output_dir = self.args.output_dir
+ output_lib_path = self.init_lib_data_basic()
+
+ # Simple link of a single Object, and reload.
+ self.reset_blender()
+
+ link_dir = os.path.join(output_lib_path, "Object")
+ bpy.ops.wm.link(directory=link_dir, filename="LibMesh")
+
+ assert(len(bpy.data.meshes) == 1)
+ assert(len(bpy.data.objects) == 1)
+ assert(len(bpy.data.collections) == 0) # Scene's master collection is not listed here
+
+ orig_data = self.blender_data_to_tuple(bpy.data, "orig_data")
+
+ lib_path, lib_ext = os.path.splitext(output_lib_path)
+ new_lib_path = lib_path + "_relocate" + lib_ext
+ os.replace(output_lib_path, new_lib_path)
+
+ bpy.ops.wm.lib_relocate(library=bpy.data.objects[0].name, directory="", filename=new_lib_path)
+
+ relocate_data = self.blender_data_to_tuple(bpy.data, "relocate_data")
+
+ print(orig_data)
+ print(relocate_data)
+ assert(orig_data == relocate_data)
+
+
+class TestBlendLibDataLibrariesLoad(TestBlendLibLinkHelper):
+
+ def __init__(self, args):
+ self.args = args
+
+ def test_link_relocate(self):
+ output_dir = self.args.output_dir
+ output_lib_path = self.init_lib_data_basic()
+
+ # Simple link of a single Object, and reload.
+ self.reset_blender()
+
+ with bpy.data.libraries.load(filepath=output_lib_path) as lib_ctx:
+ lib_src, lib_link = lib_ctx
+
+ assert(len(lib_src.meshes) == 1)
+ assert(len(lib_src.objects) == 1)
+ assert(len(lib_src.collections) == 1)
+
+ assert(len(lib_link.meshes) == 0)
+ assert(len(lib_link.objects) == 0)
+ assert(len(lib_link.collections) == 0)
+
+ lib_link.collections.append(lib_src.collections[0])
+
+ # Linking happens when living the context manager.
+
+ assert(len(bpy.data.meshes) == 1)
+ assert(len(bpy.data.objects) == 1) # This code does no instantiation.
+ assert(len(bpy.data.collections) == 1)
+
+
TESTS = (
TestBlendLibLinkSaveLoadBasic,
TestBlendLibAppendBasic,
TestBlendLibAppendReuseID,
+ TestBlendLibLibraryReload,
+ TestBlendLibLibraryRelocate,
+ TestBlendLibDataLibrariesLoad,
)